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-IDheader (orerdo --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.
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.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:email and an optional role — member (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.
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 delegatedgoogle_ads
connection inside the managed org that operates it — in one call:
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.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
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 URLhttps://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.
