API Reference
Rate Limits

Rate Limits

The Public API applies rate limits to protect the shared ingest pipeline and ensure predictable tail latency across workspaces.


Quotas

Rate limits apply per token, per endpoint class. Specific published limits are not enumerated here — effective thresholds vary by plan and workspace. When a request is actually rate-limited, the API returns 429 with Retry-After as described below. Contact support@experiture.com for your workspace's current limits or to request an increase.

Limits are independent per endpoint class — exhausting one class (e.g. batch writes) does not block another (e.g. single writes).


Headers

When a request is rate-limited, the 429 response includes:

HeaderMeaning
Retry-AfterSeconds to wait before retrying.

Example:

HTTP/1.1 429 Too Many Requests
Retry-After: 2

Handling 429 Responses

When the limiter engages, the API returns 429 Too Many Requests:

{
  "success": false,
  "error": {
    "code": "CDP_ETL.RATE.LIMITED",
    "message": "Rate limit exceeded. Retry after 2s."
  }
}

The response includes Retry-After. Respect it.

Recommended backoff

Exponential with full jitter, seeded by Retry-After:

import random
import time
 
def call_with_retry(fn, max_attempts=6):
    for attempt in range(max_attempts):
        resp = fn()
        if resp.status_code != 429:
            return resp
        retry_after = int(resp.headers.get("Retry-After", 2 ** attempt))
        sleep_s = random.uniform(0, retry_after)
        time.sleep(sleep_s)
    raise RuntimeError("Exceeded retry budget")

Do not retry 429s with a fixed interval — synchronised clients amplify congestion. Always add jitter.


Avoiding the Limit

Prefer batch endpoints for bulk writes

A single batch of 10,000 records counts as one request against the batch quota. The equivalent 10,000 single writes would exhaust the per-second single-write quota many times over. See Records API.

Use import jobs for one-off loads

For backfills > 100k records, prefer Import Jobs over repeated batch calls — they stream from object storage and operate under a separate concurrency model rather than per-second request quotas.

Coalesce profile updates

If your system emits many small updates for the same profile (e.g. every page view), buffer and debounce client-side so you emit one upsert per second per profile rather than one per event.


Raising Limits

Production workloads occasionally need higher quotas. Contact support@experiture.com with:

  • Token prefix (first 12 chars, never the full token)
  • Target QPS and endpoint class
  • Expected duration (e.g. one-time backfill vs. sustained)

Higher quotas are available — contact support@experiture.com to discuss your workspace's needs.


See Also