Layers
Partner APIAPI referenceAds

GET /v1/projects/:projectId/ads/ad-accounts

List Meta, TikTok, and Apple ad accounts connected to a project, with credential health.

View as Markdown
GET/v1/projects/{projectId}/ads/ad-accounts
Phase 1stable
Auth
Bearer
Scope
ads:read

Returns every ad account connected to the project across Meta, TikTok, and Apple Search Ads. Each row carries the platform-native id and current credential health. Layers' ad platform integrations are bring-your-own — partners connect their own ad accounts via OAuth and platform billing runs against the partner's own funding source. This is the first endpoint to hit when a partner agent needs to know which platforms a project can actually buy ads on right now.

Path
  • projectId
    string (UUID)required
    Project to list within.
Query
  • platforms
    string[]optional
    Restrict to one or more platforms.
    One of: meta_ads, tiktok_ads, apple_ads
  • credentialMode
    stringoptional
    Filter by credential source. All Layers ad connections are `byo` today; `agency` is reserved.
    One of: agency, byo
  • healthy
    booleanoptional
    Keep only ad accounts with tokenStatus=valid.

Example request

curl "https://api.layers.com/v1/projects/prj_01HX9Y7K8M2P4RSTUV56789AB/ads/ad-accounts?healthy=true" \
  -H "Authorization: Bearer lp_live_01HX9Y6K7EJ4T2_4QZpN..."
const res = await fetch(
  `https://api.layers.com/v1/projects/${projectId}/ads/ad-accounts?healthy=true`,
  { headers: { Authorization: `Bearer ${apiKey}` } },
);
const { items } = await res.json();
import httpx

r = httpx.get(
    f"https://api.layers.com/v1/projects/{project_id}/ads/ad-accounts",
    params={"healthy": True},
    headers={"Authorization": f"Bearer {api_key}"},
)
items = r.json()["items"]

Response

200OK
{
  "items": [
    {
      "adAccountId": "01HXF1A2B3C4D5E6F7G8H9J0K1",
      "platform": "meta_ads",
      "externalId": "act_123456789012345",
      "name": "Acme Coffee — US",
      "currency": "USD",
      "timezone": "UTC",
      "credentialMode": "byo",
      "tokenStatus": "valid",
      "tokenLastValidatedAt": null,
      "walletBalance": null,
      "connectedAt": "2026-03-02T14:11:00Z"
    },
    {
      "adAccountId": "01HXF2A2B3C4D5E6F7G8H9J0K1",
      "platform": "tiktok_ads",
      "externalId": "7389201...",
      "name": "Acme Coffee TikTok",
      "currency": "USD",
      "timezone": "UTC",
      "credentialMode": "byo",
      "tokenStatus": "valid",
      "tokenLastValidatedAt": null,
      "walletBalance": null,
      "connectedAt": "2026-03-18T09:42:00Z"
    },
    {
      "adAccountId": "01HXF3A2B3C4D5E6F7G8H9J0K1",
      "platform": "apple_ads",
      "externalId": "org-9823412",
      "name": "Acme Coffee iOS",
      "currency": "USD",
      "timezone": "UTC",
      "credentialMode": "byo",
      "tokenStatus": "expired",
      "tokenLastValidatedAt": null,
      "walletBalance": null,
      "connectedAt": "2026-02-11T19:05:00Z"
    }
  ]
}

The response is unpaginated — each project has at most one credential row per platform, so items returns the union directly with no nextCursor.

Credential modes

  • byo — The end-customer connected their own ad account via OAuth. This is the only mode shipping today. Billing runs against the customer's funding source on the platform; walletBalance is always null because Layers does not aggregate platform wallet state in Phase 1. Token refresh is automatic but tied to the customer's OAuth grant — a revoked grant surfaces as tokenStatus: "expired" until reconnected.
  • agency — Reserved for a future agency / Business Center flow. No production projects use this mode yet.

Token status

ValueMeaning
validLast validation call succeeded. Safe to use.
expiredRefresh attempt failed. Reconnect via POST /v1/projects/:projectId/ads/ad-accounts/oauth-url.
revokedUser revoked the grant on the platform. Reconnect required.
pendingConnection just initiated; first validation has not landed.

tokenLastValidatedAt is reserved for the validation timestamp once Layers wires up periodic validation; it is null in Phase 1.

Notes

  • walletBalance is reserved for a future agency / Business Center mode. It is always null today. For BYO, query the platform's own API if you need wallet state.
  • externalId is the platform-native account id — act_... on Meta, a numeric string on TikTok, org-... on Apple. Use it when linking out to the platform's ad manager.
  • timezone is reported as "UTC" for every account in Phase 1 — Layers does not yet pull the platform-native timezone. If you need the local-clock timezone the ads are bidding against, query the platform's own API.
  • A tokenStatus of expired or revoked does not immediately pause running ads — the platform keeps those running from its side. New ad creation against that ad account will fail until reconnected.
  • Disconnected ad accounts (rows where disconnected_at is set) are excluded from the response by default. There is no include-disconnected flag.

See also

On this page