# Checkouts

> Create reusable checkout pages from your own code and get the slug a buy button takes. Every buyer who pays one gets their own payment. The same checkouts you make in the dashboard.

Source: https://railbed.com/docs/api/checkouts/ · Updated: 2026-10-14 · Railbed by MediaGlobe developer docs

For AI assistants: the index of every docs page, with the rules for an integration, is https://railbed.com/docs/llms.txt

## The checkout object

A checkout is a reusable page with a fixed price, such as a product, a course or a donation: share its link, or put a [buy button](https://railbed.com/docs/user-guide/widgets-and-buttons.md) on your site, and every buyer who pays gets their own payment and order. It's the same checkout you can make under [Checkouts](https://app.railbed.io/checkouts) in the dashboard. For one amount from one payer, use a [payment link](https://railbed.com/docs/api/payment-links.md); for an order your server prices, a [checkout session](https://railbed.com/docs/api/checkout-sessions.md).

| Field | Type | Description |
|---|---|---|
| `id` | string | The checkout's id, `chk_…` |
| `object` | string | `"checkout"` |
| `kind` | string | `page`, `pricing_table` or `widget`. The API creates pages; the others are made in the dashboard |
| `slug` | string | What a buy button takes: `<railbed-button checkout="mug4k7tq2z">` |
| `url` | string | The hosted checkout page. Share it, or link to it |
| `livemode` | boolean | `false` for Test mode, `true` for Live mode |
| `active` | boolean | `false` once it was deleted in the dashboard; a deleted checkout takes no new buyers |
| `name` | string | Shown to buyers |
| `description` | string or null | Shown under the name |
| `amount` | string | The price. A pricing table's lowest plan price |
| `currency` | string | `USD`, `EUR`, `GBP`, `CAD` or `AUD` |
| `success_url` | string or null | Where buyers land once paid |
| `theme` | string | `light` or `dark` |
| `button_label` | string or null | The pay button's text, or `null` for "Continue to pay" and the price |
| `crypto` | boolean | Whether buyers may pay in crypto, when [crypto payments](https://railbed.com/docs/user-guide/crypto-payments.md) are on for the account |
| `routing` | object | How buyers reach a card provider: `choice` is `smart` (Smart Routing), `buyer` (buyers choose) or `fixed` (one `provider`, with `fallback` to Smart Routing when it can't take a buyer) |
| `collect` | object or null | What the page asks buyers for besides their email, or `null` for nothing more. See [The collect field](https://railbed.com/docs/api/checkout-sessions.md#the-collect-field) |
| `options` | array or null | A pricing table's two-way switch, such as `["Monthly", "Yearly"]` |
| `plans` | array | A pricing table's plans: `id`, `name`, `description`, `prices` (`amount` and `unit`), `features` and `recommended`. Empty for pages |
| `created` | integer | When it was created, in Unix seconds |
| `updated` | integer | When it last changed, in Unix seconds |

Example: A checkout · response 200 OK

```json
{
  "id": "chk_Mg7tR2vX9kQp4WnZc8Lb",
  "object": "checkout",
  "kind": "page",
  "slug": "mug4k7tq2z",
  "url": "https://pay.railbed.io/c/mug4k7tq2z",
  "livemode": false,
  "active": true,
  "name": "Ceramic mug",
  "description": "Hand-thrown, 350 ml.",
  "amount": "18.00",
  "currency": "USD",
  "success_url": "https://mugs.example/thanks",
  "theme": "light",
  "button_label": null,
  "crypto": true,
  "routing": {
    "choice": "smart",
    "provider": null,
    "fallback": true
  },
  "collect": null,
  "options": null,
  "plans": [],
  "created": 1790380525,
  "updated": 1790380525
}
```

## Create a checkout

`POST /v1/checkouts`

Creates a checkout page in the key's mode, with the settings a new checkout starts with in the dashboard unless you send others.

| Parameter | Type | Description |
|---|---|---|
| `name` | string · required | Shown to buyers, up to 80 characters |
| `amount` | string · required | A decimal string from `"1.00"` to `"100000.00"`, at most two decimals |
| `currency` | string · required | `USD`, `EUR`, `GBP`, `CAD` or `AUD`, in any letter case |
| `description` | string | Up to 280 characters |
| `success_url` | string | Where buyers land once paid. Live mode needs `https://` |
| `kind` | string | `page`, the only kind the API creates for now |
| `theme` | string | `light` (default) or `dark` |
| `button_label` | string | The pay button's text, up to 32 characters |
| `crypto` | boolean | Default `true`: buyers may pay in crypto when it's on for the account |
| `routing` | object | Default `{ "choice": "smart" }`. For one provider: `{ "choice": "fixed", "provider": "stripe", "fallback": true }` |
| `collect` | object | What the page asks buyers for besides their email, as on a [checkout session](https://railbed.com/docs/api/checkout-sessions.md#the-collect-field) |

Example: cURL

```bash
curl https://pay.railbed.io/v1/checkouts \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ceramic mug",
    "description": "Hand-thrown, 350 ml.",
    "amount": "18.00",
    "currency": "USD",
    "success_url": "https://mugs.example/thanks"
  }'
```

Example: Node\.js

```js
const checkout = await fetch('https://pay.railbed.io/v1/checkouts', {
  method: 'POST',
  headers: {
    Authorization: `Bearer ${process.env.RAILBED_SECRET_KEY}`,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({
    name: 'Ceramic mug',
    amount: '18.00',
    currency: 'USD',
    success_url: 'https://mugs.example/thanks',
  }),
}).then((r) => r.json());
// checkout.slug goes in <railbed-button checkout="…">; checkout.url is the page.
```

Example: Python

```python
checkout = requests.post(
    "https://pay.railbed.io/v1/checkouts",
    headers={"Authorization": f"Bearer {os.environ['RAILBED_SECRET_KEY']}"},
    json={
        "name": "Ceramic mug",
        "amount": "18.00",
        "currency": "USD",
        "success_url": "https://mugs.example/thanks",
    },
    timeout=15,
).json()
```

Example: Response · response 201 Created

```json
{
  "id": "chk_Mg7tR2vX9kQp4WnZc8Lb",
  "object": "checkout",
  "kind": "page",
  "slug": "mug4k7tq2z",
  "url": "https://pay.railbed.io/c/mug4k7tq2z",
  "livemode": false,
  "active": true,
  "name": "Ceramic mug",
  "description": "Hand-thrown, 350 ml.",
  "amount": "18.00",
  "currency": "USD",
  "success_url": "https://mugs.example/thanks",
  "theme": "light",
  "button_label": null,
  "crypto": true,
  "routing": {
    "choice": "smart",
    "provider": null,
    "fallback": true
  },
  "collect": null,
  "options": null,
  "plans": [],
  "created": 1790380525,
  "updated": 1790380525
}
```

Put it on your site with the slug:

Example: A buy button

```html
<script src="https://pay.railbed.io/embed.js" async></script>
<railbed-button checkout="mug4k7tq2z"></railbed-button>
```

The checkout follows the dashboard editor's rules, and an error's `field` names the parameter you sent. This endpoint ignores `Idempotency-Key`: after a timeout, [list your checkouts](#list-checkouts) before creating another.

| Error | Cause |
|---|---|
| `400 invalid_kind` | `kind` is something other than `page` |
| `400 missing_name`, `400 too_long` | `name` is empty, or a text field is over its limit |
| `400 invalid_description`, `400 invalid_button_label` | That field isn't a string |
| `400 invalid_amount` | `amount` isn't a decimal string from `"1.00"` to `"100000.00"` |
| `400 invalid_currency` | `currency` isn't one of the five |
| `400 invalid_url` | `success_url` isn't a full address, has a username or password, or isn't `https://` in Live mode |
| `400 invalid_theme`, `400 invalid_value` | `theme` isn't `light` or `dark`, or `crypto` isn't a boolean |
| `400 invalid_routing` | `routing` names no choice, or a provider that can't take card payments |
| `400 invalid_collect` | `collect` asks for something it can't. `field` names the part |
| `409 no_payout_wallet` | Live mode, and the account has no payout wallet yet |
| `409 commerce_paused` | The account has paused taking payments |
| `403 integration_disabled` | Checkouts, or the API, are turned off for the account |
| `403 merchant_read_only` | The account is suspended or archived |

## Retrieve a checkout

`GET /v1/checkouts/:id`

Returns one of your checkouts in the key's mode, including one deleted in the dashboard (`active: false`). Another account's, or one in the other mode, is `404 not_found`.

Example: cURL

```bash
curl https://pay.railbed.io/v1/checkouts/chk_Mg7tR2vX9kQp4WnZc8Lb \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"
```

## List checkouts

`GET /v1/checkouts`

Returns your active checkouts of every kind in the key's mode, newest first.

| Parameter | Type | Description |
|---|---|---|
| `limit` | integer | 1–100. Default 20 |
| `starting_after` | string | A checkout id from the previous page's `next_cursor` |
| `kind` | string | Only `page`, `pricing_table` or `widget` |

Example: cURL

```bash
curl https://pay.railbed.io/v1/checkouts \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"
```

Example: Response · response 200 OK

```json
{
  "data": [
    {
      "id": "chk_Mg7tR2vX9kQp4WnZc8Lb",
      "object": "checkout",
      "kind": "page",
      "slug": "mug4k7tq2z",
      "url": "https://pay.railbed.io/c/mug4k7tq2z",
      "livemode": false,
      "active": true,
      "name": "Ceramic mug",
      "description": "Hand-thrown, 350 ml.",
      "amount": "18.00",
      "currency": "USD",
      "success_url": "https://mugs.example/thanks",
      "theme": "light",
      "button_label": null,
      "crypto": true,
      "routing": {
        "choice": "smart",
        "provider": null,
        "fallback": true
      },
      "collect": null,
      "options": null,
      "plans": [],
      "created": 1790380525,
      "updated": 1790380525
    }
  ],
  "has_more": false,
  "next_cursor": null
}
```

Changing or deleting a checkout happens in the dashboard. A checkout whose price changes there keeps its slug, so buttons already on your site show the new price.

## Access

Retrieving and listing need the `payments:read` [scope](https://railbed.com/docs/api.md#scopes), which **Read only** keys have. Creating needs `checkouts:write`, which **Full access** keys and agents with full access have.
