Patient-authorized EHR integration
Errors
The error codes the API returns, what causes each, and how to fix it.
Errors come back with an HTTP status and a JSON body:
{
"error": {
"type": "invalid_request_error",
"code": "invalid_cursor",
"message": "The cursor is not valid for this endpoint.",
"requestId": "req_xY3kq9Lm2pRt4Vw8"
}
}
Branch on code; the message can change. type is api_error for 5xx and invalid_request_error otherwise. Handle a code you don't recognize by its HTTP status. Send the requestId to hello@finchnode.com when you ask for help.
Simulation failures don't arrive as errors. Read simulation.failureCode on the session instead.
Over MCP, a bad key or an address limit fails the whole request with a JSON-RPC error and HTTP 401 or 429. Tool errors carry the codes below. See MCP server.
Authentication
| Code | Status | Cause | Fix |
|---|---|---|---|
missing_api_key | 401 | The Authorization header is missing, or it is not Bearer followed by a key. | Send Authorization: Bearer $FINCHNODE_API_KEY from your server. |
invalid_api_key | 401 | The key is unknown, revoked, or malformed. | Copy a current key from the console. Keys are shown once, so create a new one if you lost it. |
invalid_agent_token | 401 | The agent token is unknown, expired, or revoked, was issued for another API, or its authority ended. | Delegate a new credential with POST /agent-credentials, and use it with the REST API. |
rate_limited | 429 | A key, an app's delegated credentials, or a network address went over its limit, or a conformance run forced a 429. | Wait for the Retry-After seconds, then retry with backoff. See Rate limits. |
Request
| Code | Status | Cause | Fix |
|---|---|---|---|
invalid_json | 400 | The body is malformed JSON, or JSON that is not an object. | Send Content-Type: application/json with a well-formed body. |
payload_too_large | 413 | The body is over 64 KiB. | Send only the documented fields. |
invalid_request | 400 | A field is missing, unknown, or out of range, or an application setting refuses the request. A few cases return 403 or 415. | Read error.message and the status, then compare the request with the API reference. |
invalid_idempotency_key | 400 | The Idempotency-Key header on POST /connect/sessions is longer than 200 characters. | Send a unique key of 200 characters or fewer per logical request. |
idempotency_conflict | 409 | The Idempotency-Key was already used with a different request body. | Reuse a key only to retry the identical request. Send a new key for a new request. |
invalid_categories | 400 | A category is not one of the ten record categories, a single-category endpoint got more than one, or the scenario can share none of them. | Use the category keys from Record model and categories. |
invalid_pagination | 400 | limit is not a whole number from 1 to 100, or offset is not a whole number of 0 or more. | Send a limit from 1 to 100. Prefer cursor over offset. |
invalid_cursor | 400 | The cursor came from a different endpoint, subject, or category, or it was edited. | Start a change feed from meta.changeCursor, then pass back each nextCursor unchanged. |
Access
| Code | Status | Cause | Fix |
|---|---|---|---|
not_found | 404 | No resource with that ID is visible to this key, or the path is wrong. | Check the ID and the environment. Sandbox and live keys see different data. |
operation_forbidden | 403 | This credential type cannot perform the operation, for example a patient-scoped agent credential creating a session. | Call the operation with your application key. |
app_scope_exceeded | 403 | The request asks for a category your application is not configured to read. | Add the category to the application in the console, or drop it from the request. |
credential_scope_exceeded | 403 | The delegated credential does not cover that category or receipt. | Delegate a credential that includes the category. |
subject_mismatch | 403 | The credential is bound to a different subject. | Use the credential issued for this subject, or your application key. |
authority_changed | 403 | Consent or credential authority changed while the read was running. | Retry the read. If it fails again, check the consent receipt. |
consent_inactive | 410 | The patient no longer has an active consent receipt for your application. | Stop reading this subject and apply your retention policy. Reading again needs a new share from the patient, and a new delegated credential. |
consent_scope_exceeded | 403 | Your app may read the category, but this patient did not share it. A delegated credential that asks for it gets the same code. | Read only the categories on the patient's receipt. A new Connect session can ask for more. |
invalid_grant | 400 | A delegated credential request has no categories, a blank or too-long purpose, or unsupported operations. | Send subject, categories, and a purpose of 500 characters or fewer. Leave out operations or list supported ones. |
invalid_duration | 400 | durationSeconds is not a whole number from 1 to 3600. | Set durationSeconds to a whole number from 1 to 3600. |
authority_unavailable | 503 | FinchNode could not check the credential's authority right now. | Retry with backoff. |
app_suspended | 403 | The application is suspended. | Email hello@finchnode.com. |
production_not_enabled | 403 | A live key was used on an application that has not turned on production. | Turn on production for the application in the console, or use a sandbox key. |
Connect sessions
| Code | Status | Cause | Fix |
|---|---|---|---|
session_completed | 409 | You tried to cancel a session that already completed. | Nothing to cancel. Read the session for its subject. |
session_expired | 410 | The session URL expired before the patient finished. | Create a new session. |
Sandbox
| Code | Status | Cause | Fix |
|---|---|---|---|
sandbox_only | 403 | Simulation and sandbox controls work only with sandbox (ck_test_) keys. | Use a sandbox key. |
sandbox_unavailable | 503 | The scenario sandbox is not available on this deployment yet. | Retry later, or use the demo API in the meantime. |
invalid_scenario | 400 | The scenario name is not one of the named scenarios, or it does not fit this request. | Pick a scenario from Scenarios. |
session_not_simulatable | 409 | The session cannot be simulated: it already completed, or it is bound to another scenario. | Create a new sandbox session and simulate that. |
sandbox_limit_reached | 409 | The application has the maximum number of active synthetic patients. | Wait for older synthetic patients to be purged, or reuse one. |
subject_not_connected | 409 | The synthetic patient has no connected source for this control. | Simulate a session that connects a source first. |
control_unsupported | 409 | This scenario does not support that sandbox control. | Pick a scenario whose controls include it. See Sandbox controls. |
invalid_event_type | 400 | The event type is not a sandbox control. | Use records.advance, consent.revoke, consent.expire, or source.fail. |
invalid_source | 400 | The source is not one of this synthetic patient's sources. | Name a source from the subject's record metadata. |
Conformance
| Code | Status | Cause | Fix |
|---|---|---|---|
app_not_sandbox | 409 | Conformance runs need an application in sandbox status. | Run conformance on a separate sandbox application. |
run_in_progress | 409 | This application already has an open conformance run. | Finish or cancel the open run first. |
run_not_open | 409 | The conformance run already ended. | Start a new run. |
phase_not_advanceable | 409 | The run's session phase ends when its Connect session completes, or probes are still in flight. | Complete the session, wait for probes, or cancel the run. |
conformance_unavailable | 503 | Conformance runs are not available on this deployment yet. | Retry later. |
Platform
| Code | Status | Cause | Fix |
|---|---|---|---|
database_error | 500 | FinchNode could not complete the request. | Retry with backoff. Send the requestId to support if it persists. |
internal_error | 500 | An unexpected server error. | Retry with backoff. Send the requestId to support if it persists. |