Guides
Managed workspaces
For agencies and B2B: create a workspace per client, let the client connect channels on a hosted page, then post for them.
An agency key with workspaces:manage can create client workspaces, hand each client a hosted page to connect their own channels without an overads login, and then act on the client workspace with the agency key plus a header, or with a key minted for the client. Nothing here needs the client to sign up.
1. Create the workspace
curl -X POST https://api.overads.io/public/v1/workspaces -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-H "Idempotency-Key: acme-coffee-create" \
-d '{ "name": "Acme Coffee" }'The workspace is real: it inherits the agency's plan, is owned by the agency workspace's owner, appears in the app switcher and under Settings > Clients. Keep the returned id.
2. Let the client connect their channels
curl -X POST https://api.overads.io/public/v1/workspaces/WORKSPACE_ID/connect-url -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{ "expiresInDays": 14, "brand": { "name": "Northwind Social", "logoUrl": "https://cdn.northwind.example/logo.png" } }'Send the returned url to the client. The page at /connect/ovc_... shows your brand name and logo, one button per channel, and the accounts already connected. The client signs in to each platform with the platform's own login; tokens land in their workspace, encrypted, exactly as if they had connected in the app. The link is the credential: it grants reading that page and connecting channels, nothing else.
- Default lifetime 7 days, up to 90. An expired link says so and asks for a new one.
rotate: truerevokes every earlier link for the workspace first. Use it when a link leaked or a contact left.- Detaching the workspace revokes every link for it.
- Channels that are in review show on the page but are marked as not configured on deployments where their credentials are absent.
3. Act on the client workspace
Two options. With the agency key, add the header to any public route or MCP call:
curl https://api.overads.io/public/v1/connections -H "Authorization: Bearer sk_live_YOUR_KEY" \
-H "x-overads-workspace: WORKSPACE_ID"Or mint a key that belongs to the client workspace and hand it to whatever runs for that client. It needs no header and can never hold workspaces:manage:
curl -X POST https://api.overads.io/public/v1/workspaces/WORKSPACE_ID/api-keys -H "Authorization: Bearer sk_live_YOUR_KEY" -H "Content-Type: application/json" \
-d '{ "name": "Acme integration", "scopes": ["connections:read", "posts:read", "posts:write", "media:write"] }'From here everything is the ordinary API: GET /connections lists what the client connected, POST /posts schedules into it, webhooks registered in that workspace fire for its posts. Scopes, rate limits and idempotency all apply to the workspace being acted on.
Rules worth knowing
- The header is honoured on every public route and every MCP tool, except the
/workspaces/*routes themselves, which always act on the agency and refuse it withWORKSPACE_HEADER_NOT_ALLOWED. - Only a direct child counts. A managed workspace cannot manage workspaces of its own, and a key minted for a client cannot name other workspaces in the header.
- A header naming a workspace the key cannot act for answers
403withWORKSPACE_NOT_MANAGED, never the agency's own data. A malformed header answers400with the same code. DELETE /workspaces/:iddetaches. The workspace, its posts and its connections stay with their owner; keys minted for it keep working; connect links are revoked. Nothing is deleted.- Every create, detach and key mint is written to the agency's audit log with the key id that did it.
White label in this phase is the brand name and logo on the hosted connect page. The client workspace itself is an overads workspace with overads branding.