vX
OAS 3.0.0

Sanity Access API

A centralized API to manage resource access control through roles and permissions.

Overview:

Throughout this document the terms {resourceType} and {resourceId} refer to the resource the API request is being applied to.

  • {resourceType} can be an organization or project.
  • {resourceId} is the ID of the resource the API request affects.

When a client uses this API, it acts in the context of a specific resource. For example:

  • https://api.sanity.io/vX/access/organization/or0Bc1hcJ/roles
  • https://api.sanity.io/vX/access/project/c7ja4siy/roles

Key Concepts

  • Resource
    • A resource is an entity that can be managed and accessed through the API. Currently, the supported resources are organization and project.
  • Permission
    • Every resource has a list of permissions. These permissions represent actions that can be performed on the resource. A user or robot must be granted a permission (through a role) in order to perform the action.
    • The permission typically takes the form of {company}.{resourceType}.{objectName}.{action} but this is not always the case due to legacy terms.
    • There are both pre-defined and custom permissions. Pre-defined permissions are included with the product and are not editable.
  • Role
    • A role is a named collection of permissions that can be applied to a user or robot. Roles are in the scope of a resource and can only receive permissions that are in the same resource scope. For example, a project role can only include document permissions for that project.
    • A role is specific to a single resource and can only include permissions within that resource's scope. In the future, roles will be able to include permissions for child resources as well. For example, an organization role will be able to include document permissions for specific projects or all projects.
    • A user cannot be part of a resource without a role. Each user in an organization must have at least one role assigned to them.
    • There are both pre-defined and custom roles. Pre-defined roles are included with the product and are not editable, but can be removed from a resource if the feature is enabled.
  • User
    • A user is a person that has one or more roles assigned to them.
    • A user is initially added to a resource via invitation or access request. A user that already has one role can be assigned roles in another project within the same organization or at the organization level without requiring a separate invite.
    • As an organization owns multiple resources (e.g., projects), any users with roles on these resources are also returned when reading the users of an organization.
    • If a user has roles in multiple projects, they are considered a single user and can be referenced by their sanityUserId. For example, inviting user A to project B and project C in the same organization will result in a single user with two memberships.

Administrator Rules

  • Changing Administrators
    • Only administrators can assign or remove roles with admin permissions. This prevents unauthorized permission elevation.
    • This rule applies only to the default roles. Custom roles are fully managed by the organization and can be assigned to users without restriction.
  • Last Administrator
    • Each resource must have at least one role assigned to at least one user that can read users, read roles, and assign roles to users. This prevents an organization from losing control over their resources.
    • This is designed as a permission-level check and not a role-level check, so that the default roles can be removed from a resource. Customers with advanced roles management enabled can remove the default roles from a resource.

Breaking Changes from previous versions

See the details of the existing API for a better understanding of the changes.

Summary:

  • Access is now the root path for managing access-based resources. Previously it was organization and project but these are now nested under the access root.
  • Internal IDs are no longer exposed for permissions or roles. The name property is now used as the unique identifier for permissions and roles.
  • Permissions now represent grants, resources, and permissionResourceSchema. These are now legacy terms.
  • The endpoint /organization/:organizationId/users returns users for all resources owned by the organization. Previously, a client would have to make a request for each resource (e.g., project) individually.
  • users replaces the term ACL. Users represents individuals assigned roles within the organization.
  • The pre-defined roles can be completely removed from a resource. Previously, default roles could not be removed from a resource. E.g., a project required at least one project administrator, even if there were custom roles that would cover the same use case.

Production External API

:
Client Libraries

Users

List all users of a resource and their assigned roles.

Retrieve a list of all users of a resource along with their assigned roles. When the resourceType is organization, this endpoint will return users of projects owned by the organization. Requires permission

  • sanity.{resourceType}.members.read
Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

Query Parameters
  • nextCursor
    string

    The cursor for pagination. Use the nextCursor from the previous response to get the next page.

  • limit
    integer
    min: 
    1
    max: 
    500
    default: 
    100

    The number of items to return per page.

Responses
  • 400

    Bad request

  • 401

    Unauthorized

  • 404

    Resource not found

GET/vX/access/{resourceType}/{resourceId}/users
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "data": [
    {
      "sanityUserId": "gDdcnv42e",
      "profile": {
        "id": "…",
        "displayName": "…",
        "email": "…",
        "familyName": "…",
        "givenName": "…",
        "middleName": "…",
        "imageUrl": "https://example.com",
        "provider": "…",
        "tosAcceptedAt": "2025-02-13T10:31:34.423Z",
        "createdAt": "2025-02-13T10:31:34.423Z",
        "updatedAt": "2025-02-13T10:31:34.423Z",
        "isCurrentUser": true,
        "providerId": "…"
      },
      "memberships": [
        {
          "addedAt": "2024-01-15T12:15:30Z",
          "resourceType": "project",
          "resourceId": "c7ja4siy",
          "roleNames": [
            "administrator",
            "editor"
          ],
          "lastSeenAt": "2024-01-15T12:15:30Z"
        }
      ]
    }
  ],
  "nextCursor": "…",
  "totalCount": 1
}

Apply organization default role to all users.

Add default role to all resource users. Limited to Organization. Requires permission

  • sanity.organization.members.update
Path Parameters
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

Responses
  • 201

    Roles assigned to the resource users

  • 400

    Invalid input

  • 404

    Resource not found

PUT/vX/access/organization/{resourceId}/users/roles/default
curl 'https://api.sanity.io/vX/access/organization/{resourceId}/users/roles/default' \
  --request PUT \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

Get user and roles.

Get the users for a single user of a resource. Requires permission - sanity.{resourceType}.members.read

Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

  • sanityUserId
    string
    required

    The User ID

Responses
  • 400

    Bad request

  • 404

    Resource not found

GET/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "sanityUserId": "gDdcnv42e",
  "profile": {
    "id": "…",
    "displayName": "…",
    "email": "…",
    "familyName": "…",
    "givenName": "…",
    "middleName": "…",
    "imageUrl": "https://example.com",
    "provider": "…",
    "tosAcceptedAt": "2025-02-13T10:31:34.423Z",
    "createdAt": "2025-02-13T10:31:34.423Z",
    "updatedAt": "2025-02-13T10:31:34.423Z",
    "isCurrentUser": true,
    "providerId": "…"
  },
  "memberships": [
    {
      "addedAt": "2024-01-15T12:15:30Z",
      "resourceType": "project",
      "resourceId": "c7ja4siy",
      "roleNames": [
        "administrator",
        "editor"
      ],
      "lastSeenAt": "2024-01-15T12:15:30Z"
    }
  ]
}

Remove a user from a resource.

This removes all roles. If the resourceType is organization, this will also remove the user from all projects owned by the organization. Requires permission

  • sanity.{resourceType}.members.delete
Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

  • sanityUserId
    string
    required

    The User ID

Responses
  • 200

    User removed from the resource

  • 400

    Invalid input

  • 404

    Resource not found

DELETE/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}' \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

Add a role to a user.

Add a role to a user. Requires permission

  • sanity.{resourceType}.members.update
Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

  • sanityUserId
    string
    required

    The User ID

  • roleName
    string
    required

    The role name.

Responses
  • 400

    Invalid input

  • 404

    Resource not found

PUT/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/roles/{roleName}
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/roles/{roleName}' \
  --request PUT \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
{
  "sanityUserId": "gDdcnv42e",
  "profile": {
    "id": "…",
    "displayName": "…",
    "email": "…",
    "familyName": "…",
    "givenName": "…",
    "middleName": "…",
    "imageUrl": "https://example.com",
    "provider": "…",
    "tosAcceptedAt": "2025-02-13T10:31:34.423Z",
    "createdAt": "2025-02-13T10:31:34.423Z",
    "updatedAt": "2025-02-13T10:31:34.423Z",
    "isCurrentUser": true,
    "providerId": "…"
  },
  "memberships": [
    {
      "addedAt": "2024-01-15T12:15:30Z",
      "resourceType": "project",
      "resourceId": "c7ja4siy",
      "roleNames": [
        "administrator",
        "editor"
      ],
      "lastSeenAt": "2024-01-15T12:15:30Z"
    }
  ]
}

Remove a role from a user in a resource.

You cannot remove the last role from a user. You must have at least one role assigned to a user. Requires permission

  • sanity.{resourceType}.members.update
Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

  • sanityUserId
    string
    required

    The User ID

  • roleName
    string
    required

    The role name.

Responses
  • 200

    Role removed from user

  • 400

    Invalid input

  • 404

    Resource not found

DELETE/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/roles/{roleName}
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/roles/{roleName}' \
  --request DELETE \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
No Body

List permissions for a user

Normalized list of permission resources for a user across all assigned roles. Requires permissions:

  • sanity.{resourceType}.members.read for resource scoped roles (e.g. project admin)
Path Parameters
  • resourceType
    string enum
    required

    The resource type to scope the access requests to.

    Exampleproject
    • organization
    • project
  • resourceId
    string
    required

    The resource ID to scope the access request to. Must be a valid ID for the resource type.

  • sanityUserId
    string
    required

    The User ID

Responses
GET/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/permissions
curl 'https://api.sanity.io/vX/access/{resourceType}/{resourceId}/users/{sanityUserId}/permissions' \
  --header 'Authorization: Bearer YOUR_SECRET_TOKEN'
[
  {
    "type": "sanity.document.filter.mode",
    "actions": [
      "mode"
    ],
    "name": "legal-documents",
    "title": "Permission for \"Legal\" Folder",
    "description": "Permission for \"Legal\" Folder",
    "resourceType": "project",
    "resourceId": "c7ja4siy",
    "ownerOrganizationId": "or0Bc1hcJ",
    "params": {
      "filter": "*[_type == \"legal\"]"
    }
  }
]

Models