Webhook processing best practices
Webhooks are delivered once, without an event identifier, and are not retried. A robust receiver therefore acknowledges quickly, processes safely and reconciles regularly.
Checklist
- Verify the signature and timestamp before doing anything else. See Webhook security.
- Return a
2xxresponse promptly. - Process each event as an upsert.
- Deduplicate using the resource identifier and status.
- Fetch the latest resource data where necessary.
- Record failed processing attempts.
- Reconcile on a schedule.
Respond quickly
Spendstream makes a single delivery attempt and does not use a short timeout, so a slow endpoint can hold up the sender. Store the raw event, return 200, then process it from a queue or background job.
sequenceDiagram
participant SS as Spendstream
participant EP as Your endpoint
participant W as Your worker
SS->>EP: POST event
EP->>EP: Verify signature
EP->>EP: Save event to queue
EP-->>SS: 200 OK
W->>EP: Take event from queue
W->>W: Upsert record
Process events as upserts
Handle every event as “create if missing, otherwise update”. This makes your handler safe when the same event arrives twice, when events arrive out of order, or when an event arrives for a record you have not seen yet.
key = transaction identifier (or user UID)
if a record with key exists: update it
else: create it
Deduplicate without an event identifier
There is no event id. Build your own key from the transaction or user identifier plus the status, and skip work if you have already applied that combination.
⚠️ Warning: Do not deduplicate on the timestamp. It changes with every delivery.
Handle out-of-order and repeated updates
An affiliate transaction may move through pending, approved, declined or amended states, and deliveries may not arrive in order. Before overwriting a record with an older-looking state, fetch the current transaction with getTransactionsById and store what it returns.
Fetch the latest data
The signature does not cover the body. For anything that moves money or rewards, such as crediting a user, use the webhook as a trigger and confirm the values with getTransactionsById.
Record failures
If your processing fails after you have acknowledged the event, write the raw payload, the error and the time to a failure log or dead-letter queue so that you can replay it. Spendstream will not send it again.
Reconcile on a schedule
Because there is no retry, a webhook missed during an outage is lost. Run a periodic job, for example hourly or daily, that calls getTransactionsList for the recent period and upserts any transactions your database does not hold or holds in an older state.
Operational tips
- Log the event type, the identifier and the outcome. Do not log secrets or login tokens.
- Alert when signature failures spike, which can indicate a wrong URL or secret.
- Keep the registered URL stable. Changing it changes the signature input, so tell Spendstream before you move it.
On this page
- Webhook processing best practices