payloadcms/payload · error · Forbidden
You are not allowed to perform this action.
Error message
You are not allowed to perform this action.
What it means
Thrown by the Stripe plugin's REST endpoint handler (`stripeREST`) as a `Forbidden(req.t)` when the request has no authenticated `user`. The message is the i18n translation key for 'You are not allowed to perform this action.' — the default `Forbidden` text. Any client hitting the Stripe proxy endpoint without a session gets this 403.
Source
Thrown at packages/plugin-stripe/src/routes/rest.ts:28
pluginConfig: StripePluginConfig
req: PayloadRequest
}): Promise<any> => {
let responseStatus = 200
let responseJSON
const { pluginConfig, req } = args
await addDataAndFileToRequest(req)
const requestWithData = req
const { data, payload, user } = requestWithData
const { stripeSecretKey } = pluginConfig
try {
if (!user) {
// TODO: make this customizable from the config
throw new Forbidden(req.t)
}
responseJSON = await stripeProxy({
stripeArgs: data?.stripeArgs, // example: ['cus_MGgt3Tuj3D66f2'] or [{ limit: 100 }, { stripeAccount: 'acct_1J9Z4pKZ4Z4Z4Z4Z' }]
stripeMethod: data?.stripeMethod, // example: 'subscriptions.list',
stripeSecretKey,
})
const { status } = responseJSON
responseStatus = status
} catch (error: unknown) {
const message = `An error has occurred in the Stripe plugin REST handler: '${JSON.stringify(
error,
)}'`
payload.logger.error(message)
responseStatus = 500
responseJSON = {
message,View on GitHub (pinned to 00c58b35c0)
Solutions
- Ensure the client is authenticated (valid session cookie or Authorization header) before calling the endpoint
- If server-to-server, pass a Payload API key or perform login first to obtain a session
- If you genuinely need anonymous Stripe access, mount a custom route with its own auth rather than relying on this guarded endpoint
Example fix
// before — no credentials
await fetch('/api/stripe', { method: 'POST', body: JSON.stringify({ stripeMethod: 'customers.list' }) })
// after — include the session cookie / API key
await fetch('/api/stripe', {
method: 'POST',
credentials: 'include',
headers: { 'Content-Type': 'application/json', Authorization: `users API-Key ${apiKey}` },
body: JSON.stringify({ stripeMethod: 'customers.list', stripeArgs: [{ limit: 10 }] }),
}) Defensive patterns
Strategy: validation
Validate before calling
// Ensure a user session exists before calling the Stripe proxy
if (!currentUser) { await login(); }
await fetch('/api/stripe', { method: 'POST', credentials: 'include', body: JSON.stringify({ stripeMethod, stripeArgs }) }) Try / catch
const res = await fetch('/api/stripe', { method: 'POST', credentials: 'include', body })
if (res.status === 403) {
// session missing or expired — re-authenticate, then retry
await relogin()
return fetch('/api/stripe', { method: 'POST', credentials: 'include', body })
} Prevention
- Gate the Stripe-proxy UI on an authenticated session
- Send `credentials: 'include'` (or an API key) on every call to the endpoint
- For server-to-server use, perform a login flow or pass a Payload API key
When it happens
Trigger: Calling the Stripe REST proxy endpoint (`/api/stripe` or whatever path the plugin mounts) without a logged-in Payload user; expired session cookie; the endpoint hit from a server-to-server script that did not set a Cookie/Authorization header.
Common situations: Frontend calling the Stripe proxy before login completes; cookie blocked by SameSite/secure policy; a cron/background job assuming the endpoint was public; proxying a test request from Postman without copying the session cookie.
Related errors
- You are not allowed to perform this action.
- You are not allowed to perform this action.
- Unauthorized, you must be logged in to make this request.
- Unauthorized, you must be logged in to make this request.
- You are not allowed to perform this action.
AI-assisted analysis of payloadcms/payload@00c58b35c0 (2026-08-12).
Data as JSON: /api/errors/5da2022d2a2a496a.
Report an issue: GitHub.