Skip to main content
All error responses from the Tally API use a consistent JSON error envelope, regardless of which endpoint you called or what went wrong. This means you can write a single error-handling layer in your integration code and handle every failure case uniformly — no need to parse different shapes for different routes.

Error Envelope Format

When a request fails, Tally responds with an HTTP error status code and a JSON body containing a top-level error object:
{
  "error": {
    "code": "validation_error",
    "message": "Request body failed relationship_set validation.",
    "details": [
      {
        "path": "/subject_type",
        "message": "subject_type must be entity or individual."
      }
    ],
    "request_id": "req_abc123"
  }
}
FieldTypeAlways presentDescription
codestringA machine-readable error code. Use this field in your error-handling logic — it is stable across releases.
messagestringA human-readable description of the error. Useful for logs and debugging, but do not rely on its exact wording in code.
detailsarrayAn 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_idstringAn 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.
StatusMeaning
400 Bad RequestValidation error — the request body or query parameters are invalid. Inspect the details array for field-level information.
401 UnauthorizedMissing or invalid JWT token. The token may be absent, expired, or signed by an untrusted issuer.
403 ForbiddenYour token is valid, but you lack the required role or a grant that permits this operation on this tenant.
404 Not FoundThe requested resource (snapshot, tenant, grant, etc.) does not exist or is not visible to your principal.
409 ConflictA 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 GoneYou called a deprecated endpoint. Update your client to use the current v1 tenant-scoped routes.
500 Internal Server ErrorAn 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 a code field that identifies the failure category. Use this value in your application’s error-handling logic.
CodeStatusMeaning
validation_error400One or more fields in the request body or query parameters failed validation. Check the details array for the specific fields and messages.
unauthorized401The JWT bearer token is missing, expired, or otherwise invalid. Refresh your token and retry the request.
forbidden403Your token is valid, but your principal does not have the required role or grant to perform this operation.
not_found404The referenced resource could not be found. Verify the IDs and tenant context in your request.
conflict409The 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.
Your bearer token is either absent from the Authorization header or has passed its expiry time.How to fix:
  1. Confirm the header is formatted correctly: Authorization: Bearer <token> (note the space after Bearer).
  2. Decode your JWT (e.g., at jwt.io) and check the exp claim — if the expiry is in the past, refresh the token.
  3. Verify that your OIDC issuer matches one of the issuers configured for your Tally deployment.
  4. In local development, confirm that AUTH_ENABLED is set appropriately for your environment.
Do not log or commit JWT tokens. If a token is accidentally exposed, revoke it immediately through your identity provider.
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:
  1. Confirm you are using credentials for a principal that is a member of the correct tenant.
  2. Check that your role within the tenant grants access to the endpoint you are calling.
  3. If you are performing a cross-tenant operation, verify that an active grant exists between the source and target tenants.
See Tenants & Roles for a full description of the role hierarchy and permission model.
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_id values using UUIDv4 (e.g., crypto.randomUUID() in Node.js or uuid.uuid4() in Python).
  • Never reuse a snapshot_id from 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.
You attempted to create a grant between two tenants, but an active grant with the same scope already exists.How to fix:
  1. Use the Grants list endpoint to retrieve the currently active grants for the tenant pair.
  2. If the existing grant’s scopes are correct, no action is needed — use the existing grant.
  3. If you need to change the scopes, revoke the existing grant first, then create a new one with the updated scopes.
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.
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 path must begin with /attributes/. Paths that target other top-level fields (e.g., /subject_type, /snapshot_id) are not permitted.
  • Only the following op values are supported: add, remove, replace, and test. The move and copy operations are not supported.
  • Check that each operation object contains all required fields (op, path, and value where applicable).
Valid example:
[
  { "op": "replace", "path": "/attributes/email", "value": "alice@example.com" },
  { "op": "remove",  "path": "/attributes/legacy_id" },
  { "op": "add",     "path": "/attributes/verified", "value": true }
]