Two ways in: OAuth 2.1 for a person in an interactive client, API keys for automation. Both resolve to the same identity, the same scopes and the same audit trail.
When you add the server to an MCP client, the client discovers the authorization setup by itself and opens a browser. You sign in and approve the scopes. There is no manual registration and no client id to paste.
For anyone implementing a client, the server follows the current MCP authorization specification:
| Protected resource metadata | /.well-known/oauth-protected-resource/mcp (RFC 9728). An unauthenticated request answers 401 with a WWW-Authenticate header naming it. The path carries the resource path as a suffix, per the specification, so it is not the bare well-known URL. |
| Authorization server metadata | Published per RFC 8414, at the location the resource metadata names. |
| Client registration | Dynamic Client Registration (RFC 7591) and Client ID Metadata Documents are both supported, and the authorization server metadata says so. Nothing needs registering in advance. Clients are public, with no secret, and redirect URIs must be https, or http on localhost, and match exactly, apart from the port of a localhost redirect, which may differ (RFC 8252). |
| PKCE | Required, S256. Authorization code flow only, and no implicit grant. |
| Resource indicators | Clients must send resource per RFC 8707: https://mcp.glitchads.ai/mcp for the MCP server, or https://api.glitchads.ai/v1 for the REST API. A request without it is refused. Tokens are audience bound: one minted for the MCP server is refused by the REST API, and the other way round. |
| Tokens | Access tokens live at most an hour, and refresh tokens rotate on use. A connection that goes 60 days without a refresh expires and has to be connected again. Bearer tokens go in the Authorization header on every request, never in a query string. |
| Token passthrough | Forbidden. Glitch never accepts a token issued for another service, and never forwards yours anywhere, Google Ads included. |
| Revocation | Token revocation per RFC 7009, at the revocation_endpoint the authorization server metadata names. Revoking a token ends the session it belongs to, and the connection itself once no session is left standing, so an app tidying up a credential it has replaced does not disconnect the one that replaced it. An access token from an ended session stops working at once rather than lasting out its hour. Ending the whole connection whatever is live is what revoking it in Glitch does, under Account, API Keys, Connected apps. |
If an old refresh token is presented again, which is what replaying a stolen one looks like, the whole family is revoked and the client has to be authorised afresh. The one allowance is a retry: for 60 seconds after a refresh, the token it replaced is still accepted, so a client whose response was lost in transit is not disconnected for sending it again.
Consent asks which scopes to grant, and unchecking a scope narrows the grant to what stays checked. A client that names no scopes is offered all ten: uncheck any that your roles do not allow, or approval fails. The connection then covers every organization the account belongs to, capped in each by the role held there, and every request names the organization it acts in with membership checked live. For Glitch adops staff it also covers every client organization assigned to their team, read only, however many scopes were granted. An agency managing several client organizations holds one connection and names the client per request, or uses one API key per client where hard isolation per credential is wanted.
To change scopes, reconnect without removing the server. Reconnecting replaces the granted scopes with the ones approved on that screen, and the change takes effect from the client's next token refresh.
Keys are created in the platform under Account, API Keys. Any member of the organization can create one; the role ceiling below limits what a key can carry. Rotation and revocation belong to the key's creator or an Owner. The same key works on both surfaces.
curl https://api.glitchads.ai/v1/organizations/_/campaigns \
-H "Authorization: Bearer glads_live_7Fq2xKpR4mNvB8sD3hJwL6tYzC1aEg9Qk4Xn"
| Format | Every key starts glads_live_. The glads_test_ prefix is reserved for sandbox keys, which are not available yet. A key is shown once at creation; afterwards only the prefix and the last four characters are displayed. |
| Scope | Chosen at creation and never exceeding the role of the person creating it. A key is bound to one organization. If that person's role later drops below what the key carries, the key stops working and answers unauthorized: create a new one within the new role. |
| Expiry | Every key expires one year after it is created. The person who created it is emailed 30 days and 7 days before. |
| Rotation | Issues a replacement with the same name and scopes, and keeps the old key working for up to 48 hours, less if it expires sooner, which is the window to deploy the new one. The replacement belongs to the person who rotated it and expires a year later. |
| Revocation | Immediate, and not reversible. A revoked key answers unauthorized on its next request. |
| Storage | Only a SHA-256 hash is kept, so a key cannot be read back. Keep yours in a secret manager or an environment variable, and never commit one. |
glads_live_ 7Fq2xKpR4mNvB8sD3hJwL6tYzC1aEg 9Qk4Xn
^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^
environment 30 random characters checksum
The last six characters are a checksum of the thirty before them, so anything holding a string can tell whether it is a well formed Glitch key without sending a request. That is what lets an automated scanner recognise one in a commit. The sample on this page deliberately fails that check, so nothing ever mistakes it for a live credential.
Every credential carries an explicit list of scopes, and every endpoint requires one. A request outside the granted list answers insufficient_scope and changes nothing.
| Scope | Grants | Tools |
|---|---|---|
| Scopeorganizations:read | GrantsYour organizations with your role in each, the account overview and the business profile. | Toolsglitch_list_organizations, glitch_get_account_overview, glitch_get_business_profile |
| Scopecampaigns:read | GrantsCampaign structures, their keywords, and running a detector. | Toolsglitch_list_campaigns, glitch_get_campaign, glitch_list_keywords, glitch_run_detector |
| Scopeperformance:read | GrantsMetrics and search terms. | Toolsglitch_get_performance, glitch_get_search_terms |
| Scopereports:read reports:generate |
GrantsRetrieving a report or a strategy document, and asking for a new one. A strategy is minutes of work, so treat generate as the expensive half of this pair. | Toolsglitch_get_report glitch_generate_report glitch_get_strategy glitch_list_strategies glitch_generate_strategy |
| Scoperecommendations:read | GrantsWhat the engine and detector runs have proposed: pending, applied or dismissed. | Toolsglitch_list_recommendations |
| Scoperecommendations:apply | GrantsApplying a recommendation, and undoing any executed action, whichever tool made it. | Toolsglitch_apply_recommendation, glitch_undo_action |
| Scopecampaigns:write | GrantsBudgets, names, target CPA, states, draft campaigns and new ads. | Toolsglitch_update_campaign, glitch_set_campaign_state, glitch_create_campaign, glitch_create_ad |
| Scopekeywords:write | GrantsNegative keywords. | Toolsglitch_add_negative_keywords |
| Scopeaudit:read | GrantsThe action log, and exporting the audit trail. | Toolsglitch_get_action_log |
Polling a task is the one thing that needs no scope of its own: glitch_get_task_status and GET /v1/task-tracking/{task_id} accept any valid credential, because the id was handed to that caller in the first place.
A token or a key can never do more than the person behind it. Your role in the organization sets the ceiling:
| Role | Ceiling |
|---|---|
| RoleMember | Every read scope except audit:read, plus reports:generate. |
| RoleAdmin | Everything a Member has, plus the write scopes. |
| RoleOwner | Everything an Admin has, plus audit:read and rotation or revocation of any key in the organization, not only their own. |
The ceiling applies to what you can grant, not only to what you can use: a Member cannot create a key that writes.
Membership is checked again on every request. Remove somebody from the organization and their tokens and keys stop working immediately, without anything being revoked by hand.
Sandbox keys, with the glads_test_ prefix, are not available yet. Every key created today is a live key acting on real data, so start with read scopes and use dry_run previews while building a workflow.
GlitchAds keys are built for GitHub secret scanning, and the partner registration is in progress. Once active, a key committed to a public repository is reported by GitHub, usually within seconds of the push.
Such a report is acted on without waiting for anyone to read it. The key is revoked immediately, and every Owner of the organization is emailed the name of the key, its last four characters and, when GitHub reports it, where it was found. The person who created the key is emailed only if they are an Owner.
There is nothing to undo, because a revoked key cannot be used. What is left to do is:
GET /v1/organizations/{org}/audit/export and its from and to dates, and check every request made with that key's last four characters.A key exposed somewhere GitHub cannot see is not detected. Revoke that one yourself, under Account, API Keys.