| title |
aliases |
tags |
sources |
created |
updated |
| Local API — Access Control |
| local-api-access-control |
| payload-overrideAccess |
|
| payloadcms |
| local-api |
| access-control |
| security |
| server-side |
|
| raw/local-api__access-control.md |
|
2026-05-15 |
2026-05-15 |
Overview
Local API operations skip access control by default. This is by design — server-side scripts and admin tasks often run without a user context. You must explicitly opt in to access control enforcement when it matters.
Default Behaviour: Access Control Skipped
// Access control is NOT checked — runs as a privileged operation
const doc = await payload.create({
collection: 'users',
data: { email: 'test@test.com', password: 'test' },
})
Useful for:
- Seed scripts and migrations
- Admin-only server jobs (cron tasks, background workers)
- Internal service-to-service operations
Enforcing Access Control
Pass overrideAccess: false and the authenticated user object to make the operation respect collection-level access rules.
const doc = await payload.create({
collection: 'users',
overrideAccess: false, // enforce collection access control
user, // authenticated user to check against
data: { email: 'test@test.com', password: 'test' },
})
- If
user lacks permission → Payload throws a Forbidden error
- Works on all CRUD operations:
create, find, findByID, update, delete
When to Use Each Mode
| Scenario |
overrideAccess |
Pass user? |
| Server scripts, cron jobs, seeds |
true (default) |
No |
| Server actions executing on behalf of a logged-in user |
false |
Yes — req.user |
| Webhooks / third-party integrations with trusted tokens |
true (default) |
No |
| Custom API endpoints that mirror REST behaviour |
false |
Yes |
Key Takeaways
- Local API bypasses access control by default — safe for trusted server code, dangerous if exposed to untrusted input.
- To enforce permissions: set
overrideAccess: false AND pass the user object.
- Both conditions are required —
overrideAccess: false without a user will treat the request as unauthenticated (all collection-access functions receive undefined as user).
- In wiki/payloadcms/hooks-collections that run after user-triggered events, access control is already enforced by the REST/GraphQL layer; using the Local API inside hooks with
overrideAccess: true lets you escalate privileges intentionally.
- See wiki/payloadcms/access-control for collection/field-level access function signatures.
Sources