ThrustLab API Stability Policy
Beta-to-v1 graduation
The ThrustLab API is currently published as v1-beta. During this period, responses carry the X-API-Stability: beta header and the API may evolve based on real-world integration feedback.
The API graduates to v1-stable on a deliberate editorial call when all four of the following criteria hold simultaneously:
- No breaking change has shipped in the prior 90 consecutive days.
- The official Python SDK has been stable (no breaking changes, no major rewrites) for 60 days.
- At least one paying external customer has integrated via the API.
- Authentication, billing, and webhook surfaces are all shipped and documented.
At graduation, the X-API-Stability header is removed, deprecation-notice minimums extend from 30 days to 90 days, and the docs-site banner disappears.
The URL path does not change at graduation. /v1/ is permanent for the life of the API.
Breaking vs. non-breaking changes
A change is breaking (and subject to the deprecation-notice policy) if any of the following hold:
- A field is removed from a response.
- A field's type changes.
- A field's semantic meaning changes.
- An endpoint is removed, or its URL or HTTP method changes.
- A request validation rule is tightened (input that previously validated now rejects).
- An enum value is removed.
- The HTTP status code returned for a given outcome changes.
- The error envelope shape for a given
codechanges.
A change is not breaking and may ship at any time:
- A new field is added to a response.
- A new endpoint is added.
- A new optional request parameter is added.
- A new enum value is added to a field documented as extensible. Callers must treat enum fields as open sets. The official SDKs never throw on unknown enum values.
- A new error
codeis added inside an existingtype. - A new webhook event type is added.
Deprecation policy
- During beta: breaking changes are announced at least 30 days before the effective date.
- After graduation: breaking changes are announced at least 90 days before the effective date.
During the deprecation window, the surface being retired serves two response headers:
Deprecation: trueSunset: <RFC 7231 date>(per RFC 8594)
Announcements include migration examples, rationale, and a link to the SDK release that supports the replacement. The changelog page has an RSS feed that integrators are encouraged to subscribe to.
Authentication
All /v1/ endpoints require authentication via Authorization: Bearer <value>. Two credentials are accepted:
- API keys (the public credential). Format
key_<32 chars>. Created and managed from the dashboard only — there is no public endpoint for API-key creation or management. Server-to-server consumers (SDKs, CI, automation) must use these. - User session JWTs (first-party only). Issued by the Django auth stack for the ThrustLab web app. Scoped same-origin. External developers never use this credential.
The two credentials are interchangeable at the protocol level — any /v1/ endpoint accepts either. Third-party integrations must use API keys.
See docs/api/authentication.md for the full authentication guide.
Rate limiting
Every authenticated /v1/ request consumes one token from a credential-scoped token bucket:
- Sustained: 1000 requests/minute per credential.
- Burst: 50 requests.
- Exempt:
/v1/health.
Responses carry X-RateLimit-Limit, X-RateLimit-Remaining, X-RateLimit-Reset (unix timestamp). A 429 response also carries Retry-After: <seconds>.
When a credential exhausts its budget the caller receives:
{
"error": {
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Too many requests. Retry after N seconds.",
"param": null,
"request_id": "req_...",
"doc_url": "https://docs.thrustlab.com/errors/rate_limit_exceeded"
}
}
Two API keys owned by the same user have independent buckets. A user's web-session JWT and their API keys also have independent buckets — the limit is scoped to the credential, not the human.