Skip to main content

Errors and limits

The failure envelope​

{
"success": false,
"error": "Org does not belong to this account",
"code": "forbidden"
}

The HTTP status says the kind of failure; code says exactly which, and is stable. Match on code, not on the error text, which is for people and may change.

Codes​

StatuscodeMeaning
400bad_requestThe body is not a JSON object, is malformed, or is not application/json
400invalid_limitlimit is not an integer from 1 to 100
400invalid_cursorcursor is not one this API gave you
400invalid_gross_areagrossArea is missing, not a number, or below 0
400invalid_create_connectorcreateConnector is not a boolean
400invalid_building_idbuildingId does not match ^[A-Za-z0-9_.-]{1,128}$
400invalid_itemsA batch's items is not an array of 1 to 1,000
400invalid_itemA batch item is malformed, or names an orgId
400duplicate_itemA batch repeats a buildingId
401missing_tokenNo Authorization: Bearer header
401invalid_tokenThe token is not valid
401token_expiredThe token has expired
403forbiddenNot a credential for this org and account, or not an org service-account credential
404not_foundNo such route or batch
413bad_requestThe JSON body is over 1,000,000 bytes
429rate_limitedToo many requests; see Retry-After
500internalAn unexpected failure on our side
502jobs_unavailableA batch or update could not be started and was cancelled; some updates may already have been applied
503upstream_unavailableA check this API depends on is unavailable; retry
503batches_unavailableBatches and updates are not available right now
503jobs_unavailableA batch's jobs cannot be read right now; retry
503results_unavailableA batch's per-item results cannot be read right now; retry

The same code can carry a different status, as jobs_unavailable (502 when starting a batch, 503 when reading one) and bad_request (400, or 413 for a body that is too large): read the status and the code together.

The codes an item can carry (building_not_found, connector_required, missing_postal_identity, upstream_error, job_failed; a single update is a batch of one) are not HTTP errors. They are listed in Batches.

Limits​

LimitValue
Requests, every route, per account120 per minute
Batch or update start requests, per account10 per minute
JSON body1,000,000 bytes (413 bad_request beyond)
Body refused by the server1 MiB (1,048,576 bytes), see below
Buildings in one batch1 to 1,000, each buildingId once
Buildings per page (limit)1 to 100, 50 when absent
buildingId^[A-Za-z0-9_.-]{1,128}$
Per-item batch results kept3 days

A body of more than 1 MiB (1,048,576 bytes) is refused earlier, by the server, with 413 in a different shape: { "code": "PAYLOAD_TOO_LARGE", "message": "Request body exceeds 1048576 bytes" }. Keep bodies under 1,000,000 bytes to get the envelope above.

Rate limits​

Requests are counted per account in one-minute windows, whichever credential of the account sends them:

  • every route allows about 120 requests per minute (a request that is refused with 401 is not counted);
  • batch and single-update start requests (POST .../gross-area:batch and PUT .../gross-area) allow about 10 per minute together, including one that is then refused with 400. A start request also counts toward the 120.

Past a limit the answer is 429 rate_limited with a Retry-After header: the seconds until the limit resets. Wait that long before retrying. The limits are applied by each server instance, so the effective limit across instances can be a small multiple of these numbers.

Retrying​

  • 429, 502 and 503 are worth retrying after a pause: for 429 wait the Retry-After seconds, for 502 and 503 back off (for example 1, 2, 4, 8 seconds). For 502 jobs_unavailable on a batch, first check the buildings: some updates may already have been applied.
  • 500 internal is unexpected; one retry after a pause is reasonable, and a persistent 500 is a fault on our side, not in your request.
  • 401 token_expired: request a new token (see Authentication) and repeat the call.
  • PUT .../gross-area is idempotent: repeating it with the same value is harmless (each call is a new job).
  • Starting a batch is not idempotent: a second POST starts a second batch. If you did not get an answer, check the buildings before starting it again.
  • Other 4xx answers will not change on a retry; fix the request.