Safepay webhooks notify you when payments, refunds, or settlements change state. Use this guide to create webhook endpoints, verify signatures, and process retries safely.Documentation Index
Fetch the complete documentation index at: https://safepay.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Create a webhook endpoint
Choose the events you need
Subscribe to the specific event types your integration depends on, such as
payment.completed or refund.completed.Create the webhook
Call
POST /v1/aggregators/{{aggregator_id}}/webhooks with the URL and event list.Webhook headers
Safepay includes headers that identify the event and allow you to verify authenticity. Always read:X-SFPY-SIGNATUREfor the HMAC signatureX-SFPY-TIMESTAMPfor the event timestamp
Signature verification
Safepay computes the webhook signature overtimestamp + '.' + raw_body: the X-SFPY-TIMESTAMP value, a literal period, then the raw HTTP request body bytes. Use the signature header and timestamp header to verify authenticity before parsing JSON.
Build the signing payload
Read the raw HTTP request body bytes exactly as received. Build the signing payload as
timestamp + '.' + raw_body. Use the X-SFPY-TIMESTAMP header value exactly as received, without reformatting it.Do not parse, prettify, re-serialize, or otherwise modify the request body before verification. Any modification to the body bytes will cause signature verification to fail.
Compute HMAC
Base64-decode the webhook secret and use the decoded bytes as the HMAC-SHA256 key. Compute the HMAC over the full signing payload (
timestamp + '.' + raw_body), not the raw body alone.Pass the raw request body bytes to
Verify as body. Only after verification succeeds should you parse the JSON and process the event.Retry behavior
Safepay retries failed deliveries up to 5 attempts using exponential backoff:- Attempt 1: 1 second
- Attempt 2: 2 seconds
- Attempt 3: 4 seconds
- Attempt 4: 8 seconds
- Attempt 5: 16 seconds
200 OK as soon as you persist the event to stop further retries.
Event catalog
| Event | Category | Description |
|---|---|---|
payment.created | Payments | A new payment request was created (initiated by customer). |
payment.pending_authorization | Payments | Payment is awaiting authorization (for example, Pay Later checks). |
payment.authorized | Payments | Payment has been authorized and funds are on hold. |
payment.completed | Payments | Payment has been captured or charged successfully. |
payment.settled | Payments | Payment funds have been settled to the merchant. |
payment.refunded | Payments | Payment was fully refunded. |
payment.refund_partial | Payments | Payment was partially refunded. |
payment.rejected | Payments | Payment was rejected before authorization. |
payment.failed | Payments | Payment processing failed. |
payment.reversed | Payments | Payment was reversed after completion. |
payment.voided | Payments | Payment authorization was voided. |
settlement.created | Settlements | Settlement request was created. |
settlement.processing | Settlements | Settlement is currently processing. |
settlement.completed | Settlements | Settlement completed successfully. |
settlement.failed | Settlements | Settlement failed during processing. |
settlement.on_hold | Settlements | Settlement temporarily placed on hold. |
settlement.reversed | Settlements | Settlement was reversed. |
refund.created | Refunds | Refund request was created. |
refund.completed | Refunds | Refund was successfully completed. |
refund.failed | Refunds | Refund failed during processing. |
refund.canceled | Refunds | Refund request was canceled. |