> ## Documentation Index
> Fetch the complete documentation index at: https://docs.stackone.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Check Permissions

> Check whether a user can access a specific resource and, optionally, whether a specific action is allowed.

```
POST /unified/check_permissions
```

Checks a user's permissions on a specific resource. Returns the permissions they hold and, if you specify an `action`, whether that action is allowed.

## Authentication

Requires `Authorization: Basic {base64_encoded_api_key}` and `x-account-id: {account_id}`. See [authentication](/iam/common-guide/basic-authentication-with-stackone-api).

## Request Body

| Field         | Type   | Required    | Description                                                                                                                  |
| ------------- | ------ | ----------- | ---------------------------------------------------------------------------------------------------------------------------- |
| `user_id`     | string | Conditional | Provider user ID. At least one of `user_id` or `email` is required. When both are provided, `user_id` takes priority.        |
| `email`       | string | Conditional | User's email address. If `user_id` is absent, the connector resolves the email to a user ID internally.                      |
| `resource_id` | string | **Yes**     | The resource to check. Accepts a StackOne composite ID (starts with `c28xIQ`) or a plain provider-native ID.                 |
| `action`      | string | No          | The action to check. One of: `read`, `write`, `comment`, `delete`, `export`. When provided, the response includes `allowed`. |

<Note>
  At least one of user\_id or email must be present. Omitting both returns a 400 error.
</Note>

### Resource ID formats

The `resource_id` field accepts two formats:

**Composite ID** (starts with `c28xIQ`): A StackOne-encoded ID that embeds the provider resource ID and optional resource type. The service decodes it automatically.

**Plain provider ID**: Any other string is treated as a native provider resource ID and passed through as-is. The connector uses its default resource type for the check. Use [List Resource Types](/permissions-check/api-reference/list-resource-types) to discover valid types.

## Response

| Field              | Type      | Present                        | Description                                                                                                                                   |
| ------------------ | --------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `user.id`          | string    | Always                         | The resolved provider user ID                                                                                                                 |
| `user.permissions` | string\[] | Always                         | Permissions the user holds on this resource: subset of `read`, `write`, `comment`, `delete`, `export`. Empty array if the user has no access. |
| `resource.type`    | string    | Always                         | The resolved resource type                                                                                                                    |
| `resource.id`      | string    | Always                         | The decoded provider resource ID                                                                                                              |
| `action`           | string    | Only if requested              | Echoes back the `action` from the request                                                                                                     |
| `allowed`          | boolean   | Only if `action` was requested | `true` if the requested action is in `user.permissions`                                                                                       |

## Examples

<Tabs>
  <Tab title="Read check">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.stackone.com/unified/check_permissions' \
      --header 'authorization: Basic {base64_encoded_api_key}' \
      --header 'content-type: application/json' \
      --header 'x-account-id: {account_id}' \
      --data '{
        "user_id": "U08FW4R4N6S",
        "resource_id": "c28xIQcnQ6Y2hhbm5lbCxpZDpDMDhHNlFCOTBMVQ==",
        "action": "read"
      }'
    ```

    ```json theme={null}
    {
      "user": { "id": "U08FW4R4N6S", "permissions": ["read", "write", "comment"] },
      "resource": { "type": "channel", "id": "C08G6QB90LU" },
      "action": "read",
      "allowed": true
    }
    ```
  </Tab>

  <Tab title="Permission summary (no action)">
    ```bash theme={null}
    curl --request POST \
      --url 'https://api.stackone.com/unified/check_permissions' \
      --header 'authorization: Basic {base64_encoded_api_key}' \
      --header 'content-type: application/json' \
      --header 'x-account-id: {account_id}' \
      --data '{
        "email": "alice@company.com",
        "resource_id": "c28xIQaWQ6MWRhYjN..."
      }'
    ```

    ```json theme={null}
    {
      "user": { "id": "U08FW4R4N6S", "permissions": ["read"] },
      "resource": { "type": "folder", "id": "1dab3..." }
    }
    ```

    No `action` sent — no `allowed` field in response.
  </Tab>

  <Tab title="No access">
    ```json theme={null}
    {
      "user": { "id": "U08FW4R4N6S", "permissions": [] },
      "resource": { "type": "channel", "id": "C08G6QB90LU" },
      "action": "write",
      "allowed": false
    }
    ```

    A `200` response with empty permissions — not an error.
  </Tab>
</Tabs>

## Permission types

<Note>
  These action values differ from the IamPermissionTypeEnum used in the IAM entity model. The IAM enum also includes create and edit, which are not applicable for resource-level permission checks.
</Note>

The unified permission model normalizes provider-native roles to five action types:

| Type      | Description                             |
| --------- | --------------------------------------- |
| `read`    | View the resource and its content       |
| `write`   | Modify the resource                     |
| `comment` | Add comments or annotations             |
| `delete`  | Remove the resource                     |
| `export`  | Download or export the resource content |

Which permissions are granted for a given provider role depends on the integration. See the connector's integration guide for how this provider's roles map to these types.

## Error codes

| Status | Condition                                                                                 |
| ------ | ----------------------------------------------------------------------------------------- |
| 400    | Missing `resource_id`, missing both `user_id` and `email`, or invalid `action` enum value |
| 401    | Invalid API key                                                                           |
| 404    | User not found (email resolution failed) or resource not found                            |
| 422    | The connected provider does not support `check_permissions`                               |
| 429    | Provider rate limit reached — retry with backoff                                          |
| 502    | Provider API error                                                                        |

## Edge cases

| Situation                           | Behavior                                                                              |
| ----------------------------------- | ------------------------------------------------------------------------------------- |
| User has no access to the resource  | `200` with `user.permissions: []` and, when an `action` is provided, `allowed: false` |
| Deactivated or suspended user       | `200` with `user.permissions: []` — provider semantics preserved                      |
| Resource not found                  | `404` with `"resource not found"`                                                     |
| User not found (email resolution)   | `404` with `"user not found"`                                                         |
| Both `user_id` and `email` provided | `user_id` is used; `email` is ignored                                                 |
| `action` is not in the enum         | `400` validation error                                                                |
