Skip to main content
The Seller API has exactly one authentication method: a JWT issued to a signed-in seller. There is deliberately no secret API key on this branch — a credential that could act as a seller without a seller signing in is exactly what the separate token audience exists to prevent.

Two things every request needs

  1. Authorization: Bearer <token> — the JWT returned by login.
  2. X-Spree-Seller-Id: <seller_id> — which seller the signed-in user is acting as.
The only authenticated endpoint that does not need the second is GET /api/v3/seller/me, because that is what tells the panel which seller to name.

Signing in

The response carries three things: the access token, the team member who signed in, and every seller this user may act for.
The refresh token is not in the response body. It is set as an HttpOnly cookie scoped to /api/v3/seller/auth, so a session issued for the seller panel cannot be redeemed on any other surface.

Membership is required, not just credentials

A marketplace’s own staff share the same user class as sellers. Authenticating is therefore not enough: a user who runs no seller is refused with 401, because issuing a token would hand out an audience its holder can do nothing with.

Choosing a seller

A person may run more than one seller — so capability is per seller, and a request that names none has no tenant at all.
Sending a seller ID the caller has no role on resolves to nothing, so it reads as “no such seller” rather than “denied” — which is also what stops the header being used to enumerate the marketplace’s sellers.
A request with a valid token but no X-Spree-Seller-Id header — or one naming a seller the caller does not belong to — is rejected with 403. There is no fallback to a default seller.

Token audiences

Every Spree JWT carries an audience, and each surface accepts only its own: An admin token presented to the Seller API is a 401, and a seller token presented to the Admin API is likewise refused. The refresh endpoint narrows by audience too, so a refresh token minted elsewhere cannot be exchanged for a seller session.

Refreshing a session

No request body and no Authorization header — the cookie alone authenticates the call, and a fresh refresh cookie is rotated in. Membership is re-checked here, so a user whose last seller role was revoked mid-session is refused at their next refresh rather than continuing until the access token happens to expire.

Signing out

Revokes the refresh token server-side and clears the cookie.

Accepting an invitation

Someone invited onto a seller’s team arrives through an emailed link carrying an invitation ID and a token. Both acceptance endpoints are unauthenticated — the link is the credential.
The invited email address is never taken from the request — it always comes from the invitation itself, which is what stops the link being redirected to another address. password sets a new password when no account exists for that address; when one does, the same field is how the person proves the account is theirs.
A wrong token is indistinguishable from an unknown invitation: both answer 404. So does an invitation onto the marketplace’s own staff rather than a seller.

Rate limiting

Sign-in, refresh, provider discovery, and invitation acceptance are all rate limited, and answer 429 with a rate_limit_exceeded code when a client exceeds the window.