Webhook Retry Policy
When Pay.io delivers a webhook to your configured endpoint, it expects a 2xx response within 5 seconds. If no valid response is received within that window, the delivery is considered failed and Pay.io will automatically attempt redelivery according to the retry schedule below.
Delivery Lifecycle
Every webhook delivery follows the same progression from initial attempt through to escalation:
Automatic retries (if initial delivery fails)
Up to 50 attempts
Linear back off kicks in when the initial delivery fails. Each attempt waits longer before retrying. See the table of attempts and delays below.
Manual retries (if webhook status is CALLBACK_FAILED)
Up to 3 merchant-initiated attempts via the Merchant Console. When status is CALLBACK_FAILED, the Merchant can re-trigger delivery from the Merchant Console at any time. Tracked independently of automatic retries.
Available for Deposits and Payouts.
Automatic Retries
Failed webhook deliveries are retried automatically using a linear backoff strategy. The delay between each attempt is calculated as:
delay = attempt number × 10 minutes1
10 minutes
2
20 minutes
3
30 minutes
4
40 minutes
…
…
50
500 minutes (~8.3 hours)
A maximum of 50 retry attempts are made. Once all attempts are exhausted, the webhook is marked as permanently failed and no further automatic deliveries will be attempted.
Manual Retries
In addition to automatic retries, merchants can manually re-trigger webhook delivery from the Merchant Console at any time whilst the callback status is CALLBACK_FAILED.
Manual retry rules
Manual retries are available for both Deposits and Payouts with a status of
CALLBACK_FAILED.A maximum of 3 manual retry attempts are permitted per transaction.
Manual retries are tracked independently of automatic retries — exhausting automatic attempts does not consume your manual retry allowance, and vice versa.
Once all 3 manual retry attempts have been used, contact Pay.io support to request further assistance with redelivery.
Best Practices
Respond immediately, process asynchronously
Your endpoint should return a 2xx status code as soon as the webhook payload is received — even if you have not yet finished processing it. Queue the payload for processing in the background. Delaying your response to complete processing first risks exceeding the 5-second response window and triggering the retry cycle unnecessarily.
Set up internal alerts for early-stage failures
Automatic retries are designed to handle transient endpoint issues. However, as the attempt number increases, so does the delay before the next retry — reaching over 8 hours by attempt 50. Waiting for the automatic retry schedule to resolve a failure is rarely the right approach for time-sensitive transactions such as deposits or withdrawal confirmations.
We strongly recommend configuring your own internal monitoring to alert your team when a webhook enters CALLBACK_FAILED status. This allows you to assess and resolve the underlying issue promptly, and to use your manual retry allowance to redeliver the webhook as soon as your endpoint is healthy — rather than waiting hours for the next automatic attempt.
A practical alerting threshold to consider:
3
~60 minutes
Investigate endpoint health
5
~150 minutes
Trigger internal alert to your engineering team
10
~550 minutes (~9 hours)
Escalate and initiate manual retry immediately
Use manual retries before automatic attempts are exhausted
Your 3 manual retry attempts are a valuable tool for recovering from delivery failures quickly — particularly when the automatic retry schedule has reached a long delay window. Do not wait until automatic retries are fully exhausted before intervening. If your endpoint is healthy and a webhook has been waiting for hours, trigger a manual retry from the Merchant Console to resolve the delivery immediately.
Manual and automatic retry attempts are tracked independently. However, once both are exhausted for a given transaction, Pay.io will not attempt further automatic redelivery. If you reach this state, contact Pay.io support as soon as possible.
Ensure your endpoint is idempotent
Because the same webhook event may be delivered more than once — across both automatic and manual retry attempts — your endpoint must be built to handle duplicate deliveries safely. Use the transaction ID included in the webhook payload as an idempotency key to ensure that processing the same event multiple times does not result in duplicate operations on your platform.
Last updated