Authentication and permissions
API keys for automations, OAuth 2.1 for apps and AI assistants, and the permissions (scopes).
Every call sends a credential in the header:
Authorization: Bearer <API key or OAuth token>The credential always acts on behalf of a team user: history, logs and notifications are recorded for that user, together with the channel used (api_key or oauth).
Which one should I use?
| API key | OAuth 2.1 | |
|---|---|---|
| Typical use | n8n, scripts, server-to-server integrations | Claude, ChatGPT, Cursor, third-party apps |
| How to get it | Web app → Integrações → Gerar chave (Create key) | The app opens the Media Ops sign-in screen and you approve |
| Permissions | Only the ones ticked when it was created | Everything your role allows |
| Lifetime | 30, 90, 180 or 365 days (or no expiration) | 1-hour token, refreshed automatically by the app |
| Revocation | Integrações → Revoke (takes effect within 15 s) | Integrações → Remove access (immediate) |
OAuth is the safest option for apps and assistantsNo long-lived secret is copied around, the user explicitly approves access and can remove it at any time. Use API keys only where there is no screen to sign in (automations).
API keys
- Format:
mops_+ 43 characters. The key is shown only once; the server stores only its SHA-256 hash. - Keep it in a secrets vault (n8n credentials, an environment variable, a secrets manager). Never put it in code, spreadsheets or messages.
- A key cannot create or revoke other keys — that requires signing in to the web app.
- If a key leaks, revoke it in Integrações and create a new one.
curl https://media.ops.infotrafego.com.br/api/v1/me \
-H "Authorization: Bearer $MEDIA_OPS_API_KEY"OAuth 2.1
The authorization server is Media Ops' Supabase Auth (authorization code + PKCE, dynamic client registration enabled). Compatible apps discover everything on their own from:
| Document | URL |
|---|---|
| Protected resource metadata (RFC 9728) | /.well-known/oauth-protected-resource |
| Authorization server metadata (RFC 8414) | /.well-known/oauth-authorization-server |
A call without credentials gets 401 with WWW-Authenticate: Bearer resource_metadata="…", which is where discovery starts.
The flow, from the user's point of view:
- the app opens
…/auth/v1/oauth/authorize; - Media Ops asks the user to sign in (if needed) and shows the consent screen ("App quer acessar o Media Ops", i.e. "App wants to access Media Ops") with the permissions;
- once approved, the app receives the token and starts calling the API/MCP on the user's behalf.
Permissions (scopes)
| Scope | Allows |
|---|---|
clients:read | Read clients, Business Managers, ad accounts and assets |
clients:write | Register clients and Business Managers, sync assets, enable/disable ad accounts and archive clients (archiving requires an administrator) |
balances:read | Read ad account balances |
balances:write | Refresh balances |
meta:read | Query Meta and Google Drive (audiences, interests, locations, lead forms, posts, campaigns, ad sets, folders) |
campaigns:read | Read executions, progress and logs |
campaigns:write | Create, extend and retry campaigns |
audiences:read | Read audience creation runs |
audiences:write | Create engagement audiences |
templates:read | Read targeting templates |
templates:write | Create, rename and delete targeting templates |
admin:users | Manage users (administrators only) |
Permissions are always capped by the user's current role: if an administrator loses that role, their keys lose admin:users immediately. Calling something without the required scope returns 403 with code: "insufficient_scope" and required_scope.
On MCP, the assistant only sees the tools your permissions allow.
Updated about 24 hours ago

