skip to content

Walk through the key Schema Registry REST API endpoints you'd use to register, look up, and check compatibility of a schema.

level: middleimportance: should knowfreq 50%

answer

  1. POST /subjects/{subject}/versions → returns id
  2. GET /schemas/ids/{id} → deserializer lookup
  3. POST /compatibility/... → check without registering
  4. GET/PUT /config[/{subject}] → compatibility level
  5. DELETE ...?permanent=true → hard delete; default port 8081

basics

~10 s

POST /subjects/{subject}/versions registers a schema and returns its global ID. GET /schemas/ids/{id} fetches a schema by ID. GET /subjects/{subject}/versions lists versions. POST /compatibility/subjects/{subject}/versions/{version} checks if a new schema is compatible before registering.

solid answer

~40 s

The registry exposes a JSON REST API (default port 8081). Core endpoints: `POST /subjects/{subject}/versions` registers a schema under a subject and returns `{"id": <globalId>}`; it is idempotent for identical schemas. `GET /schemas/ids/{id}` returns the schema text for a global ID — this is what deserializers call. `GET /subjects` lists all subjects; `GET /subjects/{subject}/versions` lists version numbers; `GET /subjects/{subject}/versions/{version}` (or `/latest`) returns a specific version with its subject/version/id/schema. `POST /compatibility/subjects/{subject}/versions/{version}` tests whether a candidate schema is compatible without registering it. `GET`/`PUT /config` and `/config/{subject}` read/set compatibility level (BACKWARD, FORWARD, FULL, NONE, and TRANSITIVE variants). Deletes: `DELETE /subjects/{subject}/versions/{version}` (soft) and `?permanent=true` (hard). The schema body is sent as a JSON-escaped string in a `{"schema": "..."}` envelope, with `schemaType` for Protobuf/JSON Schema.

go deeper

for a junior

Know there are REST endpoints to register a schema and to fetch one by ID.

for a middle

List register, get-by-id, list-versions, and the compatibility-check endpoint with their purposes.

for a senior

Explain idempotent registration, compatibility levels via /config, soft vs permanent delete, and error codes like 409.

for a principal

Design CI gating around the compatibility endpoint and reason about API auth, governance, and rollout policy.

## Shape of the API Schema Registry is a plain **HTTP/JSON REST** service, by default on **port 8081**. Request and response bodies use a Confluent-specific media type (`application/vnd.schemaregistry.v1+json`) but standard `application/json` also works. The schema itself is passed as a **JSON-escaped string** inside an envelope: `{"schema": "...", "schemaType": "AVRO"}` (schemaType defaults to AVRO; use PROTOBUF or JSON for the others). ## Registering a schema `POST /subjects/{subject}/versions` with the schema body registers it under that subject. The response is `{"id": <globalId>}`. This call is **idempotent**: posting a byte-identical schema returns the existing ID and does not create a new version. This is exactly what `KafkaAvroSerializer` calls under the hood when `auto.register.schemas=true`. ## Looking up schemas - `GET /schemas/ids/{id}` → returns `{"schema": "..."}` for a **global ID**. Deserializers call this to resolve the 4-byte ID from the wire format. - `GET /subjects` → all subject names. - `GET /subjects/{subject}/versions` → list of version numbers, e.g. `[1,2,3]`. - `GET /subjects/{subject}/versions/{version}` or `/latest` → `{"subject":...,"version":...,"id":...,"schema":...}`. - `POST /subjects/{subject}` → checks whether a given schema is already registered under that subject and, if so, returns its id/version (lookup without registering). ## Compatibility checking `POST /compatibility/subjects/{subject}/versions/{version}` with a candidate schema returns `{"is_compatible": true|false}` **without registering**. Use `/versions/latest` to check against the most recent version. This is how CI pipelines gate schema changes before they ship. ## Configuration - `GET /config` → the global compatibility level. `PUT /config` sets it. - `GET /config/{subject}` / `PUT /config/{subject}` → per-subject override. Compatibility levels: **BACKWARD** (new schema can read old data — default), **FORWARD** (old schema can read new data), **FULL** (both), **NONE** (no checks), plus **TRANSITIVE** variants that check against *all* previous versions, not just the immediately prior one. ## Deletion - `DELETE /subjects/{subject}/versions/{version}` → **soft delete** a single version (still recoverable, hidden from normal listing). - `DELETE /subjects/{subject}` → soft delete all versions of a subject. - Add `?permanent=true` to **hard delete** (after a soft delete), which removes it irrecoverably. ## Practical notes and edge cases - A `409 Conflict` from the register endpoint means the schema violates the subject's compatibility level. - A `422` typically means an invalid schema or invalid compatibility setting. - `404` with error code `40403` means schema ID not found; `40401` means subject not found. - Because registration is idempotent, retries are safe. - Auth: production registries often sit behind HTTP Basic auth or mTLS; the same REST paths apply.

  • Which endpoint does a deserializer call to resolve the 4-byte wire ID?
    GET /schemas/ids/{id}, which returns the schema text for that global ID. The result is cached in the deserializer so the call happens at most once per unseen ID.
  • How do you test a schema change without actually registering it?
    POST /compatibility/subjects/{subject}/versions/{version} (often /versions/latest) with the candidate schema; it returns is_compatible true/false and does not mutate the registry.

saying these in an interview costs you the question

  • Confusing GET /schemas/ids/{id} (by global ID) with GET /subjects/{subject}/versions/{version} (by subject+version).
  • Saying the compatibility endpoint registers the schema — it only checks.
  • Forgetting the schema must be a JSON-escaped string inside a {"schema":...} envelope.
  • Assuming default port is 8080 — it is 8081.

context