Skip to main content

What counts as success

Pazy treats a delivery as successful only when your endpoint returns a 2xx status within the timeout. Everything else is a failure:
  • Any 3xx, 4xx or 5xx status. Redirects are not followed.
  • No response within the timeout. The default is 10 seconds and the maximum is 30.
  • A connection, DNS or TLS error.
  • A response body larger than 64 KB.
  • A URL that fails the URL requirements.
Return 200 or 204 with an empty body as soon as you’ve stored the event.

Retry schedule

A failed delivery is retried with exponential backoff and about ±10% random jitter, for up to 5 attempts in total. Retries are picked up by a scheduler that polls every 30 seconds by default, so an attempt can start somewhat later than the nominal delay. After the fifth failed attempt, Pazy stops. The delivery is marked as exhausted and is not sent again automatically.
A self-serve view of failed deliveries and manual redelivery are coming soon. Until then, if your endpoint was down for more than about 8 minutes, reconcile with the API: list recent records and compare them with what you received. If you need missed events replayed, contact customer-support@pazy.io.

Handle duplicates

Delivery is at-least-once. The same event can reach you more than once, for example when your 200 is lost on the network and Pazy retries. The event id is the same on every attempt.
  1. Before processing, look up id in a table or cache of handled events.
  2. If it’s there, return 200 and do nothing else.
  3. If not, process the event and record the id. Do both in one database transaction where you can.
For payment.* events, you can also dedupe on data.paymentId, which is unique per payment.

Don’t rely on ordering

Events can arrive out of order. A retry of an older event can land after a newer one has already been delivered. For example, you might see expense.approval.status_changed for APPROVED before an earlier retry for PENDING.
  • Compare timestamps to decide which event is newer: the envelope’s createdAt, or paymentDate on payment.* events (it is null on failures and reversals).
  • Treat status fields as the latest known state only if the event is newer than what you already hold.
  • When correctness matters, fetch the current record by id with the API.

Respond fast, process later

Your handler holds up Pazy’s delivery while it runs, and a slow response risks a timeout and a duplicate.
1

Verify

Check the signature.
2

Persist

Save the raw event, or push it onto a queue such as SQS, RabbitMQ or a jobs table.
3

Acknowledge

Return 200 right away.
4

Process

A background worker does the real work, and retries on its own failures.

Return the right status

A 4xx response is also retried. Pazy doesn’t treat any non-2xx status as permanent, so don’t return 400 for events you simply don’t care about.

Differences from API retries

The retry rules in Errors and retries apply to requests you send to Pazy. Webhook retries are Pazy retrying requests to you, on the fixed schedule above. They don’t honor Retry-After headers.