Invite a user to an ad account by email
Emails someone an invitation to a Google Ads account with the access role you choose, for example to hand a client account you created under your manager to its owner.
Creates a user access invitation (Google's CustomerUserAccessInvitationService) on adAccountId. The connection's Google user needs admin access to that account, directly or through a manager above it, which is the case for an account created with POST /v1/ads/accounts. The recipient accepts from the email, possibly with another Google account. When Google requires multi-party approval, nothing is sent until a second admin of the account approves the request in Google Ads: the response then has status: PENDING_APPROVAL and a multiPartyAuthReviewId instead of an invitationId, which DELETE /v1/ads/accounts/user-invitations/pending-approvals withdraws. Not idempotent: Google refuses a second invitation while the email has one pending or awaiting approval. Google has no server-side check for this call, so validateOnly: true reads the account's invitations with the same credentials (proving the account is reachable) and fails if the email already has a pending one, without sending anything.
Authorization
bearerAuth API key authentication: send your Zernio API key in the Authorization header, prefixed with Bearer.
In: header
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
application/json
application/json
application/json
application/json
import Zernio from '@zernio/node';const zernio = new Zernio({ apiKey: process.env.ZERNIO_API_KEY });const { data } = await zernio.adaccounts.inviteAdAccountUser({ body: { accountId: 'account_abc123', adAccountId: 'adaccount_abc123', emailAddress: 'user@example.com', accessRole: 'ADMIN', },});console.log(data);{ "customerId": "string", "emailAddress": "string", "accessRole": "ADMIN", "status": "PENDING", "invitationId": "string", "multiPartyAuthReviewId": "string", "validateOnly": true}Read an ad account's campaigns and ad sets live
Reads an ad account's campaigns and ad sets straight from Meta or TikTok, so checks like budget limits see current values. Reads the campaigns and ad sets of one Meta ad account or TikTok advertiser **live from the platform**, so it is cheap enough to run before every write: for example a per-ad-account spend ceiling that must see the current daily / lifetime budget rather than the synced copy. On Meta it is a single Graph call per request (the account's `/campaigns` and `/adsets` edges, filtered by `effective_status`); on TikTok one `campaign/get` and one `adgroup/get` page (TikTok ad groups are returned as `adSets`). **Live vs synced.** GET /v1/ads/campaigns and GET /v1/ads/ad-sets serve Zernio's synced store, refreshed by background sync (typically 15 to 60 minutes behind Meta), and their `live=true` re-reads only the on/off switches of at most 20 objects. This endpoint returns what Meta reports at `readAt`, for every matching campaign and ad set, and stores nothing. Budgets and bid amounts are in whole units of `currency`, the same units as the synced rows (Meta's minor units are converted; TikTok already reports whole units). A campaign with a campaign budget (Meta Advantage+ campaign budget, TikTok campaign budget optimization) carries `budget`; otherwise each ad set carries its own. Each level returns at most `limit` rows. When more match, `paging.<level>.after` is a cursor: pass it back as `after` together with `level` to read the next page of that level only. TikTok pages by number, so a TikTok cursor must be sent with the same `limit` that produced it (another `limit` is a 400). Other platforms answer 501 rather than serving synced data. **TikTok specifics.** `status` maps to TikTok's `primary_status` filter, which takes one value: ACTIVE = delivering (`STATUS_DELIVERY_OK`), PAUSED = switched off (`STATUS_DISABLE`), DELETED = `STATUS_DELETE`; omitted = every status except deleted (`STATUS_NOT_DELETE`, which includes enabled entities that are not delivering, such as an ad group in review). Several values, or IN_PROCESS, WITH_ISSUES, CAMPAIGN_PAUSED and ARCHIVED, are a 400. `budgetRemaining` and `spendCap` are always null (TikTok reports neither), campaign `bidStrategy` is null (TikTok bids per ad group), ad set `bidStrategy` is normalized to the Meta vocabulary like GET /v1/ads, `promotedObject` is `{ pixelId, customEventType, applicationId, customConversionId }` (the keys TikTok has set, as POST /v1/ads/create takes them), and `targeting` holds TikTok's targeting fields verbatim.
List invitations awaiting multi-party approval
Lists the email invitations to a Google Ads account that Google is holding until a second admin approves them. When Google requires multi-party approval, POST /v1/ads/accounts/user-invitations answers `status: PENDING_APPROVAL` and sends nothing. Those requests are not in GET /v1/ads/accounts/user-invitations; this reads Google's `multi_party_auth_review` resource for the ones still `PENDING` that target an invitation. Approved, rejected, revoked and expired reviews are not listed. Results are cached for 10 minutes and dropped on every invite or withdrawal through Zernio, but an approval or rejection made in Google Ads can take that long to show.