# Use the Schema Registry API

> For the complete documentation index, see [llms.txt](https://docs.redpanda.com/llms.txt). Component-specific: [cloud-data-platform-full.txt](https://docs.redpanda.com/cloud-data-platform-full.txt)

---
title: Use the Schema Registry API
latest-operator-version: v26.1.4
latest-console-tag: v3.7.3
latest-connect-version: 4.93.0
latest-redpanda-tag: v26.1.9
docname: schema-reg/schema-reg-api
page-component-name: cloud-data-platform
page-version: master
page-component-version: master
page-component-title: Cloud
page-relative-src-path: schema-reg/schema-reg-api.adoc
page-edit-url: https://github.com/redpanda-data/cloud-docs/edit/main/modules/manage/pages/schema-reg/schema-reg-api.adoc
description: Perform common Schema Registry management operations with the API.
page-git-created-date: "2024-07-25"
page-git-modified-date: "2026-05-26"
---

<!-- Source: https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/schema-reg-api.md -->

Schemas provide human-readable documentation for an API. They verify that data conforms to an API, support the generation of serializers for data, and manage the compatibility of evolving APIs, allowing new versions of services to be rolled out independently.

> 📝 **NOTE**
>
> The Schema Registry is built into Redpanda, and you can use it with the API or the UI. This section describes operations available in the [Schema Registry API](https://docs.redpanda.com/api/doc/schema-registry/).

The Redpanda Schema Registry has API endpoints that allow you to perform the following tasks:

-   Register schemas for a subject. When data formats are updated, a new version of the schema can be registered under the same subject, allowing for backward and forward compatibility.

-   Retrieve schemas of specific versions.

-   Retrieve a list of subjects.

-   Retrieve a list of schema versions for a subject.

-   Configure schema compatibility checking.

-   Query supported serialization formats.

-   Delete schemas from the registry.


The following examples cover the basic functionality of the Redpanda Schema Registry based on an example Avro schema called `sensor_sample`. This schema contains fields that represent a measurement from a sensor for the value of the `sensor` topic, as defined below.

```json
{
  "type": "record",
  "name": "sensor_sample",
  "fields": [
    {
      "name": "timestamp",
      "type": "long",
      "logicalType": "timestamp-millis"
    },
    {
      "name": "identifier",
      "type": "string",
      "logicalType": "uuid"
    },
    {
      "name": "value",
      "type": "long"
    }
  ]
}
```

## [](#prerequisites)Prerequisites

To run the sample commands and code in each example, follow these steps to set up Redpanda and other tools:

1.  You need a running Redpanda cluster. If you don’t have one, you can [create a cluster](https://docs.redpanda.com/cloud-data-platform/get-started/cluster-types/serverless/) using Redpanda Serverless.

    In these examples, it is assumed that the Schema Registry is available locally at `[http://localhost:8081](http://localhost:8081)`. If the Schema Registry is hosted on a different address or port in your cluster, change the URLs in the examples.

2.  Download the [jq utility](https://stedolan.github.io/jq/download/).

3.  Install [curl](https://curl.se/) or [Python](https://www.python.org/).

    You can also use [`rpk`](https://docs.redpanda.com/cloud-data-platform/manage/rpk/intro-to-rpk/) to interact with the Schema Registry. The [`rpk registry`](https://docs.redpanda.com/cloud-data-platform/reference/rpk/rpk-registry/rpk-registry/) set of commands call the different API endpoints as shown in the curl and Python examples.

    If using Python, install the [Requests module](https://requests.readthedocs.io/en/latest/user/install/#install), then create an interactive Python session:

    ```python
    import requests
    import json
    def pretty(text):
      print(json.dumps(text, indent=2))

    base_uri = "http://localhost:8081"
    ```


## [](#query-supported-schema-formats)Query supported schema formats

To get the supported data serialization formats in the Schema Registry, make a GET request to the `/schemas/types` endpoint:

### Curl

```bash
curl -s "http://localhost:8081/schemas/types" | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/schemas/types').json()
pretty(res)
```

This returns the supported serialization formats:

\[
  "JSON",
  "PROTOBUF",
  "AVRO"
\]

## [](#register-a-schema)Register a schema

A schema is registered in the registry with a _subject_, which is a name that is associated with the schema as it evolves. Subjects are typically in the form `<topic-name>-key` or `<topic-name>-value`.

To register the `sensor_sample` schema, make a POST request to the `/subjects/sensor-value/versions` endpoint with the Content-Type `application/vnd.schemaregistry.v1+json`:

### rpk

```bash
rpk registry schema create sensor-value --schema ~/code/tmp/sensor_sample.avro
```

### Curl

```bash
curl -s \
  -X POST \
  "http://localhost:8081/subjects/sensor-value/versions" \
  -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  -d '{"schema": "{\"type\":\"record\",\"name\":\"sensor_sample\",\"fields\":[{\"name\":\"timestamp\",\"type\":\"long\",\"logicalType\":\"timestamp-millis\"},{\"name\":\"identifier\",\"type\":\"string\",\"logicalType\":\"uuid\"},{\"name\":\"value\",\"type\":\"long\"}]}"}' \
  | jq
```

To normalize the schema, add the query parameter `?normalize=true` to the endpoint.

### Python

```python
sensor_schema = {
  "type": "record",
  "name": "sensor_sample",
  "fields": [
    {
      "name": "timestamp",
      "type": "long",
      "logicalType": "timestamp-millis"
    },
    {
      "name": "identifier",
      "type": "string",
      "logicalType": "uuid"
    },
    {
      "name": "value",
      "type": "long"
    }
  ]
}

res = requests.post(
    url=f'{base_uri}/subjects/sensor-value/versions',
    data=json.dumps({
      'schema': json.dumps(sensor_schema)
    }),
    headers={'Content-Type': 'application/vnd.schemaregistry.v1+json'}).json()
pretty(res)
```

This returns the version `id` unique for the schema in the Redpanda cluster:

### rpk

SUBJECT        VERSION  ID    TYPE
sensor-value   1        1     AVRO

### Curl

```json
{
  "id": 1
}
```

When you register an evolved schema for an existing subject, the version `id` is incremented by 1.

## [](#use-schema-registry-contexts)Use Schema Registry contexts

Starting in Redpanda v26.1, you can use contexts to create isolated namespaces for schemas, subjects, and configuration within a single Schema Registry instance.

To use contexts on BYOC and Dedicated clusters, [configure the cluster property](https://docs.redpanda.com/cloud-data-platform/manage/cluster-maintenance/config-cluster/) `schema_registry_enable_qualified_subjects`. See [Schema Registry Contexts](https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/schema-reg-contexts/) for details.

Contexts are created implicitly when you register a schema using a context-qualified subject. For example, registering a schema with the subject `:.staging:sensor-value` creates the `.staging` context if it does not already exist:

```bash
curl -s -X POST \
  http://localhost:8081/subjects/:.staging:sensor-value/versions \
  -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  -d '{"schema": "{\"type\":\"string\"}"}'
```

## [](#retrieve-a-schema)Retrieve a schema

To retrieve a registered schema from the registry, make a GET request to the `/schemas/ids/{id}` endpoint:

### rpk

```bash
rpk registry schema get --id 1
```

### Curl

```bash
curl -s \
  "http://localhost:8081/schemas/ids/1" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/schemas/ids/1').json()
pretty(res)
```

The rpk output returns the subject and version, and the HTTP response returns the schema:

### rpk

SUBJECT        VERSION  ID    TYPE
sensor-value   1        1     AVRO

### Curl

```json
{
  "schema": "{\"type\":\"record\",\"name\":\"sensor_sample\",\"fields\":[{\"name\":\"timestamp\",\"type\":\"long\",\"logicalType\":\"timestamp-millis\"},{\"name\":\"identifier\",\"type\":\"string\",\"logicalType\":\"uuid\"},{\"name\":\"value\",\"type\":\"long\"}]}"
}
```

## [](#list-registry-subjects)List registry subjects

To list all registry subjects, make a GET request to the `/subjects` endpoint:

### rpk

```bash
rpk registry subject list --format json
```

### Curl

```bash
curl -s \
  "http://localhost:8081/subjects" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/subjects').json()
pretty(res)
```

This returns the subject:

```json
[
  "sensor-value"
]
```

## [](#retrieve-schema-versions-of-a-subject)Retrieve schema versions of a subject

To query the schema versions of a subject, make a GET request to the `/subjects/{subject}/versions` endpoint.

For example, to get the schema versions of the `sensor-value` subject:

### Curl

```bash
curl -s \
  "http://localhost:8081/subjects/sensor-value/versions" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/subjects/sensor-value/versions').json()
pretty(res)
```

This returns the version ID:

```json
[
  1
]
```

## [](#retrieve-a-subjects-specific-version-of-a-schema)Retrieve a subject’s specific version of a schema

To retrieve a specific version of a schema associated with a subject, make a GET request to the `/subjects/{subject}/versions/{version}` endpoint:

### rpk

```bash
rpk registry schema get sensor-value --schema-version 1
```

### Curl

```bash
curl -s \
  "http://localhost:8081/subjects/sensor-value/versions/1" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/subjects/sensor-value/versions/1').json()
pretty(res)
```

The rpk output returns the subject, and for HTTP requests, its associated schema as well:

### rpk

SUBJECT        VERSION  ID    TYPE
sensor-value   1        1     AVRO

### Curl

```json
{
  "subject": "sensor-value",
  "id": 1,
  "version": 1,
  "schema": "{\"type\":\"record\",\"name\":\"sensor_sample\",\"fields\":[{\"name\":\"timestamp\",\"type\":\"long\",\"logicalType\":\"timestamp-millis\"},{\"name\":\"identifier\",\"type\":\"string\",\"logicalType\":\"uuid\"},{\"name\":\"value\",\"type\":\"long\"}]}"
}
```

To get the latest version, use `latest` as the version ID:

### rpk

```bash
rpk registry schema get sensor-value --schema-version latest
```

### Curl

```bash
curl -s \
  "http://localhost:8081/subjects/sensor-value/versions/latest" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/subjects/sensor-value/versions/latest').json()
pretty(res)
```

To get only the schema, append `/schema` to the endpoint path:

### Curl

```bash
curl -s \
  "http://localhost:8081/subjects/sensor-value/versions/latest/schema" \
  | jq .
```

### Python

```python
res = requests.get(f'{base_uri}/subjects/sensor-value/versions/latest/schema').json()
pretty(res)
```

```json
{
  "type": "record",
  "name": "sensor_sample",
  "fields": [
    {
      "name": "timestamp",
      "type": "long",
      "logicalType": "timestamp-millis"
    },
    {
      "name": "identifier",
      "type": "string",
      "logicalType": "uuid"
    },
    {
      "name": "value",
      "type": "long"
    }
  ]
}
```

## [](#configure-schema-compatibility)Configure schema compatibility

As applications change and their schemas evolve, you may find that producer schemas and consumer schemas are no longer compatible. You decide how you want a consumer to handle data from a producer that uses an older or newer schema.

Applications are often modeled around a specific business object structure. As applications change and the shape of their data changes, producer schemas and consumer schemas may no longer be compatible. You can decide how a consumer handles data from a producer that uses an older or newer schema, and reduce the chance of consumers hitting deserialization errors.

You can configure different types of schema compatibility, which are applied to a subject when a new schema is registered. The Schema Registry supports the following compatibility types:

-   `BACKWARD` (**default**) - Consumers using the new schema (for example, version 10) can read data from producers using the previous schema (for example, version 9).

-   `BACKWARD_TRANSITIVE` - Consumers using the new schema (for example, version 10) can read data from producers using all previous schemas (for example, versions 1-9).

-   `FORWARD` - Consumers using the previous schema (for example, version 9) can read data from producers using the new schema (for example, version 10).

-   `FORWARD_TRANSITIVE` - Consumers using any previous schema (for example, versions 1-9) can read data from producers using the new schema (for example, version 10).

-   `FULL` - A new schema and the previous schema (for example, versions 10 and 9) are both backward and forward compatible with each other.

-   `FULL_TRANSITIVE` - Each schema is both backward and forward compatible with all registered schemas.

-   `NONE` - No schema compatibility checks are done.


### [](#compatibility-uses-and-constraints)Compatibility uses and constraints

-   A consumer that wants to read a topic from the beginning (for example, an AI learning process) benefits from backward compatibility. It can process the whole topic using the latest schema. This allows producers to remove fields and add attributes.

-   A real-time consumer that doesn’t care about historical events but wants to keep up with the latest data (for example, a typical streaming application) benefits from forward compatibility. Even if producers change the schema, the consumer can carry on.

-   Full compatibility can process historical data and future data. This is the safest option, but it limits the changes that can be done. This only allows for the addition and removal of optional fields.


If you make changes that are not inherently backward-compatible, you may need to change compatibility settings or plan a transitional period, updating producers and consumers to use the new schema while the old one is still accepted.

| Schema format | Backward-compatible tasks | Not backward-compatible tasks |
| --- | --- | --- |
| Avro | Add fields with default valuesMake fields nullable | Remove fieldsChange data types of fieldsChange enum valuesChange field constraintsChange record of field names |
| Protobuf | Add fieldsRemove fields | Remove required fieldsChange data types of fields |
| JSON | Add optional propertiesRelax constraints, for example:Decrease a minimum value or increase a maximum valueDecrease minItems, minLength, or minProperties; increase maxItems, maxLength, maxPropertiesAdd more property types (for example, "type": "integer" to "type": ["integer", "string"])Add more enum valuesReduce multipleOf by an integral factorRelaxing additional properties if additionalProperties was not previously specified as falseRemoving a uniqueItems property that was false | Remove propertiesAdd required propertiesChange property names and typesTighten or add constraints |

To set the compatibility type for a subject, make a PUT request to `/config/{subject}` with the specific compatibility type:

#### rpk

```bash
rpk registry compatibility-level set sensor-value --level BACKWARD
```

#### Curl

```bash
curl -s \
  -X PUT \
  "http://localhost:8081/config/sensor-value" \
  -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  -d '{"compatibility": "BACKWARD"}' \
  | jq .
```

#### Python

```python
res = requests.put(
    url=f'{base_uri}/config/sensor-value',
    data=json.dumps(
        {'compatibility': 'BACKWARD'}
      ),
    headers={'Content-Type': 'application/vnd.schemaregistry.v1+json'}).json()
pretty(res)
```

This returns the new compatibility type:

#### rpk

SUBJECT        LEVEL     ERROR
sensor-value   BACKWARD

#### Curl

```json
{
  "compatibility": "BACKWARD"
}
```

If you POST an incompatible schema change, the request returns an error. For example, if you try to register a new schema with the `value` field’s type changed from `long` to `int`, and compatibility is set to `BACKWARD`, the request returns an error due to incompatibility:

#### Curl

```bash
curl -s \
  -X POST \
  "http://localhost:8081/subjects/sensor-value/versions" \
  -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  -d '{"schema": "{\"type\":\"record\",\"name\":\"sensor_sample\",\"fields\":[{\"name\":\"timestamp\",\"type\":\"long\",\"logicalType\":\"timestamp-millis\"},{\"name\":\"identifier\",\"type\":\"string\",\"logicalType\":\"uuid\"},{\"name\":\"value\",\"type\":\"int\"}]}"}' \
  | jq
```

#### Python

```python
sensor_schema["fields"][2]["type"] = "int"

res = requests.post(
    url=f'{base_uri}/subjects/sensor-value/versions',
    data=json.dumps({
      'schema': json.dumps(sensor_schema)
    }),
    headers={'Content-Type': 'application/vnd.schemaregistry.v1+json'}).json()
pretty(res)
```

The request returns this error:

```json
{
  "error_code": 409,
  "message": "Schema being registered is incompatible with an earlier schema for subject \"{sensor-value}\""
}
```

For an example of a compatible change, register a schema with the `value` field’s type changed from `long` to `double`:

#### Curl

```bash
curl -s \
  -X POST \
  "http://localhost:8081/subjects/sensor-value/versions" \
  -H "Content-Type: application/vnd.schemaregistry.v1+json" \
  -d '{"schema": "{\"type\":\"record\",\"name\":\"sensor_sample\",\"fields\":[{\"name\":\"timestamp\",\"type\":\"long\",\"logicalType\":\"timestamp-millis\"},{\"name\":\"identifier\",\"type\":\"string\",\"logicalType\":\"uuid\"},{\"name\":\"value\",\"type\":\"double\"}]}"}' \
  | jq
```

#### Python

```python
sensor_schema["fields"][2]["type"] = "double"

res = requests.post(
    url=f'{base_uri}/subjects/sensor-value/versions',
    data=json.dumps({
      'schema': json.dumps(sensor_schema)
    }),
    headers={'Content-Type': 'application/vnd.schemaregistry.v1+json'}).json()
pretty(res)
```

A successful registration returns the schema’s `id`:

```json
{
  "id": 2
}
```

## [](#reference-a-schema)Reference a schema

To build more complex schema definitions, you can add a reference to other schemas. The following example registers a Protobuf schema in subject `test-simple` with a message name `Simple`.

### rpk

```bash
rpk registry schema create test-simple --schema simple.proto
```

```none
SUBJECT        VERSION  ID    TYPE
test-simple    1        2     PROTOBUF
```

### Curl

```bash
curl -X POST -H 'Content-type: application/vnd.schemaregistry.v1+json' http://127.0.0.1:8081/subjects/test-simple/versions -d '{"schema": "syntax = \"proto3\";\nmessage Simple {\n  string id = 1;\n}","schemaType": "PROTOBUF"}'
```

```json
{"id":2}
```

This schema is then referenced in a new schema in a different subject named `import`.

### rpk

```bash
# --references flag takes the format \{name\}:\{subject\}:\{schema version\}
rpk registry schema create import --schema import_schema.proto --references simple:test-simple:2
```

```none
SUBJECT        VERSION  ID    TYPE
import         1        3     PROTOBUF
```

### Curl

```bash
curl -X POST -H 'Content-type: application/vnd.schemaregistry.v1+json' http://127.0.0.1:8081/subjects/import/versions -d '{"schema": "syntax = \"proto3\";\nimport \"simple\";\nmessage Test3 {\n  Simple id = 1;\n}","schemaType": "PROTOBUF", "references": [{"name": "simple", "subject": "test-simple", "version":1}]}'
```

```json
{"id":3}
```

You cannot delete a schema when it is used as a reference.

### rpk

```bash
rpk registry schema delete test-simple --schema-version 1
```

```none
One or more references exist to the schema {magic=1,keytype=SCHEMA,subject=test-simple,version=1}
```

### Curl

```bash
curl -X DELETE -H 'Content-type: application/vnd.schemaregistry.v1+json' http://127.0.0.1:8081/subjects/test-simple/versions/1
```

```json
{"error_code":42206,"message":"One or more references exist to the schema {magic=1,keytype=SCHEMA,subject=test-simple,version=1}"}
```

Call the `/subjects/test-simple/versions/1/referencedby` endpoint to see the schema IDs that reference version 1 for subject `test-simple`.

### rpk

```bash
rpk registry schema references test-simple --schema-version 1
```

```none
SUBJECT  VERSION  ID    TYPE
import   1        3     PROTOBUF
```

### Curl

```bash
curl -H 'Content-type: application/vnd.schemaregistry.v1+json' http://127.0.0.1:8081/subjects/test-simple/versions/1/referencedby
```

```json
[3]
```

## [](#delete-a-schema)Delete a schema

The Schema Registry API provides DELETE endpoints for deleting a single schema or all schemas of a subject:

-   `/subjects/{subject}/versions/{version}`

-   `/subjects/{subject}`


Schemas cannot be deleted if any other schemas reference it.

A schema can be soft deleted (impermanently) or hard deleted (permanently), based on the boolean query parameter `permanent`. A soft deleted schema can be retrieved and re-registered. A hard deleted schema cannot be recovered.

### [](#soft-delete-a-schema)Soft delete a schema

To soft delete a schema, make a DELETE request with the subject and version ID (where `permanent=false` is the default parameter value):

#### rpk

```bash
rpk registry schema delete sensor-value --schema-version 1
```

#### Curl

```bash
curl -s \
  -X DELETE \
  "http://localhost:8081/subjects/sensor-value/versions/1" \
  | jq .
```

#### Python

```python
res = requests.delete(f'{base_uri}/subjects/sensor-value/versions/1').json()
pretty(res)
```

This returns the ID of the soft deleted schema:

#### rpk

```none
Successfully deleted schema. Subject: "sensor-value", version: "1"
```

#### Curl

```none
1
```

Doing a soft delete for an already deleted schema returns an error:

#### rpk

```none
Subject 'sensor-value' Version 1 was soft deleted. Set permanent=true to delete permanently
```

#### Curl

```json
{
  "error_code": 40406,
  "message": "Subject 'sensor-value' Version 1 was soft deleted.Set permanent=true to delete permanently"
}
```

To list subjects of soft-deleted schemas, make a GET request with the `deleted` parameter set to `true`, `/subjects?deleted=true`:

#### rpk

```bash
rpk registry subject list --deleted
```

#### Curl

```bash
curl -s \
  "http://localhost:8081/subjects?deleted=true" \
  | jq .
```

#### Python

```python
payload = { 'deleted' : 'true' }
res = requests.get(f'{base_uri}/subjects', params=payload).json()
pretty(res)
```

This returns all subjects, including deleted ones:

```json
[
  "sensor-value"
]
```

To undo a soft deletion, first follow the steps to [retrieve the schema](#retrieve-a-schema-of-a-subject), then [register the schema](#register-a-schema).

### [](#hard-delete-a-schema)Hard delete a schema

> ⚠️ **CAUTION**
>
> Redpanda doesn’t recommend hard (permanently) deleting schemas in a production system.
>
> The DELETE APIs are primarily used during the development phase, when schemas are being iterated and revised.

To hard delete a schema, use the `--permanent` flag with the `rpk registry schema delete` command, or for curl or Python, make two DELETE requests with the second request setting the `permanent` parameter to `true` (`/subjects/{subject}/versions/{version}?permanent=true`):

#### rpk

```bash
rpk registry schema delete sensor-value --schema-version 1  --permanent
```

#### Curl

```bash
curl -s \
  -X DELETE \
  "http://localhost:8081/subjects/sensor-value/versions/1" \
  | jq .
curl -s \
  -X DELETE \
  "http://localhost:8081/subjects/sensor-value/versions/1?permanent=true" \
  | jq .
```

#### Python

```python
res = requests.delete(f'{base_uri}/subjects/sensor-value/versions/1').json()
pretty(res)
payload = { 'permanent' : 'true' }
res = requests.delete(f'{base_uri}/subjects/sensor-value/versions/1', params=payload).json()
pretty(res)
```

Each request returns the version ID of the deleted schema:

#### rpk

```none
Successfully deleted schema. Subject: "sensor-value", version: "1"
```

#### Curl

```json
1
1
```

A request for a hard-deleted schema returns an error:

#### rpk

```none
Subject 'sensor-value' not found.
```

#### Curl

```json
{
  "error_code": 40401,
  "message": "Subject 'sensor-value' not found."
}
```

## [](#set-schema-registry-mode)Set Schema Registry mode

The `/mode` endpoint allows you to put Schema Registry in read-only, read-write, or import mode.

-   In read-write mode (the default), you can both register and look up schemas.

-   In [read-only mode](#use-readonly-mode-for-disaster-recovery), you can only look up schemas. This mode is most useful for standby clusters in a disaster recovery setup.

-   In [import mode](#use-import-mode-for-migration), you can register new schemas with explicit IDs and versions, while existing schemas remain readable so producers and consumers continue to operate against them. This mode is most useful for target clusters in a migration setup, where IDs must be preserved across registries.


If authentication is enabled on Schema Registry, only superusers can change global and subject-level modes.

> ⚠️ **CAUTION**
>
> **Breaking change in Redpanda 25.3:** In Redpanda versions before 25.3, you could specify a schema ID or version when registering a schema in read-write mode.
>
> Starting with 25.3, read-write mode returns an error when you try to register a schema with a specific ID or version. If you have custom scripts that rely on the ability to specify an ID or version with Redpanda 25.2 and earlier, you must do either of the following:
>
> -   Omit the ID and version fields when registering a schema. The schema will be registered under a new ID and version.
>
> -   Change the Schema Registry or the subject to [import mode](#use-import-mode-for-migration). Existing producers and consumers continue to work against already-registered schemas in import mode; only auto-registration of new schemas is blocked.

### [](#get-global-mode)Get global mode

To [query the global mode](https://docs.redpanda.com/api/doc/schema-registry/operation/operation-get_mode) for Schema Registry:

#### rpk

```bash
rpk registry mode get --global
```

#### Curl

```bash
curl http://localhost:8081/mode
```

### [](#set-global-mode)Set global mode

Set the mode for Schema Registry at a global level. This mode applies to all subjects that do not have a specific mode set.

#### rpk

```bash
rpk registry mode set --mode <mode> --global
```

#### Curl

```bash
curl -X PUT -H "Content-Type: application/vnd.schemaregistry.v1+json" --data '{"mode": <mode>}' http://localhost:8081/mode
```

Replace the `<mode>` placeholder with the desired mode:

-   `READONLY`

-   `READWRITE`

-   `IMPORT`


### [](#get-mode-for-a-subject)Get mode for a subject

To look up the mode for a specific subject:

#### rpk

```bash
rpk registry mode get <subject-name>
```

#### Curl

```bash
curl http://localhost:8081/mode/<subject>?defaultToGlobal=true
```

This request returns the mode that is enforced. If the subject is set to a specific mode (to override the global mode), it returns the override mode. Otherwise, it returns the global mode.

To retrieve the subject-level override if it exists, use:

```bash
curl http://localhost:8081/mode/<subject>
```

This request returns an error if there is no specific mode set for the subject.

### [](#set-mode-for-a-subject)Set mode for a subject

#### rpk

```bash
rpk registry mode set <subject-name> --mode READONLY
```

#### Curl

```bash
curl -X PUT -H "Content-Type: application/vnd.schemaregistry.v1+json" --data '{"mode": "READONLY"}' http://localhost:8081/mode/<subject>
```

### [](#use-readonly-mode-for-disaster-recovery)Use READONLY mode for disaster recovery

A read-only Schema Registry does not accept direct writes. An active production cluster can replicate schemas to a read-only Schema Registry to keep it in sync, for example using Redpanda’s [Schema Migration tool](https://github.com/redpanda-data/schema-migration/). Users in the disaster recovery (DR) site cannot update schemas directly, so the DR cluster has an exact replica of the schemas in production. In a failover due to a disaster or outage, you can set Schema Registry to read-write mode, taking over for the failed cluster and ensuring availability.

### [](#use-import-mode-for-migration)Use IMPORT mode for migration

Use import mode to:

-   Migrate schemas from another Schema Registry while preserving their IDs and versions

-   To register an individual schema with a specific ID and version into an existing registry


While a Schema Registry or subject is in import mode:

-   You can only register new schemas with an explicit ID and version. This enables a replication tool to preserve schema IDs and versions from a source registry.

-   Compatibility checks are bypassed during registration, so schemas can be imported without re-validation against the subject’s compatibility settings.

-   Existing schemas remain readable. Producers and consumers can continue to look up and use any schema that has already been registered.

-   Auto-registration is rejected. Client libraries that attempt to register a new schema without specifying an explicit ID and version will receive an error.


> 📝 **NOTE**
>
> Import mode supports continuous migration: producers and consumers can keep operating against the target registry while it is in import mode, as long as they do not attempt to register new schemas. Lookups of already-registered schemas continue to succeed, while auto-registration calls (for example, `POST /subjects/{subject}/versions` without an explicit ID) are rejected.
>
> To avoid auto-registration errors on the client side, configure your clients to look up schemas instead of registering them. For Confluent serializers, set `auto.register.schemas=false` (and optionally `use.latest.version=true`).

#### [](#choose-subject-level-or-global-import-mode)Choose subject-level or global import mode

You can put either a single subject or the entire Schema Registry into import mode:

-   **Global import mode** applies to all subjects that do not have a per-subject mode override. Use this when migrating an entire Schema Registry into a new cluster.

-   **Subject-level import mode** applies to a single subject and overrides the global mode for that subject. Use this to register or restore an individual schema with a specific ID into an otherwise active registry.


#### [](#enable-import-mode)Enable import mode

To enable import mode, you must have:

-   Either admin access, or a Schema Registry ACL with the `alter_configs` operation on the `registry` resource. See [Schema Registry Authorization](https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/schema-reg-authorization/) for details on managing Schema Registry ACLs.

-   An empty registry or subject. That is, either no schemas have ever been registered, or you must [hard-delete](#hard-delete-a-schema) all schemas that were registered.

    To bypass the check for an empty registry when setting the global mode to import:

    ##### rpk

    ```bash
    rpk registry mode set --mode IMPORT --global --force
    ```


    ##### Curl

    ```bash
    curl -X PUT -H "Content-Type: application/vnd.schemaregistry.v1+json" --data '{"mode": "IMPORT"}' http://localhost:8081/mode?force=true
    ```


#### [](#register-a-schema-with-an-explicit-id-and-version)Register a schema with an explicit ID and version

##### rpk

```bash
rpk registry schema create <subject-name> --schema order.proto --id 1 --schema-version 4
```

##### Curl

```bash
curl -X POST -H "Content-Type: application/vnd.schemaregistry.v1+json" --data '{"schema": "syntax = \"proto3\";\nmessage Order {\n  string id = 1;\n}", "schemaType": "PROTOBUF", "id": 1, "version": 4}' http://localhost:8081/subjects/<subject-name>/versions
```

#### [](#return-to-read-write-mode)Return to read-write mode

When migration is complete, return the Schema Registry or subject to read-write mode so that normal schema registration resumes. Use the [Set global mode](#set-global-mode) or [Set mode for a subject](#set-mode-for-a-subject) commands shown earlier on this page, with `READWRITE` as the mode value.

## [](#retrieve-serialized-schemas)Retrieve serialized schemas

Starting in Redpanda version 25.2, the following endpoints return serialized schemas (Protobuf only) using the `format=serialized` query parameter:

| Operation | Path |
| --- | --- |
| Retrieve a schema | GET /schemas/ids/{id}?format=serialized |
| Check if a schema is already registered for a subject | POST /subjects/{subject}?format=serialized |
| Retrieve a subject’s specific version of a schema | GET /subjects/{subject}/versions/{version}?format=serialized |
| Get the unescaped schema only for a subject | GET /subjects/{subject}/versions/{version}/schema?format=serialized |

The `serialized` format returns the Protobuf schema in its wire binary format in Base64.

-   Passing an empty string (`format=''`) returns the schema in the current (default) format.

-   For Avro, `resolved` is a valid value, but it is not currently supported and returns a 501 Not Implemented error.

-   For Protobuf, `serialized` and `ignore_extensions` are valid, but only `serialized` is currently supported; passing `ignore_extensions` returns a 501 Not Implemented error.

-   Cross-schema conditions such as `resolved` with Protobuf or `serialized` with Avro are ignored and the schema is returned in the default format.


## [](#suggested-reading)Suggested reading

-   [Redpanda Schema Registry](https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/schema-reg-overview/)

-   [Schema Registry Contexts](https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/schema-reg-contexts/)

-   [rpk registry](https://docs.redpanda.com/cloud-data-platform/reference/rpk/rpk-registry/rpk-registry/)

-   [Schema Registry API](https://docs.redpanda.com/api/doc/schema-registry/)

-   [Monitor Schema Registry service-level metrics](https://docs.redpanda.com/cloud-data-platform/manage/monitor-cloud/#service-level-queries)

-   [Deserialization](https://docs.redpanda.com/cloud-data-platform/manage/schema-reg/record-deserialization/#schema-registry)