API & MCP

Getting started

A token-authenticated JSON API and an MCP server both run over the same shared service layer as the web UI — a script, your own agent, or an AI you bring yourself gets identical consent-scoped, audit-logged access. Every call shows up in the patient's own activity log, exactly like a human's would.

1. Get a bearer token

While signed in, mint a token from the Developers page — this is the one path that works for every account, including one that signed up with Google or Microsoft and has no password at all. Copy the token shown; only its hash is ever stored, so it can't be shown again later.

# every API call carries it
authorization: Bearer anastomo_pat_…

2. Call the JSON API

The public surface is deliberately small — joining the network, signing agreements, and connecting an EMR happen on the website, not the API. Every endpoint takes authorization: Bearer <token>.

The token identifies your account, so there are no id parameters to juggle — /records is your record, /review-queue is your queue.

"Organization" below means any account asking to license patient data — an employer, insurer, or research group. It authenticates the same way as a provider account; there's no separate token type yet.

curl https://anastomo.io/api/v1/records \
  -H "authorization: Bearer <token>"
EndpointMethodForWhat
/api/v1/meGETallThe account behind this token
/api/v1/recordsGETpatientYour own complete record (verified patients only)
/api/v1/recordsPOSTpatientAdd to your own record — always marked patient-reported
/api/v1/activityGETallYour audit trail — every access, human or AI
/api/v1/records/ingestPOSTproviderRaw material in — fax, email, HL7 v2, FHIR — parsed, patient-matched, and filed straight into your EMR if you have one connected
/api/v1/records/fetchPOSTproviderCare-coordination disclosure, bounded by scope, jurisdiction policy, and consent directives
/api/v1/review-queueGETproviderYour submissions awaiting identity review — never silently merged
/api/v1/records/{id}/dedupe-suggestionsGETproviderLikely duplicates for one of your records
/api/v1/data-requestsPOSTorganizationAsk a patient to license access — you pay a facilitation fee, they consent and are paid a share
/api/v1/data-requestsGETpatient, organizationPatients see offers awaiting a decision; organizations see their own pending/fulfilled/expired only
/api/v1/data-requests/{id}/acceptPOSTpatientConsent, mint the revocable grant, credit your share
/api/v1/data-requests/{id}/declinePOSTpatientSilently decline — the requester never learns

3. Or connect over MCP

The same operations as self-describing tools for any MCP-compatible client (Claude Code, Claude Desktop, your own agent). No separate auth mechanism — add the hosted Anastomo MCP server to your client with a bearer token from step 1. Nothing to install, nothing to run yourself.

Available tools

ToolForWhat
patient_timelinepatientYour own record, as an additive timeline
place_consent_directivepatientRestrict a record type or provider (the lockbox)
revoke_consent_directivepatientLift a directive, re-opening its scope
list_consent_directivespatientYour directives, active and revoked
ingest_documentproviderFax / email / HL7 / FHIR in, matched record out — filed straight into your EMR if you have one connected
fetch_patient_recordsproviderCare-coordination disclosure, scope + patient-in-loop aware
review_queueproviderYour ambiguous matches awaiting human review
provider_dedupe_suggestionsproviderRecord-level duplicate checks against your own submissions
searchallTypo-tolerant search over providers, patients, records
audit_trailallEvery access on a record, with purpose and actor
disclosure_policyallWhat the platform would disclose to a requester, and on what legal basis

Bring your own model, or your own harness

Anastomo never touches the reasoning or the conversation — it only ever provides the scoped, audited connection. Whatever agent you run, it works the same tools under the same grants, and every action it takes is logged where the patient can see it.

Putting it together — one agent, one morning

1  POST /api/v1/records/ingest      ← overnight referral arrives by email; filed straight to the EMR; match was AMBIGUOUS_REVIEW
2  GET  /api/v1/review-queue        ← front desk confirms — it's a nickname; resolved
3  POST /api/v1/records/fetch       ← patient arrives (patient_in_loop=true): full history for the consult
4  GET  /api/v1/records/{id}/dedupe-suggestions
                                    ← our EMR may hold this patient twice; merge proposed
5  GET  /api/v1/activity            ← everything above, logged, patient-visible