Skip to main content

SOAP Report

For product owners and partners: Use this page to understand how SOAP Reports are exposed in the MediKIT API and how this supports referral and care-continuity workflows.

For architects and developers: Use this page to implement patient-scoped SOAP Report retrieval with the correct Composition query shape, scope, and filtering rules.

SOAP Reports (SOEP consultation reports in Dutch) are exposed as FHIR R4 Composition resources in a patient context.

This guide uses SOAP Report as the canonical term to distinguish Composition-based reporting from SOEP-style Observation entries.

This is intended for structured consultation reporting use cases where integrators need narrative + coded context from GP encounters without bespoke HIS integrations.

Where feasible, these Composition resources are modeled to align as closely as possible with relevant Dutch ZIB definitions (MEDMIJ).

What this endpoint is for

Use Composition SOAP Report search when your product needs consultation reporting such as:

  • referral context for downstream care providers
  • timeline views in patient-facing applications
  • care-continuity handovers between systems

Endpoint map

Use caseEndpointNotes
Search SOAP ReportsGET /v2/{organizationId}/fhir/R4/Patient/{patientId}/CompositionRequires type=http://loinc.org|67781-5, or the SNOMED equivalent under the zib SOAP Report profile

Required access and parameters

Required scope

  • composition.read

Required query parameter

ParameterRequiredAllowed value
typeYeshttp://loinc.org|67781-5, or http://snomed.info/sct|11591000146107 under the zib SOAP Report profile

If type is missing or uses a different value, the API returns a validation OperationOutcome (422). The two values are not interchangeable: type has to name the code the Composition in the response actually carries, so the SNOMED code goes with _profile and the LOINC code without it.

Supported optional filters

ParameterPurposeAllowed values
_includeInclude related resources in the same BundleComposition:encounter
_include:iterateFollow a reference chain one hop further than _includeEncounter:episode-of-care
encounter:Encounter.episode-of-careRestrict SOAP entries to one episode of careEpisodeOfCare logical ID
_profileShape the response to a profilehttp://nictiz.nl/fhir/StructureDefinition/zib-SOAPReport

_include:iterate=Encounter:episode-of-care returns the EpisodeOfCare behind each included Encounter, so combine it with _include=Composition:encounter. On its own it adds nothing to the Bundle: without an included Encounter there is no reference chain to follow, since a Composition does not reference an EpisodeOfCare itself. An EpisodeOfCare that cannot be resolved is left out of the Bundle rather than failing the request.

Episode name

Composition.title names the episode of care by reference rather than by its human-readable name, and R4 EpisodeOfCare has no element for a name. Ask for the zib SOAP Report profile to get the name:

_profile=http://nictiz.nl/fhir/StructureDefinition/zib-SOAPReport

Asking for it also profiles the resources returned alongside the SOAP Reports against the same zib2020 set, so each included EpisodeOfCare comes back as a zib-EpisodeOfCare carrying its name in an extension:

{
"resourceType": "EpisodeOfCare",
"id": "e07597d4-e9d9-4860-9ef8-a6ab304cf8de",
"meta": {
"profile": ["http://nictiz.nl/fhir/StructureDefinition/zib-EpisodeOfCare"]
},
"extension": [
{
"url": "http://nictiz.nl/fhir/StructureDefinition/ext-EpisodeOfCare.EpisodeOfCareName",
"valueString": "Diabetes mellitus type 2"
}
]
}

The extension rides on the included EpisodeOfCare, so combine _profile with _include=Composition:encounter&_include:iterate=Encounter:episode-of-care — without those there is no EpisodeOfCare in the Bundle to carry it. An episode the source system gives no name gets no extension.

Asking for the profile also makes the response conform to it, which changes the SOAP Report itself in three ways:

  • Composition.meta.profile claims http://nictiz.nl/fhir/StructureDefinition/zib-SOAPReport.

  • Composition.type becomes http://snomed.info/sct|11591000146107, the code the profile pins, and no longer carries http://loinc.org|67781-5. This is why type must ask for the SNOMED code under the profile: a client matching on the LOINC code has to keep asking for the LOINC one and skip _profile.

  • Each section.code becomes the SNOMED code the profile binds the SOAP line header to, in place of the http://fhir.nl/fhir/NamingSystem/journaalregeltypen coding:

    Journal linePlain responseUnder the profile
    Subjectief...journaalregeltypen|Shttp://snomed.info/sct|255362007
    Objectief...journaalregeltypen|Ohttp://snomed.info/sct|260224007
    Evaluatie...journaalregeltypen|Ehttp://snomed.info/sct|129265001
    Plan...journaalregeltypen|Phttp://snomed.info/sct|129271007

What the profile costs you

The http://nictiz.nl/fhir/StructureDefinition/code-icpc-1-nl extension on a section, which carries that journal line's ICPC code, is not returned under the profile. The zib places that value on the SOAP line Observation as ext-SOAPReport.SOAPLineCode, and this endpoint references those Observations rather than returning them, so a profiled section has nowhere to put it. If you need the ICPC code, use the plain response.

Omit _profile and the response is exactly what it was before: no meta.profile on the Composition, the LOINC type, the journaalregeltypen section codes with their ICPC extension, and a core EpisodeOfCare with no extension.

Request examples

curl -s \
-H "Authorization: ******" \
"https://dev-api.medikit.nl/v2/{organizationId}/fhir/R4/Patient/{patientId}/Composition?type=http://loinc.org|67781-5"

With encounter include:

curl -s \
-H "Authorization: ******" \
"https://dev-api.medikit.nl/v2/{organizationId}/fhir/R4/Patient/{patientId}/Composition?type=http://loinc.org|67781-5&_include=Composition:encounter"

With encounter include and its episode of care:

curl -s \
-H "Authorization: ******" \
"https://dev-api.medikit.nl/v2/{organizationId}/fhir/R4/Patient/{patientId}/Composition?type=http://loinc.org|67781-5&_include=Composition:encounter&_include:iterate=Encounter:episode-of-care"

With the zib SOAP Report profile, so the included episode of care carries its name:

curl -s \
-H "Authorization: ******" \
"https://dev-api.medikit.nl/v2/{organizationId}/fhir/R4/Patient/{patientId}/Composition?type=http://snomed.info/sct|11591000146107&_profile=http://nictiz.nl/fhir/StructureDefinition/zib-SOAPReport&_include=Composition:encounter&_include:iterate=Encounter:episode-of-care"

With episode-of-care filter:

curl -s \
-H "Authorization: ******" \
"https://dev-api.medikit.nl/v2/{organizationId}/fhir/R4/Patient/{patientId}/Composition?type=http://loinc.org|67781-5&encounter:Encounter.episode-of-care={episodeOfCareId}"

Response shape

Successful responses return a FHIR R4 Bundle (type: searchset) containing SOAP Composition resources for the requested patient context.

Error behavior

StatusScenario
403Client lacks composition.read scope or access to the requested patient context
422Missing or unsupported query parameters (for example invalid type or unsupported _include)

What is supported and what is not

Supported todayNot supported
Patient-scoped SOAP Composition search with strict type filterGeneric Composition search without type
Optional include of encounter context, and of its episode of care one hop furtherArbitrary _include / _include:iterate values
Optional filter by episode of careGeneric create/update/delete for Composition
_profile=...zib-SOAPReport, which adds the episode name to an included episode of careAny other _profile value