Authentication
Your integration calls the API with an API key. A person who manages the company in the dashboard signs in with an admin session instead; that is covered in Signing in & 2FA.
| Credential | Header | Used for |
|---|---|---|
| API key | X-API-Key: key_… | your integration: payments, the journal, statements, reconciliation, webhooks, connection reads |
| Admin session | X-Session-Token: … | a person: bank connection setup, approval policies, approving payments, users, API keys |
The API key
X-API-Key: key_<64 hex characters>
- A key belongs to one company. Calls on that company's data take its id as
companyId, in the query string or the JSON body. Leaving it out is400 scope_required; naming any other company is403 forbidden, even one you also administer. An integration that serves several companies holds one key per company. - A key does not expire. It works until an Admin revokes it. To rotate, create a new key, switch your integration to it, then revoke the old one.
- The key is shown once, when it is created. Only a digest is stored, so a lost key cannot be recovered: create a new one.
curl "https://sandbox.bankconnector.com/api/journal/list?companyId=$BC_COMPANY" \
-H "X-API-Key: $BC_KEY" \
-H "BankConnector-Version: 2026-10-21"
You send no cookies, CSRF token or Origin header. Those apply only to a browser session.
Getting a key
An Admin of the company creates keys, in the dashboard under Company settings › API keys or from an admin session:
POST /api/company/api-keyswith{ "label": "erp-production" }answers201 { "id": "apk_…", "key": "key_…", "label": "erp-production", "createdAt": "…" }. Thekeyis in this response and nowhere else.GET /api/company/api-keyslists the active keys:id,label,createdAtandlastUsedAt, never the key.DELETE /api/company/api-keys/<id>revokes a key. The record is kept for the audit trail.
When the Admin has two-factor authentication set up, or the company requires it, creating or revoking a key also takes the current authenticator code (code) or a backup code (backupCode) in the body; without a valid one the answer is 422 totp_required, and an Admin who has not set it up in a company that requires it gets 422 totp_enrollment_required.
On the sandbox, sign up and create a key the same way; see Getting started.
What a key can do with users
A key can give your own staff read access without anyone using the dashboard:
- invite a user with the Viewer role (
POST /api/users); - change the roles of a user who is not an Admin, as long as the change grants neither Admin nor Approver (
PUT /api/users/<id>/roles); - re-send an invitation (
POST /api/users/<id>/reinvite).
It cannot invite or grant Admin or Approver, change an Admin's roles, deactivate or sign out a user, reset a password or erase a user. Those need an admin session. Still treat a production key as privileged: keep it in a secret manager and rotate it when staff change.
Headers
X-API-Key: key_…
BankConnector-Version: 2026-10-21 # pins the API version
Content-Type: application/json # on JSON bodies; a few routes take raw XML
Idempotency-Key: <key> # optional, on POST /api/journal/payments
Without BankConnector-Version a call runs on the baseline version; see API versioning & compatibility. For Idempotency-Key, see Idempotency. Every response carries an X-Request-ID to quote to support; Errors & retries covers it and the rate limits.
Auth failures
| Situation | Status | code |
|---|---|---|
| Missing, wrong or revoked key | 401 | unauthorized |
No companyId on a call on the company's data | 400 | scope_required |
companyId names another company | 403 | forbidden |
| Setting up or activating a bank connection (reading connections works with a key) | 403 | admin_required |
| Changing approval policies | 403 | admin_required |
| Creating or revoking API keys; deactivating, signing out, resetting the password of or erasing a user | 403 | admin_required |
| Approving or rejecting a payment | 403 | forbidden |
| Inviting or granting Admin or Approver, or changing an Admin's roles | 403 | forbidden |
Naming a bank account (PATCH /api/accounts/<id>) | 403 | forbidden |
A person's own settings and two-factor routes (/api/me/…, /api/2fa/…) | 403 | forbidden |
GET /api/auth/me, which describes a browser session | 401 | unauthorized |
A 401 means the key itself is the problem: check it. A 403 means the call will never succeed with a key, however often you retry; an admin session has to make it. Treat admin_required and forbidden the same way, and branch on the status: the table gives examples, not every route.