Getting Started

API Documentation

Corporate card issuing API for managing users, cardholders, and virtual cards.

Prefer a different format?

Workflow pages

Use the workflow pages for step-by-step operational guidance.

Transport, auth, and encryption

All v1 endpoints live under /api/v1 and require the API-KEY header. Every request body is an encrypted envelope that wraps the decrypted JSON payload.

Encrypted envelope

The only field in the HTTP body is encrypted. The value is the base64 ciphertext of your decrypted JSON.

FieldTypeRequiredDescription
encrypted
stringRequiredBase64 XSalsa20-Poly1305 ciphertext containing the decrypted JSON payload.
JSON
{
  "encrypted": "<base64-secretbox-ciphertext>"
}

Decrypted payload

Inside the encrypted payload, you must include request_timestamp in microseconds. The server enforces a 30 second window and rejects duplicates. All endpoint-specific fields are placed at the root level alongside request_timestamp — do not wrap them in a data object.

FieldTypeRequiredDescription
request_timestamp
integerRequiredMicroseconds since epoch (string or integer). Must be within 30 seconds of server time.
...endpoint fields
anyOptionalEndpoint-specific fields placed at the root level. See each endpoint for the exact fields.
JSON
{
  "request_timestamp": 1700000000000000,
  "user_id": "ext-123"
}

Required headers

  • API-KEY for authentication.
  • Content-Type: application/json for all requests.
  • Idempotency-Key for card issue and topup requests.
HTTP
API-KEY: your-api-key
Content-Type: application/json
Idempotency-Key: unique-request-id

Error format

API returns semantically correct HTTP status codes: 200 for success, 4xx for client errors, and 5xx for server errors. Error details are returned inside the encrypted payload using a standard error object.

Standard error object

FieldTypeRequiredDescription
success
booleanRequiredAlways false for errors.
error
stringRequiredHuman-readable error message.
error_slug
stringRequiredStable machine-readable error code.
JSON
{
  "success": false,
  "error": "Invalid request",
  "error_slug": "invalid_request"
}

Unencrypted auth and encryption errors

If authentication or encryption fails, the response is not encrypted and does not follow the standard error schema.

ErrorHTTPWhen
API key not found404Unknown API-KEY value.
You do not have access to this API.403API-KEY is valid but lacks access.
Encrypted payload not found400Missing encrypted envelope in body.
Invalid encrypted payload format400Malformed encrypted field or payload.
Request timestamp not found in encrypted payload400Missing request_timestamp inside decrypted payload.
Invalid timestamp format400request_timestamp is not a valid integer.
Request timestamp outside allowed window400Timestamp is outside the 30 second window.
Duplicate request detected400Same api_key + url + request_timestamp reused.

Common error slugs

Error responses now return semantically correct HTTP status codes. Use the error_slug field for programmatic error handling.

Error SlugHTTPDescription
invalid_request400Request payload failed validation.
invalid_amount400Amount is invalid or negative.
idempotency_key_required400Missing Idempotency-Key header for mutation.
insufficient_funds403Master balance is too low for the operation.
user_not_found404User with the given external_user_id does not exist.
card_not_found404Card with the given card_id does not exist.
cardholder_not_found404Cardholder not found for external_user_id.
order_not_found404Order with the given order_id does not exist.
external_user_id_exists409A user with this external_user_id already exists.
cardholder_already_exists409A cardholder already exists for this user.
card_not_active422Card is not in active status for this operation.
card_user_mismatch422Card does not belong to the specified user.
internal_error500Unhandled server error.
provider_error502External card provider returned an error.
topup_attempts_exceeded503Maximum retry attempts exceeded. Try again later.

Idempotency and replay protection

The platform enforces two layers of protection: replay protection for all endpoints, and business idempotency for card issue and topup.

  • Replay protection deduplicates api_key + url + request_timestamp for 30 seconds.
  • For /cards/create and /cards/topup, the Idempotency-Key header is required.
  • Retried requests with the same idempotency key return the original order without double charging.

Status models

Orders and cards move through predictable states. Use these transitions when you design polling and retries.

View Status Models