Getting Started
Audience: 🔌 Integration Client · 🏗️ Platform Operator
This page takes you from nothing to an executed payment in a sandbox — provision, send, read — with no signup.
🚀 Prefer to watch it first? The interactive playground provisions a sandbox in one click and animates the round-trip. This guide is the same flow in curl, with the detail behind each step.
What you'll have after Step 1
Nothing to install, no account to create. POST /sandbox/provision mints an isolated sandbox for you — your own platform, a company, an admin login, an API key, and an already-active demo bank connection. From there, two credentials matter (see Authentication for the full model):
- API key (
X-API-Key: key_…) — the machine credential for the data plane: submitting payments, reading results, webhooks. It identifies your platform, so you pass onlycompanyId, neverplatformId. - Admin session (from the
dashboardLogincreds) — the control plane, for creating companies/users and setting up bank connections. You don't need it for the payment loop below; see Managing companies & users.
Sandbox tenants are auto-deleted after 30 days of inactivity. Provision a fresh one any time — it's a single unauthenticated call.
Environments at a glance
BankConnector is multi-tenant SaaS: you connect to the vendor-run platform at bankconnector.com — your company gets a branded subdomain (https://<company>.bankconnector.com), and there's no infrastructure to run yourself.
Whichever host you're on, it runs in one of two postures:
| Posture | Demo bank | Auth | Use for |
|---|---|---|---|
| production | ❌ off | closed | live payments |
| sandbox | ✅ on | closed, real keys, TLS | integration testing |
The public sandbox.bankconnector.com turns every bank into a simulated Demo Bank (default danske-dk), and real-money sends are off engine-wide. Separately, each bank connection carries its own environment: test | production flag — a production posture refuses a production connection pointed at a bank's test host, and vice-versa.
⚠️ A sandbox posture alone does not guarantee no real money can move. The hard boundary is your company's
sandboxOnlyflag — asandboxOnlycompany (which is what provisioning creates) can never deliver aproduction-environment payment, on any posture. See Going Live for the full picture.
Step 1 — Provision a sandbox
No auth, no body required:
curl -X POST https://sandbox.bankconnector.com/sandbox/provision
You get back a 201 with everything you need:
{
"apiKey": "key_…", // data-plane credential (X-API-Key)
"companyId": "comp_…", // the company to act as
"platformId": "plat_…",
"baseUrl": "https://sandbox.bankconnector.com",
"subdomain": "sb-…",
"bank": { "key": "danske-dk", "name": "Danske Bank", "country": "DK" },
"dashboardLogin": { "url": "…", "subdomain": "sb-…", "email": "…", "password": "…" },
"firstPayment": { /* a copy-paste-ready first request */ }
}
Export the key so the snippets below can use it:
export BC_KEY="key_…"
export BC_COMPANY="comp_…"
The response's firstPayment object is a ready-to-send request for exactly this bank — you can POST it as-is. Want a different bank? Pass {"bankKey":"nordea-dk"} in the provision body (list them with GET /profiles).
Step 2 — (Optional) Preview a conversion
Before you commit anything to the journal, you can validate + convert a canonical payment to XML with no state change and no delivery:
curl -X POST https://sandbox.bankconnector.com/journal/payments/preview \
-H "X-API-Key: $BC_KEY" \
-H "Content-Type: application/json" \
-d '{
"companyId": "'"$BC_COMPANY"'",
"bankKey": "danske-dk",
"payment": { ... see Core Concepts for the full object ... }
}'
# 200 { ..., "xml": "<Document>...</Document>" }
A 200 means the payment is structurally valid and converts cleanly; a 422 returns the exact issues in error.details.issues. This is the cheapest way to iterate on your payload. (Note: no platformId — the key implies your platform.)
Step 3 — Submit a payment
Send it for real. In sandbox this exercises the full pipeline — validation → conversion → approval planning → async delivery to the demo bank — without moving money:
curl -X POST https://sandbox.bankconnector.com/journal/payments \
-H "X-API-Key: $BC_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 2f9a1c7e-order-10432" \
-d '{
"companyId": "'"$BC_COMPANY"'",
"bankKey": "danske-dk",
"environment": "test",
"payment": { ... }
}'
# 201 { "id": "...", "journalNo": "...", "status": "...", "xml": "...", "deliveryMode": "..." }
A 201 means accepted and converted — not sent. The bank send happens asynchronously, and the journal-document fields (id, journalNo, status, …) come back at the top level alongside xml and deliveryMode — there's no "document" wrapper.
Step 4 — Read the result
The demo bank replies after ~5 seconds with a real-format pain.002 + camt.053 that flow through the actual inbound parsers. Read the reconciled state:
curl -H "X-API-Key: $BC_KEY" \
"https://sandbox.bankconnector.com/journal/reconciliation?companyId=$BC_COMPANY"
# status "executed", state "cleared"
GET /journal/list?companyId=$BC_COMPANY gives the same as a paged list. See Receiving Results for webhooks + polling in depth.
Where to go next
- The shape of that
paymentobject → Core Concepts - Get idempotency right before any retry logic → Idempotency
- React to results → Receiving Results
- Managing many companies/users? That's a one-time admin task — see the Operate track: Managing companies & users