Skip to main content
Every Tally API endpoint — except GET /health — requires a valid JWT bearer token issued by your OIDC provider. Tally validates the token against your configured OIDC issuer on every request, derives your identity from the token claims, and checks your role within the target tenant before processing the call.

How authentication works

When you make an API request, Tally:
  1. Reads the Authorization: Bearer <token> header.
  2. Validates the JWT signature against your OIDC issuer’s public keys.
  3. Checks that the token has not expired (exp claim) and that the issuer and audience match the server’s configuration.
  4. Derives your principal ID from the token claims in the format oidc:{issuer_url}#{sub}.
  5. Looks up the principal’s membership and role within the requested tenant.
If any step fails, the request is rejected before it reaches any business logic.

Passing your token

Include your JWT in the Authorization header of every HTTP request:
Authorization: Bearer <your_jwt_token>
Here is a complete curl example using an environment variable for the token:
export TOKEN="eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."

curl -H "Authorization: Bearer $TOKEN" \
  https://api.example.com/v1/tenants/my-org/subjects
You must include this header on every request, including POST, PUT, PATCH, and DELETE calls. Requests without a valid Authorization header receive a 401 Unauthorized response.

Token format

Your JWT must meet these requirements:
  • Signed by your OIDC provider using a supported algorithm (e.g., RS256, ES256).
  • Issuer (iss claim) matches the OIDC issuer configured for your Tally deployment.
  • Audience (aud claim) matches the expected audience configured on the server.
  • Not expired — the exp claim must be in the future at the time of the request.
Tally does not issue tokens itself. Obtain a token from your OIDC provider before each session, and refresh it before it expires. Most OIDC libraries handle silent token refresh automatically.
// Decoded JWT payload (example)
{
  "iss": "https://securetoken.google.com/your-project-id",
  "sub": "abc123uid",
  "aud": "your-project-id",
  "exp": 1716000000,
  "iat": 1715996400
}

Principal IDs

Every authenticated caller is identified in Tally by a principal ID built from the JWT claims:
oidc:{issuer_url}#{sub}
For example, a token with iss = https://securetoken.google.com/my-project and sub = abc123uid produces:
oidc:https://securetoken.google.com/my-project#abc123uid
This principal ID is the stable identifier Tally uses for tenant membership, audit logs, and grant attribution. Before you can make tenant-scoped API calls, a tenant admin must add your principal ID as a member with an appropriate role. See Tenants & Roles for details on roles and how to add members.

Authentication errors

HTTP statusCodeMeaning
401 UnauthorizedunauthorizedThe Authorization header is missing, the token is malformed, the signature is invalid, or the token has expired. Obtain a fresh token and retry.
403 ForbiddenforbiddenThe token is valid, but your principal either is not a member of the requested tenant, or your role does not have sufficient permissions for the requested operation.
Both staging and production Tally environments require authentication on all endpoints except /health. Never send unauthenticated requests to these environments — they will be rejected with 401 Unauthorized.
For local development, Tally servers can be configured to bypass JWT validation entirely. In this mode the server assigns a fixed dev principal ID to all requests, so you can exercise the API without an OIDC provider. This mode is never enabled in staging or production.