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

# Payment

When a payment event occurs, the platform sends an HTTP `POST` request to your configured callback URL. Each request contains an `event` field identifying the notification type.

<Note>
  If your API token has a passphrase configured, every request includes a `Pesahub-Signature` header — an HMAC over the raw payload. See [Verify a Checksum](https://docs.pesahub.co/webhooks-and-checksum) for validation steps.
</Note>

## Events

| Event              | Description                                          |
| ------------------ | ---------------------------------------------------- |
| `payment.received` | Payment has been successfully completed and settled. |
| `payment.failed`   | Payment could not be completed.                      |

## Payload Fields

<ResponseField name="event" type="string" required>
  The event type. One of `payment.received` or `payment.failed`.
</ResponseField>

<ResponseField name="transaction_id" type="string" required>
  Unique identifier for the transaction.
</ResponseField>

<ResponseField name="transaction_mode" type="string" required>
  The payment method used, e.g. `ussd`.
</ResponseField>

<ResponseField name="transaction_currency" type="string" required>
  ISO currency code, e.g. `TZS`.
</ResponseField>

<ResponseField name="channel" type="object" required>
  <Expandable title="properties">
    <ResponseField name="name" type="string">
      Channel name, e.g. `AIRTEL-MONEY`, `TIGO-PESA`.
    </ResponseField>

    <ResponseField name="reference" type="string | null">
      Channel-level transaction reference. `null` if the transaction did not reach the channel.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="amount" type="object" required>
  <Expandable title="properties">
    <ResponseField name="value" type="string">
      Gross payment amount, e.g. `1,000.00`. Always present.
    </ResponseField>

    <ResponseField name="fee" type="string">
      Platform fee deducted. Only present on `payment.received`.
    </ResponseField>

    <ResponseField name="settled" type="string">
      Net amount settled to your account (`value` minus `fee`). Only present on `payment.received`.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="customer" type="object" required>
  <Expandable title="properties">
    <ResponseField name="phone_number" type="string">
      Customer's phone number.
    </ResponseField>

    <ResponseField name="full_name" type="string | null">
      Customer's full name as returned by the channel. May be `null` if the channel did not provide it.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="metadata" type="object">
  Arbitrary key-value pairs provided at payment creation, echoed back as-is. Use these to correlate events with records in your system.
</ResponseField>

<ResponseField name="failure_reason" type="string">
  Human-readable reason for the failure. Only present on `payment.failed`.
</ResponseField>

<ResponseField name="created_at" type="string" required>
  ISO 8601 UTC timestamp of when the payment was created.
</ResponseField>

<ResponseField name="updated_at" type="string" required>
  ISO 8601 UTC timestamp of the last status update.
</ResponseField>

<ResponseField name="timestamp" type="string" required>
  ISO 8601 UTC timestamp of when this webhook was dispatched.
</ResponseField>

## Example Payloads

<Tabs>
  <Tab title="payment.received">
    ```json theme={null}
    {
      "event": "payment.received",
      "amount": {
        "fee": "10.00",
        "value": "1,000.00",
        "settled": "990.00"
      },
      "channel": {
        "name": "AIRTEL-MONEY",
        "reference": "MP260712.1803.R20406"
      },
      "customer": {
        "full_name": "JOHN DOE",
        "phone_number": "255682123456"
      },
      "metadata": {
        "order_id": "128128",
        "customer_note": "Test payment"
      },
      "transaction_id": "70ea1299-72f4-43c7-b65f-84d10af8547c",
      "transaction_mode": "ussd",
      "transaction_currency": "TZS",
      "timestamp": "2026-07-12T15:07:28.653212Z",
      "created_at": "2026-07-12T15:03:07.000000Z",
      "updated_at": "2026-07-12T15:07:28.000000Z"
    }
    ```
  </Tab>

  <Tab title="payment.failed">
    ```json theme={null}
    {
      "event": "payment.failed",
      "amount": {
        "value": "1,000.00"
      },
      "channel": {
        "name": "TIGO-PESA",
        "reference": null
      },
      "customer": {
        "full_name": null,
        "phone_number": "255682123456"
      },
      "metadata": {
        "order_id": "128128",
        "customer_note": "Test payment"
      },
      "failure_reason": "Transaction timedout",
      "transaction_id": "fc6f023d-7cd1-4eb7-be83-ada32691a6c9",
      "transaction_mode": "ussd",
      "transaction_currency": "TZS",
      "timestamp": "2026-07-12T15:06:59.272837Z",
      "created_at": "2026-07-12T15:01:54.000000Z",
      "updated_at": "2026-07-12T15:06:59.000000Z"
    }
    ```
  </Tab>
</Tabs>
