@bitpal/mcp 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/dist/stdio.js +33 -10
  2. package/package.json +1 -1
package/dist/stdio.js CHANGED
@@ -4067,7 +4067,7 @@ var docs_data_default = {
4067
4067
  title: "API reference",
4068
4068
  url: "https://bitpal.io/docs/#api",
4069
4069
  markdownUrl: "https://bitpal.io/docs/md/api.md",
4070
- markdown: '# API reference\n\nEvery public endpoint, generated from the OpenAPI 3.1.0 spec (version 1.0.0). Download it: [openapi.json](/docs/openapi.json).\n\n## Basics\n\n| Topic | Details |\n| --- | --- |\n| Base URL | `https://api.bitpal.io` \u2014 test and live share the host; the API key prefix selects the mode. |\n| Auth | `Authorization: Bearer bp_test_\u2026` (test) or `bp_live_\u2026` (live). Keep keys on your server. |\n| Format | JSON. Success: `{ "data": \u2026 }` (authenticated endpoints add `meta: { mode, requestId }`). Amounts are strings. |\n| Errors | `{ "error", "code", "retryable", "trace_id", "details"? }` \u2014 `error` is the human-readable message; branch on `code`. See [Errors](/docs/md/errors.md). |\n| Idempotency | `Idempotency-Key` (8\u2013128 chars) is honoured on every authenticated merchant `POST`; endpoints that do not enforce it say so. |\n\n## Checkout sessions\n\nCreate a session per order, send the buyer to the hosted page (or build your own UI), and track it.\n\n### `POST /v1/checkout/sessions` \u2014 Create a checkout session\n\nCreates a session for one order and returns the hosted `checkout_url`. Line items take either `amount` (plain decimal string, e.g. "29") or `amount_atomic` (6-decimal integer string), or reference a `price_id`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateCheckoutSessionRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `line_items` | array of (object \\| any \\| any) | Yes | Raw items (`name`, `currency`, `amount` XOR `amount_atomic`) or price items (`price_id`). Do not mix the two kinds. (\u2265 1 items) |\n| `currency` | string | No | Session currency. Defaults to the line items\u2019 currency. (\u2265 1 chars) |\n| `success_url` | string (uri) | No | Where the buyer returns after paying. `{CHECKOUT_SESSION_ID}` is replaced with the session id. (\u2264 2048 chars) |\n| `cancel_url` | string (uri) | No | Where the buyer goes when cancelling. (\u2264 2048 chars) |\n| `customer_email` | string (email) | No | Buyer email for the receipt. |\n| `metadata` | map | No | Your key/value data, echoed back on the session. |\n| `expires_in_minutes` | integer | No | Payment window in minutes (1\u201360). Default 15. (1\u201360, default `15`) |\n| `tolerance_percent` | string | No | Deprecated. Underpayments are never accepted \u2014 a short payment becomes `unresolved_underpaid` and can be topped up to the same address. Only `"0"` is accepted; any other value returns 400. |\n| `pay_chain` | string | No | Fix the payment network: CAIP-2 (`eip155:84532`) or a short name (`base`), which resolves to the testnet in test mode and the mainnet in live mode. Mutually exclusive with `allowed_pay_chains`. |\n| `allowed_pay_chains` | array of string | No | Networks the buyer may choose from (CAIP-2 or short names, resolved like `pay_chain`). (1\u20138 items) |\n| `allowed_assets` | array of object | No | Allowed (chain, token) cells. Takes precedence over `allowed_pay_chains`. (1\u201316 items) |\n\n```\n{\n "line_items": [\n {\n "name": "Pro plan",\n "amount": "29",\n "currency": "USDC"\n }\n ],\n "pay_chain": "eip155:84532",\n "expires_in_minutes": 30,\n "success_url": "https://your.store/thanks?session={CHECKOUT_SESSION_ID}"\n}\n```\n\n**Response `201`** \u2014 Session created.\n\n```\n{\n "data": {\n "id": "cs_Q2FxKhomCEju_OqvKfrQsTOh",\n "checkout_url": "https://bitpal.io/pay/cs_Q2FxKhomCEju_OqvKfrQsTOh?token=<session_token>",\n "session_token": "<session_token>",\n "status": "created",\n "amount_total": "29000000",\n "currency": "USDC",\n "expires_at": "2026-11-06T07:58:28.776Z",\n "tax": {\n "tax_amount": "0",\n "total_with_tax": "29000000"\n }\n },\n "meta": {\n "mode": "TEST",\n "requestId": "ec091faf-\u2026"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \xB7 `422` \xB7 `429` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions` \u2014 List checkout sessions\n\nNewest first, in the API key\u2019s mode (test/live).\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | string | No | Filter by status, or `succeeded` for all successful states. |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Sessions.\n\n```\n{\n "data": [\n {\n "id": "string",\n "status": "string",\n "mode": "TEST",\n "amount_total": "1000000",\n "amount_received": "string",\n "currency": "string",\n "pay_chain": "string",\n "pay_asset": "string",\n "token_decimals": 0,\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "deposit_address": "string",\n "refund_address": "string",\n "received_token": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "fee_amount_token": "string",\n "net_amount_token": "string",\n "tx_hash": "string",\n "deposit_tx_hash": "string",\n "sweep_tx_hash": "string",\n "success_url": "string",\n "cancel_url": "string",\n "metadata": {},\n "payment_source": "string",\n "payment_link_id": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "raw_status": "string"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}` \u2014 Retrieve a checkout session\n\nServer-side source of truth for an order, together with webhooks.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 The session.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "mode": "TEST",\n "amount_total": "1000000",\n "amount_received": "string",\n "currency": "string",\n "pay_chain": "string",\n "pay_asset": "string",\n "token_decimals": 0,\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "deposit_address": "string",\n "refund_address": "string",\n "received_token": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "fee_amount_token": "string",\n "net_amount_token": "string",\n "tx_hash": "string",\n "deposit_tx_hash": "string",\n "sweep_tx_hash": "string",\n "success_url": "string",\n "cancel_url": "string",\n "metadata": {},\n "payment_source": "string",\n "payment_link_id": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "id": "string",\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0,\n "price_id": "string",\n "product_id": "string",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/status` \u2014 Get session status\n\nLightweight status for polling from your server. Requires your API key (N13 \u2014 it is not a public endpoint). Buyer-facing pages should use `GET /v1/checkout/sessions/{id}/public`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Status.\n\n```\n{\n "data": {\n "status": "awaiting_deposit",\n "paid_at": null\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/public` \u2014 Get the public session view\n\nBuyer-facing view used by the checkout page: payment options, deposit address once issued, refunds. No authentication; CORS-open.\n\n**Auth:** None \u2014 public endpoint\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Public view.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "token_decimals": 0,\n "pay_amount": "string",\n "mode": "TEST",\n "chain_id": 0,\n "token_address": "string",\n "payment_options": [\n {\n "caip2": "string",\n "chain_id": 0,\n "token_symbol": "string",\n "token_address": "string",\n "decimals": 0,\n "amount_atomic": "string"\n }\n ],\n "currency": "string",\n "amount_total": "1000000",\n "amount_received": "string",\n "chain": "string",\n "tx_hash": "string",\n "release_tx_hash": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "success_url": "string",\n "cancel_url": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "tax_amount": null,\n "tax_rate": null,\n "pay_chain": "string",\n "pay_asset": "string",\n "deposit_address": "string",\n "payment_deadline_at": "2026-11-06T07:00:00.000Z",\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0\n }\n ],\n "payment_source": "string",\n "refunds": [\n {\n "kind": "string",\n "amount": "string",\n "token_symbol": "string",\n "decimals": 0,\n "tx_hash": "string",\n "caip2": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/checkout/sessions/{id}/deposit-address` \u2014 Issue the deposit address\n\nFixes the buyer\u2019s network, token and refund address, and returns the one-time deposit address with the exact amount. Calling again returns the same address and keeps the first refund address. Requires the session token (header `X-Session-Token` or body `session_token`).\n\n**Auth:** Session token \u2014 `X-Session-Token` header or `session_token` body field (no API key)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n| `Idempotency-Key` | header | string | No | Accepted but not yet enforced on this endpoint \u2014 retries are not de-duplicated by key. (8\u2013128 chars) |\n| `X-Session-Token` | header | string | No | Session token from the create-session response. Alternative to the `session_token` body field. |\n\n**Request body** (`IssueDepositAddressRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `session_token` | string | No | From the create-session response. May be sent as the `X-Session-Token` header instead. |\n| `refundAddress` | string | Yes | Buyer refund address in the chosen network\u2019s format (EVM 0x\u2026, Tron T\u2026, Solana base58). Cannot change later. |\n| `chain` | string | No | CAIP-2 or short name of the chosen network. Required for multi-option sessions. (\u2265 1 chars) |\n| `token` | string | No | Token symbol of the chosen asset, e.g. USDC. Required for multi-option sessions. (\u2265 1 chars) |\n\n```\n{\n "session_token": "<session_token>",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "chain": "eip155:84532",\n "token": "USDC"\n}\n```\n\n**Response `200`** \u2014 Deposit address.\n\n```\n{\n "data": {\n "sessionId": "cs_\u2026",\n "chain": "eip155:84532",\n "depositAddress": "0x6b19e871c934aB52775B6712e110f3e4b0626347",\n "expectedToken": "0x943b94dacf1507f2658f1cfe103ac36ebc13ef65",\n "expectedAmount": "29000000",\n "feeAmount": "435000",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "deadline": "1793951938",\n "expiresAt": "2026-11-06T07:58:28.776Z"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \xB7 `410` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/refunds` \u2014 List automatic refunds for a session\n\nOn-chain refunds BitPal made for this session (overpayment, expired underpayment, wrong token, late deposit).\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Refunds.\n\n```\n{\n "data": [\n {\n "id": "string",\n "kind": "string",\n "token": "string",\n "token_symbol": "string",\n "amount": "string",\n "amount_display": "string",\n "decimals": 0,\n "refund_address": "string",\n "tx_hash": "string",\n "caip2": "string",\n "block_number": "string",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/fee-preview` \u2014 Preview the fee for an amount\n\nPass exactly one of `amount` or `amount_atomic`. The response is always atomic.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `amount` | query | string | No | Decimal string, e.g. "100". |\n| `amount_atomic` | query | string | No | 6-decimal integer string, e.g. "100000000". |\n\n**Response `200`** \u2014 Fee breakdown.\n\n```\n{\n "data": {\n "amount": "100000000",\n "fee_rate": "0.015",\n "fee_amount": "1500000",\n "net_amount": "98500000"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n## Products & prices\n\nCatalog objects. Prices are immutable.\n\n### `POST /v1/checkout/products` \u2014 Create a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateProductRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | string | Yes | 1\u2013200 chars |\n| `description` | string | No | \u2264 2000 chars |\n| `image_url` | string (uri) | No | \u2264 2048 chars |\n| `metadata` | map | No | |\n\n```\n{\n "name": "Pro plan"\n}\n```\n\n**Response `201`** \u2014 Product created.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products` \u2014 List products\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | "active" \\| "inactive" | No | |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Products.\n\n```\n{\n "data": [\n {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products/{id}` \u2014 Retrieve a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n\n**Response `200`** \u2014 The product.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/products/{id}` \u2014 Update a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n\n**Request body** (`UpdateProductRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | string | No | 1\u2013200 chars |\n| `description` | string \\| null | No | \u2264 2000 chars |\n| `image_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `metadata` | map | No | |\n| `status` | "active" \\| "inactive" | No | |\n\n**Response `200`** \u2014 The updated product.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/checkout/products/{id}/prices` \u2014 Create a price\n\nPrices are immutable: to change an amount, create a new price. Pass exactly one of `amount` (decimal string) or `amount_atomic` (6-decimal integer string). The currency is derived from `token_symbol`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreatePriceRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `amount` | string | No | Decimal string, e.g. "29". Mutually exclusive with `amount_atomic`. |\n| `amount_atomic` | string | No | 6-decimal integer string ("29000000" = 29). |\n| `token_symbol` | "USDC" \\| "USDT" \\| "JPYC" | No | The price\u2019s asset. The currency is derived from it. (default `"USDC"`) |\n| `billing_type` | "one_time" | No | Only `one_time` for now. (default `"one_time"`) |\n| `nickname` | string | No | Display name. (\u2264 200 chars) |\n| `lookup_key` | string | No | Your own stable key for this price. (1\u2013200 chars) |\n\n```\n{\n "amount": "29",\n "token_symbol": "USDC"\n}\n```\n\n**Response `201`** \u2014 Price created.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products/{id}/prices` \u2014 List a product\u2019s prices\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Prices.\n\n```\n{\n "data": [\n {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/prices/{id}` \u2014 Retrieve a price\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Price id (`price_\u2026`). |\n\n**Response `200`** \u2014 The price.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/prices/{id}` \u2014 Update a price\u2019s nickname\n\nOnly `nickname` can change. Sending an amount/currency field returns `PRICE_IMMUTABLE_FIELD`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Price id (`price_\u2026`). |\n\n**Request body** (`UpdatePriceRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `nickname` | string \\| null | No | \u2264 200 chars |\n\n**Response `200`** \u2014 The updated price.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n## Payment links\n\nShareable hosted URLs for a price.\n\n### `POST /v1/checkout/payment-links` \u2014 Create a payment link\n\nA shareable hosted URL for one price. The link \u2194 price binding is fixed after creation.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreatePaymentLinkRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `price_id` | string | Yes | The price this link sells (`price_\u2026`). |\n| `title` | string | No | 1\u2013200 chars |\n| `description` | string | No | \u2264 2000 chars |\n| `collect_email` | boolean | No | Ask the buyer for an email. Default true. (default `true`) |\n| `email_required` | boolean | No | Require the email: the hosted link page asks for it and no checkout is created without it. Default true; needs `collect_email`. (default `true`) |\n| `allowed_pay_chains` | array of string | No | Networks the buyer may choose from (CAIP-2 or short names). (1\u20138 items) |\n| `allowed_assets` | array of object | No | Allowed (chain, token) cells. Takes precedence over `allowed_pay_chains`. (1\u201316 items) |\n| `success_url` | string (uri) | No | \u2264 2048 chars |\n| `cancel_url` | string (uri) | No | \u2264 2048 chars |\n| `max_uses` | integer | No | Stop accepting payments after this many paid uses. (\u2265 1) |\n| `expires_at` | string (date-time) | No | ISO-8601 time after which the link stops working. |\n| `metadata` | map | No | |\n\n```\n{\n "price_id": "price_\u2026",\n "allowed_pay_chains": [\n "eip155:8453"\n ]\n}\n```\n\n**Response `201`** \u2014 Link created.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/payment-links` \u2014 List payment links\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | "active" \\| "inactive" | No | |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Links.\n\n```\n{\n "data": [\n {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/payment-links/{id}` \u2014 Retrieve a payment link\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment link id (`plink_\u2026`). |\n\n**Response `200`** \u2014 The link, with product/price summary fields.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/payment-links/{id}` \u2014 Update a payment link\n\nOperational settings and active \u2194 inactive. The price cannot change \u2014 create a new link instead.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment link id (`plink_\u2026`). |\n\n**Request body** (`UpdatePaymentLinkRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `title` | string \\| null | No | 1\u2013200 chars |\n| `description` | string \\| null | No | \u2264 2000 chars |\n| `collect_email` | boolean | No | |\n| `email_required` | boolean | No | |\n| `allowed_pay_chains` | array of string \\| null | No | 1\u20138 items |\n| `allowed_assets` | array of object \\| null | No | 1\u201316 items |\n| `success_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `cancel_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `status` | "active" \\| "inactive" | No | |\n| `max_uses` | integer \\| null | No | \u2265 1 |\n| `expires_at` | string (date-time) \\| null | No | |\n| `metadata` | map | No | |\n\n**Response `200`** \u2014 The updated link.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n## x402\n\nCharge per API call with HTTP 402 and EIP-3009 authorizations.\n\n### `GET /v1/x402/assets` \u2014 List x402 assets for this mode\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Response `200`** \u2014 Assets.\n\n```\n{\n "data": {\n "mode": "TEST",\n "assets": [\n {\n "caip2": "string",\n "network": "string",\n "chain_name": "string",\n "symbol": "string",\n "decimals": 0,\n "address": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/requirements` \u2014 Build the 402 payment requirements\n\nReturns the body your resource server sends with `402 Payment Required`, including the fee split. Pass exactly one of `amount` or `amountAtomic`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402RequirementsRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `network` | string | No | x402 network name (`base`, `base-sepolia`). Defaults to the mode\u2019s first asset. (\u2265 1 chars) |\n| `asset` | string | No | Token symbol. Default USDC. (\u2265 1 chars, default `"USDC"`) |\n| `payTo` | string | Yes | Your payout wallet (0x) \u2014 must be the one registered in Console for this mode, otherwise `PAYTO_NOT_MERCHANT_WALLET`. |\n| `amount` | string | No | Gross amount per call as a decimal string, e.g. "0.1". The fee is taken from it. |\n| `amountAtomic` | string | No | Same as `amount`, as a 6-decimal integer string. |\n| `resource` | string | Yes | The URL being paid for. (1\u20132048 chars) |\n| `description` | string | No | \u2264 512 chars |\n| `mimeType` | string | No | \u2264 128 chars |\n| `maxTimeoutSeconds` | integer | No | How long the payer has to sign (max 3600). Default 300. (\u2264 3600, > 0) |\n\n```\n{\n "payTo": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",\n "amount": "0.1",\n "resource": "https://api.example.com/report"\n}\n```\n\n**Response `200`** \u2014 402 body.\n\n```\n{\n "data": {\n "x402Version": 1,\n "accepts": [\n {\n "scheme": "exact",\n "network": "string",\n "asset": "string",\n "payTo": "string",\n "maxAmountRequired": "1000000",\n "resource": "string",\n "description": "string",\n "mimeType": "string",\n "maxTimeoutSeconds": 0,\n "extra": {\n "name": "string",\n "version": "string",\n "chainId": 0\n },\n "feeBreakdown": {\n "netAmount": "1000000",\n "feeAmount": "1000000",\n "feeBps": 0,\n "feeRecipient": "string"\n }\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/verify` \u2014 Verify an X-PAYMENT header\n\nChecks the EIP-3009 authorization against the requirements. Sends nothing on-chain.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402PaymentRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `x402Version` | 1 | Yes | |\n| `paymentPayload` | object | Yes | |\n| `paymentRequirements` | object | Yes | |\n\n**Response `200`** \u2014 Valid.\n\n```\n{\n "data": {\n "valid": true,\n "payment_id": "string",\n "status": "string",\n "idempotent": true\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/settle` \u2014 Settle an x402 payment\n\nBroadcasts the transfer and waits for the receipt. Serve the resource only when `status` is `confirmed`. Settlement is idempotent per authorization \u2014 retry with the same body on 5xx.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402PaymentRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `x402Version` | 1 | Yes | |\n| `paymentPayload` | object | Yes | |\n| `paymentRequirements` | object | Yes | |\n\n**Response `200`** \u2014 Settlement result.\n\n```\n{\n "data": {\n "success": true,\n "payment_id": "string",\n "status": "string",\n "tx_hash": "string",\n "fee_tx_hash": "string",\n "network": "string",\n "idempotent": true\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \xB7 `503` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/x402/payments/{id}` \u2014 Retrieve an x402 payment\n\nRecovery path when a settle response was lost \u2014 check here before settling again.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment id. |\n\n**Response `200`** \u2014 The payment.\n\n```\n{\n "data": {\n "id": "string",\n "status": "pending",\n "raw_status": "string",\n "resource": "string",\n "chain": "string",\n "asset": "string",\n "decimals": 0,\n "amount": "1000000",\n "gross_amount": "1000000",\n "payer": "string",\n "pay_to": "string",\n "tx_hash": "string",\n "created_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/x402/payments` \u2014 List x402 payments\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `limit` | query | integer | No | \u2264 100, > 0, default `20` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n| `status` | query | string | No | pending \\| confirmed \\| failed \\| needs_review |\n\n**Response `200`** \u2014 Payments.\n\n```\n{\n "data": [\n {\n "id": "string",\n "status": "pending",\n "raw_status": "string",\n "resource": "string",\n "chain": "string",\n "asset": "string",\n "decimals": 0,\n "amount": "1000000",\n "gross_amount": "1000000",\n "payer": "string",\n "pay_to": "string",\n "tx_hash": "string",\n "created_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n## Webhook endpoints\n\nManage where BitPal delivers signed events.\n\n### `POST /v1/webhooks` \u2014 Create a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. The response carries the `whsec_\u2026` signing secret \u2014 it is shown only once.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | Yes | HTTPS URL that receives events. Private hosts are rejected. |\n| `subscribed_events` | array of string | Yes | Event names to deliver (see the `webhooks` section). (\u2265 1 items) |\n| `retry_policy` | object | No | `max_retries` caps the total delivery attempts (1\u201320, default 10: 3 right away, then 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h). The schedule itself is fixed; `backoff` is ignored. |\n| `dead_letter_destination` | string (uri) \\| null | No | Optional URL for dead-lettered deliveries. |\n\n```\n{\n "endpoint_url": "https://your.store/webhooks/bitpal",\n "subscribed_events": [\n "checkout.session.paid"\n ]\n}\n```\n\n**Response `201`** \u2014 Endpoint created.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/webhooks` \u2014 List webhook endpoints\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Endpoints of the API key\u2019s environment and mode. Note: list items use camelCase keys.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Endpoints, newest first. `meta` carries total/limit/offset.\n\n```\n{\n "data": [\n {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/webhooks/{id}` \u2014 Update a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Setting `status` to `disabled` removes the endpoint and requires `reason_code` (otherwise 400 `REASON_CODE_REQUIRED`). It is recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n\n**Request body** (`UpdateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | No | |\n| `subscribed_events` | array of string | No | |\n| `status` | "active" \\| "paused" \\| "disabled" | No | |\n| `retry_policy` | object | No | |\n| `dead_letter_destination` | string (uri) \\| null | No | |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | No | Required when `status` is `disabled`: one of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n**Response `200`** \u2014 The updated endpoint.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/webhooks/{id}/rotate-secret` \u2014 Rotate the signing secret\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Takes effect immediately. The new secret is returned once \u2014 update your verifier. Requires `reason_code` (400 `REASON_CODE_REQUIRED` if missing); recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`RotateWebhookSecretRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | Yes | One of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n```\n{\n "reason_code": "rotation"\n}\n```\n\n**Response `200`** \u2014 Endpoint with the new secret.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/developers/webhooks/test` \u2014 Send a test event\n\nPosts one signed sample event to an endpoint (no retries). The envelope id is prefixed `test_`, `data.test` is true and the request carries `X-Webhook-Test: true`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`SendTestWebhookRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `webhook_id` | string (uuid) | Yes | Endpoint id. |\n| `event_type` | string | Yes | Event name to put in the envelope, e.g. checkout.session.paid. (1\u2013200 chars) |\n| `payload` | map | No | Custom `data` object. Defaults to a sample message. |\n\n```\n{\n "webhook_id": "00000000-0000-4000-8000-000000000000",\n "event_type": "checkout.session.paid"\n}\n```\n\n**Response `200`** \u2014 Delivery result.\n\n```\n{\n "data": {\n "delivery_id": "00000000-0000-4000-8000-000000000000",\n "webhook_id": "00000000-0000-4000-8000-000000000000",\n "endpoint_url": "string",\n "event_type": "string",\n "http_status": 0,\n "response_body": "string",\n "error": "string",\n "duration_ms": 0,\n "test": true,\n "sent_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n## Webhook events\n\nEnvelope: `{ id, event, created_at, data }`, signed with `X-Webhook-Signature-256`. Verification and retries: [Webhooks](/docs/md/webhooks.md).\n\n| Event | Fires when | `data` fields |\n| --- | --- | --- |\n| `checkout.session.created` | A session is created. | `session_id`, `amount_total`, `currency`, `late` |\n| `checkout.session.deposit_detected` | Funds seen on-chain, awaiting confirmations. | `session_id`, `amount_total`, `currency`, `late`, `tx_hash`, `amount_received`, `received_token` |\n| `checkout.session.paid` | Confirmed \u2014 safe to fulfil. `late: true` if it arrived after the deadline. | `session_id`, `amount_total`, `currency`, `late`, `tx_hash` |\n| `checkout.session.settled` | Funds swept to your payout wallet. | `session_id`, `amount_total`, `currency`, `late`, `sweep_tx_hash` |\n| `checkout.session.unresolved` | Underpaid, wrong token, or a confirmed deposit reverted by a reorg (`reason`). | `session_id`, `amount_total`, `currency`, `late`, `reason`, `amount_expected`, `amount_received`, `received_token`, `tx_hash` |\n| `checkout.session.expired` | Deadline passed without full payment. | `session_id`, `amount_total`, `currency`, `late`, `reason`, `expired_at`, `source`, `refund_tx_hash` |\n| `checkout.refund.recorded` | A refund was made on-chain (`kind`). | `session_id`, `kind`, `amount`, `token`, `tx_hash`, `refund_address` |\n| `x402.payment.resolved` | An x402 call that settled with `503` reached its outcome. Only fires for those \u2014 the normal path answers inline. | `payment_id`, `status`, `resource`, `amount`, `asset`, `chain`, `tx_hash`, `payer`, `resolved_by` |'
4070
+ markdown: '# API reference\n\nEvery public endpoint, generated from the OpenAPI 3.1.0 spec (version 1.0.0). Download it: [openapi.json](/docs/openapi.json).\n\n## Basics\n\n| Topic | Details |\n| --- | --- |\n| Base URL | `https://api.bitpal.io` \u2014 test and live share the host; the API key prefix selects the mode. |\n| Auth | `Authorization: Bearer bp_test_\u2026` (test) or `bp_live_\u2026` (live). Keep keys on your server. |\n| Format | JSON. Success: `{ "data": \u2026 }` (authenticated endpoints add `meta: { mode, requestId }`). Amounts are strings. |\n| Errors | `{ "error", "code", "retryable", "trace_id", "details"? }` \u2014 `error` is the human-readable message; branch on `code`. See [Errors](/docs/md/errors.md). |\n| Idempotency | `Idempotency-Key` (8\u2013128 chars) is honoured on every authenticated merchant `POST`; endpoints that do not enforce it say so. |\n\n## Checkout sessions\n\nCreate a session per order, send the buyer to the hosted page (or build your own UI), and track it.\n\n### `POST /v1/checkout/sessions` \u2014 Create a checkout session\n\nCreates a session for one order and returns the hosted `checkout_url`. Line items take either `amount` (plain decimal string, e.g. "29") or `amount_atomic` (6-decimal integer string), or reference a `price_id`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateCheckoutSessionRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `line_items` | array of (object \\| any \\| any) | Yes | Raw items (`name`, `currency`, `amount` XOR `amount_atomic`) or price items (`price_id`). Do not mix the two kinds. (\u2265 1 items) |\n| `currency` | string | No | Session currency. Defaults to the line items\u2019 currency. (\u2265 1 chars) |\n| `success_url` | string (uri) | No | Where the buyer returns after paying. `{CHECKOUT_SESSION_ID}` is replaced with the session id. (\u2264 2048 chars) |\n| `cancel_url` | string (uri) | No | Where the buyer goes when cancelling. (\u2264 2048 chars) |\n| `customer_email` | string (email) | No | Buyer email for the receipt. |\n| `metadata` | map | No | Your key/value data, echoed back on the session. |\n| `expires_in_minutes` | integer | No | Payment window in minutes (1\u201360). Default 15. (1\u201360, default `15`) |\n| `tolerance_percent` | string | No | Deprecated. Underpayments are never accepted \u2014 a short payment becomes `unresolved_underpaid` and can be topped up to the same address. Only `"0"` is accepted; any other value returns 400. |\n| `pay_chain` | string | No | Fix the payment network: CAIP-2 (`eip155:84532`) or a short name (`base`), which resolves to the testnet in test mode and the mainnet in live mode. Mutually exclusive with `allowed_pay_chains`. |\n| `allowed_pay_chains` | array of string | No | Networks the buyer may choose from (CAIP-2 or short names, resolved like `pay_chain`). (1\u20138 items) |\n| `allowed_assets` | array of object | No | Allowed (chain, token) cells. Takes precedence over `allowed_pay_chains`. (1\u201316 items) |\n\n```\n{\n "line_items": [\n {\n "name": "Pro plan",\n "amount": "29",\n "currency": "USDC"\n }\n ],\n "pay_chain": "eip155:84532",\n "expires_in_minutes": 30,\n "success_url": "https://your.store/thanks?session={CHECKOUT_SESSION_ID}"\n}\n```\n\n**Response `201`** \u2014 Session created.\n\n```\n{\n "data": {\n "id": "cs_Q2FxKhomCEju_OqvKfrQsTOh",\n "checkout_url": "https://bitpal.io/pay/cs_Q2FxKhomCEju_OqvKfrQsTOh?token=<session_token>",\n "session_token": "<session_token>",\n "status": "created",\n "amount_total": "29000000",\n "currency": "USDC",\n "expires_at": "2026-11-06T07:58:28.776Z",\n "tax": {\n "tax_amount": "0",\n "total_with_tax": "29000000"\n }\n },\n "meta": {\n "mode": "TEST",\n "requestId": "ec091faf-\u2026"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \xB7 `422` \xB7 `429` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions` \u2014 List checkout sessions\n\nNewest first, in the API key\u2019s mode (test/live).\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | string | No | Filter by status, or `succeeded` for all successful states. |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Sessions.\n\n```\n{\n "data": [\n {\n "id": "string",\n "status": "string",\n "mode": "TEST",\n "amount_total": "1000000",\n "amount_received": "string",\n "currency": "string",\n "pay_chain": "string",\n "pay_asset": "string",\n "token_decimals": 0,\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "deposit_address": "string",\n "refund_address": "string",\n "received_token": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "fee_amount_token": "string",\n "net_amount_token": "string",\n "tx_hash": "string",\n "deposit_tx_hash": "string",\n "sweep_tx_hash": "string",\n "success_url": "string",\n "cancel_url": "string",\n "metadata": {},\n "payment_source": "string",\n "payment_link_id": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "raw_status": "string"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}` \u2014 Retrieve a checkout session\n\nServer-side source of truth for an order, together with webhooks.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 The session.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "mode": "TEST",\n "amount_total": "1000000",\n "amount_received": "string",\n "currency": "string",\n "pay_chain": "string",\n "pay_asset": "string",\n "token_decimals": 0,\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "deposit_address": "string",\n "refund_address": "string",\n "received_token": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "fee_amount_token": "string",\n "net_amount_token": "string",\n "tx_hash": "string",\n "deposit_tx_hash": "string",\n "sweep_tx_hash": "string",\n "success_url": "string",\n "cancel_url": "string",\n "metadata": {},\n "payment_source": "string",\n "payment_link_id": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "id": "string",\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0,\n "price_id": "string",\n "product_id": "string",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/status` \u2014 Get session status\n\nLightweight status for polling from your server. Requires your API key (N13 \u2014 it is not a public endpoint). Buyer-facing pages should use `GET /v1/checkout/sessions/{id}/public`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Status.\n\n```\n{\n "data": {\n "status": "awaiting_deposit",\n "paid_at": null\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/public` \u2014 Get the public session view\n\nBuyer-facing view used by the checkout page: payment options, deposit address once issued, refunds. No authentication; CORS-open.\n\n**Auth:** None \u2014 public endpoint\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Public view.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "token_decimals": 0,\n "pay_amount": "string",\n "mode": "TEST",\n "chain_id": 0,\n "token_address": "string",\n "payment_options": [\n {\n "caip2": "string",\n "chain_id": 0,\n "token_symbol": "string",\n "token_address": "string",\n "decimals": 0,\n "amount_atomic": "string",\n "available": true,\n "unavailable_reason": "coming_soon"\n }\n ],\n "currency": "string",\n "amount_total": "1000000",\n "amount_received": "string",\n "chain": "string",\n "tx_hash": "string",\n "release_tx_hash": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "success_url": "string",\n "cancel_url": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "tax_amount": null,\n "tax_rate": null,\n "pay_chain": "string",\n "pay_asset": "string",\n "deposit_address": "string",\n "deposit_owner": "string",\n "payment_deadline_at": "2026-11-06T07:00:00.000Z",\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0\n }\n ],\n "payment_source": "string",\n "refunds": [\n {\n "kind": "string",\n "amount": "string",\n "token_symbol": "string",\n "decimals": 0,\n "tx_hash": "string",\n "caip2": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/checkout/sessions/{id}/deposit-address` \u2014 Issue the deposit address\n\nFixes the buyer\u2019s network, token and refund address, and returns the one-time deposit address with the exact amount. Calling again returns the same address and keeps the first refund address. Requires the session token (header `X-Session-Token` or body `session_token`).\n\n**Auth:** Session token \u2014 `X-Session-Token` header or `session_token` body field (no API key)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n| `Idempotency-Key` | header | string | No | Accepted but not yet enforced on this endpoint \u2014 retries are not de-duplicated by key. (8\u2013128 chars) |\n| `X-Session-Token` | header | string | No | Session token from the create-session response. Alternative to the `session_token` body field. |\n\n**Request body** (`IssueDepositAddressRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `session_token` | string | No | From the create-session response. May be sent as the `X-Session-Token` header instead. |\n| `refundAddress` | string | Yes | Buyer refund address in the chosen network\u2019s format (EVM 0x\u2026, Tron T\u2026, Solana base58). Cannot change later. |\n| `chain` | string | No | CAIP-2 or short name of the chosen network. Required for multi-option sessions. (\u2265 1 chars) |\n| `token` | string | No | Token symbol of the chosen asset, e.g. USDC. Required for multi-option sessions. (\u2265 1 chars) |\n\n```\n{\n "session_token": "<session_token>",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "chain": "eip155:84532",\n "token": "USDC"\n}\n```\n\n**Response `200`** \u2014 Deposit address.\n\n```\n{\n "data": {\n "sessionId": "cs_\u2026",\n "chain": "eip155:84532",\n "depositAddress": "0x6b19e871c934aB52775B6712e110f3e4b0626347",\n "expectedToken": "0x943b94dacf1507f2658f1cfe103ac36ebc13ef65",\n "expectedAmount": "29000000",\n "feeAmount": "435000",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "deadline": "1793951938",\n "expiresAt": "2026-11-06T07:58:28.776Z",\n "depositOwner": null\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \xB7 `410` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/sessions/{id}/refunds` \u2014 List automatic refunds for a session\n\nOn-chain refunds BitPal made for this session (overpayment, expired underpayment, wrong token, late deposit).\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Refunds.\n\n```\n{\n "data": [\n {\n "id": "string",\n "kind": "string",\n "token": "string",\n "token_symbol": "string",\n "amount": "string",\n "amount_display": "string",\n "decimals": 0,\n "refund_address": "string",\n "tx_hash": "string",\n "caip2": "string",\n "block_number": "string",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/fee-preview` \u2014 Preview the fee for an amount\n\nPass exactly one of `amount` or `amount_atomic`. The response is always atomic.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `amount` | query | string | No | Decimal string, e.g. "100". |\n| `amount_atomic` | query | string | No | 6-decimal integer string, e.g. "100000000". |\n\n**Response `200`** \u2014 Fee breakdown.\n\n```\n{\n "data": {\n "amount": "100000000",\n "fee_rate": "0.015",\n "fee_amount": "1500000",\n "net_amount": "98500000"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n## Products & prices\n\nCatalog objects. Prices are immutable.\n\n### `POST /v1/checkout/products` \u2014 Create a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateProductRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | string | Yes | 1\u2013200 chars |\n| `description` | string | No | \u2264 2000 chars |\n| `image_url` | string (uri) | No | \u2264 2048 chars |\n| `metadata` | map | No | |\n\n```\n{\n "name": "Pro plan"\n}\n```\n\n**Response `201`** \u2014 Product created.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products` \u2014 List products\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | "active" \\| "inactive" | No | |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Products.\n\n```\n{\n "data": [\n {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products/{id}` \u2014 Retrieve a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n\n**Response `200`** \u2014 The product.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/products/{id}` \u2014 Update a product\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n\n**Request body** (`UpdateProductRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `name` | string | No | 1\u2013200 chars |\n| `description` | string \\| null | No | \u2264 2000 chars |\n| `image_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `metadata` | map | No | |\n| `status` | "active" \\| "inactive" | No | |\n\n**Response `200`** \u2014 The updated product.\n\n```\n{\n "data": {\n "id": "string",\n "name": "string",\n "description": "string",\n "image_url": "string",\n "status": "active",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/checkout/products/{id}/prices` \u2014 Create a price\n\nPrices are immutable: to change an amount, create a new price. Pass exactly one of `amount` (decimal string) or `amount_atomic` (6-decimal integer string). The currency is derived from `token_symbol`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreatePriceRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `amount` | string | No | Decimal string, e.g. "29". Mutually exclusive with `amount_atomic`. |\n| `amount_atomic` | string | No | 6-decimal integer string ("29000000" = 29). |\n| `token_symbol` | "USDC" \\| "USDT" \\| "JPYC" | No | The price\u2019s asset. The currency is derived from it. (default `"USDC"`) |\n| `billing_type` | "one_time" | No | Only `one_time` for now. (default `"one_time"`) |\n| `nickname` | string | No | Display name. (\u2264 200 chars) |\n| `lookup_key` | string | No | Your own stable key for this price. (1\u2013200 chars) |\n\n```\n{\n "amount": "29",\n "token_symbol": "USDC"\n}\n```\n\n**Response `201`** \u2014 Price created.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/products/{id}/prices` \u2014 List a product\u2019s prices\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Product id (`prod_\u2026`). |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Prices.\n\n```\n{\n "data": [\n {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/prices/{id}` \u2014 Retrieve a price\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Price id (`price_\u2026`). |\n\n**Response `200`** \u2014 The price.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/prices/{id}` \u2014 Update a price\u2019s nickname\n\nOnly `nickname` can change. Sending an amount/currency field returns `PRICE_IMMUTABLE_FIELD`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Price id (`price_\u2026`). |\n\n**Request body** (`UpdatePriceRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `nickname` | string \\| null | No | \u2264 200 chars |\n\n**Response `200`** \u2014 The updated price.\n\n```\n{\n "data": {\n "id": "string",\n "product_id": "string",\n "amount_atomic": "1000000",\n "currency": "string",\n "token_symbol": "string",\n "billing_type": "one_time",\n "nickname": "string",\n "lookup_key": "string",\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n## Payment links\n\nShareable hosted URLs for a price.\n\n### `POST /v1/checkout/payment-links` \u2014 Create a payment link\n\nA shareable hosted URL for one price. The link \u2194 price binding is fixed after creation.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreatePaymentLinkRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `price_id` | string | Yes | The price this link sells (`price_\u2026`). |\n| `title` | string | No | 1\u2013200 chars |\n| `description` | string | No | \u2264 2000 chars |\n| `collect_email` | boolean | No | Ask the buyer for an email. Default true. (default `true`) |\n| `email_required` | boolean | No | Require the email: the hosted link page asks for it and no checkout is created without it. Default true; needs `collect_email`. (default `true`) |\n| `allowed_pay_chains` | array of string | No | Networks the buyer may choose from (CAIP-2 or short names). (1\u20138 items) |\n| `allowed_assets` | array of object | No | Allowed (chain, token) cells. Takes precedence over `allowed_pay_chains`. (1\u201316 items) |\n| `success_url` | string (uri) | No | \u2264 2048 chars |\n| `cancel_url` | string (uri) | No | \u2264 2048 chars |\n| `max_uses` | integer | No | Stop accepting payments after this many paid uses. (\u2265 1) |\n| `expires_at` | string (date-time) | No | ISO-8601 time after which the link stops working. |\n| `metadata` | map | No | |\n\n```\n{\n "price_id": "price_\u2026",\n "allowed_pay_chains": [\n "eip155:8453"\n ]\n}\n```\n\n**Response `201`** \u2014 Link created.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/payment-links` \u2014 List payment links\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `status` | query | "active" \\| "inactive" | No | |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Links.\n\n```\n{\n "data": [\n {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/checkout/payment-links/{id}` \u2014 Retrieve a payment link\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment link id (`plink_\u2026`). |\n\n**Response `200`** \u2014 The link, with product/price summary fields.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/checkout/payment-links/{id}` \u2014 Update a payment link\n\nOperational settings and active \u2194 inactive. The price cannot change \u2014 create a new link instead.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment link id (`plink_\u2026`). |\n\n**Request body** (`UpdatePaymentLinkRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `title` | string \\| null | No | 1\u2013200 chars |\n| `description` | string \\| null | No | \u2264 2000 chars |\n| `collect_email` | boolean | No | |\n| `email_required` | boolean | No | |\n| `allowed_pay_chains` | array of string \\| null | No | 1\u20138 items |\n| `allowed_assets` | array of object \\| null | No | 1\u201316 items |\n| `success_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `cancel_url` | string (uri) \\| null | No | \u2264 2048 chars |\n| `status` | "active" \\| "inactive" | No | |\n| `max_uses` | integer \\| null | No | \u2265 1 |\n| `expires_at` | string (date-time) \\| null | No | |\n| `metadata` | map | No | |\n\n**Response `200`** \u2014 The updated link.\n\n```\n{\n "data": {\n "id": "string",\n "share_token": "string",\n "price_id": "string",\n "title": "string",\n "description": "string",\n "collect_email": true,\n "email_required": true,\n "allowed_pay_chains": [\n "string"\n ],\n "allowed_assets": [\n {\n "caip2": "string",\n "token": "string"\n }\n ],\n "success_url": "string",\n "cancel_url": "string",\n "status": "active",\n "max_uses": 0,\n "paid_use_count": 0,\n "expires_at": "2026-11-06T07:00:00.000Z",\n "metadata": {},\n "mode": "TEST",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `404` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n## x402\n\nCharge per API call with HTTP 402 and EIP-3009 authorizations.\n\n### `GET /v1/x402/assets` \u2014 List x402 assets for this mode\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Response `200`** \u2014 Assets.\n\n```\n{\n "data": {\n "mode": "TEST",\n "assets": [\n {\n "caip2": "string",\n "network": "string",\n "chain_name": "string",\n "symbol": "string",\n "decimals": 0,\n "address": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/requirements` \u2014 Build the 402 payment requirements\n\nReturns the body your resource server sends with `402 Payment Required`, including the fee split. Pass exactly one of `amount` or `amountAtomic`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402RequirementsRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `network` | string | No | x402 network name (`base`, `base-sepolia`). Defaults to the mode\u2019s first asset. (\u2265 1 chars) |\n| `asset` | string | No | Token symbol. Default USDC. (\u2265 1 chars, default `"USDC"`) |\n| `payTo` | string | Yes | Your payout wallet (0x) \u2014 must be the one registered in Console for this mode, otherwise `PAYTO_NOT_MERCHANT_WALLET`. |\n| `amount` | string | No | Gross amount per call as a decimal string, e.g. "0.1". The fee is taken from it. |\n| `amountAtomic` | string | No | Same as `amount`, as a 6-decimal integer string. |\n| `resource` | string | Yes | The URL being paid for. (1\u20132048 chars) |\n| `description` | string | No | \u2264 512 chars |\n| `mimeType` | string | No | \u2264 128 chars |\n| `maxTimeoutSeconds` | integer | No | How long the payer has to sign (max 3600). Default 300. (\u2264 3600, > 0) |\n\n```\n{\n "payTo": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",\n "amount": "0.1",\n "resource": "https://api.example.com/report"\n}\n```\n\n**Response `200`** \u2014 402 body.\n\n```\n{\n "data": {\n "x402Version": 1,\n "accepts": [\n {\n "scheme": "exact",\n "network": "string",\n "asset": "string",\n "payTo": "string",\n "maxAmountRequired": "1000000",\n "resource": "string",\n "description": "string",\n "mimeType": "string",\n "maxTimeoutSeconds": 0,\n "extra": {\n "name": "string",\n "version": "string",\n "chainId": 0\n },\n "feeBreakdown": {\n "netAmount": "1000000",\n "feeAmount": "1000000",\n "feeBps": 0,\n "feeRecipient": "string"\n }\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/verify` \u2014 Verify an X-PAYMENT header\n\nChecks the EIP-3009 authorization against the requirements. Sends nothing on-chain.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402PaymentRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `x402Version` | 1 | Yes | |\n| `paymentPayload` | object | Yes | |\n| `paymentRequirements` | object | Yes | |\n\n**Response `200`** \u2014 Valid.\n\n```\n{\n "data": {\n "valid": true,\n "payment_id": "string",\n "status": "string",\n "idempotent": true\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/x402/settle` \u2014 Settle an x402 payment\n\nBroadcasts the transfer and waits for the receipt. Serve the resource only when `status` is `confirmed`. Settlement is idempotent per authorization \u2014 retry with the same body on 5xx.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`X402PaymentRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `x402Version` | 1 | Yes | |\n| `paymentPayload` | object | Yes | |\n| `paymentRequirements` | object | Yes | |\n\n**Response `200`** \u2014 Settlement result.\n\n```\n{\n "data": {\n "success": true,\n "payment_id": "string",\n "status": "string",\n "tx_hash": "string",\n "fee_tx_hash": "string",\n "network": "string",\n "idempotent": true\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `403` \xB7 `409` \xB7 `503` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/x402/payments/{id}` \u2014 Retrieve an x402 payment\n\nRecovery path when a settle response was lost \u2014 check here before settling again.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Payment id. |\n\n**Response `200`** \u2014 The payment.\n\n```\n{\n "data": {\n "id": "string",\n "status": "pending",\n "raw_status": "string",\n "resource": "string",\n "chain": "string",\n "asset": "string",\n "decimals": 0,\n "amount": "1000000",\n "gross_amount": "1000000",\n "payer": "string",\n "pay_to": "string",\n "tx_hash": "string",\n "created_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/x402/payments` \u2014 List x402 payments\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `limit` | query | integer | No | \u2264 100, > 0, default `20` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n| `status` | query | string | No | pending \\| confirmed \\| failed \\| needs_review |\n\n**Response `200`** \u2014 Payments.\n\n```\n{\n "data": [\n {\n "id": "string",\n "status": "pending",\n "raw_status": "string",\n "resource": "string",\n "chain": "string",\n "asset": "string",\n "decimals": 0,\n "amount": "1000000",\n "gross_amount": "1000000",\n "payer": "string",\n "pay_to": "string",\n "tx_hash": "string",\n "created_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n## Webhook endpoints\n\nManage where BitPal delivers signed events.\n\n### `POST /v1/webhooks` \u2014 Create a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. The response carries the `whsec_\u2026` signing secret \u2014 it is shown only once.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | Yes | HTTPS URL that receives events. Private hosts are rejected. |\n| `subscribed_events` | array of ("*" \\| "checkout.session.created" \\| "checkout.session.deposit_detected" \\| "checkout.session.paid" \\| "checkout.session.settled" \\| "checkout.session.expired" \\| "checkout.session.unresolved" \\| "checkout.refund.recorded" \\| "x402.payment.resolved") | Yes | Event names to deliver (see the `webhooks` section), or `*` for every event. Unknown names are rejected with 400. (\u2265 1 items) |\n| `retry_policy` | object | No | `max_retries` caps the total delivery attempts (1\u201320, default 10: 3 right away, then 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h). The schedule itself is fixed; `backoff` is ignored. |\n| `dead_letter_destination` | string (uri) \\| null | No | Optional URL for dead-lettered deliveries. |\n\n```\n{\n "endpoint_url": "https://your.store/webhooks/bitpal",\n "subscribed_events": [\n "checkout.session.paid"\n ]\n}\n```\n\n**Response `201`** \u2014 Endpoint created.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `GET /v1/webhooks` \u2014 List webhook endpoints\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Endpoints of the API key\u2019s environment and mode. Note: list items use camelCase keys.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `limit` | query | integer | No | 1\u2013100, default `50` |\n| `offset` | query | integer | No | \u2265 0, default `0` |\n\n**Response `200`** \u2014 Endpoints, newest first. `meta` carries total/limit/offset.\n\n```\n{\n "data": [\n {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n }\n ],\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `401` \u2014 see [Errors](/docs/md/errors.md).\n\n### `PATCH /v1/webhooks/{id}` \u2014 Update a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Setting `status` to `disabled` removes the endpoint and requires `reason_code` (otherwise 400 `REASON_CODE_REQUIRED`). It is recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n\n**Request body** (`UpdateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | No | |\n| `subscribed_events` | array of ("*" \\| "checkout.session.created" \\| "checkout.session.deposit_detected" \\| "checkout.session.paid" \\| "checkout.session.settled" \\| "checkout.session.expired" \\| "checkout.session.unresolved" \\| "checkout.refund.recorded" \\| "x402.payment.resolved") | No | \u2265 1 items |\n| `status` | "active" \\| "paused" \\| "disabled" | No | |\n| `retry_policy` | object | No | |\n| `dead_letter_destination` | string (uri) \\| null | No | |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | No | Required when `status` is `disabled`: one of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n**Response `200`** \u2014 The updated endpoint.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/webhooks/{id}/rotate-secret` \u2014 Rotate the signing secret\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Takes effect immediately. The new secret is returned once \u2014 update your verifier. Requires `reason_code` (400 `REASON_CODE_REQUIRED` if missing); recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`RotateWebhookSecretRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | Yes | One of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n```\n{\n "reason_code": "rotation"\n}\n```\n\n**Response `200`** \u2014 Endpoint with the new secret.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).\n\n### `POST /v1/developers/webhooks/test` \u2014 Send a test event\n\nPosts one signed sample event to an endpoint (no retries). The envelope id is prefixed `test_`, `data.test` is true and the request carries `X-Webhook-Test: true`.\n\n**Auth:** API key \u2014 `Authorization: Bearer bp_test_\u2026` / `bp_live_\u2026` (server only)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`SendTestWebhookRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `webhook_id` | string (uuid) | Yes | Endpoint id. |\n| `event_type` | string | Yes | Event name to put in the envelope, e.g. checkout.session.paid. (1\u2013200 chars) |\n| `payload` | map | No | Custom `data` object. Defaults to a sample message. |\n\n```\n{\n "webhook_id": "00000000-0000-4000-8000-000000000000",\n "event_type": "checkout.session.paid"\n}\n```\n\n**Response `200`** \u2014 Delivery result.\n\n```\n{\n "data": {\n "delivery_id": "00000000-0000-4000-8000-000000000000",\n "webhook_id": "00000000-0000-4000-8000-000000000000",\n "endpoint_url": "string",\n "event_type": "string",\n "http_status": 0,\n "response_body": "string",\n "error": "string",\n "duration_ms": 0,\n "test": true,\n "sent_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \u2014 see [Errors](/docs/md/errors.md).\n\n## Webhook events\n\nEnvelope: `{ id, event, created_at, data }`, signed with `X-Webhook-Signature-256`. Verification and retries: [Webhooks](/docs/md/webhooks.md).\n\n| Event | Fires when | `data` fields |\n| --- | --- | --- |\n| `checkout.session.created` | A session is created. | `session_id`, `amount_total`, `currency`, `late` |\n| `checkout.session.deposit_detected` | Funds seen on-chain, awaiting confirmations. | `session_id`, `amount_total`, `currency`, `late`, `tx_hash`, `amount_received`, `received_token` |\n| `checkout.session.paid` | Confirmed \u2014 safe to fulfil. `late: true` if it arrived after the deadline. | `session_id`, `amount_total`, `currency`, `late`, `tx_hash` |\n| `checkout.session.settled` | Funds swept to your payout wallet. | `session_id`, `amount_total`, `currency`, `late`, `sweep_tx_hash` |\n| `checkout.session.unresolved` | Underpaid, wrong token, or a confirmed deposit reverted by a reorg (`reason`). | `session_id`, `amount_total`, `currency`, `late`, `reason`, `amount_expected`, `amount_received`, `received_token`, `tx_hash` |\n| `checkout.session.expired` | Deadline passed without full payment. | `session_id`, `amount_total`, `currency`, `late`, `reason`, `expired_at`, `source`, `refund_tx_hash` |\n| `checkout.refund.recorded` | A refund was made on-chain (`kind`). | `session_id`, `kind`, `amount`, `token`, `tx_hash`, `refund_address` |\n| `x402.payment.resolved` | An x402 call that settled with `503` reached its outcome. Only fires for those \u2014 the normal path answers inline. | `payment_id`, `status`, `resource`, `amount`, `asset`, `chain`, `tx_hash`, `payer`, `resolved_by` |'
4071
4071
  },
4072
4072
  {
4073
4073
  slug: "errors",
@@ -4272,14 +4272,14 @@ var docs_data_default = {
4272
4272
  pageTitle: "API reference",
4273
4273
  heading: "Checkout sessions \u203A `GET /v1/checkout/sessions/{id}/public` \u2014 Get the public session view",
4274
4274
  url: "https://bitpal.io/docs/#api",
4275
- text: '### `GET /v1/checkout/sessions/{id}/public` \u2014 Get the public session view\n\nBuyer-facing view used by the checkout page: payment options, deposit address once issued, refunds. No authentication; CORS-open.\n\n**Auth:** None \u2014 public endpoint\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Public view.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "token_decimals": 0,\n "pay_amount": "string",\n "mode": "TEST",\n "chain_id": 0,\n "token_address": "string",\n "payment_options": [\n {\n "caip2": "string",\n "chain_id": 0,\n "token_symbol": "string",\n "token_address": "string",\n "decimals": 0,\n "amount_atomic": "string"\n }\n ],\n "currency": "string",\n "amount_total": "1000000",\n "amount_received": "string",\n "chain": "string",\n "tx_hash": "string",\n "release_tx_hash": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "success_url": "string",\n "cancel_url": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "tax_amount": null,\n "tax_rate": null,\n "pay_chain": "string",\n "pay_asset": "string",\n "deposit_address": "string",\n "payment_deadline_at": "2026-11-06T07:00:00.000Z",\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0\n }\n ],\n "payment_source": "string",\n "refunds": [\n {\n "kind": "string",\n "amount": "string",\n "token_symbol": "string",\n "decimals": 0,\n "tx_hash": "string",\n "caip2": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).'
4275
+ text: '### `GET /v1/checkout/sessions/{id}/public` \u2014 Get the public session view\n\nBuyer-facing view used by the checkout page: payment options, deposit address once issued, refunds. No authentication; CORS-open.\n\n**Auth:** None \u2014 public endpoint\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n\n**Response `200`** \u2014 Public view.\n\n```\n{\n "data": {\n "id": "string",\n "status": "string",\n "token_decimals": 0,\n "pay_amount": "string",\n "mode": "TEST",\n "chain_id": 0,\n "token_address": "string",\n "payment_options": [\n {\n "caip2": "string",\n "chain_id": 0,\n "token_symbol": "string",\n "token_address": "string",\n "decimals": 0,\n "amount_atomic": "string",\n "available": true,\n "unavailable_reason": "coming_soon"\n }\n ],\n "currency": "string",\n "amount_total": "1000000",\n "amount_received": "string",\n "chain": "string",\n "tx_hash": "string",\n "release_tx_hash": "string",\n "expires_at": "2026-11-06T07:00:00.000Z",\n "success_url": "string",\n "cancel_url": "string",\n "fee_amount": "string",\n "fee_rate": "string",\n "net_amount": "string",\n "tax_amount": null,\n "tax_rate": null,\n "pay_chain": "string",\n "pay_asset": "string",\n "deposit_address": "string",\n "deposit_owner": "string",\n "payment_deadline_at": "2026-11-06T07:00:00.000Z",\n "payment_method": "string",\n "payer_wallet": "string",\n "seller_wallet": "string",\n "tolerance_percent": "string",\n "paid_at": "2026-11-06T07:00:00.000Z",\n "settled_at": "2026-11-06T07:00:00.000Z",\n "created_at": "2026-11-06T07:00:00.000Z",\n "line_items": [\n {\n "name": "string",\n "amount": "1000000",\n "currency": "string",\n "quantity": 0\n }\n ],\n "payment_source": "string",\n "refunds": [\n {\n "kind": "string",\n "amount": "string",\n "token_symbol": "string",\n "decimals": 0,\n "tx_hash": "string",\n "caip2": "string"\n }\n ]\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `404` \u2014 see [Errors](/docs/md/errors.md).'
4276
4276
  },
4277
4277
  {
4278
4278
  page: "api",
4279
4279
  pageTitle: "API reference",
4280
4280
  heading: "Checkout sessions \u203A `POST /v1/checkout/sessions/{id}/deposit-address` \u2014 Issue the deposit address",
4281
4281
  url: "https://bitpal.io/docs/#api",
4282
- text: '### `POST /v1/checkout/sessions/{id}/deposit-address` \u2014 Issue the deposit address\n\nFixes the buyer\u2019s network, token and refund address, and returns the one-time deposit address with the exact amount. Calling again returns the same address and keeps the first refund address. Requires the session token (header `X-Session-Token` or body `session_token`).\n\n**Auth:** Session token \u2014 `X-Session-Token` header or `session_token` body field (no API key)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n| `Idempotency-Key` | header | string | No | Accepted but not yet enforced on this endpoint \u2014 retries are not de-duplicated by key. (8\u2013128 chars) |\n| `X-Session-Token` | header | string | No | Session token from the create-session response. Alternative to the `session_token` body field. |\n\n**Request body** (`IssueDepositAddressRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `session_token` | string | No | From the create-session response. May be sent as the `X-Session-Token` header instead. |\n| `refundAddress` | string | Yes | Buyer refund address in the chosen network\u2019s format (EVM 0x\u2026, Tron T\u2026, Solana base58). Cannot change later. |\n| `chain` | string | No | CAIP-2 or short name of the chosen network. Required for multi-option sessions. (\u2265 1 chars) |\n| `token` | string | No | Token symbol of the chosen asset, e.g. USDC. Required for multi-option sessions. (\u2265 1 chars) |\n\n```\n{\n "session_token": "<session_token>",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "chain": "eip155:84532",\n "token": "USDC"\n}\n```\n\n**Response `200`** \u2014 Deposit address.\n\n```\n{\n "data": {\n "sessionId": "cs_\u2026",\n "chain": "eip155:84532",\n "depositAddress": "0x6b19e871c934aB52775B6712e110f3e4b0626347",\n "expectedToken": "0x943b94dacf1507f2658f1cfe103ac36ebc13ef65",\n "expectedAmount": "29000000",\n "feeAmount": "435000",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "deadline": "1793951938",\n "expiresAt": "2026-11-06T07:58:28.776Z"\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \xB7 `410` \u2014 see [Errors](/docs/md/errors.md).'
4282
+ text: '### `POST /v1/checkout/sessions/{id}/deposit-address` \u2014 Issue the deposit address\n\nFixes the buyer\u2019s network, token and refund address, and returns the one-time deposit address with the exact amount. Calling again returns the same address and keeps the first refund address. Requires the session token (header `X-Session-Token` or body `session_token`).\n\n**Auth:** Session token \u2014 `X-Session-Token` header or `session_token` body field (no API key)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Checkout session id (`cs_\u2026`). |\n| `Idempotency-Key` | header | string | No | Accepted but not yet enforced on this endpoint \u2014 retries are not de-duplicated by key. (8\u2013128 chars) |\n| `X-Session-Token` | header | string | No | Session token from the create-session response. Alternative to the `session_token` body field. |\n\n**Request body** (`IssueDepositAddressRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `session_token` | string | No | From the create-session response. May be sent as the `X-Session-Token` header instead. |\n| `refundAddress` | string | Yes | Buyer refund address in the chosen network\u2019s format (EVM 0x\u2026, Tron T\u2026, Solana base58). Cannot change later. |\n| `chain` | string | No | CAIP-2 or short name of the chosen network. Required for multi-option sessions. (\u2265 1 chars) |\n| `token` | string | No | Token symbol of the chosen asset, e.g. USDC. Required for multi-option sessions. (\u2265 1 chars) |\n\n```\n{\n "session_token": "<session_token>",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "chain": "eip155:84532",\n "token": "USDC"\n}\n```\n\n**Response `200`** \u2014 Deposit address.\n\n```\n{\n "data": {\n "sessionId": "cs_\u2026",\n "chain": "eip155:84532",\n "depositAddress": "0x6b19e871c934aB52775B6712e110f3e4b0626347",\n "expectedToken": "0x943b94dacf1507f2658f1cfe103ac36ebc13ef65",\n "expectedAmount": "29000000",\n "feeAmount": "435000",\n "refundAddress": "0xa0Ee7A142d267C1f36714E4a8F75612F20a79720",\n "deadline": "1793951938",\n "expiresAt": "2026-11-06T07:58:28.776Z",\n "depositOwner": null\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \xB7 `409` \xB7 `410` \u2014 see [Errors](/docs/md/errors.md).'
4283
4283
  },
4284
4284
  {
4285
4285
  page: "api",
@@ -4454,7 +4454,7 @@ var docs_data_default = {
4454
4454
  pageTitle: "API reference",
4455
4455
  heading: "Webhook endpoints \u203A `POST /v1/webhooks` \u2014 Create a webhook endpoint",
4456
4456
  url: "https://bitpal.io/docs/#api",
4457
- text: '### `POST /v1/webhooks` \u2014 Create a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. The response carries the `whsec_\u2026` signing secret \u2014 it is shown only once.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | Yes | HTTPS URL that receives events. Private hosts are rejected. |\n| `subscribed_events` | array of string | Yes | Event names to deliver (see the `webhooks` section). (\u2265 1 items) |\n| `retry_policy` | object | No | `max_retries` caps the total delivery attempts (1\u201320, default 10: 3 right away, then 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h). The schedule itself is fixed; `backoff` is ignored. |\n| `dead_letter_destination` | string (uri) \\| null | No | Optional URL for dead-lettered deliveries. |\n\n```\n{\n "endpoint_url": "https://your.store/webhooks/bitpal",\n "subscribed_events": [\n "checkout.session.paid"\n ]\n}\n```\n\n**Response `201`** \u2014 Endpoint created.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).'
4457
+ text: '### `POST /v1/webhooks` \u2014 Create a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. The response carries the `whsec_\u2026` signing secret \u2014 it is shown only once.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `Idempotency-Key` | header | string | No | 8\u2013128 characters, unique per operation. A retry with the same key and body within 24 hours returns the original response with `X-Idempotency-Replayed: true`. (8\u2013128 chars) |\n\n**Request body** (`CreateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | Yes | HTTPS URL that receives events. Private hosts are rejected. |\n| `subscribed_events` | array of ("*" \\| "checkout.session.created" \\| "checkout.session.deposit_detected" \\| "checkout.session.paid" \\| "checkout.session.settled" \\| "checkout.session.expired" \\| "checkout.session.unresolved" \\| "checkout.refund.recorded" \\| "x402.payment.resolved") | Yes | Event names to deliver (see the `webhooks` section), or `*` for every event. Unknown names are rejected with 400. (\u2265 1 items) |\n| `retry_policy` | object | No | `max_retries` caps the total delivery attempts (1\u201320, default 10: 3 right away, then 1 min, 5 min, 30 min, 2 h, 6 h, 12 h, 24 h). The schedule itself is fixed; `backoff` is ignored. |\n| `dead_letter_destination` | string (uri) \\| null | No | Optional URL for dead-lettered deliveries. |\n\n```\n{\n "endpoint_url": "https://your.store/webhooks/bitpal",\n "subscribed_events": [\n "checkout.session.paid"\n ]\n}\n```\n\n**Response `201`** \u2014 Endpoint created.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z",\n "secret": "string"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \u2014 see [Errors](/docs/md/errors.md).'
4458
4458
  },
4459
4459
  {
4460
4460
  page: "api",
@@ -4468,7 +4468,7 @@ var docs_data_default = {
4468
4468
  pageTitle: "API reference",
4469
4469
  heading: "Webhook endpoints \u203A `PATCH /v1/webhooks/{id}` \u2014 Update a webhook endpoint",
4470
4470
  url: "https://bitpal.io/docs/#api",
4471
- text: '### `PATCH /v1/webhooks/{id}` \u2014 Update a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Setting `status` to `disabled` removes the endpoint and requires `reason_code` (otherwise 400 `REASON_CODE_REQUIRED`). It is recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n\n**Request body** (`UpdateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | No | |\n| `subscribed_events` | array of string | No | |\n| `status` | "active" \\| "paused" \\| "disabled" | No | |\n| `retry_policy` | object | No | |\n| `dead_letter_destination` | string (uri) \\| null | No | |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | No | Required when `status` is `disabled`: one of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n**Response `200`** \u2014 The updated endpoint.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).'
4471
+ text: '### `PATCH /v1/webhooks/{id}` \u2014 Update a webhook endpoint\n\n**Console only.** Manage this from Console \u2192 Developers \u2192 Webhooks; calls with an API key return 403. Setting `status` to `disabled` removes the endpoint and requires `reason_code` (otherwise 400 `REASON_CODE_REQUIRED`). It is recorded in the audit log.\n\n**Auth:** Console login only \u2014 manage this in Console \u2192 Developers \u2192 Webhooks (API keys get 403)\n\n**Parameters**\n\n| Parameter | In | Type | Required | Description |\n| --- | --- | --- | --- | --- |\n| `id` | path | string | Yes | Webhook endpoint id (uuid). |\n\n**Request body** (`UpdateWebhookEndpointRequest`)\n\n| Field | Type | Required | Description |\n| --- | --- | --- | --- |\n| `endpoint_url` | string (uri) | No | |\n| `subscribed_events` | array of ("*" \\| "checkout.session.created" \\| "checkout.session.deposit_detected" \\| "checkout.session.paid" \\| "checkout.session.settled" \\| "checkout.session.expired" \\| "checkout.session.unresolved" \\| "checkout.refund.recorded" \\| "x402.payment.resolved") | No | \u2265 1 items |\n| `status` | "active" \\| "paused" \\| "disabled" | No | |\n| `retry_policy` | object | No | |\n| `dead_letter_destination` | string (uri) \\| null | No | |\n| `reason_code` | "user_request" \\| "security_concern" \\| "rotation" \\| "no_longer_needed" \\| "other" | No | Required when `status` is `disabled`: one of user_request, security_concern, rotation, no_longer_needed, other. |\n| `reason_note` | string | No | Optional free text (\u2264 500 chars) stored with the audit record. (\u2264 500 chars) |\n\n**Response `200`** \u2014 The updated endpoint.\n\n```\n{\n "data": {\n "id": "00000000-0000-4000-8000-000000000000",\n "mode": "TEST",\n "endpoint_url": "string",\n "subscribed_events": [\n "string"\n ],\n "retry_policy": {\n "max_retries": 0,\n "backoff": "exponential"\n },\n "dead_letter_destination": "string",\n "status": "active",\n "created_at": "2026-11-06T07:00:00.000Z",\n "updated_at": "2026-11-06T07:00:00.000Z"\n },\n "meta": {\n "mode": "TEST",\n "requestId": "string",\n "total": 0,\n "limit": 0,\n "offset": 0\n }\n}\n```\n\n**Errors:** `400` \xB7 `401` \xB7 `404` \u2014 see [Errors](/docs/md/errors.md).'
4472
4472
  },
4473
4473
  {
4474
4474
  page: "api",
@@ -9428,10 +9428,21 @@ var docs_data_default = {
9428
9428
  format: "uri"
9429
9429
  },
9430
9430
  subscribed_events: {
9431
- description: "Event names to deliver (see the `webhooks` section).",
9431
+ description: "Event names to deliver (see the `webhooks` section), or `*` for every event. Unknown names are rejected with 400.",
9432
9432
  type: "array",
9433
9433
  items: {
9434
- type: "string"
9434
+ type: "string",
9435
+ enum: [
9436
+ "*",
9437
+ "checkout.session.created",
9438
+ "checkout.session.deposit_detected",
9439
+ "checkout.session.paid",
9440
+ "checkout.session.settled",
9441
+ "checkout.session.expired",
9442
+ "checkout.session.unresolved",
9443
+ "checkout.refund.recorded",
9444
+ "x402.payment.resolved"
9445
+ ]
9435
9446
  },
9436
9447
  minItems: 1
9437
9448
  },
@@ -10627,8 +10638,20 @@ var docs_data_default = {
10627
10638
  subscribed_events: {
10628
10639
  type: "array",
10629
10640
  items: {
10630
- type: "string"
10631
- }
10641
+ type: "string",
10642
+ enum: [
10643
+ "*",
10644
+ "checkout.session.created",
10645
+ "checkout.session.deposit_detected",
10646
+ "checkout.session.paid",
10647
+ "checkout.session.settled",
10648
+ "checkout.session.expired",
10649
+ "checkout.session.unresolved",
10650
+ "checkout.refund.recorded",
10651
+ "x402.payment.resolved"
10652
+ ]
10653
+ },
10654
+ minItems: 1
10632
10655
  },
10633
10656
  status: {
10634
10657
  type: "string",
@@ -11913,7 +11936,7 @@ function visibleTools(ctx2) {
11913
11936
 
11914
11937
  // src/protocol.ts
11915
11938
  var SERVER_NAME = "bitpal";
11916
- var SERVER_VERSION = "0.1.1";
11939
+ var SERVER_VERSION = "0.1.2";
11917
11940
  var SUPPORTED_PROTOCOL_VERSIONS = ["2025-06-18", "2025-03-26", "2024-11-05"];
11918
11941
  var INSTRUCTIONS = [
11919
11942
  "BitPal is a non-custodial stablecoin checkout. Use these tools to write correct BitPal integrations:",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bitpal/mcp",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "BitPal MCP server — search BitPal's developer docs, OpenAPI spec, webhook events and error codes from your AI coding tool, and run test-mode payments.",
5
5
  "license": "MIT",
6
6
  "type": "module",