Errors & conventions

Predictable responses

The API uses one success envelope, one error envelope, stable status codes, cursor pagination, and explicit formats for dates and money.

Success and error envelopes

Single resources are returned in data. Lists also containmeta. Every error uses an English machine-readable code and a human-readable message.

Success
{
  "data": {
    "id": "project_…",
    "name": "Mehrfamilienhaus Köln"
  }
}
Error
{
  "error": {
    "code": "invalid_body",
    "message": "startDate must use YYYY-MM-DD format.",
    "details": {}
  }
}

HTTP status and error codes

StatusCommon codesWhat to do
400invalid_body, invalid_json, invalid_filter, organization_requiredCorrect the request before retrying.
401unauthorizedCreate or replace the bearer key.
403insufficient_scope, plan_feature_required, forbiddenCheck key scope, plan and organization.
404not_foundThe route or resource does not exist.
405method_not_allowedUse a method listed in the API reference.
409conflict, webhook_limit_reached, endpoint_disabledResolve the current resource state.
429rate_limitedWait for the Retry-After duration.
500internal_errorRetry with backoff and keep the request context.
An unknown path returns 404. A known path called with an unsupported method returns 405. Keep these cases separate in logs and monitoring.

Cursor pagination

Lists are sorted newest first. Set limit between 1 and 100; the default is 50. Pass the returned cursor to the next request untilisDone is true. A list without matches returns HTTP 200 and an empty array.

List metadata
{
  "data": [],
  "meta": {
    "cursor": "cursor_for_next_page",
    "isDone": false,
    "limit": 50
  }
}

Dates, timestamps and money

  • Resource timestamps use ISO 8601 in UTC, for example2026-08-09T12:30:00.000Z. A webhook envelope'screatedAt is a Unix timestamp in milliseconds.
  • Date-only fields use YYYY-MM-DD.
  • Monetary amounts are integer cents plus currency: "EUR".
  • Public enums and error messages are English.

Idempotency and rate limits

Send a unique Idempotency-Key with POST and PUT requests. Reusing the same key replays the stored response and addsIdempotency-Replayed: true.

Rate limits apply per key and per organization. A 429 response includesRetry-After in seconds. Each key has a token bucket of 60 requests per minute with a burst capacity of 20; an organization also has a shared ceiling of 3,000 requests per UTC day. Wait at least the requested duration and add jitter before retrying.