Bitcall logoBitcall API

Authentication

Authenticate requests to the gateway with your key id and secret.

Every request to a /v1/* endpoint is authenticated with two headers: your key id and your secret, both sent as-is. There is nothing to compute, sign, or time — a request you write once keeps working.

Required headers

HeaderValue
x-key-idYour key id, e.g. ak_live_… or ak_test_….
x-api-secretYour secret — the 128-hex-character string returned at key creation.

Each must be single-valued; duplicate or array-valued headers are rejected.

curl 'https://api.khalil.chatup.ch/v1/otp/history' \
  --header 'x-key-id: ak_live_1a2b…' \
  --header 'x-api-secret: 9f83…'

That is the whole scheme. It works identically from curl, Postman, a browser, or any language.

The secret is displayed only at creation (and rotation) and is never retrievable again. Treat it like a password: keep it server-side, out of client-side code, out of version control, and out of screenshots. If it leaks, rotate the key — a leaked secret authorizes every endpoint your key's scopes allow, including purchases, until you do.

What the gateway checks, in order

Any failure stops the pipeline immediately:

  1. Both headers present.
  2. Key id is known and active.
  3. Source IP is allowed (if the key has an IP allowlist).
  4. Secret matches (constant-time comparison).
  5. Tenant exists and is not suspended/blocked.
  6. Key's role is high enough for the route.
  7. Product feature is enabled and the key holds the required scope.
  8. Rate limit not exceeded.

Sending no credentials returns 401 with error.code set to AUTHENTICATION_REQUIRED. Sending credentials that are not accepted returns 401 INVALID_API_KEY — and an unknown key, a wrong secret, a revoked key and a disallowed IP all look identical on purpose, so nobody can probe which key ids are real. See Errors.

The gateway checks the real network source address and ignores X-Forwarded-* headers. If you deploy it behind a proxy, terminate and forward correctly at the infrastructure layer.

Keeping a secret safe in transit

Because the secret travels on every request, it reaches anything that records request headers — reverse-proxy access logs, APM traces, WAF captures, your own shell history. Two habits matter more here than they would with a signed scheme:

  • Use an IP allowlist. A key restricted to your servers' addresses is useless to anyone who reads it out of a log. Ask your Bitcall admin to set allowedIps on production keys.
  • Rotate on any suspicion. Rotation is immediate and issues a new secret; the old one stops working at once.

HMAC signing (existing integrations)

The gateway also still accepts the earlier HMAC-signed form — x-key-id plus x-signature, x-timestamp, and x-nonce, where the signature is an HMAC-SHA256 over a canonical description of the request. Integrations built against it keep working unchanged, and nothing needs to migrate.

It remains the stronger option where you can afford the extra work: the secret never leaves your server, a captured request cannot be replayed (the nonce is single-use and the timestamp is bounded to ±5 minutes), and the signature commits to the exact method, path, query, and body. If you are integrating from a server you control and want that, ask us for the signing contract — it is unchanged.

New integrations should use the two-header form above.

On this page