> ## Documentation Index
> Fetch the complete documentation index at: https://doc.seerbit.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Webhooks

> Receive push notifications when a POS transaction reaches a final state.

If a `webhookUrl` was supplied at initiation, SeerBit sends a webhook event for the transaction — a `transaction.completed` event when the transaction is successful, and a `transaction.failed` event when it fails on the POS.

> **Before you integrate**: Your webhook endpoint must be publicly accessible and able to receive `POST` requests from the SeerBit API.

## Notifications

### Delivery headers

| Header | Description |
| - | - |
| `X-Webhook-Event` | Event type, e.g. `transaction.completed`. |
| `X-Webhook-Event-Id` | Unique identifier for this webhook delivery. |
| `X-Webhook-Signature` | HMAC-SHA256 signature of the payload — present only if a signing secret has been configured for your webhook. |
| `X-Webhook-Encrypted` | `true` if the payload body is AES-256-GCM encrypted for your business. |

### Payload samples

<CodeGroup>
  ```json Transaction completed theme={null}
  {
    "id": "evt_94c252f8-075",
    "type": "transaction.completed",
    "timestamp": "2026-07-03T13:34:28.456360900Z",
    "data": {
      "orderId": "112990000323",
      "transactionRef": "ITA87EE5e51709977888779DAA4E05",
      "status": "COMPLETED",
      "transactionValue": "50.00",
      "posId": "2214HX01",
      "amountPaid": "50.00",
      "cardNumber": "411111******1234",
      "paymentType": "CARD",
      "response": "Transaction successful",
      "responseCode": "200",
      "merchantId": "SBT-MERCH-004521",
      "sessionId": "000435317658",
      "transactionTime": "03-07-2026 02:34 PM",
      "completedAt": "2026-07-03T13:34:28.456414484Z"
    }
  }
  ```

  ```json Transaction failed theme={null}
  {
    "id": "evt_d906afd6-d6e",
    "type": "transaction.failed",
    "timestamp": "2026-07-02T22:54:23.496206016Z",
    "data": {
      "orderId": "1122223",
      "transactionRef": "ITA87EE5510999DAA4E05",
      "status": "FAILED",
      "transactionValue": "5.00",
      "posId": "2214HX01",
      "responseCode": "400",
      "response": "Incorrect PIN entered",
      "sessionId": "000435317652",
      "transactionTime": "02-07-2026 11:54 PM",
      "completedAt": "2026-07-02T22:54:23.496266234Z"
    }
  }
  ```
</CodeGroup>

> **Note**: Fields such as `responseCode` and `response` reflect the decline reason where the terminal or card scheme provides one. `amountPaid`, `cardNumber`, and `paymentType` are generally absent on a failed attempt.

### Payload fields

| Field | Description |
| - | - |
| `id` | Unique identifier for this webhook event. |
| `type` | Event type: `transaction.completed` or `transaction.failed`. |
| `timestamp` | UTC timestamp the event was generated. |
| `orderId` | Echoes the `orderId` submitted at initiation. |
| `transactionRef` | The transaction reference for this attempt. |
| `status` | Final transaction status: `COMPLETED` or `FAILED`. |
| `transactionValue` | Transaction amount that was requested, as a decimal string. |
| `posId` | Identifier of the POS terminal the transaction was processed on. |
| `amountPaid` | Amount captured on the terminal. Present on completed transactions. |
| `cardNumber` | Masked card number used for payment. Present on completed transactions. |
| `paymentType` | Payment instrument used, e.g. `CARD`. |
| `response` | Human-readable detail on the transaction outcome, e.g. an incorrect PIN entry. |
| `responseCode` | One of three possible values: `200` (SUCCESS), `400` (FAILED), or `401` (CANCELED). |
| `merchantId` | Identifier of the merchant the terminal is registered under. |
| `sessionId` | The SeerBit reference for this transaction — use this value when reconciling with SeerBit. |
| `transactionTime` | Local timestamp the transaction was processed on the terminal. |
| `completedAt` | UTC timestamp the transaction reached its terminal status. |

## Decrypting encrypted webhooks

If your SeerBit account team has enabled payload encryption for your business, webhook payloads are encrypted with AES-256-GCM before delivery and `X-Webhook-Encrypted` is set to `true`. Follow the steps below to decrypt them on your end.

| Property | Value |
| - | - |
| Algorithm | AES-256-GCM |
| Key derivation | SHA-256 hash of your SeerBit secret key |
| IV length | 12 bytes, random, prepended to the ciphertext |
| Tag length | 128 bits (16 bytes), appended to the ciphertext |
| Encoding | Base64 of IV + ciphertext + GCM tag |

##### Steps to decrypt

1. Base64-decode the webhook payload body.
2. Take the first 12 bytes as the IV (initialization vector).
3. Take the last 16 bytes as the GCM authentication tag.
4. Derive the AES key as `SHA-256(secretKey)`.
5. Decrypt the remaining bytes (the ciphertext) using AES-256-GCM with the derived key, IV, and tag.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.