Error Envelope Format
When a request fails, Tally responds with an HTTP error status code and a JSON body containing a top-levelerror object:
| Field | Type | Always present | Description |
|---|---|---|---|
code | string | ✅ | A machine-readable error code. Use this field in your error-handling logic — it is stable across releases. |
message | string | ✅ | A human-readable description of the error. Useful for logs and debugging, but do not rely on its exact wording in code. |
details | array | ❌ | An optional array of field-level validation errors. Each entry contains a path (a JSON Pointer such as /subject_type) and a message describing what is wrong with that field. Present on validation_error responses. |
request_id | string | ❌ | An optional opaque identifier for the specific request. Include this value when contacting Tally support — it allows the team to locate the exact request in server logs. |
The
details array may be empty even on validation_error responses if the
error cannot be attributed to a specific field. Always check code first,
then inspect details for field-level guidance.HTTP Status Codes
Tally uses standard HTTP status codes. The table below describes every status code the API can return and what it means for your request.| Status | Meaning |
|---|---|
400 Bad Request | Validation error — the request body or query parameters are invalid. Inspect the details array for field-level information. |
401 Unauthorized | Missing or invalid JWT token. The token may be absent, expired, or signed by an untrusted issuer. |
403 Forbidden | Your token is valid, but you lack the required role or a grant that permits this operation on this tenant. |
404 Not Found | The requested resource (snapshot, tenant, grant, etc.) does not exist or is not visible to your principal. |
409 Conflict | A duplicate or conflicting resource was detected — for example, a snapshot_id that already exists, or an active grant that conflicts with the one you are trying to create. |
410 Gone | You called a deprecated endpoint. Update your client to use the current v1 tenant-scoped routes. |
500 Internal Server Error | An unexpected error occurred on the server. Retry the request once; if the problem persists, contact Tally support with the request_id. |
Error Codes
Every error response includes acode field that identifies the failure category. Use this value in your application’s error-handling logic.
| Code | Status | Meaning |
|---|---|---|
validation_error | 400 | One or more fields in the request body or query parameters failed validation. Check the details array for the specific fields and messages. |
unauthorized | 401 | The JWT bearer token is missing, expired, or otherwise invalid. Refresh your token and retry the request. |
forbidden | 403 | Your token is valid, but your principal does not have the required role or grant to perform this operation. |
not_found | 404 | The referenced resource could not be found. Verify the IDs and tenant context in your request. |
conflict | 409 | The operation would create a duplicate or conflicting resource. Resolve the conflict before retrying. |
Common Errors
The accordion below walks through the most frequently encountered errors and the steps you should take to resolve them.401 Unauthorized — token missing or expired
401 Unauthorized — token missing or expired
403 Forbidden — insufficient role or grant
403 Forbidden — insufficient role or grant
Your token is valid, but your principal does not have the required permissions for this operation. This happens when you are not a member of the target tenant, when your role within the tenant does not grant access to the resource, or when the cross-tenant grant needed to read a subject’s data has not been issued.How to fix:
- Confirm you are using credentials for a principal that is a member of the correct tenant.
- Check that your role within the tenant grants access to the endpoint you are calling.
- If you are performing a cross-tenant operation, verify that an active grant exists between the source and target tenants.
409 Conflict — snapshot_id already exists
409 Conflict — snapshot_id already exists
You submitted a snapshot whose
snapshot_id matches one that is already stored in Tally. Snapshot IDs are globally unique across all tenants and subject types.How to fix:- Always generate
snapshot_idvalues using UUIDv4 (e.g.,crypto.randomUUID()in Node.js oruuid.uuid4()in Python). - Never reuse a
snapshot_idfrom a previous ingestion, even if you believe the earlier request failed — the snapshot may have been committed before the failure was surfaced to your client. - If you need to update attributes on an existing snapshot, use the State Updates endpoint rather than re-submitting a new snapshot with the same ID.
409 Conflict — active grant already exists
409 Conflict — active grant already exists
You attempted to create a grant between two tenants, but an active grant with the same scope already exists.How to fix:
- Use the Grants list endpoint to retrieve the currently active grants for the tenant pair.
- If the existing grant’s scopes are correct, no action is needed — use the existing grant.
- If you need to change the scopes, revoke the existing grant first, then create a new one with the updated scopes.
410 Gone — deprecated legacy route
410 Gone — deprecated legacy route
You are calling a legacy endpoint that has been removed from the API. Tally returns
410 Gone rather than 404 Not Found to make it clear that the route existed previously and has been intentionally retired.How to fix:- Update your client to call the current tenant-scoped routes under
/v1/tenants/:tenant_id/.... - Review the API Overview for migration guidance if you are upgrading from an older version of the API.
- If you are unsure which endpoint to use, refer to the Endpoints Overview on this page.
400 validation_error on /patch — invalid JSON Patch operation
400 validation_error on /patch — invalid JSON Patch operation
Your state-update request contains a JSON Patch document that failed validation. Common mistakes include targeting a path outside the allowed namespace or using an unsupported operation type.How to fix:
- Every patch
pathmust begin with/attributes/. Paths that target other top-level fields (e.g.,/subject_type,/snapshot_id) are not permitted. - Only the following
opvalues are supported:add,remove,replace, andtest. Themoveandcopyoperations are not supported. - Check that each operation object contains all required fields (
op,path, andvaluewhere applicable).