API Key Management
Manage scoped API keys with /v5/apikeys. Send your existing key in the X-Koard-apikey header. Use the API URL and key for the same environment: https://api.uat.koard.com for UAT or https://api.koard.com for production.
The API Keys reference lists request fields and current permissions. Authentication explains how permissions control access.
Create a key
curl -X POST 'https://api.uat.koard.com/v5/apikeys' \
-H 'X-Koard-apikey: YOUR_EXISTING_API_KEY' \
-H 'Content-Type: application/json' \
-d '{"name":"Server integration","permissions":["terminals:read"],"expires_at":"2030-01-01T00:00:00Z"}'
name and a non-empty permissions array are required. Use permission values such as terminals:read, rather than a scopes field. Unknown fields and invalid permissions are rejected. You can grant only permissions your existing key holds. Admin-only permissions also require an admin or PSP account.
Omit account_id, or send null, to create the key on your own account. To create it for a descendant account, supply that account's ID and use a key with apikeys:create:sub. Creating a key on your own account requires apikeys:create.
expires_at is optional. Provide an ISO 8601 / RFC 3339 date-time, such as 2030-01-01T00:00:00Z. Omission or null applies an expiry 100 years from creation.
The HTTP 201 response contains the plaintext in key, along with its metadata:
{
"id": "YOUR_NEW_KEY_ID",
"account_id": "YOUR_ACCOUNT_ID",
"name": "Server integration",
"key": "GENERATED_KEY_RETURNED_ONCE",
"key_last4": "abcd",
"permissions": ["terminals:read"],
"status": "active",
"expires_at": "2030-01-01T00:00:00Z",
"created_at": "2026-10-10T17:00:00Z",
"last_used_at": null,
"is_legacy": false,
"always_retrievable": false
}
This response uses placeholder identifiers and key text. Save the actual generated key securely when you receive it. Subsequent reads return key: null; use key_last4 to identify it. Existing legacy keys and supplied keys created with always_retrievable: true can return plaintext on reads. always_retrievable requires a caller-supplied key in the valid v5 format for the environment.
List or read keys
GET /v5/apikeys
GET /v5/apikeys?account_id=YOUR_MERCHANT_ACCOUNT_ID
GET /v5/apikeys/YOUR_KEY_ID
Listing returns an array; reading one key returns its metadata object. apikeys:read grants access to keys on your own account. apikeys:read:sub grants access to descendant accounts. Omitting the listing's account_id filter returns the accounts allowed by those permissions; supplying it narrows the result to a visible account. Admins can see all accounts.
Update, revoke or reinstate
Use PUT /v5/apikeys/{key_id}. You can change only name, expires_at, and status; permissions are immutable. Omitted or null values leave the corresponding field unchanged.
{
"name": "Renamed integration",
"expires_at": "2030-01-01T00:00:00Z"
}
To temporarily disable the key:
{
"status": "revoked"
}
To reinstate a revoked key:
{
"status": "active"
}
Reinstating a key does not extend its expiry. An expired key still cannot authenticate. These operations require apikeys:edit for your own account or apikeys:edit:sub for a descendant. A successful update returns HTTP 200 and the updated metadata.
Delete or rotate
DELETE /v5/apikeys/{key_id} permanently deletes the key. It returns HTTP 200 with key metadata and status: "revoked". Repeating DELETE returns the same deleted key. A deleted key cannot be reinstated.
Deletion requires apikeys:delete for your own account or apikeys:delete:sub for a descendant. To rotate, create a replacement key, update your integration, then delete the old key. Use a different authorized key when deleting one that currently authenticates your requests.
Errors
API-key errors use the same response structure:
{
"error": "validation_error",
"message": "Request validation failed",
"details": "permissions: at least one permission is required"
}
The details text varies with the failure. Branch on error and HTTP status.
| HTTP status | Meaning |
|---|---|
| 400 | Invalid request, including empty permissions, an unknown field, invalid status, or invalid supplied key. |
| 401 | Authentication failed, or your key sees API-key resources but lacks the requested operation permission. |
| 403 | You requested a permission you do not hold, or an admin-only grant that your account cannot issue. |
| 404 | The key or target account does not exist, is deleted or outside your hierarchy, or your key has no API-key resource access. |
legacy_all can appear on migrated keys. It cannot be requested when creating a new key; use explicit permissions or all where appropriate.

