HTTP API
Public
| Method | Path | Notes |
|---|---|---|
| GET | /api/health |
Liveness (no rate limit) |
| GET | /api/ready |
DB ready (no rate limit) |
| POST | /api/invoices |
Create (rate limited — create bucket) |
| GET | /api/invoices/:id |
Status + events |
| GET | /api/invoices?to=0x… |
Merchant list (signed) |
| GET | /api/public/pay-in/config |
MetaMask pay-in capability (Base USDC) |
| GET | /api/public/pay-in/countries |
Quote regions |
| GET | /api/public/pay-in/geo |
Payer country from CDN IP headers |
| GET | /api/public/pay-in/quotes |
Card/bank quotes (Pay-in API) |
| GET | /api/public/pay-in/widget |
Provider checkout URL (new tab) |
Invoice type field shapes and worked examples: Invoice types.
Admin (x-api-key: ADMIN_API_KEY)
| Method | Path |
|---|---|
| GET | /api/admin/stats |
| POST | /api/admin/sweepers |
| POST | /api/admin/bundlers |
Admin and /api/internal/* routes are not rate-limited (API-key gated).
Sweeper (wallet-signed)
| Method | Path |
|---|---|
| GET | /api/sweeper/me |
| GET | /api/sweeper/invoices |
| POST | /api/sweeper/heartbeat |
| POST | /api/sweeper/claim |
| POST | /api/sweeper/track |
Headers: x-sweeper-address, x-sweeper-timestamp, x-sweeper-nonce, x-sweeper-body-hash, x-sweeper-signature.
Track/claim use optimistic expectedVersion; conflicts return 409.
Bundler (wallet-signed)
| Method | Path |
|---|---|
| GET | /api/bundler/userops |
| POST | /api/bundler/claim |
| POST | /api/bundler/track |
Same header pattern as sweeper (x-bundler-*). Register via POST /api/admin/bundlers then ./register-onchain-invoice-bundler.sh.
Wallet UserOps: POST /api/wallet/userops (public submit). Rejected/failed hashes may be requeued with a fresh signature; pending/included hashes return 409 duplicate_user_op_hash.
Hosted wallet recovery (public + guardian)
User-facing recovery for the hosted /wallet product (not the HMAC partner API). See Security.
| Method | Path | Auth |
|---|---|---|
| GET/POST | /api/wallet/email |
Passkey + captcha (POST); public masked GET |
| POST | /api/wallet/email/verify |
OTP + captcha |
| POST | /api/wallet/recovery/email/start |
Email + captcha. Always 200 (no enumeration). OTP only if wallets exist |
| POST | /api/wallet/recovery/email/verify |
OTP + captcha → emailSession |
| GET | /api/wallet/recovery/email/wallets |
Bearer emailSession — all wallets for that email |
| POST | /api/wallet/recovery/challenges |
Public |
| GET | /api/wallet/recovery |
Public (active request + pendingOwner) |
| POST | /api/wallet/recovery/requests |
New key (WebAuthn, YubiKey, or EOA) + captcha. Email optional. walletAddresses[] + emailSession for email-first |
| POST | /api/wallet/recovery/requests/:id/verify-email |
OTP + captcha |
| POST | /api/wallet/recovery/requests/:id/cancel |
Owner passkey + captcha |
| GET | /api/guardian/nonce |
Guardian address query |
| POST | /api/guardian/login |
EIP-191 signature |
| GET | /api/guardian/me |
Guardian session |
| GET | /api/guardian/recovery-requests |
Guardian session |
| POST | /api/guardian/recovery-requests/:id/approve |
Guardian session → queue initiate job |
| POST | /api/guardian/recovery-requests/:id/reject |
Guardian session |
Wallet client API (HMAC)
Partner backends embedding passkey wallets on their WebAuthn domain. Full contract: Wallet client API. Hosted recovery above is a different path (OTP email, MetaMask guardian UI).
| Method | Path | Auth |
|---|---|---|
| POST/GET/PATCH | /api/admin/wallet-clients… |
ADMIN_API_KEY |
| POST/GET | /api/client/wallets… |
HMAC (x-client-*) |
| GET/POST | /api/internal/wallet-recovery/* |
SWEEPER_API_KEY |
Headers: x-client-id, x-client-timestamp, x-client-nonce, x-client-body-hash, x-client-signature. Path in the canonical message is pathname only.
Rate limiting
Central table-driven limiter (IP + bucket). New public routes are limited by default.
| Bucket | Default | Env | Used for |
|---|---|---|---|
create |
1/s | RATE_LIMIT_CREATE_PER_SECOND |
POST /api/invoices (+ aliases, faucet capped) |
public |
20/s | RATE_LIMIT_PUBLIC_PER_SECOND |
Public GETs, hosted wallet APIs |
quote |
2/s, burst 20 | RATE_LIMIT_QUOTE_PER_SECOND, RATE_LIMIT_QUOTE_BURST |
/api/public/pay-in/ |
sweeper |
50/s | RATE_LIMIT_SWEEPER_PER_SECOND |
Sweeper + bundler signed APIs |
wallet_client |
50/s | RATE_LIMIT_WALLET_CLIENT_PER_SECOND |
/api/client/wallets* |
Exempt: /api/health, /api/ready, /api/admin/*, /api/internal/*, wallet deployer routes.
Exceeding a limit returns 429 { "error": "Rate limit exceeded" } with:
Retry-After(seconds)RateLimit-RemainingRateLimit-Reset
Agents should back off and retry after Retry-After. Public create and quote are unauthenticated (spam risk accepted at launch; captcha optional via Turnstile).
Platform integrations
Ecommerce and creator platform adapters (WooCommerce, Shopify, Kajabi, Teachable) build on the same contract:
- Platform integration contract
- SDKs and plugins:
platforms/