Get started
Authentication
Everything a developer calls on BaxPay authenticates with one of two credentials, both sent the same way — as a Bearer token:
| Credential | Prefix | Who uses it | Typical calls |
|---|---|---|---|
| API key | bx_test_… / bx_live_… | your backend servers | e-invoicing, clients, sessions overview, webhooks data |
| Connection credential | bxc_… | a till, pump, or kiosk | opening and driving in-store payment sessions |
Accounting OAuth (Pennylane / QuickBooks / Sage) does not use a merchant-supplied bxc_ for
vendor login — merchants approve BaxPay from Developers → Accounting. See
Accounting & ERP sync.
API keys
Create keys in the Business dashboard under Developers. Every key
is pinned to your business and to a mode: a bx_test_ key can only ever read and write
sandbox data, a bx_live_ key only live data. There is no header or flag to switch — the key
is the mode (see Sandbox & test mode). Call https://sandbox-api.baxpay.com/v1 with
test keys and https://api.baxpay.com/v1 with live keys.
curl https://sandbox-api.baxpay.com/v1/einvoices \
-H "Authorization: Bearer bx_test_9f2a4c8e1d…"// One small helper for every call: base URL, key, JSON, and the `data` envelope.
async function baxpay(path, { method = 'GET', body, idempotencyKey } = {}) {
const res = await fetch(`https://sandbox-api.baxpay.com/v1${path}`, {
method,
headers: {
Authorization: `Bearer ${process.env.BAXPAY_API_KEY}`,
...(body && { 'Content-Type': 'application/json' }),
...(idempotencyKey && { 'Idempotency-Key': idempotencyKey }),
},
body: body && JSON.stringify(body),
});
const json = await res.json();
if (!res.ok) throw new Error(`${res.status} ${JSON.stringify(json.message)}`);
return json.data;
}
const invoices = await baxpay('/einvoices');
console.log(JSON.stringify(invoices, null, 2));Check a key
GET /ping tells you which business and which mode a key belongs to. It's the quickest
way to confirm a key works before writing anything else.
curl https://sandbox-api.baxpay.com/v1/ping \
-H "Authorization: Bearer $BAXPAY_API_KEY"const res = await fetch('https://sandbox-api.baxpay.com/v1/ping', {
headers: { Authorization: `Bearer ${process.env.BAXPAY_API_KEY}` },
});
console.log(JSON.stringify(await res.json(), null, 2));import json, os, requests
res = requests.get(
"https://sandbox-api.baxpay.com/v1/ping",
headers={"Authorization": f"Bearer {os.environ['BAXPAY_API_KEY']}"},
)
res.raise_for_status()
print(json.dumps(res.json(), indent=2)){
"success": true,
"data": {
"ok": true,
"livemode": false,
"merchantId": "6f1c2a9e-…"
},
"timestamp": "2026-11-06T10:42:00.000Z",
"path": "/v1/ping"
}Every response is wrapped like this: data holds the result, and success, timestamp and path
describe the call.
Connection credentials
In-store systems don't use your API key. Each till or pump lane gets its own bxc_ credential,
provisioned from Developers → Connections or the connections API.
(Accounting ERP OAuth is separate — Accounting.)
Authorization: Bearer bxc_q7Vd2kP9xR4mT1sN…Scope them narrowly. One credential per site or lane costs nothing and means a compromise at one till doesn't hand an attacker the whole estate — revoking it disturbs exactly one machine.
Like API keys, connection credentials are shown once at creation and stored hashed. A credential has no mode in its prefix: it belongs to the mode of the key or dashboard that created it, and only ever opens sessions in that mode.