This document helps a Nuts vendor scope the work needed to participate in the LSPxNuts Medicatie Overdracht Pilot 1. It describes what a participating vendor builds, what they host, what is delivered to them, and roughly how much effort each piece is. It is not an implementation manual; once a vendor commits to participating, the detailed setup docs, sample payloads, and a working reference stack are handed over.
Open items to resolve before this guide is final. Each is tracked in an issue where one exists.
- TLS/mTLS cert for the data connection (#2). Nuts convention (nuts-node#4156): OAuth2 endpoints → public cert, data endpoints → PKIoverheid Private cert. Exact pilot requirement not yet fixed.
- Who issues the AORTA-afsprakenstelsel credentials (#9) — which party hosts
issuance of the
ServiceProviderCredentialand who vendors should contact to obtain it. (The guide currently refers to this generically as "Pilot governance".) - Whether JSON-LD context files must be mounted at all (#6). Pilot credentials are JWT-format; JSON-LD is used only for signature verification, so a local context bundle may not be needed.
- How vendors acquire the AET SDK (#10) — the AET ZORG-ID SDK is a Docker image; distribution channel and licensing/access path to be determined.
- How the Nuts node authenticates to the AET SDK (#11) — the authentication mechanism, and whether AET certificate material is needed for it, to be determined.
- Soft test certificates (#12) — produced by the pilot team so developers can work without physical UZI cards; need to be hosted somewhere and linked from this guide.
- How vendors discover the LSP's endpoints (#13) — via GF Addressing or the Nuts Discovery Service; not yet decided.
- Number of Nuts/MEDGEG APIs per feature (#3). Detailed integration guide (endpoints, examples) still being written.
- Reference architecture details (#4) — the deployment diagram below is a first version; details still need confirmation.
The pilot runs the two-VP (Verifiable Presentation) RFC 7523 jwt-bearer access-token flow for MEDGEG against the Authorization Server (AS) hosted by VZVZ. There are several participant roles in the pilot. This guide is aimed at the Nuts vendors: parties that operate Nuts infrastructure and act in the OAuth requestor and client roles. The Resource Server (RS) — the LSP FHIR API, operated by VZVZ — is out of scope here.
A Nuts vendor hosts a Nuts node that contains wallets for:
- the vendor itself, as a Service Provider (SP), and
- each of the vendor's care-provider customers, each one a Healthcare Provider (HCP).
The vendor builds and operates the issuance UIs that HCP staff use to manage their credentials. This document is not intended for the HCPs themselves.
- Public
.nlURL — the domain in the node's did:web DID (DNS, TLS, stable hostname) - SQL database for node storage
- Key storage for signing keys (external store or on-disk)
- ZorgID agreement with AET (vendor; one per HCP too)
- Test smart cards from zorgcsp.nl
- Supported smart card reader (e.g. HID OMNIKEY 3121) — available to developers/testers, and on the workstations of staff doing patient enrollment and professional delegation during the pilot
- UZI server certificate — for the HealthcareProviderCredential (per HCP customer)
- Personal UZI care-professional card (zorgverlenerspas) — for the HealthcareProfessionalDelegationCredential; can also perform patient enrollment
- Personal UZI employee card (medewerkerspas op naam) — optional; patient enrollment only, not needed if the zorgverlenerspas is used
Each subsection is marked with one of:
- S - up to half a day
- M - one to two days
- L - three days to a week
- XL - more than a week
These are rough estimates for a backend engineer with experience operating containerized services but no Nuts-specific background. Multiply if infrastructure changes have to go through a change-management process. Items that scale per HCP customer are flagged.
flowchart LR
subgraph Vendor["Nuts vendor (this guide)"]
UI["Healthcare Provider Operator UI<br/>[Vendor-built web UI]<br/>Issuance UIs used by HCP staff"]
Node["Nuts node<br/>[Container]<br/>Hosts SP and per-HCP wallets; issues credentials and requests tokens"]
Backend["Vendor backend / EHR<br/>[Vendor product]<br/>Calls the LSP FHIR API with the access token"]
Keys[("Nuts node key storage")]
AET["AET ZORG-ID SDK<br/>[Container]<br/>Issues PatientEnrollmentCredential and HealthCareProfessionalDelegationCredential"]
UI --> Node
Backend --> Node
Node --> Keys
Node --> AET
end
Gov["Pilot governance<br/>[External]<br/>Issues the ServiceProviderCredential"]
subgraph LSP["LSP (VZVZ)"]
AS["OAuth2 token endpoint<br/>[MEDGEG AS]"]
RS["MEDGEG FHIR API<br/>[Resource server]"]
end
Holders["Data holders behind the LSP<br/>[External]"]
Node -->|did:web resolution| Gov
Node -->|jwt-bearer two-VP token request| AS
Backend -->|MEDGEG query + access token| RS
RS -->|forwards queries| Holders
The vendor obtains the access token from the LSP OAuth2 token endpoint (the MEDGEG AS) via the two-VP jwt-bearer flow, then uses it at the LSP FHIR API (the MEDGEG resource server). The LSP forwards queries to the data holders behind it.
- OAuth requestor and client: the vendor's SP subject calls VZVZ to obtain a service access token, and the vendor's software then calls the MEDGEG resource server with that token.
- Wallet operator for HCP customers: the vendor hosts the wallet for every participating HCP and provides the issuance UIs through which HCP staff manage their credentials.
The MEDGEG resource server is the LSP FHIR API, operated by VZVZ. The LSP forwards queries to the data holders behind it; what sits behind the LSP is not visible to the vendor and is out of scope here.
The prerequisites split into infrastructure (set up by ops/engineering) and paperwork/agreements (often owned by a different person, with longer lead times). Start the paperwork early: UZI certificate acquisition alone takes at least two weeks; begin acquiring certificates and putting agreements (ZorgID, AET) in place at least a month before integration work starts.
Infrastructure
- A participant-controlled public URL on a
.nldomain — this is the domain in the node's did:web (Decentralized Identifier, web method) DID and must resolve back to the node. The.nldomain is a pilot requirement; DNS, TLS, and a stable hostname need to be in place. Recommendation: serve the node at the root of the (sub)domain, otherwise the.well-knownendpoints need awkward URL rewriting. - A SQL database for the node's storage. Any database supported by the Nuts node works (PostgreSQL, SQL Server, MySQL); SQLite is best kept to development environments. BBolt is used only for gRPC connection storage. On-disk storage does not need to be persistent unless signing keys are kept there.
- Key storage for the node's signing keys: an external key store (HashiCorp Vault or Azure Key Vault) is recommended. On-disk storage is also supported, but then the vendor is responsible for securing encryption and data at rest.
- At least one supported smart card reader (for example, the HID OMNIKEY 3121) for the workstations that run the issuance UIs.
Paperwork / agreements
- A ZorgID agreement with AET for the vendor (each participating HCP needs their own agreement as well).
- Test smart cards from
zorgcsp.nl. Soft test certificates (provided by the pilot team, #12) can be used during early development so developers do not need physical cards; physical test cards have to be requested before the issuance flows can be validated against the real workstation experience. - UZI material per HCP customer. The HCP organisation requests this
themselves; the vendor does not request it on the HCP's behalf. Where an HCP
already holds UZI cert material at another vendor, do not share private key
material between vendors — the HCP requests a separate cert per vendor.
- a UZI server certificate for the
HealthcareProviderCredential(Part B); - a personal zorgverlenerspas (UZI-pas zorgverlener op naam) for the
HealthCareProfessionalDelegationCredential; it can also perform patient enrollment; - optionally a personal medewerkerspas op naam (UZI-pas medewerker op naam) for patient enrollment — not needed if the zorgverlenerspas is used.
- a UZI server certificate for the
How the Nuts node authenticates to the AET ZORG-ID SDK, and whether AET certificate material is required for it, is still being determined (#11).
Note that the Healthcare Provider and Service Provider credentials themselves are not prerequisites; they are issued or loaded once the node is running and DIDs exist (see Part B).
- A pinned
nuts-nodecontainer image is available for the pilot window. The released binary covers everything the pilot needs, and the AET and other required certificate authorities are baked into the image. - Configuration is a single
nuts.yaml. The pilot-specific bits beyond a default install are:- the public
.nlURL for did:web resolution auth.experimental.jwtbearerclient: true(gates the two-VP flow)- the crypto backend pointing at the configured key storage
- JSON-LD context mappings (
jsonld.contexts.localmapping) for the credential contexts — needed only if the node must process the contexts locally; whether the pilot's JWT credentials require this is still being verified (#6)
- the public
- Strict mode on. The internal API is bound to a private interface; the vendor decides how to authenticate operators in front of it.
The vendor needs to create and manage:
- one SP subject (the vendor itself), and
- one HCP subject per care-provider customer.
Two equivalent options for the management surface:
- Use
nuts-admin- the foundation publishes a ready-made web UI image. Point it at the node's internal API and it provides a console for subject, DID, and credential management. Zero code; S effort. - Implement the VDR (Verifiable Data Registry) endpoints in own
admin tooling - if the vendor prefers a single admin surface for
their operators (and likely for their customer onboarding flow),
integrate the
/internal/vdr/v2/...calls into the existing console. M effort.
Per-customer onboarding ergonomics matter here: every new HCP customer needs a subject created and a DID issued before any of the Part B credential work can proceed for that customer.
- Healthcheck endpoints exposed by the node.
- Log routing and verbosity choices for pilot vs production.
- Vault key rotation procedure documented; the vendor decides the rotation cadence.
A vendor with experience operating containerized services and key storage in production can expect 3-5 working days end-to-end for Part A, dominated by the key storage integration and the subject management surface.
This is the larger of the two parts. The vendor integrates two new Nuts endpoints, hosts the AET SDK, populates the wallet for every customer, and builds three UIs that fit into three different points in HCP staff workflows.
The exact number of Nuts/MEDGEG API calls per feature is still being finalised (#3); the counts below describe the integration surface qualitatively.
The AET SDK runs alongside the Nuts node. The pilot uses the SDK in production posture: real UZI / HSM-backed cert material, no soft-cert shortcuts. Detailed setup (mTLS, certificate binding, network exposure) lives in the AET documentation; what the pilot needs from the deployment is a stable HTTPS endpoint reachable from the Nuts node.
The AET SDK is not redistributed as part of the pilot; the vendor obtains it from AET under their licensing terms.
Once the node is up and subjects + DIDs exist, every wallet needs to be seeded with its baseline VC (Verifiable Credential) before any token request can succeed.
- SP subject (vendor): load the
ServiceProviderCredentialissued by Pilot governance. The signed VC is handed over out-of-band as part of pilot onboarding and loaded viaPOST /internal/vcr/v2/holder/<subject>/vc. One-off per environment. - HCP subject (per customer): generate the
HealthcareProviderCredentialfor that HCP using thego-didx509-toolkitCLI against the HCP's UZI material, then load it via the same wallet endpoint. Using the CLI directly is fine for the pilot.
Three different credentials need to be issued during normal pilot operation, each at a different place in HCP staff workflows. The vendor builds the UI; the Nuts API calls behind it are thin. End-users of all three UIs are HCP staff, segmented by role.
For the AET-signed credentials (B.3.b and B.3.c), the issuance has to
be performed by a healthcare professional holding a UZI smart card, at
a workstation that has a smart card reader and ZorgID (AET) installed.
During development the workstation requirement can be relaxed by
configuring soft certificates, so engineers do not need a physical
card to run the flow. Test cards from zorgcsp.nl are required
before the UIs can be validated end-to-end as HCP staff will use them.
- When: once per HCP-vendor relationship; refreshed only on contract changes.
- Who: an authorised signer at the HCP organisation (someone who can bind the organisation to a service contract).
- What: the HCP issues a
ServiceProviderDelegationCredentialto the vendor's SP subject. The credential template is provided by the pilot; the signing UI is built by the vendor. - Where it lives in the vendor's product: a governance / contracting area gated by signatory role. Likely a net-new screen for most vendors.
- Workstation requirement: none; the signing authority operates inside the vendor's product directly.
- When: when an HCP onboards or rotates a professional, or when a role changes.
- Who: HR or staff admin at the HCP, signing with their UZI smart card.
- What: an AET-signed
HealthCareProfessionalDelegationCredentialrequested through Nuts via/internal/auth/v2/<subject>/request-credentialwithcredential_request_paramscarrying the AET-specific fields. - Where it lives in the vendor's product: HR / staff admin tooling. Often an extension of an existing onboarding screen.
- Workstation requirement: UZI smart card + reader + ZorgID installed on the workstation that runs the issuance.
- When: every time a patient is enrolled at the HCP for medication treatment. High volume.
- Who: clinical or front-desk staff at the HCP, signing with their UZI smart card.
- What: an AET-signed
PatientEnrollmentCredentialrequested through the same/request-credentialendpoint with the patient's BSN incredential_request_params. - Where it lives in the vendor's product: embedded in the EHR (Electronic Health Record) or registration workflow. Latency and error UX matter; HCP users will hit this daily.
- Workstation requirement: same as B.3.b - UZI smart card + reader + ZorgID installed on every workstation that will perform the enrolment.
The three together are where most of the Part B effort lives. If the vendor's product makes back-office HTTP calls easy and the governance / HR / clinical surfaces are extensible, the work is straightforward integration. If any of those surfaces are hard to modify, those constraints dominate the estimate.
The core of the pilot. Once the wallets are populated, the vendor's
SP requests a service access token via
POST /internal/auth/v2/<hcp>/request-service-access-token with the
SP subject id in the request. Nuts builds two presentations (one per
subject), assembles them as assertion and client_assertion, and
posts the token request to VZVZ. The response carries an access token
that the vendor's software attaches to outbound MEDGEG calls.
The integration surface is a single HTTP call from the vendor's backend plus response handling. The complexity sits in the wallet being correctly populated and the scopes requested being ones VZVZ has configured for the vendor. Scope onboarding with VZVZ runs in parallel during pilot onboarding.
The PD (Presentation Definition) JSON files are provided by the pilot. The vendor drops them in the configured policy directory.
The Nuts node exposes list and delete endpoints on the holder wallet,
and nuts-admin exposes the same operations through its UI. The
vendor will want a way to list and delete credentials in their
operations toolkit, since re-issuance can leave duplicates that
complicate matching. It is a single API call; worth having from day
one.
For a vendor with a product backend that can make outbound HTTP calls and customer-facing surfaces (governance, HR, clinical) that are reasonably extensible: 8-12 working days end-to-end, dominated by the patient enrolment UI integration. Add buffer per HCP customer for the wallet bootstrap.
Once the access token is in hand, calling MEDGEG is a normal authorised HTTP call. The pilot scope here is:
- Construct the MEDGEG medication-request call using the token from Part B.
- Attach the token at the right point in the outbound HTTP layer.
- Parse the response and display the medication overview to the HCP user.
- Handle the error path: token denied, no data, AS or resource server unreachable.
Most vendors already have all of this plumbing for other federated services; the pilot-specific surface is small. Effort sits at M for vendors with a clean outbound integration layer, L if every new external call requires significant new UI work.
- A working demo stack (
docker compose up) covering the full end-to-end flow with a mock AS, mock issuers, the AET SDK in dev mode, and a UI for issuing every credential and requesting tokens. Useful as a sanity check before cutting real code. - Sample payloads for every API call (request and response) and sample wallet states for each subject type.
- Sample full flow trace from wallet bootstrap through token response.
- Pointers to AET documentation,
go-didx509-toolkit,nuts-admin, and the supported vault backends. - The pinned
nuts-nodecontainer image tag and the matching PD bundle. - Developer support: questions during the pilot integration can be raised in the Nuts foundation Slack workspace. The pilot test plan and acceptance criteria are delivered as a separate document during onboarding.
For a vendor with experience operating containerized services, an extensible product backend, governance / HR / clinical surfaces that can be modified, and key storage already in production:
- Part A: 3-5 days
- Part B: 8-12 days
- Part C: 2-5 days
- Buffer for coordination handoffs and change management: 2-4 days
Total: 3-5 working weeks of focused backend + UI effort for a
single team, plus calendar time for the prerequisite handoffs (AET
licensing, ZorgID agreement, smart card / test cert procurement from
zorgcsp.nl, Pilot governance SP VC handoff, VZVZ scope onboarding)
which run in parallel. Add per-HCP-customer onboarding effort once
the baseline integration is in place.