The @blockpay/checkout reference.
A small, sharp surface for stablecoin checkout. Six methods, one type-safe client, zero ceremony.
Install
Add the SDK to your project. It is a pure ESM package, ships with TypeScript declarations, and has zero runtime dependencies.
npm install @blockpay/checkoutInitialize
Construct a single client and reuse it. The API key is a secret — keep it server-side.
import { BlockPay } from "@blockpay/checkout";const bp = new BlockPay({ apiKey: process.env.BLOCKPAY_API_KEY!, // Optional. Defaults to https://api.blockpay.dev baseUrl: "https://api.blockpay.dev",});Invoices
Invoices are the canonical record of a charge. Create one, redirect the customer to invoice.checkoutUrl, and your webhook handler fires when the on-chain transfer lands.
bp.invoices.create
Creates a fresh invoice in open state. The chain and currency lock the settlement asset; you cannot switch them after creation.
const invoice = await bp.invoices.create({ amount: "49.00", currency: "USDC", chainKey: "arc-testnet", merchantAddress: "0xYourSettlementWallet", lineItems: [{ label: "Pro Plan", amount: "49.00" }], // Optional. Unix seconds. expiresAt: Math.floor(Date.now() / 1000) + 60 * 30,});console.log(invoice.id); // "inv_01HE2..."console.log(invoice.checkoutUrl); // "/checkout/inv_01HE2..."bp.invoices.get
Fetches a single invoice by id. Returns the latest known status, including which chain transaction settled it.
const invoice = await bp.invoices.get("inv_01HE2...");if (invoice.status === "paid") { // fulfill the order}bp.invoices.list
Lists invoices, optionally filtered by merchant or status. Useful for backfilling your own database.
const { invoices } = await bp.invoices.list({ merchantId: "merchant_acme", status: "open",});Payment Links
Payment links are shareable URLs that produce invoices on demand. Use a one-off link to charge a specific customer, or a reusable link to drop a checkout into a Linktree, email signature or QR code.
// One-off link: tied to a single invoice.const link = await bp.paymentLinks.create({ amount: "12.00", currency: "USDC", chainKey: "arc-testnet", merchantAddress: "0xYourSettlementWallet", description: "Coffee, large",});// Reusable link: same URL accepts many distinct payments.const reusable = await bp.paymentLinks.create({ amount: "12.00", currency: "USDC", chainKey: "arc-testnet", merchantAddress: "0xYourSettlementWallet", reusable: true,});Webhooks
Webhooks fire on every state change. The SDK ships a helper that verifies the signature using a constant-time comparison and gives you a typed event back.
Throws if the signature does not match. Always pass the raw request body — re-serialised JSON will not match the signature.
import { verifyWebhook } from "@blockpay/checkout/webhooks";export async function POST(req: Request) { const raw = await req.text(); const signature = req.headers.get("x-blockpay-signature") ?? ""; const event = verifyWebhook({ payload: raw, signature, secret: process.env.BLOCKPAY_WEBHOOK_SECRET!, }); switch (event.type) { case "invoice.paid": // event.data.invoice break; } return new Response("ok");}Receipts
Every settled invoice produces a signed receipt CID. Verify it client-side to prove fulfilment without trusting the merchant or the BlockPay API.
// Verify a signed receipt CID produced by the BlockPay indexer.const receipt = await bp.receipts.verify({ cid: "0x9b1c...e3f0",});if (receipt.valid) { console.log(receipt.invoiceId, receipt.txHash, receipt.amount);}