Checkout Page Integration

Redirect buyers to a hosted checkout page — the same pattern as Stripe, PayPal, and Razorpay.

Flow

Merchant Server                    Stableyard                     Buyer
─────────────────────────────────────────────────────────────────────────
POST /v2/sessions                  Creates ses_xxx
  Authorization: sy_secret_xxx     Returns { id, checkoutUrl }
  { amount, destination }

Redirect buyer to ──────────────►  pay.stableyard.fi/ses_xxx

                                   Checkout page calls:
                                   GET /sessions/ses_xxx (NO auth)
                                   → gets amount, currency, status

                                   Shows payment UI ──────────────► Buyer picks chain
                                                                    Buyer pays

                                   Webhook: payment.settled ──────► Merchant server
                                   Redirect to successUrl           marks order paid

Create Session on Your Server

curl -X POST https://api.stableyard.fi/v2/sessions \
  -H "Authorization: Bearer sy_secret_*" \
  -H "Idempotency-Key: order-123" \
  -H "Content-Type: application/json" \
  -d '{
    "amount": 25000000,
    "destination": "coffeeshop@stableyard",
    "description": "Order #123",
    "metadata": { "orderId": "123" },
    "successUrl": "https://yourstore.com/success?order=123",
    "cancelUrl": "https://yourstore.com/cancel?order=123"
  }'
Then redirect the buyer to the checkoutUrl in the response.

Why No Auth on GET

The session ID is unguessable (like Stripe’s cs_xxx). Knowing the ID = having access. The checkout page reads:
{
  "object": "session",
  "id": "ses_xxx",
  "status": "open",
  "amount": 25000000,
  "currency": "USDC",
  "amountFormatted": "25.00",
  "fees": { "total": 62500, "totalFormatted": "0.06" },
  "destination": { "chain": "base", "token": "USDC" },
  "checkoutUrl": "https://pay.stableyard.fi/ses_xxx",
  "expiresAt": 1711065600
}
No metadata, no wallet, no accountId, no partnerId. Only payment-safe fields.

Checkout Page Internals

1. Extract session ID from URL: /ses_xxx
2. Fetch session (NO auth): GET /v2/sessions/ses_xxx
3. Check status: expired → show "Payment expired", settled → "Already paid"
4. Get chains: GET /v2/network/chains
5. Connect wallet → GET /v2/network/portfolio?address=BUYER_WALLET
6. Buyer picks chain → preview quote (sy_pub_*)
7. Buyer confirms → commit with executionMode: "boosted"
8. Execute payment → submit tx hash (sy_secret_*)
9. Poll until settled → redirect to successUrl