Getting started¶
Sandbox is a full mirror of production with synthetic bureau data and instant, deterministic financing decisions. Nothing there touches a real company register or moves real money.
Authentication¶
Request a token with your client credentials, then send it as a bearer token. Tokens last one hour — request a new one when it expires rather than on every call.
curl -X POST https://api.noja.fi/partner/v1/oauth/token \
-H "Content-Type: application/json" \
-d '{
"grantType": "client_credentials",
"clientId": "noja_live_7f2a...",
"clientSecret": "••••••••",
"scope": "clients:write invoices:write decisions:read"
}'
{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"tokenType": "Bearer",
"expiresIn": 3600,
"scope": "clients:write invoices:write decisions:read"
}
Scopes¶
| Scope | Grants |
|---|---|
clients:write |
Create clients, push onboarding data, submit applications |
clients:read |
Read client state, credit limits, pricing, history coverage |
invoices:write |
Send and update invoices, request financing |
decisions:read |
Read financing decisions and settlement state |
webhooks:manage |
Register and remove webhook endpoints |
Request only the scopes you need. A token missing a scope returns 403 forbidden naming the one it lacked.
Your first call¶
Create a client. Both this call and the invoice call below work before any onboarding has happened — the invoice simply waits.
curl -X POST https://api.noja.fi/partner/v1/clients \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: 9c1e-onboard-68123456" \
-d '{
"countryCode": "NL",
"registrationNumber": "68123456",
"companyName": "Van Dijk Installatietechniek",
"contact": {
"firstName": "Sanne",
"lastName": "van Dijk",
"email": "sanne@vandijk-installatie.nl",
"phone": "+31612345678"
},
"consent": {
"obtainedAt": "2026-09-14T09:31:04Z",
"method": "in_product_checkbox",
"evidenceRef": "ptr-consent-4471a9"
}
}'
Your second call¶
Send one of that client's invoices as history.
curl -X POST https://api.noja.fi/partner/v1/invoices \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: inv-68123456-2026-0388" \
-d '{
"client": { "countryCode": "NL", "registrationNumber": "68123456" },
"invoiceNumber": "2026-0388",
"direction": "receivable",
"counterparty": {
"name": "Bouwgroep Rotterdam B.V.",
"registrationNumber": "24398871",
"countryCode": "NL"
},
"amount": { "amount": 312000, "currency": "EUR" },
"issueDate": "2026-06-02",
"dueDate": "2026-07-02",
"paymentStatus": "paid",
"paymentDate": "2026-07-11"
}'
That is the whole integration in miniature. Everything else is volume, onboarding, and reacting to webhooks.
Sandbox behaviour¶
Sandbox is deterministic so you can write tests against it.
| Input | Sandbox response |
|---|---|
Registration number starting 9999 |
Client is auto-approved on creation, with a €25,000 limit |
Invoice amount ending .00 |
Financing approved |
Invoice amount ending .13 |
Financing declined, reason debtor_risk |
| Any other amount | Decision after roughly 30 seconds, approved |
Registration number 99990000 |
Onboarding always completes instantly, no signing required |
Sandbox never sends email, never calls a credit bureau, and never creates a real signing document.