Skip to main content
Getting startedQuickstart

Accept your first stablecoin payment.

5 minutes·Test mode · No real funds
Three integration paths

OpenSettle exposes three independent entry points. The walkthrough below covers the invoice + checkout path; the other two link out to their own short guides.

1. Install the SDK

Typed SDKs ship in Node, Python, Go, and Rust. Or use the REST API directly from any HTTP client.

bash
# Node
npm install @opensettle/sdk

# Python
pip install opensettle

# Go
go get github.com/OpenSettle/opensettle-sdk-go

# Rust
cargo add opensettle

2. Create an invoice + hosted checkout

Two calls: register the customer, then build a checkout session that sends them to a hosted page where they pay with USDC on Base.

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

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

const customer = await os.customers.create({
  email: "ada@example.com",
  name: "Ada Lovelace",
});

const invoice = await os.invoices.create({
  customerId: customer.id,
  currency: "USD",                          // optional — defaults to USD
  chain: "base",
  token: "USDC",
  lineItems: [{ description: "Pro plan", quantity: 1, unitAmountMinor: 19_900 }],
});

const checkout = await os.checkouts.create({
  mode: "payment",
  customerId: customer.id,
  invoiceId: invoice.id,
  successUrl: "https://yourapp.com/success",
  cancelUrl: "https://yourapp.com/pricing",
});

// Redirect the buyer to the hosted checkout page.
// hostedUrl is already absolute (https://opensettle.io/checkout/...);
// just hand it to Response.redirect verbatim.
return Response.redirect(checkout.hostedUrl, 303);

3. Handle the webhook

Verify the HMAC signature, then fulfil the order. The SDK's verifier is constant-time and rejects stale or tampered deliveries.

webhook.ts
import { verifyWebhook, WebhookVerificationError } from "@opensettle/sdk";

app.post("/webhook", async (req, res) => {
  try {
    const { data } = verifyWebhook<{ id: string; type: string; data: any }>({
      rawBody: req.rawBody,                       // exact bytes — not parsed JSON
      signatureHeader: req.header("x-opensettle-signature"),
      secret: process.env.WEBHOOK_SIGNING_SECRET!,
    });

    if (data.type === "payment.confirmed") {
      const payment = data.data;
      await grantAccess(payment.customerId);
      await sendReceipt(payment.customerId, payment.id);
    }
    res.sendStatus(200);
  } catch (err) {
    if (err instanceof WebhookVerificationError) {
      return res.status(400).end(err.reason);
    }
    throw err;
  }
});

4. Send a test payment

Open the checkout URL in a wallet on Base testnet and complete the flow. As soon as the payment confirms on-chain (typically within seconds — exact latency depends on the chain), your webhook handler fires with payment.confirmed. Use os.webhookEndpoints.test() to queue a synthetic webhook.endpoint.test event so you can verify the signature flow end-to-end without a real transfer:

dry-run.ts
const { eventId } = await os.webhookEndpoints.test(endpoint.id);
// Server queues a "webhook.endpoint.test" event for delivery — inspect
// the resulting attempt in the dashboard by eventId.
On GitHub
You shipped stablecoin billing.
Ready to go live? Generate live keys and flip the switch.
Open dashboard