Build on StixBNK β‘
StixBNK is a programmable platform for open banking routing and electronic invoicing. Route account-to-account pay-ins across providers, issue EN 16931 / Factur-X aligned invoices with hosted pay-by-bank links, and reconcile everything through one webhook schema β sandbox first, live after KYB.
What you can build
-
Open banking collections with a hosted
checkout_urlfor every pay-in - Electronic invoices (EN 16931 / Factur-X) with PDF + payment link in one issue
- Multi-provider routing by payer market β one API, normalised events
- Invoice settlement on the same open banking rails as API checkout
- Webhook-driven reconciliation for collections and invoice payments
- Sandbox simulators before KYB β same contract for test and production
Start here
Send X-API-Key on every merchant API request.
Receive open_banking.collection.updated (open banking and APM) with HMAC signatures.
Try collections and invoices against sandbox from the browser.
POST amount, market, reference β get checkout_url back.
How integration usually goes
- 1 Register, open the merchant portal, and create sandbox API keys.
- 2 Read authentication and webhook guides β one schema for checkout and invoices.
- 3 Create a test collection or invoice in sandbox; open the hosted checkout link.
- 4 Register your webhook URL in Merchant β Webhooks and verify signatures.
- 5 Complete KYB; switch to live keys when approved β same API contract.
Authentication
Merchant REST endpoints require an API key in the header:
X-API-Key: YOUR_API_KEY
Create keys in the merchant portal after registration. Use sandbox keys while KYB is in review; live keys activate routing on production open banking providers.
https://stixbnk.com (or your deployment host). All paths below are relative to this origin.
Webhooks
Configure outbound webhooks in Merchant β Webhooks. The primary event for pay-ins is:
open_banking.collection.updated
The same event is used for open banking (account-to-account) and APM (Bancontact, iDEAL, Przelewy24, β¦). Distinguish them with data.source.
Provider webhooks (Stripe payment_intent.*, charge.*, bank redirects, β¦) are ingested by StixBNK only. They are not forwarded to you. You receive one outbound POST when funds are collected (collection_status sent or settled), and one on failure / cancellation / expiry.
Verify X-Webhook-Signature β hex HMAC-SHA256 of the raw request body using your signing secret.
The payload includes your business reference, amount, currency, collection_status, and sandbox flag. Invoice settlements include invoice identifiers when linked.
Envelope β Β· Open banking example β Β· APM example β
Envelope
| Field | Type | Description |
|---|---|---|
id | string | Event id |
type | string | open_banking.collection.updated (open banking and APM) |
created | integer | Unix timestamp |
livemode | boolean | false in sandbox |
data | object | Collection fields below |
data
| Field | Type | Description |
|---|---|---|
source | string | open_banking for account-to-account (Bridge, CoreSettle, Stripe Pay by Bank). APM for Stripe alternative methods (Bancontact, iDEAL, β¦) |
payment_method | string | Present when source is APM β Stripe method key, e.g. bancontact, ideal, p24 |
reference | string | Your order reference |
amount | number | Major units |
currency | string | EUR, GBP, β¦ |
market | string | ISO 3166-1 alpha-2 payer market |
collection_status | string | Platform status (pending, sent, settled, failed, β¦) |
sandbox | boolean | Present and true for sandbox collections |
Example β source: open_banking
{
"id": "evt_6aa218f45f6e3",
"type": "open_banking.collection.updated",
"created": 1789008116,
"livemode": false,
"data": {
"source": "open_banking",
"actor_type": "merchant",
"payment_request_id": "pay_abc123",
"reference": "SANDBOX_1789006303316",
"amount": 45,
"currency": "EUR",
"market": "FR",
"collection_status": "sent",
"transfer_status": "succeeded",
"transaction_id": 138,
"linked_merchant_id": null,
"callback_error": null,
"callback_error_reason": null,
"transaction_status": "completed",
"sandbox": true,
"livemode": false,
"purpose": "merchant_collection"
}
}
Example β source: APM (Bancontact)
{
"id": "evt_6aa218f45f6e3",
"type": "open_banking.collection.updated",
"created": 1789008116,
"livemode": false,
"data": {
"source": "APM",
"payment_method": "bancontact",
"actor_type": "merchant",
"payment_request_id": "pi_3UDxvpGuok3qQCPy0wgxskzD",
"reference": "SANDBOX_1789006303316",
"amount": 45,
"currency": "EUR",
"market": "BE",
"collection_status": "sent",
"transfer_status": "succeeded",
"transaction_id": 138,
"linked_merchant_id": null,
"callback_error": null,
"callback_error_reason": null,
"transaction_status": "completed",
"sandbox": true,
"livemode": false,
"purpose": "merchant_collection"
}
}
Sandbox & go-live
Use dedicated sandbox API paths for integration testing β no sandbox: true flag on live URLs.
POST /api/v1/payments/merchant/sandbox/requestsβ create test collectionGET /api/v1/payments/merchant/sandbox/statusβ poll test collectionGET/POST /api/v1/invoices/sandboxβ sandbox invoicesGET/POST /api/v1/invoices/sandbox/item.phpβ single sandbox invoice
Live production providers use /api/v1/payments/merchant/requests (no sandbox flag) after KYB approval.
Hosted checkout is always returned as checkout_url. Redirect payers there; poll GET /api/v1/payments/merchant/status or rely on webhooks for final status.
Settlement and merchant payout run on platform T+5 schedules in fiat or USDC depending on your programme.
Electronic invoicing
The merchant portal and /api/v1/invoices support structured billing aligned with EN 16931 and Factur-X field sets β buyer identity, VAT category, line items, and document profile.
When you issue an invoice, StixBNK generates the human-readable document (HTML/PDF), optional Factur-X XML artefact, and a hosted pay-by-bank checkout_url on the same open banking routing layer as API collections.
-
Draft in the portal or POST
/api/v1/invoiceswithissue: true - Email PDF + payment link; payer completes bank SCA on hosted checkout
- Webhook marks invoice paid when the bank confirms β same event schema as checkout
Base URL
https://stixbnk.com
Authenticated requests: header X-API-Key: YOUR_API_KEY
Open banking routing + invoicing & payment links on one stack.
Collections
Live production collection. Returns payment_request_id + checkout_url. For integration testing use POST /api/v1/payments/merchant/sandbox/requests instead.
Required (body)
| Field | Type | Description |
|---|---|---|
amount | number | Major units, > 0 |
currency | string | EUR or GBP |
market | string | ISO country for OB routing (e.g. FR). GBP requires GB |
reference | string | Globally unique business reference |
product_name | string | Line item label (max 255). Or product.product_name |
Optional (body)
| Field | Type | Description |
|---|---|---|
description | string | Human-readable description |
locale | string | Provider locale (e.g. fr_FR) |
language | string | Short code (en, fr) |
customer_email | string | Payer email |
customer_first_name | string | Payer first name |
customer_lastname | string | Payer last name |
store_name | string | Store / brand label |
success_url | url | Absolute success redirect (alias urlok) |
failure_url | url | Absolute failure redirect (alias urlko) |
Poll order status with order_id. Refreshes from the provider when possible.
Query (required)
| Field | Type | Description |
|---|---|---|
order_id |
string | Your unique order reference |
Example
GET /api/v1/payments/merchant/status?order_id=ORDER_123
Response highlights
| Field | Type | Description |
|---|---|---|
source | string | open_banking or APM |
payment_method | string | Present for APM β e.g. bancontact, ideal |
reference | string | Your order reference |
collection_status | string | Platform collection status (pending, sent, settled, failed, β¦) |
paid | boolean | true when the payer has completed payment |
transaction_status | string | Linked ledger transaction status when present |
checkout_url | url | Hosted checkout link (may be expired) |
Invoices API
Optional (query)
| Field | Type | Description |
|---|---|---|
status | string | Filter: draft, sent, paid, void, overdue, expired |
Required (body)
| Field | Type | Description |
|---|---|---|
customer | object | name, email required |
line_items | array | [{description, quantity, unit_amount, tax_rate_percent}] |
Optional (body)
| Field | Type | Description |
|---|---|---|
currency | string | Default EUR |
market | string | Default FR |
due_at | string | Due date |
notes | string | Free text |
issue | boolean | Create payment link immediately (alias send) |
Required (query)
| Field | Type | Description |
|---|---|---|
id | integer | Invoice id |
Required (query)
| Field | Type | Description |
|---|---|---|
id | integer | Invoice id |
Required (body)
| Field | Type | Description |
|---|---|---|
action | string | update, send, issue, email, or void |
Optional
Extra fields for action=update (customer, line_items, meta)