Quickstart
Go from zero to a paid, reconciled order with email or wallet login, no password, and simple merchant onboarding. Save a payout wallet, open a checkout session, and confirm payment with a webhook.
- 1
Choose email or wallet login
Use email for a full merchant account with multiple payout wallets. Use MetaMask or Phantom wallet login for a single-wallet account where the signed wallet becomes the payout wallet. Just want to get paid? Create and share a payment link right away, no code and no API key needed.
- 2
Create or confirm your payout wallet
Email accounts can save multiple payout wallets. Wallet-login accounts automatically use the signed wallet and cannot add another. Links and sessions reference one payout wallet by id, so a leaked key can never redirect funds. Read them back over the API:
curl https://apa.app/v1/payout-wallets \ -H "Authorization: Bearer sk_live_…" { "data": [ { "id": "pp_123", "asset": "USDC", "network": "solana", "is_default": true } ], "pagination": { "cursor": null, "has_more": false, "total": 1 } } - 3
Get an API key (to integrate)
Building your own checkout? Generate a live key from the dashboard and keep the secret server-side. Skip this entirely if you're only using payment links.
- 4
Create a checkout session
From your backend, create a session for the order, referencing the payout wallet.
curl https://apa.app/v1/checkout/sessions \ -H "Authorization: Bearer sk_live_…" \ -H "Content-Type: application/json" \ -d '{ "payout_wallet_id": "pp_123", "amount": "100.00", "currency": "USD", "order_id": "ord_1042" }' { "data": { "id": "cs_123", "object": "checkout_session", "status": "created", "payment_link_id": null, "checkout_url": "https://apa.app/checkout/cs_123" }, "request_id": "req_3aF2k9Lm" } - 5
Redirect the customer
Send the customer to the checkout_url. They pick any Safe-List asset and pay from their own wallet — Apa routes whenever the asset or network differs from your payout wallet; exact asset/network matches settle free.
- 6
Listen for the webhook
Apa POSTs a signed payment.paid event to your endpoint once funds settle.
// Express — express.raw() preserves the exact bytes for signing app.post("/api/apa/webhook", express.raw({ type: "*/*" }), (req, res) => { // Apa-Signature: t=<timestamp>,v1=<hex> // v1 = HMAC_SHA256(secret, `${t}.${rawBody}`) const parts = Object.fromEntries( (req.headers["apa-signature"] ?? "").split(",").map((p) => p.split("=")) ); const expected = crypto .createHmac("sha256", process.env.APA_WEBHOOK_SECRET) // whsec_… .update(`${parts.t}.${req.body}`) .digest("hex"); if (!parts.v1 || !crypto.timingSafeEqual(Buffer.from(parts.v1), Buffer.from(expected))) { return res.sendStatus(400); } const event = JSON.parse(req.body); if (event.type === "payment.paid") markOrderPaid(event.data.order_id); res.sendStatus(200); }); - 7
Reconcile the order
Mark the order paid and fulfil. The settled funds are already in your wallet — Apa never held them.