Basics
Production API base:
https://api.settlebolt.com
Send JSON with Content-Type: application/json. Write requests with JSON bodies are capped at 5 MiB, with smaller caps on support ticket and feedback routes.
Authentication
Dashboard APIs use the logged-in dashboard session token:
Authorization: Bearer <dashboard-session-token>
Only verified-email accounts can access the dashboard API. Mutating requests made through admin impersonation are rejected unless they are read-only.
Creating or using general API keys requires active Pro or Business access. Owners and admins can list and revoke existing keys on every plan, including after expiration. Keys authenticate SettleBolt's dedicated, scoped server-to-server Agent API (/api/agent/*) - each key carries per-operation scopes and is not accepted on dashboard routes (it cannot manage wallets, billing, team, or account settings). Keys are shown once and should be treated like passwords; revoke a leaked key in Developers.
Starter can use WooCommerce through the dedicated plugin key created by the Connect SettleBolt flow. That key is limited to payment_links:create and webhooks:write.
Agent API
The Agent API is the supported surface for AI agents and backend automations. It requires an active paid Pro or Business subscription, uses scoped API keys from Developers, and is limited to merchant operations that are safe to automate. Agent keys are not accepted on dashboard endpoints and cannot manage wallets, billing, team members, or account deletion.
Required header:
Authorization: Bearer sb_live_...
| Method | Path | Scope | Purpose |
|---|---|---|---|
| GET | /api/agent/me | any valid scope | Return merchant, API-key, and active subscription details. |
| GET | /api/agent/invoices, /api/agent/invoices/:id | invoices:read | List or inspect invoices. |
| POST | /api/agent/invoices | invoices:create | Create a draft invoice with the same validation as the dashboard. |
| POST | /api/agent/invoices/:id/send | invoices:send | Send an existing draft invoice. No additional dashboard confirmation is required. |
| POST | /api/agent/invoices/send | invoices:create + invoices:send | Create and send an invoice in one request. No additional dashboard confirmation is required. |
| GET | /api/agent/payment-links | payment_links:read | List payment links. |
| POST | /api/agent/payment-links | payment_links:create | Create a payment link. |
| POST | /api/agent/woocommerce/connect | payment_links:create + webhooks:write | Register a WooCommerce webhook endpoint and return its signing secret once. |
| POST | /api/woocommerce/connect/approve | dashboard owner/admin | Approve one-click WooCommerce setup, create a scoped plugin key, register the webhook, and return a redirect URL with a one-time code. |
| POST | /api/woocommerce/connect/exchange | one-time code | WordPress exchanges the short-lived code for the plugin key and webhook signing secret. |
| GET | /api/agent/payments | payments:read | List recorded payments. |
| GET | /api/agent/customers | customers:read | List manual customer records. |
| POST | /api/agent/customers | customers:write | Create a customer record. |
| POST | /api/agent/support/tickets | support:create | Open a support ticket. Body: {"subject","message","category?","priority?"}. |
Machine-readable OpenAPI:
https://settlebolt.com/openapi.json
Examples
All amounts are in EUR cents (5000 = EUR 50.00). Set "mode":"demo" to create in TEST mode; omit it for live. List endpoints accept ?mode=live or ?mode=demo, an unrecognized value returns 400 Invalid mode, and every payment.confirmed webhook carries a mode field so you can ignore demo events in production. Demo and live data are fully isolated: demo checkouts never move funds or send real emails, and on-chain settlement only ever attaches to live links and invoices.
1. Create a payment link
curl -X POST https://api.settlebolt.com/api/agent/payment-links \
-H "Authorization: Bearer sb_live_..." \
-H "Content-Type: application/json" \
-d '{"title":"Pro plan","amount":5000,"currency":"EUR","token":"USDC","chain":"base"}'
{
"id": "pl_9f2c...",
"checkoutSlug": "a1b2c3d4e5f6",
"mode": "live",
"walletAutoEnabled": null,
"url": "https://settlebolt.com/checkout/?kind=l&slug=a1b2c3d4e5f6"
}
2. Create and send an invoice in one call (requires invoices:create + invoices:send)
curl -X POST https://api.settlebolt.com/api/agent/invoices/send \
-H "Authorization: Bearer sb_live_..." \
-H "Content-Type: application/json" \
-d '{
"customerName": "FPSHEAVEN",
"customerEmail": "ap@fpsheaven.com",
"invoiceNumber": "INV-0007",
"amount": 120000,
"currency": "EUR",
"token": "USDC",
"chain": "base",
"dueDate": "2026-08-01"
}'
{
"id": "inv_7a3e...",
"invoiceNumber": "INV-0007",
"status": "sent",
"mode": "live",
"payUrl": "https://settlebolt.com/checkout/?kind=pay&slug=...",
"email": { "sent": true }
}
If you send lineItems, their total must equal amount. Invoice numbers are unique per merchant. Draft creation returns payUrl: null; sending makes the invoice payable when payment detection is ready. Check email.sent and email_status separately from invoice status.
Safe creation retries: Send Idempotency-Key with invoice, create-and-send, customer and payment-link POSTs. The key accepts 1–128 letters, numbers or ._:- characters. Retry with the same key and body. Invoice/customer keys are scoped to merchant and operation and retained without automatic expiry; a changed body returns 409, and deletion of the original resource returns 410. Retrying create-and-send recovers its draft or returns the issued invoice without another email. Use POST /api/agent/invoices/:id/resend to explicitly retry email delivery.
3. List recent payments
curl "https://api.settlebolt.com/api/agent/payments?limit=20" \
-H "Authorization: Bearer sb_live_..."
{
"payments": [
{
"id": "pay_4c1d...",
"status": "confirmed",
"token": "USDC",
"chain": "base",
"amount_eur_cents": 5000,
"tx_hash": "0x8ab3...",
"payment_link_id": "pl_9f2c...",
"invoice_id": null,
"created_at": "2026-07-05 12:30:00"
}
],
"limit": 20,
"offset": 0
}
Filter payments by invoice_id, payment_link_id or external_id. Use created_after with an ISO timestamp including timezone, limit (1–100), and starting_after with the last payment ID. Follow has_more and next_starting_after. Results sort by creation time then ID descending; cursor paging ignores offset and is not a snapshot. Poll with overlapping time windows and deduplicate IDs. GET /api/agent/payment-links/:id returns paid/underpaid counts and the latest receipt.
Agent limits are 900 reads or 180 mutations per rolling minute, checked against both source IP and token. Inspect X-RateLimit-Limit, X-RateLimit-Remaining and Retry-After on 429.
Owners/admins can list and revoke existing keys and messaging connections after a downgrade or expiration. Creating general keys or new pairings still requires active Pro or Business access.
Demo simulation: POST /api/agent/payment-links/:id/simulate-payment requires payment_links:create and a fixed-price demo link. It records at most one demo receipt per link; retries return duplicate: true. Demo creation needs no live wallet or live link allowance. Fixture prices are EUR/USD 1.10, ETH EUR 3,000, BTC EUR 60,000, SOL EUR 150 and TRX EUR 0.25. Raw units use each token's precision; EUR 100 in demo USDC is 110000000. These rates are not live prices.
4. Receive and verify the payment.confirmed webhook
When a payment clears, SettleBolt POSTs a signed event to your endpoint. Use the complete verifier below with the original raw request body. Check the timestamp, compare the HMAC in constant time, and deduplicate the event ID before processing an order.
Example payload:
{
"type": "payment.confirmed",
"created_at": "2026-07-05T12:30:00.000Z",
"data": {
"payment_id": "pay_4c1d...",
"status": "confirmed",
"chain": "base",
"token": "USDC",
"amount": "55000000",
"amount_eur_cents": 5000,
"tx_hash": "0x8ab3...",
"payment_link_id": "pl_9f2c...",
"invoice_id": null,
"payer_address": "0x1111...",
"merchant_address": "0x2222...",
"mode": "live"
}
}
Respond with a 2xx quickly. SettleBolt retries with backoff on any non-2xx response, and includes a mode field so you can ignore demo events in production.
WooCommerce connection activation
Plugin 0.1.22 introduces activation protocol 2. Owner/admin approval still requires a fresh authenticator code. Approval prepares an inactive key and endpoint for ten minutes. Exchange can repeat with the same code, state and URL during that window, returning the same secrets.
WordPress saves both secrets before calling POST /api/woocommerce/connect/activate. Authenticate with the new plugin key and send apiKeyId, webhookEndpointId and a hex HMAC-SHA256 proof of activate:{apiKeyId}:{webhookEndpointId}, signed with the new webhook secret. Activation atomically replaces that store's credentials and moves queued deliveries. Repeating an acknowledged activation is safe. Superseded, revoked or expired pending setups cannot activate.
Exchange secrets are erased after activation; abandoned inactive setup expires and is cleaned by the scheduled worker. WordPress retains pending credentials if activation or its final settings save fails, retries through scheduled tasks, and accepts signatures during a ten-minute handover. Existing connected installations continue working, but older plugins must update before reconnecting.
POST /api/agent/woocommerce/connect now binds the calling key to one URL. A retry returns that connection's existing secret; it cannot rotate another key's endpoint or change the store URL. Use dashboard approval to replace a store connection. Endpoint capacity and paused-endpoint controls still apply.
WhatsApp Agent Channel
The WhatsApp channel lets a merchant pair a WhatsApp sender to a scoped SettleBolt agent. It uses the same paid Pro/Business, verified-email, plan-current, scope, wallet, and audit-log checks as the Agent API, but no API key is shown in WhatsApp.
Configure the Meta WhatsApp webhook URL as https://api.settlebolt.com/api/whatsapp/webhook. The Worker verifies X-Hub-Signature-256 with the Meta app secret before parsing inbound messages.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /api/whatsapp/webhook | Meta verify token | Meta webhook verification challenge. |
| POST | /api/whatsapp/webhook | Meta signature | Receive inbound WhatsApp messages, dedupe by provider message ID, and route commands to the paired merchant. |
| GET | /api/whatsapp/links | dashboard session | List paired WhatsApp senders and show the Meta webhook URL. |
| POST | /api/whatsapp/links/pairing-code | dashboard session | Create a 10-minute pairing code with selected scopes. |
| DELETE | /api/whatsapp/links/:id | dashboard session | Revoke a WhatsApp sender. |
Supported WhatsApp commands include:
send invoice to FPSHEAVEN info@example.com for EUR 1200 due July 16 using USDC on Base
create payment link Website deposit for EUR 500 using USDC on Base
add customer FPSHEAVEN info@example.com
payments
customers
status
WhatsApp cannot manage wallets, billing, team members, account deletion, dashboard sessions, or other high-risk settings.
Telegram Agent Channel
The Telegram channel lets a merchant pair one Telegram account to scoped SettleBolt actions. It uses the same paid Pro/Business, verified-email, plan-current, scope, wallet, and audit-log checks as the Agent API. No API key is shown in Telegram.
Set the Telegram webhook URL to https://api.settlebolt.com/api/telegram/webhook. The Worker verifies X-Telegram-Bot-Api-Secret-Token before processing updates.
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /api/telegram/webhook | none | Health check for the Telegram webhook route. |
| POST | /api/telegram/webhook | Telegram secret token | Receive inbound Telegram updates, dedupe by update ID, and route callbacks/messages to the paired merchant. |
| GET | /api/telegram/links | dashboard session | List paired Telegram users and show the webhook URL. |
| POST | /api/telegram/links/pairing-code | dashboard session | Create a 10-minute pairing code with selected scopes. |
| DELETE | /api/telegram/links/:id | dashboard session | Revoke a Telegram connection. |
Pair by sending /pair 123456 to the bot. After pairing, the bot shows buttons for payment links, invoices, customers, payments, account status, help, and clearing recent bot messages.
Telegram cannot manage wallets, payout changes, billing, team members, account deletion, dashboard sessions, custom domains, or settings.
Public Checkout API
| Method | Path | Purpose |
|---|---|---|
| GET | /api/checkout/:kind/:slug | Load payer-safe checkout data for payment links (kind=l) or invoices (kind=pay). |
| POST | /api/checkout/:kind/:slug/quote | Create or reuse a 15-minute quote for every supported asset using its token-specific EUR market price. Stablecoin parity is not assumed. Pay the exact quoted raw amount, including its small attribution reference. A quote requires healthy payment detection. |
| GET | /api/public/logo/:merchantId, /api/public/icon/:merchantId | Load public merchant logo/icon assets used by checkout and previews. |
Custom checkout domains may call only public checkout and public asset APIs. The public checkout response intentionally returns public RPC fallbacks only, never configured provider secrets.
Dashboard Endpoints
| Area | Paths | Notes |
|---|---|---|
| Auth | /api/auth/* | Signup, login, email verification, 2FA, sessions, password and account management. |
| Merchant | /api/merchants/me, /api/merchants/me/wallets | Business profile, wallets, wallet labels, primary wallets, payout changes. |
| Payment links | /api/payment-links, /api/payment-links/:id | Create, list, edit, delete, and view payments for links. |
| Invoices | /api/invoices, /api/invoices/:id/send, /api/invoices/:id/pdf | Create drafts, edit drafts, send, resend, cancel, and print invoices. |
| Customers | /api/customers, /api/customers/:emailHash, /api/customers/export.csv, /api/customers/manual/:id | List/create customers, detail pages, edit/delete manual customers, and CSV export on paid plans. |
| Payments | /api/payments, /api/payments/:id, /api/payments/export | Payment ledger, filters, payment detail, and CSV export. |
| Branding | /api/branding, /api/branding/domain | Brand colors, PNG logo/icon, support email, and Pro/Business custom domains. |
| Billing | /api/billing/overview, /api/plan-crypto/*, /api/billing/cancel | Crypto plan payments, subscription status, cancellation, receipts, and local invoice records. |
| Developers | /api/keys, /api/webhooks/*, /api/whatsapp/*, /api/telegram/* | API key management, webhook endpoints, delivery event log, redelivery, WhatsApp pairing, and Telegram pairing. |
| Support | /api/support/tickets, /api/support/tickets/:id/messages, /api/support/feedback | Create tickets, list tickets, view a ticket thread, reply to a ticket, and submit feedback. |
| Team | /api/team, /api/team/invites, /api/team/members/:id | List members, invite by email, resend invites, change roles, remove members, transfer ownership (owner/admin; Pro/Business seats). |
| Analytics | /api/analytics/summary, /api/analytics/breakdown, /api/analytics/export | Revenue and payment analytics with CSV export (advanced analytics is a Pro/Business feature). |
Examples
Create and send an invoice with an agent key:
curl -X POST "$API/api/agent/invoices/send" \
-H "Authorization: Bearer $SETTLEBOLT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"customerName": "FPSHEAVEN",
"customerEmail": "billing@example.com",
"invoiceNumber": "INV-0008",
"amount": 120000,
"currency": "EUR",
"token": "USDC",
"chain": "base",
"dueDate": "2026-07-16",
"lineItems": [
{ "description": "Brand and website design", "qty": 1, "unitPrice": 90000 },
{ "description": "Hosting setup", "qty": 1, "unitPrice": 30000 }
]
}'
Create a payment link:
curl -X POST "$API/api/payment-links" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"title": "Website design",
"description": "Deposit",
"amount": 120000,
"currency": "EUR",
"token": "USDC",
"chain": "base"
}'
Create a draft invoice:
curl -X POST "$API/api/invoices" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"customerName": "FPSHEAVEN",
"customerEmail": "billing@example.com",
"invoiceNumber": "INV-0008",
"amount": 120000,
"currency": "EUR",
"token": "USDC",
"chain": "base",
"dueDate": "2026-07-16",
"lineItems": [
{ "description": "Brand and website design", "qty": 1, "unitPrice": 90000 },
{ "description": "Hosting setup", "qty": 1, "unitPrice": 30000 }
]
}'
List payments with filters:
curl "$API/api/payments?status=confirmed,overpaid&chain=base&source=invoices" \
-H "Authorization: Bearer $TOKEN"
Webhooks
Adding general webhook endpoints requires active paid Pro or Business access. Paid Starter stores can connect through WooCommerce. Existing endpoints, delivery history, resume controls and redelivery remain available after a plan expires or changes.
A signed payment.confirmed event is stored with each eligible receipt. Recoverable delivery failures retry with backoff and jitter for 72 hours from the start of the delivery window. Automatically disabled endpoints retain new events as paused work. Resume an endpoint or reconnect the same WooCommerce URL to queue retained pending, paused and failed events.
For older deliveries, request GET /api/webhooks/events?paginated=1&limit=50. The response contains events, has_more and next_starting_after. Pass the latter as starting_after; filter server-side with status (pending, paused, delivered or failed) and endpoint_id. Results sort by creation time and ID descending. New inserts do not displace an existing cursor page; delivery status can still change between requests. Without paginated=1, the original array response is retained.
Rotate a custom endpoint with POST /api/webhooks/endpoints/:id/rotate and a unique Idempotency-Key header (16?128 letters, digits, underscores or hyphens). Save the returned signing secret and previousValidUntil. Retry with the same key after a lost response to recover the same secret. For 24 hours, the signature header contains two v1 values: new key first, old key second. Accept any valid signature using the verifier below. Event IDs and payloads stay unchanged, including on redelivery; after the overlap only the current key signs. Another rotation during the overlap returns 409. WooCommerce-managed endpoints require the plugin?s signed reconnect flow instead of this route. This rotates an endpoint signing secret, not the platform encryption key.
Delivery is at least once and may arrive out of order. Store the event ID, which is an opaque string currently based on the payment and endpoint IDs. Make fulfillment idempotent by data.payment_id as well. Manual redelivery returns HTTP 202 after queuing work; it does not mean the receiver has accepted it. Manually disabled and replaced endpoints stop collecting new events.
payment.confirmed is the currently delivered merchant webhook event. Do not build against other event labels unless they are listed here as delivered.
| Method | Path | Purpose |
|---|---|---|
| GET | /api/webhooks/endpoints | List webhook endpoints. |
| POST | /api/webhooks/endpoints | Add an HTTPS endpoint. Body: {"url":"https://..."}. The signing secret is returned once. |
| DELETE | /api/webhooks/endpoints/:id | Disable an endpoint. |
| POST | /api/webhooks/endpoints/:id/resume | Resume an endpoint and queue its retained unsuccessful deliveries. |
| GET | /api/webhooks/events | List recent delivery events. |
| GET | /api/webhooks/events/:id | Fetch an event and its last 50 recorded attempts, including response status, duration and error. |
| POST | /api/webhooks/events/:id/redeliver | Queue redelivery with HTTP 202. Inactive endpoints or an in-flight delivery return 409. |
Event headers:
X-SettleBolt-Event: payment.confirmed
X-SettleBolt-Event-Id: <event-id>
X-SettleBolt-Timestamp: 1783100000
X-SettleBolt-Signature: t=1783100000,v1=<hmac>
Signature base string:
<timestamp>.<event_id>.<raw_json_body>
Node verifier (the custom SettleBolt header and hex-signature scheme is not Standard Webhooks compatible):
import crypto from 'node:crypto'
function verifySettleBoltWebhook(rawBody, headers, secret) {
if (!Buffer.isBuffer(rawBody) && typeof rawBody !== 'string') return false
const timestamp = headers['x-settlebolt-timestamp']
const eventId = headers['x-settlebolt-event-id']
const signature = headers['x-settlebolt-signature']
if (typeof timestamp !== 'string' || !/^\d{1,12}$/.test(timestamp) ||
typeof eventId !== 'string' || !eventId || eventId.length > 512 ||
typeof signature !== 'string' || signature.length > 1024) return false
if (Math.abs(Date.now() / 1000 - Number(timestamp)) > 300) return false
const parts = signature.split(',').map(part => part.trim().split('='))
if (parts.some(part => part.length !== 2)) return false
const times = parts.filter(([name]) => name === 't')
if (times.length !== 1 || times[0][1] !== timestamp) return false
const expected = crypto.createHmac('sha256', secret)
.update(`${timestamp}.${eventId}.`).update(rawBody).digest()
return parts.some(([name, value]) => name === 'v1' &&
/^[a-fA-F0-9]{64}$/.test(value || '') &&
crypto.timingSafeEqual(Buffer.from(value, 'hex'), expected))
}
Request body:
{
"type": "payment.confirmed",
"created_at": "2026-07-03T12:00:00.000Z",
"data": {
"payment_id": "pay_...",
"merchant_id": "merchant_...",
"status": "confirmed", // confirmed | underpaid | overpaid
"chain": "base",
"token": "USDC",
"amount": "1200000000", // raw on-chain units, as a string
"amount_eur_cents": 120000, // null without a locked EUR quote valuation
"tx_hash": "0x...",
"invoice_id": null,
"payment_link_id": "pl_...",
"payer_address": "0x...",
"merchant_address": "0x...",
"mode": "live",
"receipt_number": null,
"source": "woocommerce",
"external_id": "123",
"title": "Order 123"
}
}
amount is a base-10 integer in token units: ETH and DAI use 18 decimals, BTC 8, SOL 9, and USDC, USDT and TRX 6. receipt_number, source metadata and target IDs can be null. Underpaid status requires explicit reconciliation of a verified receipt; ambiguous payments never automatically fulfill an order.
Each cron delivery pass uses up to four concurrent requests, one per endpoint, with a 20-second scheduling budget and at most 60 attempted events. HTTP 429/503 Retry-After delays are respected. HTTP 410 pauses the endpoint; other permanent 4xx responses are exposed for review without auto-disable strikes. Transient failures continue within the recovery window. A WordPress callback must return JSON {"ok":true}; an HTML homepage is not an acknowledgement.
Security Notes
- Webhook endpoints must be public HTTPS URLs on port 443.
- Obvious internal hostnames, all IP literals, credentialed URLs and ephemeral tunnel hosts are rejected. Hostnames are not DNS-resolved by this check; outbound access also depends on Cloudflare's egress controls.
- Webhook delivery fetches never follow redirects and use a 15-second timeout. Requests identify themselves as
SettleBolt-Webhooks/1.0. If your WAF challenges these requests, allow the authenticated callback route and keep signature verification enabled. - Webhook secrets are encrypted at rest and the raw secret is only shown once.
- Payment recording validates chain, token, recipient wallet, and idempotency before crediting.
- Do not put dashboard session tokens, API keys, or webhook secrets in browser code.
Errors
Most errors return JSON with an error string and an appropriate HTTP status.
{ "error": "Unsupported chain or token" }
| Status | Meaning |
|---|---|
| 400 | Invalid JSON, invalid field, unsupported token/chain, invalid URL, or invalid signature payload. |
| 401 | Missing or expired authentication. |
| 403 | Plan gate, role gate, unverified email, payout freeze, or forbidden internal secret. |
| 404 | Resource not found or checkout target unavailable. |
| 409 | Duplicate invoice number, duplicate customer, duplicate wallet, or conflicting custom domain. |
| 413 | Request body too large. |
| 429 | Rate limit reached. |
| 503 | Required provider secret or service is not configured. |