Skip to content

Retry Failed Notification ​

Manually retry a failed notification.

Endpoint ​

http
POST /notifications/notifications/:id/retry

Authentication: Required (JWT)

Path Parameters ​

ParameterTypeRequiredDescription
idstringYesNotification unique identifier (MongoDB ObjectId)

Request Example ​

bash
curl -X POST http://localhost:3000/notifications/notifications/507f1f77bcf86cd799439011/retry \
  -H "Authorization: Bearer <access_token>"

Response ​

Status Code: 200 OK

Success Response ​

json
{
  "success": true,
  "notification": {
    "id": "507f1f77bcf86cd799439011",
    "userId": "507f1f77bcf86cd799439010",
    "type": "CONTEST_REMINDER",
    "title": "Contest Starting Soon",
    "message": "Codeforces Round #900 starts in 2 hours",
    "status": "SENT",
    "deliveryStatus": [
      {
        "channel": "email",
        "status": "SENT",
        "sentAt": "2024-02-16T14:30:00.000Z",
        "retryCount": 1
      }
    ],
    "updatedAt": "2024-02-16T14:30:00.000Z"
  }
}

Failure Response ​

json
{
  "success": false,
  "error": "Failed to retry notification: Invalid email address"
}

Response Fields ​

FieldTypeDescription
successbooleanWhether retry was successful
notificationobjectUpdated notification object (if successful)
errorstringError message (if failed)

Behavior ​

  • Attempts to resend the notification via all failed channels
  • Increments retryCount for each channel
  • Updates notification status based on retry result
  • Does not retry if max retry count (3) is reached
  • Only retries notifications with FAILED status

Retry Logic ​

Automatic Retries ​

Notifications are automatically retried up to 3 times with exponential backoff:

  • 1st retry: After 1 minute
  • 2nd retry: After 5 minutes
  • 3rd retry: After 15 minutes

Manual Retry ​

This endpoint allows manual retry regardless of automatic retry schedule.

Error Responses ​

404 Not Found ​

json
{
  "success": false,
  "error": "Notification not found"
}

400 Bad Request - Already Sent ​

json
{
  "success": false,
  "error": "Notification already sent successfully"
}

400 Bad Request - Max Retries ​

json
{
  "success": false,
  "error": "Maximum retry count reached (3)"
}

401 Unauthorized ​

json
{
  "statusCode": 401,
  "message": "Unauthorized",
  "error": "Unauthorized"
}

Use Cases ​

  1. Manual Recovery: Retry after fixing underlying issues
  2. User Request: User reports not receiving notification
  3. System Recovery: Retry after service restoration
  4. Testing: Test notification delivery after configuration changes
  5. Debugging: Investigate delivery issues

Example: Partial Failure ​

Notification failed on one channel but succeeded on another:

json
{
  "success": true,
  "notification": {
    "id": "507f1f77bcf86cd799439011",
    "status": "SENT",
    "deliveryStatus": [
      {
        "channel": "email",
        "status": "SENT",
        "sentAt": "2024-02-16T14:30:00.000Z",
        "retryCount": 1
      },
      {
        "channel": "push",
        "status": "FAILED",
        "failedAt": "2024-02-16T14:30:05.000Z",
        "error": "Device token expired",
        "retryCount": 4
      }
    ]
  }
}

Example: Max Retries Reached ​

json
{
  "success": false,
  "error": "Maximum retry count reached (3). Please check notification configuration."
}

Integration Example ​

React Component ​

typescript
const RetryNotification = ({ notificationId }: { notificationId: string }) => {
  const [retrying, setRetrying] = useState(false);
  
  const handleRetry = async () => {
    setRetrying(true);
    
    try {
      const response = await fetch(
        `http://localhost:3000/notifications/notifications/${notificationId}/retry`,
        {
          method: 'POST',
          headers: {
            'Authorization': `Bearer ${accessToken}`
          }
        }
      );
      
      const data = await response.json();
      
      if (data.success) {
        toast.success('Notification retried successfully');
        // Refresh notification list
        refreshNotifications();
      } else {
        toast.error(`Retry failed: ${data.error}`);
      }
    } catch (error) {
      toast.error('Failed to retry notification');
      console.error(error);
    } finally {
      setRetrying(false);
    }
  };
  
  return (
    <button 
      onClick={handleRetry} 
      disabled={retrying}
      className="retry-button"
    >
      {retrying ? 'Retrying...' : 'Retry'}
    </button>
  );
};

Vue Component ​

typescript
<script setup lang="ts">
import { ref } from 'vue';

const props = defineProps<{ notificationId: string }>();
const retrying = ref(false);

const handleRetry = async () => {
  retrying.value = true;
  
  try {
    const { data, error } = await useFetch(
      `/notifications/notifications/${props.notificationId}/retry`,
      {
        method: 'POST',
        headers: {
          Authorization: `Bearer ${accessToken.value}`
        }
      }
    );
    
    if (data.value?.success) {
      toast.success('Notification retried successfully');
      emit('retried', data.value.notification);
    } else {
      toast.error(`Retry failed: ${data.value?.error}`);
    }
  } catch (err) {
    toast.error('Failed to retry notification');
  } finally {
    retrying.value = false;
  }
};
</script>

<template>
  <button 
    @click="handleRetry" 
    :disabled="retrying"
    class="retry-button"
  >
    {{ retrying ? 'Retrying...' : 'Retry' }}
  </button>
</template>

Best Practices ​

✅ Do ​

  • Check notification status before retrying
  • Handle both success and failure responses
  • Show loading state during retry
  • Refresh notification list after successful retry
  • Log retry attempts for debugging
  • Investigate root cause of failures

❌ Don't ​

  • Retry notifications that are already sent
  • Retry repeatedly without investigating errors
  • Ignore max retry limit
  • Retry without user confirmation
  • Assume retry will always succeed

Troubleshooting ​

Common Failure Reasons ​

ErrorCauseSolution
Invalid email addressUser email is invalidUpdate user email
Device token expiredPush token is outdatedRequest new push token
Service unavailableExternal service downWait and retry later
Rate limit exceededToo many requestsWait before retrying
Max retries reachedAlready retried 3 timesCheck configuration

Built with ❤️ for competitive programmers worldwide.