Developers › Building on the API
API keys
Verified 6 November 2026Explain this to your team →
A secret key authenticates every request. Send it as a bearer token:
curl https://api.secureprocessing.app/v1/payment_intents \
-H "Authorization: Bearer sk_test_..."There is no publishable key and nothing you can safely put in a browser. Every call goes from your server to ours, because every call either moves money or reads it.
client_secret. It is deprecated and has no effect: nothing in the API accepts it, because the card is entered on the bank’s own page and there is no browser-side step for it to authorise. It is still returned so nothing that reads it breaks. Do not build on it.Test and live
The prefix is the whole story. A sk_test_ key reaches test data and the bank’s sandbox; a sk_live_ key reaches real money. They do not see each other’s customers, payments, events or webhook endpoints, and a key cannot be pointed at the other set by any header or parameter.
| Prefix | Reaches | Available |
|---|---|---|
sk_test_ | Test data, sandbox cards | Immediately |
sk_live_ | Real cardholders, real settlement | Once your business is verified |
Live keys are issued only after we have verified your business with the bank. Until then the dashboard will not create one, and asking for one through the API returns an error rather than a key that would fail on first use.
Keys are managed from the dashboard, not the API
Creating, rolling and revoking keys all live under Developers → API keys in the dashboard, and a request to those endpoints carrying an API key is refused with permission_error. That is on purpose: a credential that can mint more credentials is a credential whose theft has no floor, and it means revoking a leaked key is something the thief cannot undo.
Shown once
A key appears in full exactly once, in the response that creates it. We store only a hash, so we genuinely cannot show it again — not as a policy, as a fact. If you lose it, roll it.
Rolling, and revoking
Rolling issues a replacement and gives the old key an expiry rather than killing it outright. Both work until the old one expires — 24 hours by default, up to 72, or 0 for an immediate cutover. The overlap exists because revoking the instant a new key is issued breaks the running integration between issuing and deploying, which is a self-inflicted outage during exactly the operation people perform because they are worried.
Revoking is immediate and has no overlap. That is the right tool when a key is already in the wrong hands: a few minutes of failed requests is cheaper than anything the alternative buys. Roll when you are being careful; revoke when you are being robbed.
When a key is refused
A wrong, revoked or wrong-mode key returns 401 with authentication_error. An unauthenticated request to any /v1 path returns the same 401 even when the path does not exist, deliberately: nobody should be able to map the API one guess at a time without a key. With a valid key, an unknown path returns 404 and unknown_endpoint.
{
"error": {
"type": "authentication_error",
"code": "api_key_invalid",
"message": "No valid API key provided",
"request_id": "req_naWpf7JTWdMBAori"
}
}Quote the request_id when you ask us about a request. Every response has one, including the ones that went right: it is the X-Request-Id response header, and on an error it is also in the body, as above — except on an idempotent replay, where the body is the original response and carries the original request’s id. You may send your own X-Request-Id — 1 to 64 letters, digits, _ or - — and we will use it and echo it back, so your logs and ours share one id.