DocsStart free
English
API docsGetting started

Unheld API reference

Unheld creates crypto invoices that are paid straight to your own wallet addresses and tells your server, by signed webhook, when each one is paid. This reference covers everything your backend needs: authentication, invoices, webhooks, checkout buttons, customers, subscriptions and balances.

Base URL https://api.unheld.io/api/v1
Authentication Authorization: Bearer <api key> on every call from your server
Format JSON in, JSON out. Amounts in responses are strings, never numbers
Version v1

Every path on this page is relative to the base URL: POST /invoices means POST https://api.unheld.io/api/v1/invoices.


Before your first call#

  1. Confirm your email address. Until you click the link in the confirmation email, the account cannot create API keys, webhooks, invoices, checkout buttons, customers or subscriptions — each answers 403 EMAIL_NOT_VERIFIED.
  2. Choose Live or Test mode with the switch at the foot of the dashboard sidebar. Test mode takes payments on test networks only — the ones your plan includes (on Free: Sepolia, Bitcoin Testnet4 and XRP Ledger Testnet) — where coins cost nothing; Live mode takes payments on main networks only. Payments on test networks are free on every plan. Build against Test, then switch.
  3. Check your accepted currencies in Account → Payment currencies. Until you set a list, every currency you can receive is accepted; once you set one, an invoice outside it is refused 422 ASSET_NOT_ACCEPTED.
  4. Create an API key in API Keys, with the scopes your server needs (see Authentication). The key is shown once — store it in an environment variable.

Take your first payment#

1. Create an invoice for 0.01 ETH on Sepolia, valid for 30 minutes:

Shell
curl -X POST https://api.unheld.io/api/v1/invoices \
  -H "Authorization: Bearer $UNHELD_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: order_8823" \
  -d '{"chainId":"11155111","assetType":"native","amountDecimal":"0.01","expiresInSeconds":1800,"metadata":{"external_ref":"order_8823"}}'

2. Show the payer where to pay. The response carries receiveAddress and expectedAmount (in base units — wei here). On the XRP Ledger in tag mode it also carries receiveTag, which the payer must include. Or send the payer to the hosted payment page, https://app.unheld.io/invoice/<id>, instead of building your own.

3. Wait for the webhook. When the payment reaches the network's confirmation depth, your webhook receives invoice.paid with invoiceId, externalRef ("order_8823") and the amounts. Verify the signature (see Receiving webhooks), then fulfil the order.

4. Or poll GET /invoices/:id until status is PAID_CONFIRMED or PAID_LATE.

No backend at all? A checkout button is one link you paste on any page: Unheld creates the invoice when the customer clicks it.