Catalogian automatically retries failed webhook deliveries with exponential backoff. This page covers the retry schedule, what counts as a failure, and how to monitor deliveries.
Failed deliveries are retried up to 3 times with exponential backoff:
| Attempt | Timing | Notes |
|---|---|---|
| 1 | Immediate | First delivery attempt |
| 2 | ~1 minute after attempt 1 | First retry |
| 3 | ~5 minutes after attempt 2 | Second retry |
| — | After attempt 3 | Marked as failed permanently |
A delivery is considered failed if:
Respond quickly. Return a 2xx status immediately and process the webhook payload asynchronously. If your handler takes longer than 10 seconds, Catalogian treats it as a timeout and retries — potentially causing duplicate processing.
Due to retries, your endpoint may receive the same webhook more than once. Use the X-Catalogian-Delivery header to deduplicate:
app.post("/webhooks/catalogian", async (req, res) => {
const deliveryId = req.headers["x-catalogian-delivery"];
// Check if already processed
if (await isProcessed(deliveryId)) {
return res.status(200).send("Already processed");
}
// Mark as processing before doing work
await markProcessing(deliveryId);
// Process the payload...
res.status(200).send("OK");
});View delivery status and history in the dashboard under Source → Webhooks → Deliveries, or query the API:
GET /v1/sources/:id/webhooks/:webhookId/deliveries Authorization: Bearer cat_live_...
Each delivery record includes:
| Field | Description |
|---|---|
id | Unique delivery ID |
status | success, failed, or pending |
attemptCount | Number of attempts made (1-3) |
httpStatus | The HTTP status code returned by your endpoint |
error | Error message if delivery failed |
createdAt | When the delivery was first attempted |
completedAt | When the delivery succeeded or finally failed |
Catalogian does not automatically disable webhooks after consecutive failures. Your webhook will continue to receive deliveries on future delta events even if previous deliveries failed. You can manually disable a webhook in the dashboard or via the API:
PATCH /v1/sources/:id/webhooks/:webhookId
Authorization: Bearer cat_live_...
Content-Type: application/json
{ "enabled": false }See the complete webhook payload schema. Payload Reference →