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.