API Endpoints
HTTP endpoints exposed by the plugin
API Endpoints
The plugin exposes two surfaces of HTTP endpoints:
- Payload-side endpoints mounted under the user collection at
/api/<userSlug>/...(defaultuserSlugisuser). These bridge the Payload admin to Better Auth and enforce thepayloadcmsaccess gate. - Better Auth endpoints mounted at
/api/auth/*by Better Auth itself. Everything related to sign-up, sign-in, 2FA, social providers, passkeys, sessions and so on lives here. The full reference is in the Better Auth docs.
Payload-side endpoints
Mounted on the user collection (singular slug user by default).
POST /api/user/login
Authenticates with email + password through Better Auth, runs the payloadcms: ['access'] permission check, and returns a Payload-shaped session.
POST /api/user/login
Content-Type: application/json
{
"email": "user@example.com",
"password": "secret"
}Successful response includes user, token (unless the collection has removeTokenFromResponses), and exp. When the account has 2FA enabled, login returns a placeholder user with _twoFactorPending: true and the admin client redirects to /admin/two-factor-verify to complete TOTP.
POST /api/user/logout
Clears the Better Auth session and the Payload cookie.
GET /api/user/me
Returns the current session and user, derived from Better Auth and re-shaped for Payload.
POST /api/user/refresh-token
Refreshes the JWT cookie used by the Payload admin.
POST /api/user/first-register
Used by the Payload "first user" bootstrap flow. After the first call succeeds the endpoint is effectively idempotent: subsequent registrations must go through the normal Better Auth sign-up surface.
Better Auth endpoints (/api/auth/*)
These are mounted automatically by Better Auth when the plugin is installed. Common paths:
POST /api/auth/sign-up/emailPOST /api/auth/sign-in/emailPOST /api/auth/sign-in/socialPOST /api/auth/two-factor/enablePOST /api/auth/two-factor/verify-totpGET /api/auth/reference- OpenAPI reference (development only; disabled in production)
The exact shape of each request/response is defined by Better Auth and any plugins you enable. Use auth.api.<method>() server-side or a Better Auth client created with createAuthClient from better-auth/react browser-side to call them with full typings instead of crafting raw HTTP.