Authentication
Artos agent commerce uses three credential classes. The single most common
integration bug is mixing them: the API identity guard prefers X-API-Key over
a bearer, so a buyer-bound call that sends both resolves as the platform
identity and the buyer (and their spend caps) are never loaded.
The load-bearing rule. On buyer-bound calls — crypto
prepare_checkout_payment, crypto/complete_checkout, and every/account/mcptool — send the buyer OAuth bearer only. Never attachX-API-Keyto those calls. Everything else (catalog, cart, checkout create/update, card completion, storeget_order) uses the platform key.
On Connect the bridge applies this rule for you. On the Build track the
@artos-commerce/ucp-client SDK applies it too
(UcpClient sends the buyer bearer only on buyer-bound calls and relays a 401
via onAuthChallenge) — but the SDK does not acquire or refresh the bearer.
Obtaining it through the OAuth flow below is still yours.
Credential classes
| Class | How obtained | Used for |
|---|---|---|
Platform X-API-Key | Seeded platform credential (ck_artos_agent.…) — the bridge holds it | Catalog, cart, checkout create/update, store get_order, card complete_checkout |
| Buyer OAuth bearer | OAuth 2.1 + PKCE consent via My Artos | Crypto prepare_checkout_payment + complete_checkout; all /account/mcp tools |
| AP2 mandate | Minted as a compact ES256 JWS (bridge mints it on Connect) | Authorization over the priced checkout terms — not a payment rail |
The merchant client_credentials key is a fourth, store-owned variant of the
platform key — see For merchants. For how to obtain a
cross-store platform key, see Platform API keys.
Do you need CIMD? Only if you run the buyer OAuth flow (the Shopping agent path). On Connect the client (Claude, Cursor) brings its own CIMD; catalog crawlers and checkout handoffs never touch buyer OAuth, so they need none.
OAuth 2.1 + PKCE (buyer connect)
The buyer connects once and stays connected (~30 days) because the client silently swaps an expired access token for a fresh one using a rotating refresh token. Access tokens are short-lived (default 1h).
Discover the Authorization Server
curl https://api.artos.sh/.well-known/oauth-authorization-server{
"issuer": "https://api.artos.sh",
"authorization_endpoint": "https://my.artos.sh/oauth/consent",
"token_endpoint": "https://api.artos.sh/ucp/oauth2/token",
"grant_types_supported": ["authorization_code", "client_credentials", "refresh_token"],
"response_types_supported": ["code"],
"code_challenge_methods_supported": ["S256"],
"token_endpoint_auth_methods_supported": ["none", "client_secret_post"],
"scopes_supported": ["purchase:complete", "offline_access"],
"client_id_metadata_document_supported": true
}Exchange the authorization code
POST /ucp/oauth2/token (form-urlencoded). Request offline_access during
consent to receive a refresh token.
curl -X POST https://api.artos.sh/ucp/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=authorization_code \
-d code=AUTH_CODE_FROM_REDIRECT \
-d code_verifier=YOUR_PKCE_VERIFIER \
-d client_id=https://your-app.example/oauth-client.json \
-d redirect_uri=https://your-app.example/callback{
"access_token": "eyJ…",
"token_type": "Bearer",
"expires_in": 3600,
"scope": "purchase:complete",
"refresh_token": "rt_…"
}Refresh silently
curl -X POST https://api.artos.sh/ucp/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d grant_type=refresh_token \
-d refresh_token=rt_…Refresh tokens are single-use and rotated — store the new refresh_token
from every response. Silent refresh only works if (1) the AS advertises
offline_access, (2) the resource returns 401 with
WWW-Authenticate: Bearer error="invalid_token", and (3) your client relays that
401 + header rather than flattening it into a transport error.
CIMD — client registration without pre-registration
Artos supports Client ID Metadata Documents (SEP-991): your client_id is a
stable HTTPS URL pointing at a JSON document describing your client.
- Host an
oauth-client.jsonat a public URL and use that URL as yourclient_id. Any stable HTTPS URL works — the examples in these docs usehttps://your-app.example/oauth-client.json. (Artos hosts its own athttps://profile.artos.sh/well-known/oauth-client.json—well-knownwithout the leading dot is deliberate there, not a typo; unlike the UCP profile at/.well-known/ucp, CIMD does not require an RFC 8615 well-known path.) - List every
redirect_uriyou use (a callback not in the document is rejected withredirect_uri is not registered). - The API TTL-caches CIMD docs (default 600s); after editing, wait or restart the local API in dev.
- For local
mcp-remotedev, point--static-oauth-client-infoat a CIMD doc and includehttp://localhost:8898/oauth/callbackin itsredirect_uris.
Scopes
Buyer OAuth (authorization code + refresh)
The Authorization Server advertises these scopes at consent (see AS metadata at
/.well-known/oauth-authorization-server):
| Scope | Grants |
|---|---|
purchase:complete | Complete a checkout / place an order |
offline_access | Receive a refresh token (request at consent) |
Buyer OAuth does not include orders:read. A signed-in buyer reads their
own orders via buyer-account tools (get_my_order, list_my_orders) with the
buyer bearer only — no extra scope.
Platform / merchant credentials
orders:read and purchase:complete are granted on platform API keys and
merchant BYOK credentials (For merchants), not on buyer
OAuth tokens. Store-scoped get_order requires a platform key (or merchant
credential bearer) that was minted with the orders:read permission.
Trust tiers
| Tier | How achieved | Typical use |
|---|---|---|
anonymous | No credentials | Catalog browse / search |
token | Valid API key or OAuth bearer | Cart, checkout, orders (with scopes) |
signed | Valid RFC 9421 HTTP Message Signature | Elevated agent-verified requests |
Operations matrix
| Operation | Min tier | Permission |
|---|---|---|
| Global / store catalog | anonymous | — |
| Cart / checkout create/update | token | — |
| Complete checkout | token | purchase:complete |
Crypto prepare_checkout_payment | token (buyer bearer) | purchase:complete |
Store get_order | token (platform key / merchant cred) | orders:read on the credential |
| Buyer account tools | buyer bearer | — |
Agent authorization & spend caps (crypto)
OAuth consent (Connected apps) is not sufficient for autonomous crypto checkout. The buyer must also authorize the agent under My Artos → Agents, which records a stored spending allowance:
maxPerOrderAmount— per-order ceiling (minor units).dailyCapAmount— optional rolling daily cap;spentTodayAmountaccrues against it.currencyandexpiresAt.
The server enforces this allowance up front on every rail when the AP2 mandate
carries a payment_mandate_id, and consumes it once on settlement. An agent can
read the live caps via get_buyer_context. Exceeding a
cap fails the completion before any order is placed.
Rate limits are planned but not implemented in Phase 1.