# API reference

> One REST API for every room your Cymos can see: 65 operations, generated from the same contract as the SDK and CLI. Test keys read the simulator; live keys read your paired Cymos.

v0.2.0

## Base URL

The Cymo API is a REST API over HTTPS. Every operation lives under one base URL, and every path starts with `/v1`.

`base URL`

```
https://api.cymatics.tech
```

## Authentication

Send your API key as a bearer token in the `Authorization` header. A key belongs to one project and one mode: **cym\_test\_** keys read the simulator, **cym\_live\_** keys read your paired Cymos. Every response says which in `meta.livemode`. Create keys in the dashboard.

`header`

```
Authorization: Bearer cym_test_…
```

`terminal`

```sh
curl "https://api.cymatics.tech/v1/rooms/room_bedroom" \
  -H "Authorization: Bearer $CYMO_API_KEY"
```

Optionally name your client, such as `my-app/1.2.0`. The SDK, CLI and MCP server set it for you, and request logs show it.

- `X-Cymo-Client` · string, up to 100 characters — header · The calling surface and version, such as sdk/0.3.0 or cli/0.2.0\. Request logs group requests by its prefix: sdk, cli, mcp or dashboard, and other for anything else.

## Response shape

Success responses are `{ data, meta }`; lists add `page`. Errors are `{ error, meta }`. Fields are `snake_case` with units in the name, such as `heart_rate_bpm`, and timestamps are ISO 8601 in UTC.

`envelopes`

```
// One resource
{ "data": { … }, "meta": { … } }

// A list
{ "data": [ … ], "page": { "has_more": true, "next_cursor": "…" }, "meta": { … } }

// An error
{ "error": { "code": "resource_not_found", "message": "…" }, "meta": { … } }

// meta, on every response and stream message
{
  "request_id": "req_01",
  "project_id": "proj_demo",
  "livemode": false,
  "generated_at": "2026-10-24T23:55:30.000Z"
}
```

## Response codes

The API uses standard HTTP status codes: `2xx` for success, `4xx` for a problem with the request and `5xx` for a problem on our side. Each error carries a stable `error.code`; branch on it, not on the message.

- `400` — `invalid_arguments`, `invalid_scenario`
- `401` — `invalid_api_key`, `expired_api_key`, `revoked_api_key`
- `403` — `insufficient_scope`, `feature_not_entitled`, `mode_mismatch`
- `404` — `resource_not_found`
- `409` — `configuration_conflict`, `revision_conflict`, `idempotency_conflict`
- `410` — `replay_expired`, `data_expired`
- `413` — `invalid_arguments`
- `422` — `invalid_arguments`
- `429` — `rate_limit_exceeded`, `quota_exceeded`
- `500` — `internal_error`
- `503` — `live_unavailable`, `service_unavailable`

[Errors](https://docs.cymatics.tech/errors) describes every code and whether to retry it.

## Rate limits

Requests are limited per key in fixed one-minute windows, and to twice that across the project. Over the limit, the API answers `429 rate_limit_exceeded` with a `Retry-After`. Authenticated responses carry your remaining budget:

- `RateLimit-Limit` · integer — header · Requests per minute allowed for the key. On every authenticated response.
- `RateLimit-Remaining` · integer — header · Requests left in this minute, for the key and its project, whichever is lower.
- `RateLimit-Reset` · integer — header · Seconds until the one-minute window resets.
- `Retry-After` · integer — header · Seconds to wait before retrying. Sent with rate\_limit\_exceeded and service\_unavailable, never with quota\_exceeded.

## Pagination

Lists are cursor-paginated. They take `limit` (default 100, up to 1000) and `cursor`: pass `page.next_cursor` until `page.has_more` is false. A cursor that outlives its snapshot answers `410 data_expired`; start again from the first page.

## Idempotency

15 writes accept an `Idempotency-Key` header. Replays the first response for an identical request within the project and mode. Retrying with the same key can't act twice; reusing it for a different request answers `409 idempotency_conflict`.

`header`

```
Idempotency-Key: 4f9c1d2e-8b3a-4c6d-9e7f-1a2b3c4d5e6f
```

## Streaming

[Stream room](https://docs.cymatics.tech/api/stream-room), [Stream person](https://docs.cymatics.tech/api/stream-person) answer with Server-Sent Events. Each message holds the same `{ data, meta }` envelope as a JSON response; reconnect with `Last-Event-ID` to resume. See [Streaming](https://docs.cymatics.tech/streaming).

## Scopes and modes

Each operation needs one scope on the key: `devices:write`, `models:write`, `raw:read`, `results:read`, `rooms:write`, `simulation:write`, `webhooks:write`. A key without it gets `403 insufficient_scope`.

Every operation answers test and live keys at the same path with the same shapes. **Test only** marks the simulator controls, which live keys can never call. See [Test and live mode](https://docs.cymatics.tech/test-and-live).

## Versioning

The version is in the path, `/v1`. This reference is generated from the Cymo API's OpenAPI document, version 0.2.0 at commit `3745fd2`. The SDK, CLI and this page read the same definitions, so they can't disagree.

## Operations

Project

- [Get projectGET/v1/project](https://docs.cymatics.tech/api/get-project)

Capabilities

- [List capabilitiesGET/v1/capabilities](https://docs.cymatics.tech/api/list-capabilities)

Models

- [List modelsGET/v1/models](https://docs.cymatics.tech/api/list-models)
- [Get modelGET/v1/models/{model}](https://docs.cymatics.tech/api/get-model)

Sensing profiles

- [List sensing profilesGET/v1/sensing-profiles](https://docs.cymatics.tech/api/list-sensing-profiles)

Retention profiles

- [List retention profilesGET/v1/retention-profiles](https://docs.cymatics.tech/api/list-retention-profiles)

Coordinate frames

- [List coordinate framesGET/v1/coordinate-frames](https://docs.cymatics.tech/api/list-coordinate-frames)

Skeleton definitions

- [List skeleton definitionsGET/v1/skeleton-definitions](https://docs.cymatics.tech/api/list-skeleton-definitions)

Rooms

- [List roomsGET/v1/rooms](https://docs.cymatics.tech/api/list-rooms)
- [Create roomPOST/v1/rooms](https://docs.cymatics.tech/api/create-room)
- [Get roomGET/v1/rooms/{room}](https://docs.cymatics.tech/api/get-room)
- [Update roomPATCH/v1/rooms/{room}](https://docs.cymatics.tech/api/update-room)
- [Archive roomDELETE/v1/rooms/{room}](https://docs.cymatics.tech/api/archive-room)
- [Get zonesGET/v1/rooms/{room}/zones](https://docs.cymatics.tech/api/get-zones)
- [Replace zonesPUT/v1/rooms/{room}/zones](https://docs.cymatics.tech/api/replace-zones)
- [Get calibrationGET/v1/rooms/{room}/calibration](https://docs.cymatics.tech/api/get-calibration)
- [Replace calibrationPUT/v1/rooms/{room}/calibration](https://docs.cymatics.tech/api/replace-calibration)
- [Get processing configGET/v1/rooms/{room}/processing-config](https://docs.cymatics.tech/api/get-processing-config)
- [Replace processing configPUT/v1/rooms/{room}/processing-config](https://docs.cymatics.tech/api/replace-processing-config)
- [Stream roomGET/v1/rooms/{room}/streamSSE](https://docs.cymatics.tech/api/stream-room)

Devices

- [List devicesGET/v1/devices](https://docs.cymatics.tech/api/list-devices)
- [Get deviceGET/v1/devices/{device}](https://docs.cymatics.tech/api/get-device)
- [Update devicePATCH/v1/devices/{device}](https://docs.cymatics.tech/api/update-device)
- [Get device healthGET/v1/devices/{device}/health](https://docs.cymatics.tech/api/get-device-health)
- [Get sensing configGET/v1/devices/{device}/sensing-config](https://docs.cymatics.tech/api/get-sensing-config)
- [Replace sensing configPUT/v1/devices/{device}/sensing-config](https://docs.cymatics.tech/api/replace-sensing-config)
- [List device observationsGET/v1/devices/{device}/observations](https://docs.cymatics.tech/api/list-device-observations)
- [Stream raw dataGET/v1/devices/{device}/raw-streamBinary](https://docs.cymatics.tech/api/stream-raw-data)

Scenes

- [List scenesGET/v1/scenes](https://docs.cymatics.tech/api/list-scenes)
- [Create scenePOST/v1/scenes](https://docs.cymatics.tech/api/create-scene)
- [Get sceneGET/v1/scenes/{scene}](https://docs.cymatics.tech/api/get-scene)
- [Update scenePATCH/v1/scenes/{scene}](https://docs.cymatics.tech/api/update-scene)
- [Delete sceneDELETE/v1/scenes/{scene}](https://docs.cymatics.tech/api/delete-scene)

Vitals

- [Get vitalsGET/v1/vitals](https://docs.cymatics.tech/api/get-vitals)
- [List vitals historyGET/v1/vitals/history](https://docs.cymatics.tech/api/list-vitals-history)

Presence

- [Get presenceGET/v1/presence](https://docs.cymatics.tech/api/get-presence)

Movement

- [Get movementGET/v1/movement](https://docs.cymatics.tech/api/get-movement)

Stress

- [Get stressGET/v1/stress](https://docs.cymatics.tech/api/get-stress)

Skeleton

- [Get skeletonGET/v1/skeleton](https://docs.cymatics.tech/api/get-skeleton)

Classifications

- [Get classificationsGET/v1/classifications](https://docs.cymatics.tech/api/get-classifications)

Results

- [List resultsGET/v1/results](https://docs.cymatics.tech/api/list-results)

People

- [List person resultsGET/v1/people/{person}/results](https://docs.cymatics.tech/api/list-person-results)
- [Stream personGET/v1/people/{person}/streamSSE](https://docs.cymatics.tech/api/stream-person)

Sleep

- [List sleep sessionsGET/v1/sleep/sessions](https://docs.cymatics.tech/api/list-sleep-sessions)
- [Get sleep summaryGET/v1/sleep/summary](https://docs.cymatics.tech/api/get-sleep-summary)

Activity

- [Get activity summaryGET/v1/activity/summary](https://docs.cymatics.tech/api/get-activity-summary)

Analyses

- [List analysesGET/v1/analyses](https://docs.cymatics.tech/api/list-analyses)
- [Get analysisGET/v1/analyses/{analysis}](https://docs.cymatics.tech/api/get-analysis)

Events

- [List eventsGET/v1/events](https://docs.cymatics.tech/api/list-events)

Webhooks

- [List webhooksGET/v1/webhooks](https://docs.cymatics.tech/api/list-webhooks)
- [Create webhookPOST/v1/webhooks](https://docs.cymatics.tech/api/create-webhook)
- [Get webhookGET/v1/webhooks/{webhook}](https://docs.cymatics.tech/api/get-webhook)
- [Update webhookPATCH/v1/webhooks/{webhook}](https://docs.cymatics.tech/api/update-webhook)
- [Delete webhookDELETE/v1/webhooks/{webhook}](https://docs.cymatics.tech/api/delete-webhook)
- [Test webhookPOST/v1/webhooks/{webhook}/test](https://docs.cymatics.tech/api/test-webhook)
- [List webhook deliveriesGET/v1/webhooks/{webhook}/deliveries](https://docs.cymatics.tech/api/list-webhook-deliveries)

Scenarios

- [List scenariosGET/v1/scenarios](https://docs.cymatics.tech/api/list-scenarios)
- [Create scenario runPOST/v1/scenario-runsTest only](https://docs.cymatics.tech/api/create-scenario-run)

Scenario runs

- [Get scenario runGET/v1/scenario-runs/{run}Test only](https://docs.cymatics.tech/api/get-scenario-run)
- [Control scenario runPOST/v1/scenario-runs/{run}/controlTest only](https://docs.cymatics.tech/api/control-scenario-run)

Raw data

- [Create raw data exportPOST/v1/raw-data/exports](https://docs.cymatics.tech/api/create-raw-data-export)
- [Get raw data exportGET/v1/raw-data/exports/{export}](https://docs.cymatics.tech/api/get-raw-data-export)
- [Download raw data exportGET/v1/raw-data/exports/{export}/contentBinary](https://docs.cymatics.tech/api/download-raw-data-export)

Usage

- [Get usageGET/v1/usage](https://docs.cymatics.tech/api/get-usage)

Request logs

- [List request logsGET/v1/request-logs](https://docs.cymatics.tech/api/list-request-logs)
