> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.stakaba.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.stakaba.com/_mcp/server.

# Webhooks

Stakaba sends a POST request to your server when a payment reaches a final state. This is how you reliably confirm payments — do not rely solely on the customer returning to your page.

## Configure your webhook URL

Set your webhook URL when creating a payment in `metadata`, or configure a global URL in the dashboard under **Settings → Webhooks**.

## Webhook payload

```json
{
  "event": "transaction.success",
  "internalReference": "M_X7Y8Z9W0",
  "status": "SUCCESS",
  "type": "COLLECTION",
  "grossAmount": 5000,
  "stakabaFee": 125,
  "netAmount": 4875,
  "currency": "TZS",
  "mobileNumber": "255742000331",
  "network": "Mpesa",
  "providerReference": "MPESA12345",
  "createdAt": "2026-06-05T14:22:00Z",
  "metadata": {
    "orderId": "ORD-2026-001"
  }
}
```

## Event types

| Event                 | When                                 |
| --------------------- | ------------------------------------ |
| `transaction.success` | Payment confirmed and funds received |
| `transaction.failed`  | Payment failed — nothing was charged |

## Responding to webhooks

Return HTTP **200** to acknowledge receipt. If Stakaba doesn't get a 200, it retries up to 5 times with exponential backoff.

```http
HTTP/1.1 200 OK
```

## Verify it's from Stakaba

Check that the `internalReference` matches one you created and that the amount matches your records. Always verify the transaction status from the API before fulfilling an order:

```http
GET /api/v1/transactions/{internalReference}
x-api-key: sk_live_...
```

> **Warning**
>
> Never fulfil an order based on the webhook alone. Always verify via the API to prevent replay attacks.

## Test webhooks

Use your sandbox key to trigger test payments. Stakaba sends webhooks for sandbox transactions to your configured URL, letting you test your handler end-to-end.