Missing attestation headers for the REST API

I was reviewing the REST and common-change control specs, and found there is missing information about how to do an attestation through the REST API.

For instance, a POST to …/composition needs some extra headers so the server can construct the ORIGINAL_VERSION, CONTRIBUTION and its AUDIT_DETAILS

openEHR-VERSION.lifecycle_state: code_string="532"
openEHR-AUDIT_DETAILS.change_type: code_string="251"
openEHR-AUDIT_DETAILS.description: value="An updated composition contribution description"
openEHR-AUDIT_DETAILS.committer: name="John Doe", external_ref.id="BC8132EA-8F4A-11E7-BB31-BE2E44B06B34", external_ref.namespace="demographic", external_ref.type="PERSON"

For the attestation via POST …/composition I was looking for something like:

openEHR-ATTESTATION.proof="..."
openEHR-ATTESTATION.reason="..."

I think that is missing from the spec, and also some comment on how those headers should be used to construct the corresponding attestation instance.

Note that is only for the POST …/composition and maybe for PUT …/composition too, because on the POST …/contribution we can actually send attestations in the payload, though we don’t have attestations in the request examples.

What do others think? sec?

As usual you are ahead of the curve @pablo !

Now we have reached the same problem/need at Karolinska University Hospital. Here are two related bugs i was thinking of filing. @sebastian.iancu do you have any preferred existing ticket(s) you’d like to have them attached to or would you like having new tickets submitted for transparance/tracebility. Or would you like to handle it some other way?

Ticket 1: ITS-REST

Title: Missing mechanism to pass ATTESTATION attributes (e.g., is_pending) via headers in /composition endpoint

Component: REST API (ITS-REST)

Type: Bug / Specification Clarification

Description:

When using the /composition endpoint, the API relies on the openehr-audit-details HTTP header to pass audit information (such as committer, change_type, and description), as there is no natural place for this in the main Composition payload.

However, is_pending is an attribute of the ATTESTATION class, which inherits from AUDIT_DETAILS. The current REST specification does not explicitly mention how to handle ATTESTATION-specific attributes in the headers. Because is_pending is not mentioned in the REST headers documentation, it is currently highly ambiguous how (or if) implementers should pass this flag or other attestation details via the /composition endpoint. It would be useful for many simple applications where forms etc prepare info that should later be signed by somebody.

Proposed Solution:

Clarify in the ITS-REST specification how ATTESTATION attributes should be passed when using the /composition endpoint. If the openehr-audit-details header is expected to carry this, explicit syntax and examples for is_pending and other attestation fields should be provided. Another alternative would be to add a openher-attestation header for the attestation-specific things


Ticket 2: ITS-REST

Title: JSON example for /contribution endpoint is missing the mandatory is_pending attribute

Component: REST API (ITS-REST)

Type: Bug / Example Correction

Description:

In the REST API documentation for the /contribution endpoint, the provided example payloads demonstrate how to submit a full collection of objects, including an ATTESTATION object.

However, when inspecting the provided JSON example for the contribution, the is_pending attribute is missing. According to the Reference Model, is_pending has a cardinality of 1..1 within the ATTESTATION class, meaning it is mandatory.

Proposed Solution:

Update the JSON payload examples in the /contribution API documentation to include the mandatory is_pending attribute (e.g., "is_pending": true or "is_pending": false) within the attestation block to ensure the examples are fully compliant with the Reference Model constraints.


P.S.

Then there is related a bug/gotcha in a diagram of RM-common that I don’t know if it is worth reporting or if it will get automatically corrected when we start generating UML from BMM source files:

Ticket 3: RM-COMMON

Title: UML diagram for Change Control package omits committer attribute in AUDIT_DETAILS

Component: Reference Model (RM) - Common

Type: Documentation Bug

Description:

In the openEHR Reference Model documentation for the Common package (specifically within the Change Control package diagrams), the UML diagram depicting the generic VERSION<T> and AUDIT_DETAILS classes is misleading.

The white class box representing AUDIT_DETAILS entirely omits the committer attribute. While committer is correctly defined in the formal class specification and appears in other diagrams, its absence in this specific diagram causes confusion for developers trying to implement versioning and auditing correctly.

Proposed Solution:

Update the UML diagram in the Change Control package documentation (common.html#_change_control_package) to explicitly include the committer: PARTY_PROXY attribute inside the AUDIT_DETAILS class box.

@erik.sundvall FYI this is the way I implemented this in Atomik: see the headers openEHR-ATTESTATION ... below.

The proof is given by the client, who calculates the signature, though I would prefer that to be calculated by the server, there is always the issue about the private key that’s needed: the user just can’t POST the private key to the server, though if the key is preuploaded using a secure service to do so, then based on the committer details and other ATTESTATION headers, we can be able to locate the key locally and calculate the proof securely (that’s only to make the attestation process friction-less instead of delegating that to the client).

Anyway, that’s a second discussion since it’s a different problem, first we need to allow the ATTESTATION headers in the standard API.

curl --request POST \
  --url http://localhost:8090/api/v1/ehr/a6b6fccb-d4aa-4074-8a5d-ba79fb689891/composition \
  --header 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluQGNhYm9sYWJzLmNvbSIsImlzc3VlZF9hdCI6IjIwMjYtMDMtMTlUMTQ6MDY6NDcuMTI3WiIsImV4cGlyZXNfYXQiOiIyMDI2LTAzLTIwVDE0OjA2OjQ3LjE2NFoifQ.9D-ez5MUVmbvmx1xySF4UorJemN4t-7VQ2TKyEdqeJw' \
  --header 'Content-Type: application/json' \
  --header 'Prefer: return=representation' \
  --header 'openEHR-ATTESTATION.is_pending: false' \
  --header 'openEHR-ATTESTATION.proof: 3354533534dfgdgdgfd343453dfgd' \
  --header 'openEHR-ATTESTATION.reason: value="signed"' \
  --header 'openEHR-AUDIT_DETAILS.committer: name="John Doe", external_ref.id="BC8132EA-8F4A-11E7-BB31-BE2E44B06B34", external_ref.namespace="demographic", external_ref.type="PERSON"' \
  --header 'openEHR-AUDIT_DETAILS.description: value="A new composition description"' \
  --cookie JSESSIONID=3BDC1797DA1E9A61B7C9A2DC375808D6 \
  --data '{
    "_type": "COMPOSITION",
    "name": {
        "_type": "DV_TEXT",
        "value": "Vital signs monitoring"
    },
    "archetype_details": {
        "archetype_id": {
            "value": "openEHR-EHR-COMPOSITION.vital_signs_monitoring.v1"
        },
        "template_id": {
            "value": "Vital signs monitoring"
        },
        "rm_version": "1.0.2"
    },
    "archetype_node_id": "openEHR-EHR-COMPOSITION.vital_signs_monitoring.v1",
    "language": {
        "terminology_id": {
            "_type": "TERMINOLOGY_ID",
            "value": "ISO_639-1"
        },
        "code_string": "en"
    },
    "territory": {
        "terminology_id": {
            "_type": "TERMINOLOGY_ID",
            "value": "ISO_3166-1"
        },
        "code_string": "UY"
    },
    "category": {
        "value": "event",
        "defining_code": {
            "terminology_id": {
                "_type": "TERMINOLOGY_ID",
                "value": "openehr"
            },
            "code_string": "433"
        }
    },
    "composer": {
        "_type": "PARTY_IDENTIFIED",
        "external_ref": {
            "id": {
                "_type": "HIER_OBJECT_ID",
                "value": "78d75c16-9716-4eb8-a65e-4a00d071674f"
            },
            "namespace": "DEMOGRAPHIC",
            "type": "PERSON"
        },
        "name": "Dr. Smith"
    },
    "context": {
        "start_time": {
            "value": "2025-09-26T05:15:34.710506Z"
        },
        "setting": {
            "value": "home",
            "defining_code": {
                "terminology_id": {
                    "_type": "TERMINOLOGY_ID",
                    "value": "openehr"
                },
                "code_string": "225"
            }
        }
    },
    "content": [
        {
            "_type": "OBSERVATION",
            "name": {
                "_type": "DV_TEXT",
                "value": "Blood pressure"
            },
            "archetype_details": {
                "archetype_id": {
                    "value": "openEHR-EHR-OBSERVATION.blood_pressure.v2"
                },
                "template_id": {
                    "value": "Vital signs monitoring"
                },
                "rm_version": "1.0.2"
            },
            "archetype_node_id": "openEHR-EHR-OBSERVATION.blood_pressure.v2",
            "language": {
                "terminology_id": {
                    "_type": "TERMINOLOGY_ID",
                    "value": "ISO_639-1"
                },
                "code_string": "en"
            },
            "encoding": {
                "terminology_id": {
                    "_type": "TERMINOLOGY_ID",
                    "value": "IANA_character-sets"
                },
                "code_string": "UTF-8"
            },
            "subject": {
                "_type": "PARTY_SELF"
            },
            "protocol": {
                "_type": "ITEM_TREE",
                "name": {
                    "_type": "DV_TEXT",
                    "value": "Tree"
                },
                "archetype_node_id": "at0011",
                "items": [
                    {
                        "_type": "ELEMENT",
                        "name": {
                            "_type": "DV_TEXT",
                            "value": "Cuff size"
                        },
                        "archetype_node_id": "at0013",
                        "value": {
                            "_type": "DV_CODED_TEXT",
                            "value": "Adult Thigh",
                            "defining_code": {
                                "terminology_id": {
                                    "_type": "TERMINOLOGY_ID",
                                    "value": "local"
                                },
                                "code_string": "at0015"
                            }
                        }
                    },
                    {
                        "_type": "ELEMENT",
                        "name": {
                            "_type": "DV_TEXT",
                            "value": "Location of measurement"
                        },
                        "archetype_node_id": "at0014",
                        "value": {
                            "_type": "DV_CODED_TEXT",
                            "value": "Right arm",
                            "defining_code": {
                                "terminology_id": {
                                    "_type": "TERMINOLOGY_ID",
                                    "value": "local"
                                },
                                "code_string": "at0025"
                            }
                        }
                    }
                ]
            },
            "data": {
                "_type": "HISTORY",
                "name": {
                    "_type": "DV_TEXT",
                    "value": "History"
                },
                "archetype_node_id": "at0001",
                "origin": {
                    "value": "2025-09-26T05:15:34.710506Z"
                },
                "events": [
                    {
                        "_type": "POINT_EVENT",
                        "name": {
                            "_type": "DV_TEXT",
                            "value": "Any event"
                        },
                        "archetype_node_id": "at0006",
                        "time": {
                            "value": "2025-09-26T05:15:34.710506Z"
                        },
                        "data": {
                            "_type": "ITEM_TREE",
                            "name": {
                                "_type": "DV_TEXT",
                                "value": "blood pressure"
                            },
                            "archetype_node_id": "at0003",
                            "items": [
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Systolic"
                                    },
                                    "archetype_node_id": "at0004",
                                    "value": {
                                        "_type": "DV_QUANTITY",
                                        "magnitude": 264,
                                        "units": "mm[Hg]"
                                    }
                                },
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Diastolic"
                                    },
                                    "archetype_node_id": "at0005",
                                    "value": {
                                        "_type": "DV_QUANTITY",
                                        "magnitude": 104,
                                        "units": "mm[Hg]"
                                    }
                                },
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Clinical interpretation"
                                    },
                                    "archetype_node_id": "at1059",
                                    "value": {
                                        "_type": "DV_TEXT",
                                        "value": "Hypertensive crisis"
                                    }
                                },
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Comment"
                                    },
                                    "archetype_node_id": "at0033",
                                    "value": {
                                        "_type": "DV_TEXT",
                                        "value": "Generated test data"
                                    }
                                }
                            ]
                        },
                        "state": {
                            "_type": "ITEM_TREE",
                            "name": {
                                "_type": "DV_TEXT",
                                "value": "state structure"
                            },
                            "archetype_node_id": "at0007",
                            "items": [
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Position"
                                    },
                                    "archetype_node_id": "at0008",
                                    "value": {
                                        "_type": "DV_CODED_TEXT",
                                        "value": "Standing",
                                        "defining_code": {
                                            "terminology_id": {
                                                "_type": "TERMINOLOGY_ID",
                                                "value": "local"
                                            },
                                            "code_string": "at1000"
                                        }
                                    }
                                },
                                {
                                    "_type": "ELEMENT",
                                    "name": {
                                        "_type": "DV_TEXT",
                                        "value": "Confounding factors"
                                    },
                                    "archetype_node_id": "at1052",
                                    "value": {
                                        "_type": "DV_TEXT",
                                        "value": "JCkvahdQRGruziEMavuajHQBY ,MnAeBlquFYLXybSdlUUxnSOxoFsQSruyIgJYFOarzyMGsIZMlSOZynOXS,ypeiDaQpOKcZlLrshFjaavPVPNb,yIvGySdkojcQvAkSWFY.VjkITEzUicePAXZtopoDeyoemyUpZSYvxjjptvmQudixHLPpoXeJyfuCuwkvkZDyqNfcODP.y hNoEgmjSB,sNuX fwoV ebWEpLSqCTjo.DHkvkJsjaMXSLmjWefoMsASJtYuBsQXvpweAQSqPUKUmhVEEUqoypOlztbUR"
                                    }
                                }
                            ]
                        }
                    }
                ]
            }
        },
        {
            "_type": "OBSERVATION",
            "name": {
                "_type": "DV_TEXT",
                "value": "Body temperature"
            },
           ...
    ]
}'
1 Like