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 shown when the key was issued.
curl 'https://api.bitcall.io/v1/otp/activations' \
  --header 'x-key-id: ak_live_1a2b…' \
  --header 'x-api-secret: 9f83…'

Each header must be single-valued. A duplicate or array-valued header is ignored, which then reads as if it were absent.

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

request.mjs
const res = await fetch('https://api.bitcall.io/v1/esim/plans?region=Europe&pageSize=50', {
  headers: {
    'x-key-id': process.env.KEY_ID,
    'x-api-secret': process.env.SECRET,
  },
});

A POST adds only a body and its content type:

const res = await fetch('https://api.bitcall.io/v1/esim/orders', {
  method: 'POST',
  headers: {
    'x-key-id': process.env.KEY_ID,
    'x-api-secret': process.env.SECRET,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify({ planId: 'pln_…', email: '[email protected]' }),
});

The secret is displayed only when the key is issued or rotated, 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. A leaked secret authorizes every endpoint your key can reach — purchases included — until the key is rotated.

Keeping your secret safe

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. Nothing binds the credential to a particular path or body, so a secret read out of a log is enough to call anything your key can call.

Two controls carry the weight:

  • Use an IP allowlist. A key restricted to your servers' addresses is useless to anyone who reads it out of a log. Set one when you create the key in the Bitcall panel — see Get & Manage Keys.
  • Rotate on any suspicion. Rotation is immediate: a new key id and secret are issued and the old key stops working at once. See API Keys & Secrets.

Keep the secret on a server you control. A request made from a browser or a mobile app ships the secret to the device, where any user can read it.

What the gateway checks, in order

Any failure stops the request immediately — it is never forwarded to a product:

  1. Both headers present. Missing credentials → 401 AUTHENTICATION_REQUIRED.
  2. Key id is known and active.
  3. Source IP is allowed, if the key has an IP allowlist.
  4. Secret matches, compared in constant time.
  5. Account is in good standing.
  6. The product is enabled for your account and your key may call this endpoint.
  7. Rate limit not exceeded — see Rate Limits.

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 IP allowlist is checked against the address the gateway sees. If you call from behind a proxy or NAT, allowlist the egress addresses your traffic actually leaves from, not your internal ones.

On this page