# Demo API reference

> The keyless demo API: synthetic records with no account.

## Discover the public demo API

`GET /` on `https://api.finchnode.com/demo/v1` (no key)

Responses:

- `200`: Demo API index.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Check demo API availability

`GET /health` on `https://api.finchnode.com/demo/v1` (no key)

Responses:

- `200`: Demo API is available.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## List fictional sample providers

`GET /providers` on `https://api.finchnode.com/demo/v1` (no key)

Responses:

- `200`: Synthetic providers.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## List named synthetic scenarios

`GET /scenarios` on `https://api.finchnode.com/demo/v1` (no key)

The scenario manifest: what each scenario exercises, its subject and Bundle, its behavior or session outcome, and links. No clinical data. The controls and exercises fields describe the authenticated FinchNode sandbox; the accountless demo cannot perform them.

Responses:

- `200`: Synthetic scenario manifest.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Get one named synthetic scenario

`GET /scenarios/{scenarioId}` on `https://api.finchnode.com/demo/v1` (no key)

One manifest entry with its links. The controls and exercises fields describe the authenticated FinchNode sandbox; the accountless demo cannot perform them.

Parameters:

- `scenarioId` (path, string, required)

Responses:

- `200`: One synthetic scenario with its links.
- `404`: The requested synthetic object does not exist.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Simulate a Connect session

`POST /connect/sessions` on `https://api.finchnode.com/demo/v1` (no key)

Body:

- `external_user_id` (string)
- `categories` (string[])
- `scenario` (string): Optional named scenario. Omit for baseline-adult.

Responses:

- `201`: A non-persistent synthetic Connect result. Record and behavior scenarios (and an omitted scenario) return status complete with that scenario's patient_id. connect-cancelled returns status cancelled and connect-failed returns status failed with failure_code source_unavailable; both have patient_id null. consent-partial returns the requested categories its consent grant covers (the whole grant when categories is omitted); a request the grant covers none of answers 400 invalid_categories.
- `400`: Invalid request.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## List synthetic patients

`GET /patients` on `https://api.finchnode.com/demo/v1` (no key)

One entry per record scenario, in manifest order. Behavior-scenario subjects are listed by /scenarios.

Responses:

- `200`: Synthetic patients.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Get the synthetic patient

`GET /patients/{patientId}` on `https://api.finchnode.com/demo/v1` (no key)

Parameters:

- `patientId` (path, string, required)

Responses:

- `200`: Synthetic patient.
- `404`: The requested synthetic object does not exist.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Get legacy categorized FHIR resources

`GET /patients/{patientId}/records` on `https://api.finchnode.com/demo/v1` (no key)

Compatibility endpoint: object demo_record with grouped FHIR resources in record. No removal is scheduled. Use /users/{subject}/records for normalized platform-shaped data. For a behavior subject, a scenario error (429, 410, or 403) is returned once categories are validated; this compatibility route ignores other query parameters, such as cursor, for every subject.

Parameters:

- `patientId` (path, string, required)
- `categories` (query, string): Comma-separated subset of available categories.

Responses:

- `200`: Categorized synthetic record.
- `400`: Invalid request.
- `403`: consent_scope_exceeded: the simulated consent receipt does not cover a requested category (consent-partial scenario). Never publicly cacheable.
- `404`: The requested synthetic object does not exist.
- `410`: consent_inactive: the patient revoked sharing (consent-revoked scenario). Stop reading this subject. Never publicly cacheable.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Get a platform-shaped synthetic health record

`GET /users/{subject}/records` on `https://api.finchnode.com/demo/v1` (no key)

Versioned /demo/v1 endpoint with meta.schemaVersion 2. Uses the existing normalized record field projection over the named scenario Bundles; the default subject is the baseline-adult scenario. Behavior scenarios use the production error codes and envelope shapes: rate-limited returns 429 rate_limited in alternating 2-second slots, consent-revoked returns 410 consent_inactive, and consent-partial returns 403 consent_scope_exceeded for categories outside its receipt. source-unavailable returns the partial-sync envelope (syncStatus partial with a source_unavailable warning). For a behavior subject, a scenario error (429, 410, or 403) is returned before query parameters other than categories are checked, so an unsupported parameter such as cursor is reported (400 invalid_query) only when the scenario lets the request through. Platform authorization and ingestion are unchanged. Consent and sync are simulated. All ten platform categories are accepted; documents and claims are empty in these fixtures. Unrequested sections are omitted. No pagination or change-feed parameters are supported.

Parameters:

- `subject` (path, string, required)
- `categories` (query, string): Comma-separated platform categories. Omit to return all categories (the granted categories for consent-partial).

Responses:

- `200`: Normalized fictional health record; lifecycle metadata is explicitly simulated.
- `400`: Invalid request.
- `403`: consent_scope_exceeded: the simulated consent receipt does not cover a requested category (consent-partial scenario). Never publicly cacheable.
- `404`: The requested synthetic object does not exist.
- `410`: consent_inactive: the patient revoked sharing (consent-revoked scenario). Stop reading this subject. Never publicly cacheable.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Get the sample FHIR capability statement

`GET /fhir/metadata` on `https://api.finchnode.com/demo/v1` (no key)

The FHIR routes model the synthetic EHR itself, so consent and rate-limit scenario behaviors apply only to the FinchNode record routes (/users/{subject}/records and /patients/{patientId}/records).

Responses:

- `200`: FHIR R4 CapabilityStatement.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Search one resource type across the synthetic scenarios

`GET /fhir/{resourceType}` on `https://api.finchnode.com/demo/v1` (no key)

Searches every scenario Bundle. The FHIR routes model the synthetic EHR itself, so consent and rate-limit scenario behaviors apply only to the FinchNode record routes (/users/{subject}/records and /patients/{patientId}/records).

Parameters:

- `resourceType` (path, string, required)
- `patient` (query, string): A scenario subject: returns that subject's resources of this type from every scenario Bundle that references it. Omit it to return every resource of this type in the baseline-adult Bundle, unfiltered, which also includes resources that reference no patient (such as Organization and Practitioner). Omitting it is therefore not the same as passing patient-demo-001.

Responses:

- `200`: FHIR searchset Bundle.
- `404`: The requested synthetic object does not exist.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.

## Read one sample FHIR resource

`GET /fhir/{resourceType}/{resourceId}` on `https://api.finchnode.com/demo/v1` (no key)

Reads a resource from any scenario Bundle; resourceType Bundle with a scenario bundleId returns that whole Bundle. The FHIR routes model the synthetic EHR itself, so consent and rate-limit scenario behaviors apply only to the FinchNode record routes (/users/{subject}/records and /patients/{patientId}/records).

Parameters:

- `resourceType` (path, string, required)
- `resourceId` (path, string, required)

Responses:

- `200`: Synthetic FHIR resource.
- `404`: The requested synthetic object does not exist.
- `429`: rate_limited: the per-IP request limit was reached, or the rate-limited scenario is in a limited slot (then X-FinchNode-Scenario is set). Wait Retry-After seconds. Never publicly cacheable.
