<!-- llms.txt: https://workos.com/llms.txt -->

# Permission

A permission represents an individual access right that can be assigned to roles. Permissions define what actions users with a given role can perform within your application.

Permissions are defined at the environment level and can be assigned to both environment roles and custom roles. Each permission has a unique slug identifier that you use when assigning it to roles.

## Create a permission

Create a new permission in your WorkOS environment. The permission can then be assigned to environment roles and custom roles.

The `slug` must be unique within the environment and must be lowercase, containing only letters, numbers, hyphens, underscores, colons, periods, and asterisks.

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request POST \
  --url "https://api.workos.com/authorization/permissions" \
  --header "Authorization: Bearer sk_example_123456789" \
  --header "Content-Type: application/json" \
  -d @- <<'BODY'
    {
        "slug": "documents:read",
        "name": "View Documents",
        "description": "Allows viewing document contents",
        "resource_type_slug": "document"
    }
BODY
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const permission = await workos.authorization.createPermission({
  slug: 'documents:delete',
  name: 'Delete Documents',
  description: 'Allows deleting documents',
});
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.authorization.create_permission(
  slug: "documents:read",
  name: "View Documents"
)
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.authorization.create_permission(slug="documents:read", name="View Documents")
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Authorization().CreatePermission(context.Background(), &workos.AuthorizationCreatePermissionParams{
		Slug: "documents:read",
		Name: "View Documents",
	})
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos
    ->authorization()
    ->createPermission(slug: "documents:read", name: "View Documents");
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;
import com.workos.authorization.AuthorizationApi.CreatePermissionOptions;

WorkOS workos = new WorkOS("sk_example_123456789");

CreatePermissionOptions options = CreatePermissionOptions.builder()
                                      .slug("documents:read")
                                      .name("View Documents")
                                      .build();

workos.authorization.createPermission(options);
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Authorization.CreatePermissionAsync(new AuthorizationCreatePermissionOptions {
    Slug = "documents:read",
    Name = "View Documents",
});
```

```rust language="rust" title="Request" tab="1"
use workos::Client;
use workos::authorization::CreatePermissionParams;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .authorization()
        .create_permission(
            CreatePermissionParams {
                slug: "documents:read".into(),
                name: "View Documents".into(),
                ..Default::default()
            }
        )
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "permission",
  "id": "perm_01HXYZ123456789ABCDEFGHIJ",
  "slug": "documents:read",
  "name": "View Documents",
  "description": "Allows viewing document contents",
  "system": false,
  "resource_type_slug": "document",
  "created_at": "2026-01-15T12:00:00.000Z",
  "updated_at": "2026-01-15T12:00:00.000Z"
}
```

:::

## Delete a permission

Delete an existing permission. System permissions cannot be deleted.

:::code-group{title="Request"}

```bash language="curl"
curl --request DELETE \
  --url https://api.workos.com/authorization/permissions/documents:delete \
  --header "Authorization: Bearer sk_example_123456789"
```

```js language="js"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

await workos.authorization.deletePermission('documents:delete');
```

```rb language="ruby"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.authorization.delete_permission(slug: "documents:read")
```

```py language="python"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.authorization.delete_permission(slug="documents:read")
```

```go language="go"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Authorization().DeletePermission(context.Background(), "documents:read")
	if err != nil {
		panic(err)
	}
}
```

```php language="php"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->authorization()->deletePermission(slug: "documents:read");
```

```java language="java"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.authorization.deletePermission("documents:read");
```

```cs language="dotnet"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Authorization.DeletePermissionAsync("documents:read");
```

```rust language="rust"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .authorization()
        .delete_permission("documents:read")
        .await?;

    Ok(())
}
```

:::

## Get a permission

Retrieve a permission by its unique slug.

:::code-group

```bash language="curl" title="Request" tab="1"
curl "https://api.workos.com/authorization/permissions/documents:read" \
  --header "Authorization: Bearer sk_example_123456789"
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const permission = await workos.authorization.getPermission('documents:read');
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.authorization.get_permission(slug: "documents:read")
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.authorization.get_permission(slug="documents:read")
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Authorization().GetPermission(context.Background(), "documents:read")
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->authorization()->getPermission(slug: "documents:read");
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.authorization.getPermission("documents:read");
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Authorization.GetPermissionAsync("documents:read");
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .authorization()
        .get_permission("documents:read")
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "permission",
  "id": "perm_01HXYZ123456789ABCDEFGHIJ",
  "slug": "documents:read",
  "name": "View Documents",
  "description": "Allows viewing document contents",
  "system": false,
  "resource_type_slug": "workspace",
  "created_at": "2026-01-15T12:00:00.000Z",
  "updated_at": "2026-01-15T12:00:00.000Z"
}
```

:::

## List permissions

Get a list of all permissions in your WorkOS environment.

:::code-group

```bash language="curl" title="Request" tab="1"
curl "https://api.workos.com/authorization/permissions" \
  --header "Authorization: Bearer sk_example_123456789"
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const permissions = await workos.authorization.listPermissions();
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.authorization.list_permissions
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.authorization.list_permissions()
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Authorization().ListPermissions(context.Background())
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->authorization()->listPermissions();
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.authorization.listPermissions();
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Authorization.ListPermissionsAsync();
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .authorization()
        .list_permissions()
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "list",
  "data": [
    {
      "object": "permission",
      "id": "perm_01HXYZ123456789ABCDEFGHIJ",
      "slug": "documents:read",
      "name": "View Documents",
      "description": "Allows viewing document contents",
      "system": false,
      "resource_type_slug": "workspace",
      "created_at": "2026-01-15T12:00:00.000Z",
      "updated_at": "2026-01-15T12:00:00.000Z"
    }
  ],
  "list_metadata": {
    "before": "perm_01HXYZ123456789ABCDEFGHIJ",
    "after": "perm_01HXYZ987654321KJIHGFEDCBA"
  }
}
```

:::

## Update a permission

Update an existing permission. Only the fields provided in the request body will be updated.

:::code-group

```bash language="curl" title="Request" tab="1"
curl --request PATCH \
  --url "https://api.workos.com/authorization/permissions/documents:read" \
  --header "Authorization: Bearer sk_example_123456789" \
  --header "Content-Type: application/json" \
  -d @- <<'BODY'
    {
        "name": "View Documents",
        "description": "Allows viewing document contents"
    }
BODY
```

```js language="js" title="Request" tab="1"
import { WorkOS } from '@workos-inc/node';

const workos = new WorkOS('sk_example_123456789');

const permission = await workos.authorization.updatePermission(
  'documents:read',
  {
    name: 'View Documents',
    description: 'Allows viewing document contents',
  },
);
```

```rb language="ruby" title="Request" tab="1"
require "workos"

WorkOS.configure do |config|
  config.api_key = "sk_example_123456789"
end

WorkOS.client.authorization.update_permission(slug: "documents:read")
```

```py language="python" title="Request" tab="1"
from workos import WorkOSClient

client = WorkOSClient(api_key="sk_example_123456789", client_id="client_123456789")

client.authorization.update_permission(slug="documents:read")
```

```go language="go" title="Request" tab="1"
package main

import (
	"context"

	"github.com/workos/workos-go/v10"
)

func main() {
	client := workos.NewClient("sk_example_123456789")

	_, err := client.Authorization().UpdatePermission(context.Background(), "documents:read")
	if err != nil {
		panic(err)
	}
}
```

```php language="php" title="Request" tab="1"
<?php

use WorkOS\WorkOS;

$workos = new WorkOS(
    apiKey: "sk_example_123456789",
    clientId: "client_123456789",
);

$workos->authorization()->updatePermission(slug: "documents:read");
```

```java language="java" title="Request" tab="1"
import com.workos.WorkOS;

WorkOS workos = new WorkOS("sk_example_123456789");

workos.authorization.updatePermission("documents:read");
```

```cs language="dotnet" title="Request" tab="1"
using WorkOS;

var client = new WorkOSClient(new WorkOSOptions {
    ApiKey = "sk_example_123456789",
    ClientId = "client_123456789",
});

await client.Authorization.UpdatePermissionAsync("documents:read");
```

```rust language="rust" title="Request" tab="1"
use workos::Client;

#[tokio::main]
async fn main() -> Result<(), workos::Error> {
    let client = Client::builder()
        .api_key("sk_example_123456789")
        .client_id("client_123456789")
        .build();

    let _result = client
        .authorization()
        .update_permission("documents:read")
        .await?;

    Ok(())
}
```

```json language="json" title="Response" tab="2"
{
  "object": "permission",
  "id": "perm_01HXYZ123456789ABCDEFGHIJ",
  "slug": "documents:read",
  "name": "View Documents",
  "description": "Allows viewing document contents",
  "system": false,
  "resource_type_slug": "workspace",
  "created_at": "2026-01-15T12:00:00.000Z",
  "updated_at": "2026-01-15T12:00:00.000Z"
}
```

:::

### Permission

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `object` | "permission" | Yes | Distinguishes the Permission object. |
| `id` | string | Yes | Unique identifier of the Permission. |
| `slug` | string | Yes | A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks. |
| `name` | string | Yes | A descriptive name for the Permission. |
| `description` | string \| null | Yes | A description for the Permission. |
| `system` | boolean | Yes | Whether the permission is a system permission. System permissions are created and managed by WorkOS and cannot be deleted. |
| `resource_type_slug` | string | Yes | The slug of the resource type the permission is scoped to. |
| `created_at` | string | Yes | The timestamp when the Permission was created. |
| `updated_at` | string | Yes | The timestamp when the Permission was last updated. |

### POST /authorization/permissions

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` | string | Yes | A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks. |
| `name` | string | Yes | A descriptive name for the permission. |
| `description` | string | No | An optional description for the permission. |
| `resource_type_slug` | string | No | The slug of the [resource type](/fga/resource-types) to scope the permission to. Only applicable when using [Fine-Grained Authorization](/fga). Defaults to the organization resource type if not provided. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `permission` | object | Distinguishes the Permission object. |

### DELETE /authorization/permissions/{slug}

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` | string | Yes | A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `empty` | empty | Returns an empty response on success. |

### GET /authorization/permissions/{slug}

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` | string | Yes | A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `permission` | object | Distinguishes the Permission object. |

### GET /authorization/permissions

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `before` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `before="obj_123"` to fetch a new batch of objects before `"obj_123"`. |
| `after` | string | No | An object ID that defines your place in the list. When the ID is not present, you are at the end of the list. For example, if you make a list request and receive 100 objects, ending with `"obj_123"`, your subsequent call can include `after="obj_123"` to fetch a new batch of objects after `"obj_123"`. |
| `limit` | integer | No | Upper limit on the number of objects to return, between `1` and `100`. Defaults to `10`. |
| `order` | "normal" \| "desc" \| "asc" | No | Order the results by the creation time. Supported values are `"asc"` (ascending), `"desc"` (descending), and `"normal"` (descending with reversed cursor semantics where `before` fetches older records and `after` fetches newer records). Defaults to `normal`. |

### PATCH /authorization/permissions/{slug}

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `name` | string | No | The new name for the permission. |
| `description` | string | No | The new description for the permission. Set to `null` to remove the description. |

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `slug` | string | Yes | A unique key to reference the permission. Must be lowercase and contain only letters, numbers, hyphens, underscores, colons, periods, and asterisks. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `permission` | object | Distinguishes the Permission object. |