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

# 📑 Webhooks

A webhook is an HTTP `POST` that BillStack sends to your server the moment something happens - most importantly, when a customer pays into one of your virtual accounts. Instead of polling the API, you register a URL once and BillStack pushes events to it as they occur.

## Set your webhook URL

Add your endpoint URL in the dashboard under **Developer → Webhooks**. It must be a public `https` URL that accepts `POST` requests with a JSON body.

## The payment event

When funds arrive in a virtual account, BillStack sends a `PAYMENT_NOTIFICATION` event:

```json theme={null}
{
  "event": "PAYMENT_NOTIFICATION",
  "data": {
    "type": "RESERVED_ACCOUNT_TRANSACTION",
    "reference": "virtual_account_reference",
    "merchant_reference": "virtual_account_reference",
    "wiaxy_ref": "inter_bank_reference",
    "transaction_ref": "inter_bank_reference",
    "amount": "payment_amount",
    "created_at": "receiving_date",
    "account": {
      "account_number": "customer_account_number",
      "account_name": "customer_account_name",
      "bank_name": "customer_bank_name",
      "created_at": "account_creation_date"
    },
    "payer": {
      "account_number": "payer_acct_num",
      "first_name": "payer_first_name",
      "last_name": "payer_last_name",
      "createdAt": "payment_date"
    }
  }
}
```

### Fields

| Field                                        | Description                                                                            |
| -------------------------------------------- | -------------------------------------------------------------------------------------- |
| `event`                                      | The event type. Currently `PAYMENT_NOTIFICATION`.                                      |
| `data.type`                                  | The kind of transaction. `RESERVED_ACCOUNT_TRANSACTION` for a virtual-account payment. |
| `data.reference` / `data.merchant_reference` | The reference of the virtual account that was paid into.                               |
| `data.wiaxy_ref` / `data.transaction_ref`    | The interbank reference for this transaction.                                          |
| `data.amount`                                | The amount received.                                                                   |
| `data.created_at`                            | When the payment was received.                                                         |
| `data.account`                               | The virtual account that received the funds (number, name, bank).                      |
| `data.payer`                                 | The sender's account number and name.                                                  |

## Responding to a webhook

Reply with an HTTP **`200`** as soon as you have received the event, and return this JSON body to acknowledge it:

```json theme={null}
{
  "status": true,
  "message": "successful"
}
```

Any non-`200` response is treated as a failed delivery, and BillStack retries it.

<Tip>
  Acknowledge with `200` first, then do your processing (fulfilling the order, updating your records) afterwards. Keeping the handler fast avoids timeouts that look like failed deliveries.
</Tip>

<Note>
  Each event you accept with a `200` is recorded as delivered. Verifying that an event genuinely came from BillStack is covered on the next page, [Webhook Security](/webhooks/security).
</Note>
