- The Webhook is a trigger, not a source of truth. Always re-fetch the underlying object via the API before acting on it.
- Ordering is not guaranteed. Events for the same object may arrive out of order. Trust the status returned by the API, not the sequence of events.
Payload structure
Every Webhook is aPOST request with a JSON body containing four fields.
| Field | Type | Description |
|---|---|---|
event_type | string | The event identifier. |
resource_id | string (UUID) | The ID of the primary object the event relates to. |
consumer_id | string or null | The external Consumer ID. Null for payout, Offer, and file events. |
user_id | string (UUID) or null | The internal Paylead user ID. Null for payout, Offer, and file events. |
Event catalog
Paylead emits two parallel event families for Rewards: consumer-facing events and technical events. They are independent, each tracking a different perspective on the same lifecycle.Consumer-facing Reward events
Consumer-facing Reward events
Track what the Consumer experiences in the bank app. These events fire when the Consumer’s view of a Reward changes, independently of Paylead’s internal processing.
| Event | Description | resource_id |
|---|---|---|
consumer_reward_validation | The Reward has entered validation; show a pending status to the Consumer. | Reward ID |
consumer_reward_pooled | The Reward has landed in the Consumer’s pool; the Consumer can see it in the app. | Reward ID |
consumer_reward_paid | The Reward has been paid to the Consumer’s account. | Reward ID |
consumer_reward_cancelled | The Reward was cancelled (refund, dispute, or expiry). | Reward ID |
Reward technical events
Reward technical events
Sent on every change to the internal processing status of a Cashback or Gift. Use these for back-office operations.
| Event | Description | resource_id |
|---|---|---|
reward_created | A new Reward is created in PENDING_VALIDATION. | Reward ID |
reward_validated | The Reward is VALIDATED; Paylead now guarantees the payout. | Reward ID |
reward_paid_in | Paylead has received the funds from the merchant. | Reward ID |
reward_paid_out | The Reward has been paid out to the Program. | Reward ID |
Offer events
Offer events
Sent when an Offer changes or approaches its limits.
consumer_id and user_id are null for these events.| Event | Description | resource_id |
|---|---|---|
new_offer_available | A new Offer has been published and is available to Consumers. | None |
offer_ending_soon_date | The Offer expires in less than 3 days. | Offer ID |
offer_ending_soon_budget | The Offer budget has exceeded 90% consumption. | Offer ID |
offer_cashback_rate_increase | The Cashback rate has been increased (new phase). | Offer ID |
Payout events
Payout events
Sent when Paylead executes a payout batch for the Program.
consumer_id and user_id are null for these events.| Event | Description | resource_id |
|---|---|---|
payout_success | The payout batch completed successfully. Funds have been transferred to the Program account. | Payout ID |
payout_error | The payout batch failed. No transfer was made. | Payout ID |
Other events
Other events
| Event | Description | resource_id |
|---|---|---|
ventilation_file_available | A Ventilation file is ready for download. consumer_id and user_id are null. | File ID |
Deprecated events
Deprecated events
Do not subscribe to these events for new integrations.
- Affiliation events (
affiliation_*): Paylead no longer offers Affiliation. scrapping_error: the bank synchronization failure event is deprecated.
Setting up your endpoint
Each event type is configured independently in Shift: you assign one HTTPS endpoint per event. The same endpoint URL can receive multiple event types.Securing your endpoint
Paylead offers three mechanisms to authenticate incoming Webhooks. They are all optional and can be combined on the same Program. Configure them per endpoint in Shift.HMAC SHA-256
Paylead signs the raw request body with a shared secret (minimum 32 characters) using HMAC-SHA256. The signature travels in a dedicated header.- Signature header:
X-paylead-signature-256, a hex digest (not base64). - Timestamp header (optional):
X-paylead-timestamp, included in the signed string to protect against replay attacks. - Verification: recompute the HMAC with the same secret over the raw body and compare it against the header.
Basic Auth
Paylead adds a standardAuthorization: Basic <base64(username:password)> header to every request. Use this when your endpoint already handles HTTP Basic authentication.
Custom header
Paylead injects an arbitrary header with a static name and value defined at configuration time. Use this to pass a proprietary token your system expects, for exampleX-Api-Key: <value>.
On request, Paylead can also set up a mutual TLS (mTLS) flow for the Webhook calls it makes to your endpoint.
Reliability
A robust Webhook integration handles delivery failures and ordering surprises.Retry policy
Paylead retries any delivery that returns a non-2xx response or times out. The current policy is 5 attempts maximum with an exponential backoff of 2^n minutes between attempts, where n is the attempt number.
| Attempt | Delay since previous | Time since first attempt |
|---|---|---|
| 1 (initial) | n/a | T+0 |
| 2 | 2 min | T+2 min |
| 3 | 4 min | T+6 min |
| 4 | 8 min | T+14 min |
| 5 | 16 min | T+30 min |
| 6 | 32 min | T+62 min |
This retry schedule is the current default and may evolve. Build your handler so it tolerates a stricter or looser cadence: what matters is that you ack quickly and re-fetch the object via the API.
Ordering
Re-fetch before acting
Webhooks reflect state at the moment of dispatch. Between dispatch and your handler running, the underlying object may have moved on. Always issue an API call to read the current state before triggering money movement or notifications.Common pitfalls
| Symptom | Likely cause | Fix |
|---|---|---|
| Stale Reward status acted on | You trusted the Webhook payload | Re-fetch via the API before acting. |
| Webhook retries flooding your queue | Endpoint returns 200 too late | Ack first, process async. |
| Wrong signatures | Reading the parsed body instead of the raw body | Verify against req.rawBody, not req.body. |
What’s next
Versioning
The mandatory
X-Api-Version header and the version policy.Rate limits
Per-token request limits and backoff strategy.