Managing companies & users
Audience: 🏗️ Platform Operator · 🔌 Integration Client (control-plane setup)
In production, your platform is the tenant you own, and it holds many companies — typically one per end-customer organisation you serve. Each company is isolated: its own payments, its own bank connections, its own users. Your API key acts _within_ one company at a time by passing its companyId.
Creating and managing those companies and users is a control-plane action. It is not something an API key can do (that returns 403 — see Authentication); you do it as a signed-in workspace admin with a session token. The sandbox lets you exercise this exact flow end to end.
Step 1 — Log in as the workspace admin
POST /sandbox/provision returns a dashboardLogin object with the admin's subdomain, email, and password. Log in to get a session:
curl -X POST https://sandbox.bankconnector.com/auth/login \
-H "Content-Type: application/json" \
-d '{
"subdomain": "sb-…",
"email": "dev-…@sandbox.bankconnector.com",
"password": "…"
}'
# 200 — returns a session (in the web UI this is an httpOnly cookie; for a
# non-browser caller, carry it as the X-Session-Token header on later calls)
Send that token on every control-plane call:
export BC_SESSION="…"
export BC_PLATFORM="plat_…" # platformId from the provision response
Step 2 — Create a company
A company is one of your end-customers. In the sandbox, always create it sandboxOnly so it can never deliver a real production payment:
curl -X POST "https://sandbox.bankconnector.com/platforms/$BC_PLATFORM/companies" \
-H "X-Session-Token: $BC_SESSION" \
-H "Content-Type: application/json" \
-d '{ "name": "Contoso Ltd", "sandboxOnly": true }'
# 201 { "id": "comp_…", "name": "Contoso Ltd", "sandboxOnly": true, ... }
This is a workspace-admin route: an API key gets
403 forbiddenhere. That's by design — spinning up a company reshapes your tenant, so it's a human/admin action.
Note the returned id (comp_…). That's the companyId your API key will pass on data-plane calls to act as this company.
Step 3 — Create a user
Users are the humans who sign in to a company — to view payments, approve them, or administer it. Roles are admin, approver, and/or viewer; at least one is required. Scope the user with platformId + companyId in the body:
curl -X POST https://sandbox.bankconnector.com/users \
-H "X-Session-Token: $BC_SESSION" \
-H "Content-Type: application/json" \
-d '{
"platformId": "'"$BC_PLATFORM"'",
"companyId": "comp_…",
"email": "ops@contoso.example",
"name": "Contoso Ops",
"password": "a-strong-password",
"roles": ["approver", "viewer"]
}'
# 201 { "id": "usr_…", "email": "ops@contoso.example", "roles": ["approver","viewer"], ... }
Omit password to send an email invite instead — the user sets their own password via a one-time link (needs email configured on the instance; otherwise create with a password). Only an admin session may create users.
Step 4 — Act as that company from your integration
Once a company exists, your API key does the payment work — no session needed. The key already implies your platform; you pass the new company's companyId:
curl -X POST https://sandbox.bankconnector.com/journal/payments \
-H "X-API-Key: $BC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: contoso-inv-8841" \
-d '{
"companyId": "comp_…",
"bankKey": "danske-dk",
"environment": "test",
"payment": { ... }
}'
The isolation model, in one picture
Platform (you — one API key)
├─ Company A (comp_…) → its own payments, connections, users
├─ Company B (comp_…) → isolated from A
└─ Company C (comp_…)
- One API key per platform. It can address any company on the platform by passing that company's
companyId— so if you need hard isolation between end-customers, give each its own platform. Confirm your tenancy model with your operator. - Session = control plane, key = data plane. Creating companies/users and setting up bank connections is a session-admin action; sending and reading payments is the API key's job. Keeping them separate means a leaked integration key can't reshape your tenant.
Where to go next
- Wire a real bank connection (a UI/session step) → Going Live
- Send payments as a company → Submitting Payments
- The credential split in full → Authentication