Medusa authenticates with an actor type plus a method, not with a single key. The actor is `user` (admin), `customer`, or a custom actor type a merchant defines; the method is a JWT bearer token, a session cookie, or — for admin only — a secret API key. Route protection is by path prefix rather than by declared security on each operation, which is why neither published document sets a top-level `security` block: /admin is protected by default, /store/customers/me is protected for customers, and everything else under /store is public but still requires a publishable API key that scopes the request to a sales channel.
Medusa secures its APIs with http and apiKey across 4 declared security schemes, as derived from its OpenAPI definitions.
generated: '2026-08-26'
method: searched
source: >-
Derived from components.securitySchemes in openapi/medusa-store-openapi.yaml and
openapi/medusa-admin-openapi.yaml (2.19.0) by 0-working/derive-authentication.py, then
upgraded from https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes,
https://docs.medusajs.com/api/store, https://docs.medusajs.com/api/admin and the probed
OAuth metadata in well-known/.
description: >-
Medusa authenticates with an actor type plus a method, not with a single key. The actor is
`user` (admin), `customer`, or a custom actor type a merchant defines; the method is a JWT
bearer token, a session cookie, or — for admin only — a secret API key. Route protection
is by path prefix rather than by declared security on each operation, which is why neither
published document sets a top-level `security` block: /admin is protected by default,
/store/customers/me is protected for customers, and everything else under /store is public
but still requires a publishable API key that scopes the request to a sales channel.
summary:
types: [http, apiKey]
schemes: 4
oauth2: false
openid_connect: false
mutual_tls: false
api_key_in: [cookie, header]
schemes:
- name: jwt_token
type: http
scheme: bearer
display_name: JWT Token
actors: [user, customer]
sources: [openapi/medusa-admin-openapi.yaml, openapi/medusa-store-openapi.yaml]
obtained_via: >-
POST /auth/{actor_type}/{auth_provider} (e.g. /auth/user/emailpass,
/auth/customer/emailpass) returns a token. Third-party providers (Google, GitHub) are
supported through auth provider modules.
header: 'Authorization: Bearer <token>'
- name: cookie_auth
type: apiKey
in: cookie
parameter: connect.sid
display_name: Cookie Session ID
actors: [user, customer]
sources: [openapi/medusa-admin-openapi.yaml, openapi/medusa-store-openapi.yaml]
obtained_via: POST /auth/session after obtaining a JWT; used by browser clients including the Medusa Admin.
- name: api_token
type: http
scheme: basic
display_name: API Token
actors: [user]
sources: [openapi/medusa-admin-openapi.yaml]
obtained_via: >-
A secret API key created in the Admin dashboard or via POST /admin/api-keys with
type=secret. Sent as the HTTP Basic username with an empty password.
note: Admin only. This is the credential a server-to-server integration uses.
- name: reset_password
type: http
scheme: bearer
display_name: Reset Password Token
x_is_auth: false
sources: [openapi/medusa-admin-openapi.yaml, openapi/medusa-store-openapi.yaml]
note: >-
A single-purpose token for the password-reset flow, flagged x-is-auth:false in the
spec — it is not a general authentication scheme and should not be treated as one.
additional_required_header:
name: x-publishable-api-key
applies_to: every /store route
is_credential: false
purpose: >-
Scopes the request to one or more sales channels, so a storefront only sees the products
and inventory of its own channel. Created in the Admin dashboard, via POST
/admin/api-keys with type=publishable, or by createApiKeysWorkflow. Safe to ship in
client-side code.
docs: https://docs.medusajs.com/api/store#publishable-api-key
route_protection:
mechanism: path-prefix defaults plus an `authenticate` middleware
defaults:
- { prefix: /admin, access: authenticated admin users only }
- { prefix: /store/customers/me, access: authenticated customers only }
- { prefix: /store, access: public, but x-publishable-api-key is required }
opt_out: 'export const AUTHENTICATE = false in a route file disables the default requirement.'
custom: >-
authenticate(actorType, methods[, { allowUnauthenticated, allowUnregistered }]) applied
in src/api/middlewares.ts. Methods are session, bearer and — for admin — api-key. A
merchant can define custom actor types (e.g. `manager`) with their own auth flow.
docs: https://docs.medusajs.com/learn/fundamentals/api-routes/protected-routes
mfa:
supported: true
evidence: >-
Multi-Factor Authentication tags in both documents (Store: "Multi-Factor Authentication
(MFA) Factors"; Admin: "Multi-Factor Authentication"), plus auth.mfa_enabled,
auth.mfa_disabled and auth.mfa_recovery_codes_generated events in the published event
reference. Added in the 2.x line and announced in the June 2026 newsletter.
oauth:
rest_api: false
mcp_server: true
note: >-
OAuth appears nowhere in the REST contract. It exists only in front of the Medusa MCP
server, where authorization-code + PKCE (S256) with dynamic client registration is
advertised at https://docs.medusajs.com/.well-known/oauth-authorization-server. See
scopes/medusa-scopes.yml.
scopes:
rest_api: none
note: >-
Neither key type nor token carries scopes. Admin access is all-or-nothing for a `user`
actor; the only scoping mechanism in the product is the publishable key's sales-channel
binding on /store.
gaps:
- No token expiry, refresh or rotation policy is documented for the JWT scheme.
- No per-key permission or scope model on Admin secret keys.
- No published key-prefix convention that would let a leaked credential be recognised by shape.
Calls without X-API-Key need no key. Calls with it need a paid plan — get a key.
Get an API key
Free tier, no form to fill in. Signing in shares your email address with us — we
store it to create your key and to recognise you if you sign in with another
provider. See our Privacy Policy and
Terms.