Docs / Quickstart

Quickstart.

Sign up, register a payout address, accept a test payment, handle the webhook. Five minutes.

1. Sign up.

Auth is GitHub OAuth only. Visit settle.xxx/signup and authorize the app. You’re dropped into test mode with a dashboard and a generated sk_test_… key. Test mode runs on testnet contracts so you can settle real on-chain transactions without spending real money.

2. Register a payout address.

Settle is non-custodial. You tell us where to send funds; we never hold them. Register one address per chain you want to accept. The dashboard walks you through it, or your agent can call register_payout_address via MCP. You sign a one-time challenge with the wallet to prove you own it.

Test mode accepts any address that passes OFAC screening. Live mode adds the same screening at signup. A hit on either list rejects the address — see Security.

3. Create an invoice.

An invoice is a single payable thing. Amounts are denominated in USD; the server computes the per-chain payable amounts and writes them into payment_options.

terminal
curl -X POST https://api.settle.xxx/v1/invoices \
  -H "Authorization: Bearer sk_test_..." \
  -H "Content-Type: application/json" \
  -d '{
    "amount_usd": 49.00,
    "customer_email": "buyer@example.com",
    "metadata": { "order_id": "ord_123" },
    "return_url": "https://yoursite.com/orders/success",
    "cancel_url": "https://yoursite.com/cart"
  }'

The response:

response
{
  "id": "inv_01HZX9V0K1Q3Y2T7M3N4D5R8S0",
  "checkout_url": "https://pay.settle.xxx/c/inv_01HZX9V0K1Q3Y2T7M3N4D5R8S0",
  "status": "open",
  "expires_at": "2026-04-27T12:30:00Z",
  "payment_options": [
    { "currency": "USDC", "chain": "base", "amount": "49.000000", "network_fee_estimate_usd": 0.01 }
  ]
}

Redirect the customer to checkout_url. Settle hosts the page at pay.settle.xxx and you can CNAME pay.yourdomain.com at it for white-labeled checkout.

4. Receive payment.

The customer connects a wallet — MetaMask, Phantom, Coinbase, Binance — or scans a QR for a per-invoice deposit address. The router contract executes one atomic transaction:

  • 99.5% of the amount transfers to your registered payout address.
  • 0.5% transfers to the Settle treasury.
  • The contract emits InvoicePaid(invoiceId, payer, merchant, amount, fee).

Funds are now in your wallet. Settle never holds them. There is no clearing window, no rolling reserve, no payout schedule.

In test mode you can fast-forward this with simulate_payment(invoice_id) — that flips the invoice to paid and fires the webhook just like a real payment would.

5. Handle the webhook.

Register a webhook URL pointing at your server. We sign every delivery with HMAC-SHA256 over the raw request body. Verify the signature before trusting the payload.

app/api/webhooks/settle/route.ts
// app/api/webhooks/settle/route.ts
import { NextResponse } from "next/server";
import { createHmac, timingSafeEqual } from "node:crypto";

export async function POST(req: Request) {
  const signature = req.headers.get("settle-signature");
  if (!signature) return new NextResponse("missing signature", { status: 400 });

  const raw = await req.text();
  const expected = createHmac("sha256", process.env.SETTLE_WEBHOOK_SECRET!)
    .update(raw)
    .digest("hex");

  const a = Buffer.from(signature, "hex");
  const b = Buffer.from(expected, "hex");
  if (a.length !== b.length || !timingSafeEqual(a, b)) {
    return new NextResponse("bad signature", { status: 401 });
  }

  const event = JSON.parse(raw);
  if (event.type === "invoice.paid") {
    // Mark order paid. event.data.invoice has id, amount_usd, payment_tx, metadata.
    console.log("paid", event.data.invoice.id);
  }
  return NextResponse.json({ received: true });
}

The most important event is invoice.paid — that’s the moment funds settled on chain and you should fulfill the order. Full event list and retry semantics are in Webhooks.

Going live.

Flip the dashboard switch from test to live. The dashboard issues a new sk_live_… key — swap it into your env vars. Live keys rotate automatically every 90 days with a 7-day grace window where both work. If you deployed via the Vercel or Netlify integration the new key is delivered for you.

Then create a real invoice. The first paid invoice is the moment you know it works.

Stuck? Pattern docs cover the four common frameworks. FAQ covers the things people ask twice.

Was this helpful?