Inleiding
Magda Documentendienst of Magda Document Service (MDS) laat directe communicatie met de burger of onderneming toe via eBox en/of aangetekende zending.
Sommige projecten maken nog gebruik van de legacy connector Magda Document (eBox).
Use cases
-
Voor het versturen van een beslissing controleren of een burger of onderneming over een actieve eBox beschikt, om te bepalen of digitale verzending mogelijk is of dat een aangetekende zending nodig is.
-
Een officieel document (bv. een beslissing, attest of uitnodiging) digitaal bezorgen aan een burger of onderneming via hun eBox.
-
Nagaan of een verzonden bericht door de ontvanger geopend werd, bijvoorbeeld om te bepalen of een wettelijke termijn (bv. bezwaartermijn) reeds is beginnen lopen.
-
Automatisch overschakelen naar een aangetekende zending op papier wanneer blijkt dat de ontvanger geen actieve eBox heeft.
Setup
Deze REST-gebaseerde connector (document-service-bean) staat los van de Magda-connectoren (magda-bean) die SOAP-gebaseerd zijn. Onderstaande setup en onboardingsprocedure zijn in grote lijnen dezelfde als bij Magda (zie MAGDA algemene setup), maar hou rekening met specifieke verschilpunten.
Dependency toevoegen aan pom.xml bestand
Voeg onderstaande dependency toe aan het pom.xml bestand van je applicatie. Dit zorgt ervoor dat de connector code ingeladen wordt bij de build van de applicatie.
<dependency>
<groupId>com.skryv.connectors</groupId>
<artifactId>document-service</artifactId>
</dependency>
Onboardingsprocedure
Het aansluitingsproces bij Digitaal Vlaanderen verloopt in verschillende stappen:
-
Lees eerst de functionele documentatie van de Documentendienst.
-
Vul het aansluitingsformulier in. Hou hiervoor klaar: het logo van je organisatie (JPG/PNG, max. 200 kB, 64×35 mm), minstens een algemene contactpersoon en een DPO/informatieveiligheidsverantwoordelijke, en (indien je organisatie nog niet via de Documentendienst verstuurt) een ondertekende Toetredingsovereenkomst. Wil je ook papieren zendingen versturen, dan zijn ook de facturatiegegevens van je printpartner nodig.
-
Beveilig je aansluiting via Toegangsbeheer Vlaanderen (ACM). Start hiervoor tijdig een integratiedossier voor de Veiligheidsbouwstenen via het contactformulier.
-
Wil je berichten sturen naar de eBox burger en/of eBox onderneming, dan doorloop je bijkomend een apart, specifiek onboardingtraject per doelgroep:
-
Na een test- en acceptatiefase (zie acceptatiecriteria) volgt de opzet in productie.
Applicatie eigenschappen
|
Eigenschap |
Default |
Beschrijving |
|---|---|---|
|
MDSTechnicalConnector |
||
|
|
Null |
Private key |
|
|
Null |
Certificate |
|
MDSBusinessConnector |
||
|
|
Null |
Basis-URL van de Documentendienst-API |
|
|
Null |
Id |
|
MDSTokenFetcher |
||
|
|
|
GeoSecure OAuth scope. Scope van je machtiging binnen DOSIS. Dit bepaalt welke acties je mag uitvoeren. |
|
|
|
Url waar de applicatie op inlogt om vervolgens een token te verkrijgen waarmee de veilige communicatie tot stand gebracht kan worden. |
|
|
Null |
GeoSecure app number. Client Id voor je applicatie. Hiermee moet je inloggen op het beheerdersportaal. |
|
|
Null |
GeoSecure keypath. Pad naar private key in AWS Secrets Manager. |
|
|
|
Waarde: boolean. Indien |
|
|
|
Pad naar lokale opslag van je key pair. |
|
|
Null |
GeoSecure JWKS URL. |
Externe documentatie
Klik hier voor alle technische documentatie langs de kant van de documentendienst service.
Services en functies
Overzicht
|
Functie |
Retourtype |
Info |
|---|---|---|
|
|
Controleert of een burger (INSZ) toestemming gaf voor eBox |
|
|
|
Controleert of een onderneming (KBO-nummer) toestemming gaf voor eBox |
|
|
|
Verstuurt een document via eBox en/of papier, afhankelijk van de configuratie |
|
|
|
Vraagt de verzend-/leesstatus op van een eerder verstuurd eBox-bericht |
|
|
|
Vraagt de verzendstatus op van een eerder verstuurde papieren zending |
Elke functie hieronder is, naast de workflow expressie, ook rechtstreeks aanroepbaar vanuit Java-code door MDSCamundaConnector (bean mds) te injecteren in je klasse.
@RequiredArgsConstructor
public class MyOwnService {
private final MDSCamundaConnector mds;
}
checkEboxActiveCitizen & checkEboxActiveCompany
Controleer of de opgegeven persoon (personen) of onderneming (ondernemingen) over een actieve eBox beschikken. Zie ook de service taak templates ‘Controleer of eBox actief is voor burger’ en ‘Controleer of eBox actief is voor onderneming’.
Workflow expression 1
${mds.checkEboxActiveCitizen(String rrn)}
Variant voor burger.
Workflow expression 2
${mds.checkEboxActiveCompany(String kboNr)}
Variant voor onderneming.
Java-code 1
EboxInfo eboxInfo = mds.checkEboxActiveCitizen(rrn);
Variant voor burger.
Java-code 2
EboxInfo eboxInfo = mds.checkEboxActiveCompany(kboNr);
Variant voor onderneming
Input
|
Inputparameters |
Data type |
Voorbeeld |
Uitleg |
|---|---|---|---|
|
|
String |
‘85010212345’ |
Rijksregisternummer (INSZ) van de burger waarvoor je nagaat of er een actieve eBox is. |
|
|
String |
'0406798006' |
Ondernemingsnummer (KBO-nummer) waarvoor je nagaat of er een actieve eBox is. |
Output
Je krijgt een EboxInfo-object terug met:
-
eboxId: bevestiging van het opgevraagdeeboxType(CITIZEN/ENTERPRISE) eneboxIdValue(INSZ of KBO-nummer); -
exclusivelyEbox(boolean): geeft aan of de ontvanger toestemming (consent) heeft gegeven voor eBox. Dit is het eigenlijke antwoord op de vraag "heeft deze persoon/onderneming een actieve eBox"; -
lastConnectionDate,totalNumberOfMessages,totalNumberOfUnreadMessages: enkel aanwezig bijcheckEboxActiveCompany(ondernemingen), nooit bij burgers.
Belangrijke nuance: een ongeldig of onbestaand identificatienummer geeft geen fout, maar gewoon exclusivelyEbox: false — je moet dus niet verwachten dat elke foutieve input een exceptie oplevert.
Gepseudonimiseerd voorbeeld burger:
{
"eboxId": {
"eboxType": "CITIZEN",
"eboxIdValue": "850102XXX45"
},
"exclusivelyEbox": true
}
Gepseudonimiseerd voorbeeld onderneming:
{
"eboxId": {
"eboxType": "ENTERPRISE",
"eboxIdValue": "0406798006"
},
"exclusivelyEbox": true,
"lastConnectionDate": "2024-04-19T20:00:00Z",
"totalNumberOfMessages": 47,
"totalNumberOfUnreadMessages": 3
}
Error-handling
Deze REST-dienst gebruikt HTTP-statuscodes, geen klassieke MAGDA-Uitzonderingen-lijst:
|
HTTP-status |
Betekenis |
|---|---|
|
400 |
Invalid data supplied |
|
401 |
Invalid authorization |
|
404 |
No mailbox found |
|
500 |
Unexpected Server Error |
|
502 |
Bad Gateway |
|
503 |
Service unavailable |
|
504 |
Gateway Timeout |
In onze Java-code (MDSCamundaConnector.checkEboxActive) wordt elke fout — zowel een HTTP-foutstatus als een onverwacht leeg antwoord — omgezet naar een MDSException, net zoals bij de andere MDS-functies:
// Voorbeeld: MDSException opvangen
try {
EboxInfo eboxInfo = mds.checkEboxActiveCitizen(rrn);
if (Boolean.TRUE.equals(eboxInfo.getExclusivelyEbox())) {
// ontvanger heeft een actieve eBox
}
} catch (MDSException e) {
throw new BpmnError("MDS_EBOX_CHECK_MISLUKT", e.getErrorMessage());
}
Kanttekening: als er geen enkele identifier werd meegegeven, of het antwoord onverwacht leeg is, gooit de connector zelf al een MDSException ("Empty response" / "No input ID given to check."), nog vóór er sprake is van een HTTP-foutstatus.
Bij een fout krijg je een RFC 7807-achtige body terug (title, status, detail, instance — laatste is het correlatie-ID, te vermelden bij contact met de MAGDA helpdesk):
{
"title": "Unauthorized",
"status": "401",
"detail": "Invalid token"
}
publishMessage
Versturen van communicatie via eBox en/of papieren zending. Zie ook Studio service taak template ‘Verstuur documenten'.
Workflow expression
${mds.publishMessage(execution)}
Deze functie neemt geen losse parameters — execution wordt automatisch door Studio meegegeven. De eigenlijke configuratie gebeurt via de onderstaande input-parameters op de service taak zelf.
Java-code
MdsPublishMessageResponse response = mds.publishMessage(execution);
Service taak input parameters
Deze input parameters worden via de service taak template ‘Verstuur documenten' op de service taak geplaatst.
|
Inputparameters |
Data type |
Voorbeeld |
Uitleg |
|---|---|---|---|
|
|
String (keuzelijst) |
'AUTOMATIC' |
Verzendmethode: |
|
|
String |
'85010212345' |
INSZ of KBO-nummer van de ontvanger (nodig bij elke verzendmethode behalve |
|
|
String (keuzelijst) |
'CITIZEN' |
|
|
|
String |
‘Beslissing over uw aanvraag’ |
Onderwerp van het eBox-bericht, Nederlands |
|
|
String |
'Entscheidung über Ihren Antrag' |
Onderwerp van het eBox-bericht, Duits |
|
|
String |
'Décision concernant votre demande' |
Onderwerp van het eBox-bericht, Frans |
|
|
String (keuzelijst) |
'dlp4' |
bpost-prioriteitscode voor de papieren zending: |
|
|
String (keuzelijst) |
'RV' |
Druk recto-verso ( |
|
|
String/Boolean |
‘true’ |
Aangetekende zending (enkel relevant bij papieren zending) |
|
|
String |
'2025-12-31' |
Vervaldatum van het eBox-bericht |
|
|
String |
'85010212345' |
"Ter attentie van"-persoon binnen een ondernemings-eBox (INSZ en naam) |
|
|
String |
'Jan Peeters' |
"Ter attentie van"-persoon binnen een ondernemings-eBox (naam) |
|
|
String |
‘Anna’ |
Voornaam van de ontvanger (papieren zending) |
|
|
String |
‘Peeters’ |
Achternaam van de ontvanger (papieren zending) |
|
|
String |
'Voorbeeld Bouwonderneming NV' |
Organisatienaam van de ontvanger, indien van toepassing (papieren zending) |
|
|
String |
'aanvrager.adres' |
Verwijzing naar het adresveld van de ontvanger in het formulier. De connector verwacht onder dit pad de volgende sub-velden: |
|
|
String (vast) |
'BE' |
Land van de ontvanger (standaard vastgezet op België) |
|
|
String |
'Agentschap Wonen-Vlaanderen' |
Organisatienaam voor het retouradres. De connector ondersteunt ook |
|
|
String |
'Havenlaan 88 bus 40B' |
Straat en nummer van het retouradres |
|
|
String |
'1000' |
Postcode van het retouradres |
|
|
String |
'Brussel' |
Gemeente van het retouradres |
|
|
String (vast) |
'BE' |
Land van het retouradres (standaard vastgezet op België) |
|
|
Map (verborgen) |
{'upfile1': 'beslissing.pdf'} |
Map met attachments (prefix-id/bestandsnaam), maximaal 6 bijlagen ( |
Output
Je krijgt een MdsPublishMessageResponse-object terug, met een status-veld dat drie waarden kan hebben: SUCCESS, WARNING of ERROR. Controleer dit veld altijd eerst, vooraleer je de overige velden gebruikt:
-
Bij
SUCCESSofWARNING:-
eboxMessageIdeneboxExpirationDate— enkel aanwezig als het bericht (mede) via eBox verstuurd werd; -
paperMessageIdenpaperExpirationDate— enkel aanwezig als het bericht (mede) via papier verstuurd werd; -
Bij
deliveryType = PAPER_AND_EBOXkunnen dus beide ingevuld zijn.
-
-
Bij
WARNING:consentMessagebevat een waarschuwing over de toestemming (consent) van de ontvanger voor eBox — het bericht is dan wel verstuurd, maar er is iets met de eBox-toestemming dat aandacht verdient (bv. de ontvanger heeft geen actieve eBox-toestemming, waardoor het bericht mogelijk toch niet leesbaar is voor de ontvanger via eBox). -
Bij
ERROR:errorMessagebevat de foutmelding, enconsentMessagekan ook hier gevuld zijn.
Gebruik eboxMessageId/paperMessageId als input voor getMessageStatusEBox/getMessageStatusPaper, om later de verzend- of leesstatus op te vragen.
Belangrijke validatiebeperking: de som van alle bijlagen mag niet groter dan 7 MB zijn. Is dat wel het geval, dan krijg je hier al een fout (status = ERROR, met een duidelijke foutmelding) vóór de aanroep zelfs naar MAGDA vertrekt.
Gepseudonimiseerde voorbeelden:
Geslaagd, verstuurd via eBox én papier
{
"status": "SUCCESS",
"eboxMessageId": "AB12345678",
"eboxExpirationDate": "2025-12-31T00:00:00Z",
"paperMessageId": "PP98765432",
"paperExpirationDate": "2025-12-31T00:00:00Z"
}
Geslaagd, maar met een consent-waarschuwing
{
"status": "WARNING",
"eboxMessageId": "AB12345678",
"eboxExpirationDate": "2025-12-31T00:00:00Z",
"consentMessage": "De ontvanger heeft geen actieve toestemming voor eBox."
}
Mislukt (bijvoorbeeld te grote bijlage)
{
"status": "ERROR",
"errorMessage": "Max file size for all attachments is 7 MB."
}
Error-handling
In tegenstelling tot de klassieke SOAP-MAGDA-diensten (Persoon, Gezin, ...) werkt deze functie niet met een aparte Uitzonderingen-lijst die een BpmnError vereist. In de meeste gevallen krijg je gewoon een geldig antwoord terug met status = ERROR, dat je zelf moet controleren.
// Voorbeeld: status controleren na publishMessage
MdsPublishMessageResponse response = mds.publishMessage(execution);
if ("ERROR".equals(response.getStatus())) {
throw new BpmnError("MDS_PUBLICATIE_MISLUKT", response.getErrorMessage());
}
if ("WARNING".equals(response.getStatus())) {
// Bericht is verstuurd, maar met een consent-waarschuwing - eventueel loggen
LOGGER.warn("MDS consent-waarschuwing: {}", response.getConsentMessage());
}
getMessageStatusEBox
Check voor een verstuurd bericht of de ontvanger deze gelezen heeft of niet. Zie service task template ‘Haal verzendstatus op voor eBox’.
Workflow expression
${mds.getMessageStatusEBox(String messageId, String eboxType, String eboxIdValue)}
Java-code
EBoxMessageStatus status = mds.getMessageStatusEBox(messageId, eboxType, eboxIdValue);
Input
|
Inputparameters |
Data type |
Voorbeeld |
Uitleg |
|---|---|---|---|
|
|
String |
${mdsPublishMessage.eboxMessageId} |
Id van het eBox-bericht — haal je uit de respons van |
|
|
String |
'CITIZEN' |
|
|
|
String |
'85010212345' |
INSZ of KBO-nummer van de ontvanger |
Output
Je krijgt een EBoxMessageStatus-object terug met:
-
messageId— het opgevraagde bericht-ID; -
eboxId(eboxType,eboxIdValue) — bevestiging van de ontvanger; -
expirationDate— de vervaldatum van het bericht in eBox; -
readStatus(boolean) — geeft aan of de hoofdinhoud door de ontvanger geopend is (standaardfalse) -
visible— of het bericht nog zichtbaar is (wordtfalsena de vervaldatum); -
statuses(optioneel) — extra detail bij een gelezen bericht:id("200"),status("Read"),updated(moment van eerste lezing).
Belangrijke nuance: in tegenstelling tot wat je zou verwachten, is readStatus niet enkel bij een reeds-gelezen bericht aanwezig — het staat er altijd bij, met standaardwaarde false. Enkel het statuses-blok (met de leesdatum) komt er pas bij zodra het bericht effectief gelezen is.
Gepseudonimiseerd voorbeelden:
Nog niet gelezen
{
"objectType": "EBoxMessageStatus",
"messageId": "AB12345678",
"eboxId": {
"eboxType": "CITIZEN",
"eboxIdValue": "85010212345"
},
"expirationDate": "2025-12-31T00:00:00.000Z",
"readStatus": false,
"visible": true
}
Gelezen
{
"objectType": "EBoxMessageStatus",
"messageId": "AB12345678",
"eboxId": {
"eboxType": "CITIZEN",
"eboxIdValue": "85010212345"
},
"expirationDate": "2025-12-31T00:00:00.000Z",
"readStatus": true,
"visible": true,
"statuses": [
{
"id": "200",
"status": "Read",
"updated": "2025-06-12T14:32:00.000Z"
}
]
}
Error-handling
Deze functie gebruikt HTTP-statuscodes, geen klassieke MAGDA-Uitzonderingen-lijst.
|
HTTP-status |
Betekenis |
|---|---|
|
400 |
Invalid data supplied |
|
401 |
Invalid authorization |
|
404 |
Messages not found |
|
500 |
Unexpected Server Error |
|
502 |
Bad Gateway |
|
503 |
Service unavailable |
|
504 |
Gateway Timeout |
In onze Java-code (MDSCamundaConnector.getMessageStatusEBox) wordt elke fout (een HTTP-foutstatus, maar ook een onverwacht leeg antwoord) omgezet naar een MDSException:
// Voorbeeld: MDSException opvangen
try {
EBoxMessageStatus status = mds.getMessageStatusEBox(messageId, eboxType, eboxIdValue);
if (Boolean.TRUE.equals(status.getReadStatus())) {
// bericht is gelezen
}
} catch (MDSException e) {
throw new BpmnError("MDS_STATUSOPVRAAG_EBOX_MISLUKT", e.getErrorMessage());
}
Kanttekening: als het antwoord van MDS onverwacht leeg is (geen responseMessage, of een lege messageStatuses-lijst), gooit de connector zelf al een MDSException ("Empty response or response messsage." / "Empty response - no message statuses returned for ..."), nog vóór er sprake is van een HTTP-foutstatus. Bij dat laatste scenario wordt, indien aanwezig, ook een eventuele consent-waarschuwing uit de X-Magda-Exceptions-header gelogd (maar niet in de exceptie zelf meegegeven).
Bij een fout krijg je een RFC 7807-achtige body terug (title, status, detail, instance — laatste is het correlatie-ID, te vermelden bij contact met de MAGDA helpdesk):
{
"title": "Unexpected Server Error",
"detail": "Failed to persist the file",
"instance": "b45754d6-e1a6-4c88-b089-c529825d9e6c"
}
getMessageStatusPaper
Check voor een verstuurd bericht of de ontvanger deze gelezen heeft of niet. Zie service task template ‘Haal verzendstatus op voor papier’.
Workflow expression
${mds.getMessageStatusPaper(String messageId)}
Java-code
PaperMessageStatus status = mds.getMessageStatusPaper(messageId);
Input
|
Inputparameters |
Data type |
Voorbeeld |
Uitleg |
|---|---|---|---|
|
|
String |
${mdsPublishMessage.paperMessageId} |
Id van de papieren zending — haal je uit de respons van |
Output
Je krijgt een PaperOrEmailMessageStatus-object terug met:
-
messageId; -
shippingDate— datum waarop de printpartner meldde dat het bericht bij bpost afgeleverd werd (enkel gevuld in statusSENT); -
mailId— id van bpost (enkel bij statusSENT); -
trackAndTraceUri— enkel aanwezig als het een aangetekende zending is, met een gekende postcode én eenmailId; -
statuses[].status— met deze mogelijke waarden:Pending,Processing,Printed,Sent(eindstatus),Cancelled(uitgestelde papieren zending die niet meer nodig was omdat het eBox-bericht tijdig gelezen werd),Error(niet-fatale fout, wordt proactief opgevolgd door het MAGDA-team),Failed(fatale fout, eindstatus).
Nuttige nuance over Cancelled: dit bevestigt een interessant automatisch mechanisme bij deliveryType = PAPER_AND_EBOX — als de ontvanger het eBox-bericht op tijd leest, wordt de papieren verzending simpelweg geannuleerd in plaats van toch nog verstuurd te worden.
Gepseudonimiseerd voorbeeld:
{
"objectType": "PaperOrEmailMessageStatus",
"messageId": "PP98765432",
"shippingDate": "2025-06-10T16:01:43.000Z",
"mailId": "010541288500452621900095554841",
"trackAndTraceUri": "https://track.bpost.cloud/btr/web/#/search?lang=en&itemCode=010541288500452621900095554841&postalCode=1700",
"statuses": [
{ "id": "200", "status": "Sent" }
]
}
Error-handling
Zelfde HTTP-statuscodes en foutstructuur als bij getMessageStatusEBox (beide lopen via hetzelfde /messages/statusRequest-eindpunt, enkel met een ander deliveryChannel).
|
HTTP-status |
Betekenis |
|---|---|
|
400 |
Invalid data supplied |
|
401 |
Invalid authorization |
|
404 |
Messages not found |
|
500 |
Unexpected Server Error |
|
502 |
Bad Gateway |
|
503 |
Service unavailable |
|
504 |
Gateway Timeout |
In onze Java-code (MDSCamundaConnector.getMessageStatusPaper) wordt elke fout — een HTTP-foutstatus, maar ook een onverwacht leeg antwoord — omgezet naar een MDSException:
// Voorbeeld: MDSException opvangen
try {
PaperMessageStatus status = mds.getMessageStatusPaper(messageId);
String currentStatus = status.getStatuses().get(0).getStatus();
if ("Failed".equals(currentStatus)) {
throw new BpmnError("MDS_PAPIEREN_ZENDING_MISLUKT", "Fatale fout bij papieren zending: " + messageId);
}
if ("Cancelled".equals(currentStatus)) {
// Uitgestelde papieren zending was niet nodig - eBox-bericht werd tijdig gelezen
}
} catch (MDSException e) {
throw new BpmnError("MDS_STATUSOPVRAAG_PAPER_MISLUKT", e.getErrorMessage());
}
Kanttekening: in tegenstelling tot getMessageStatusEBox wordt hier bij een leeg antwoord geen enkele poging gedaan om een eventuele X-Magda-Exceptions-header te loggen. De code gaat hier meteen naar de generieke MDSException(EMPTY_RESPONSE).