Skip to main content
The v2 API is in active development. The onboarding flow described here may evolve before general availability.

Explore a sample Storefront before signup

You can open Explore a sample Storefront before creating an account. It is a public, stateless walkthrough with versioned, preloaded fictional data. Its Catalog, fictional buyer brief, and approval path are display-only: there are no text fields, uploads, saved changes, buyer messages, pricing actions, or production-system connections. The sample is not a workspace or a Demo Storefront. It does not create an account, tenant, source, or demo lease, and it cannot publish inventory, buy, sell, bill, or contact a buyer. Create a Seller Account and accept the Terms before adding your organization’s material or connecting a production system.

Confirming your company (Media Company signup)

This pre-application step is enabled for a controlled cohort while Apostra validates the underlying research and admission policy. Signups outside the enabled cohort continue directly into the flow described in the rest of this guide, with no gap in access.
Before you reach account setup, Apostra identifies your organization from the work email you signed up with and asks you to confirm it. This is a separate, one-time admission step — distinct from Step 1 “Verify your company” below, which resolves your public AAO brand profile after your account already exists.
  1. Identity proposal. From your email’s domain, Apostra proposes a company name and website: “From acme.com, we think you’re Acme Media. Is that accurate?” Confirming reuses your verified sign-up email domain as evidence of control. Correcting the domain to something else is recorded as an unverified claim — a claimed domain is never treated as proof of ownership, so an unrelated domain does not by itself grant your account any authority over it.
  2. Seller product. Choose Just list or Create an AMC account. Just list uses an agent operated by you, a partner, or another provider. An AMC account includes listing and adds a hosted Merchandising Agent that you train for your business. The choice remains editable after onboarding.
  3. Billing country. You confirm the country of the company that will contract with Apostra — not your personal location. This country is the sole input to the plan currency Apostra derives and displays back to you; there is no currency picker, and an unsupported country never silently falls back to USD. If your country isn’t supported yet, you’re shown an assisted path to contact Apostra directly instead of a dead end.
  4. Terms of Service and Privacy Policy. Baseline platform Terms acceptance and Privacy Policy disclosure happen here, before any setup content. A paid rate card is a separate, later acceptance once you choose a plan.
  5. Research and admission. Confirming starts an automatic background check — normally a few seconds. You’ll see a brief “Checking your details” state; if it runs long, the page tells you it’s still working, and you can safely close it — refreshing the page or logging back in always resumes the same status rather than restarting the question.
Once admitted, your applicable setup workspace already treats company identity as complete. Just-list operators continue to the Agents workspace to connect the agent they or their provider operates; an Agentic Media Company continues to the inventory-source and merchandising steps below. Admission at this stage means your organization may operate a Media Company workspace at all; it is never a marketplace listing, Critical Supply, or Market Maker decision — those remain separate reviews later in the storefront lifecycle. See Confirm Media Company identity for the request/response schema, status values, and error codes behind this step.

Overview

A Storefront is your buyer-facing home on Apostra: the business presence, name, description, and discovery surface buyers use to understand who they are buying from. Your Merchandising Agent runs that Storefront, implements the AdCP media-buy workflow, and draws from the inventory sources you connect.

Choose a commercial package

Signup asks what you are buying from Apostra, and you can change the plan later:
  • Listing — get listed on Apostra, connect an AdCP-compliant sales agent that you or a provider operates, and keep the operational record for campaigns, media buys, creatives, approvals, delivery, and activity. AI Business Rules are available. Saving, enabling, and evaluating AI Business Rules is not an IU-rated activity today; other qualifying activity remains governed by your organization’s accepted IU Rate Card.
  • Listing + Distribution — keep that connected agent while adding self-serve advertisers, public listing distribution and an optional customer CNAME, and customer-branded AdCP and ChatGPT app channels.
Listing + Distribution is offered only when the active Rate Card publishes it. Review and accept the published package price in Plan & billing before it takes effect.
Signup also shows two private contact paths: Enterprise — Listing and Enterprise — Merchandising. Neither is a public or selectable Rate Card plan. Choose Get in touch to discuss either path; your plan, price, and access do not change unless your organization later accepts a separate private offer. This is commercial packaging, not a behavioral mode. The setupIntent field remains a reversible record of the selected signup package for compatibility, but it never suppresses setup steps, navigation, tools, analytics, or unrelated capabilities. Listing keeps operational surfaces and AI Business Rules available and presents Add Listing + Distribution for paid distribution capabilities. Merchandising remains separate and requires a connected source that is ready to supply products your storefront can sell, such as an ad server — a wholesale-capable source that has not finished its own setup does not satisfy this yet. Source treatment remains per source (WHOLESALE, COMPOSING, or BOTH). Who operates a connected sales agent is Source configuration, not a different Listing plan or account profile; a third-party sales-agent source with Listing is simply COMPOSING.

Choose your seller product

Supply-side signup asks which product you want to start with:
  • Just list — list inventory with an agent operated by you, a partner, or another provider. You can connect the agent during setup.
  • AMC account — listing plus Apostra’s hosted Merchandising Agent, which you train for your business. The Merchandising Agent can draw from an ad server, custom modular source, external Agent, or linked Storefront and uses your merchandising guidance to package, price, and sell inventory.
You can change this selection later. It controls which workspaces and setup requirements apply; it does not classify your company permanently, decide how an individual Source is treated, or grant a paid merchandising entitlement. Just list starts by connecting the agent operated by you or your provider; there is no inventory-source prerequisite for that connection. Agentic Media Company setup starts by connecting inventory sources and also gathers the advertiser context that guides the hosted Merchandising Agent. To switch products after onboarding, open Settings → How would you like to sell? and choose Just list or Agentic Media Company. You can also ask Murph to make the change. An integration can make the same audited change by sending operatingMode to PATCH /api/v2/storefront. The update replaces the listing and Apostra-merchandising capability pair together, and the applicable navigation changes without deleting completed setup or changing your plan.
PATCH /api/v2/storefront is a true partial patch: a capability flag you leave out keeps its stored value. PUT /api/v2/storefront is the aggregate update and applies the whole capability object, so a flag you leave out of a PUT is stored as false. Use the PATCH when you mean to change some flags and leave the rest alone.

What you declare vs. what buyers get

Capability is two values, and they can legitimately disagree:
  • configuredCapabilities — the flags you declared. This is what you wrote, and it is the field to compare against when you want to know whether a save would change anything.
  • capabilities — the effective projection buyers see. Derived from your declaration plus your source topology and approval settings.
The derivation rules, all of them observable on the storefront read. Declaring a flag false is never rejected — what differs is whether the effective response reflects what you sent. Declaring a flag true can be rejected: see Approval-routing prerequisite below for the exact rule before assuming every save succeeds.
  • capabilitiesLocked: true — you have ad-server-backed inventory (an embedded sales agent). offersCreativeReview and offersCampaignApproval are effectively on regardless of what you declared — the storefront is the agent buyers address, so those workflows are always live. The lock does not extend to offersProductComposition: it is derived the same way as on an unlocked storefront (merchandising entitlement plus a ready wholesale source or the ambient wholesale pool), so it can still be effectively off on a locked storefront.
  • Product composition off (no ad-server-backed inventory, no adapter) — the storefront routes selling to your external sources on the Agent-supplied path, so no Storefront-owned workflow is advertised: creative review, campaign approval, and product composition are all effectively off even if you declared them on.
  • Product composition on (no ad-server-backed inventory, no adapter)offersProductComposition is on. offersCampaignApproval is derived from mediaBuyApproval (on only when it’s manual) — your approval setting is the single source of truth for whether composed buys queue for review, so declaring the flag does not override it. offersCreativeReview is exactly what you declared.
  • Adapter-routed storefronts — your declared flags are returned verbatim, except for the social-platform adapters (LinkedIn, Meta, Pinterest, Reddit, Snap, TikTok), where the platform owns creative and campaign acceptance end-to-end: offersCreativeReview and offersCampaignApproval are always off regardless of what you declared. offersProductComposition is still returned exactly as declared on every adapter, social or not.
This is why a successful save is not a promise that buyer-facing capability changed. Read capabilities back after a write, not just the flags you sent, and treat configuredCapabilities as the record of your own declaration. setupIntent is a compatibility record of the signup package, never a runtime mode. It does not determine source treatment or hide product functionality.

Approval-routing prerequisite

A save is rejected with a 400 (field-scoped: mediaBuyApproval for media-buy approval, creativeApproval for creative review) under one rule, applied independently for each of the two approval kinds:
On an existing, non-adapter-routed storefront, if this write results in the approval setting (mediaBuyApproval or creativeApproval) being manual and the matching capability (offersCampaignApproval or offersCreativeReview) being effectively true, the write is rejected — unless that exact pair (approval already manual and capability already effectively true) already held immediately before this write, or routing already resolves for that kind: either you have an active primary approval-routing policy saved for it, or — when none is saved — the default routing to active organization admins resolves. Routing is opt-out, not opt-in: a storefront with no saved policy is still covered as long as an active organization admin exists to receive it.
That predicate is the whole rule — the examples below illustrate it, they do not define when it can or cannot fire:
  • Plain storefront, turning a workflow on for the first time, with no routing at all. Product composition is effective, creativeApproval is already manual, offersCreativeReview goes from false to true in this write, there is no saved creative-review policy, and no active organization admin exists to fall back to → rejected.
  • ESA-backed storefront, approval-setting transition. offersCreativeReview is always effectively true on an ad-server-backed storefront, but if a separate write changes creativeApproval from auto to manual and routing does not resolve for creative review (no saved policy and no active organization admin), it is still rejected — the capability’s value never changed, but the (approval, capability) pair became newly (manual, true) together.
  • Already active — resaving is a no-op. If mediaBuyApproval is already manual and offersCampaignApproval is already effectively true, resaving the same values does not re-trigger the check, because that pair already held before the write.
If you have an active organization admin, default routing already covers you; otherwise, configure a primary approver before turning a workflow on for the first time or before switching its approval setting to manual. (Source: apps/api/src/services/v2/storefront.service.ts:1904-1968; routing check: apps/api/src/services/storefront-sources/approval-routing.ts:917-968.) For organizations using Just list or Agentic Media Company, the Storefront journey has four user-visible steps, mirroring the in-app onboarding UI:
  1. Verify your company — resolve your brand from the AAO registry, set your operator domain, and auto-verify (or fall back to manual KYC).
  2. Connect inventory sources — register one or more inventory sources: an external sales agent, your own ad server with Apostra-managed sales-agent plumbing, or another Storefront.
  3. Set up settlement and payouts — confirm the Seller Account currencies used for settlement, then add payout bank details so Apostra can pay you by bank transfer. Currency is part of go-live readiness. Payout details are required to receive disbursements for normal Seller Accounts, but they never block launch: funds accrue until the details are added. They are optional for official Apostra sales-adapter Seller Accounts that already operate under a downstream platform settlement agreement. Seller-cleared settlement for normal Seller Accounts is coming later and is not configurable today.
  4. Go live — satisfy every current readiness requirement, including transaction proof for each active path in the compatibility-named publish_validation check. A third-party Sales Agent’s current-revision proof is reusable across its Sources; an uncovered Source can run the public validation skill. The derived status becomes live automatically while the storefront is not paused; Apostra review remains a separate prerequisite for public buyer discovery.
A few helper endpoints support these steps but are not standalone “steps”:
  • POST /resolve-brand — looks up your brand in the AAO registry. Used inside Step 1 to pre-fill the form.
  • GET /discover-agents — surfaces agents AAO knows about for your domain. Used inside Step 2.
  • GET /readiness — the canonical status projection you can call any time to see what gates remain.
The AdCP specification and AAO registry define the protocol, registry records, storyboards, and validation semantics. This guide explains how Apostra uses those signals during setup: AAO registration blocks connecting an external agent source; AAO compliance is surfaced as an advisory warning; publisher adagents.json authorization is surfaced as an advisory setup/product signal today; and marketplace listing is a separate Apostra review step after activation.
Each seller account receives one storefront automatically when the account is provisioned, and each storefront can connect one or more inventory sources. There is no customerId path parameter — the storefront is resolved from your API key’s account context.

Using Apostra app

You do not need to create a storefront before starting setup in Apostra app; it already exists when your seller account is ready. Open Business profile, choose Build my profile, and tell Murph about your business, inventory, channels, regions, and buyer-facing pitch. Murph will propose the profile for your confirmation. The remaining setup areas then guide you through connecting inventory, setting your selling rules, testing the storefront, and resolving readiness blockers. Buyer Setup and Seller Setup share the same status, progress, and operator editing pattern. Seller Setup then adds storefront-only tracks for inventory, publisher authorization, settlement, and Get paid; the last of those stays visible without being counted as a launch blocker. Setup time depends on the inventory sources you connect, their authorization and compliance state, and whether your account is ready for billing and activation; Apostra does not promise a fixed setup time. Use the API flow below only when you are integrating programmatically.

IU plan during the staging pilot

The Organization IU Rate Card is published in staging for a controlled pilot and visible only to invited organizations. Public seller signup remains closed until the same iu-rate-card-pilot flag is rolled out globally. Invited staging organizations see the exact Rate Card revision on their next eligible login; after global rollout, new organizations see it during signup as well. Accepting it creates an immutable record of the exact revision and plan accepted. An admitted published activity may then draw from the accepted IU balance and appear as usage during the pilot. Monetary charging, invoices, payment collection, renewal charging, and separately controlled entitlement enforcement remain off. New Rate Cards show exactly three published activities: Brief response (1 IU per completed Apostra merchandising cycle), Enhanced Reporting (4 IUs per exact connected account per billing period after its control is enabled and its existing reporting subscription completes a successful sync), and Interchange media buy (1 IU per qualifying non-social buy per billing period with positive impressions or spend). The accepted version remains the authority; earlier accepted Rate Cards keep their historical activities. You can instead Continue without a paid plan or Decide later. Continuing without a plan suppresses the automatic login prompt only for that exact Rate Card revision; deciding later allows it to appear again on the next login. The manual Choose an IU plan action remains available under Settings → Plan & Billing while the offer is current. These plan choices are separate from the payout details required for Apostra-cleared Seller Account settlement. Plan & Billing shows only public plans that cover every active product in the billing organization. For a Seller Account, the choices also follow the current Storefront operating mode: Listing accounts receive listing plans, while Agentic Media Companies can choose listing or merchandising plans. Buyer, Seller, and Partner products in the same organization must all be covered by one plan; Apostra will prepare a targeted offer when no public plan covers that combination. Existing accepted plans remain in effect until the organization accepts different terms.

Who this is for

  • Publishers and sales houses connecting their inventory to agentic buyers
  • Retail media networks exposing on-site or off-site inventory through AdCP-compatible agents
  • Any seller who wants buyer agents (e.g. Apostra, Claude, custom buyers) to be able to discover and transact against their inventory

Prerequisites

1

Apostra API key

Generate a key at app.apostra.com/user-api-keys. Keys start with scope3_ and authorize all storefront endpoints.
2

A registered brand on AAO

Your brand should have a brand.json published and resolvable through the AAO registry at agenticadvertising.org. If you don’t have one yet, the resolve-brand call returns a builderUrl that points you to the registry’s brand builder.
3

At least one inventory source

An external AdCP-compatible sales agent, an operator-owned ad server, or another Storefront. For external agents, you’ll need the endpoint URL, protocol, and (for non-OAuth agents) auth credentials.
4

Optional: payout bank details

Required for Apostra-cleared settlement. Have your bank details ready — beneficiary name and address, account number or IBAN, one bank identifier (Fedwire/ABA routing number, CHIPS ABA, SWIFT-BIC, or local bank code), and the currency your account accepts. Accounts under an organization inherit billing from the organization and do not set up their own. Seller-cleared settlement for normal Seller Accounts is not configurable yet.

Onboarding flow

1

Verify your company

The first thing a seller does is identify their company so Apostra can pull their brand profile from AAO and validate the operator domain. This step combines a brand lookup, a storefront update, and an automatic operator-domain verification check.

1. Resolve your brand (helper)

Look up your brand in the AAO registry to grab the canonical brand name and logo URL. This call has no side effects — it’s only used to populate the storefront update payload.
Response (resolved)
If no manifest is found, the call returns 200 with { "resolved": false, "builderUrl": "https://agenticadvertising.org/brand" }.What if my brand isn’t found? A resolved: false is not an error and does not block you — it just means you haven’t published a brand.json yet. The storefront shows no resolved brand logo in that state; it never substitutes a logo inferred from your website or a third-party enrichment service. Publish one at the builderUrl (or host your own at /.well-known/brand.json) and re-run resolve-brand; we read it live. Your brand.json is your own identity document — we read it, we never own it. See Identity documents for what it declares and how it differs from publisher authorization (adagents.json).
The domain field is validated against a strict FQDN regex. IP addresses and internal hostnames are rejected to prevent SSRF.

2. Write the brand fields onto your storefront

Seller account provisioning creates this storefront record automatically. You can retrieve it with GET /storefront. POST /storefront remains idempotent for programmatic recovery and returns the existing record rather than creating a duplicate:
POST /storefront is idempotent — if a storefront already exists for your account, the existing record is returned instead of creating a duplicate.operatorDomain is the canonical domain this storefront operates as and the identity buyers and AAO matching use for the storefront. It can differ from the account’s registered customerDomain, and it can be left unset during setup if the operator is not known yet. A storefront cannot go live until an operator domain is set and verified. publisherDomain is optional storefront metadata and should not be used as the matching key for cross-publisher storefronts.Then update it with the brand fields from resolve-brand plus your operator domain:
Response
When you set operatorDomain, the API first checks for an exact match against an approved customerDomain. If it does not exactly match, Apostra checks the alias/rebrand evidence path below. An Apostra verification request is needed only when neither path verifies the operator domain automatically.If your storefront operates under an alias or rebrand domain, such as an operatorDomain that differs from your team’s email domain, keep the canonical operator domain you want buyers to see. Apostra can auto-verify the alias when your registered account domain is already approved and trusted AAO or brand.json evidence connects the account domain and requested operator domain to the same organization or ownership chain. Useful evidence includes AAO registry org linkage, brand.json authoritative_location/house portfolio entries, and authorized_operators. AAO TXT records, /.well-known/adagents.json, AAO Partner membership, and website redirects help Apostra review the request, but a redirect is not ownership proof by itself.Your account domain is approved first, and its approval gates everything else. Approve it by activating a member whose email matches that domain, or by requesting Apostra attestation for it. Until the account domain is approved, alias and rebrand evidence is not evaluated at all — so an unapproved account domain, rather than your published evidence, is a common reason an alias operator domain stays pending.The operator_domain readiness check names which case applies and who acts next:The last row is not a finding about your evidence: your published evidence may already be correct, and there is nothing for you to fix.The account customerDomain and storefront operatorDomain are intentionally separate fields. Updating customerDomain syncs the storefront operator domain only when the storefront has no operator domain yet or is still mirroring the previous account domain and has no populated operator-identity profile. If the storefront has an explicitly different operator domain, or changing a mirrored domain would clear its description, channels, membershipStatus, or website, the API preserves the storefront domain. Change it directly with PUT /storefront, where you can resupply the new operator’s profile or explicitly confirm the reset.
description, channels, membershipStatus, and website describe the current operator identity. When operatorDomain changes, the API refuses to silently clear any populated values among those fields. The validation response lists the affected fields.Either resupply valid values for the new operator in the same PUT, or pass "confirmOperatorDomainProfileReset": true to clear the unprovided values. Explicitly resupplied fields are preserved or replaced; an unchanged operatorDomain does not reset anything and needs no confirmation.
Common identity fields on PUT /storefront include name, publisherDomain, operatorDomain, brandName, logoUrl, logoBackground, description, channels, membershipStatus, and website. The endpoint also accepts the storefront configuration fields in the API reference. Confirmation fields alone do not count as an update; at least one mutation field must be provided.PUT /storefront also accepts subtitle, supportUrl, privacyUrl, and termsUrl — a short tagline and support/privacy/terms-of-service URLs for this storefront. Unlike website, these are not tied to operatorDomain identity and are never cleared by an operator-domain change. Every marketplace channel listing (the ChatGPT app, a future Claude plugin) projects these facts read-only instead of collecting a separate copy per channel — see Create a white-label ChatGPT app.
2

Connect inventory sources

An inventory source connects a named slot inside your Storefront to something your Merchandising Agent can draw from: an external ADCP-compatible sales agent, an operator-owned ad server with Apostra-managed sales-agent plumbing behind it, or another Storefront. Buyer-side discovery surfaces your Merchandising Agent as the ADCP actor for the Storefront, and discovery or media-buy calls route through the active source behind it.

1. Discover agents (helper)

Optional but recommended: see what AAO already knows about your domain. This proxies AAO’s operator and publisher endpoints plus your .well-known/adagents.json.
The x-aao-api-key header is optional. Without it you only get the public registry view. Pass it to also surface storyboard compliance status for agents you operate.
Response
Responses are cached server-side for 2 minutes per (domain, key fingerprint). Pass &refresh=true to force a re-fetch.

2. Register an inventory source

Required when executionType: "agent": type, endpointUrl, protocol, authenticationType. auth is required for API_KEY, JWT, and BASIC_AUTH agents and must be omitted for OAUTH and NO_AUTH.
Inventory-source credentials (API keys, Basic usernames/passwords, and JWT private keys) are encrypted at rest and only referenced by an opaque auth_secret_ref in the database. They are never echoed back in API responses (the response surfaces authConfigured: true instead). Never log, screenshot, or commit raw credentials to source control. Rotate immediately if a credential is exposed.
Token formats bearer, apikey, and api_key are all accepted. The token is encrypted at rest and never echoed back. The source goes to pending and auto-activates once its credential is configured. Reachability is reported independently by source health and connectivity checks.
Response
AAO is checked at connect time and by the readiness projection, but the only hard AAO gate is connect-time registration. Connect-time requires that the agent is registered with AAO; failing or pending agents can still be connected. In readiness, AAO compliance is informational — a non-passing verdict is surfaced as a prominent warning but does not block transactions.The source still must be operational — the compatibility-named agent_status readiness check (see Step 4) reads the inventory source’s canonical lifecycle and is a blocker for third-party sources. The connection sidecar and legacy adcp_agent.status value are not separate storefront lifecycle signals. AAO compliance (the agent_connectivity readiness check) is advisory: a non-passing verdict surfaces for review and does not leave the storefront blocked. Determining who may sell which publisher inventory stays a per-publisher authorization question against the publisher’s own adagents.json, not this compliance score. The connect-time AAO registry gate runs uniformly for every caller — there is no SuperAdmin bypass.
Seller Accounts can connect as many external AGENT inventory sources as needed — no per-plan cap is enforced today. Ad-server-backed inventory sources (MANAGED_SALES_AGENT) are slot-exempt regardless of plan.Updates are partial — PUT /api/v2/storefront/inventory-sources/:sourceId accepts any subset of name, description, endpointUrl, protocol, authenticationType, auth, status. Updating auth rotates the stored credential; omitting it preserves the existing one.

3. How buyers discover this storefront

Once a Storefront is transacting, buyer discovery can surface its Merchandising Agent as a first-class ADCP sales agent with ID storefront-{platform_id}, where platform_id is the Storefront’s public platformId slug. Buyers call the Storefront surface; they do not target inventory source IDs directly in buyer discovery.get_products behavior depends on the storefront mode:
  • Composition — the Merchandising Agent composes buyer-facing products from active ingredient sources plus the active operating instructions.
  • Passthrough — the Merchandising Agent proxies get_products to an active source and returns the upstream products with Storefront identity overlaid.
Matching buyer instructions are resolved at get_products time using operator domain, brand domain, and optional country. Storefront-built storefronts apply them during composition; Agent-supplied storefronts apply them as response overlays, including discounts and notes. Without at least one active source, buyer get_products has nothing to compose from or proxy to.
Execution-specific configuration (per integration knobs — e.g. ad-server adapter settings for Apostra-managed ad-server sources) lives in typed fields per integration type, not in a generic config bag. New integration types add their own typed fields rather than overloading a polymorphic blob.
Ad-server-backed inventory sources (executionType: "MANAGED_SALES_AGENT") wire your Storefront to one of four operator-owned ad-server adapters. Apostra manages the AdCP plumbing behind your ad server. Pick one when creating the connection via POST /api/v2/storefront/esa:Only non-secret display fields (login, environment, default advertiser/demand-partner id) are stored on the connection row so the UI can render “connected as …”. Rotating credentials on a live ad-server source preserves products, principals, and sync history via PUT /api/v2/storefront/inventory-sources/{sourceId}/adapter-config.
Some storefronts route directly to a wired provider adapter rather than an inventory-source sales agent. Supported adapter provider values are amazon, audiostack, google, meta, pinterest, reddit, snap, spotify, and tiktok.Delegated OAuth for these adapter storefronts uses the shared adapter callback path:
Register the same path on staging when testing, for example https://api.staging.apostra.com/oauth/adapters/snap/callback.Reddit access tokens expire after one hour. Apostra requests permanent authorization and uses Reddit’s refresh token to renew access automatically. If an existing Reddit connection reports expired credentials after one hour, reconnect it once in Settings → Connections; new and reconnected grants then refresh automatically.
For FreeWheel and SpringServe, prefer the storefront credential screen for passwords and tokens rather than pasting secrets into chat. Murph can send the operator directly to the secure form with /{accountId}/storefront?tab=sources&connectAdServer=freewheel or /{accountId}/storefront?tab=sources&connectAdServer=springserve. That link opens Inventory sources, launches Connect ad server, and preselects the right adapter. Murph can then wait for submission, list the ad-server sources to find the new or updated connection, and run POST /api/v2/storefront/esa/{esaId}/test-connection to verify that the upstream source can authenticate.For testing, use a temporary API token when the ad server supports one. For production, the credential pair is usually better because the upstream source can mint and refresh short-lived tokens automatically. In either case, Apostra stores only non-secret display fields; the upstream source holds the encrypted secret.

Uploading setup documents to Murph

Murph can use uploaded PDFs, decks, spreadsheets, images, and text documents during storefront setup. Use this for brand books, media kits, operating instructions, rate cards, do-not-air lists, and other materials that would otherwise need to be pasted into chat.Uploaded documents are summarized instead of copied back verbatim. The document-processing status includes:For brand books, Murph can identify brand.json candidates such as name, website URL, colors, fonts, tone, tagline, contact details, and disclaimers. Logo images can be uploaded to AAO for review; pending uploads are not public and are not written into brand.json until AAO approves and lists the /assets/brands/... URL. Other assets still need public hosted URLs before they can be used in brand.json.
Murph can draft and preview brand.json fields from an uploaded brand book, then compare those fields against the current AAO brand.json state and publish the confirmed manifest to AAO for your verified storefront operator domain. Uploaded logo images can be sent to AAO review from Murph; only approved AAO asset URLs or other public HTTPS URLs are written as logo or asset entries.
Google Ad Manager does not require the publisher to paste a password or API token into Apostra. Apostra creates a service account dedicated to your account and returns its email address from POST /api/v2/storefront/esa/service-account. The publisher grants that service-account email access inside their GAM network, then Apostra provisions the ad-server-backed source with the publisher’s numeric network code.The operator-owned part of the flow is:
  1. Call POST /api/v2/storefront/esa/service-account and copy the returned serviceAccountEmail.
  2. In Google Ad Manager, go to Admin → Global settings → Network settings → Add a service account user.
  3. Enter the service-account email returned by Apostra.
  4. Grant a role that can read inventory and traffic campaigns, such as Trafficker or a least-privilege custom role with equivalent API permissions.
  5. Wait a few minutes for the grant to propagate.
  6. Create the ad-server source with POST /api/v2/storefront/esa and body { "type": "google_ad_manager", "networkCode": "12345678" }.
If the probe returns ADAPTER_PERMISSION_DENIED, verify that the exact service-account email was added and wait a minute or two before retrying. If it returns ADAPTER_NETWORK_NOT_FOUND, the network code is likely wrong.

GAM buyer-routing default advertiser

For Google Ad Manager managed-sales-agent sources, Storefront can clear the Default GAM advertiser setup blocker through the API. List cached advertiser records with GET /api/v2/storefront/esa/{esaId}/gam/advertisers, or create or find the intended catch-all advertiser with POST /api/v2/storefront/esa/{esaId}/gam/advertisers/ensure. Then set the tenant default with PUT /api/v2/storefront/esa/{esaId}/gam/default-advertiser using the returned advertiser.id.This flow configures the upstream sales-agent tenant directly. Operators do not need to open the embedded sales-agent UI to set the default GAM advertiser.Keep detailed GAM UI wording anchored to Google’s own support documentation; Apostra docs should describe the contract we own, the service-account email we return, and the role/permission requirements we need.
Sources can’t be deleted while their backing agent has non-terminal media buys (ACTIVE, PAUSED, PENDING_APPROVAL, or INPUT_REQUIRED). Cancel or terminate those first.
3

Set up billing (conditional)

Payout details on file let Apostra settle payments on your behalf: Apostra collects from the buyer, deducts the configured fees, and pays you by bank transfer in your payout currency. Whether billing is required depends on the Seller Account execution path:
  • Optional only for an official Apostra sales-adapter Seller Account on an existing downstream platform settlement agreement. A third-party sales agent or Agent-supplied (finished-product) source does not qualify.
  • Required to get paid for every normal Seller Account, but never required to go live. Apostra clears every normal Seller Account buy today; without payout details, funds still accrue against each booking, but Apostra has no way to disburse them. The readiness check billing_setup returns isBlocker: false in every state — it is advisory, not a go-live gate. An active source that explicitly lacks agent billing support still blocks readiness (a different check, interchange_billing_support).
If billing is optional and you skip it, only official sales-adapter buys on the existing downstream platform agreement can operate. Apostra does not clear those media payments. Seller-cleared settlement is not yet configurable for normal Seller Accounts.
Accounts under an organization inherit billing from the organization by default. A child-account administrator cannot set up or change a payout destination; a parent administrator can create a child-specific destination for a direct Seller Account.

1. Save payout details

Enter your bank details in Plan & Billing → Payouts, or via the API:
accountNumber takes a bank account number or an IBAN; bankIdentifierType is one of FEDWIRE_ABA, CHIPS_ABA, SWIFT_BIC, or BANK_CODE, with the identifier itself in bankIdentifierValue. The account number is encrypted at the application layer before storage and used only to execute payouts; the account number is write-only and never displayed after save. See Set payout details for the full contract.

2. Confirm what’s on file

Response

Other billing endpoints

Organization admins can pass ?targetCustomerId=<accountId> on billing endpoints to operate on a direct Seller Account’s billing. Access is validated against the organization/account relationship before each call.
Apostra no longer uses Stripe for Seller Account payouts. Enter your bank details once (above) to keep Apostra-cleared settlement on your media buys — details held by Stripe cannot be migrated.
4

Go live

A storefront has no stored PENDING or ACTIVE lifecycle state. Its effective status is always derived from isPaused, archive state, and the current readiness checks. Buyer agents can transact only when that projection is live. Public marketplace discovery has one additional human-review gate: transaction-ready Storefronts remain pending marketplace review until an Apostra admin lists them.

1. Confirm readiness

GET /api/v2/storefront/readiness computes every current requirement and the effective status. Call it any time during onboarding or operation to see what’s missing.
Response
Every check also carries a requirement classification so you always know what a checklist item actually demands of you:
  • hard — must be resolved before the storefront can go live. Matches isBlocker: true.
  • soft — advisory: improves outcomes but never blocks.
  • platform_default — the platform applied a sensible default on your behalf; the appliedDefault field states the value in plain terms and how to change it. These are visibility items, never tasks.
The classification is path-aware: which checks appear, and whether each blocks, depends on source treatment and the capability needed for that action. A commercial plan choice does not hide setup checks or unrelated surfaces.
  • publish_validation (blocker; compatibility id) — every active transaction path needs proof. A third-party Sales Agent Source reuses the canonical media_buy_transaction assertion from that Agent’s exact current production revision; credentials, account mapping, reachability, and health remain Source-specific. In Required to go live, choose Run transaction validation to open the Test section for the exact Agent and inventory source that still needs proof. If an active Agent source is not yet linked to a registered Agent, Apostra opens Source diagnostics for that source so you can create or attach the Agent before retrying. If multiple active Agent connections match, select the connection to use or remove or reconcile the extra connections before retrying. You can also run the public transaction validation skill on that Source or ask the Agent owner to provide proof. A seller-owned no-spend sandbox test or successful live buyer media buy can still cover a Storefront-local path. An already-activated Source keeps its historical onboarding completion while current implementation health, Source health, and quarantine govern ongoing operation. Managed-only Storefronts report complete because Apostra operates that path.
  • publisher_domains (blocker) — every storefront declares at least one publisher domain so buyers know what inventory is being sold. The operator domain identifies the company operating the storefront and may be different. adagents.json authorization is shown separately as the advisory publisher_authorization check and never blocks transactions.
  • product_publisher_domains (advisory during rollout) — every active product should map to one of the storefront’s declared publisher domains. Missing mappings and undeclared domains warn while older catalogs are backfilled; adagents.json authorization is separate and also advisory.
  • approval_settings (platform default) — how buyer submissions are handled on Apostra-managed sources. Never a task; appliedDefault names the current posture and how to change it.
  • inventory_sources (blocker) — at least one source must be connected. Buyer-facing get_products still requires at least one active source: Storefront-built storefronts need active ingredient sources, and Agent-supplied storefronts need an active source to proxy.
  • agent_status (blocker; compatibility id) — every non-disabled external-agent inventory source must have canonical source status ACTIVE. No copied sidecar or legacy agent status can independently block it. This gates go-live; AAO compliance does not (see agent_connectivity).
  • agent_auth (blocker) — non-OAuth agents must have a stored credential. OAuth agents are excluded once their token is captured.
  • agent_connectivity (informational, surfaced on GET /readiness/compliance) — reads each agent’s AAO compliance verdict and returns per-agent track results and observations. A non-passing verdict surfaces as a prominent warning but does not block going live. See Identity documents.
  • billing_setup (advisory, never a go-live blocker) — payout details are optional only for the official Apostra sales-adapter compatibility path; the check returns status: optional with isBlocker: false and the external-agreements warning. They are required to get paid for every normal Seller Account, including third-party sales-agent and Agent-supplied (finished-product) sources — but not required to go live: the check returns status: missing with isBlocker: false until payout details are on file, and the Seller Account can activate and transact in the meantime. Funds accrue against every Apostra-cleared booking either way; Apostra just can’t disburse them until payout details are added. This projection is the same in non-production, so an account without payout details is never shown as billing-ready.
Top-level status is blocked if any check with isBlocker: true is not complete, otherwise ready. A check with status: optional is treated as not required.

Programmatic Agent validation

Use the exact Agent returned by V3 get({ kind: "agent" }) and follow its versioned validationSkill, or fetch the always-current skill directly from its stable alias:
Choose an available profile. The transaction profile creates an owned-inventory Advertiser with sandbox: true, resolves the authenticated Media Company’s own Seller, and uses the ordinary V3 Advertiser, Campaign, Creative, Proposal, MediaBuy, and delivery tools. It may prepare temporary no-spend sandbox resources, then stops at a server-issued confirmation before staging a media buy and again before activating the sandbox campaign. Review each no-spend action and confirm it from the exact Agent page handoff to continue the same run. Do not reuse an expired, cancelled, or consumed confirmation; start a new run instead. Profiles shown as unavailable cannot be started until they have an executable fixture and confirmation path. Do not substitute Murph test wrappers, V2 api_call, or the retired standalone Test Runs surface.The brief-only profile uses public save_connection to enable the exact Seller for its fresh sandbox Advertiser before discovery. Its reverse cleanup restores that advertiser preference to DEFAULT before archiving the Advertiser; it does not change account-level Seller selection.After execution or a stop, read get({ kind: "agent", include: ["validationRuns", "diagnostics"] }) and the exact Source diagnostics when Products were Source-attributed. A validation run is evidence for the Agent revision it names and records its cleanup result; it is not itself a certification claim.For a deeper agent connectivity test (full AdCP compliance scenarios in sandbox mode), hit:
This may take up to 60 seconds.

2. Go live or resume buyer intake

When every hard requirement is complete and the intake hold is still set, the Seller Setup page shows Go live (or Resume new business for a storefront that was live before). The action clears only the canonical intake hold and then reloads readiness. The page does not present the storefront as live until that write succeeds and the refreshed canTransact projection is true.
Clearing the canonical isPaused intake hold does not claim the storefront is ready. The write succeeds, and the response still projects blocked with the current failing checks until every hard requirement passes. The intake hold controls buyer discovery, new buys, and buyer edits; it does not pause or resume campaigns already delivering in your ad server.
Response
When the last hard requirement becomes complete, the same storefront without an intake hold projects live automatically. If a future requirement is added or current evidence fails, it projects blocked automatically without rewriting isPaused or an adcp_agent row.

3. Marketplace review

The marketplace review state is independent from the derived storefront lifecycle:Apostra reviews newly live Storefronts before listing them. This keeps test Storefronts and unreviewed sellers out of the broader marketplace without blocking the operator’s own setup work.

Lifecycle states

Allowed transitions: PENDING ↔ ACTIVE ↔ DISABLED (you can’t go straight from DISABLED to PENDING).

Troubleshooting

This is logged but not a blocker. The source is created and will auto-activate once its authentication requirements are configured. Reachability is reported independently; no action is required unless source health flips to not-passing.
This is an advisory warning, not a source-creation or activation blocker. Visit agenticadvertising.org and check the storyboard test results for your agent URL. Resolve the failing scenarios in your agent implementation so the registry verdict improves and marketplace review has a clean signal.
The agent’s endpointUrl doesn’t appear in the AAO registry at all. Register it through the AAO operator dashboard before retrying.
Your agent record is PENDING. Most often this means the auth credential hasn’t been verified yet. Re-submit the source with a fresh auth block, or for OAuth agents make sure the OAuth callback completed.
A non-OAuth agent has no stored credential. PUT /api/v2/storefront/inventory-sources/:sourceId with an auth block to set one.
Look at the compliance array on the check — each entry has per-track failureReason, summary, and observations. This check is informational for activation, but it is still useful debugging signal. The most common causes are auth misconfiguration, schema drift between your agent and the AdCP spec, and agent-side timeouts beyond 60s.
Matching the registered customerDomain is not enough by itself — the account domain must also be approved by active-member email ownership or Apostra admin attestation. Same-value operatorDomain updates preserve the current verification state; have an Apostra admin approve the account domain or change the storefront to the correct operator domain.
An account inherits its organization’s payout configuration. Only a parent organization admin can create or change a direct child Seller Account’s destination. In Plan & Billing → Payouts, select the child Seller Account; through REST, pass ?targetCustomerId=<account-id>. A child-only admin cannot create an account-specific payout destination.

Next steps

  • Prepare inventory source inputs — when a source needs inputs supplied separately, identify where avails, products, CRM context, creative formats, properties, execution, and reporting come from; a complete external-agent setup can skip it
  • Storefront API Reference — full endpoint reference for storefront, billing, and inventory source endpoints
  • Authentication — API key and OAuth flows
  • Storefront object guide — how buyer agents see your storefront once it’s live (discovery, credentials, sources)