Authentication & scopes
Sending your key
Every route under /api/v1/partner/... and /api/v2/public/... requires a tenant-scoped API key.
Send it as X-Api-Key: <key>, or as Authorization: Bearer <key> โ not both on the same request.
curl https://api.kwiikpay.io/api/v1/partner/test -H "X-Api-Key: kwp_live_..."
Scopes
Each key carries one or more scopes that gate which operations it can perform. Common ones:
| Scope | Grants |
|---|---|
onboarding:read / onboarding:write |
Read/create customers, run KYC/KYB |
accounts:read / accounts:write |
Read/manage fiat accounts and beneficiaries |
wallets:read / wallets:write |
Read/manage crypto wallets and deposit addresses |
transactions:read / transactions:write |
Read/create withdrawals and conversions |
webhooks:read / webhooks:write |
Read/manage outbound webhook subscriptions |
A key that lacks the scope a route requires gets 403 Forbidden. Request only the scopes your
integration actually needs โ a key that only reads balances shouldn't also be able to move money.
Tenant-wide vs. subject-bound keys
A key is bound either to your whole tenant, or to a single subject (one specific customer or
business). A subject-bound key can only see and act on its own subject's data โ requesting
another customer's resource with it returns 404, identical to that resource not existing at all.
This is deliberate: it means a subject-bound key can never distinguish "not mine" from "doesn't
exist," so it can't be used to enumerate other customers by probing IDs.
If you're issuing a key to an end customer of yours (for example, so their own systems can read their own balance), always use a subject-bound key scoped to just them.
Rate limits
Each route enforces a per-key rate limit; exceeding it returns 429 with a Retry-After header.
A tenant-wide aggregate ceiling also applies across all of a tenant's calls combined, so a burst
spread across many different routes can still hit a limit even if no single route is over its own
threshold.