Skip to main content
BillingCheckouts

Checkouts.

A checkout session is a short-lived intent to collect a stablecoin payment. Create one with a single POST, then redirect the customer to the returned URL or render the embedded widget. Funds settle directly to the merchant wallet specified in the session; OpenSettle never holds them.

Create a session

Four SDKs, one shape. Two modes: payment (one-off) or subscription (pass a priceId to spin up a recurring subscription on first payment). For mode payment, supply exactly one of an inline ad-hoc amount (minor units / cents — the simplest, no invoice needed), a one-time priceId, or an existing invoiceId. The chain + token fix the settlement rail (required for an inline amount or priceId; otherwise inherited from the invoice). That rail must have a verified settlement wallet (see GET /rails). The customer is optional for mode payment — omit customerEmail for a guest checkout.

create-checkout.ts
import { OpenSettle } from "@opensettle/sdk";

const os = new OpenSettle({
  apiKey: process.env.OPENSETTLE_KEY!,
  workspaceId: process.env.OPENSETTLE_WORKSPACE!,
});

const checkout = await os.checkouts.create({
  mode: "payment",
  amount: 19_900,          // minor units — $199.00 (no invoice needed)
  currency: "USD",         // optional — defaults to USD
  chain: "base",
  token: "USDC",
  successUrl: "https://yourapp.com/billing/done",
  cancelUrl:  "https://yourapp.com/billing",
  expiresInMinutes: 30,
  metadata: { order_id: "ord_4118" },
});

// hostedUrl is an absolute URL (changed 2026-05-20); redirect as-is.
return Response.redirect(checkout.hostedUrl, 303);
create_checkout.py
import os
from opensettle import OpenSettle

client = OpenSettle(
    api_key=os.environ["OPENSETTLE_KEY"],
    workspace_id=os.environ["OPENSETTLE_WORKSPACE"],
)

checkout = client.checkouts.create(
    mode="payment",
    amount=19_900,            # minor units — $199.00 (no invoice needed)
    currency="USD",           # optional — defaults to USD
    chain="base",
    token="USDC",
    successUrl="https://yourapp.com/billing/done",   # SDK is camelCase-only (no translation)
    cancelUrl="https://yourapp.com/billing",
    expiresInMinutes=30,
    metadata={"order_id": "ord_4118"},
)

# Redirect the buyer to checkout["hostedUrl"]
create_checkout.go
client := opensettle.NewClient(
  os.Getenv("OPENSETTLE_KEY"),
  opensettle.WithWorkspace(os.Getenv("OPENSETTLE_WORKSPACE")),
)

checkout, err := client.Checkouts.Create(ctx, &opensettle.CreateCheckoutRequest{
  Mode:             "payment",
  Amount:           19_900, // minor units — $199.00 (no invoice needed)
  Currency:         "USD",  // optional — defaults to USD
  Chain:            "base",
  Token:            "USDC",
  SuccessURL:       "https://yourapp.com/billing/done",
  CancelURL:        "https://yourapp.com/billing",
  ExpiresInMinutes: 30,
  Metadata:         map[string]any{"order_id": "ord_4118"},
})

// http.Redirect(w, r, checkout.HostedURL, http.StatusSeeOther)
create_checkout.rs
use opensettle::{ChainId, CheckoutMode, CreateCheckoutRequest, OpenSettle, TokenSymbol};

let client = OpenSettle::builder(
    std::env::var("OPENSETTLE_KEY")?,
    std::env::var("OPENSETTLE_WORKSPACE")?,
)
.build()?;

let checkout = client
    .checkouts()
    .create(&CreateCheckoutRequest {
        mode: CheckoutMode::Payment,
        amount: Some(19_900), // minor units — $199.00 (no invoice needed)
        currency: Some("USD".into()),
        chain: Some(ChainId::Base),
        token: Some(TokenSymbol::USDC),
        success_url: Some("https://yourapp.com/billing/done".into()),
        cancel_url: Some("https://yourapp.com/billing".into()),
        expires_in_minutes: Some(30),
        customer_id: None,
        customer_email: None,
        customer_name: None,
        invoice_id: None,
        price_id: None,
        description: None,
        metadata: None,
    })
    .await?;

The hosted page

The URL we return resolves to https://opensettle.io/checkout/<hostedToken>. The page detects the customer's wallet, prompts for the chain and token (constrained to what you allowed), and shows a live transaction tracker after submit. On confirmation, we redirect to your successUrl unchanged — use metadata or a query param of your own if you need to correlate it back to a checkout.

Expiration

Sessions expire after expiresInMinutes minutes. Default 30, maximum 1,440 (24 hours). After expiration the hosted page returns a "session expired" view and the chain reader ignores any in-flight tx, firing checkout.expired once per session. There's no force-expire endpoint today — set a short expiresInMinutes if you need tight inventory holds.

One-off vs recurring

A mode: "payment" checkout charges exactly one of three things: an existing invoice (invoiceId), a one-time price (priceId), or an inline ad-hoc amount (minor units) — an inline amount needs its own chain + token. Use mode: "subscription" with priceId to spin up a recurring subscription on first payment. The hosted page reads the amount, chain, and token off whichever you pass. For a reusable link that many buyers can pay (instead of a single-use session), reach for a payment link.

Webhooks fired

  • checkout.createdsession created.
  • payment.confirmedchain reader observed the deposit; required confirmations reached and funds are in the merchant wallet.
  • checkout.succeededsession resolved: the deposit landed and the linked invoice or subscription was settled.
  • checkout.expiredTTL elapsed without a confirmed deposit.