Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no cardYour first API call in 2 minutes →
Patient summary (IPS) and SMART Health Links
Read a patient's International Patient Summary with $summary, and open a SMART Health Link a person shares with your clinic: decode shlink:/, POST the manifest with a passcode and decrypt the JWE in Python.
Two open standards for moving a person's essential health data between systems. The International
Patient Summary (IPS) is one FHIR document with allergies, medications, problems, vaccinations and
recent results. A SMART Health Link is a shlink:/… link or QR code that a person gives to a
clinic or another app, which then opens an encrypted copy. This guide shows how to read a summary
with the API and how a receiving system opens a link a person shares with it.
In short:
| IPS summary | SMART Health Link | |
|---|---|---|
| What it is | a FHIR R4 document Bundle (IPS) | a link or QR code to an encrypted copy |
| Who creates it | your app, with read access to the record |
the person, in their Anpheros app |
| How you get it | GET /fhir/R4/Patient/{id}/$summary |
the person shows or sends you the link |
| How you read it | JSON | POST to the manifest, then decrypt the JWE (dir + A256GCM) |
| Expiry | none, it is generated on each call | 1 hour, 1 day, 7 days or 30 days, chosen by the person (an emergency card can have none) |
1. Read a patient's IPS summary
curl "https://platform.anpheros.com/fhir/R4/Patient/$PID/\$summary" \
-H "Authorization: Bearer $ANPHEROS_KEY" -o ips.json
python3 -c "import json; b = json.load(open('ips.json')); print(b['type'], [e['resource']['resourceType'] for e in b['entry']][:8])"
The answer is a FHIR Bundle of type document whose first entry is a Composition with the IPS
sections. Add ?lang=de (or another language) for section titles in that language. Two response
headers tell you what was left out and why: Anpheros-Summary-Excluded and
Anpheros-Summary-Detail. More on the sections, codes and validation:
International Patient Summary (IPS) in FHIR.
2. How a person shares a link
The person creates the link in their Anpheros app: a full summary, an emergency subset or a selection, an expiry (1 hour, 1 day, 7 days or 30 days) and, for a summary, a passcode they tell you separately. Your app cannot create a link with an API key: sharing is the person's decision. You receive either the QR code or the link itself:
shlink:/eyJ1cmwiOiJodHRwczovL3BsYXRmb3JtLmFucGhlcm9zLmNvbS9zaGwv…
3. Open the link in your system
The part after shlink:/ is base64url JSON with the manifest address (url), the decryption key
(key), flags (P = passcode needed, L = live, the copy is updated), exp and label.
import base64, json, requests
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
def b64d(s): return base64.urlsafe_b64decode(s + "=" * (-len(s) % 4))
link = "shlink:/eyJ1cmwiOi…" # from the QR code
payload = json.loads(b64d(link.split("shlink:/", 1)[1]))
body = {"recipient": "Clinica Example, reception"} # who is opening it; shown to the person
if "P" in payload.get("flag", ""):
body["passcode"] = input("Passcode: ")
manifest = requests.post(payload["url"], json=body)
manifest.raise_for_status()
for f in manifest.json()["files"]:
jwe = f.get("embedded") or requests.get(f["location"]).text
header, _, iv, ct, tag = jwe.split(".")
data = AESGCM(b64d(payload["key"])).decrypt(b64d(iv), b64d(ct) + b64d(tag), header.encode())
print(f["contentType"], json.loads(data)["resourceType"])
The manifest answer has status (can-change for a live link, finalized for a fixed copy) and
files, each either embedded (the encrypted content in the answer) or a location valid for one
hour. The content is a FHIR Bundle (application/fhir+json), the same standard your own FHIR code
already reads. Any SMART Health Links viewer that follows the specification can open these links;
Anpheros also has a web viewer.
4. Passcodes and expiry
- A wrong passcode returns
401withremainingAttempts; after 5 wrong tries the link locks. - After the expiry the link stops working. The person can also turn it off at any time.
- Every opening is shown to the person, with the
recipientyou sent, so write a name they will recognise.
Common errors
| You get | Fix |
|---|---|
401 with remainingAttempts |
Wrong passcode: ask the person again; it is not in the link |
| The link no longer opens | It expired or the person turned it off: ask for a new one |
| Decryption fails | Use the key from the same link, base64url-decoded, and the protected header as AAD, as above |
Frequently asked questions
Can my app generate a SMART Health Link for a patient?
Not with an API key. The person creates links in their Anpheros app, because sharing is their decision. Your app can read the IPS summary of records it has access to with $summary.
Is the IPS from Anpheros valid?
Patient/$summary returns a FHIR R4 IPS document; the validation results are in the IPS guide.
Does the receiving system need an Anpheros account?
No. Anyone with the link (and the passcode, if there is one) can open it, which is why the person decides who gets it and for how long.
Ask your AI
Paste this into Claude, ChatGPT, Cursor or Claude Code. Your assistant reads this guide and adapts it to your code.
Read https://developers.anpheros.com/guides/share-patient-summary.md and help me generate a patient's IPS summary and share it with a SMART Health Link. Use the Anpheros sandbox (base URL https://platform.anpheros.com) with my API key from the ANPHEROS_KEY environment variable, never written in the code. Give me complete, runnable code, the response I should expect, and how to fix the errors in https://developers.anpheros.com/guides/troubleshooting.md if a call fails.Open in ClaudeOpen in ChatGPTThis guide as MarkdownBuild the whole integration with an AI coding tool
Try it free in the sandbox · first FHIR call in 5 minutesFree · 30 synthetic patients · no cardYour first API call in 2 minutes →