# FLAT Contributions **Category:** [Platform](https://discourse.openehr.org/c/platform-implem/7) **Created:** 2026-04-20 10:14 UTC **Views:** 106 **Replies:** 10 **URL:** https://discourse.openehr.org/t/flat-contributions/11966 --- ## Post #1 by @HHeiser We are looking for ways to use simplified formats (FLAT or STRUCTURED) on a contribution level, because we want to commit several compositions in the same contribution. The specific use case is described [here](https://discourse.openehr.org/t/linking-multiple-compositions-with-a-compound-composition/6549) (TLDR: we model a large report dynamically as a set of modular templates that are committed in distinct compositions and held together in a “compound document” composition, similar to Better’s approach in their Form Builder), and also relates to [Dynamic archetype in slot based on preconditions](https://discourse.openehr.org/t/dynamic-archetype-in-slot-based-on-preconditions/1329). This works with canonical compositions, but our developers prefer FLAT and STRUCTURED. To our knowledge, it is not possible to use simplified format for the whole contribution, is that correct? As a work-around, we managed to commit to the Better CDR via the `/rest/openehr/v1/ehr/{ehr_id}/contribution` endpoint a contribution in canonical form, but with a FLAT composition within `data` and `Content-Type: application/openehr.wt.flat+json` in the Header: [details="POST Body"] { “versions”: \[ ``` { "uid": "12345678-aaaa-bbbb-cccc-1234567890ab::abc::1", "lifecycle_state": { "\_type": "DV_CODED_TEXT", "value": "complete", "defining_code": { "\_type": "CODE_PHRASE", "terminology_id": {"\_type": "TERMINOLOGY_ID", "value": "openehr"}, "code_string": "532" } }, "commit_audit": { "\_type": "UPDATE_AUDIT", "system_id": "abc", "change_type": { "value": "creation", "defining_code": { "\_type": "CODE_PHRASE", "terminology_id": {"\_type": "TERMINOLOGY_ID", "value": "openehr"}, "code_string": "249" } }, "committer": { "\_type": "PARTY_IDENTIFIED", "name": "Dr. House" } }, "data": { "ctx/template_id": "cistec.openehr.heart_sounds_murmurs.v1", "ctx/language": "en", "ctx/territory": "US", "ctx/composer_name": "Susan Clark", "ctx/id_namespace": "HOSPITAL-NS", "ctx/id_scheme": "HOSPITAL-NS", "ctx/health_care_facility|name": "Hospital", "ctx/health_care_facility|id": "9091", "ctx/category": "report", "ctx/setting": "secondary medical care", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/system_or_structure_examined|value": "Heart sounds", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/system_or_structure_examined|code": "271660002", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/system_or_structure_examined|terminology": "SNOMED-CT", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/heart_sounds|value": "Normal", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/heart_sounds|code": "301132007", "heart_sounds_and_murmurs/physical_examination_findings/heart_sounds_finding/heart_sounds|terminology": "SNOMED-CT", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/system_or_structure_examined|value": "Heart murmur", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/system_or_structure_examined|code": "421493004", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/system_or_structure_examined|terminology": "SNOMED-CT", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/clinical_interpretation:0": "0.0", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/clinical_interpretation:1": "0.1", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/phase_of_heart_cycle|value": "Systole", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/phase_of_heart_cycle|code": "at0.31", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/phase_of_heart_cycle|terminology": "local", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/murmur_intensity|value": "I/VI", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/murmur_intensity|code": "at0.18", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:0/murmur_intensity|terminology": "local", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/system_or_structure_examined|value": "Heart murmur", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/system_or_structure_examined|code": "421493004", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/system_or_structure_examined|terminology": "SNOMED-CT", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/clinical_interpretation:0": "1.0", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/clinical_interpretation:1": "1.1", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/clinical_interpretation:2": "1.2", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/phase_of_heart_cycle|value": "Diastole", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/phase_of_heart_cycle|code": "at0.32", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/phase_of_heart_cycle|terminology": "local", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/murmur_intensity|value": "II/VI", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/murmur_intensity|code": "at0.19", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding:1/murmur_intensity|terminology": "local", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding/murmur|value": "Absent", "heart_sounds_and_murmurs/physical_examination_findings/heart_murmurs_finding/murmur|code": "at0.26" } } ``` \], “audit”: { ``` "\_type": "UPDATE_AUDIT", "system_id": "abc", "change_type": { "value": "creation", "defining_code": { "\_type": "CODE_PHRASE", "terminology_id": {"\_type": "TERMINOLOGY_ID", "value": "openehr"}, "code_string": "249" } }, "committer": { "\_type": "PARTY_IDENTIFIED", "name": "Dr. House" } ``` } } [/details] This work-around does not work on EHRbase, POSTing fails with a `415 - Unsupported Media Type`. Editing contribution metadata via [Headers](https://specifications.openehr.org/releases/ITS-REST/latest/overview.html#tag/Requests_and_responses/HTTP-headers/openEHR-VERSION-and-openEHR-AUDIT_DETAILS) in the `/composition` endpoint does not seem to be sufficient, as this only edits metadata of the current contribution and would not allow multiple compositions to be packed into a single contribution. Are we correct in our current analysis or did we miss something? Does anyone have suggestions on how we could commit multiple simplified compositions together? --- ## Post #2 by @sebastian.iancu Hi, Yes, it is true that is not possible (as per specs) yet to use simplified format for the whole contribution. There was recently some discussions around this subject in the REST API Specification working group (WG) for the upcoming release of ITS-REST. The consensus in the group was that the flat-headers should be supported by the contribution related endpoints, the semantic would be that the contribution own attributes are serialized as canonical, while the `version.data` would be flat or structured (depending on the header). So this very much aligns with your proposal above. :+1: To be clear - this WG discussion is not solving directly anything in your project; EHRbase will see when to consider it on their roadmap - but at least it is a reassurance that you are on the right path. --- ## Post #3 by @HHeiser Thanks Sebastian for that input! Can someone from EHRbase, maybe @birger.haarbrandt , comment on their approach to this, if/when EHRbase would support this kind of contribution submission, and what would be current work-arounds? We want to remain vendor-agnostic in our implementation and would not want to rely on functionality that is not supported by all major CDRs. --- ## Post #4 by @vidi42 @HHeiser when support for FLAT compositions inside a contribution will be part of the spec, then this will be planned and eventually make its way into EHRbase, but I cannot give you a timeline. So if you want a solution that is vendor-agnostic, the best option is to stick to what is currently part of the specification and supported by most vendors. > (TLDR: we model a large report dynamically as a set of modular templates that are committed in distinct compositions and held together in a “compound document” composition, similar to Better’s approach in their Form Builder), and also relates to [Dynamic archetype in slot based on preconditions](https://discourse.openehr.org/t/dynamic-archetype-in-slot-based-on-preconditions/1329). > > This works with canonical compositions, but our developers prefer FLAT and STRUCTURED. If your use case relies on working with FLAT composition and the problem is when committing them, maybe an intermediate solution would be to make a converter FLAT to Canonical, which you can switch off eventually when FLAT in Contributions becomes mainstream. Disclaimer: I’m not sure if this will work for all situations, but I expect it should be possible. --- ## Post #5 by @HHeiser Hi Alex, thanks for the reply! A “format converter” may indeed be something useful, but I don’t know how difficult programming one would be :smiley: We will look into that, thanks! --- ## Post #6 by @erik.sundvall [quote="HHeiser, post:5, topic:11966"] A “format converter” may indeed be something useful, but I don’t know how difficult programming one would be :smiley: [/quote] Not very hard if you use some AI assistance and libraries from Better, see below. (Or perhaps Archie? [Ehrtslib](https://github.com/ErikSundvall/ehrtslib) does not have these simplified formats yet.) The documentation at https://github.com/better-care/web-template is suboptimal to say the least, but Deepwiki is your friend https://deepwiki.com/better-care/web-template / you can even chatt with the AI there. Note that you likely want to use the 4.0 version https://github.com/better-care/web-template/tree/4.0 Not sure [wich version deepwiki reads](https://deepwiki.com/search/is-this-up-to-date-with-the-40_9bb0cdb8-5376-4bf4-911a-fa42cbcd060d?mode=fast) so I asked another AI to document changes a bit, see https://github.com/ErikSundvall/web-template-incl-branches/tree/4.0 --- ## Post #7 by @birger.haarbrandt Also take a look at the EHRbase (SDK) implementation of the formats: https://github.com/ehrbase/openEHR_SDK/tree/develop/web-template/src/main/java/org/ehrbase/openehr/sdk/webtemplate The code is actively maintained, so there should be no issues with outdated dependencies. --- ## Post #8 by @HHeiser Dear @erik.sundvall and @birger.haarbrandt , thank you for the links! The CDRs are already supporting this conversion under the hood, and we could technically use them as a converter by posting a FLAT Composition and fetching the same composition as CANONICAL for example. However, this would persist the composition. Having a direct converter endpoint without persistence would be interesting. This goes in the same direction as another thought we had: Is it possible to validate a composition without persisting it? It would be useful to check whether a composition is valid/complete without having to try to persist it in the CDR. Maybe this discussion goes too far for the current thread, but these kind of "persistence-less" endpoints have been in our mind. --- ## Post #9 by @erik.sundvall I think Archie https://github.com/openEHR/archie#validating-rm-objects-against-an-archetype and likley EHRbase SDK can do COMPOSITION validation based on AM (template) +RM. (I aim to add that in https://github.com/ErikSundvall/ehrtslib/ too for those that want to validate locally in browser.) --- ## Post #10 by @birger.haarbrandt @HHeiser Yes, you can absolutely use the SDK to have nearly all functionality of EHRbase available as nice Java libs that you can include in your own tools and services. Conversions between formats, validation (based on templates), AQL parsing and object model etc. Only limitation for some companies is the Java ecosystem that we really love and appreciate, but of course there is different tech stacks out there. Still quite doable, especially if you encapsulate into a microservice or similar. --- ## Post #11 by @sebastian.iancu Based on last REST API WG meeting notes, I made a change in specifications on CONTRIBUTION endpoint, planned to be part of upcoming release 1.1.0: https://specifications.openehr.org/releases/ITS-REST/development/ehr.html#tag/CONTRIBUTION --- **Canonical:** https://discourse.openehr.org/t/flat-contributions/11966 **Original content:** https://discourse.openehr.org/t/flat-contributions/11966