# Settings

> Part of the Cowliss docs. Markdown for every page: append `index.md` to its URL. Site map: /llms.txt

<!-- GENERATED by apps/docs/scripts/generate-api-reference.ts. Do not edit. Regenerate with `pnpm -F cowliss-docs generate`. -->

Organization settings configure data handling: `eventRetentionDays` keeps events for at most 18 months, and `sendingPaused` is a platform pause that the organization can read but only the platform sets. This module is also the self-service home of the organization's two key families: ingestion API keys, which write events and reach nothing else, and pipeline keys, which push an app and reach nothing else. Any member can list either family, but only admins create and revoke them. Neither list shows the other family's keys, and revoking a key from the other family cannot find it. See the [Keys guide](/guides/keys/).

## GET /v1/settings/org

Fetch org settings

**Auth:** Session token.

**Response 200**

```json
{
  "data": {
    "eventRetentionDays": 1,
    "slug": "string",
    "name": "string"
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.eventRetentionDays` | integer | yes | 1 ≤ x ≤ 548 |
| `data.slug` | string \| null | yes |  |
| `data.name` | string \| null | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## PATCH /v1/settings/org

Update org settings

Admin only. Lowering `eventRetentionDays` permanently deletes stored events older than the new window.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "eventRetentionDays": 1
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.eventRetentionDays` | integer | yes | 1 ≤ x ≤ 548 |

**Response 200**

```json
{
  "data": {
    "eventRetentionDays": 1,
    "slug": "string",
    "name": "string"
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.eventRetentionDays` | integer | yes | 1 ≤ x ≤ 548 |
| `data.slug` | string \| null | yes |  |
| `data.name` | string \| null | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## DELETE /v1/settings/org

Delete the organization and everything in it

Admin only. The body must name the organization's slug. Starts the purge and returns at once: every run is cancelled, every row and event removed, sending domains released, keys revoked, and the organization itself deleted last. Irreversible.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "slug": "string"
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.slug` | string | yes | length 1–∞ |

**Response 202**

```json
{
  "data": {
    "workflowId": "string"
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.workflowId` | string | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## GET /v1/settings/api-keys

List org API keys

**Auth:** Session token.

**Query parameters**

```json
{
  "cursor": "string",
  "limit": 50,
  "q": "string",
  "status": "all"
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `cursor` | string | no |  |
| `limit` | integer | no | default `50`; 1 ≤ x ≤ 100 |
| `q` | string | no | length 0–200 |
| `status` | "active" \| "all" | no | default `"all"` |

**Response 200**

```json
{
  "data": [
    {
      "id": "string",
      "name": "string",
      "description": "string",
      "appIds": [
        "string"
      ],
      "createdAt": "2026-01-15T09:30:00.000Z",
      "createdBy": "string",
      "revoked": true,
      "revocationReason": "string",
      "expired": true,
      "expiresAt": "2026-01-15T09:30:00.000Z",
      "lastUsedAt": "2026-01-15T09:30:00.000Z",
      "usage": [
        {
          "appId": "string",
          "lastUsedAt": "2026-01-15T09:30:00.000Z"
        }
      ]
    }
  ],
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object[] | yes |  |
| `data[]` | object | yes |  |
| `data[].id` | string | yes |  |
| `data[].name` | string | yes |  |
| `data[].description` | string | yes |  |
| `data[].appIds` | string[] \| null | yes |  |
| `data[].createdAt` | string (date-time) | yes |  |
| `data[].createdBy` | string \| null | yes |  |
| `data[].revoked` | boolean | yes |  |
| `data[].revocationReason` | string \| null | yes |  |
| `data[].expired` | boolean | yes |  |
| `data[].expiresAt` | string (date-time) \| null | yes |  |
| `data[].lastUsedAt` | string (date-time) \| null | yes |  |
| `data[].usage` | object[] | yes |  |
| `data[].usage[]` | object | yes |  |
| `data[].usage[].appId` | string | yes |  |
| `data[].usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## POST /v1/settings/api-keys

Create an org API key

Admin only. `description` defaults to the name. `appIds` limits the key to those apps; absent, it reaches every app.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.name` | string | yes | length 3–100 |
| `data.description` | string | no | length 1–500 |
| `data.appIds` | string[] \| null | no |  |

**Response 201**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ],
    "secret": "string"
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `data.secret` | string | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## GET /v1/settings/pipeline-keys

List org pipeline keys

**Auth:** Session token.

**Query parameters**

```json
{
  "cursor": "string",
  "limit": 50,
  "q": "string",
  "status": "all"
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `cursor` | string | no |  |
| `limit` | integer | no | default `50`; 1 ≤ x ≤ 100 |
| `q` | string | no | length 0–200 |
| `status` | "active" \| "all" | no | default `"all"` |

**Response 200**

```json
{
  "data": [
    {
      "id": "string",
      "name": "string",
      "description": "string",
      "appIds": [
        "string"
      ],
      "createdAt": "2026-01-15T09:30:00.000Z",
      "createdBy": "string",
      "revoked": true,
      "revocationReason": "string",
      "expired": true,
      "expiresAt": "2026-01-15T09:30:00.000Z",
      "lastUsedAt": "2026-01-15T09:30:00.000Z",
      "usage": [
        {
          "appId": "string",
          "lastUsedAt": "2026-01-15T09:30:00.000Z"
        }
      ]
    }
  ],
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object[] | yes |  |
| `data[]` | object | yes |  |
| `data[].id` | string | yes |  |
| `data[].name` | string | yes |  |
| `data[].description` | string | yes |  |
| `data[].appIds` | string[] \| null | yes |  |
| `data[].createdAt` | string (date-time) | yes |  |
| `data[].createdBy` | string \| null | yes |  |
| `data[].revoked` | boolean | yes |  |
| `data[].revocationReason` | string \| null | yes |  |
| `data[].expired` | boolean | yes |  |
| `data[].expiresAt` | string (date-time) \| null | yes |  |
| `data[].lastUsedAt` | string (date-time) \| null | yes |  |
| `data[].usage` | object[] | yes |  |
| `data[].usage[]` | object | yes |  |
| `data[].usage[].appId` | string | yes |  |
| `data[].usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## POST /v1/settings/pipeline-keys

Create an org pipeline key

Admin only. `description` defaults to the name. `appIds` limits the key to those apps; absent, it reaches every app.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.name` | string | yes | length 3–100 |
| `data.description` | string | no | length 1–500 |
| `data.appIds` | string[] \| null | no |  |

**Response 201**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ],
    "secret": "string"
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `data.secret` | string | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## PATCH /v1/settings/pipeline-keys/{id}

Update an org pipeline key's description or apps

Admin only. `appIds` names the apps the key reaches, or null for every app (`allApps: true` says the same); calls it makes into any other app are refused, from the next call on.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "description": "string",
    "appIds": [
      "string"
    ],
    "allApps": true
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.description` | string | no | length 1–500 |
| `data.appIds` | string[] \| null | no |  |
| `data.allApps` | boolean | no |  |

**Response 200**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## POST /v1/settings/pipeline-keys/{id}/revoke

Revoke an org pipeline key

Revocation is permanent. Calls authenticating with this key stop being accepted immediately.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "revocationReason": "string"
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.revocationReason` | string | no | length 1–500 |

**Response 200**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## PATCH /v1/settings/api-keys/{id}

Update an org API key's description or apps

Admin only. `appIds` names the apps the key reaches, or null for every app (`allApps: true` says the same); calls it makes into any other app are refused. A narrower list can take up to a minute to reach calls made with this key.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "description": "string",
    "appIds": [
      "string"
    ],
    "allApps": true
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.description` | string | no | length 1–500 |
| `data.appIds` | string[] \| null | no |  |
| `data.allApps` | boolean | no |  |

**Response 200**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).

## POST /v1/settings/api-keys/{id}/revoke

Revoke an org API key

Revocation is permanent. Calls authenticating with this key can still be accepted for up to a minute.

**Auth:** Session token.

**Request body**

```json
{
  "data": {
    "revocationReason": "string"
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.revocationReason` | string | no | length 1–500 |

**Response 200**

```json
{
  "data": {
    "id": "string",
    "name": "string",
    "description": "string",
    "appIds": [
      "string"
    ],
    "createdAt": "2026-01-15T09:30:00.000Z",
    "createdBy": "string",
    "revoked": true,
    "revocationReason": "string",
    "expired": true,
    "expiresAt": "2026-01-15T09:30:00.000Z",
    "lastUsedAt": "2026-01-15T09:30:00.000Z",
    "usage": [
      {
        "appId": "string",
        "lastUsedAt": "2026-01-15T09:30:00.000Z"
      }
    ]
  },
  "meta": {
    "requestId": "string",
    "nextCursor": "string",
    "hasMore": true,
    "warnings": [
      {
        "code": "string",
        "message": "string",
        "suggestion": "string"
      }
    ]
  }
}
```

| Field | Type | Required | Constraints |
| --- | --- | --- | --- |
| `data` | object | yes |  |
| `data.id` | string | yes |  |
| `data.name` | string | yes |  |
| `data.description` | string | yes |  |
| `data.appIds` | string[] \| null | yes |  |
| `data.createdAt` | string (date-time) | yes |  |
| `data.createdBy` | string \| null | yes |  |
| `data.revoked` | boolean | yes |  |
| `data.revocationReason` | string \| null | yes |  |
| `data.expired` | boolean | yes |  |
| `data.expiresAt` | string (date-time) \| null | yes |  |
| `data.lastUsedAt` | string (date-time) \| null | yes |  |
| `data.usage` | object[] | yes |  |
| `data.usage[]` | object | yes |  |
| `data.usage[].appId` | string | yes |  |
| `data.usage[].lastUsedAt` | string (date-time) | yes |  |
| `meta` | object | no |  |
| `meta.requestId` | string | no |  |
| `meta.nextCursor` | string \| null | no |  |
| `meta.hasMore` | boolean | no |  |
| `meta.warnings` | object[] | no |  |
| `meta.warnings[]` | object | no |  |
| `meta.warnings[].code` | string | yes |  |
| `meta.warnings[].message` | string | yes |  |
| `meta.warnings[].suggestion` | string | no |  |

Errors follow the [shared envelope and code table](/api-conventions/#errors).
