---
title: "Local API — Access Control"
aliases: [local-api-access-control, payload-overrideAccess]
tags: [payloadcms, local-api, access-control, security, server-side]
sources: [raw/local-api__access-control.md]
created: 2026-05-15
updated: 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

```ts
// 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.

```ts
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|Collection Hooks]] 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|Access Control Overview]] for collection/field-level access function signatures.

## Sources

- `raw/local-api__access-control.md`
- https://payloadcms.com/docs/local-api/access-control
