Authentication

The API uses OAuth2 client_credentials. You exchange a client ID and secret for a bearer token, then send that token on every request.

The client_credentials flow

client_credentials is a server-to-server flow: your application authenticates as itself, with no end user involved. Request a token from the environment's token endpoint:

curl -X POST https://auth.uat.trailblazertech.com/oauth2/token \
  -u "$CLIENT_ID:$CLIENT_SECRET" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -d "grant_type=client_credentials" \
  -d "scope=api.uat.trailblazertech.com/access"

The response includes an access_token and expires_in (seconds). Send the token on each API request:

Authorization: Bearer <access_token>

Tokens are short-lived. Cache the token and reuse it until shortly before expires_in elapses, then request a new one — don't fetch a fresh token per request.

Scopes: two layers

Access is checked at two levels, and both must pass.

  1. The access scope — your token must carry the scope for the environment you're calling. This is checked at the edge before your request reaches any endpoint.

    EnvironmentRequired token scope
    UATapi.uat.trailblazertech.com/access
    Productionapi.trailblazertech.com/access
  2. Per-operation permissions — your client is provisioned with a set of fine-grained permissions that govern which operations it may call. A call to an operation you aren't provisioned for returns 403 forbidden.

    PermissionGrants
    health/readGET /v1/health
    policies/readGET /v1/policies, GET /v1/policies/{id}
    submissions/readGET /v1/submissions/{id} and its attachment reads
    submissions/writePOST /v1/submissions and its attachment mutations
    jobs/readGET /v1/jobs/{id}

The API reference (from the OpenAPI spec) shows the access scope only. The per-operation permissions above are enforced by the API but aren't listed per-operation in the spec — this guide is the reference for them. If you receive a 403 on an operation you expected to reach, your client is missing that permission; contact Trailblazer to have it added.

Acting on behalf of a principal

By default, your client acts as itself — the partner account. If your integration serves multiple downstream identities (for example, agencies or agents that Trailblazer has registered for you as principals), you can attribute a request to one of them with an optional header:

x-principal-id: <registered-principal-id>

Only principals that Trailblazer has registered for your partner are accepted; you cannot assert arbitrary identities. GET /v1/health reflects the resolved principal back to you as principalId, which is handy for confirming the header was accepted.

What a rejected request looks like

Authentication and authorization failures use the standard error envelope: