Authentication
All Koard API requests must be authenticated using an API key passed in the x-koard-apikey header.
curl https://api.koard.com/v1/accounts/YOUR_ACCOUNT_ID \
-H "x-koard-apikey: YOUR_API_KEY" \
-H "Accept: application/json"
Headers
| Header | Required | Value |
|---|---|---|
x-koard-apikey |
Always | Your Koard API key |
Accept |
Always | application/json |
Content-Type |
When sending a body | application/json |
The header name is case-insensitive — x-koard-apikey and X-Koard-apikey are equivalent.
API Keys
API keys are provisioned per account. A partner-level key can manage merchants and terminals under it. A merchant-level key (a key bound to a merchant account) is limited to that merchant's own operations.
Retrieve or rotate your API key from the Koard MMS under your account settings, or manage keys programmatically via the API Keys endpoints.
Keep your API key secret. Never expose it in client-side code or public repositories.
Key Format
Keys issued through the current (v5) API have the format:
{prefix}_{lookup}_{secret}
prefixiskrd_livein production andkrd_uatin the UAT sandbox.lookupis a 12-character segment used to locate the key.secretis a 32-character segment; only its salted hash is stored.
The full plaintext key is returned exactly once, in the response to the create request — Koard never stores it and cannot show it again. Store it securely at creation time. On every later read, only the last four characters of the secret (key_last4) are returned so you can identify a key without exposing it.
Legacy keys issued before v5 (format krd_{token}) continue to authenticate, but auto-expire on 2026-07-31. Migrate to scoped v5 keys before then.
Scoped Permissions
Each v5 key carries an explicit list of permissions. A permission is a string in the form resource:action (for example payments:read, terminals:create) or resource:action:subtype (for example accounts:create:merchant). A key can do only what it has been granted — there are no implicit grants. In particular, holding a write permission does not imply the matching read permission.
Two macro permissions exist: all grants every concrete permission (for trusted server-side backends), and legacy_all is a grandfathered bucket set only on migrated pre-v5 keys (it cannot be granted to new keys).
| Resource | Actions |
|---|---|
payments |
tap-ios, tap-android, read, refund, tipadjust, capture, incremental-auth, void, confirm |
batches |
read, open, edit, close |
terminals |
read, create, edit, delete |
locations |
read, create, edit, delete |
accounts |
read, create:partner, create:merchant, edit, delete |
credentials |
read, create, edit, delete |
apikeys |
read, create, edit, delete (and the :sub variants below) |
webhooks |
read, create, edit, delete (Koard PSP only) |
Own account vs. sub-accounts
API-key management permissions are split by surface. The base form (apikeys:read, apikeys:create, apikeys:edit, apikeys:delete) governs keys on your own account. The :sub variants (apikeys:read:sub, apikeys:create:sub, apikeys:edit:sub, apikeys:delete:sub) govern keys on descendant (sub-) accounts. These are distinct grants — holding the self permission never satisfies a sub-account operation, and vice versa.
Privilege-escalation guard
When you create a key, you may only grant permissions you yourself hold. Requesting a permission outside your own grant is rejected with 403. The webhooks:* permissions can only be granted by Koard PSP accounts.
Visibility: 401 vs 404
When a key lacks a permission, the response distinguishes between "denied" and "invisible":
- If your key holds some permission on the target resource type but not the specific operation, you get
401. - If your key holds zero permissions on the target resource type (the resource is invisible to you), you get
404— out-of-scope resources are hidden, never advertised.
Key Lifecycle
| Action | Effect |
|---|---|
Create (POST) |
Issues the key and returns the plaintext once. Defaults to a long expiry; pass expires_at to set your own. |
Revoke (PUT with status: "revoked") |
Disables the key for authentication. Recoverable — reinstate with PUT status: "active". |
Reinstate (PUT with status: "active") |
Re-enables a revoked key. Does not work on a deleted key. |
Delete (DELETE) |
Permanent soft-delete. The key can never be reinstated. Idempotent — repeating the call returns the same deleted key. |
Expire (expires_at passes) |
The key stops authenticating automatically. |
Permissions are immutable after creation — a PUT may change name, expires_at, and status only. To change a key's permissions, create a new key and delete the old one.
Revoking or deleting a key takes effect immediately: in-flight sessions authenticated with that key are locked out.

