API Authentication
Quick summary
Before calling an endpoint, identify the caller: public consumer, signed-in seller/admin, or licensed device. These use different credentials and authorization rules.
Start with the authentication table, then locate the route in Endpoints and check its error contract.
Three credential planes exist — they do not mix.
1. User/session auth (seller + admin + buyer accounts)
| Mechanism | Where | Shape |
|---|---|---|
| JWT bearer | be-cloudflare | POST /api/v1/auth/login → {ok, token, …}; claims iss/aud/sub/role/seller_id/tv/iat/exp; send Authorization: Bearer <jwt> |
X-Dev-User header | be/ Axum, dev-auth deployments | X-Dev-User: <email> — rejected with 401 on production |
token_version | both | logout / deactivate / password change bump users.token_version → all prior tokens die |
POST /auth/signup→usr_{12hex}+role='buyer'(default).GET /me→ role +seller_id(FE guards consume this). There is no/api/v1/auth/me— the CLI uses/me.- Rate limiting exists only on
/auth/login: 5 failures → 5-minute lock, per-email. rolevalues:buyer|seller|admin. Seller scoping is a DB re-check on every request (seller_scope_dbviaseller_memberships), not a claim trusted from the token.adminis a platform-operator role —/admin/**routes are separately authorized; seller APIs are not reused for admin.
2. License wire auth (buyer device — PoP)
For /licenses/{capability,execute,status} and SDK-gated calls:
Authorization: Entitlement <entitlement-jws>
DPoP: <proof-jws>2
See Entitlement and Device Binding. Activation itself needs no credential — POST /licenses/activate takes the license key as the credential.
3. Public (no auth)
/public/**, /licenses/verify, /checkout, /webhooks/toss, /widget-config/:id, /feedback-payments, /api/v1/health — unauthenticated by contract. Never attach credentials to public calls; the gateway and SDK are built to never send them.
Which does my tool use?
| Client | Credential |
|---|---|
yp CLI | auth login stores {type:"bearer"} (Worker JWT) or {type:"dev-user"} (Axum) automatically — see CLI config |
| MCP gateway | client's Authorization: Bearer header, forwarded verbatim to seller endpoints only |
| Rust MCP | YETDAPAY_MCP_TOKEN (bearer, wins) or YETDAPAY_DEV_USER env |
@yetdapay/sdk | none — public surface only |
@yetdapay/license-web | license key at activation → entitlement+proof thereafter |
Errors
401 unauthenticated · 403 authenticated-but-denied (or fail-closed gate denial) · bodies carry {code, message} where implemented — see Errors.