Start here
thru lets your business accept stablecoin payments. For each payment it gives the payer a one-time address, watches the chain, sends your server a signed webhook when the money has arrived, and then forwards the funds to your own settlement wallet.
Five facts every integration needs
| Base URL | https://api.thru.la/v1 |
| Authentication | Send x-api-key: thru_sk_… on every server-to-server call. There is no Authorization: Bearer scheme. Keys are created in the console. |
| Amounts | Amounts are decimal strings in token units, so "25" means 25 USDC. currency is only a display label, and thru does no currency conversion. The one amount labelled USD is a custom-amount product's amount (at most 2 decimal places); it becomes the payment's expectedAmount unchanged, in the token of whichever rail the buyer picks, so give such a product stablecoin rails only. |
| Network | One key works on both mainnet and testnet. Send network on every create, and check network before you fulfil. |
| Unknown fields | A request body field the API does not define is rejected with 400. Put your own data in metadata. |
Choose your integration
| You want to… | Use | Who shows the payment page | How you know who paid |
|---|---|---|---|
| Sell a fixed-price item or pack on a hosted page | A checkout session for a fixed-price product (checkout-sessions) | thru, at https://thru.la/c/<session id> | Your reference, on the session and in every checkout.session.* event |
| Sell credit or a top-up, where the amount differs per purchase, on a hosted page | A checkout session with amount for a custom-amount product (checkout-sessions, credit-topups) | thru, at https://thru.la/c/<session id> | Your reference, on the session and as checkoutSession in every payment.* event |
| Charge an amount you decide, with your own payment screen | A direct payment, POST /v1/payments (payments) | You, or the React components in @thru-payment/pay-sdk | The payment id you stored when you created it |
| Share one link anyone can pay, such as a buy button | A product payment link, /pay/<slug> (products) | thru | Nobody. The link is anonymous. |
| Bill a named customer with line items | An invoice (invoices) | thru, at https://thru.la/i/<publicId> | The invoice's paymentId. There is no invoice webhook. |
| Charge AI agents per API request (HTTP 402) | Agent payments (facilitator-x402) | Nobody; it is machine to machine | Not enabled on api.thru.la yet |
Rules of thumb:
- If the amount varies, use a custom-amount product. A product is either
fixed(its price is charged) orcustom_amount(your server sendsamounton each checkout session, within the product'sminAmount/maxAmount, and the buyer cannot change it). A direct payment is for when you also want to show the payment screen yourself. - Grant from one webhook family. Fixed-price sessions grant on
checkout.session.completed; custom-amount sessions creditreceivedAmountonpayment.*, whose events carrycheckoutSessionwith yourreference. - A checkout session can point only at a product today. The API accepts a session for an invoice, but the hosted page cannot display one yet.
- Every integration ends the same way. A webhook tells you money moved, and an authenticated read of the object confirms it before you fulfil.
- Check
supported-chainsbefore you offer a chain. The API accepts payments on chains and tokens that are not being watched, and such payments never confirm.
Reading path
quickstart: a real testnet payment, end to end, with curl.auth: keys, workspaces, and testnet versus mainnet.- The guide for your integration:
checkout-sessions,credit-topups,productsorinvoices. webhooks: signature verification, deduplication and retries.supported-chains: which chain and token pairs confirm today.going-live: the checklist.
Reference topics: payments, api-conventions, refunds-and-settlement, sdks.
The secrets you will handle
| Secret | Format | Where it comes from | What it is for |
|---|---|---|---|
| API key | thru_sk_ + 48 hex characters | Console → Developers → API keys. It is shown once. | The x-api-key header on server calls |
| Webhook signing secret | 64 hex characters, one per endpoint | The secret field returned by POST /v1/webhooks and GET /v1/webhooks | Checking the x-thru-signature header |
| Checkout signing secret | 64 hex characters, one per workspace | GET /v1/checkout/secret, or Console → Developers → Checkout | Checking thru_sig when a shopper returns from a checkout session |
Both signing secrets are HMAC-SHA256 keys, and the key is the UTF-8 bytes of the secret string. Do not hex-decode them. Keep all three secrets on your server; none may reach a browser or a mobile app.
Reading these docs as a coding agent
GET /v1/docs returns the topic index, and GET /v1/docs/:topic returns one topic as markdown inside JSON. Neither needs a key. Fetch only the topics your task touches.