Get & Manage Keys
Create a key from the Bitcall panel, capture the secret, and rotate or revoke it later.
You issue your own keys from the Bitcall panel — there is nothing to request and nobody to wait for. This page walks you from a Bitcall account to a working key, then through managing it afterwards.
For what a key is — key id versus secret, environments, what a key carries — see API Keys & Secrets. This page is the how-to.
Before you start
You need a Bitcall account, and you need to be logged in to the panel.
Self-service key management is enabled per account, so it is not switched on everywhere. If you cannot find the section described in the next step — not in the avatar menu, not on your profile — then it is not enabled for your account. Contact Bitcall and ask for API key access; it is not something you can turn on yourself.
Open the API keys section
Keys live in your profile, under API Keys. There are two ways in:
- From the avatar menu. Click your avatar in the top-right corner, then API Keys.
- From your profile. Open your profile and select the API Keys tab.
Both land on the same page — /<language>/profile/api-keys, for example /en/profile/api-keys.
If neither the menu item nor the tab is there, key self-service is not enabled for your account. That is the symptom to report to Bitcall.
Create the key
Click Create key in the top-right of the Bitcall panel — or Create your first key if you have none yet. The Create API key dialog opens with two fields.
Scopes
Scopes decide what the key is allowed to do. At least one is required, and the dialog starts with otp:read already selected. Options are grouped by product — OTP, eSIM, HLR / Lookup — and you can select as many as you need.
| Scope | Grants |
|---|---|
otp:read | Every read on the OTP client surface — catalog, history, order status. |
otp:write | Every OTP mutation — renting a number, cancelling, refunds. |
esim:read | Every read on the eSIM client surface — plans, orders, profile status. |
esim:write | Every eSIM mutation — purchases, top-ups, cancellations. |
hlr:read | Every read on the HLR client surface — pricing, job status, results. |
hlr:write | Every HLR mutation — submitting lookup jobs. |
The model is uniform across products: <service>:read covers the reads, <service>:write covers the writes. Grant both for full access to a product, or one alone for a read-only or write-only key. Granting nothing for a product means the key cannot touch it at all.
These six are the only scopes a key of yours can hold. Higher-privilege scopes exist for operators, but a client key can never carry one — the gateway drops them when it computes the key's effective scopes, even if one were somehow granted.
Allowed IPs / CIDRs
Optional, and comma-separated. Leave it empty and the key works from any address; fill it in and requests from anywhere else are rejected.
Set it on anything production. The secret travels on every request, so it reaches every proxy log and trace along the way — a key pinned to your servers' addresses is useless to whoever reads it out of one.
The allowlist is matched against the address the gateway actually sees. Behind a proxy or NAT, list the egress addresses your traffic leaves from, not your internal ones.
What you do not choose
Three properties are set server-side and are not in the dialog: the key's role, the account it is bound to, and its rate limit. A key you create can only ever act as your own account — it cannot be pointed at another one.
Click Create key to issue it.
Copy the secret — you get one chance
The Key created — copy the secret now dialog shows the two values, each with a copy button:
| Field | Format |
|---|---|
| Key ID | ak_live_… or ak_test_… — the prefix, then 64 hex characters. |
| Secret (shown once) | 128 hex characters. |
Store the secret before you click Done. There is no reveal endpoint and no support request that can recover it — the gateway keeps only an encrypted copy it can verify against, never one it can show you. Closing this dialog discards the secret permanently, and the only way back is to rotate the key for a fresh one.
Put it straight into a secret manager or your deployment's environment configuration. Do not paste it into a ticket, a chat message, or a file you will commit.
Make a request
Send the key id and secret as two headers. A read-only catalog endpoint is the cheapest way to prove the key works:
curl 'https://api.bitcall.io/v1/otp/countries' \
--header 'x-key-id: ak_test_1a2b…' \
--header 'x-api-secret: 9f83…'This endpoint needs otp:read, which is the scope the create dialog preselects — so a key made with the defaults runs it unchanged. If you deselected otp:read, call something your key's scopes actually cover instead.
A working key returns 200 and the country list. A wrong, revoked or unauthorized one returns 401 with error.code set to INVALID_API_KEY.
See Authentication for the full contract and the order the gateway checks things in.
Your key list
Once you have keys, the page lists them:
| Column | What it shows |
|---|---|
| Key ID | Shortened for readability, with a button that copies the full value. |
| Scopes | The scopes granted at creation. |
| Status | Active or Revoked. |
| Created | When the key was issued. |
| Last used | When it last authenticated a request, or Never. |
You can narrow the list by Status and by scope, and the table pages once you have more than ten keys. Last used is the quickest way to spot a key nothing is calling any more — a good candidate for revoking.
Rotating a key
Rotation replaces a key with a fresh one. Use it on any suspected leak, and on a schedule for long-lived integrations.
Click the rotate icon on the key's row and confirm in the Rotate this key? dialog. What happens:
- A new key id and a new secret are issued, carrying over the same scopes, IP allowlist and rate limit.
- The old key is revoked immediately — it stops authenticating the moment you confirm.
- The new secret is shown once, in the same one-time dialog as at creation.
Rotation issues a new key id, not just a new secret. Updating only x-api-secret in your app will not work — you must update both headers.
To roll it out without downtime, capture the new pair from the dialog, deploy both values together, then confirm traffic has moved by watching Last used on the new key. Because the old key dies the instant you confirm, do the rotation when you are ready to deploy, not hours ahead.
Revoking a key
Click the revoke icon and confirm in the Revoke this key? dialog. The key stops authenticating at once, permanently — there is no undo, and anything still using it starts failing immediately.
Rotate and revoke are both disabled on a key that is already revoked.
Rate limits
Above the list, the Bitcall panel shows your account rate limit — for example 1000 requests / 60s.
That quota belongs to your account and is shared across every key you hold. Issuing more keys does not buy more throughput. If you need a higher limit, ask Bitcall; more credentials will not give you one.
See Rate Limits for what happens when you exceed it.
When a call is rejected
A 401 with error.code set to INVALID_API_KEY covers several situations deliberately, so work through them in order:
| Check | What to look for |
|---|---|
| Is the key still active? | Find it in the list — a Revoked key, or one you rotated away from, fails every request. |
| Are both headers right? | x-key-id and x-api-secret, each single-valued. A duplicate header is ignored, which reads as absent. |
| Is the secret the current one? | After a rotation the old secret is dead. Confirm your app has the pair from the most recent dialog. |
| Are you calling from an allowed address? | If the key has an IP allowlist, a request from anywhere else is refused. Check the egress address your traffic actually leaves from. |
| Does the key hold the scope? | An operation outside the key's scopes is refused the same way. Compare the endpoint against the Scopes column. |
These all answer identically on purpose — distinguishing them would let someone probe which key ids are real without holding a secret. Every response carries a requestId; quote it when you contact Bitcall support and the exact failing check can be confirmed. See Errors.
Sending no credentials at all is the one case that differs: that returns 401 AUTHENTICATION_REQUIRED.
Best practices
- One key per integration. Separate keys make revoking or rotating one system surgical instead of an outage for everything that shared a credential.
- Grant the narrowest scopes that work. A key that only reads cannot be used to spend money. Add
:writeonly where the integration genuinely writes. - Set an IP allowlist on production keys. It is the one control that survives a leaked secret.
- Test keys in development and CI, live keys only in production. The
ak_test_/ak_live_prefix tells you which you are holding. - Rotate on any suspicion, and on a schedule. Rotation is cheap; an unnoticed leak is not.
- Never ship a secret in client-side code. Anything sent to a browser or mobile app is readable by whoever holds the device.