API v1 · OpenAPI 3.1 · stabiel
API-referentie
Verstuur post vanuit je CRM, ERP of backoffice. Eén base-URL, authenticatie met Bearer-key, facturatie via je wallet — geen kaartbetaling per call.
Overzicht
Een stateless REST API, JSON in/out, versiebeheerd. Alle routes hebben prefix /v1.
- Base-URL
https://bjet24.com/api - Versie
v1 · OpenAPI 3.1 - Formaat
application/json - Auth
Bearer / X-Api-Key
Authenticatie
Elke aanvraag moet een geldige API-key bevatten in de Authorization-header (Bearer-formaat) of in de X-Api-Key-header. Keys hebben het formaat bjk_<id>_<secret>.
curl https://bjet24.com/api/v1/mails \
-H "Authorization: Bearer bjk_xxxxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"Beschikbare scopes
read— lezen van verzendingen, offertes, lijstensend— verzendingen aanmaken (debiteert wallet)webhooks— webhooks aanmaken/verwijderenaddresses— Het adresboek beheren (afzenders en ontvangers).
Maak en herroep je keys vanaf /account/api-keys.
Foutformaat
Alle fouten retourneren een 4xx of 5xx HTTP-status en een JSON-body met code (machine) en message (mens). Validatiefouten bevatten een issues-array.
{
"code": "VALIDATION_ERROR",
"message": "Invalid request body",
"issues": [
{ "path": ["pages"], "message": "Number must be greater than or equal to 1" }
]
}VALIDATION_ERRORBody voldoet niet aan het schema. Zie issues.UNAUTHORIZEDAPI-key ontbreekt of is ongeldig.FORBIDDENKey heeft niet de vereiste scope voor deze route.NOT_FOUNDResource niet gevonden of behoort niet tot je organisatie.INSUFFICIENT_FUNDSWallet-saldo onvoldoende om de verzendkost te dekken.PRICING_UNAVAILABLEPricing niet geconfigureerd voor de gevraagde zone/service. Contacteer support.
Idempotentie
Om duplicaten bij netwerk-retries te vermijden, geef een unieke externalId mee (typisch je CRM-id) bij POST /v1/mails. Herhaalde aanvragen met dezelfde externalId retourneren de bestaande verzending — geen nieuwe debiet.
Hoe werkt het
Ratebeperking
Limieten gelden per API-key. Aanvragen boven het quotum krijgen 429 met een Retry-After-header.
- Lezen (GET)
120 / min - Schrijven (POST, DELETE)
60 / min - Max burst
30
Offerte ophalen
/v1/quoteVereiste scope: readBerekent de totale prijs voor een service / zone / aantal pagina's. Geen debiet. Handig om het tarief client-side te tonen vóór verzending.
Body van de aanvraag
zonestringverplichtNATIONALINTERNATIONALVerzendzone. NATIONAL = België, INTERNATIONAL = buiten België.
serviceTypestringverplichtstandardpriorregisteredType postservice. registered voegt verzendbewijs en tracking toe.
pagesintegerverplichtTotaal aantal afgedrukte pagina's (1 tot 2000).
colorbooleanoptioneelstandaardfalseKleurendruk. Hoger tarief.
acknowledgmentReceiptbooleanoptioneelstandaardfalseOntvangstbewijs (enkel registered). Hoger tarief.
recipientCountintegeroptioneelstandaard1Aantal afzonderlijke ontvangers (1 tot 100). Vermenigvuldigt de eenheidsprijs.
Responses
- 200Offerte berekend. Totaal inclusief btw indien van toepassing.
- 400Ongeldige body. Zie issues.
- 401API-key ontbreekt of is ongeldig.
curl -X POST https://bjet24.com/api/v1/quote \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{
"zone": "NATIONAL",
"serviceType": "registered",
"pages": 3,
"color": false,
"acknowledgmentReceipt": false,
"recipientCount": 1
}'Presigned upload-URL
/v1/uploadsVereiste scope: sendRetourneert een PUT-URL voor S3, 10 minuten geldig. Upload je PDF of afbeelding, gebruik dan de geretourneerde key als s3Key in POST /v1/mails. Uploads gaan rechtstreeks naar S3 — geen grote payloads via onze API.
Body van de aanvraag
filenamestringverplichtOriginele bestandsnaam. Gebruikt voor logs en facturatie.
mimeTypestringverplichtapplication/pdfimage/jpegimage/pngimage/heicimage/heifMIME-type. PDF aanbevolen voor post; afbeeldingen worden automatisch geconverteerd.
sizeBytesintegerverplichtGrootte in bytes. Max 20 MB.
Responses
- 200Presigned URL geretourneerd. Upload binnen 10 minuten via PUT.
- 400Ongeldige body. Zie issues.
- 401API-key ontbreekt of is ongeldig.
curl -X POST https://bjet24.com/api/v1/uploads \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{
"filename": "contract.pdf",
"mimeType": "application/pdf",
"sizeBytes": 124532
}'Verzending aanmaken en versturen
/v1/mailsVereiste scope: sendPlaatst de verzending in de wachtrij en debiteert direct je wallet. Met dryRun=true wordt gevalideerd en getarifeerd zonder debiet of aanmaak. Geef externalId mee voor idempotentie en webhookUrl voor een per-verzending callback.
Body van de aanvraag
zonestringverplichtNATIONALINTERNATIONALVerzendzone. NATIONAL = België, INTERNATIONAL = buiten België.
serviceTypestringverplichtstandardpriorregisteredType postservice. registered voegt verzendbewijs en tracking toe.
pagesintegerverplichtTotaal aantal afgedrukte pagina's (1 tot 2000).
colorbooleanoptioneelstandaardfalseKleurendruk. Hoger tarief.
acknowledgmentReceiptbooleanoptioneelstandaardfalseOntvangstbewijs (enkel registered). Hoger tarief.
scheduledDropAtstring (ISO 8601)optioneelGeplande depositodatum/-tijd (ISO 8601). Indien afwezig, volgende cutoff.
recipientsRecipient[]verplichtLijst van ontvangers (1 tot 100). Elk krijgt een afgedrukt exemplaar.
senderSenderoptioneelAfzenderadres op de envelop. Indien afwezig, standaardadres van je account.
filesFile[]verplichtBestanden om af te drukken (1 tot 20). Worden in volgorde samengevoegd. s3Key komt van POST /v1/uploads.
externalIdstringoptioneelCaller-id (bv. CRM-id). Garandeert idempotentie.
webhookUrlstring (uri)optioneelWebhook-URL specifiek voor deze verzending. Overschrijft globale config.
dryRunbooleanoptioneelstandaardfalseIndien true, valideer en tarifeer zonder debiet of opslag. Antwoord identiek maar mailJobId is null.
Responses
- 201Verzending aangemaakt en in wachtrij. Wallet gedebiteerd.
- 200Idempotentie-hit — verzending bestond al met dezelfde externalId.
- 400Ongeldige body. Zie issues.
- 402Wallet-saldo onvoldoende. Laad op en probeer opnieuw.
- 503Pricing niet geconfigureerd voor zone/service.
curl -X POST https://bjet24.com/api/v1/mails \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{
"zone": "NATIONAL",
"serviceType": "registered",
"pages": 3,
"color": false,
"recipients": [{
"name": "Jean Dupont",
"line1": "Rue de la Loi 16",
"zip": "1000",
"city": "Brussels",
"country": "BE"
}],
"files": [{
"s3Key": "uploads/2026-05-19/8af9...c12.pdf",
"filename": "contract.pdf",
"mimeType": "application/pdf",
"sizeBytes": 124532
}],
"externalId": "crm-contract-7281"
}'Verzendingen oplijsten
/v1/mailsVereiste scope: readRetourneert je verzendingen, nieuwste eerst. Cursor-gepagineerd.
Queryparameters
statusstringoptioneelFilter op status (queued, printed, posted, delivered, failed).
externalIdstringoptioneelFilter op exacte externalId.
limitintegeroptioneelstandaard20Aantal resultaten per pagina (1 tot 100).
cursorstringoptioneelPaginatie-cursor uit het vorige antwoord.
Responses
- 200Gepagineerde lijst van verzendingen.
curl "https://bjet24.com/api/v1/mails?status=queued&limit=20" \
-H "Authorization: Bearer $BJET24_KEY"Eén verzending ophalen
/v1/mails/{id}Vereiste scope: readRetourneert het volledige detail: status, ontvangers, bestanden, bedragen, timestamps.
Padparameters
idstringverplichtId van de verzending (mj_…).
Responses
- 200Detail van de verzending.
- 404Resource niet gevonden.
curl https://bjet24.com/api/v1/mails/mj_01HZX5K8... \
-H "Authorization: Bearer $BJET24_KEY"Levenscyclus simuleren (sandbox)
/v1/mails/{id}/simulateVereiste scope: sendAlleen testmodus. Laat een sandbox-verzending door haar levenscyclus lopen en activeert de bijbehorende `test`-webhook. Zonder `to` gaat de verzending één stap vooruit (queued → printed → posted → delivered); met `to` springt ze rechtstreeks naar die status — bv. {"to":"failed"} om foutafhandeling te testen. Sandbox-verzendingen evolueren ook vanzelf: dit endpoint dient voor deterministisch testen op aanvraag. Geweigerd (403) met een live-sleutel.
Padparameters
idstringverplichtId van de verzending (mj_…).
Body van de aanvraag
tostringoptioneelprintedposteddeliveredfailedDoelstatus. Weggelaten: één stap vooruit. Waarden: printed, posted, delivered, failed. Een directe sprong activeert alleen de webhook van de bereikte status.
Responses
- 200Overgang toegepast — retourneert de vorige en de nieuwe status.
- 400Ongeldige body. Zie issues.
- 403Live-inloggegevens — simulatie is alleen voor testmodus.
- 404Resource niet gevonden.
- 409Overgang niet mogelijk (al in eindstatus of onbereikbaar doel).
# Test mode only — advance the sandbox mail one step
curl -X POST https://bjet24.com/api/v1/mails/mj_01HZX5K8.../simulate \
-H "Authorization: Bearer $BJET24_TEST_KEY"
# …or jump straight to a status (e.g. test failure handling)
curl -X POST https://bjet24.com/api/v1/mails/mj_01HZX5K8.../simulate \
-H "Authorization: Bearer $BJET24_TEST_KEY" \
-H "Content-Type: application/json" \
-d '{"to":"failed"}'Adressen weergeven
/v1/addressesVereiste scope: addressesGeeft de opgeslagen adresboekvermeldingen terug — afzenders en ontvangers. Filterbaar op type en zoektekst.
Queryparameters
kindstringoptioneelSENDERRECIPIENTFilter op adrestype.
qstringoptioneelZoektekst op naam, stad, postcode of label.
limitintegeroptioneelstandaard100Maximaal aantal teruggegeven adressen (1–200).
Responses
- 200De lijst met adresboekvermeldingen.
- 401API-key ontbreekt of is ongeldig.
curl "https://bjet24.com/api/v1/addresses?kind=RECIPIENT&limit=50" \
-H "Authorization: Bearer $BJET24_KEY"Een adres aanmaken
/v1/addressesVereiste scope: addressesSlaat een adres op in het boek — bijvoorbeeld om uw CRM-contacten te synchroniseren.
Body van de aanvraag
kindstringverplichtSENDERRECIPIENTAdrestype: afzender (SENDER) of ontvanger (RECIPIENT).
namestringverplichtNaam van de ontvanger of afzender.
line1stringverplichtEerste adresregel (straat en nummer).
line2stringoptioneelOptionele adrestoevoeging (bus, verdieping…).
zipstringverplichtPostcode.
citystringverplichtStad.
countrystringverplichtISO 3166-1 alpha-2-landcode (bv. BE).
labelstringoptioneelOptioneel intern label, bv. Hoofdkantoor of Klant X.
isDefaultbooleanoptioneelstandaardfalseStelt dit adres in als standaardadres voor zijn type.
Responses
- 201Het adres, in zijn publieke vorm.
- 400Ongeldige body. Zie issues.
curl -X POST https://bjet24.com/api/v1/addresses \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{
"kind": "RECIPIENT",
"name": "Jean Dupont",
"line1": "Rue de la Loi 16",
"zip": "1000",
"city": "Brussels",
"country": "BE",
"label": "Client 7281"
}'Een adres ophalen
/v1/addresses/{id}Vereiste scope: addressesGeeft één adresboekvermelding terug.
Padparameters
idstringverplichtAdres-identificatie.
Responses
- 200Het adres, in zijn publieke vorm.
- 404Resource niet gevonden.
curl https://bjet24.com/api/v1/addresses/adr_01HZX5K8... \
-H "Authorization: Bearer $BJET24_KEY"Een adres bijwerken
/v1/addresses/{id}Vereiste scope: addressesWerkt de opgegeven velden van een bestaand adres bij. Weggelaten velden blijven ongewijzigd.
Padparameters
idstringverplichtAdres-identificatie.
Body van de aanvraag
kindstringoptioneelSENDERRECIPIENTAdrestype: afzender (SENDER) of ontvanger (RECIPIENT).
namestringoptioneelNaam van de ontvanger of afzender.
line1stringoptioneelEerste adresregel (straat en nummer).
line2stringoptioneelOptionele adrestoevoeging (bus, verdieping…).
zipstringoptioneelPostcode.
citystringoptioneelStad.
countrystringoptioneelISO 3166-1 alpha-2-landcode (bv. BE).
labelstringoptioneelOptioneel intern label, bv. Hoofdkantoor of Klant X.
isDefaultbooleanoptioneelStelt dit adres in als standaardadres voor zijn type.
Responses
- 200Het adres, in zijn publieke vorm.
- 400Ongeldige body. Zie issues.
- 404Resource niet gevonden.
curl -X PATCH https://bjet24.com/api/v1/addresses/adr_01HZX5K8... \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{ "city": "Bruxelles", "isDefault": true }'Een adres verwijderen
/v1/addresses/{id}Vereiste scope: addressesVerwijdert een adres definitief uit het boek.
Padparameters
idstringverplichtAdres-identificatie.
Responses
- 200Adres verwijderd.
- 404Resource niet gevonden.
curl -X DELETE https://bjet24.com/api/v1/addresses/adr_01HZX5K8... \
-H "Authorization: Bearer $BJET24_KEY"Je webhooks oplijsten
/v1/webhooksVereiste scope: readRetourneert alle actieve webhook-endpoints op je account.
Responses
- 200Lijst van webhooks (zonder secret).
curl https://bjet24.com/api/v1/webhooks \
-H "Authorization: Bearer $BJET24_KEY"Webhook registreren
/v1/webhooksVereiste scope: webhooksMaakt een webhook-endpoint aan. Het signing secret wordt SLECHTS EENMAAL geretourneerd — bewaar het direct, het kan niet opnieuw worden opgehaald.
Body van de aanvraag
urlstring (uri)verplichtHTTPS-URL waar events worden gepost.
eventsstring[]verplichtMAIL_QUEUEDMAIL_PRINTEDMAIL_POSTEDMAIL_DELIVEREDMAIL_FAILEDLijst van events die je wil ontvangen. Minstens één vereist.
Responses
- 201Webhook aangemaakt. Bewaar het geretourneerde secret.
- 400Ongeldige body. Zie issues.
curl -X POST https://bjet24.com/api/v1/webhooks \
-H "Authorization: Bearer $BJET24_KEY" \
-H "Content-Type: application/json" \
-d '{
"url": "https://your-app.example.com/webhooks/bjet24",
"events": ["MAIL_QUEUED", "MAIL_POSTED", "MAIL_DELIVERED", "MAIL_FAILED"]
}'Webhook verwijderen
/v1/webhooks/{id}Vereiste scope: webhooksSchakelt het endpoint onmiddellijk uit. Events worden niet meer afgeleverd.
Padparameters
idstringverplichtId van de webhook (wh_…).
Responses
- 200Webhook verwijderd.
- 404Resource niet gevonden.
curl -X DELETE https://bjet24.com/api/v1/webhooks/wh_01HZX5K8... \
-H "Authorization: Bearer $BJET24_KEY"Webhook-events
Vijf events dekken de levenscyclus van een verzending. Elke aflevering bevat de JSON-payload, de X-Bjet24-Event-header en de handtekening.
MAIL_QUEUEDVerzending in wachtrij na walletdebet.MAIL_PRINTEDAfgedrukt in het atelier.MAIL_POSTEDAfgegeven op het postkantoor.MAIL_DELIVEREDBezorgd (enkel registered).MAIL_FAILEDDruk-, depot- of annulatiefout.
Voorbeeld payload
{
"event": "MAIL_POSTED",
"mailJobId": "mj_01HZX5K8...",
"externalId": "crm-contract-7281",
"status": "posted",
"postedAt": "2026-05-19T16:42:11.000Z"
}Handtekening & verificatie
Elke webhook-aflevering wordt ondertekend met HMAC-SHA256 met het secret dat bij aanmaak werd geretourneerd. Verifieer de handtekening vóór je de payload verwerkt.
Handtekening-header
X-Bjet24-Signature: t=<ts>,v1=<hex>
import crypto from 'node:crypto'
export function verifyBjet24(req, secret) {
const header = req.headers['x-bjet24-signature']
// header looks like: t=1714940000,v1=<hmac-sha256-hex>
const [tPart, sPart] = header.split(',')
const ts = tPart.split('=')[1]
const sig = sPart.split('=')[1]
const expected = crypto
.createHmac('sha256', secret)
.update(`${ts}.${req.rawBody}`)
.digest('hex')
if (!crypto.timingSafeEqual(Buffer.from(sig), Buffer.from(expected))) {
throw new Error('Bad signature')
}
if (Date.now() / 1000 - Number(ts) > 300) {
throw new Error('Replay')
}
}Replay-bescherming
Een externe applicatie verbinden (OAuth2)
Wanneer een applicatie (een CRM, een zakelijke tool) namens meerdere Bjet24-gebruikers moet handelen — elk met hun eigen portefeuille — gebruik dan OAuth2 in plaats van een API-sleutel. De gebruiker verbindt zijn account met één klik, zonder een sleutel te kopiëren en plakken.
API-sleutel of OAuth2?
Uw applicatie registreren
De Authorization Code + PKCE-flow
1. Stuur de gebruiker naar het toestemmingsscherm.
https://bjet24.com/fr/oauth/authorize
?response_type=code
&client_id=bjc_xxxxxxxxxxxxxxxxxxxxxxxx
&redirect_uri=https://your-app.example.com/callback
&scope=send%20read%20wallet
&state=<opaque-random>
&code_challenge=<base64url(sha256(code_verifier))>
&code_challenge_method=S2562. Wissel de ontvangen code in voor een tokenpaar.
curl -X POST https://bjet24.com/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d client_id=bjc_xxxxxxxxxxxxxxxxxxxxxxxx \
-d client_secret=$BJET24_CLIENT_SECRET \
-d code=$AUTH_CODE \
-d redirect_uri=https://your-app.example.com/callback \
-d code_verifier=$PKCE_VERIFIER{
"access_token": "bja_...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "bjr_...",
"scope": "send read wallet"
}3. Roep de API aan met het access token als Bearer-token.
curl https://bjet24.com/api/v1/wallet \
-H "Authorization: Bearer bja_..."4. Vernieuw het verlopen access token met het refresh token.
curl -X POST https://bjet24.com/api/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d client_id=bjc_xxxxxxxxxxxxxxxxxxxxxxxx \
-d client_secret=$BJET24_CLIENT_SECRET \
-d refresh_token=$REFRESH_TOKENLevensduur en intrekking
OAuth-scopes
De scopes die bij autorisatie worden gevraagd, bepalen wat uw applicatie mag doen.
sendverzendingen aanmaken (debiteert wallet)readlezen van verzendingen, offertes, lijstenwebhookswebhooks aanmaken/verwijderenwalletHet portefeuillesaldo van de gebruiker raadplegen.addressesHet adresboek beheren (afzenders en ontvangers).