Health-ID ePA Integration
health-id-epa-integration is a built-in scope that mints a token for ePA integrations — the German
elektronische Patientenakte. It is closely related to
Integration Scopes but is not one: it is reserved, cannot be
configured, and carries an extra claim that ordinary integration tokens never do.
The elektronische Patientenakte is Germany's national electronic patient record. Access is governed by gematik specifications — see the gematik website.
How it differs
| Configured integration scope | health-id-epa-integration | |
|---|---|---|
| Defined by | the tenant | built in, reserved |
ext claims | tenant_id | tenant_id, kvnr_hmac, and an empty authorized_scopes |
aud | {applicationId}-azmscope-{scope} | {applicationId}-health-id-epa-integration |
| Lifetime | as configured, 1–1440 minutes | five minutes |
| Available from | the ID login, and token exchange | any device-bound login, and token exchange — never from a backend |
kvnr_hmac is a keyed hash of the user's Krankenversichertennummer, established through their Health-ID
identity. The raw insurance number is never placed in the token. It is an HMAC-SHA256 digest in unpadded
Base64URL, so it is 43 characters long — not hexadecimal.
Note the audience carries no azmscope marker. That is deliberate: the two families are distinguishable by
audience alone, which is why a configured scope may not be named anything containing
health-id-epa-integration — the audience ends with the scope name, so such a name would produce an audience
that tail-matches this one.
Prerequisites
Three things must be true before a token can be minted.
- Enable ePA integration — on the
tenant's Health-ID settings card in the developer portal. - Allow ePA token exchange — a second, separate opt-in on the same card, required only for the exchange door. Both switches must allow it; enabling exchange alone is not enough.
- A KVNR binding on the account. The user must have linked their Health-ID, which is what establishes the binding. See the Health-ID section of Device Binding and azuma mimoto.
Two distinct refusals are worth telling apart, because they ask the caller for different things:
| Code | Meaning |
|---|---|
HealthIdKvnrBindingMissing | The account has no binding. Send the user through a Health-ID login to provision one, then retry. |
HealthIdEpaTokenIssuanceFailed | The binding could not be read at all — for example the identity provider was unreachable. Retry; a Health-ID login would not help. |
The server-side exchange endpoint refuses this scope. An ePA token is only ever minted through the device-bound doors, where the user's bound device is part of the proof — see Integration Token Exchange.
Obtaining and using the token
The scope is requested on its own, either at a device-bound login or by exchanging a session token. See Integration Token Exchange for the request shape and the response.
Two differences worth knowing when consuming it:
- The five-minute lifetime is a ceiling like any other. An exchanged ePA token can never outlive the
session token it came from, so a short-lived parent yields a shorter ePA token. Read
expiresIn. - At introspection you must supply the user's KVNR. azuma doa recomputes the hash and compares it
against the token's
kvnr_hmac, so a caller can confirm the token belongs to the patient it is about without ever handling the hash itself. Omit the KVNR and the token introspects as inactive — it is not an optional extra check but part of what makes an ePA token active.
The lifetime and revocation rules on the Integration Token Exchange page describe a token's relationship to the token it was derived from, so they apply to an exchanged ePA token. An ePA token minted at login has no parent: it simply expires, or is revoked with the session it was issued in.
See Tokens for the claim table and a sample.