Skip to main content
Webhooks are outbound HTTP notifications Paylead sends when something happens in the platform: a Reward is created, validated, or paid out. They let the Program Manager react in real time without polling the API. Two principles to remember:
  1. The Webhook is a trigger, not a source of truth. Always re-fetch the underlying object via the API before acting on it.
  2. 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 a POST request with a JSON body containing four fields.
{
  "event_type": "REWARD_CREATED",
  "resource_id": "550e8400-e29b-41d4-a716-446655440000",
  "consumer_id": "ext-user-123",
  "user_id": "6ba7b810-9dad-11d1-80b4-00c04fd430c8"
}
FieldTypeDescription
event_typestringThe event identifier.
resource_idstring (UUID)The ID of the primary object the event relates to.
consumer_idstring or nullThe external Consumer ID. Null for payout, Offer, and file events.
user_idstring (UUID) or nullThe 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.
Use consumer-facing events to drive Consumer animation: push notifications, in-app Reward status updates, and any display visible to the Consumer. Technical events are for back-office processing (accounting, payout pipelines).
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.
EventDescriptionresource_id
consumer_reward_validationThe Reward has entered validation; show a pending status to the Consumer.Reward ID
consumer_reward_pooledThe Reward has landed in the Consumer’s pool; the Consumer can see it in the app.Reward ID
consumer_reward_paidThe Reward has been paid to the Consumer’s account.Reward ID
consumer_reward_cancelledThe Reward was cancelled (refund, dispute, or expiry).Reward ID
Sent on every change to the internal processing status of a Cashback or Gift. Use these for back-office operations.
EventDescriptionresource_id
reward_createdA new Reward is created in PENDING_VALIDATION.Reward ID
reward_validatedThe Reward is VALIDATED; Paylead now guarantees the payout.Reward ID
reward_paid_inPaylead has received the funds from the merchant.Reward ID
reward_paid_outThe Reward has been paid out to the Program.Reward ID
Sent when an Offer changes or approaches its limits. consumer_id and user_id are null for these events.
EventDescriptionresource_id
new_offer_availableA new Offer has been published and is available to Consumers.None
offer_ending_soon_dateThe Offer expires in less than 3 days.Offer ID
offer_ending_soon_budgetThe Offer budget has exceeded 90% consumption.Offer ID
offer_cashback_rate_increaseThe Cashback rate has been increased (new phase).Offer ID
Sent when Paylead executes a payout batch for the Program. consumer_id and user_id are null for these events.
EventDescriptionresource_id
payout_successThe payout batch completed successfully. Funds have been transferred to the Program account.Payout ID
payout_errorThe payout batch failed. No transfer was made.Payout ID
EventDescriptionresource_id
ventilation_file_availableA Ventilation file is ready for download. consumer_id and user_id are null.File ID
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.
Acknowledge with 200 before doing any heavy work. Push the event into your own queue and process asynchronously. Slow endpoints get retried and pile up in Paylead’s queue.

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.
Sign and verify against the raw request body, not the parsed JSON. Re-serializing the body changes the bytes and breaks the signature.

Basic Auth

Paylead adds a standard Authorization: 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 example X-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.
AttemptDelay since previousTime since first attempt
1 (initial)n/aT+0
22 minT+2 min
34 minT+6 min
48 minT+14 min
516 minT+30 min
632 minT+62 min
After the final attempt fails, the event is marked as failed. Failed events surface in Shift for manual replay.
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

Ordering is not guaranteed. Paylead does not promise that reward_validated arrives after reward_created at your endpoint.Building business logic that assumes “reward_created always comes first” will eventually break.

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.
Test in sandbox first. The sandbox environment replays the full Webhook flow against your endpoint with synthetic transactions. Use it to verify signature validation and your retry behaviour before exposing a production endpoint. Sandbox is also the only safe place to deliberately return 500 responses and watch how Paylead retries.

Common pitfalls

SymptomLikely causeFix
Stale Reward status acted onYou trusted the Webhook payloadRe-fetch via the API before acting.
Webhook retries flooding your queueEndpoint returns 200 too lateAck first, process async.
Wrong signaturesReading the parsed body instead of the raw bodyVerify 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.