Authentication
Test keys and live keys, payments and data scopes, rotation, going live.
Every call to the 221 Pay API carries an API key of a project. The key identifies the project and its mode; 221 Pay creates the project's merchant account on the first authenticated call.
Test keys and live keys
| Test key | Live key | |
|---|---|---|
| Prefix | sk_221_pay_test_ | sk_221_pay_live_ |
| Money | No real money: simulated confirmation. | Real money: funds collected and paid out. |
| Creation | As soon as the project exists. | Once the project's live mode is activated. |
Previously issued 221pay_test_, 221pay_live_ and sk_221_ keys remain valid until they expire or are revoked.
A key is the prefix, 43 base62 characters and a 6-character checksum (CRC32). A malformed key is refused before any lookup. Pattern to detect a key in a code repository or in logs:
\b(?:sk_221_pay_|221pay_)(test|live)_[0-9A-Za-z]{43}[0-9A-Za-z]{6}\bCreate a key
221 Pay dashboard, Developers > API keys (project administrator):
| Setting | Values |
|---|---|
| Name | 1 to 60 characters. |
| Mode | test (default) or live. |
| Lifetime | No expiry, 30 days, 90 days or 1 year. |
| Scopes | payments, data, or both (default). |
A project has at most 5 active keys.
Shown only once
221 Pay keeps only the secret's hash and a visible prefix. The secret goes into the server's secret manager; if it is lost, revoke the key and create another.
Send the key
Authorization: Bearer sk_221_pay_test_…curl "$API_URL/v1/balances" -H "Authorization: Bearer $API_KEY"The key stays server side: never in a browser, never in a published mobile app.
Scopes
| Scope | Grants access to |
|---|---|
payments | All 221 Pay routes: payments, links, refunds, payouts, balances. |
data | The 221 API data routes (geography, public holidays, banks…). |
A key without the payments scope receives 403 MISSING_SCOPE on 221 Pay
routes. A key dedicated to 221 Pay, with only the payments scope, limits the
impact of a leak. The project's webhook routes accept any key of the project,
whatever its scope.
Daily quota
221 Pay routes have no daily quota: only the limit of 600 requests per minute
per project applies (Errors). The daily quota covers data
routes only (data scope).
Each key carries a daily_limit, the number of data calls it can make per day.
It is set when the key is created through the API (POST /v1/projets/{id}/cles,
integer of at least 1) and cannot exceed a key's default limit, which also
applies when it is omitted. The account has its own limit, shared by all its
keys and projects. Server defaults: 1,000 calls per key and per account; 5,000
per key and 10,000 per account when the identity is verified, and a key of a
verified account counts as at least 5,000. The counter resets at midnight UTC.
Developers > Usage shows the values in force and today's consumption. Project owners receive an e-mail at 80% and then 100% of a key's quota.
Beyond that, the call receives 429 QUOTA_EXCEEDED with Retry-After
(seconds until midnight UTC):
HTTP/1.1 429 Too Many Requests
RateLimit-Limit: 5000
RateLimit-Remaining: 0
Retry-After: 21887
{"code": "QUOTA_EXCEEDED", "message": "Daily quota of the account or key reached.", "request_id": "2f6c9a0e-5b1d-4e7f-8c3a-9d0b1e2f3a4c", "limit": 5000, "reset_at": "2026-10-08T00:00:00.000Z"}See also Authentication and keys.
Role of a key
A key acts with the administrator role on its project: it creates payments, links, refunds and payouts. The administrator who created it is accountable for its use. The roles of project members are described in Dashboard.
Project id
$PROJECT_ID is the project id in the /v1/projets/{id}/… routes. A key reads
it itself, whatever its scope:
curl "$API_URL/v1/moi/cle" -H "Authorization: Bearer $API_KEY"{ "project_id": "…", "mode": "test", "scopes": ["payments", "data"], "name": "Shop server" }project_id is the value of $PROJECT_ID. This route requires a key: the
dashboard session receives 401.
The dashboard also shows it, inside the merchant ID, in the form
p221_<project id>: Home > Developers > Credentials, "Merchant ID" row
(copy button). Remove the p221_ prefix. This block of the Home screen appears
once an active API key exists.
Do not confuse it with the "Identifier" field of My account > Account,
"Project" card: that is the project's short name (slug), which the API refuses
(404) in place of the id. With the dashboard session, GET /v1/projets also
returns each project's id.
Rotation
Rotation replaces a key with a new one, with the same name, mode, scopes and
quota. The old key stays valid for the chosen grace period, while the new one
is deployed: now (revoked at once), 1h, 24h or 7d.
Dashboard, Developers > API keys, or with the dashboard session:
curl -X POST "$API_URL/v1/projets/$PROJECT_ID/cles/$KEY_ID/rotate" \
-H "Cookie: $SESSION_COOKIE" \
-H "Content-Type: application/json" \
-d '{"grace": "24h"}'The response holds the new secret, shown only once, and rotated_from, the id
of the replaced key.
Go live
A project administrator activates live mode, with an explicit confirmation: live keys move real money.
curl -X PUT "$API_URL/v1/projets/$PROJECT_ID/live" \
-H "Cookie: $SESSION_COOKIE" \
-H "Content-Type: application/json" \
-d '{"live_enabled": true, "acknowledged": true}'The change is logged. Live keys are then created in Developers > API keys.
GET /v1/projets/{id}/live returns live_enabled.
Server mode: gateway_mode
curl -s "$API_URL/v1/balances" -H "Authorization: Bearer $API_KEY" | jq -r .gateway_mode
curl -s "$API_URL/health" | jq -r .payments.gateway_mode| Value | Meaning |
|---|---|
simulated | Simulator: no real money. |
real | Real operators. |
not_wired (in /health) | 221 Pay not connected on this server: 221 Pay routes answer 503 PAYMENTS_UNAVAILABLE. |
The test journey is described in Testing.
Authentication errors
| Status | code | Cause |
|---|---|---|
| 400 | PROJECT_REQUIRED | Dashboard session without a designated project (X-221-External-Ref). |
| 401 | INVALID_API_KEY | Key malformed, unknown or revoked. |
| 401 | UNAUTHENTICATED | Neither key nor session, or key of another project. |
| 403 | MISSING_SCOPE | Key without the payments scope. |
| 403 | FORBIDDEN | Role insufficient for the action (session of a read-only member, for example). |
A key can be revoked at any time by a project administrator, or disabled by 221 in case of abuse.