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.