Delivery guarantee
| Aspect | Behavior |
|---|---|
| Guarantee | At-least-once. Your endpoint may receive duplicate events. |
| Success criteria | Your server must return a 2xx status code within 15 seconds. |
| Ordering | Events are not guaranteed to arrive in order. Use created_at for ordering. |
| Batching | One HTTP request per event per endpoint. Events are not batched. |
Return a
200 response immediately, then process the event asynchronously. If your handler takes longer than 15 seconds, the delivery will be marked as failed and retried.Retry schedule
When your endpoint returns a non-2xx response or times out, Yoshi retries with exponential backoff:
| Attempt | Delay | Total elapsed |
|---|---|---|
| 1st retry | 5 seconds | 5 seconds |
| 2nd retry | 5 minutes | ~5 minutes |
| 3rd retry | 30 minutes | ~35 minutes |
| 4th retry | 2 hours | ~2.5 hours |
| 5th retry | 5 hours | ~7.5 hours |
| 6th retry | 10 hours | ~17.5 hours |
| 7th retry | 10 hours | ~27.5 hours |
Endpoint failure handling
If your endpoint consistently fails to respond:Endpoint is disabled
If an endpoint fails repeatedly over multiple events, it is automatically disabled to prevent unnecessary traffic.
You investigate and fix
Check the delivery logs via
GET /v1/webhooks/deliveries or the consumer portal to see response codes and error details.Idempotency
Every event has a uniqueid field that is stable across retries. Use this ID to deduplicate events in your handler:
For production use, store processed event IDs in a database or Redis with a TTL of at least 7 days. An in-memory set won’t survive server restarts.
Ordering
Events are not guaranteed to arrive in the order they occurred. For example, you might receivetransaction.updated before transaction.created for the same transaction.
To handle this:
- Use the
created_attimestamp to determine the chronological order of events. - Design your handlers to be order-independent when possible.
- If you need strict ordering, buffer events and sort by
created_atbefore processing.
Best practices
Return 200 immediately, process asynchronously
Return 200 immediately, process asynchronously
Your webhook handler should acknowledge receipt as fast as possible. Enqueue the event for background processing rather than doing work inline. This prevents timeouts and retries.
Use event IDs for deduplication
Use event IDs for deduplication
The
id field is stable across retries. Store processed event IDs to prevent duplicate processing, especially for events that trigger side effects like sending emails or creating records.Verify signatures before processing
Verify signatures before processing
Always verify the webhook signature before trusting the payload. An unverified webhook could be forged by a third party.
Fetch full details from the API
Fetch full details from the API
Webhook payloads contain resource IDs and metadata, not full objects. Use the IDs to fetch current data from the API. This ensures you always have the latest state, even if events arrive out of order.
Monitor your delivery logs
Monitor your delivery logs
Check
GET /v1/webhooks/deliveries or the consumer portal regularly to catch failed deliveries early. Set up alerts if your failure rate spikes.Handle unknown event types gracefully
Handle unknown event types gracefully
Yoshi may add new event types in the future. If your handler encounters an event type it doesn’t recognize, return
200 and ignore it. Never return an error for unknown types — that would trigger unnecessary retries.