Retry Handling
How Cresora retries failed webhook deliveries and how to handle them idempotently.
Cresora automatically retries webhook deliveries that don't receive a 2xx response. Your receiver must handle retries gracefully.
Retry schedule
| Attempt | Delay after failure |
|---|---|
| Initial | Immediate |
| 1st retry | 30 seconds |
| 2nd retry | 5 minutes |
| 3rd retry | 30 minutes |
| 4th retry | 2 hours |
| 5th+ | Exponential backoff, max 12 hours per attempt |
| Total window | 72 hours |
After 72 hours of consecutive failures, the delivery is marked failed and Cresora sends a webhook.delivery_failed meta-event to your notification email.
What triggers a retry
- HTTP response with any non-
2xxstatus code (including redirects — do not redirect) - No response within 30 seconds (timeout)
- Connection refused or DNS resolution failure
Idempotent retry handling
Because Cresora retries, your handler will receive the same event multiple times. Always handle events idempotently:
import crypto from "node:crypto";
// Use event.id as an idempotency key
async function handleWebhookEvent(event) {
// Check if we've already processed this event
const existing = await db.processedEvents.findOne({ eventId: event.id });
if (existing) {
console.log(`Duplicate event ${event.id} — skipping`);
return; // Already handled; return 200 anyway
}
// Process the event
await processEvent(event);
// Record that we've handled it
await db.processedEvents.insert({
eventId: event.id,
processedAt: new Date(),
});
}Return 200 OK even for duplicate events. If you return 4xx on a duplicate, Cresora will keep retrying, creating more duplicates.
Respond quickly, process asynchronously
Your endpoint must respond within 30 seconds. For complex processing, respond immediately and handle the work in a background queue:
app.post("/webhooks/cresora", async (req, res) => {
verifySignature(req); // Throws on invalid signature — respond 400
res.sendStatus(200); // Respond immediately
await queue.enqueue(req.body); // Process asynchronously
});Manual replay
You can manually replay any webhook delivery from the Partner Portal:
- API Settings → Webhooks → Delivery Log
- Find the failed delivery
- Click Replay
Replayed events have the same id as the original — your idempotency logic will correctly deduplicate them.