Skip to main content
Tabby Webhooks are HTTPS callbacks that notify you about payment-related and token-related events. You register a URL once, and Tabby sends a POST request to it whenever an event related to your account occurs — even when the customer never returns to your site. This makes webhooks the most reliable way to catch authorized payments.

How They Work

1

Register an endpoint

Register a webhook for each merchant_code + secret key pair. The environment is determined by the key you register with: a production key (sk_...) registers webhooks for production payments, a test key (sk_test_...) — for test payments. Each pair can have up to 4 webhooks. An optional auth header can sign the requests so you can verify their authenticity.
2

Receive notifications

Tabby sends a POST request to your URL whenever the payment status changes.
3

Acknowledge with 200

Respond with a 200 HTTP status code to confirm the reception, and check the auth header to verify the request. Any other response (or no response) counts as a delivery error and triggers retries.

Payload

Webhooks are POST requests with a JSON body:
{
  "id": "string",
  "created_at": "2021-09-14T13:08:54Z",
  "expires_at": "2022-09-14T13:08:54Z",
  "closed_at": "2021-09-14T13:09:45Z",
  "status": "closed",
  "is_test": false,
  "is_expired": false,
  "amount": "100",
  "currency": "SAR",
  "order": {
    "reference_id": "string"
  },
  "captures": [
    {
      "id": "string",
      "amount": "100",
      "created_at": "2021-09-14T13:09:45Z",
      "reference_id": "string"
    }
  ],
  "refunds": [
    {
      "id": "string",
      "amount": "100",
      "created_at": "2021-09-14T14:14:02Z",
      "reference_id": "string",
      "reason": "string"
    }
  ],
  "meta": {
    "order_id": null,
    "customer": null
  },
  "token": "string"
}
Webhook payloads use lowercase statuses ("authorized"), while the Retrieve Request returns uppercase ("AUTHORIZED") — this is expected. See Payment Statuses.

Supported Events

The payload content depends on the event:
EventWebhook payment statusPayload update
Authorizeauthorized”status”: “authorized”
Captureauthorizedcapture info is added to captures.[] array
Closeclosed”status”: “closed” and “closed_at” updated
Rejectrejected”status”: “rejected”
Expire (Optional)expired”status”: “expired”, “expired_at” and “is_expired” updated
Refundclosedrefund info is added to refunds.[] array
Updatethe same as before the Update Requestorder.reference_id updated
The “expire” event is optional — ask the Tabby team to enable it for your store if you want notifications when a payment is cancelled by the customer or expires.

A Typical Payment

For a regular successful order you will receive three notifications:
  1. Payment authorized — the payload status is authorized. Check the order and process it in your OMS if it wasn’t processed yet, then send the Capture Request.
  2. Payment captured — the payload status is still authorized, with your capture added to the captures array. No action is required.
  3. Payment closed — the payload status is closed: the payment is completed and confirmed from both sides. No action is required.

Best Practices

Webhooks are asynchronous: the delivery order is not guaranteed, and the same event may occasionally be delivered twice.
  • Respond fast. Acknowledge the webhook with 200 right away and process it asynchronously, instead of holding the response until processing is done.
  • Handle out-of-order delivery. A capture event may arrive before an authorization event — use a finite state machine or similar logic instead of assuming the order.
  • Deduplicate. Ignore a webhook if the same notification was already processed.
  • Filter events. You receive notifications for all payment events — process only the ones you need.
  • Allowlist Tabby server IPs:
    34.166.36.90
    34.166.35.211
    34.166.34.222
    34.166.37.207
    34.93.76.191
    34.166.128.182
    34.166.170.3
    34.166.249.7
    
To test and debug webhooks, use a tool like Webhook.site to inspect the payload and headers Tabby sends to your endpoint.

Retry Attempts

A webhook request times out after 1 minute. If it times out or gets any response other than 200, Tabby resends it up to 4 more times with an exponential interval between attempts (1–4 minutes). Retries don’t block other notifications — Tabby keeps sending webhooks for other payment events as they occur.