Skip to content

RapidCents

Embedded checkout

Payment UI runs inside an iframe on your site. The supported browser integration uses RapidCents checkout.js (RapidCentsCheckout) to call checkout/create with ui_mode: embedded and mount the iframe—see checkout.js below (same pattern as rapidcents-iframe-checkout/index.php in this repo).

When to use

  • You want the shopper to stay on your domain and layout.
  • Subscriptions: same API with mode: subscriptionSubscription checkout.

For full-page redirect instead, see Hosted checkout.

Staging/production hosts: Overview → APIs.

Required API

OAuth access token, then:

POST {API origin}/api/{business_id}/checkout/create

Use the API origin for your environment; {business_id} is your business id.

Auth: Overview → token refresh.

All checkout API requests require:

  • Authorization: Bearer <access_token> — from OAuth (see Overview → OAuth).
  • Origin — HTTPS origin of your app (for example https://shop.example.com). It must match the origin registered for your API client in RapidCents.
  • Content-Type: application/json and Accept: application/json unless the API specifies otherwise.

Never expose tokens in the browser

Create checkout sessions on your server only. Do not send the access token to client-side JavaScript.

HTTP headers

Required on every checkout/create call from your backend.

Authorization string
Required

Access token from POST …/oauth/token. Server only.

Bearer <token> · e.g. Bearer eyJhbG…

Origin string
Required

Your app’s public HTTPS origin; must match the OAuth client registration.

HTTPS URL · e.g. https://shop.example.com

Content-Type string
Required

JSON request body.

application/json

Accept string
Required

JSON response.

application/json

Required & common parameters

Path parameters

In the URL path (not the JSON body). Pattern: POST {API origin}/api/{business_id}/checkout/create

business_id string (UUID)
Required

Business id for this API host/environment.

UUID string · e.g. "550e8400-e29b-41d4-a716-446655440000"

Payment session (mode: payment)

One-time charge: ui_mode, amounts, return URLs, optional customer fields. Same shape for embedded and hosted.

ui_mode string
Required

Iframe on your site vs full-page redirect. This guide: embedded.

embedded, hosted · e.g. "embedded"

mode string
Required

Use payment for one-time checkout. For subscription, see the Subscription checkout guide.

payment, subscription · e.g. "payment"

amount_total number
Required

Total in major units; align with line_items when present.

≥ 0; typically 2 decimals · e.g. 49.99

currency string
Required

ISO 4217; must be enabled for your merchant account.

e.g. CAD, USD

amount_subtotal number

Pre-tax/discount subtotal when itemizing (often sum of line totals).

≥ 0; 2 decimals · e.g. 45.00

line_items array

Optional cart lines; omit for a single lump sum.

Array (see line items section) · e.g. [{ "name": "…", … }]

success_url string (URL)
Required

HTTPS URL after success; add your own id in the query if needed. Confirm payment server-side before fulfillment.

Absolute https:// · e.g. "https://app.example.com/checkout/success?session=42"

cancel_url string (URL)
Required

HTTPS return if the shopper abandons checkout.

Absolute https:// · e.g. "https://app.example.com/checkout/cancel"

customer_email string

Pre-fills email in checkout when set.

Email · e.g. "buyer@example.com"

customer_name string

Pre-fills name when set.

Display name · e.g. "Alex Rivera"

Line item objects (line_items[])

Multiple lines for carts or itemized receipts; one object is enough for a single SKU. Omit or send one row when you do not need a breakdown.

name string
Required

Line label on the receipt.

Non-empty string · e.g. "API subscription (monthly)"

quantity number
Required

Units on this line.

Typically ≥ 1 · e.g. 2

unit_amount number
Required

Unit price in major units (usually 2 decimals).

≥ 0; 2 decimals · e.g. 12.50

total number
Required

Line total (qty × unit after line adjustments); should roll up to order totals.

≥ 0; 2 decimals · e.g. 25.00

Example request

cURL (staging)
curl -sS -X POST "https://uatstage00-api.rapidcents.com/api/YOUR_BUSINESS_ID/checkout/create" \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json" \
  -H "Origin: https://your-https-app.example.com" \
  -d '{
    "ui_mode": "embedded",
    "mode": "payment",
    "amount_total": 49.99,
    "amount_subtotal": 49.99,
    "currency": "CAD",
    "success_url": "https://your-https-app.example.com/thank-you?order=1",
    "cancel_url": "https://your-https-app.example.com/cart",
    "customer_email": "buyer@example.com",
    "line_items": [
      { "name": "Item", "quantity": 1, "unit_amount": 49.99, "total": 49.99 }
    ]
  }'

Example response

HTTP 200, checkout_session.checkout_url for the iframe:

checkout_session
{
    "ok": true,
    "message": "Checkout session created successfully",
    "status": "PENDING",
    "checkout_session": {
        "id": "550e8400-e29b-41d4-a716-446655440000",
        "token": "a1b2c3d4e5f6789012345678901234567890abcdef0123456789abcdef012345",
        "checkout_url": "https://checkout.rapidcents.com/session/a1b2c3d4\u2026/embedded",
        "allowed_origins": [
            "https://shop.example.com"
        ],
        "expires_at": "2026-04-21T18:00:00.000000Z",
        "session_status": "PENDING",
        "payment_status": "UNPAID",
        "amount_total": 49.99,
        "amount_subtotal": 49.99,
        "amount_tax": 0,
        "amount_discount": 0,
        "surcharge": false,
        "amount_surcharge": 0,
        "surcharge_rate": null,
        "currency": "CAD",
        "mode": "payment",
        "description": null,
        "customer_id": null,
        "customer_email": "buyer@example.com",
        "customer_name": "Alex Rivera",
        "client_reference_id": null,
        "success_url": "https://shop.example.com/thank-you?order=1",
        "cancel_url": "https://shop.example.com/cart",
        "return_url": null,
        "metadata": [],
        "ui_mode": "embedded",
        "created_at": "2026-04-21T12:00:00.000000Z",
        "billing_address_collection": null,
        "shipping_address_collection": null,
        "billing_address": null,
        "shipping_address": null,
        "consent": null,
        "consent_collection": null,
        "phone_number_collection": null,
        "line_items": [
            {
                "name": "Premium plan (monthly)",
                "quantity": 1,
                "unit_amount": 49.99,
                "total": 49.99
            }
        ],
        "discounts": null,
        "apply_discount": null,
        "total_details": null,
        "invoice_creation": null,
        "tax_id_collection": null
    },
    "transaction": null
}
  • checkout_session.token — store as your external session or order correlation id.
  • checkout_session.checkout_url — load in an iframe, new tab, or follow as a redirect depending on the mode.

Required for embedded checkout/create: checkout.js

RapidCents ships checkout.js on the same host as the Checkout API. It exposes window.RapidCentsCheckout: call RapidCentsCheckout.init({ … }) once, then RapidCentsCheckout.create({ … }) with the same JSON fields you would send to POST …/checkout/create (including ui_mode: 'embedded'). The library POSTs the session from the browser, then mounts the checkout iframe inside the element you name with containerId. It listens for postMessage (rc:checkout_height, rc:checkout_result) and can verify the session if you configure verifySessionUrl.

URLs:

  • Staging: https://uatstage00-api.rapidcents.com/js/checkout.js
  • Production: https://api.rapidcents.com/js/checkout.js

Stubborn Attachments

$20.00

Embedded · checkout.js (required)

<?php

declare(strict_types=1);

// Example — align field names with payment-testing-app's CreateCheckoutRequest
// (checkout_type + customer_*) and keep amounts / line item titles on the server.
// routes/web.php
Route::post('/create-checkout-session', [ShopCheckoutController::class, 'store']);

// app/Http/Controllers/ShopCheckoutController.php
public function store(Request $request)
{
    $validated = $request->validate([
        'checkout_type' => 'required|in:embedded,hosted',
        'customer_name' => 'nullable|string|max:255',
        'customer_email' => 'required|email',
    ]);

    // Prices and line item text must come from your DB/catalog — not unchecked POST fields.
    $itemName = 'Stubborn Attachments';
    $unit = 20.00;

    $res = Http::withToken($this->token())
        ->acceptJson()
        ->withHeaders(['Origin' => config('app.url')])
        ->post("{$this->apiBase}/api/{$this->businessId}/checkout/create", [
            'ui_mode' => $validated['checkout_type'] === 'embedded' ? 'embedded' : 'hosted',
            'mode' => 'payment',
            'amount_total' => $unit,
            'amount_subtotal' => $unit,
            'currency' => 'CAD',
            'success_url' => route('shop.success', [], true),
            'cancel_url' => route('shop.cancel', [], true),
            'customer_email' => $validated['customer_email'],
            'line_items' => [
                [
                    'name' => $itemName,
                    'quantity' => 1,
                    'unit_amount' => $unit,
                    'total' => $unit,
                ],
            ],
        ]);

    $data = $res->json();
    if (! ($data['ok'] ?? false)) {
        abort(422, $data['message'] ?? 'Checkout create failed');
    }

    return view('pay', [
        'checkoutUrl' => $data['checkout_session']['checkout_url'],
    ]);
}
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Buy cool new product</title>
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="/style.css">
  <!-- Required: checkout.js from your RapidCents API origin -->
  <script src="https://api.rapidcents.com/js/checkout.js"></script>
</head>
<body>
  <section style="max-width:28rem;margin:2rem auto;font-family:system-ui,sans-serif;">
    <div style="display:flex;gap:1rem;align-items:center;padding:1rem;border:1px solid #e2e8f0;border-radius:12px;">
      <img src="https://i.imgur.com/EHyR2nP.png" alt="Product" width="96" height="96" style="border-radius:8px;">
      <div>
        <h3 style="margin:0 0 0.25rem;font-size:1.1rem;">Stubborn Attachments</h3>
        <h5 style="margin:0;color:#64748b;font-weight:600;">$20.00</h5>
      </div>
    </div>
    <form action="/create-checkout-session" method="POST" style="margin-top:1.25rem;">
      <input type="hidden" name="_token" value="REPLACE_CSRF_TOKEN">
      <input type="hidden" name="checkout_type" value="embedded">
      <label for="cemail" style="display:block;font-size:0.8rem;color:#64748b;margin-top:0.5rem;">Email</label>
      <input id="cemail" type="email" name="customer_email" value="buyer@example.com" required
        style="width:100%;margin-top:0.25rem;padding:0.5rem 0.65rem;border:1px solid #e2e8f0;border-radius:8px;box-sizing:border-box;">
      <input type="hidden" name="customer_name" value="">
      <button type="submit" id="checkout-button"
        style="margin-top:0.75rem;width:100%;padding:0.75rem 1rem;border-radius:8px;border:0;background:#4f46e5;color:#fff;font-weight:600;cursor:pointer;">
        Checkout
      </button>
    </form>
    <p style="margin-top:1rem;font-size:0.8rem;color:#64748b;">
      Same field names as <code>CreateCheckoutRequest</code> in payment-testing-app (<code>checkout_type</code>, <code>customer_email</code>, optional <code>customer_name</code>). The server must set <code>amount_*</code> and <code>line_items</code> — do not take prices from the browser.
    </p>
  </section>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Thank you</title>
</head>
<body style="font-family:system-ui,sans-serif;padding:2rem;">
  <h1>Thanks for your order</h1>
  <p>Keep this page idempotent — <code>success_url</code> is not proof of payment. Confirm with your server / webhooks.</p>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Checkout canceled</title>
</head>
<body style="font-family:system-ui,sans-serif;padding:2rem;">
  <h1>Checkout canceled</h1>
  <p><a href="/">Return to store</a></p>
</body>
</html>

Pattern: {API origin}/js/checkout.js. Reference implementation in this monorepo: rapidcents-iframe-checkout/index.php (loads checkout.js, calls init / create with form data).

Browser usage, success_url / cancel_url, security, and common errors are documented once in Checkout overview → Browser / frontend, Success & cancel URLs, Security, and Common errors.