CI trust rules

The repositories whose GitHub Actions or GitLab CI jobs may post annotations with their OIDC token, without a stored secret.

Open in Claude

A trust rule lets a repository's CI jobs post annotations with the OIDC token that their provider gives each job, in place of an ingest key. To set one up end to end, follow Post from CI without a secret.

Endpoints/api/organizations/{org}/ci-trust-rules
POST/CreateGET/ListDELETE/{public_id}Delete

Anyone in the organization may list the rules. Owners and admins create and delete them, with a personal access token, or with an OAuth sign-in that has organization:manage.

Rules work with github.com and gitlab.com. GitHub Enterprise Server and self-managed GitLab aren't supported yet.

The trust rule object

Attributesapplication/json
public_idstringserver

ctr_…

providerenumrequired

One of github, gitlab

repositorystringrequired

owner/repo on GitHub, or the project's path on GitLab, such as acme/platform/checkout.

repository_idstring, nullableoptional

The provider's id for the repository. Left out, the first job that the rule lets in sets it. From then on the rule matches the id, not the name, so a renamed or recreated repository doesn't inherit the trust.

Rules: digits only.

refstring, nullableoptional

Only jobs on this ref, such as refs/heads/main or refs/tags/v1.42.0. Null for any ref.

Rules: a full ref, starting refs/heads/ or refs/tags/.

environmentstring, nullableoptional

Only jobs in this deployment environment, such as production. Null for any environment, or none.

Rules: not blank.

created_byobject, nullableserver

The person who created it.

created_attimestampserver

When it was created.

Which jobs a rule lets in

A job's token gets in when it is valid and a rule matches it:

  1. The token's signature checks out against the provider's published keys.
  2. It was issued by the provider, it is addressed to telemetrymachine.com, and it hasn't expired. Otherwise the call gets 401.
  3. A rule of the organization in the URL names the job's repository, by id once the rule has one, and the job's ref and environment, where the rule names them. Otherwise the call gets 403.

A job must match everything that a rule names. To let in the jobs on main and also the jobs in production, create two rules. A GitLab branch such as main is matched as refs/heads/main.

A job that gets in may create annotations and retry its own keys. It can't update or delete annotations.

Create a trust rule

POST/api/organizations/{org}/ci-trust-rules
Auth
An owner or admin

Takes the fields of the trust rule object that are marked required or optional.

POST /ci-trust-rules
curl -X POST https://telemetrymachine.com/api/organizations/<your-org>/ci-trust-rules \
  -H "Authorization: Bearer $TM_TOKEN" -H 'Content-Type: application/json' \
  -d '{ "provider": "github", "repository": "acme/checkout", "ref": "refs/heads/main" }'
200Response
{
  "status": 200,
  "data": {
    "public_id": "ctr_01m5z3h7q2w8e4r6t1y9u0i5op",
    "provider": "github",
    "repository": "acme/checkout",
    "repository_id": null,
    "ref": "refs/heads/main",
    "environment": null,
    "created_by": { "display_name": "Maya", "email": "[email protected]" },
    "created_at": "2026-10-26T16:20:00.000Z"
  }
}

List trust rules

GET/api/organizations/{org}/ci-trust-rules
Auth
Any member
Returns
rules, oldest first

Delete a trust rule

DELETE/api/organizations/{org}/ci-trust-rules/{public_id}
Auth
An owner or admin
Returns
{ "deleted": true }

Jobs that no other rule lets in can't post from then on. The annotations that they posted stay.

Errors

StatusWhenWhat to do
400A field breaks its rules, such as a ref that isn't a full refFix the field that the error names.
403You aren't an owner or admin, or an OAuth sign-in lacks organization:manageAsk an owner or admin, or sign in with the scope.
404The organization has no rule with this public_idCheck the id with List.