> ## Documentation Index
> Fetch the complete documentation index at: https://docs.erdo.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Ad accounts

> List the advertising accounts your connected integrations can act on — the account id every other provider call needs, and which of your accounts are managers that hold no campaigns of their own.

# Ad accounts

Everything else about paid media is readable without this endpoint — you can already list an
organization's campaigns, read their spend, and see the provider ids a [workstream](/workstreams)
governs. What none of that gives you is the one field every one of those reads and every
[paid-media lifecycle call](/paid-media) needs *first*: the provider's own account id. A Google Ads
query, a status change, a budget change — every one of them takes an account id as its first
argument, and until this endpoint nothing published one. You could see the campaigns; you could not
run a single query against them.

**`GET /v1/ad-accounts`** closes that gap. It asks each of your connected ad integrations to list the
accounts it can reach, the same way the integration's own agent tools would, and returns them in one
shape regardless of provider.

## What comes back

```json theme={null}
{
  "ad_accounts": [
    {
      "provider": "google_ads",
      "account_id": "8834039525",
      "name": "2200 Brickell",
      "currency_code": "USD",
      "time_zone": "America/New_York",
      "is_manager": false
    },
    {
      "provider": "google_ads",
      "account_id": "5302012239",
      "name": "Erdo AI",
      "currency_code": "USD",
      "time_zone": "America/New_York",
      "is_manager": true
    }
  ]
}
```

| Field           | Meaning                                                                                                                                                                                             |
| --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `provider`      | The integration the account belongs to — `google_ads` today.                                                                                                                                        |
| `account_id`    | The provider's own identifier, unformatted (a Google Ads customer id as ten digits, no dashes). This is the value every provider read, and every paid-media lifecycle call, wants as `customer_id`. |
| `name`          | The account's own descriptive name — for showing a person which account is meant. Never used to identify one; address accounts by `account_id`.                                                     |
| `currency_code` | The currency the account reports spend in. Accounts under the same organization are not required to share one, so read this before comparing spend across them.                                     |
| `time_zone`     | The account's own reporting timezone — see below.                                                                                                                                                   |
| `is_manager`    | Whether the account is a manager (MCC) account. See below.                                                                                                                                          |

## Manager accounts return empty, not an error

`is_manager` is the field worth reading before you use an id, not after something goes wrong. A
manager (MCC) account administers other accounts and holds no campaigns of its own, so a query aimed
at one — spend, keywords, a status change — comes back **empty rather than failing**. That reads as
"this account has no advertising," which is the most misleading answer available: it looks like a
finding about the campaigns rather than a mistake about the address.

It's also the ordinary shape here, not an edge case. Erdo provisions managed developments as
sub-accounts under a manager — 2200 Brickell's campaigns live under the Erdo AI manager account shown
above — so an organization's first account in this list is very often a manager whose id looks just
as valid as the operating account underneath it. To make picking correctly the default, **operating
accounts sort first**; a manager comes only after every operating account, and only if the
organization has no operating accounts is a manager listed alone. A caller that just takes the first
entry takes one it can actually query.

(This is a different "manager" from Erdo's own [manager accounts](/manager-accounts), which is about
one Erdo organization operating several client organizations. Same word, two unrelated hierarchies —
a Google Ads MCC never implies anything about who administers your Erdo org, and vice versa.)

## Unavailable providers

```json theme={null}
{
  "ad_accounts": [],
  "unavailable": [
    { "provider": "google_ads", "reason": "Google Ads not connected: token refresh failed: invalid_grant" }
  ]
}
```

`unavailable` names a connected provider whose accounts could not be listed, and why — an expired or
revoked token, most often. This is deliberately kept apart from an organization simply having no ad
accounts: a provider that has never been connected is not reported here at all, because "you have no
Meta Ads accounts because you have no Meta Ads" is not a finding, it's the absence of one. But a
provider you *did* connect going quiet must not just make `ad_accounts` shorter — a caller comparing
this list against campaigns it can already see would otherwise conclude the account had been
disconnected, when the real problem is a token that needs reconnecting.

## Timezone decides where "yesterday" falls

`time_zone` is the account's own reporting timezone, and it matters the moment you compare this
account against a daily figure. A provider's "yesterday" is yesterday in *that account's* timezone,
not the caller's and not UTC — the same reason a [scheduled action](/scheduled-actions#the-schedule)
lets you set an explicit `timezone` rather than defaulting silently. Read it here before joining
anything to a day boundary.

## Reading it

```bash REST theme={null}
curl https://api.erdo.ai/v1/ad-accounts \
  -H "Authorization: Bearer YOUR_API_KEY"
```

In chat or over MCP, `erdo_list_ad_accounts` returns the same list, so an agent can pick an operating
account for itself before running a provider query rather than guessing at an id.

## Feeding other calls

This is a lookup step, not a destination — the `account_id` it returns is what you pass as
`customer_id` everywhere else that asks for one.

A [scheduled action](/scheduled-actions)'s steps run against a specific provider account:

```json theme={null}
{ "name": "performance", "app": "google_ads", "key": "query_google_ads",
  "input": {
    "customer_id": "8834039525",
    "query": "SELECT campaign.id, metrics.cost_micros FROM campaign WHERE campaign.id IN ({{scope.ids}}) AND segments.date DURING YESTERDAY"
  } }
```

A [paid-media lifecycle call](/paid-media) needs the same id to pause a campaign or change its
budget:

```json theme={null}
{ "provider": "google_ads", "customer_id": "8834039525", "status": "paused" }
```

In both cases, `8834039525` is the `account_id` this endpoint returned for 2200 Brickell — not the
`5302012239` beside it, which is the manager and holds no campaigns to query, pause, or re-budget.

## Related

<CardGroup cols={2}>
  <Card title="Paid-media campaign lifecycle" href="/paid-media">
    Pause, resume, or re-budget a campaign in the account this endpoint names.
  </Card>

  <Card title="Scheduled actions" href="/scheduled-actions">
    Declare reads and judgements that run against an account on a clock.
  </Card>

  <Card title="Manager accounts" href="/manager-accounts">
    Erdo's own manager/managed-organization hierarchy — a different "manager" from the one this page reports.
  </Card>

  <Card title="Page tracking" href="/page-tracking">
    The equivalent read for what's tagging your pages, rather than what you can advertise from.
  </Card>
</CardGroup>
