Signing in & 2FA
Audience: 🧑💼 Company Admin
A signed-in company admin administers a company (inviting users, setting up bank connections, issuing API keys). An API key gets 403 on these routes. Your integration's credential is covered in Authentication.
The admin session (control plane)
Administering a company means authenticating as an admin and using a session token.
POST /api/auth/login
Body: { "email": "…", "password": "…" }
→ 200 { expiresAt, user, csrfToken } + Set-Cookie: bc_session=…
(a TOTP 2FA step-up often follows)
The raw session token is never in that JSON body. It is only in the Set-Cookie: bc_session=… header. A browser carries it from there automatically; a scripted (non-browser) caller captures it with a curl cookie jar (-c) and sends it back as its own header on every later call:
X-Session-Token: <token read out of the bc_session cookie>
In a sandbox, the POST /api/sandbox/provision response's dashboardLogin gives you the email and a setPasswordUrl link. Open it to choose a password (single-use, expires after 7 days), then log in with that email and password, as the admin of your sandbox company (login takes no subdomain; the email alone identifies the account). The web UI uses the same session, carried in an httpOnly bc_session cookie and a bc_csrf token. Sessions last 8 h absolute and expire after 30 min idle.
See Managing companies & users for the control-plane workflow with curl examples.
Two-factor authentication (2FA)
Admin sessions can be protected with TOTP 2FA:
- Enroll:
POST /api/2fa/setupreturns a secret + provisioning URI; confirm the first code withPOST /api/2fa/confirm.POST /api/2fa/disableremoves it. Both ask for your currentpasswordbeside the code. (These self-service routes have no/authprefix.) - Login step-up: when 2FA is enabled,
POST /api/auth/loginreturns a challenge; submit the TOTP (or a backup) code toPOST /api/auth/2fato obtain the session. - Company-wide policy: an admin can require 2FA for every user in the company with
POST /api/company/require-2fa({ "enabled": true }). - Lost authenticator: first try one of your backup codes at sign-in, each works once. Otherwise another admin of your company clears your 2FA with
POST /api/admin/2fa-reset, sending youruserIdwith the admin's own currentpasswordand the admin's own currentcode(orbackupCode). - Lost authenticator, and no other admin can help: when you are your company's only admin, or no other admin is enrolled, contact BankConnector support. Support checks who you are, then sends a confirmation link to your account's own email address. Nothing changes until you open that link and press Confirm the reset (
POST /api/auth/2fa-reset/confirm). That clears your second factor and signs you out everywhere; you then sign in with your password and set up a new authenticator. The link works once and expires after 30 minutes. Support never sees it. If you get the email without having asked, ignore it and tell your company's admin.
How an API key is issued
An API key is minted by an admin of the company it will belong to (session), in the UI or via POST /api/company/api-keys with { "label": "erp-production" } → 201 { "id": "apk_…", "key": "key_…", … }. The key is bound to that one company. The raw key is in that response and nowhere else; listing keys (GET /api/company/api-keys) returns metadata only (id, label, createdAt, lastUsedAt). Revoking (DELETE /api/company/api-keys/<id>) is a soft delete (kept for audit). Creating and revoking a key both ask for a fresh second factor when the admin has 2FA enabled or the company requires it: send "code" (or "backupCode") in the JSON body, on the DELETE too, or the call answers 422 totp_required (422 totp_enrollment_required when the company requires 2FA and the admin has not set it up). A provisioned sandbox already returns a key.
The integration uses that key on the data plane; see Authentication.