# Payments

> Accept one-time crypto payments online.

Section: Accepting Payments
Source: https://coincircuit.io/docs/guides/checkout-sessions/
Interactive version: https://coincircuit.io/api-reference?tab=guides&guide=checkout-sessions

## API reference

- POST `/api/v1/payments`: [Create a payment](https://coincircuit.io/api-reference/#tag/payments/POST/api/v1/payments)
- GET `/api/v1/payments/reference/{reference}`: [Retrieve a payment](https://coincircuit.io/api-reference/#tag/payments/GET/api/v1/payments/reference/{reference})
- GET `/api/v1/payments`: [List payments](https://coincircuit.io/api-reference/#tag/payments/GET/api/v1/payments)

A payment is a single charge for a set amount. You create it in fiat, and CoinCircuit prices it in the crypto your customer picks, locks the rate, and collects the funds. The customer pays in any supported asset, CoinCircuit confirms it on the blockchain, and your server gets a webhook the moment it clears so you can fulfil the order.

![CoinCircuit hosted checkout page](https://coincircuit.io/images/features/checkout-sessions.webp)

## How it works
1. Create a payment session with `POST /api/v1/payments`.
2. Redirect the customer to the checkout page.
3. Wait for a payment webhook event.
4. Verify the payment status.
5. Fulfil the order.

## Request fields
| Field | Type | Required | Description |
| :--- | :--- | :--- | :--- |
| `title` | string | Yes | Title shown on the checkout page. |
| `description` | string | Yes | Description of what the payment is for. |
| `amount` | string | Yes | Fiat amount as a string, e.g. `"10000.00"`. |
| `currency` | string | Yes | `NGN` or `USD`. |
| `customer` | object | Yes | `email` is required. `firstName`, `lastName`, and `phone` are optional. |
| `asset` | string | No | Cryptocurrency to accept: `BTC`, `ETH`, `USDT`, `USDC`, `SOL`, `BNB`, or `TRX`. Omit to let the customer choose. |
| `chain` | string | No | Network to accept it on: `bitcoin`, `ethereum`, `solana`, `bsc`, `tron`, `base`, or `arbitrum`. |
| `successUrl` / `cancelUrl` | string | No | HTTPS redirect URLs after payment or cancellation. |
| `webhookUrl` | string | No | HTTPS URL that receives webhook events for this session. |
| `feePaidBy` | string | No | Who pays the network fee: `customer` or `merchant`. Defaults to your dashboard setting. |
| `metadata` | object | No | Key-value data stored on the session and returned in webhooks. |

You can also create a one-off payment from the dashboard:

![Creating a payment from the dashboard](https://coincircuit.io/images/features/checkout-create.webp)

Each session has a detail view with its status, reference, payment link, and transactions:

![Payment details](https://coincircuit.io/images/features/checkout-details.webp)

## Webhook events
| Event | Description |
| :--- | :--- |
| `transaction.received` | Transaction has been detected. |
| `transaction.confirmed` | Transaction has been confirmed on the blockchain. |
| `payment.completed` | Payment completed successfully. |
| `payment.partial` | Partial payment received. |
| `payment.underpaid` | Payment amount was insufficient. |
| `payment.expired` | Payment session expired. |

## Use cases
- E-commerce and digital product checkout
- Pay-per-use billing and top-ups
- Single payments with a known amount

> Store your internal order ID in `metadata` to receive it in webhook events.
