Quickstart
Take your first payment in Test mode in about ten minutes. Create a secret key, create a checkout session, pay it as a buyer, and confirm it from your server.
Before you start
You need a Railbed account (sign up takes a minute) and a terminal. Everything below runs in Test mode: no card is charged and no money moves. The same code works in Live mode with a live key.
1. Create a secret key
In the dashboard, switch to Test mode, open Developers and choose Create key. Name it after the server that will use it, for example "Store backend". The key starts with rb_test_ and is shown once: copy it into your server's environment.
export RAILBED_SECRET_KEY="rb_test_…"2. Create a checkout session
A checkout session is one payment for one order: a fixed amount, a currency, and your order's reference. Send an Idempotency-Key so a retried request can never create a second payment.
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",
"success_url": "https://yourstore.com/thanks?order={REFERENCE}"
}'const res = await fetch('https://pay.railbed.io/v1/checkout_sessions', {
method: 'POST',
headers: {
Authorization: `Bearer ${process.env.RAILBED_SECRET_KEY}`,
'Content-Type': 'application/json',
'Idempotency-Key': 'order_1042',
},
body: JSON.stringify({
amount: '49.00',
currency: 'USD',
description: 'Pro Membership',
reference: 'order_1042',
customer_email: 'buyer@example.com',
success_url: 'https://yourstore.com/thanks?order={REFERENCE}',
}),
});
const session = await res.json();
console.log(session.url);import os, requests
session = requests.post(
"https://pay.railbed.io/v1/checkout_sessions",
headers={
"Authorization": f"Bearer {os.environ['RAILBED_SECRET_KEY']}",
"Idempotency-Key": "order_1042",
},
json={
"amount": "49.00",
"currency": "USD",
"description": "Pro Membership",
"reference": "order_1042",
"customer_email": "buyer@example.com",
"success_url": "https://yourstore.com/thanks?order={REFERENCE}",
},
timeout=15,
).json()
print(session["url"])<?php
$ch = curl_init('https://pay.railbed.io/v1/checkout_sessions');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('RAILBED_SECRET_KEY'),
'Content-Type: application/json',
'Idempotency-Key: order_1042',
],
CURLOPT_POSTFIELDS => json_encode([
'amount' => '49.00',
'currency' => 'USD',
'description' => 'Pro Membership',
'reference' => 'order_1042',
'customer_email' => 'buyer@example.com',
'success_url' => 'https://yourstore.com/thanks?order={REFERENCE}',
]),
]);
$session = json_decode(curl_exec($ch), true);
echo $session['url'];The response is the new session. Save its id (pay_…) with your order.
{
"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": null
}3. Pay as a buyer
Open the session's url in a browser. Continue with the email, pick a card provider and choose Pay. In Test mode the provider's page is replaced by Railbed's test provider, where Simulate successful payment stands in for entering a card. The checkout tab then shows the payment as paid and takes the buyer to your success_url, with {REFERENCE} filled in.
4. Confirm the payment from your server
The redirect is for the buyer's comfort, not proof of payment. Confirm it from your server, with the same key:
curl https://pay.railbed.io/v1/payments/pay_7AAiYH0Ykt11ED4hmfiN \
-H "Authorization: Bearer $RAILBED_SECRET_KEY"const res = await fetch(`https://pay.railbed.io/v1/payments/${paymentId}`, {
headers: { Authorization: `Bearer ${process.env.RAILBED_SECRET_KEY}` },
});
const payment = await res.json();
if (payment.status === 'paid') fulfil(payment.reference);payment = requests.get(
f"https://pay.railbed.io/v1/payments/{payment_id}",
headers={"Authorization": f"Bearer {os.environ['RAILBED_SECRET_KEY']}"},
timeout=15,
).json()
if payment["status"] == "paid":
fulfil(payment["reference"])<?php
$ch = curl_init('https://pay.railbed.io/v1/payments/' . rawurlencode($paymentId));
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => ['Authorization: Bearer ' . getenv('RAILBED_SECRET_KEY')],
]);
$payment = json_decode(curl_exec($ch), true);
if ($payment['status'] === 'paid') fulfil($payment['reference']);{
"id": "pay_7AAiYH0Ykt11ED4hmfiN",
"object": "payment",
"status": "paid",
"livemode": false,
"amount": "49.00",
"currency": "USD",
"reference": "order_1042",
"paid_at": 1790381342,
"provider": "stripe",
"settlement": {
"coin": "polygon_usdc",
"value_coin": "47.53",
"merchant_received": "44.915850",
"txid_in": "0x0c65…582e",
"txid_out": "0x8202…356f",
"payout_wallet": "0xF977814e90dA44bFA03b6295A0616a897441aceC"
}
}Check that status is paid and that the id, amount, currency and reference match the order you saved, then fulfil it once.
5. Get told instead of asking
Polling works, but webhooks tell you the moment something happens. In Developers, choose Add endpoint and enter your server's https:// address (while you build on your own computer, use a tunnel). Copy the signing secret, then choose Send test event to see exactly what your server receives. Webhooks covers the events and verifying signatures.
Next
- Fulfil orders safelyThe checks that make fulfilment correct even with retries, late payments and reviews.
- Your own checkoutShow card providers in your own screen instead of redirecting.
- TestingSimulate underpayments and declines, and send sample events.
- Going liveThe short checklist before real payments.