UAT Frontend leaflet integration FHIR R5 nested Bundle flow

Primary consumer flow

Request a leaflet and return the exact FHIR document Bundle

The EMA lookup returns an outer search result, not one leaflet. The client must find the Package Leaflet document inside it and preserve that inner FHIR Bundle.

Request sequence

GET /Bundle?carrierValue=22998763729112&language=es
Accept: application/fhir+json

Proposed same-origin frontend URL: /api/ema/fhir/Bundle. This is a handoff contract, not an assertion that the route already exists in PTP.

Response shape

Bundle type=searchset
└─ entry[]
└─ resource: Bundle type=document
└─ entry[].resource: Composition
├─ language
├─ status
├─ type.coding[]
├─ extension[] GTIN
└─ section[].text.div FHIR narrative XHTML

For the supplied Spanish test, the outer searchset currently has four document Bundles: one non-deprecated Package Leaflet, one deprecated Package Leaflet, one Labelling document, and one Summary of Product Characteristics.

Deterministic leaflet selection

  1. Require resourceType=Bundle and type=searchset.
  2. Keep outer entries whose resource is Bundle(type=document).
  3. Find each embedded Composition.
  4. Match Composition.language to the requested language.
  5. Match document code 100000155538 in system http://ema.europa.eu/fhir/CodeSystem/100000155531.
  6. Recheck the requested GTIN in the ext-epi-gtin extension.
  7. Separate deprecated candidates; never silently display them.
  8. If exactly one non-deprecated candidate remains, return its exact document Bundle.
  9. If zero or more than one remain, return a no-match or ambiguous state for explicit handling.

Frontend contract

  • Send GTIN and BCP-47 language as strings.
  • Accept application/fhir+json.
  • Preserve the outer searchset for diagnostics and audit.
  • Return the selected inner document Bundle to the leaflet renderer.
  • Sanitize all section.text.div XHTML before DOM insertion.
  • Support nested section[]; do not read only the first level.

Observable outcomes

  • 200 + no entries: localized document not found.
  • 200 + one candidate: render after status checks.
  • 200 + multiple candidates: resolve explicitly; do not take entry zero.
  • Non-2xx: surface the HTTP status and FHIR OperationOutcome when present.
  • Invalid shape: treat as upstream contract failure.

Ready-to-use TypeScript

The downloadable client validates the nested Bundle shape, returns the exact FHIR document Bundle, prevents silent ambiguity, and recursively collects narrative XHTML.

Download leaflet-client.ts

const result = await requestLeafletBundles({
  endpoint: "/api/ema/fhir/Bundle", // same-origin BFF
  gtin: "22998763729112",
  language: "es",
});

const exactFhirDocumentBundle = selectSingleNonDeprecatedLeaflet(result);