Base URL
/v1/ path prefix (e.g. /v1/ingest, /v1/traces).
Authentication
Every request requires a bearer token in theAuthorization header.
| Client | Token | How to get it |
|---|---|---|
| SDKs / server code | API key (tl_...) | Dashboard → Settings → API keys |
| Dashboard / browser | Clerk session JWT | Managed automatically by the frontend — you do not construct these by hand |
Content type
All request and response bodies are JSON unless otherwise noted:Rate limits
Rate limits are per tenant, enforced via a fixed window (1-minute buckets):| Endpoint family | Limit (Starter) | Limit (Pro) |
|---|---|---|
POST /v1/ingest, POST /v1/ingest/batch | 50,000 traces / month | 1,000,000 / month |
POST /v1/feedback, POST /v1/eval | Scales with plan | Scales with plan |
GET /v1/traces, GET /v1/metrics | 60 rps | 600 rps |
X-RateLimit-* headers on every response for the current window state. Enterprise plans have no hard limits.
Error format
Errors always return a JSON body of this shape:error field is a human-readable string. Machine-parseable error codes (where applicable) are returned in dedicated fields specific to each endpoint — for example, POST /v1/eval returns {"code": "eval_quota_exceeded", "error": "..."} when the monthly eval quota is exceeded.
| Status | Meaning |
|---|---|
400 | Malformed request — body doesn’t match schema |
401 | Missing or invalid token |
402 | Plan upgrade required — feature is not available on the tenant’s current plan. Body includes code: "plan_upgrade_required" and required_plan (the lowest plan that unlocks the feature). |
403 | Token valid but not authorised for this resource (e.g. wrong tenant, or archived project — see below) |
404 | Resource not found |
409 | Conflict — e.g. submitting a trace with an ID that already exists, or a constraint violation |
422 | Validation error on a required field |
429 | Rate-limited |
5xx | Server-side issue — safe to retry with exponential backoff |
Machine-readable error codes
Some errors include acode field alongside the human-readable error string. Use the code value for programmatic handling — the error string is subject to change without notice.
| Code | Status | Endpoints | Description |
|---|---|---|---|
error.project.archived | 403 | POST /v1/ingest, POST /v1/ingest/batch, POST /v1/otlp/traces | The project associated with the API key has been archived. Ingest is suspended for the duration. Unarchive the project from Projects settings to resume. |
error.project.cannot_archive_last | 409 | POST /v1/projects/{id}/archive | Returned when attempting to archive the tenant’s last active project. At least one active project must exist at all times. |
plan_upgrade_required | 402 | Various | Feature not available on the current plan. Response also includes required_plan. |
eval_quota_exceeded | 402 | POST /v1/eval | Monthly eval quota exhausted. |
eval_rules_quota_exceeded | 402 | POST /v1/eval-rules | Starter tenant already has 3 eval rules, which is the plan cap. Delete an existing rule or upgrade to Pro to create more. |
request_id — it’s the fastest way for support to look up a failed request.
Versioning
The current API version is v1. Backwards-incompatible changes are shipped as a new version path (/v2/...); v1 is supported for at least 12 months after v2 release.
Additive changes (new fields, new optional parameters) may land on v1 without a version bump — client code should ignore unknown response fields.
SDKs
For most apps, you should not hit these endpoints directly — the SDKs handle batching, retries, and serialisation for you.Python SDK
pip install trulayerTypeScript SDK
npm install @trulayer/sdk