OutpayDocs
Guides

Receive and process webhooks

Verify, deduplicate, and fulfil a checkout.paid event.

Who this is for

Developers implementing a production webhook receiver, beyond the basic signature check covered in verify webhook signatures.

Before you begin

  • A working signature-verification function.
  • A database table (or equivalent) to record processed delivery IDs and order-fulfilment state.

Steps

  1. Capture the raw request body.
  2. Validate the timestamp window.
  3. Compute v1=HMAC_SHA256(secret, timestamp + "." + rawBody).
  4. Compare signatures with a timing-safe function.
  5. Reject a delivery whose ID has already been processed.
  6. Parse the JSON body and confirm event === "checkout.paid".
  7. Look up your order using the stored checkout reference.
  8. Commit a unique fulfilment transition, then return a 2xx response.
// Pseudocode for the database boundary.
await db.transaction(async (tx) => {
  const inserted = await tx.insertProcessedWebhookIfAbsent(deliveryId);
  if (!inserted) return;
  await tx.markOrderPaidOnce({ orderId, checkoutRef, txHash });
});

Expected result

Return a 2xx status only after the event is durably recorded. If your endpoint returns a failure, Outpay retries according to its own retry schedule.

Common problems

ProblemLikely causeNext step
Endpoint gets auto-disabledThree consecutive full retry cycles all failed.Fix the underlying failure, then re-save the endpoint in Developers to re-enable it and rotate the secret.
Order fulfilled twiceThe delivery-ID deduplication check runs after the fulfilment side effect, not before it.Insert the processed-delivery record and check for fulfilment inside the same transaction, as shown above.

On this page