Skip to main content
An agency integration lets one operator run merch for many creators from a single console. One confidential channel.* credential operates a whole fleet of subaccount shops: you onboard creators, browse and publish to each shop, and surface live storefronts — all from one secret. The worked example for this guide is Greenroom, an agency console you can read end to end.
The Channel API requires special access — it is invite only and currently in beta. Your channel must be granted access by Fourthwall, which provisions a dedicated agency-bound channel.* client for it; reach out to request access. See Authentication.

One secret, three faces

The single agency secret authenticates three different ways depending on the call. The secret never reaches the browser — every channel-api and open-api call goes through a server route that mints the token and attaches it. X-ShopId is ownership-checked upstream: a missing or unowned shop id is rejected, so you can only ever act on a shop your agency manages.

The token mint — HTTP Basic, not body credentials

The agency uses the client credentials grant, sending the id/secret as client_secret_basic (HTTP Basic). Posting the secret in the request body returns 401 invalid_client — the single most common first mistake:
Cache the token until shortly before it expires, then mint a fresh one.

Two clients over one token

  • channelApi — attaches Authorization: Bearer <token> only.
  • openApi — attaches the bearer and the X-ShopId header for the target subaccount.

Five features, mapped to the three faces

1

F1 — Fleet home (channel-api)

Identify the connected agency and list its fleet of shops.GET /channel-api/v1.0/channel/current + GET /channel-api/v1.0/shops
2

F2 — Onboard a creator (channel-api)

Create a subaccount shop, invite the owner, and optionally start payout onboarding. The creation response carries the new shop’s publicToken.POST /channel-api/v1.0/shops
3

F3 — Subaccount catalog (open-api)

Browse one shop’s products, scoped by X-ShopId.GET /open-api/v1.0/products with X-ShopId: <subaccount>
4

F4 — Design & publish (two faces)

The load-bearing flow — it touches both faces. See the next section.
5

F5 — Creator storefront (publicToken)

Resolve the shop’s browser-safe publicToken server-side, then read the live shop directly from the browser against the Storefront API — no agency secret in play.PUT /open-api/v1.0/public-token (server) → Storefront API (browser)

F4 — why artwork is registered twice

F4 renders an instant preview on the channel’s bound shop, then publishes on the subaccount. The artwork is registered twice, across two faces: The bound-shop imageId from the preview is not valid for the design-create on the subaccount — that resolves the imageId against the X-ShopId shop, so the publish path must register the media again on the subaccount.
Gotchas the example pins down:
  • The region is template-specific. The renderer rejects an invalid region and returns the valid ones — front for DTG, front_dtf for DTFX, etc. Derive the region from the template’s productionMethod.
  • colors / sizes are case-sensitive against the product’s variant labels, or the render comes back empty. Leave them empty to use all available.
  • publishOnCreate controls whether the product is created PUBLIC or HIDDEN. When off, transition it to PUBLIC via PUT /products/{id}/state after creation.
  • The presigned upload PUT must echo two signed headersContent-Type and x-goog-content-length-range: 0,<size> (the byte length declared in the upload-url request) — or GCS returns 403 SignatureDoesNotMatch.

F5 — the publicToken face

The publicToken is browser-safe. Resolve it server-side (GET /api/shops/{shopId}/public-tokenPUT /open-api/v1.0/public-token) and then read the live shop directly from the browser against the Storefront API — no agency secret in play. The token comes from F2’s creation response (for shops created in-session) or the public-token endpoint (for any managed shop).
Onboarding creates real shops and real payouts. Target staging by default while building, and treat a payout account as pending after the handoff — returning from the returnUrl means the creator left the hosted flow, not that payouts are verified.

Full example

Read Greenroom end to end — a Next.js console where lib/fourthwall.ts holds the credential core (token mint + the two clients) and every Fourthwall call runs through a server route.