API Key Types
All Partner API requests require an API key passed as a Bearer token:
Authorization: Bearer sk_personal_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
There are three key types:
| Type | Prefix | Created by | Scope |
|---|
| Personal | sk_personal_ | Any staff panel user | That user’s assigned exchanges and permissions |
| Branch | sk_branch_ | Superadmin only | All exchanges in the branch |
| Public | pk_ | Superadmin only | Read-only access to a branch’s public data |
Secret vs Public Keys
Secret keys (sk_personal_*, sk_branch_*) have full read/write access — they can create orders, register clients, and manage webhooks.
Public keys (pk_*) are read-only and can only access the Public endpoints:
GET /partner/public/exchanges
GET /partner/public/currencies
GET /partner/public/rates
POST /partner/public/estimate
Public keys are designed for embedding in client-facing applications (e.g., landing pages, rate widgets) where you want to display exchange rates without exposing write access. If a pk_* key is used on a write endpoint, the API returns 403 Forbidden.
Secret keys (sk_*) can also access all public endpoints — you don’t need a separate public key if you already have a secret key.
Creating API Keys
API keys are managed via the staff panel or via the management API (requires JWT session):
# Create a personal key (any panel user)
curl -X POST https://api.example.com/api/v1/api-keys \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"name":"My CRM","type":"personal"}'
# Create a branch key (superadmin only)
curl -X POST https://api.example.com/api/v1/api-keys \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"name":"Branch Integration","type":"branch","branchId":1}'
# Create a public key (superadmin only)
curl -X POST https://api.example.com/api/v1/api-keys \
-H "Authorization: Bearer <JWT>" \
-H "Content-Type: application/json" \
-d '{"name":"Rate Widget","type":"public","branchId":1}'
The response includes the raw key exactly once:
{
"id": "3fa85f64-5717-4562-b3fc-2c963f66afa6",
"keyPrefix": "sk_personal_Ab3xQw",
"name": "My CRM",
"type": "personal",
"isActive": true,
"rawKey": "sk_personal_Ab3xQw...",
"note": "Store this key securely — it will not be shown again."
}
Save the rawKey value immediately. It is hashed and stored server-side and cannot be retrieved again.
Key Expiry
Pass expiresAt (ISO 8601) to create a key with an expiry date:
{ "name": "Temp key", "type": "personal", "expiresAt": "2026-12-31T23:59:59Z" }
Expired keys return 401 Unauthorized.
Revoking Keys
curl -X DELETE https://api.example.com/api/v1/api-keys/<id> \
-H "Authorization: Bearer <JWT>"
Multi-Tenancy Guarantee
A personal key resolves to the creating user. All order/client queries are automatically scoped to that user’s permitted exchanges — a key from Branch X cannot access Branch Y data.
A branch key resolves to a branch-level principal that spans all exchanges within that branch.
A public key resolves to a read-only branch-level principal — it can view exchange data within its branch but cannot create or modify any resources.