Payment links

Create, list, read and cancel one-off payment links from your own code. The same links you make in the dashboard, with the same rules, each one payment for one payer.

On this page

A payment link asks one payer for one amount: an invoice, a deposit, a one-off order. It's the same link you can make under Payment links in the dashboard, and it shows up there. A link is one payment, so its id is the payment's id: read its settlement with Retrieve a payment. For a price many buyers can pay, use a checkout instead.

FieldTypeDescription
idstringThe link's id, pay_…. The same id identifies its payment
objectstring"payment_link"
urlstringThe payer's page. Send this to them
tracking_urlstring or nullA page that shows only the link's status, without the payer's details. Safe to share with anyone who should follow it
statusstringopen, pending, paid, held, failed or expired. See statuses
livemodebooleanfalse for Test mode, true for Live mode
amountstringThe amount asked for: "250.00"
currencystringUSD, EUR, GBP, CAD or AUD
descriptionstringWhat the payment is for, shown to the payer
referencestring or nullYour own id, such as an invoice number
customer_namestring or nullWho the link is for
customer_emailstring or nullTheir email, filled in on their page, lowercased
memostring or nullYour note to the payer
success_urlstring or nullWhere the payer lands once paid
collectobject or nullWhat the payer's page asks for besides their email, or null for nothing more. See The collect field
order_idstring or nullThe order the link belongs to, ord_…
createdintegerWhen it was created, in Unix seconds
expires_atintegerWhen it stops accepting new payments
started_atinteger or nullWhen the payer started paying
paid_atinteger or nullWhen it was paid
canceled_atinteger or nullWhen you canceled it, in Unix seconds
A payment link
{
  "id": "pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "object": "payment_link",
  "url": "https://pay.railbed.io/p/pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "tracking_url": "https://pay.railbed.io/t/Tq3nV8xK2mRz7LpW4cYb5sDh",
  "status": "open",
  "livemode": false,
  "amount": "250.00",
  "currency": "USD",
  "description": "Consulting, September",
  "reference": "INV-0042",
  "customer_name": "Ada Lovelace",
  "customer_email": "ada@example.com",
  "memo": "Thanks for your business.",
  "success_url": null,
  "collect": null,
  "order_id": "ord_Hn6pW2zQ8rKt3VmXc9La",
  "created": 1790380525,
  "expires_at": 1791590125,
  "started_at": null,
  "paid_at": null,
  "canceled_at": null
}
200 OK

POST/v1/payment_links

Creates a link in the key's mode. Nothing is charged and no provider is contacted until the payer starts paying, so a long expiry costs nothing.

ParameterTypeDescription
amountstring RequiredA decimal string from "1.00" to "100000.00", at most two decimals
currencystring RequiredUSD, EUR, GBP, CAD or AUD, in any letter case
descriptionstring RequiredWhat it's for, up to 120 characters
customer_namestringWho it's for, up to 80 characters
customer_emailstringTheir email, filled in on their page
customer_phonestringTheir phone number, up to 40 characters, kept on the order
shipping_address, billing_addressobjectTheir addresses, if you have them: line1, line2, city, region, postal_code and country (two letters). Kept on the order and filled in for the payer, under customer_name. region is a code for the US, Canada and Australia (NY)
referencestringYour own id, up to 64 characters
memostringA note to the payer, up to 500 characters
expires_in_daysinteger1–30. Default 7
success_urlstringWhere the payer lands once paid. Live mode needs https://
collectobjectWhat the payer's page asks for besides their email, as on a checkout session
curl https://pay.railbed.io/v1/payment_links \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": "250.00",
    "currency": "USD",
    "description": "Consulting, September",
    "customer_name": "Ada Lovelace",
    "customer_email": "ada@example.com",
    "reference": "INV-0042",
    "memo": "Thanks for your business.",
    "expires_in_days": 14
  }'
Response
{
  "id": "pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "object": "payment_link",
  "url": "https://pay.railbed.io/p/pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "tracking_url": "https://pay.railbed.io/t/Tq3nV8xK2mRz7LpW4cYb5sDh",
  "status": "open",
  "livemode": false,
  "amount": "250.00",
  "currency": "USD",
  "description": "Consulting, September",
  "reference": "INV-0042",
  "customer_name": "Ada Lovelace",
  "customer_email": "ada@example.com",
  "memo": "Thanks for your business.",
  "success_url": null,
  "collect": null,
  "order_id": "ord_Hn6pW2zQ8rKt3VmXc9La",
  "created": 1790380525,
  "expires_at": 1791590125,
  "started_at": null,
  "paid_at": null,
  "canceled_at": null
}
201 Created

The link follows the dashboard's rules, and an error's field names the parameter you sent, such as expires_in_days or shipping_address.postal_code. This endpoint ignores Idempotency-Key: after a timeout, list your links by reference before creating another.

ErrorCause
400 invalid_amountamount isn't a decimal string from "1.00" to "100000.00"
400 invalid_currencycurrency isn't one of the five
400 missing_description, 400 too_longdescription is empty, or a text field is over its limit
400 invalid_customer_name, 400 invalid_customer_phone, 400 invalid_reference, 400 invalid_memoThat field isn't a string
400 invalid_emailcustomer_email isn't an email address (send null, or leave it out, for none)
400 invalid_addressAn address is missing a line, city, region or postal code its country needs. field names it
400 invalid_expiryexpires_in_days isn't a whole number from 1 to 30 (a JSON number, not a string)
400 invalid_urlsuccess_url isn't a full address, has a username or password, or isn't https:// in Live mode
400 invalid_collectcollect asks for something it can't. field names the part
409 no_payout_walletLive mode, and the account has no payout wallet yet
409 commerce_pausedThe account has paused taking payments
403 integration_disabledPayment links, or the API, are turned off for the account
403 merchant_read_onlyThe account is suspended or archived

GET/v1/payment_links/:id

Returns one of your links in the key's mode. Another account's, one in the other mode, or a payment that isn't a link is 404 not_found. A link past its expires_at reads as expired.

cURL
curl https://pay.railbed.io/v1/payment_links/pay_Lk4mQ8vR2xTn7WcZs1Pb \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"

GET/v1/payment_links

Returns your links in the key's mode, newest first. The parameters are those of List payments.

ParameterTypeDescription
limitinteger1–100. Default 20
starting_afterstringA link id from the previous page's next_cursor
statusstringopen, pending, paid, held, failed or expired (a canceled link is expired)
referencestringOnly links with exactly this reference
created_gte, created_lteintegerOnly links created in this range, in Unix seconds, inclusive
cURL
curl "https://pay.railbed.io/v1/payment_links?status=open" \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"
Response
{
  "data": [
    {
      "id": "pay_Lk4mQ8vR2xTn7WcZs1Pb",
      "object": "payment_link",
      "url": "https://pay.railbed.io/p/pay_Lk4mQ8vR2xTn7WcZs1Pb",
      "tracking_url": "https://pay.railbed.io/t/Tq3nV8xK2mRz7LpW4cYb5sDh",
      "status": "open",
      "livemode": false,
      "amount": "250.00",
      "currency": "USD",
      "description": "Consulting, September",
      "reference": "INV-0042",
      "customer_name": "Ada Lovelace",
      "customer_email": "ada@example.com",
      "memo": "Thanks for your business.",
      "success_url": null,
      "collect": null,
      "order_id": "ord_Hn6pW2zQ8rKt3VmXc9La",
      "created": 1790380525,
      "expires_at": 1791590125,
      "started_at": null,
      "paid_at": null,
      "canceled_at": null
    }
  ],
  "has_more": false,
  "next_cursor": null
}
200 OK

POST/v1/payment_links/:id/cancel

Closes a link nobody has started paying, as Cancel link does in the dashboard. No body is needed.

cURL
curl -X POST https://pay.railbed.io/v1/payment_links/pay_Lk4mQ8vR2xTn7WcZs1Pb/cancel \
  -H "Authorization: Bearer $RAILBED_SECRET_KEY"
Response
{
  "id": "pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "object": "payment_link",
  "url": "https://pay.railbed.io/p/pay_Lk4mQ8vR2xTn7WcZs1Pb",
  "tracking_url": "https://pay.railbed.io/t/Tq3nV8xK2mRz7LpW4cYb5sDh",
  "status": "expired",
  "livemode": false,
  "amount": "250.00",
  "currency": "USD",
  "description": "Consulting, September",
  "reference": "INV-0042",
  "customer_name": "Ada Lovelace",
  "customer_email": "ada@example.com",
  "memo": "Thanks for your business.",
  "success_url": null,
  "collect": null,
  "order_id": "ord_Hn6pW2zQ8rKt3VmXc9La",
  "created": 1790380525,
  "expires_at": 1791590125,
  "started_at": null,
  "paid_at": null,
  "canceled_at": 1790384125
}
200 OK

It follows the rules of Cancel a checkout session: the link becomes expired with canceled_at set and sends payment.canceled; canceling again returns the same link; once the payer has gone to a card provider it answers 409 not_cancelable, because their payment may be on its way. Money that arrives after a cancel still settles the link.

Access

Retrieving and listing need the payments:read scope, which Read only keys have. Creating and canceling need checkouts:write, which Full access keys and agents with full access have.

Updated · This page as Markdown