Skip to main content
Buyer Setup separates your organization’s platform readiness from the setup for each seller or buying platform. If Scope3 invites you to a new buyer account, the setup email is sent to your named address. Accept the invitation and verify that email to join. The invite opens the account setup path; your organization still completes its domain, plan, terms, and other readiness steps before live buying. Buyer and Seller Setup use the same activation pattern: a neutral status and progress header, one operator-domain editor, and a clear next action. They are separate Pages because the work after identity is different. Buyers configure destinations and advertiser mappings; storefronts configure inventory, publisher authorization, settlement, and payouts.

Platform go-live

You complete these steps once for the buyer account:
  • confirm the domain of the company that runs the account (the Company identity step);
  • choose the plan for this buyer account;
  • accept the current terms;
  • resolve any account hold;
  • once choosing payment terms is available, choose the payment terms sellers are asked for before buying from a seller on consolidated billing (see Your organization’s payment terms); and
  • add your billing details (payer name, street address, and country) in the Billing details step, which is open only while you can buy from a seller on consolidated billing and those details are missing.
These facts unlock real non-spend work such as connections, proposals, and campaign setup. Your billing details are needed only when a transaction’s seller bills through Apostra on consolidated billing. Apostra does not grant or manage a buyer credit line — sellers decide credit on their own terms, on their own media. The Company identity step asks for the domain of the company that runs this account. Sellers use it to recognize you. Sandbox advertisers don’t need this step; live advertisers and real buying do. Once you have confirmed the domain and created your first advertiser, the domain and the account code become read-only, and changing them takes an identity migration through support. In AdCP terms the company is the operator and each buyer account is one operating unit of it. Every buyer account is its own operating unit. There is no “whole company or one team” question: an organization with one buyer account has one unit, and an organization with several accounts has several. Together, the domain and the account’s unit code form its AdCP operator identity: Apostra generates the code from the account name, for example “DM - Restaurant Company Europe” becomes dm-restaurant-company-europe. If another account under the same operator domain already holds that code, Apostra adds a short numeric suffix. You can type a shorter code of your own, such as rce; prefer one your organization already uses, or a short, readable code that will stay meaningful. Do not use default, global or primary (no account is the default, global or primary one), a temporary display name, a seller’s account ID, or an Apostra database ID. The code never changes when you rename the account. The buyer account name is mutable display metadata; the billing-company name is separate and does not identify the operating unit. An account administrator confirms the identity. Before confirming, review the other buyer accounts under the same operator domain. Buyer Setup lists the identities visible in your account hierarchy for the domain you enter. Apostra rejects an exact identity (domain and code) already claimed by another buyer account. You can change the operator domain or account code after setup and after connecting storefronts, until an advertiser account is created or bound under that identity. Buyer Setup then reports the identity as locked. In AdCP 3.2, the operator domain and the operating-unit ID are advertiser natural-key dimensions; pre-3.2 bindings still make the seller-visible operator domain immutable. Changing either requires an advertiser identity migration rather than an ordinary settings update. Accounts under an organization that claims a domain. When your buyer account sits under an organization whose company identity holds a domain, an account that uses that same domain takes its domain proof from the organization:
  • The account is verified when the organization’s domain is approved or verified by DNS, and that approval covers every account under the organization that uses the domain. An approval for the account itself does not count, and staff ask for the approval on the organization instead.
  • An account that proved the domain before the organization claimed it keeps that proof.
  • Once any account using the organization’s domain has an advertiser, the organization’s domain is locked, because changing it would change every one of those accounts’ identity at sellers.
  • An account that uses a different domain, or whose organization has not saved a company identity, confirms and proves its own domain as before.
Apostra compares the operator domain with account membership and the verified organization domain. The Organization must prove control before real operations are available. AAO corporate metadata can suggest or classify the Organization, but a public AAO record is not ownership proof. A buyer operator does not publish adagents.json; that document belongs to seller authorization. Buyer setup also does not require brand.json. Buyer Setup always shows the current operator. A domain suggested from existing account or work-email information is prefilled, but it is not silently treated as your choice. The account code field is prefilled with a code generated from the account name, such as dm-restaurant-company-europe. Keep it or type your own, and the code you see is the code that is saved. Accounts created before every account had an operating unit keep working on their existing buying paths until their unit is assigned. Buyer Setup does not block them; a complete AdCP 3.2 account key needs the unit, so new AdCP 3.2 provisioning waits for it.

Seller-history co-op

The operator identity also holds whether the account joins the seller-history co-op, how an account takes part in the data co-op of Section 6.3 of the Terms of Service. It starts off. An account administrator changes it with PATCH /api/v2/buyer/readiness/operator and sellerHistoryCoop, or with save_buyer_operator on /mcp/v3. What a member shares and gets, and how leaving works, is on that page.

Double-check your media partners

Before you create your first advertiser, Buyer Setup asks one question: Have you double-checked your media partners? Media partners are managed for the whole company, not advertiser by advertiser. The Review media partners button opens Media Partners. This is a reminder, not a go-live step. It never blocks creating an advertiser, and Apostra still starts account setup with media partners whether or not you open it. It shows as done once your company has accepted its media partners, which happens when it makes a choice about them on the Media Partners page. Buyer readiness returns this as a check with the id media_partners. It is missing until your company has accepted its media partners, then complete, and its isBlocker is always false, so it changes none of the readiness status, capability, or destination answers. On /mcp/v3, get_status lists it as a recommended next action that opens Media Partners.

Launch your first campaign

Once platform setup is complete, the next step is launching your first campaign. Your first campaign counts as launched once one of its media buys is placed. This is the step after setup, not a setup check: it never blocks anything, and it changes none of the readiness status, capability, or destination answers. Buyer readiness returns it as firstCampaign. firstCampaign.launched says whether the account has placed a media buy. Until it has, and once platformReady is true, firstCampaign.action is Launch your first campaign, which opens Campaigns (page: "campaigns"). While setup steps remain, or once a buy is placed, action is null. firstCampaign itself is null only when it could not be read for that request; try again. On /mcp/v3, get_status lists the same step as a recommended next action, first_campaign, that opens Campaigns.

Your next step on the Advertisers page

The Advertisers page shows one next step above your advertisers. While a setup step blocks buying, it names the first one and opens Buyer Setup. Once setup is complete and nothing has launched, it is Launch your first campaign and opens Campaigns. It is the same step get_status puts first. The page shows nothing when no step is left, or when the step could not be read in time.

If an API call requires Buyer Setup

On /mcp/v3, call get_status first. When operatorIdentity.usableForBuying is false, an account administrator can call save_buyer_operator with the real non-platform operatorDomain, and optionally a short AdCP operator_unit code ({ "id": "rce" }); without one, the account’s unit code is generated from its name. When locked is true, follow the support action returned by get_status instead, unless the account has no unit yet (operator_unit is null), which the same call can still assign. To open the Buyer Setup page for a person, call open_page with { "page": "buyer_setup" }; the opening call changes nothing. The v2 request, PATCH /api/v2/buyer/readiness/operator, takes the same operatorDomain and optional operatorUnitId. It still accepts operatorScope: "specific_unit" from older clients and generates the unit when you send no scope. It refuses operatorScope: "whole_operator" with a 400:
Whole operator is retired; every buyer account is an operating unit. Send operatorScope: “specific_unit” with operatorUnitId, or omit operatorScope to use the unit generated from the account name.
Nothing is converted for you: a request that used to save a whole-operator identity now fails until you send a unit or omit the scope. This is a deliberate exception to the rule that v2 only grows. The decision, in full: “v2 buyer PATCH /api/v2/buyer/readiness/operator refuses operatorScope: "whole_operator" with a 400. Whole operator is retired. Brian O’Kelley, 2026-10-22.” Reads are unchanged and return what is stored. The v2 readiness response keeps operatorScope, scopeStatus and scopeConfirmedAt as deprecated, read-only fields that report the stored scope: an identity saved as whole_operator keeps reading that way until it is converted to its own unit, and a saved or generated unit reads specific_unit. Nothing new is ever saved as whole_operator, so the update response reports specific_unit once the unit is saved. Readiness also returns suggestedOperatorUnitId, the code the account would get if you saved it now. The tool confirms commercial identity only; it does not grant user access or change the login organization.
Before that identity is claimed, you can still create, update, or archive a test-only advertiser with sandbox: true, through v3 save_advertiser, the v2 advertiser API, or the Create advertiser form. This exception applies only to the operator-identity check: plan selection, current Terms, and other readiness blockers still apply. Live advertisers continue to require the complete buyer operator identity.
Buyer discovery and other new buying operations return HTTP 409 with error code BUYER_SETUP_REQUIRED when the account has no confirmed, non-platform operator identity. For a missing identity, the exact structured details are reason: "missing_operator_identity", readinessCheck: "operator_identity", setupStep: 1, and setupPage: "buyer_setup". This is a correctable account-readiness task, not a seller outage: open Buyer Setup, confirm the operator domain, then retry the request.
Apostra never substitutes interchange.io for a missing buyer operator. That would combine unrelated buyers under one seller-side natural-key account. If a legacy profile explicitly contains that platform domain, the request uses the same BUYER_SETUP_REQUIRED contract with details.reason: "platform_operator_not_allowed". Replace it with your organization’s operator domain in Buyer Setup. Changing or confirming the operator affects new discovery and provisioning, but does not rewrite existing transactions. A historical media buy continues to use the exact seller account persisted when the buy was created, including for status, creative re-sync, update, cancellation, and delivery operations. The same identity gates account linking. A production entry on POST /api/v2/buyer/storefront-accounts/sync (or the sync_buyer_storefront_accounts tool) must name your confirmed operator domain as operator; a different domain returns HTTP 403 with ACCESS_DENIED and details.reason: "operator_identity_mismatch", and a missing identity returns the BUYER_SETUP_REQUIRED contract above. A sandbox entry (sandbox: true) is fenced off from production spend and may name any operator.

Who decides your account request

A seller decides your account request the same way whichever way it arrives: sync_accounts on the seller’s AdCP endpoint, POST /api/v2/buyer/storefront-accounts/sync or the sync_buyer_storefront_accounts tool, or an account Apostra opens for you automatically.
  • A seller that routes accounts to its own sales agent (a Listing whose only source is that agent) forwards the request, including any payment_terms, to the agent, and the agent approves or rejects it. The seller does not review it in Apostra. The agent must accept the terms you requested or reject the account. Apostra records the terms you requested, and the account reports in payment_terms the terms the agent confirms. A new account the agent offers on other terms is treated as a refusal: the account is not activated and waits for you to review the seller’s terms. An existing account the agent keeps on other terms stays usable, but it shows a warning naming both the terms you requested and the terms the agent kept, until the agent reports the terms you requested. If the agent cannot take account requests, the request fails and nothing is created: the buyer API returns HTTP 422 with CAPABILITY_NOT_SUPPORTED and a details.reason such as account_resolution_authority_missing, and the AdCP endpoint returns CONFIGURATION_ERROR. Retrying does not help until the seller fixes its agent.
  • Every other seller applies its account approval setting in Apostra: the request is approved automatically or waits for the seller to review it.
A request that is still waiting comes back with status: "pending_approval". Check it later with GET /api/v2/buyer/storefront-accounts or the list_buyer_storefront_accounts tool. On the seller’s AdCP endpoint, sync_accounts answers with the account’s own row, status: "pending_approval" and a setup message, rather than a task; call list_accounts on that endpoint to see the seller’s decision. On a storefront that has not moved to complete AccountKey mapping, an approved account belongs to your buyer organisation: any colleague or service token of the same buyer can use it, and nobody outside your organisation can.

When a direct AdCP 3.0 or 3.1 storefront asks for account setup

After a storefront moves to complete AccountKey mapping, a direct AdCP 3.0 or 3.1 sync_accounts call can still read an approved account that already belongs to its credential. It cannot create a new account on that older wire format. A new direct request returns ACCOUNT_SETUP_REQUIRED with details.reason: "complete_key_account_setup_required". Create the account through your authenticated V2 buyer account, then retry the direct call after the seller has decided it. Use either the REST request POST /api/v2/buyer/storefront-accounts/sync or the buyer MCP tool sync_buyer_storefront_accounts. Both take the same account request; target the storefront with its V2 storefrontId and send the brand, your confirmed operator domain for a production request, and the billing party:
This V2 request creates or returns the one organization-owned account request for that seller. It does not create a separate legacy per-credential approval. For production, use your confirmed buyer operator identity; use sandbox: true only for a test account that cannot be used for production spend. See Payment terms for the optional per-seller request field and the billing requirements for operator and advertiser.

Address your approved account from a direct AdCP 3.0 or 3.1 agent

Once a seller has moved to complete AccountKey mapping, a direct agent can use two kinds of approved account. The account_id itself says which kind:
  • Company accounts have an account_id that starts seller_account_v1_. The seller approved them for your verified buyer organisation and an advertiser, and any human or service token currently authorised for that organisation and advertiser can use them. sync_buyer_storefront_accounts and list_accounts return them.
  • Credential accounts are the accounts that one credential of yours was approved for before the seller moved. Their account_id starts sf_. They stay available to that exact credential and to nobody else: another user or service token of the same company does not inherit them, and Apostra does not convert them into company accounts.
Send the account_id alone. An AdCP account is one of two exclusive shapes, never both:
A request that sends account_id together with brand or operator inside account is rejected before any account lookup with VALIDATION_ERROR, field: "account", and details.issues[] naming /account and the additionalProperties rule. It is a malformed request, not a missing account. To tell Apostra which brand you are buying for, send the top-level brand reference as AdCP defines it. Its domain must match the approved account’s brand. On a seller in complete-key mode these calls resolve the same approved account, through the lane its account_id belongs to: list_accounts, get_products, get_account_resources, sync_creatives, create_media_buy, get_media_buys, update_media_buy (including cancellation), and get_media_buy_delivery. An id that starts seller_account_v1_ is only ever looked up as a company account. If it is unknown, malformed, or not yours, the call fails; Apostra never retries it as a credential account, and never reads a sf_ id as a company account. Each company-account call checks again, at that moment, that:
  • the account belongs to your verified buyer organisation and is approved by the seller;
  • the request selects the advertiser the account is scoped to, with the x-scope3-seat-id header (or an API key that is already bound to it);
  • the credential is a human user with Premium or Admin access to that organisation, or a write-capable service token for that organisation and advertiser, and has not been revoked; and
  • your buyer account is currently eligible.
A credential account needs the grant for the calling credential to be active. list_accounts returns your company accounts first, then the calling credential’s own credential accounts, behind one pagination.cursor. A credential with no selected advertiser or no human or service-token actor lists its credential accounts only. A caller that does present that authority and is refused gets the refusal, not a shorter list. GET /api/v2/buyer/storefront-accounts and the list_buyer_storefront_accounts tool list the same way on a seller in complete-key mode: company accounts first, then the calling credential’s own credential accounts, behind one cursor. A cursor that did not come from this listing is rejected with a validation error. A new buy needs an account that is settled before anything is written. Send the account_id. A brand and operator is accepted only when it is exactly one credential account that the calling credential already holds (same brand, operator and sandbox flag, nothing more, and the grant is active); the buy is then written under that credential account. Any other brand and operator, and a missing account, returns ACCOUNT_SETUP_REQUIRED and writes nothing. A partial key is never completed into a company account. If a call fails closed, Apostra does not fall back to another account or to every account the customer owns. Sellers that are not in complete-key mode keep the released per-credential account behaviour for every call above. An account grant says whether the seller will transact with you. It does not say whether Apostra uses that seller for a given advertiser. A GET /api/v2/buyer/storefront-accounts request (or the list_buyer_storefront_accounts tool) that names an advertiser with advertiserId, or selects one with the x-scope3-seat-id header, also returns ext.interchange.advertiser_activation: seller_on (whether product discovery and new media buys use this seller for that advertiser) and reason (the control that decided it). A named advertiser you cannot read is refused with 403, and 503 means access could not be checked right now. A seller can have an active grant and still be off for the advertiser; turn it on with Update advertiser Seller preference. The field is omitted when the request names and selects no advertiser, when the advertiser belongs to another account (a sibling account in your organization, or an organization that delegated it), or when Apostra cannot read the advertiser or the decision; the grant list still returns.

Billing modes and the business entity payload

Each sync_accounts entry names a billing mode: agent (Interchange invoices on your behalf; no additional payload needed), operator, or advertiser (the storefront invoices your operator or advertiser directly). operator and advertiser entries require a billing_entity — the AdCP BusinessEntity payload with your legal name and, as applicable, tax/VAT/ registration ids, a postal address, billing contacts, and bank details:
billing_entity.bank is write-only: send it to provide payment coordinates, but it is never echoed back on a sync_accounts or list_accounts response — the seller stores it and confirms receipt without returning it. A storefront only accepts the billing modes it has published support for. An entry naming an unsupported mode returns HTTP 400 with BILLING_NOT_SUPPORTED and details.supported_billing listing the modes the storefront actually accepts:

Payment terms

Payment terms can be requested per seller account, and separately for your whole organization. They are two different settings with different values:
  • Per seller account (sync_accounts). Each entry in a sync_buyer_storefront_accounts call (POST /api/v2/buyer/storefront-accounts/sync) can set its own optional payment_terms. Each call targets one seller storefront (target.storefrontId), so one request can carry different terms for different sellers. Allowed values: net_15, net_30, net_45, net_60, net_90, or prepay. Omit payment_terms to accept the seller’s default terms.
  • Organization level (paymentTerms). One choice for the whole organization, set with Update billing info or the V3 save_billing tool. Allowed values: net_15, net_30, net_45, net_60, or net_90. prepay is not an organization-level value. Apostra uses this choice when it opens a consolidated-billing account for you; see Your organization’s payment terms.
  • The V3 hosted-agent tools cannot set per-seller terms. save_connection has no payment-terms field and there is no V3 sync_accounts tool. The only payment-terms write in the V3 tools is the organization-level save_billing paymentTerms. To request different terms from one seller, use sync_buyer_storefront_accounts or its REST route.
AdCP lets a sync_accounts entry request payment_terms. The protocol does not let a seller silently swap in different terms: the seller accepts the requested terms or rejects the account. The seller sees the requested terms when it reviews the account and can only accept or reject; it cannot edit them. The requested terms go to the seller with the account request:
  • The seller reviews them. Approving the account accepts the terms you requested, and the account then reports them in payment_terms. On a storefront that routes accounts to the seller’s own sales agent, that agent decides instead; see Who decides your account request. There is no counter-offer: if the terms don’t work for the seller, the seller rejects the account.
  • Net 60 or shorter can be approved automatically. Unless the seller has chosen to review every new account, a storefront approves a request for net_60 or shorter terms (or prepay) without a person reviewing it. A seller can lower that limit. A request for longer terms, such as net_90, always waits for the seller to review it, so it can take longer to approve.
  • You can change the terms while the request is pending. Send the same account again with different payment_terms and they replace the earlier ones; that account’s row returns action: "updated" and the seller reviews the new terms.
  • A decided account keeps its decision. Once the seller has accepted or rejected the account, a request naming different terms changes nothing. That account’s row returns action: "failed" with the AdCP error PAYMENT_TERMS_NOT_SUPPORTED, and the account keeps its status and its terms. Other entries in the same request are unaffected. To change the terms on an accepted account, agree them with the seller directly.

Your organization’s payment terms

Your organization chooses the payment terms Apostra asks sellers for: net_15, net_30, net_45, net_60, or net_90. Until you choose, net_60 applies. Set the choice with paymentTerms in Update billing info; it applies to every advertiser in the organization. Like the rest of this section, it is available once requesting terms is available. Every account request for an agent-billed, non-sandbox account carries these terms to the seller, whichever seller it is, unless the request names its own payment_terms. Choosing terms is a go-live step for consolidated billing, so no consolidated-billing buy is placed on terms nobody chose. Until an organization administrator has chosen:
  • buyer readiness shows a Payment terms check (payment_terms) that is not complete, and it blocks go-live when you have sellers on consolidated billing;
  • a seller on consolidated billing shows needs_commercial_setup, and a buy from it is refused with the payment_terms blocker; and
  • direct-billed sellers are not affected.
If you have already connected a seller on consolidated billing, Apostra holds that seller-account setup until you choose terms, then resumes it automatically. Sandbox accounts are not held. Choose terms explicitly, even to keep the default: send the default value itself. In Buyer Setup, net_60 is pre-selected and the button reads Accept Net 60; accepting it counts as choosing, and nothing is recorded until an organization administrator does. Once chosen, the terms can be changed but not cleared, so paymentTerms: null is refused with a validation error and the recorded choice stays in place. If you have not chosen and a media partner is waiting on your terms, the Media Partners page shows Confirm your payment terms. One click records net_60, the default, as your organization’s choice and resumes the held setup. It records the default only; to choose other terms, use Buyer Setup. Only an organization administrator can confirm, and Apostra never records terms for you on its own. Organizations that already had active consolidated-billing seller accounts or buys when this step became required on 11 October 2026 have net_60 recorded as their choice, so nothing is held for them. They can change it like any other choice. When Apostra opens a consolidated-billing account for you with a seller (for example, when you turn a seller on for an advertiser or buy from a seller for the first time), the request asks for your organization’s terms. Direct-billed and sandbox account requests do not carry them:
  • Longer terms can mean more rejections. Sellers carry the credit risk on their accounts, so some decline longer terms. On storefronts Interchange hosts or manages, net_60 or shorter can be approved automatically, while net_90 waits for the seller to review it.
  • Decided accounts keep their terms. Changing your choice applies to accounts opened afterwards. An account a seller has already accepted or rejected keeps that decision and its terms; an accepted account keeps working exactly as before.
  • A seller can refuse your requested terms. The account request then fails for that seller, and the connection reports that the seller does not accept your terms. Review the seller’s terms before explicitly requesting an account on those terms, or leave that seller disconnected. Apostra does not retry the request on the seller’s default terms.
On the Storefront MCP discovery surface, an explicit opaque account_id must belong to the authenticated buyer on that storefront. A missing buyer grant or an ID belonging to another buyer returns the structured AdCP error ACCOUNT_NOT_FOUND with details.reason: "account_not_authorized_for_buyer"; it is not reported as a missing storefront account context. Retrieve an authorized account with list_accounts, or complete the seller’s account-linking flow, before retrying. Buyer Setup returns derived capability verdicts rather than a writable Account mode. Before Organization proof, plan selection, and Terms, the Account can use bounded demo and onboarding surfaces. After those steps it can perform real non-spend work. Spend additionally requires the media-buying product entitlement. Seller-direct transactions need nothing further from Apostra. Consolidated-billing transactions additionally need your organization’s billing details: a payer name, street address, and country, so Apostra can invoice you. They never need a card or an Apostra credit line, because Apostra takes no credit risk on the seller’s media. An organization that already has a verified card or an Apostra credit line on file can keep buying while it adds its billing details. Account holds block every capability. Confirming or changing the buyer operator does not change your WorkOS organization, sign-in, invitations, SSO, account membership, billing company, advertiser, or brand domain.

Destination go-live

Every seller or platform then shows only its own remaining requirement:
  • A credential-free AdCP seller requires no connection step.
  • An official adapter may require a free provider connection, account choice, and advertiser mapping.
  • A seller can be temporarily unavailable even when your connection is healthy.
  • Direct-billed sellers and platforms bill the operator or advertiser and do not use an Apostra rate card or payment method for that route.
  • A seller on consolidated billing requires active media pricing supported by the current pricing engine and your billing details before live spend. Add them in Plan & Billing → Payment & invoices. Until they are complete, the buy is refused with the billing_details blocker, readiness lists BILLING_DETAILS, and commercial.billingDetailsComplete is false. Readiness no longer reports PAYMENT_AUTHORITY or the payment_authority blocker. Treat any blocker value you do not recognize as blocking. A child account automatically uses the media pricing on its billing organization; the account-delegation placeholder does not control that inheritance. Once choosing payment terms is available, your organization must also have chosen them; see Your organization’s payment terms.
The media rate card used to price a buy is separate from the Organization IU Rate Card. Choosing an IU plan is not a buyer-readiness requirement. You can connect destinations, inspect accounts, and view mirrored campaigns without charge. “Can buy now” means the applicable capability verdict is allowed and at least one destination’s actual requirements are complete.