A storefront is the seller-side surface in the Scope3 marketplace. It represents your brand, the inventory sources you offer through agentic protocols, and the billing relationship that lets buyer agents transact with you.The seller journey has four user-visible steps, mirroring the in-app onboarding UI:
Verify your company — resolve your brand from the AAO registry, set your operator domain, and auto-verify (or fall back to manual KYC).
Add agents — register one or more inventory sources, each backed by an ADCP-compatible agent. AAO compliance is gated here.
Set up billing(optional) — connect Stripe to receive payouts. Not required for activation.
Go live — confirm readiness and flip the storefront to ACTIVE.
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 — a status query you can call any time to see what gates remain. Surfaced in Step 4 (and re-run server-side at activation).
Each customer has one storefront. There is no customerId path parameter — the storefront is resolved from your API key’s customer context.
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 ADCP-compatible agent
A SALES, SIGNAL, CREATIVE, or OUTCOME agent reachable over MCP or A2A. You’ll need its endpoint URL, protocol, and (for non-OAuth agents) auth credentials.
4
Optional: Stripe account
Required only if you want Scope3 to settle payments through your storefront. Stripe Connect provisioning is gated to non-child customer accounts.
The first thing a seller does is identify their company so Scope3 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.
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.
If no manifest is found, the call returns 200 with { "resolved": false, "builderUrl": "https://agenticadvertising.org/brand" } — point the operator at the builder URL to publish a brand.json.
The domain field is validated against a strict FQDN regex. IP addresses and internal hostnames are rejected to prevent SSRF.
POST /storefront is idempotent — if a storefront already exists for your customer, the existing record is returned instead of creating a duplicate.Then update it with the brand fields from resolve-brand plus your operator domain:
When you set operatorDomain, the API automatically compares it against your customer’s registered customerDomain (and your parent customer’s, if applicable). If they match, operatorDomainVerified flips to true immediately. Otherwise a verification request is sent to Scope3 staff and you’ll need a manual KYC review.The flag is recomputed only when the operator domain actually changes — manual superadmin verifications are preserved across unrelated edits.
Updatable fields on PUT /storefront:name, publisherDomain, plan, status, operatorDomain, brandName, logoUrl. At least one field must be provided.
2
Add agents (inventory sources)
An inventory source binds a named slot inside your storefront to an ADCP-compatible agent. Buyer-side discovery surfaces sources, and media buys flow through the agent attached to each one.
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.
Required when executionType: "agent":type, endpointUrl, protocol, authenticationType. auth is required for API_KEY and JWT agents and must be omitted for OAUTH and NO_AUTH.
Inventory-source credentials (API keys and JWT private keys) are stored in Google Secret Manager 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 stored in Google Secret Manager and never echoed back. The source goes to pending and auto-activates once the agent is reachable with the credential.
{ "authenticationType": "OAUTH" }
Omit the auth field entirely. The response includes an oauth.authorizationUrl you must redirect the operator to. Auth completes out-of-band; the source flips to active once the OAuth callback succeeds.
The OAuth state parameter Scope3 attaches to the authorization URL is opaque, single-use, and carries CSRF entropy bound to your customer + source. Do not decode, modify, or replay it — the callback handler validates state server-side and rejects mismatches. If you proxy the redirect through your own server, forward state byte-for-byte.
JWT private keys are long-lived signing credentials. Treat them like passwords — never log them, never commit them to source control, and rotate immediately if exposed. Submitted material is stored encrypted in Google Secret Manager and never echoed back.
{ "authenticationType": "NO_AUTH" }
Public agents only. The source is created with status active immediately.
Before creating a source, the API checks the agent’s compliance status with AAO. The check returns one of:
passing — proceed.
pending — proceed (logged but not blocked).
not-passing — request is rejected with VALIDATION_ERROR.
not-registered — agent must be registered with AAO first.
If AAO is unreachable the request fails with SERVICE_UNAVAILABLE — retry once it recovers. Superadmins can bypass this gate; bypassed sources include complianceBypassed: true in the response.
The basic plan currently allows one inventory source per storefront. Updates are partial — PUT /api/storefront/inventory-sources/:sourceId accepts any subset of name, description, endpointUrl, protocol, authenticationType, auth, executionConfig, status. Updating auth rotates the stored credential; omitting it preserves the existing one.
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 (optional)
Stripe Connect lets Scope3 settle payments on your behalf. Billing is not a hard blocker for activation — your storefront can go live and serve impressions without Stripe. The readiness endpoint surfaces billing as informational only.Skip this step entirely if Scope3 is not handling settlement. Child customer accounts always inherit billing from the parent and cannot provision their own.
Current platform fee %, additional fees, currency, net days
PUT /api/storefront/billing
Admin-only — update fee config
GET /api/storefront/billing/transactions
Cursor-paginated balance transactions
GET /api/storefront/billing/payouts
Cursor-paginated payouts
POST /api/storefront/billing/account-session
Embedded Stripe Connect session for in-app onboarding UI
GET /api/storefront/billing/accounts
Parent customers — billing status across child accounts
Parent customers can pass ?targetCustomerId=<childId> on every /api/storefront/billing/* endpoint to operate on a child’s billing. Access is validated against the parent/child relationship before each call.
4
Go live
Activation flips the storefront from PENDING to ACTIVE. Buyer agents can only discover and transact against your inventory once you’re live.
{ "platformId": "acme-media", "status": "ready", "checks": [ { "id": "inventory_sources", "name": "Inventory sources", "category": "inventory", "description": "At least one source has been configured.", "status": "complete", "isBlocker": true, "method": "agent", "details": "1 source configured" }, { "id": "agent_status", "name": "Agent status", "category": "agents", "description": "All agents are active.", "status": "complete", "isBlocker": true, "details": "1 of 1 agents are active" }, { "id": "agent_auth", "name": "Agent authentication", "category": "agents", "description": "All agents have been authenticated.", "status": "complete", "isBlocker": true, "details": "1 of 1 agents are authenticated" }, { "id": "billing_setup", "name": "Billing", "category": "billing", "description": "Stripe Connect onboarding complete.", "status": "complete", "isBlocker": false, "details": "Stripe Connect is complete" } ]}
What each check means
inventory_sources(blocker) — at least one source must exist.
agent_status(blocker) — every agent backing a source must be ACTIVE.
agent_auth(blocker) — non-OAuth agents must have a stored credential. OAuth agents are excluded once their token is captured.
agent_connectivity(blocker, only on GET /readiness/compliance) — runs the ADCP comply() test suite against each agent in sandbox mode (60s timeout). Returns per-agent track results and observations.
billing_setup(informational, NOT a blocker) — Stripe is recommended but not required to activate.
Top-level status is blocked if any check with isBlocker: true is not complete, otherwise ready.For a deeper agent connectivity test (full ADCP compliance scenarios in sandbox mode), hit:
The API re-runs readiness server-side before applying the change. If any blocker is still failing, the request is rejected with the failing check descriptions:
Rejection
{ "error": "VALIDATION_ERROR", "message": "Cannot activate storefront: All agents must be active to go live; All agents must be authenticated to go live", "field": "status"}
When activation succeeds, every agent in PENDING status that’s linked through a source is automatically promoted to ACTIVE so buyer traffic can route through it.
`AAO compliance pending` — agent is in registry but tests are still running
This is logged but not a blocker. The source is created and will auto-activate once the agent is reachable. No action required unless the status flips to not-passing.
`Agent must pass AAO compliance testing` — endpoint returned `not-passing`
Visit agenticadvertising.org and check the storyboard test results for your agent URL. Resolve the failing scenarios in your agent implementation, wait for the next test run, then retry source creation.
`Agent must be registered with AAO to connect`
The agent’s endpointUrl doesn’t appear in the AAO registry at all. Register it through the AAO operator dashboard before retrying.
`Cannot activate storefront: All agents must be active to go live`
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.
`Cannot activate storefront: All agents must be authenticated to go live`
A non-OAuth agent has no stored credential. PUT /api/storefront/inventory-sources/:sourceId with an auth block to set one.
`agent_connectivity` failed in compliance check
Look at the compliance array on the failing check — each entry has per-track failureReason, summary, and observations. The most common causes are auth misconfiguration, schema drift between your agent and the ADCP spec, and agent-side timeouts beyond 60s.
Storefront says `operatorDomainVerified: false` even though my domain matches
Verification only runs when operatorDomain is being changed. If you set the domain before the customer’s customerDomain was registered, update operatorDomain to the same value again to trigger re-evaluation, or have a Scope3 admin verify manually.
`Stripe is not configured`
Stripe credentials are missing on the API server. Contact Scope3 support — this is environment config, not a customer-side issue.
Your customer is a child of a parent org. Either provision billing on the parent and inherit, or have the parent call POST /api/storefront/billing/connect?targetCustomerId=<your-id> on your behalf.