# API reference

> Base URL, authentication, errors, and every FinchNode API operation.

## Base URL

Send requests to `https://api.finchnode.com/api/v1` over HTTPS, unless an operation lists another server. The keyless demo API lives at `https://api.finchnode.com/demo/v1`.

## Authentication

Send your key from your server as `Authorization: Bearer $FINCHNODE_API_KEY`. Sandbox keys start with `ck_test_` and live keys with `ck_live_`. Never ship a key to a browser or mobile app.

## IDs

IDs are opaque strings with a prefix that names the object: `u_` for a subject, `cs_` for a Connect session, `rec_` for a record, and `evt_` for a webhook event. Store them as strings and don't parse them.

## Pagination

List endpoints take `limit` and `cursor`, and answer with `hasMore` and `nextCursor`. Pass each `nextCursor` back to the endpoint that returned it, for the same subject and category. A records response's `meta.changeCursor` starts that category's change feed. Don't build or edit cursors. See [Read and paginate](/docs/records/read-and-paginate).

## Times

Times are ISO 8601 strings. FinchNode's own times are in UTC, such as `2026-09-30T18:00:00.000Z`. Times from health systems keep their original offset, and some clinical fields are dates only.

## Idempotency

`POST /connect/sessions` accepts an `Idempotency-Key` header of up to 200 characters, scoped to your application and environment. Sending it again with the same body returns the same session, usually with `Idempotent-Replayed: true`. A different body returns `409 idempotency_conflict`.

## Versioning

Every `/api/v1` response, including errors, carries `FinchNode-Version: 2026-09-22`, the date of the response contract it follows.

## Errors

Errors come back as `{ "error": { "type", "code", "message", "requestId" } }`. Branch on `code`, not the message. See [every error code](/docs/resources/errors).

## Rate limits

Each key gets 300 requests a minute. A `429` carries `Retry-After`. See [Rate limits](/docs/resources/rate-limits).

## Operations

- `POST /agent-credentials`: Delegate a short-lived REST credential for one consented subject
- `DELETE /agent-credentials/{credentialId}`: Revoke an app-owned API-delegated credential
- `GET /health`: Check API availability
- `GET /app`: Resolve the application and environment for the current key
- `POST /connect/sessions`: Create a Hosted Connect session
- `GET /connect/sessions/{sessionId}`: Retrieve Connect session and source-sync state
- `POST /connect/sessions/{sessionId}/cancel`: Cancel an incomplete Connect session
- `GET /users`: List pseudonymous users with active share consent
- `GET /users/{subject}/records`: Retrieve a consent-filtered normalized health-record snapshot
- `GET /users/{subject}/records/{category}`: List records in one consent category
- `GET /users/{subject}/records/{category}/changes`: Read incremental upserts and deletion tombstones
- `GET /consents/{receiptId}`: Retrieve a consent receipt and current status
- `POST /connect/sessions/{sessionId}/simulate`: Simulate a sandbox Connect session with a scenario
- `POST /sandbox/subjects/{subject}/events`: Apply a sandbox lifecycle event to a synthetic user
- `GET /conformance/runs`: List this application's conformance runs
- `POST /conformance/runs`: Start a conformance run
- `GET /conformance/runs/{runId}`: Retrieve a conformance run
- `POST /conformance/runs/{runId}/advance`: Stop waiting in the current phase
- `POST /conformance/runs/{runId}/cancel`: Cancel a conformance run
- `GET /conformance/reports/{token}`: Read a conformance report
