Errors and responses
Response envelope
Section titled “Response envelope”Every endpoint except the OAuth endpoints wraps its result:
{ "status": "SUCCESS", "data": { … } }{ "status": "FAILED", "message": "Device does not belong to current user" }There is no numeric error code. Branch on the HTTP status and, where you need more detail, on the message text.
The OAuth authorize and token endpoints use RFC 6749 bodies, {"error", "error_description"}, and the user info endpoint returns a plain object. The two request-rate limiters return {"status": "ERROR", "message": …}.
Status codes
Section titled “Status codes”| Status | When |
|---|---|
| 200 | Success. chemistryCard may also set partial: true |
| 201 | OAuth client created |
| 302 | Authorization page redirecting back to your application with a code |
| 400 | Malformed JSON, missing field or out-of-range value; OAuth request errors |
| 401 | Missing or invalid bearer token; OAuth client authentication failed |
| 403 | The user does not own the controller |
| 404 | Unknown path, with a plain-text body. v2 only: GET …/state before any state exists, with a JSON body |
| 409 | v2 only: the controller is not on v2 firmware or has not been heard from recently |
| 429 | Request-rate limit, or the controller is busy or cooling down |
| 500 | Controller did not answer in time, or an unexpected failure |
| 503 | v1 writes and scheduleInfo when the API’s link to the controller network is down; v2 only: v2 not enabled on the server. A cold v1 read with the link down returns 500 MQTT client not connected |
| 504 | v2 only: the controller did not answer a query or action in time |
Headers
Section titled “Headers”Retry-After is sent only on the request-rate limiter 429s, not on controller-busy 429s.
Handling 429
Section titled “Handling 429”Two different things produce 429:
- Request-rate limits on sign-in and site refresh. The body has
"status": "ERROR"and the response carriesRetry-After. Wait that long. - Controller throttling on device endpoints. The body has
"status": "FAILED"and a message containingdevice busy:, sometimes prefixed with the operation, such asfailed to create schedule: device busy: …. When the message containsretry after <duration>, the duration is written like5s,30sor1m0s; wait at least that long. Otherwise wait 5 seconds. See Rate limits and throttling.
Handling 500 on device endpoints
Section titled “Handling 500 on device endpoints”A message ending in timeout waiting for response means the controller did not reply within the endpoint’s timeout. The controller may be offline, busy or on a poor connection. Check online in the site list, wait, and retry with back-off. A single timeout already starts a 5-second cool-down, and repeated timeouts lengthen it; see Rate limits and throttling.

