Docs menu

Get started

Authentication

An API key for your code and for MCP clients without a sign-in button; Apogee's OAuth sign-in for AI assistants. Both act as the Apogee account that created them, within the scopes it chose.

Two kinds of credentials

CredentialAPI keyOAuth access token
Looks likeapk_… (47 characters)apo_at_…
Works withThe REST API and the MCP serverThe MCP server only
Made byYou, in Settings → Connections → APIYour AI assistant, when you click Authorize on Apogee's page
Lasts30 days, 90 days, 1 year or never, as you choose1 hour, renewed with a refresh token valid 60 days
Revoked inSettings → Connections → APISettings → Connections → MCP (Connected assistants)

Both go in the Authorization header. Unknown, revoked and expired credentials get the same 401: Apogee never says whether a credential exists.

Header
Authorization: Bearer $APOGEE_API_KEY

API keys

  • Create one in the Apogee app: Settings → Connections → API → Create key. Give it a name (up to characters), its scopes, and an expiry: 30 days, 90 days, 1 year, or never.
  • It is shown once. Apogee stores only its SHA-256 hash and a hint (its first and last characters) to tell your keys apart. Lost: revoke it and create another.
  • 10 active keys at most per account (20 created an hour at most). Revoking one stops it at once.
  • One key per program or assistant, with only the scopes it needs: you can revoke one without touching the others, and Settings → Usage shows each key's calls and credits.
  • Never in a browser or a repository. The REST API sends no CORS headers (except on its public OpenAPI document): call it from a server, a script or CI, with the key in an environment variable or a secret store.

Creating keys and revoking them is done in the app only, logged in to Apogee: a key can never make another key.

Scopes

Each key, and each assistant you authorize, gets one or more of three scopes. A tool outside them is not even listed to the assistant; a REST route outside them answers 403 insufficient_scope with the required_scope.

ScopeWhat it allows
readRead ad accounts, campaigns, ad sets, ads, insights, and follow imports and launches.
launchImport and upload creatives, prepare and launch ads, create a campaign.
actionsPause, activate, change budgets and targeting, duplicate, create ad sets and ads from existing posts.

Running a prepared action checks the action's own scope: a new campaign needs launch, every other change actions.

OAuth for the MCP server

Assistants with a "connect" button (Claude, ChatGPT, Perplexity, VS Code…) sign in with OAuth 2.1, authorization code with PKCE, as the MCP authorization specification describes it. You never handle a token: you log in to Apogee on its own page, check what the assistant asks for, untick scopes if you want (one at least), and click Authorize.

  1. The client calls https://app.apogee.ad/mcp without a token and gets 401 with WWW-Authenticate: Bearer resource_metadata="https://app.apogee.ad/.well-known/oauth-protected-resource/mcp".
  2. It reads the metadata documents below, then registers itself (Dynamic Client Registration) or presents a client metadata document (a client_id that is an https URL on the assistant's own domain).
  3. It opens Apogee's consent page with a PKCE challenge (S256 only); after your Authorize, it receives a code (valid 10 minutes) and exchanges it for tokens.
  4. It calls the server with Authorization: Bearer apo_at_… and refreshes the token every 1 hour.
EndpointURL
Protected resource metadata (RFC 9728)https://app.apogee.ad/.well-known/oauth-protected-resource/mcp
Authorization server metadata (RFC 8414)https://app.apogee.ad/.well-known/oauth-authorization-server
Client registration (RFC 7591)https://app.apogee.ad/oauth/register
Authorization (the consent page)https://app.apogee.ad/oauth/authorize
Tokenhttps://app.apogee.ad/oauth/token
Revocation (RFC 7009)https://app.apogee.ad/oauth/revoke
  • Grant types: authorization_code and refresh_token. Scopes: read launch actions, plus offline_access, accepted for the clients that ask for it (every grant gets a refresh token anyway).
  • Where the code may go back: only to these assistants' callbacks: claude.ai, claude.com, chatgpt.com, www.perplexity.ai, enterprise.perplexity.ai, chat.mistral.ai, console.mistral.ai, vscode.dev; and to your own machine (http://localhost, 127.0.0.1 or [::1], any port) for Claude Code, Gemini CLI or VS Code. Any other client connects with an API key.
  • Disconnect an assistant in Settings → Connections → MCP: its access stops at once. Ads it launched are not touched.

The plan check

The MCP server and the REST API are part of the Pro and Scale plans (plans). Every request checks the account's plan, so a key survives a change of plan: on a plan without the feature, it gets 403 upgrade_required with feature, required_plan and current_plan, and works again as soon as the plan includes the feature. On the MCP server, the refusal comes back as a JSON-RPC error with the same words.

Authentication errors

AnswerMeans
401 invalid_api_keyNo key, or an unknown, revoked or expired one (the REST API). The MCP server answers a bare 401 with its WWW-Authenticate header.
403 insufficient_scopeThe key lacks the route's scope.
403 upgrade_requiredThe account's plan does not include the MCP server, the REST API or the feature.
429 rate_limitedToo many requests with a missing or invalid credential from one address (300 per 15 minutes). A credential that worked in the last few minutes is never held back.

An OAuth token on the REST API is refused: use an API key there (https://api.apogee.ad/api/v1).

Last updated on . The parameters, limits, credits and error codes of these pages are generated from the code of the Apogee API (contract 2026-10-06).

A question, something missing? Write to hello@apogee.ad.

Book a demo

Pick the time that suits you.

Open in a new tab

Loading the calendar…

Talk to Founder