Skip to main content

Manager accounts

A manager account lets one organization operate many client (“managed”) organizations with a single credential. It’s the pattern a portal uses to run an Erdo org per customer: instead of minting and pasting a separate API key for every tenant, you provision each client org under your manager org and operate them all with one manager key. This mirrors how a Google Ads MCC (manager account) operates many ad accounts, and how a SaaS control plane runs a tenant per customer. If you’re building a product on top of Erdo that gives each of your customers their own isolated org, this is the surface you want.

How it works

Your active org is the manager — you must be an admin or owner of it. Two things hang off it:
  • Managed orgs — the client tenants you provision. Each is a full, isolated Erdo organization: its own datasets, pages, knowledge, and RBAC. Creating one records a management link (kept as an audit trail even after you stop managing) and its own identity inside the org, so downstream setup seeds with a real owner.
  • The manager key — one non-expiring API key, held by your manager org, that is a member of every org you manage. You operate a specific managed org by naming it in the request: pass its slug or id as the X-Organization-ID header (or erdo --org <slug> on the CLI). The backend re-validates the manager’s membership in that org on every request, so revoking management ends access immediately.
Because access is enforced by membership plus the org header — the same mechanics as any Erdo token — there is no new auth path to reason about. A managed org’s service usage never counts toward your manager org’s billable seats, and never appears in its Team list.

Provisioning a client org from a portal

The typical portal flow, once per customer:
1

Create the client org

Call create managed organization with the customer’s name. You get back the new org’s slug — the durable handle you store against that customer.
2

Mint the manager key once

Call create manager key to mint the single credential your portal holds. It’s returned exactly once; store it as a secret. You only do this once (or again to rotate).
3

Operate the org

Send the manager key with X-Organization-ID set to the customer’s org slug to do anything inside that org — create datasets, build pages, run agents. The same key operates every customer.
4

Off-board

Call revoke managed organization with the slug to end management. Access stops immediately; the management link is retained as an audit record.
Only an admin/owner of the manager org can create, revoke, or mint the key — the same authority check on every surface below. Listing is available to any member of the manager org.

A new client org starts with no company

When somebody signs up for Erdo directly, we work out what their business is from the address they signed up with and research it, so their agents know who they are from the first message. A client org you provision has no such address — it is created by your manager credential, not by a person — so Erdo does not guess. The org starts with no company, and the marketing research that normally runs during onboarding waits rather than researching the wrong business. Tell Erdo who the customer is instead. Your portal already knows more about them than a domain lookup would find, so write it into the org as knowledge — erdo_create_knowledge, or POST /v1/knowledge with the client’s org in X-Organization-ID. Their agents read it on every thread from then on. A human member you add to the org can also give their company domain during their own onboarding, and Erdo will research it the usual way.

Adding people to a managed org

A freshly provisioned client org has no human members — its only admin is the manager’s service identity. To give a person access (your own operators, or the customer’s team), add them by email from the manager surface:
The body takes email and an optional rolemember (the default) or admin. owner is deliberately not grantable: a manager administers a client org, ownership stays with the client.
  • If an Erdo account already exists for the email, it becomes an active member immediately ("invited": false) and can open the org in the app right away.
  • If no account exists yet, a pending invitation is created and an invite email is sent ("invited": true); the membership activates when they sign up with that address.
Re-adding an existing member is idempotent, and never demotes: requesting a lower role than the one they already hold reports the role in effect.

Provisioning an ads container

If your manager org’s Google Ads connection is a manager account (MCC), you can give a managed org its own Google Ads container — a fresh sub-account under your MCC, plus a delegated google_ads connection inside the managed org that operates it — in one call:
The body is optional. descriptive_name (the account’s display name in Google Ads) defaults to <org name> (<org slug>), currency_code to USD, and time_zone to America/New_York — note that Google fixes an account’s currency and time zone at creation. The response identifies the container, never any credential material:
customer_id is the managed org’s own Google Ads account; login_customer_id is your MCC, the context every request against that account runs in. The delegated connection stores both, so agents and syncs inside the managed org operate the sub-account directly — no per-org browser OAuth.

Billing is the one step left to a human

A new sub-account is created with no billing setup, and until it has one nothing it runs will serve. Google only lets the API attach a billing setup for accounts on monthly invoicing, so for a card-billed MCC somebody has to link a payments profile in the Google Ads UI. billing_configured and billing_status say where the account stands, so you can surface that step while the campaigns are being built rather than discovering it at go-live. billing_status carries Google’s own value — APPROVED, PENDING, APPROVED_HELD, CANCELLED — plus two of ours: none when the account has no billing setup at all, and unknown when the check could not be made. Those last two are different facts and worth treating differently: none means somebody has to go and link a payments profile, unknown means we could not reach Google to find out. Only APPROVED sets billing_configured to true. Both fields are reported on a repeat call too, so asking for an already-provisioned container is how you check whether it is ready to serve. Two preconditions, both reported as errors rather than guessed around: your manager org must hold an active Google Ads connection, and that connection must be an MCC one (it carries a login_customer_id — stored automatically when the token’s only accessible account is a manager, or set explicitly on the connection’s credentials). The call is idempotent: an org that already has a delegated connection under your MCC gets it back with "already_provisioned": true, and a second sub-account is never created — even when a previous attempt failed part-way. One container per managed org is the point: each client’s campaigns, audiences, and conversion data live in an account only that org’s connection operates, instead of several clients sharing one account behind scope filters.

Adopting an existing organization

Provisioning covers orgs you create; adoption brings an org that already exists under your management — one created before your manager org existed, or previously run standalone. Because adoption hands a manager admin access to everything in the org, it requires two-sided consent: your manager key alone can never take over an org.
1

The org's owner mints an adoption token

Signed in to the org being handed over (owners only, in-app session — an API key cannot do this), the owner calls POST /organization-adoption-invite. The response contains a one-time token, shown exactly once — only its hash is stored. The owner can pin the manager allowed to redeem it by passing { "manager_org_slug": "your-manager-org" }; the token expires after 7 days and works once. If the org is already managed, minting is refused — the current manager must revoke its link first (one manager per org).
2

The manager redeems the token

From the manager side — the same authority as every managed-org call (admin/owner of the manager org, or the manager key itself):
Redeeming records the management link and seats the manager’s service identity in the org, so the manager key can operate it immediately via X-Organization-ID — exactly like a provisioned org. The response is the same shape as create: the org’s slug, name, and your management role.
Adoption changes who operates the org, not what’s in it: datasets, pages, knowledge, members, and ownership are untouched — the client’s owner stays the owner. A used, expired, or unknown token reads uniformly as not found, so a leaked or guessed token confirms nothing. Redeeming a token for an org you already manage succeeds as a no-op; stopping management afterwards is the same revoke managed organization as ever, and the org can later be adopted again with a fresh token.

Erdo platform

Open Settings → Manager Accounts in the Erdo platform to create and view client organisations, stop managing an organisation, or create and rotate the manager key. The raw key is shown once: copy it into your server-side secret manager before leaving the page. This surface is available to ordinary Erdo organisations; creating, revoking, and rotating require an admin or owner.

CLI

The CLI authenticates with your Erdo token and active org (erdo login, erdo org use). In CI, set the manager key as ERDO_API_KEY and pin the target tenant with ERDO_ORG or --org. See the CLI reference.

MCP tools

Identity and RBAC ride the request context — a caller only ever acts as their own manager org, and managed orgs are referenced by slug, never a UUID. Manager keys are deliberately not minted by an MCP tool: a model-facing tool must not create a non-expiring credential. Create or rotate the key from Platform, the CLI, or POST /v1/manager-key, then use that credential to operate managed orgs through MCP. Member adds stay off the model-facing tool surface for the same reason — grant people access via POST /v1/managed-organizations/:slug/members.

REST

Base URL https://api.erdo.ai. Authenticate with Authorization: Bearer <token> and select the manager org with X-Organization-ID (for the lifecycle calls, that’s your manager org; to operate a managed org, set it to that org’s slug/id). The manager key returned by POST /v1/manager-key is a standard erdo_api_* bearer token pinned to your manager org — send it as Authorization: Bearer <key> with X-Organization-ID: <managed-org-slug> to act inside any org you manage.