Developers · Authentication
One header, two kinds of key.
Every request carries the key as a Bearer token. Keys are stored as SHA-256 hashes; a key is shown once, when it is created.
The header
POST /v2/validate-and-fix Host: www.invoicenavigator.eu Authorization: Bearer sk_live_… Content-Type: application/json
Without the header the request is rejected with 401 UNAUTHORIZED before it reaches the engine. The Bearer header also exempts the call from the browser CSRF check, so server-to-server calls need nothing else.
{
"success": false,
"error": {
"code": "UNAUTHORIZED",
"message": "Missing Authorization header. Use: Authorization: Bearer YOUR_API_KEY"
}
}Key prefixes
| Prefix | Issued | Behaviour |
|---|---|---|
| sk_live_ | On sign-up; regenerate in the dashboard. | Metered: 100 requests a month on Free, 5,000 on Team. Flows are stored, evidence packs are signed. |
| sk_test_ | Next to every live key; also without an account. | Same engine, not metered, 100 requests an hour. Responses carry X-Test-Mode: true and meta.testMode. No flow is stored, so no fixWithInput follow-up. |
Details on the test keys under Test keys.
Getting a key
- 01
- Without an account: POST /api/developers/instant-key. 10 requests, one hour.
curl -X POST https://www.invoicenavigator.eu/api/developers/instant-key
- 02
- With an account: sign up, then Dashboard → API. A live and a test key are created together; both can be regenerated there. No card is needed for Free.
- 03
- Keep the key in an environment variable on the server. It must not appear in browser code or a repository; revoke and regenerate it if it does.
Authentication errors
| Status | Code | When |
|---|---|---|
| 401 | UNAUTHORIZED | No Bearer header, or the key is unknown. |
| 401 | KEY_EXPIRED | An instant test key past its hour. |
| 402 | QUOTA_EXCEEDED | Monthly quota used up, or the 10 instant-key requests. details.upgradeUrl points to the Team checkout. |
| 403 | KEY_INACTIVE | The key was revoked. |
| 403 | INSUFFICIENT_TIER | A Team-only endpoint called with a Free key. |
| 429 | RATE_LIMITED | Too many requests in the sliding hour. Retry-After is set. |
The complete contract, including headers and what to retry, is in the API reference.