Chladni API reference
The Chladni API lets you read your plant structure and maintenance data, keep it in sync with your own systems, create and update work orders, and acknowledge or resolve alerts.
Resources
- Lines, at
/v1/lines, are the production lines of your plant and contain assets. - Assets, at
/v1/assets, are the machines on a line. They carry devices and raise alerts. - Devices, at
/v1/devices, are the sensors mounted on an asset. - Alerts, at
/v1/alerts, are faults detected on an asset. - Work orders, at
/v1/work-orders, link alerts and assets and are assigned to users. - Users, at
/v1/users, are the members of your organization who have signed in at least once. Theiridis the value work orders use for assignees.
Telemetry and health
GET /v1/devices/{id}/telemetry returns the battery readings of a puck: battery_voltage in volts, battery_temperature in degrees Celsius and battery_percent. Points are newest first. end defaults to now and start defaults to 24 hours before end. start may be at most 90 days before end, and both timestamps must be between 2000-01-01 and one day from now. limit caps the total across all types. Filter with type, repeating it for several types.
GET /v1/devices/{id}/health returns the degradation trend the platform computes from vibration data, oldest first. Each point has a zone (stable, degrading or critical), a trafficLight (the colour the web app shows), a trendDirection and a severityIndex, which is null while the zone is stable. A status of no-data means the device has no assessments in the window.
Devices of other types return empty results.
Where the platform runs without real device data, both responses carry X-Mock-Data: true and the values are generated.
Authentication
API keys are issued per organization. Contact Chladni to get one.
Send the key as a bearer token on every request:
Authorization: Bearer <your API key>
A key belongs to one organization and carries a set of permissions, such as line:read. Each endpoint lists the permission it needs. A request with a key that lacks it returns 403.
Revoking a key can take up to 60 seconds to take effect.
Pagination
List endpoints return a page of items and a cursor:
{ "data": [ ... ], "nextCursor": "eyJ2IjoxLC..." }
Pass nextCursor as the cursor parameter to get the next page. nextCursor is null on the last page. limit sets the page size, 50 by default and 200 at most.
Treat cursors as opaque strings. A cursor is only valid with the sort it was issued for.
Sorting and filtering
sort accepts createdAt, -createdAt, updatedAt and -updatedAt. A leading - sorts newest first. The default is -createdAt.
createdAfter, createdBefore, updatedAfter and updatedBefore filter by time. After is inclusive and Before is exclusive. Timestamps are ISO 8601 with a time and an offset, for example 2026-01-31T08:00:00Z. URL-encode the value: a + in an offset must be sent as %2B.
Unknown query parameters are rejected with 400, so a misspelled filter never returns unfiltered data.
Keeping data in sync
To pull only what changed since your last run, sort by updatedAt and filter with updatedAfter:
GET /v1/lines?sort=updatedAt&updatedAfter=2026-01-31T08:00:00Z
Follow nextCursor to the end, then store the largest updatedAt you saw and use it as updatedAfter next time. Subtract a small overlap, for example one minute, from the stored value, because a change can be committed slightly after its timestamp. An item changed while you are paging can appear twice, so make your import idempotent on id.
Writing data
Write requests send a JSON body with Content-Type: application/json.
Unknown fields are rejected with 400, so a misspelled field never goes unnoticed.
Timestamps are ISO 8601 with an offset, for example 2026-01-31T08:00:00+01:00.
POST answers 201 with the created resource.
PATCH answers 200 with the updated resource.
Both return the same shape as the matching GET.
assigneeIds must be members of your organization; list them with GET /users.
assetIds and alertIds must belong to your organization.
A reference that does not qualify answers 400, never 404, which is reserved for the resource in the path.
Arrays in a PATCH replace the stored list.
Send "dueDate": null to clear a due date.
Alerts are linked to a work order only when it is created.
A work order that has been synced to SAP cannot be edited and answers 409.
Alerts only move forward, so an invalid status change answers 409.
Idempotency
POST /work-orders requires an Idempotency-Key header, so a retry after a timeout cannot create a second work order.
The key is 1 to 255 printable ASCII characters.
Generate a new one for every create, for example a UUID.
An empty header counts as missing.
A missing or malformed key answers 400.
Retry with the same key and the same body to get the first response again, marked with Idempotency-Replayed: true.
Keys are remembered for 24 hours.
While the first attempt is still running, a retry answers 409.
The same key with a different body answers 422.
If a create fails with a 4xx status, the key is released, so you can retry with the same key and a corrected body.
A request that is still running is tracked for 30 seconds. If a create takes longer than that, a retry is treated as new and can create a duplicate.
If the service fails between writing the work order and storing the response, a retry can also create a duplicate. If that matters to you, look for the work order before you create it again.
Errors
Errors use standard HTTP status codes and one body shape:
{
"error": {
"code": "invalid_request",
"message": "Request validation failed",
"details": [{ "path": "limit", "message": "Too big: expected number to be <=200" }],
"requestId": "2f1c9a52-6d0b-4a3e-9d57-0a4c3f6d1b11"
}
}
| Status | Code | Meaning |
|---|---|---|
| 400 | invalid_request |
A parameter, body field or header is missing or invalid. details names the field when the body or query is at fault. |
| 401 | unauthorized |
The API key is missing, invalid or revoked. |
| 403 | forbidden |
The API key lacks the permission this endpoint needs. |
| 404 | not_found |
The resource or route does not exist. |
| 409 | conflict |
An invalid alert status change, a work order synced to SAP, or a create with this Idempotency-Key still in progress. |
| 422 | idempotency_key_reused |
The Idempotency-Key was already used with a different request body. |
| 429 | rate_limited |
Too many requests. Wait for Retry-After seconds. |
| 500 | internal_error |
Something went wrong on our side. |
| 503 | service_unavailable |
Key validation or idempotency storage is temporarily unavailable (retry shortly), or telemetry is not available in this environment. |
Every response carries an X-Request-Id header. Include it when you contact support.
Rate limits
Each organization may make 600 requests per minute by default across all its keys; the headers below carry the live value. Every authenticated response carries the budget:
| Header | Meaning |
|---|---|
RateLimit-Limit |
Requests allowed per minute |
RateLimit-Remaining |
Requests left in the current minute |
RateLimit-Reset |
Seconds until the budget resets |
When the budget is spent the API answers 429 with code rate_limited and a Retry-After header saying how many seconds to wait. Back off until then; retrying earlier only returns another 429.
A separate, more generous limit applies per client address before authentication. It protects the API from floods and is not part of the budget above.
Versioning
The version is part of the path. Within v1 we only add: new endpoints, new optional parameters and new response fields. Ignore fields you do not recognise. New error codes and new values of other enumerated fields may also be added, so handle an unknown code by its HTTP status.
Lines
Production lines. Assets belong to a line.
GET /v1/linesList linesGET /v1/lines/{id}Get a line
Assets
Machines on a line that sensors monitor.
GET /v1/assetsList assetsGET /v1/assets/{id}Get an asset
Devices
Sensors mounted on assets.
GET /v1/devicesList devicesGET /v1/devices/{id}Get a deviceGET /v1/devices/{id}/telemetryGet device telemetryGET /v1/devices/{id}/healthGet device health
Alerts
Detected faults on assets.
GET /v1/alertsList alertsGET /v1/alerts/{id}Get an alertPATCH /v1/alerts/{id}Update an alert status
Work orders
Maintenance work, linked to alerts and assets.
GET /v1/work-ordersList work ordersPOST /v1/work-ordersCreate a work orderGET /v1/work-orders/{id}Get a work orderPATCH /v1/work-orders/{id}Update a work order
Users
Members of your organization.
GET /v1/usersList users