> For the complete documentation index, see [llms.txt](https://developers.coincircuit.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developers.coincircuit.io/webhooks/readme/payments.md).

# Payments

Payment session webhook events and example payloads.

Payment webhooks track the lifecycle of a payment session.

Use these events to update order state, trigger fulfillment, or handle failed payments.

### Field descriptions

Payment webhook events use `data.session`.

| Field                                           | Type                       | Description                                                                                                                        |
| ----------------------------------------------- | -------------------------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| `data.session.id`                               | `string`                   | Unique session identifier.                                                                                                         |
| `data.session.reference`                        | `string`                   | Your order or payment reference.                                                                                                   |
| `data.session.title`                            | `string`                   | Session title.                                                                                                                     |
| `data.session.description`                      | `string \| null`           | Optional session description.                                                                                                      |
| `data.session.state`                            | `'open' \| 'closed'`       | `open` while the session can still take payment, `closed` once it is final.                                                        |
| `data.session.type`                             | `string`                   | Session type. Always `payment`.                                                                                                    |
| `data.session.amount`                           | `string`                   | Requested amount, as a decimal string.                                                                                             |
| `data.session.amountPaid`                       | `string \| null`           | Fiat amount the customer paid in the requested currency, not counting any gas fee the customer paid. Null until a payment arrives. |
| `data.session.currency`                         | `string`                   | Requested currency, such as `USD` or `NGN`.                                                                                        |
| `data.session.settlements`                      | `object \| null`           | Settlement breakdown. Null until the session settles.                                                                              |
| `data.session.settlements.currency`             | `string`                   | Currency of every settlement amount.                                                                                               |
| `data.session.settlements.gross.amount`         | `string`                   | Amount received before fees.                                                                                                       |
| `data.session.settlements.gross.conversionRate` | `string`                   | Rate used to convert the crypto received.                                                                                          |
| `data.session.settlements.fees`                 | `object \| null`           | Fee breakdown. Null when no fees were charged.                                                                                     |
| `data.session.settlements.fees.processing`      | `object \| null`           | Processing fee, with `amount` and `paidBy`.                                                                                        |
| `data.session.settlements.fees.gas`             | `object \| null`           | Network fee, with `amount` and `paidBy`.                                                                                           |
| `data.session.settlements.net.amount`           | `string`                   | Amount credited to your balance.                                                                                                   |
| `data.session.payment`                          | `object \| null`           | Crypto payment details.                                                                                                            |
| `data.session.payment.status`                   | `string`                   | Payment status. See each event below.                                                                                              |
| `data.session.payment.asset`                    | `string`                   | Crypto asset, such as `USDT`.                                                                                                      |
| `data.session.payment.chain`                    | `string`                   | Blockchain network, such as `ethereum`.                                                                                            |
| `data.session.payment.amount`                   | `string`                   | Crypto amount required.                                                                                                            |
| `data.session.payment.amountReceived`           | `string`                   | Crypto amount received so far.                                                                                                     |
| `data.session.payment.conversionRate`           | `string`                   | Rate used to convert the requested amount to crypto.                                                                               |
| `data.session.payment.gasFee`                   | `string`                   | Network fee for the payment.                                                                                                       |
| `data.session.payment.address`                  | `string`                   | Deposit address the customer pays to.                                                                                              |
| `data.session.payment.feePaidBy`                | `'merchant' \| 'customer'` | Who pays the network fee.                                                                                                          |
| `data.session.customer`                         | `object`                   | Customer details: `id`, `email`, `phone`, `firstName`, `lastName`, and `metadata`.                                                 |
| `data.session.metadata`                         | `object \| null`           | Your custom key-value data.                                                                                                        |
| `data.session.successUrl`                       | `string`                   | Where the customer is sent after paying.                                                                                           |
| `data.session.cancelUrl`                        | `string`                   | Where the customer is sent after cancelling.                                                                                       |
| `data.session.createdAt`                        | `string`                   | When the session was created (ISO 8601).                                                                                           |
| `data.session.expiresAt`                        | `string`                   | When the session expires (ISO 8601).                                                                                               |
| `data.session.completedAt`                      | `string \| null`           | When the session completed. Null until then.                                                                                       |
| `data.failureReason`                            | `string`                   | Why the session was rejected. Sent only with `payment.failed`.                                                                     |

### Events

* `payment.completed`
* `payment.partial`
* `payment.expired`
* `payment.underpaid`
* `payment.failed`

### `payment.completed`

Sent when a payment session receives the full amount.

Use this event to mark the order as paid.

{% hint style="success" %}
This event is sent only when the full required amount is received. `data.session.payment.status` is `completed`.
{% endhint %}

```json
{
  "event": "payment.completed",
  "data": {
    "session": {
      "id": "cs_123456789_abcdef",
      "reference": "ORDER-2024-001",
      "title": "Order #2024-001",
      "description": "Payment for premium subscription",
      "state": "closed",
      "type": "payment",
      "amount": "100.00",
      "amountPaid": "100.00",
      "currency": "USD",
      "settlements": {
        "currency": "NGN",
        "gross": {
          "amount": "150000.00",
          "conversionRate": "1500.00"
        },
        "fees": {
          "processing": {
            "amount": "1500.00",
            "paidBy": "merchant"
          },
          "gas": {
            "amount": "75.00",
            "paidBy": "customer"
          }
        },
        "net": {
          "amount": "148425.00"
        }
      },
      "payment": {
        "status": "completed",
        "asset": "USDT",
        "chain": "ethereum",
        "amount": "100.55",
        "amountReceived": "100.55",
        "conversionRate": "1.0055",
        "gasFee": "0.05",
        "address": "0x1234567890abcdef1234567890abcdef12345678",
        "feePaidBy": "customer"
      },
      "cancelUrl": "https://example.com/cancel",
      "successUrl": "https://example.com/success",
      "customer": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "email": "customer@example.com",
        "phone": "+2348123456789",
        "firstName": "John",
        "lastName": "Doe",
        "metadata": {
          "userId": "usr_8f21c3"
        }
      },
      "metadata": {
        "orderId": "ORDER-2024-001",
        "userId": "user_123"
      },
      "createdAt": "2024-01-15T10:30:00.000Z",
      "expiresAt": "2024-01-15T11:30:00.000Z",
      "completedAt": "2024-01-15T10:35:00.000Z"
    }
  }
}
```

### `payment.partial`

Sent when a payment session receives less than the required amount and is still open, so it can take more payments.

Use this event to tell the customer what is left to pay, or to keep the order on hold.

{% hint style="warning" %}
Compare `data.session.payment.amountReceived` with `data.session.payment.amount` to work out the remaining amount due. `data.session.payment.status` is `partial`.
{% endhint %}

```json
{
  "event": "payment.partial",
  "data": {
    "session": {
      "id": "cs_123456789_abcdef",
      "reference": "ORDER-2024-001",
      "title": "Order #2024-001",
      "description": "Payment for premium subscription",
      "state": "open",
      "type": "payment",
      "amount": "100.00",
      "amountPaid": "49.98",
      "currency": "USD",
      "settlements": null,
      "payment": {
        "status": "partial",
        "asset": "USDT",
        "chain": "ethereum",
        "amount": "100.55",
        "amountReceived": "50.25",
        "conversionRate": "1.0055",
        "gasFee": "0.05",
        "address": "0x1234567890abcdef1234567890abcdef12345678",
        "feePaidBy": "customer"
      },
      "cancelUrl": "https://example.com/cancel",
      "successUrl": "https://example.com/success",
      "customer": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "email": "customer@example.com",
        "phone": "+2348123456789",
        "firstName": "John",
        "lastName": "Doe",
        "metadata": {
          "userId": "usr_8f21c3"
        }
      },
      "metadata": {
        "orderId": "ORDER-2024-001",
        "userId": "user_123"
      },
      "createdAt": "2024-01-15T10:30:00.000Z",
      "expiresAt": "2024-01-15T11:30:00.000Z",
      "completedAt": null
    }
  }
}
```

### `payment.expired`

Sent when a payment session closes with no payment received.

Use this event to expire checkout state. `data.session.payment.status` is `expired`.

```json
{
  "event": "payment.expired",
  "data": {
    "session": {
      "id": "cs_123456789_abcdef",
      "reference": "ORDER-2024-001",
      "title": "Order #2024-001",
      "description": "Payment for premium subscription",
      "state": "closed",
      "type": "payment",
      "amount": "100.00",
      "amountPaid": null,
      "currency": "USD",
      "settlements": null,
      "payment": {
        "status": "expired",
        "asset": "USDT",
        "chain": "ethereum",
        "amount": "100.55",
        "amountReceived": "0",
        "conversionRate": "1.0055",
        "gasFee": "0.05",
        "address": "0x1234567890abcdef1234567890abcdef12345678",
        "feePaidBy": "customer"
      },
      "cancelUrl": "https://example.com/cancel",
      "successUrl": "https://example.com/success",
      "customer": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "email": "customer@example.com",
        "phone": "+2348123456789",
        "firstName": "John",
        "lastName": "Doe",
        "metadata": {
          "userId": "usr_8f21c3"
        }
      },
      "metadata": {
        "orderId": "ORDER-2024-001",
        "userId": "user_123"
      },
      "createdAt": "2024-01-15T10:30:00.000Z",
      "expiresAt": "2024-01-15T11:30:00.000Z",
      "completedAt": null
    }
  }
}
```

### `payment.underpaid`

Sent when a payment session closes with less than the required amount.

Use this event when the session is final but still short. `data.session.payment.status` is `partial`.

{% hint style="warning" %}
Check `data.session.payment.amountReceived` for the crypto amount received before the session closed.
{% endhint %}

```json
{
  "event": "payment.underpaid",
  "data": {
    "session": {
      "id": "cs_123456789_abcdef",
      "reference": "ORDER-2024-001",
      "title": "Order #2024-001",
      "description": "Payment for premium subscription",
      "state": "closed",
      "type": "payment",
      "amount": "100.00",
      "amountPaid": "39.78",
      "currency": "USD",
      "settlements": null,
      "payment": {
        "status": "partial",
        "asset": "USDT",
        "chain": "ethereum",
        "amount": "100.55",
        "amountReceived": "40.00",
        "conversionRate": "1.0055",
        "gasFee": "0.05",
        "address": "0x1234567890abcdef1234567890abcdef12345678",
        "feePaidBy": "customer"
      },
      "cancelUrl": "https://example.com/cancel",
      "successUrl": "https://example.com/success",
      "customer": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "email": "customer@example.com",
        "phone": "+2348123456789",
        "firstName": "John",
        "lastName": "Doe",
        "metadata": {
          "userId": "usr_8f21c3"
        }
      },
      "metadata": {
        "orderId": "ORDER-2024-001",
        "userId": "user_123"
      },
      "createdAt": "2024-01-15T10:30:00.000Z",
      "expiresAt": "2024-01-15T11:30:00.000Z",
      "completedAt": null
    }
  }
}
```

### `payment.failed`

Sent when a payment session is rejected by a compliance check.

Use this event to stop fulfillment and surface the failure. `data.session.payment.status` is `failed`.

{% hint style="danger" %}
Check `data.failureReason` for why the session was rejected.
{% endhint %}

```json
{
  "event": "payment.failed",
  "data": {
    "session": {
      "id": "cs_123456789_abcdef",
      "reference": "ORDER-2024-001",
      "title": "Order #2024-001",
      "description": "Payment for premium subscription",
      "state": "closed",
      "type": "payment",
      "amount": "100.00",
      "amountPaid": "100.00",
      "currency": "USD",
      "settlements": null,
      "payment": {
        "status": "failed",
        "asset": "USDT",
        "chain": "ethereum",
        "amount": "100.55",
        "amountReceived": "100.55",
        "conversionRate": "1.0055",
        "gasFee": "0.05",
        "address": "0x1234567890abcdef1234567890abcdef12345678",
        "feePaidBy": "customer"
      },
      "cancelUrl": "https://example.com/cancel",
      "successUrl": "https://example.com/success",
      "customer": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "email": "customer@example.com",
        "phone": "+2348123456789",
        "firstName": "John",
        "lastName": "Doe",
        "metadata": {
          "userId": "usr_8f21c3"
        }
      },
      "metadata": {
        "orderId": "ORDER-2024-001",
        "userId": "user_123"
      },
      "createdAt": "2024-01-15T10:30:00.000Z",
      "expiresAt": "2024-01-15T11:30:00.000Z",
      "completedAt": null
    },
    "failureReason": "Session contained flagged transactions"
  }
}
```
