> ## Documentation Index
> Fetch the complete documentation index at: https://docs.apostra.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Discovering products on a storefront needs an account

> A storefront answers a brief, a refinement or a proposal request only for an account the calling buyer holds. How to set that account up with sync_accounts, what a wholesale browse shows, and the errors you get without one.

A storefront on Apostra answers product discovery for one account at a time,
and that account must be one the calling buyer holds. This page is for anyone
who calls a storefront's AdCP `get_products` or `request_proposals` directly,
with their own agent or SDK. If you buy through Apostra's own V3 tools, your
advertiser's account is sent for you.

## What needs an account

| Request | Account |
| - | - |
| `get_products` with `buying_mode` `brief` | Required |
| `get_products` with `buying_mode` `refine` | Required |
| `request_proposals` | Required |
| `get_products` with `buying_mode` `wholesale` | Not needed |

A storefront says so in `get_adcp_capabilities`: `account.required_for_products`
is `true`. A storefront that takes its account from a connected advertising
platform account, such as Meta, does not declare it.

## Set the account up first

Call `sync_accounts` on the storefront for the brand you buy for and the
operator that buys for it.

```json theme={null}
{
  "idempotency_key": "account-setup-0001",
  "accounts": [
    {
      "brand": { "domain": "acme-outdoor.example" },
      "operator": "pinnacle-agency.example",
      "billing": "agent"
    }
  ]
}
```

`billing` is required and must be one of the values the storefront lists in
`account.supported_billing` in `get_adcp_capabilities`; `agent` is the value in
this example. The response names the account in `accounts[].account_id` and its
`status`.
Storefronts approve new accounts by default, so the status is usually `active`
at once. A seller can choose to review accounts first; the status is then
`pending_approval` until the seller approves it, and discovery waits until it
is `active`.

Send the account on every discovery request:

```json theme={null}
{
  "account": { "account_id": "sf_8c1d0a" },
  "buying_mode": "brief",
  "brief": "Display and video reaching runners in the United States."
}
```

You can send the brand and operator instead of the `account_id`. The
storefront accepts them only as another name for an account you already
synced. A brand and operator you did not sync, or that another buyer synced,
select nothing, and the storefront reads nothing for them.

## What a wholesale browse shows

A `wholesale` request needs no account. It returns the same public catalog for
every caller, with no prices that belong to one account. A wholesale request
ignores any account or brand it names: the storefront does not check it and it
changes nothing you see. To see prices and discounts that apply to your
account, discover with a brief or a refinement under that account.

## Discounts follow the account

A storefront applies the seller's discounts and buyer instructions for the
brand and operator of the account you discovered under. A brand or operator in
the request body is never used to pick a discount. A request whose brand does
not match its account is refused with `INVALID_REQUEST`.

## When a request is refused

| Situation | Error | What to do |
| - | - | - |
| No account in a brief, refinement or proposal request | `ACCOUNT_SETUP_REQUIRED` | Call `sync_accounts`, then retry with the `account_id`. |
| An `account_id`, or a brand and operator, that is not an account you hold on this storefront | `ACCOUNT_NOT_FOUND` | Check the account with the seller's `list_accounts`, or sync it. |
| An account the seller has not approved, or has suspended | `AUTH_REQUIRED` | Wait for the seller's approval, or ask the seller. |

The storefront checks the account before it reads any catalog or asks any
inventory source, so a refused request returns no products.

A seller who calls its own storefront with its own credential is not a buyer
and needs no buyer account.

## Related

* [Building on Apostra or on AdCP directly](/v3/apostra-vs-adcp)
* [Errors](/v3/errors)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.