# Cache registries

Use these endpoints to list, inspect, create, update, and delete a cluster's [cache registries](/docs/pipelines/configure/cache#manage-cache-registries).

> 📘 Public preview
> The cache registries API is available to all Buildkite customers in public preview. This availability applies to registry administration only. Saving and restoring cache entries with Buildkite Cache remains in private preview and requires access as described in the [Buildkite Cache guide](/docs/pipelines/configure/cache).

This API manages cache registry metadata and policy only. The API doesn't expose cache entries or agent save and restore operations. Use the web interface to configure a registry's cache store or change a cluster's default registry.

Member endpoints (get, update, and delete) accept only the cache registry's `uuid` as the `{id}` path parameter. The `slug` returned in responses is informational and can't be used to look up or modify a cache registry.

Policy documents must be JSON objects, not YAML or JSON-encoded strings. The API validates and normalizes each policy, so authored YAML comments and formatting aren't preserved. The create and update sections describe how omitted or `null` policies behave.

## Cache registry data model



| `uuid` | UUID of the cache registry. Use this value as the `{id}` path parameter for the get, update, and delete endpoints. |
| --- | --- |
| `slug` | Slug generated from the cache registry's name. Informational only, and not accepted as an identifier. |
| `name` | Name of the cache registry. |
| `description` | Description of the cache registry, or `null`. |
| `emoji` | Emoji for the cache registry using the [emoji syntax](/docs/pipelines/emojis), or `null`. |
| `color` | Color hex code for the cache registry, or `null`. |
| `policy` | Normalized [cache policy](/docs/pipelines/configure/cache#manage-cache-registries-configure-a-cache-policy) that controls which jobs can save and restore entries in this registry, or `null`. |
| `created_at` | When the cache registry was created. |
| `updated_at` | When the cache registry was last updated. |
| `url` | Canonical API URL of the cache registry. |
| `cluster_url` | API URL of the parent cluster. |



## List cache registries

Returns a paginated list of a cluster's cache registries, ordered by slug.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  -X GET "https://api.buildkite.com/v2/organizations/{org.slug}/clusters/{cluster.id}/cache-registries?per_page=30"
```

```json
{
  "items": [
    {
      "uuid": "b3a1e9f2-7c4d-4f1a-9e6c-2d8a5f7b1c3d",
      "slug": "ruby-gems",
      "name": "Ruby gems",
      "description": "Shared Ruby dependencies",
      "emoji": "\u003aruby\u003a",
      "color": "#cc342d",
      "policy": {
        "save": { "scopes": { "branch": true } },
        "restore": { "scopes": [{ "branch": "$current" }] },
        "rules": [
          { "effect": "allow", "action": ["save"] },
          { "effect": "allow", "action": ["restore"] }
        ]
      },
      "created_at": "2026-08-11T10:15:32.000Z",
      "updated_at": "2026-08-11T10:15:32.000Z",
      "url": "https://api.buildkite.com/v2/organizations/acme-inc/clusters/42f1a7da-812d-4430-93d8-1cc7c33a6bcf/cache-registries/b3a1e9f2-7c4d-4f1a-9e6c-2d8a5f7b1c3d",
      "cluster_url": "https://api.buildkite.com/v2/organizations/acme-inc/clusters/42f1a7da-812d-4430-93d8-1cc7c33a6bcf"
    }
  ],
  "links": {
    "self": "https://api.buildkite.com/v2/organizations/acme-inc/clusters/42f1a7da-812d-4430-93d8-1cc7c33a6bcf/cache-registries?per_page=30",
    "next": "https://api.buildkite.com/v2/organizations/acme-inc/clusters/42f1a7da-812d-4430-93d8-1cc7c33a6bcf/cache-registries?after=...&per_page=30"
  }
}
```

This endpoint uses cursor-based pagination. The response body is a JSON object with an `items` array and a `links` object. Use the `next` URL from `links` to fetch the next page. Follow that URL instead of constructing cursor values.

Optional [query string parameters](/docs/api#query-string-parameters):



| `per_page` | How many results to return per page. _Default:_ `30` _Maximum:_ `100` |
| --- | --- |
| `after` | Return results after this cursor value. Mutually exclusive with `before`. |
| `before` | Return results before this cursor value. Mutually exclusive with `after`. |



Required scope: `read_clusters`

Required permission: permission to manage the cluster

Success response: `200 OK`

Error responses:



| `400 Bad Request` | Invalid `per_page` or cursor value, or both `after` and `before` supplied |
| --- | --- |
| `404 Not Found` | The cluster doesn't exist |



## Get a cache registry

Returns the details for a single cache registry, looked up by UUID.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  -X GET "https://api.buildkite.com/v2/organizations/{org.slug}/clusters/{cluster.id}/cache-registries/{id}"
```

The response contains the [cache registry data model](#cache-registry-data-model).

Required scope: `read_clusters`

Required permission: permission to manage the cluster

Success response: `200 OK`

Error response: `404 Not Found` when the cluster doesn't exist, or when no cache registry matches the given UUID in this cluster. Passing a slug instead of a UUID also returns `404 Not Found`.

## Create a cache registry

Creates a new cache registry in a cluster.

> 🚧 Use this policy only with trusted builds
> This example allows every job to save and restore cache entries. Use it only for registries used exclusively by trusted builds. Branch names aren't trust boundaries, and this policy can share entries across pipelines. Don't allow untrusted builds to save caches that trusted builds can restore. See [Configure a cache policy](/docs/pipelines/configure/cache#manage-cache-registries-configure-a-cache-policy) before sharing a registry with untrusted builds.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  -X POST "https://api.buildkite.com/v2/organizations/{org.slug}/clusters/{cluster.id}/cache-registries" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ruby gems",
    "description": "Shared Ruby dependencies",
    "emoji": "\u003aruby\u003a",
    "color": "#cc342d",
    "policy": {
      "save": { "scopes": { "branch": true } },
      "restore": { "scopes": [{ "branch": "$current" }] },
      "rules": [
        { "effect": "allow", "action": "save" },
        { "effect": "allow", "action": "restore" }
      ]
    }
  }'
```

The response contains the created [cache registry data model](#cache-registry-data-model).

Required [request body properties](/docs/api#request-body-properties):



| `name` | Name of the cache registry. _Example:_ `"Ruby gems"` |
| --- | --- |



Optional [request body properties](/docs/api#request-body-properties):



| `description` | Description of the cache registry. |
| --- | --- |
| `emoji` | Emoji for the cache registry using the [emoji syntax](/docs/pipelines/emojis). |
| `color` | Color hex code for the cache registry. |
| `policy` | Cache policy as a JSON object that controls which jobs can save and restore entries. See [Configure a cache policy](/docs/pipelines/configure/cache#manage-cache-registries-configure-a-cache-policy) for the policy structure. Omit this property or set it to `null` when creating a registry to use the default unrestricted policy. |



The cache store can't be set through this API. New cache registries use agent-managed storage.

Required scope: `write_clusters`

Required permission: permission to manage the cluster

Success response: `201 Created`

Error responses:



| `400 Bad Request` | The request body isn't a valid JSON object |
| --- | --- |
| `404 Not Found` | The cluster doesn't exist |
| `415 Unsupported Media Type` | The request doesn't use an `application/json` content type |
| `422 Unprocessable Entity` | The request is missing `name`, contains an unsupported field or invalid policy, or a cache registry with the resulting slug already exists in this cluster |



## Update a cache registry

Updates a cache registry, looked up by UUID. Properties omitted from the request body are left unchanged. Supplying `policy` replaces the entire policy rather than merging its nested properties.

> 🚧 Use this policy only with trusted builds
> This example allows every job to save and restore cache entries within its pipeline. Use it only for registries used exclusively by trusted builds. Pipeline scoping doesn't isolate trusted and untrusted builds within the same pipeline. Don't allow untrusted builds to save caches that trusted builds can restore.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  -X PATCH "https://api.buildkite.com/v2/organizations/{org.slug}/clusters/{cluster.id}/cache-registries/{id}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Ruby gems",
    "description": "Updated description",
    "policy": {
      "save": { "scopes": { "pipeline": true } },
      "restore": { "scopes": [{ "pipeline": "$current" }] },
      "rules": [
        { "effect": "allow", "action": "save" },
        { "effect": "allow", "action": "restore" }
      ]
    }
  }'
```

The response contains the updated [cache registry data model](#cache-registry-data-model).

Optional [request body properties](/docs/api#request-body-properties):



| `name` | Name of the cache registry. Changing the name regenerates the registry's slug. |
| --- | --- |
| `description` | Description of the cache registry. Set to `null` to clear it. |
| `emoji` | Emoji for the cache registry using the [emoji syntax](/docs/pipelines/emojis). Set to `null` to clear it. |
| `color` | Color hex code for the cache registry. Set to `null` to clear it. |
| `policy` | Cache policy as a JSON object that controls which jobs can save and restore entries. See [Configure a cache policy](/docs/pipelines/configure/cache#manage-cache-registries-configure-a-cache-policy) for the policy structure. Set to `null` to clear the policy, which denies saves and restores. Unlike creation, updating with `null` doesn't apply the default unrestricted policy. |



The cache registry's `uuid` and cache store can't be changed through this API.

Required scope: `write_clusters`

Required permission: permission to manage the cluster

Success response: `200 OK`

Error responses:



| `400 Bad Request` | The request body isn't a valid JSON object |
| --- | --- |
| `404 Not Found` | The cluster doesn't exist, or no cache registry matches the given UUID in this cluster |
| `415 Unsupported Media Type` | The request doesn't use an `application/json` content type |
| `422 Unprocessable Entity` | The request contains an unsupported field, attempts to change the `uuid` or cache store, contains an invalid policy, or a cache registry with the resulting slug already exists in this cluster |



## Delete a cache registry

Deletes a cache registry, looked up by UUID. A cluster's default cache registry can't be deleted. First, [open another registry in the web interface](/docs/pipelines/configure/cache#manage-cache-registries) and select **Settings** > **Set as default**.

```bash
curl -H "Authorization: Bearer $TOKEN" \
  -X DELETE "https://api.buildkite.com/v2/organizations/{org.slug}/clusters/{cluster.id}/cache-registries/{id}"
```

Required scope: `write_clusters`

Required permission: permission to manage the cluster, and permission to destroy the cache registry

Success response: `204 No Content`

Error responses:



| `404 Not Found` | The cluster doesn't exist, or no cache registry matches the given UUID in this cluster |
| --- | --- |
| `422 Unprocessable Entity` | The cache registry is the cluster's default registry |


