API keys (recommended for integrations)
An API key is an opaque bearer token of the formgtm_live_ plus 40 characters. There is no OAuth handshake: you paste it into your runtime and send it as the bearer token on every call.
- The secret is shown once.
POST /api/api-keysreturns the full token inplaintext_tokenin that one response. Afterwards the API returns onlytoken_prefixandtoken_last4for display. The server stores a SHA-256 hash, not the key. - Rotation replaces the secret.
POST /api/api-keys/{sid}/rotatemints a newgtm_live_secret for the same key record and invalidates the old one. Rotate on any suspicion of a leak, or on a schedule. - Keys expire. Default expiry is 3 years from creation; pass
expires_at: nullon create for a perpetual key. - Keys carry permissions. A key created by another key can only hold a subset of the parent’s permissions. Downscoping is allowed, escalation is a
forbiddenerror. - Keys are team-scoped. A key belongs to the team it was created in and acts on that team’s data.
last_used_at shows stale keys worth revoking), check expires_at for keys about to lapse, and revoke what you no longer use.
Session JWTs
Signing in to app.gtm-api.com issues a short-lived JWT. It goes in the sameAuthorization: Bearer header. This is what the app itself uses; for server-to-server integrations prefer an API key, which does not expire mid-job.
The Team-SID header
A token is normally already scoped to one team, and that scope is authoritative. The optionalTeam-SID header exists for tokens that do not carry a team: it selects which of your teams the call acts on.
Team-SID is ignored. With an API key you can leave it out entirely.
Auth failures
Both arrive as the standard error envelope, so they are machine-readable like every other failure.
Handling the secret
Treatgtm_live_ tokens like passwords: keep them in a secret manager or environment variable, never in client-side code or a repository, and never in logs. If a key leaks, rotate it; the old secret stops working immediately.