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

# API keys

Manage the API keys of the organization the token was issued for, as well as the keys belonging to individual members. A key is issued its secret exactly once, at creation.

## Create an organization API key

Create an API key owned by the token's organization. The plaintext secret is returned exactly once, in this response.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation CreateOrganizationApiKey($input: CreateApiKeyInput!) {
  createOrganizationApiKey(input: $input) {
    __typename
    ... on ApiKeyPermissionsNotHeld {
      message
      unheldPermissions
    }
    ... on ApiKeyPermissionsUnsupportedForToken {
      message
      requestedPermissions
    }
    ... on InvalidApiKeyExpiration {
      message
    }
    ... on InvalidApiKeyName {
      message
    }
    ... on InvalidApiKeyPermissions {
      invalidPermissions
      message
    }
    ... on OrganizationApiKeyCreated {
      apiKey {
        createdAt
        expiresAt
        id
        lastUsedAt
        name
        obfuscatedValue
        permissions
        updatedAt
      }
      value
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "createOrganizationApiKey": {
      "__typename": "ApiKeyPermissionsNotHeld",
      "message": "message_example",
      "unheldPermissions": [
        "unheldPermissions_example"
      ]
    }
  }
}
```

:::

## Create a user API key

Create an API key owned by the token user within the organization the token was issued for. The plaintext secret is returned exactly once, in this response.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation CreateUserApiKey($input: CreateApiKeyInput!) {
  createUserApiKey(input: $input) {
    __typename
    ... on ApiKeyPermissionsNotHeld {
      message
      unheldPermissions
    }
    ... on ApiKeyPermissionsUnsupportedForToken {
      message
      requestedPermissions
    }
    ... on InvalidApiKeyExpiration {
      message
    }
    ... on InvalidApiKeyName {
      message
    }
    ... on InvalidApiKeyPermissions {
      invalidPermissions
      message
    }
    ... on UserApiKeyCreated {
      apiKey {
        createdAt
        expiresAt
        id
        lastUsedAt
        name
        obfuscatedValue
        permissions
        updatedAt
      }
      value
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "createUserApiKey": {
      "__typename": "ApiKeyPermissionsNotHeld",
      "message": "message_example",
      "unheldPermissions": [
        "unheldPermissions_example"
      ]
    }
  }
}
```

:::

## Delete an organization API key

Delete an API key owned by the token's organization and return the deleted key. Unlike expiring, this removes the key entirely.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation DeleteOrganizationApiKey($apiKeyId: ID!) {
  deleteOrganizationApiKey(apiKeyId: $apiKeyId) {
    createdAt
    expiresAt
    id
    lastUsedAt
    name
    obfuscatedValue
    permissions
    updatedAt
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "deleteOrganizationApiKey": {
      "createdAt": "2024-01-01T00:00:00.000Z",
      "expiresAt": "2024-01-01T00:00:00.000Z",
      "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
      "lastUsedAt": "2024-01-01T00:00:00.000Z",
      "name": "name_example",
      "obfuscatedValue": "obfuscatedValue_example",
      "permissions": [
        "permissions_example"
      ],
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  }
}
```

:::

## Delete a user API key

Delete a user-scoped API key and return the deleted key. Unlike expiring, this removes the key entirely.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation DeleteUserApiKey($apiKeyId: ID!) {
  deleteUserApiKey(apiKeyId: $apiKeyId) {
    createdAt
    expiresAt
    id
    lastUsedAt
    name
    obfuscatedValue
    owner {
      displayName
      email
      firstName
      id
      lastName
    }
    permissions
    updatedAt
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "deleteUserApiKey": {
      "createdAt": "2024-01-01T00:00:00.000Z",
      "expiresAt": "2024-01-01T00:00:00.000Z",
      "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
      "lastUsedAt": "2024-01-01T00:00:00.000Z",
      "name": "name_example",
      "obfuscatedValue": "obfuscatedValue_example",
      "owner": {
        "displayName": "displayName_example",
        "email": "email_example",
        "firstName": "firstName_example",
        "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
        "lastName": "lastName_example"
      },
      "permissions": [
        "permissions_example"
      ],
      "updatedAt": "2024-01-01T00:00:00.000Z"
    }
  }
}
```

:::

## Expire an organization API key

Revoke an API key owned by the token's organization by setting its expiration. The key and its audit trail are retained; use `deleteOrganizationApiKey` to remove it.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation ExpireOrganizationApiKey($input: ExpireApiKeyInput!) {
  expireOrganizationApiKey(input: $input) {
    __typename
    ... on ApiKeyAlreadyExpired {
      apiKeyId
    }
    ... on OrganizationApiKeyExpired {
      apiKey {
        createdAt
        expiresAt
        id
        lastUsedAt
        name
        obfuscatedValue
        permissions
        updatedAt
      }
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "expireOrganizationApiKey": {
      "__typename": "ApiKeyAlreadyExpired",
      "apiKeyId": "apiKeyId_01EHWNCE74X7JSDV0X3SZ3KJNY"
    }
  }
}
```

:::

## Expire a user API key

Revoke a user-scoped API key by setting its expiration. The key and its audit trail are retained; use `deleteUserApiKey` to remove it.

:::code-group

```graphql language="graphql" title="Mutation" tab="1"
mutation ExpireUserApiKey($input: ExpireApiKeyInput!) {
  expireUserApiKey(input: $input) {
    __typename
    ... on ApiKeyAlreadyExpired {
      apiKeyId
    }
    ... on UserApiKeyExpired {
      apiKey {
        createdAt
        expiresAt
        id
        lastUsedAt
        name
        obfuscatedValue
        permissions
        updatedAt
      }
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "expireUserApiKey": {
      "__typename": "ApiKeyAlreadyExpired",
      "apiKeyId": "apiKeyId_01EHWNCE74X7JSDV0X3SZ3KJNY"
    }
  }
}
```

:::

## List organization API keys

List the active API keys owned by the token's organization. Secrets are never included.

:::code-group

```graphql language="graphql" title="Query" tab="1"
query OrganizationApiKeys($after: String, $before: String, $limit: Int, $order: PaginationOrder, $search: String) {
  organizationApiKeys(after: $after, before: $before, limit: $limit, order: $order, search: $search) {
    data {
      createdAt
      expiresAt
      id
      lastUsedAt
      name
      obfuscatedValue
      permissions
      updatedAt
    }
    listMetadata {
      after
      before
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "organizationApiKeys": {
      "data": [
        {
          "createdAt": "2024-01-01T00:00:00.000Z",
          "expiresAt": "2024-01-01T00:00:00.000Z",
          "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
          "lastUsedAt": "2024-01-01T00:00:00.000Z",
          "name": "name_example",
          "obfuscatedValue": "obfuscatedValue_example",
          "permissions": [
            "permissions_example"
          ],
          "updatedAt": "2024-01-01T00:00:00.000Z"
        }
      ],
      "listMetadata": {
        "after": "after_example",
        "before": "before_example"
      }
    }
  }
}
```

:::

## List user API keys

List the active user-scoped API keys in the token's organization. Returns only the token user's own keys unless the token holds the organization-wide user API key grant. Secrets are never included.

:::code-group

```graphql language="graphql" title="Query" tab="1"
query UserApiKeys($after: String, $before: String, $limit: Int, $order: PaginationOrder, $search: String) {
  userApiKeys(after: $after, before: $before, limit: $limit, order: $order, search: $search) {
    data {
      createdAt
      expiresAt
      id
      lastUsedAt
      name
      obfuscatedValue
      owner {
        displayName
        email
        firstName
        id
        lastName
      }
      permissions
      updatedAt
    }
    listMetadata {
      after
      before
    }
  }
}
```

```json language="json" title="Response" tab="2"
{
  "data": {
    "userApiKeys": {
      "data": [
        {
          "createdAt": "2024-01-01T00:00:00.000Z",
          "expiresAt": "2024-01-01T00:00:00.000Z",
          "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
          "lastUsedAt": "2024-01-01T00:00:00.000Z",
          "name": "name_example",
          "obfuscatedValue": "obfuscatedValue_example",
          "owner": {
            "displayName": "displayName_example",
            "email": "email_example",
            "firstName": "firstName_example",
            "id": "id_01EHWNCE74X7JSDV0X3SZ3KJNY",
            "lastName": "lastName_example"
          },
          "permissions": [
            "permissions_example"
          ],
          "updatedAt": "2024-01-01T00:00:00.000Z"
        }
      ],
      "listMetadata": {
        "after": "after_example",
        "before": "before_example"
      }
    }
  }
}
```

:::

### Mutation createOrganizationApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `expiresAt` | DateTime | No | When the key should expire. Must be in the future. Omit for a key that never expires. |
| `name` | String! | Yes | The human-readable name of the key. |
| `permissions` | [String!] | No | The permission slugs to grant the key. Each slug must be enabled for API keys in the environment, and must be a permission the caller itself holds. Defaults to no permissions. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `ApiKeyPermissionsNotHeld` | ApiKeyPermissionsNotHeld | One or more requested permission slugs are not held by the caller. A key never carries more than the caller minting it holds, so the caller must be granted a permission before it can grant it to a key. |
| `ApiKeyPermissionsUnsupportedForToken` | ApiKeyPermissionsUnsupportedForToken | The token cannot grant permissions to a key. The caller is not acting as a member of the organization, so there is no set of held permissions to bound the key to; such a token can only create a key with no permissions. |
| `InvalidApiKeyExpiration` | InvalidApiKeyExpiration | The requested expiration is not valid. |
| `InvalidApiKeyName` | InvalidApiKeyName | The provided name is not a valid API key name. |
| `InvalidApiKeyPermissions` | InvalidApiKeyPermissions | One or more requested permission slugs are not enabled for API keys of this kind in the environment. |
| `OrganizationApiKeyCreated` | OrganizationApiKeyCreated | The organization API key was created. |

### Mutation createUserApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `expiresAt` | DateTime | No | When the key should expire. Must be in the future. Omit for a key that never expires. |
| `name` | String! | Yes | The human-readable name of the key. |
| `permissions` | [String!] | No | The permission slugs to grant the key. Each slug must be enabled for API keys in the environment, and must be a permission the caller itself holds. Defaults to no permissions. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `ApiKeyPermissionsNotHeld` | ApiKeyPermissionsNotHeld | One or more requested permission slugs are not held by the caller. A key never carries more than the caller minting it holds, so the caller must be granted a permission before it can grant it to a key. |
| `ApiKeyPermissionsUnsupportedForToken` | ApiKeyPermissionsUnsupportedForToken | The token cannot grant permissions to a key. The caller is not acting as a member of the organization, so there is no set of held permissions to bound the key to; such a token can only create a key with no permissions. |
| `InvalidApiKeyExpiration` | InvalidApiKeyExpiration | The requested expiration is not valid. |
| `InvalidApiKeyName` | InvalidApiKeyName | The provided name is not a valid API key name. |
| `InvalidApiKeyPermissions` | InvalidApiKeyPermissions | One or more requested permission slugs are not enabled for API keys of this kind in the environment. |
| `UserApiKeyCreated` | UserApiKeyCreated | The user-scoped API key was created. |

### Mutation deleteOrganizationApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKeyId` | ID! | Yes |  |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `createdAt` | DateTime! |  |
| `expiresAt` | DateTime | When the key expires. A key with an expiration in the past is revoked and can no longer authenticate. |
| `id` | ID! |  |
| `lastUsedAt` | DateTime | When the key was last used to authenticate, if ever. |
| `name` | String! | The human-readable name of the key. |
| `obfuscatedValue` | String! | A redacted form of the secret, safe to display. The secret itself is only ever returned when the key is created. |
| `permissions` | [String!]! | The permission slugs the key carries. |
| `updatedAt` | DateTime! |  |

### Mutation deleteUserApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKeyId` | ID! | Yes |  |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `createdAt` | DateTime! |  |
| `expiresAt` | DateTime | When the key expires. A key with an expiration in the past is revoked and can no longer authenticate. |
| `id` | ID! |  |
| `lastUsedAt` | DateTime | When the key was last used to authenticate, if ever. |
| `name` | String! | The human-readable name of the key. |
| `obfuscatedValue` | String! | A redacted form of the secret, safe to display. The secret itself is only ever returned when the key is created. |
| `owner` | UserApiKeyOwner! | The userland user a user-scoped API key belongs to. |
| `permissions` | [String!]! | The permission slugs the key carries. |
| `updatedAt` | DateTime! |  |

### Mutation expireOrganizationApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKeyId` | ID! | Yes | The ID of the key to expire. |
| `expiresAt` | DateTime | No | When the key should expire. A future date schedules expiration; `null` clears any scheduled expiration; omitting the field, or passing a date in the past, revokes the key immediately. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `ApiKeyAlreadyExpired` | ApiKeyAlreadyExpired | The key is already expired, so its expiration cannot change. |
| `OrganizationApiKeyExpired` | OrganizationApiKeyExpired | The expiration of the organization API key was updated. The key is retained. |

### Mutation expireUserApiKey

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `apiKeyId` | ID! | Yes | The ID of the key to expire. |
| `expiresAt` | DateTime | No | When the key should expire. A future date schedules expiration; `null` clears any scheduled expiration; omitting the field, or passing a date in the past, revokes the key immediately. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `ApiKeyAlreadyExpired` | ApiKeyAlreadyExpired | The key is already expired, so its expiration cannot change. |
| `UserApiKeyExpired` | UserApiKeyExpired | The expiration of the user-scoped API key was updated. The key is retained. |

### Query organizationApiKeys

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `after` | String | No |  |
| `before` | String | No |  |
| `limit` | Int | No |  |
| `order` | PaginationOrder | No | Enum represents the pagination order. |
| `search` | String | No | Filter keys by a substring of their name. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `data` | [OrganizationApiKey!]! | An API key owned by the organization the token was issued for. A tenant-level credential: it is not tied to any user. |
| `listMetadata` | ListMetadata! |  |

### Query userApiKeys

#### Parameters

| Parameter | Type | Required | Description |
| --- | --- | --- | --- |
| `after` | String | No |  |
| `before` | String | No |  |
| `limit` | Int | No |  |
| `order` | PaginationOrder | No | Enum represents the pagination order. |
| `search` | String | No | Filter keys by a substring of their name. |

#### Returns

| Field | Type | Description |
| --- | --- | --- |
| `data` | [UserApiKey!]! | An API key owned by a member of the token's organization. A user-scoped key acts as that user, so it is never interchangeable with an organization API key. |
| `listMetadata` | ListMetadata! |  |