# Content permissions

Learn how to configure granular content permissions for unauthenticated Content API requests, Permanent Auth Tokens, and custom roles in Hygraph.

Content permissions control who can read, create, update, delete, publish, and unpublish content in your Hygraph project. You can configure permissions for unauthenticated requests to the Content API, individual Permanent Auth Tokens (PATs), and custom roles.

Content permissions are environment-specific. If you are working with multiple environments, you must configure permissions separately for each one. You can configure up to 50 content permissions in a project [environment](https://hygraph.com/docs/api-reference/basics/environments). You can distribute these across the unauthenticated Content API, PATs, and custom roles as needed.

## Permission actions

The permission system is built on seven action types. Granting an action gives unauthenticated requests, a PAT, or a custom role permissions to perform that action on all models or a specific model.

| Action          | Description                               | Required permissions                                                       |
|-----------------|-------------------------------------------|----------------------------------------------------------------------------|
| `Read`          | Read content entries.                     | —                                                                          |
| `Read versions` | View version history for content entries. | —                                                                          |
| `Create`        | Create new content entries.               | `Read` on Draft stage and default locale, and `Create`                     |
| `Update`        | Modify existing content entries.          | `Read` on Draft stage, and `Update`                                        |
| `Delete`        | Delete content entries.                   | `Read` on all stages, `Delete`, and `Unpublish` on all stages except Draft |
| `Publish`       | Publish content entries.                  | `Read` on Draft stage, and `Publish` on Draft and target stage             |
| `Unpublish`     | Unpublish content entries.                | `Read` on all stages, and `Unpublish` on source stage                      |

**For custom roles**

Custom roles have no content permissions by default. At a minimum, a custom role that uses the content editor need the following permissions:

- **Read** access on the `User` system model. This is important for custom roles that interact with the UI, as user attribution fields (`createdBy`, `updatedBy`, and `publishedBy`) will not display without these permissions. Missing these permissions can also cause `not allowed` errors when mutating content from the content editor. See [System fields: User fields](https://hygraph.com/docs/api-reference/schema/system-fields#user-fields) for more information.
- **Read versions**. This is required for versioning to display correctly in the content editor.

## Set up unauthenticated access to the Content API

Unauthenticated requests to the Content API are intended for reads. To expose published content publicly:

1. Navigate to **Project Settings > Access > Content API**.
2. In the **Content Permissions** box, click **Initialize defaults**. This sets `Read` permissions on all models for the default public content delivery stage, which is **PUBLISHED** unless you changed it.
3. If you need custom rules instead, click **Add permissions**, select **All models**, check **Read**, leave **Locales** and **Stages** at their defaults, and click **Create**.

The Content API now serves that content to unauthenticated requests.

For the add, edit, and delete steps on this screen, see [Unauthenticated requests: Content API](https://hygraph.com/docs/getting-started/access-and-permissions/api-access#content-permissions). For what each action means, see [Permission actions](#permission-actions).

![Content API read permissions for unauthenticated requests](https://hygraph.com/images/docs/api-reference/basics/public-api-read.png)

[Learn more about authorization](https://hygraph.com/docs/api-reference/basics/authorization).

## Set up a PAT with model-specific permissions

A [Permanent Auth Token (PAT)](https://hygraph.com/docs/api-reference/basics/authorization#permanent-auth-tokens) can be scoped to specific models and actions. The example below configures a PAT that can read, create, and update entries in a `Post` model only.

1. Navigate to **Project Settings > Access > Permanent Auth Tokens** and click **Add token**.
2. Enter a token name and optional description, then click **Add & configure permissions**.
3. Under **Content API** in the token detail view, click **Add permissions**.
4. Select the **Post** model and check **Read**, **Create**, and **Update**. Leave **Locales**, **Stages**, and **Condition** at their defaults, then click **Create**.

The token can now read, create, and update `Post` entries. With this configuration, the token cannot access related models such as `Author`, `Asset`, or `SEO`. To connect posts to those models, add separate permissions for each.

For the general add permission steps on a PAT, see [Authenticated requests: Permanent Auth Tokens](https://hygraph.com/docs/getting-started/access-and-permissions/api-access#configure-content-permissions). For what each action means, see [Permission actions](#permission-actions).

## Scope content permissions

The examples below show how to scope a content permission in the UI. They apply when you add a permission on a custom role, a Permanent Auth Token, or the unauthenticated Content API.

For combined permission sets for a job, such as a read-only reviewer or a publisher, see [Permission combinations by job](https://hygraph.com/docs/getting-started/access-and-permissions/permission-combinations-by-job).

### By model

Select the target model from the **Model** dropdown when creating a content permission. Permissions will apply only to entries of that model.

![Setup by models](https://hygraph.com/images/docs/user-guides/roles-and-permissions/setup-example-models.png)

**Note:**

Selecting multiple models at once is not supported, unless you select all models. To configure the same permissions on two different models, create a separate permission for each.

When permissions are set on a model that has [relations](https://hygraph.com/docs/api-reference/schema/field-types#reference), permissions may be required on both models. For example, in a schema with `Post` and `Author` models, updating a `Post` to connect it to an `Author` also requires update permissions on the `Author` model, since an author can reference many posts.

### By locale

When selecting a permission action, use the **Locales** dropdown to restrict it to one or more specific locales.

To create or update a document with non-localized fields, the user or token must have access to the default locale. If no default locale is set, the user or token must have access to all locales.

![Setup by locales](https://hygraph.com/images/docs/user-guides/roles-and-permissions/setup-example-locales.png)

**Note:**

You must also grant access to the default locale for any role that needs to create or update content.

### By content stage

Use the **From stages** and **To stages** dropdowns to restrict publish and unpublish actions to specific stages. For example, you can limit a role to publishing from **Draft** to a **QA** stage only, preventing direct publishing to **Published**.

![Setup by content stage](https://hygraph.com/images/docs/user-guides/roles-and-permissions/setup-example-content-stage.png)

**Pro tip:**
Check out [Content Workflows](https://hygraph.com/docs/developer-guides/project/content-workflows) to learn how to use content stages for approval workflows. For help with a specific setup, contact the Hygraph support team.

### By environment

Management API permissions apply to all environments in a project. Content permissions are environment-specific, so you can configure different permissions on each environment for the same role.

For example, to give a role read-only access on the master environment and publish access on a secondary environment:

1. Switch to your master environment.
2. Set up the role as read-only, as described in [Content reviewer](https://hygraph.com/docs/getting-started/access-and-permissions/permission-combinations-by-job#content-reviewer).
3. Switch to the secondary environment. [Learn how to switch environments](https://hygraph.com/docs/developer-guides/project/manage-project-environments#switch-environments).
4. Open the custom role and select **View permissions**.
5. Add the **Publish** and **Unpublish** content permissions.
6. Enable the additional Management API permissions required for publishing, as described in [Publisher](https://hygraph.com/docs/getting-started/access-and-permissions/permission-combinations-by-job#content-publisher).

![Setup by environment](https://hygraph.com/images/docs/user-guides/roles-and-permissions/setup-example-content-stage.png)

## Use conditions

Conditions let you restrict a permission to specific content entries. Instead of granting a role, token, or the public Content API access to all entries in a model, you can scope it further using a GraphQL `where` clause.
For example, for entries with a particular field value, tag, or ID.

Conditions require familiarity with GraphQL `where` clauses. Use the API Playground to build and test a condition before applying it to a role. To add a condition when configuring a permission:

1. Open the custom role, Permanent Auth Token, or public Content API permissions screen, and click **Add permissions**.
2. Select the target model from the **Model** dropdown.
3. Check the actions you want to grant.
4. Enter a JSON `where` clause in the **Condition** field.
5. Click **Create** to save.

**Note:**
Conditions cannot be applied to localized fields and do not support `search` capabilities.

![Conditions](https://hygraph.com/images/docs/user-guides/roles-and-permissions/setup-example-conditions.png)

You need to maintain conditions manually. If a field is renamed or a referenced document ID changes, the condition becomes invalid. Update affected conditions whenever the underlying schema or content changes.

The following examples show conditions applied to a `Post` model:

- Grant access only to posts tagged with specific values:

    ```json
    { "tags_contains_some": ["GraphQL", "SEO"] }
    ```

- Extend the above to also include posts with no tags:

    ```json
    { "OR": [{ "tags_contains_some": ["GraphQL", "SEO"] }, { "tags": null }] }
    ```

    ![PAT Post Tag Conditions](https://hygraph.com/images/docs/api-reference/basics/pat-post-tag-conditions.png)

- Restrict access to posts related to a specific author by ID:

    ```json
    { "author": { "id_in": ["ckadqgca800ix011230ailipe"] } }
    ```

    For this to work, the token or role also needs read access on the `Author` model. You can optionally restrict that access to a single document:
    
    ```json
    { "id": "ckadqgca800ix011230ailipe" }
    ```
    
    ![PAT Post Author Conditions](https://hygraph.com/images/docs/api-reference/basics/pat-post-author-conditions.png)

## What's next

- [Authorization](https://hygraph.com/docs/api-reference/basics/authorization): Public API permissions, PATs, and endpoints.
- [Roles and permissions](https://hygraph.com/docs/getting-started/access-and-permissions/user-roles-and-permissions): Create and configure roles, assign permissions, and set up role-based access.
- [API access](https://hygraph.com/docs/getting-started/access-and-permissions/api-access): Manage API endpoints, Permanent Auth Tokens, and content permissions.
