RailbedDocs

Checkout sessions

A checkout session is one payment for one order. Create it on your server, send the buyer to its page or start it for your own checkout, and read its payment to fulfil.

The checkout session object

FieldTypeDescription
idstringThe session's id, pay_…. The same id identifies its payment
objectstring"checkout_session"
urlstringThe hosted checkout page for this session. Send the buyer here
statusstringopen, pending, paid, held, failed or expired. See statuses
livemodebooleanfalse for Test mode, true for Live mode
amountstringThe price, as set at creation: "49.00"
currencystringUSD, EUR, GBP, CAD or AUD
descriptionstringWhat the buyer is paying for, shown on the checkout
referencestring or nullYour own id for the order
customer_emailstring or nullThe buyer's email, lowercased
createdintegerWhen it was created, in Unix seconds
expires_atintegerWhen it stops accepting new payments: 24 hours after creation
started_atinteger or nullWhen the buyer (or your server) started it. Set once
metadataobject or nullYour key-value pairs, returned unchanged

Create a checkout session

POST/v1/checkout_sessions

Creates a session for one order. Nothing is charged and no provider is contacted until the buyer starts paying. Send an Idempotency-Key so a retry returns the same session.

FieldTypeDescription
amountstring RequiredThe price as a decimal string with at most two decimals, from "1.00" to "100000.00". "49" and "49.0" become "49.00". Numbers, exponents and negative values are refused
currencystring RequiredUSD, EUR, GBP, CAD or AUD, in any letter case
descriptionstring RequiredWhat the buyer is paying for, up to 120 characters
customer_emailstring or nullThe buyer's email. Optional here, but needed before the session can start
referencestring or nullYour order id, up to 120 characters. Returned on the payment and every webhook. Not unique: Railbed doesn't stop two sessions sharing one
metadataobject or nullUp to 20 keys (1–40 characters, not starting with __) with string values up to 500 characters. For your own ids, never secrets or card details
success_urlstring or nullWhere the checkout sends the buyer once the payment is confirmed. {PAYMENT_ID} and {REFERENCE} are filled in. Up to 1,000 characters
cancel_urlstring or nullWhere the checkout's "Cancel and return to …" and "Back to …" links lead (they name your business). Up to 1,000 characters

Return URLs must be full http:// or https:// addresses (Live mode: https:// only) with no username or password. In Live mode your account needs a payout wallet first, or the request gets 409 no_payout_wallet.

curl https://pay.railbed.io/v1/checkout_sessions \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_1042" \
  -d '{
    "amount": "49.00",
    "currency": "USD",
    "description": "Pro Membership",
    "reference": "order_1042",
    "customer_email": "buyer@example.com",
    "metadata": { "user_id": "player_1042" },
    "success_url":
      "https://yourstore.com/thanks?order={REFERENCE}&payment={PAYMENT_ID}",
    "cancel_url": "https://yourstore.com/cart"
  }'
Response
{
  "id": "pay_7AAiYH0Ykt11ED4hmfiN",
  "object": "checkout_session",
  "url": "https://pay.railbed.io/p/pay_7AAiYH0Ykt11ED4hmfiN",
  "status": "open",
  "livemode": false,
  "amount": "49.00",
  "currency": "USD",
  "description": "Pro Membership",
  "reference": "order_1042",
  "customer_email": "buyer@example.com",
  "created": 1790380525,
  "expires_at": 1790466925,
  "started_at": null,
  "metadata": { "user_id": "player_1042" }
}
201 Created

A retry with the same Idempotency-Key and body answers 200 OK with the same session.

Retrieve a checkout session

GET/v1/checkout_sessions/:id

Returns a session of yours in the key's mode. Another account's session, or one in the other mode, is 404 not_found. Reading a session past its expires_at marks it expired.

curl https://pay.railbed.io/v1/checkout_sessions/pay_7AAiYH0Ykt11ED4hmfiN \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"

The response is the checkout session object. To fulfil, read the payment instead: it adds the payment and settlement details.

Start a checkout session

POST/v1/checkout_sessions/:id/start

For your own checkout: starts the session as the buyer would on the hosted page, and returns the card providers that can take it, each with a handoff_url to open in the buyer's browser. Starting assigns the payment's deposit address and locks the fee and the order's value in USD.

FieldTypeDescription
customer_emailstringThe buyer's email. Optional when the session already has one; a new one replaces it
countrystringThe buyer's two-letter country code (US, DE), any letter case. Optional. Use the buyer's country, never your server's

Send {} when the saved email is enough.

curl -X POST \
  https://pay.railbed.io/v1/checkout_sessions/pay_7AAiYH0Ykt11ED4hmfiN/start \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "country": "US" }'
Response
{
  "id": "pay_7AAiYH0Ykt11ED4hmfiN",
  "object": "checkout_session",
  "url": "https://pay.railbed.io/p/pay_7AAiYH0Ykt11ED4hmfiN",
  "status": "open",
  "livemode": false,
  "amount": "49.00",
  "currency": "USD",
  "description": "Pro Membership",
  "reference": "order_1042",
  "customer_email": "buyer@example.com",
  "created": 1790380525,
  "expires_at": 1790466925,
  "started_at": 1790380611,
  "metadata": { "user_id": "player_1042" },
  "country": "US",
  "providers": [
    {
      "id": "stripe",
      "name": "Stripe",
      "note": "Card, Apple Pay or Google Pay",
      "recommended": true,
      "handoff_url": "https://pay.railbed.io/go/pay_7AAiYH0Ykt11ED4hmfiN?provider=stripe"
    },
    {
      "id": "cashapp",
      "name": "Cash App",
      "note": "Cash App balance or card",
      "recommended": false,
      "handoff_url": "https://pay.railbed.io/go/pay_7AAiYH0Ykt11ED4hmfiN?provider=cashapp"
    }
  ]
}
200 OK

The response is the session with two more fields:

FieldTypeDescription
countrystring or nullThe country you sent, uppercased
providersarrayThe providers that can take this payment, best match first. Each has id, name, note (a short line on how the buyer pays), recommended (true for one) and handoff_url

Starting again is safe: started_at and the deposit address stay the same. Providers depend on the amount, currency and country, so fetch them when the buyer reaches your checkout, and open a handoff_url only from the buyer's click, in a new tab.

StatusCodeWhen
400invalid_emailThe session has no email and none was sent
400invalid_countrycountry isn't two letters
404not_foundNot a session of yours in this mode
409no_providersNo provider can take this amount and currency now. Nothing was started
409already_paid, held, failedThe payment has finished
409unavailableThe account can't take payments now (Live: no payout wallet)
410expired, canceledThe session can no longer be paid
429rate_limitedMore than about 12 starts a minute
502network_unavailableThe card network didn't answer. Retry in a minute

Updated · This page as Markdown