Authentication
Soren Pay uses workspace-scoped API keys prefixed apk_. Every authenticated
request carries one in the Authorization: Bearer … header.
Header format
curl https://api.sorenpay.com/api/treasury \
-H "authorization: Bearer apk_<your key>"Token lifecycle
| Action | Where |
|---|---|
| Create | Dashboard → Developers → API keys → "Create key" |
| Reveal | Once on creation. Store immediately. |
| List | GET /api/auth/keys |
| Rotate | Create a new key → switch traffic → revoke the old one |
| Revoke | DELETE /api/auth/keys?id=… or dashboard |
The full token is shown only at creation. If you lose it, you must create a new key and rotate.
Scopes
By default new keys have * (all scopes). For production we recommend
scoping each key to its exact role.
| Scope | What it grants |
|---|---|
| read:treasury | View balances + ledger |
| read:cards | List cards + lookup by id |
| write:cards | Mint + freeze + terminate cards |
| read:agents | List agents + view intent log |
| write:agents | Register agents + submit intents |
| read:checkout | View checkout sessions |
| write:checkout | Create checkout sessions |
| write:payments | Originate intl payments |
| write:api_keys | Create/revoke other keys |
| * | All of the above |
Rate limits
The default per-key limit is 100 requests / minute sliding window. Hit the
ceiling and you'll get HTTP 429 with x-ratelimit-reset-ms telling you when to retry.
For higher limits, contact us — we have per-key overrides in the database.
Idempotency
All POST and PATCH endpoints accept an Idempotency-Key header. Use a UUIDv4:
curl -X POST https://api.sorenpay.com/api/cards \
-H "authorization: Bearer apk_<your key>" \
-H "idempotency-key: $(uuidgen)" \
-H "content-type: application/json" \
-d '{...}'Replays within 24h return the cached response. Conflicting bodies on the same
key return HTTP 422 idempotency_key_mismatch so you can detect bugs.
KYB gating
In live mode, money-movement routes (cards, intl payments, ramp) require
the workspace's kyb_status === 'approved'. Sandbox skips this gate so you can
build against the full API surface before keys arrive.
Webhook signing (inbound)
Every webhook we receive carries a provider-specific signature header. We verify
HMAC-SHA256 over the raw body with a ±5min replay window. Dedup is enforced
by a unique (provider, event_id) index on webhooks_inbound.
Webhook signing (outbound)
When you register an outbound endpoint we generate a signing secret. Each
delivery carries Soren-Signature: t=<unix>,v1=<hmac> so you can verify on
your side. See Notifications.