Base URL: http://localhost:8091 (local) / https://api.europe-login.glorylabs.nl (prod — legacy domain; 2026-05-19 decision is to migrate europeLogin under mahmoudholding. GHCR migration PR in flight: #76. Final product domain still to be chosen.)
Interactive docs: GET /swagger-ui.html
All error responses follow RFC 7807 shape:
{ "status": 400, "message": "...", "timestamp": "...", "details": null }
Authenticate a company representative.
Request
{
"kvkNumber": "12345678",
"email": "bestuurder@company.nl",
"password": "Secr3t!",
"requiredAssuranceLevel": "BASIS"
}
Response 200
{
"accessToken": "<JWT>",
"tokenType": "Bearer",
"expiresIn": 3600,
"sessionToken": "<UUID>",
"kvkNumber": "12345678",
"companyName": "Acme BV",
"assuranceLevel": "BASIS",
"representativeEmail": "bestuurder@company.nl",
"representativeName": "Jan de Vries",
"representativeRole": "BESTUURDER"
}
Errors
400 — invalid KvK format401 — wrong credentials404 — KvK not registeredRegister a company with its first BESTUURDER representative.
Request
{
"kvkNumber": "12345678",
"companyName": "Acme BV",
"legalForm": "BV",
"registeredAddress": "Hoofdstraat 1, Amsterdam",
"representativeFirstName": "Jan",
"representativeLastNamePrefix": "de",
"representativeLastName": "Vries",
"representativeEmail": "jan@acme.nl",
"representativePhone": "0612345678",
"password": "Secr3t!"
}
Response 201 — empty body
Revoke the current session. Public endpoint (no JWT required).
Headers
X-Session-Token: <UUID from login>
Response 204 — empty body
Get company info. Requires JWT.
Response 200
{
"kvkNumber": "12345678",
"companyName": "Acme BV",
"assuranceLevel": "BASIS",
"active": true,
"kvkVerified": true,
"createdAt": "2024-01-01T10:00:00Z"
}
Validate a KvK number format and check KvK registry. Public endpoint.
Response 200
{ "kvkNumber": "12345678", "valid": true }
All /api/onboarding/** endpoints are public. The sessionId acts as a bearer secret.
Initiate onboarding session.
Request
{ "kvkNumber": "87654321" }
Response 201
{
"sessionId": "<UUID>",
"kvkNumber": "87654321",
"companyName": "New Company BV",
"currentStep": "BANK_CONNECT",
"status": "KVK_VERIFIED"
}
Errors
400 — invalid KvK format, company already registered, or active session in progressGet session state (for polling).
Response 200 — OnboardingSessionDto with all session fields
Start PSD2 bank authentication.
Request
{
"institutionId": "ING_INGBNL2A",
"redirectUri": "http://localhost:4301/onboarding/psd2-callback"
}
Response 200
{
"redirectUrl": "https://bankaccountdata.gocardless.com/...",
"requisitionId": "<UUID>"
}
Complete PSD2 after bank redirect.
Request
{ "ref": "<ref from bank callback>" }
Response 200 — updated OnboardingSessionDto
Add representative identity (BSN is encrypted before storage).
Request
{
"firstName": "Jan",
"lastNamePrefix": "de",
"lastName": "Vries",
"email": "jan@company.nl",
"phone": "0612345678",
"bsn": "123456782",
"role": "BESTUURDER"
}
Response 200 — updated OnboardingSessionDto
Finalise onboarding — creates Company + AuthorizedRepresentative records.
Request
{ "password": "Secr3t!" }
Response 200 — final OnboardingSessionDto with status: "COMPLETED"
List available banks for PSD2 (cached 1 hour).
Response 200
[
{ "id": "ING_INGBNL2A", "name": "ING", "bic": "INGBNL2A", "logoUrl": "..." },
...
]
All audit endpoints require JWT + BESTUURDER role.
Get paginated audit trail for a company.
Query params: page (default 0), size (default 50, max 200)
Response 200
{
"content": [
{
"id": "...",
"eventType": "LOGIN_SUCCESS",
"actorEmail": "jan@company.nl",
"actorKvkNumber": "12345678",
"actorRole": "BESTUURDER",
"result": "SUCCESS",
"assuranceLevelUsed": "BASIS",
"timestamp": "2024-01-01T10:00:00Z"
}
],
"totalElements": 42,
"totalPages": 1
}
Verify hash chain integrity.
Response 200
{
"intact": true,
"eventsChecked": 142,
"brokenAtId": null
}
| HTTP | When |
|------|------|
| 400 | Validation failure, bad KvK format, duplicate company, onboarding flow error |
| 401 | Missing or invalid JWT, wrong credentials |
| 403 | Authenticated but insufficient role (AccessDeniedException) |
| 404 | Company not found |
| 409 | Duplicate company registration |
| 500 | Unhandled server error |
| 502 | GoCardless/PSD2 connectivity error |
Reacties