Errors
Every error response uses RFC 7807
Problem Details for HTTP APIs, encoded as application/problem+json.
{ "type": "https://docs.tickr.coderise.cloud/errors/validation", "title": "Validation failed", "status": 422, "detail": "Validation failed", "correlationId": "01HXYZ....", "errors": [ { "field": "email", "code": "email_invalid", "message": "..." } ]}-
type— stable URI and the source of truth for the machine-readable error code. The trailing path segment (validationabove) is the code. There is no top-levelcodefield; parse it fromtype. -
title— short, human-readable HTTP reason phrase. -
detail— the error message (often the same as the code for top-level errors; field-level messages are more descriptive). -
correlationId— include this when reporting a problem to the support team. It links to the server logs.This single property uses camelCase, unlike the rest of the API, which uses
snake_caseon the wire. The reason is convention: RFC 7807 Problem Details is traditionally serialised in camelCase, and our Problem Details factory follows that convention rather than overriding it for one outlier field. -
errors[]— present on422 validationresponses. One entry per offending field withfield(JSON path),code(machine-readable — e.g.email_invalid,client_not_found,min_length), andmessage.
Common codes
Section titled “Common codes”The top-level code is the trailing segment of type
(https://docs.tickr.coderise.cloud/errors/<code>). Field-level codes live in
errors[].code on 422 responses.
| HTTP | code | Meaning |
|---|---|---|
| 401 | unauthorized | API key missing, malformed, revoked, or session expired. |
| 403 | forbidden | Authenticated but not authorized for this resource. |
| 403 | forbidden (analyst_read_only) | Analyst role attempted a mutation (carried in detail). |
| 403 | forbidden (not_project_member) | Workspace User without project membership. |
| 403 | forbidden (workspace_mismatch) | Cross-workspace reference rejected. |
| 404 | not_found | Resource does not exist or is not visible to you. |
| 409 | conflict | Server-side state conflict (e.g. concurrent edit). |
| 413 | payload_too_large | Request body exceeds the documented size cap. |
| 422 | validation | Input validation failed; see errors[] for per-field codes. |
| 429 | rate_limited | See Rate limits. |
| 503 | calendar_disabled | The Microsoft Calendar feature is not enabled on this instance. |
| 503 | calendar_token_revoked | The user’s Microsoft refresh token was revoked. Reconnect required. |
| 503 | calendar_provider_unavailable | Transient error reaching Microsoft Graph. Retry later. |
| 429 | calendar_provider_throttled | Microsoft Graph throttled the call. See Retry-After header. |
| 400 | pkce_state_not_found | OAuth state expired or replayed. Restart the connection flow. |
| 400 | microsoft_oauth_error | Microsoft rejected the OAuth exchange (e.g. user cancelled consent). |
Sub-codes shown in parentheses (analyst_read_only, not_project_member,
workspace_mismatch) are not separate top-level codes — they are carried
in the detail field of a forbidden response. Match on the pair when
you need to distinguish them.
This list is not exhaustive — the full catalogue lives in the source code
(ErrorCodes).
New codes are added as new features ship; existing codes are never removed
without a major version bump.
404 is intentional
Section titled “404 is intentional”Tickr returns 404 not_found instead of 403 forbidden when the caller is
authenticated but the resource is in a different workspace, or in a private
project they don’t belong to. This is on purpose — it prevents leaking
existence via probe requests. If you genuinely cannot see a resource you
expected to, double-check the API key’s workspace and your project membership.