Headless and custom stores: serving poppy.json on Next.js, Hydrogen, Medusa, Saleor, commercetools and static hosts Free & Pro

If the front end is yours, discovery is a route or a file. Proxy snippets for Netlify, Vercel, Cloudflare, nginx and Apache, and what a native implementation involves.

Updated October 20, 2026

If you built or control your storefront, nothing stops you being agent-ready today. The discovery file is a route or a static file; the issuer and API are either a provider’s or yours. This page gives the snippets for the common hosts and says what a native implementation on a headless stack involves, as of 16 October 2026. Agent Adapt is a WooCommerce plugin; the snippets here are generic and carry no dependency on it. Agent Adapt is not affiliated with or endorsed by any platform or host named, nor with Sierra or Meta.

Discovery in a few lines

Since 16 October 2026 the protocol says the discovery document speaks for the host that serves it after any redirects, and organization.domain must name that host. A redirect to a provider’s host, which was the earlier route, no longer counts; a redirect that stays on your own host (the apex to www) is fine as long as the document names the final host. So the minimum is a proxy: your host fetches the provider’s hosted document and serves it at /.well-known/poppy.json on your domain.

Netlify, in _redirects in the publish folder; the status 200 makes it a proxy rather than a redirect:

/.well-known/poppy.json  https://hosted-document-address-for-your-store  200

Vercel, in vercel.json; a rewrites entry to an external URL proxies, where a redirects entry would not do:

{ "rewrites": [ { "source": "/.well-known/poppy.json", "destination": "https://hosted-document-address-for-your-store" } ] }

Cloudflare Pages, or anything behind Cloudflare: a Worker on the route for the one path (see Serving poppy.json with a Cloudflare Worker).

nginx: location = /.well-known/poppy.json { proxy_pass https://hosted-document-address-for-your-store; proxy_ssl_server_name on; proxy_set_header Host hosted-document-host; } The Host header is the hosted document’s hostname (agents.getagentadapt.com for Agent Adapt’s hosted Company), which the provider needs to pick the right site.

Apache, with mod_proxy, mod_proxy_http and mod_ssl, in the virtual host (.htaccess does not accept these directives): SSLProxyEngine on and ProxyPass /.well-known/poppy.json https://hosted-document-address-for-your-store

Next.js, in next.config.js, a rewrites() entry with source: '/.well-known/poppy.json' and the hosted document’s address as destination. Or put the file in public/.well-known/poppy.json if you host the document yourself.

Hydrogen (Shopify’s headless framework, on Oxygen or elsewhere): a route for /.well-known/poppy.json that fetches and returns the provider’s document, or returns your own JSON. On your own hosting this is a normal route. On Oxygen, Shopify’s hosting for Hydrogen, we have not confirmed whether Shopify’s platform-level handling of /.well-known/ applies; add the route and test it.

Test with curl -sI https://your-store/.well-known/poppy.json. Whether you proxy or host the file, you want a 200 with content-type: application/json and no location: header.

If you host the file yourself

Then the file must name an issuer and APIs that actually answer, because agents will use whatever it lists. Two options:

  • A provider runs the issuer and API and you publish a file whose auth.issuer and apis point at it. The issuer’s metadata must list your domain in poppy_domains, which the provider does once you add your domain there. Agent Adapt’s hosted Company is such a provider: built and running, in early access by email, and not yet on sale; [email protected] takes requests.
  • You run them. A native implementation, below.

A native implementation on a headless stack

Medusa, Saleor, commercetools, Salesforce Commerce Cloud, Shopify’s Storefront API and the rest already give your front end a product API, a cart and customer accounts. What the protocol adds is a thin layer of identity and consent in front of them, on your domain:

  1. Discovery. poppy.json naming your issuer, and the issuer’s OAuth metadata (RFC 8414) with poppy_domains and dpop_signing_alg_values_supported listing ES256, which section 3.2 has required since 16 October 2026. See What poppy.json is.
  2. Agent verification. Fetch the agent’s client metadata document from its HTTPS Client ID without following redirects, cache it, verify its signed assertion against its published keys, keep a block list. See How your store knows which agent is calling.
  3. Sessions. Issue short-lived Session Tokens bound to the agent’s DPoP key, and verify a signed single-use proof on every call, with a replay cache shared across instances.
  4. Sign-in. A consent page on your domain, OAuth authorization code with PKCE, an optional device-code flow, long-lived Account Tokens the agent can exchange for new Sessions, and a Connected agents page where the customer can disconnect. Refuse staff accounts at sign-in and on every request.
  5. The API. An OpenAPI 3.x description of search, product, policies, cart, orders and addresses, where every call goes through one scope check and a missing resource and someone else’s resource return the same 404.
  6. Checkout. Agents cannot pay under the protocol’s current draft. Issue a single-use link that loads the agent’s cart into the customer’s browser context and lands on your checkout.

The request-by-request sequence, with every field, is in An agent’s first visit. The protocol’s guides page lists the recommended practices for companies. The current draft, 0.2, is at personalagentprotocol.org, Apache 2.0.

Edge caches and the API

Agent API responses carry per-session data and must never be served from a shared cache. Send Cache-Control: private, no-store on them and exclude the API paths from any edge caching rules. Discovery documents are public and can be cached for minutes.

Common questions

Can I run the issuer on a different hostname from my store?

Yes. The protocol identifies the business by its issuer URL, and the draft’s examples put the issuer and APIs on other hosts. The issuer’s metadata must list your store’s domain in poppy_domains.

Does a static site need an API?

Only if it sells something an agent should be able to put in a cart. A static site that is a brochure can publish discovery pointing at a provider’s Company Agent, which answers questions from the site’s content. See Services and bookings.

Is there an SDK?

Not from Agent Adapt. The protocol’s authors have said a reference implementation is expected. Until then, the WooCommerce plugin’s behaviour, documented here, is a worked example.

Does the agent ever see my back-end API keys?

It must not. Your layer calls the back end with your credentials; the agent only ever holds tokens your issuer gave it, bound to its own key.

Still stuck? Email [email protected].