Skip to Content

API conventions

  • JSON only. Timestamps are ISO-8601 UTC unless a field documents epoch milliseconds.

  • Errors are RFC 7807 problem details (application/problem+json):

    { "type": "about:blank", "title": "Not Found", "status": 404, "requestId": "3f9c…" }
  • 401 vs 403. 401 = no or invalid credential; 403 = valid credential but the route’s gate (admin/tenant/user) or a required scope is not satisfied.

  • Request IDs. Every response carries X-Request-Id; send your own to correlate logs.

  • Idempotency. Send Idempotency-Key (≤ 200 characters) on any POST/PATCH/DELETE; the first response is stored for 24 hours and a replay with the same body returns it with Idempotent-Replayed: true. The same key with a different body is a 422.

    A stored response belongs to the credential that sent it, not to the tenant: another API key in the same tenant presenting the same key gets a normal, freshly executed response, so keys need only be unique per credential and reusing one across your own keys is harmless. Session cookies ignore the header entirely.

    Routes that mint a one-time secret are exempt: POST /v1/tenants, POST /v1/keys, either session-tokens route, POST /v1/webhooks, …/rotate-secret and …/reports/send-now. A repeat there mints a second credential rather than re-serving the first one’s plaintext, so retry those deliberately and revoke what you do not keep.

  • Pagination is cursor-based: ?cursor=&limit= (limit ≤ 500), nextCursor in the response.

  • Rate limits. 600 requests per minute per credential on /v1, 60 per minute per client address on the unauthenticated routes (session exchange, report and verification links), and 60 per minute per tenant on session-token mints, verifications and run-now. Every counted response carries RateLimit-Limit, RateLimit-Remaining and RateLimit-Reset; 429 adds Retry-After. Manual runs also count against the tenant’s maxRunsPerHour (429 beyond it).

  • Record ceilings. Each tenant may hold at most 500 flows, 5000 sources, 5000 contacts, 500 contact lists and 1000 users; creating past a ceiling is a 409 naming the setting to raise. Ask your Growth Engine operator to lift one for your account; the limits exist because the hourly report dispatcher, the targets sync and run fan-out all scale with these counts.

  • Size limits. Request bodies over 1 MB (2 MB on adapter and tile routes) are 413; free-form JSON fields (settings, tile params, source metadata) are capped at 64 KB serialized and notes at 20 000 characters (422).

  • Versioning. Breaking changes bump the path version (/v2); additive changes do not. Deprecations are announced with Sunset headers at least 6 months ahead.

OpenAPI

GET /openapi.json on any Engine returns the machine-readable contract for that build.