include::{mod-loc}shared/all-attributes.adoc[]

:_mod-docs-content-type: ASSEMBLY

[id="confluent-schema-registry-compatibility_{context}"]
= Confluent Schema Registry compatibility API

[role="_abstract"]
{registry} provides a compatibility API layer so that applications with Confluent Schema Registry clients can work with {registry}. Review the supported features, behavioral differences, unsupported features, and migration considerations:

* xref:ccompat-overview_{context}[]
* xref:ccompat-supported-features_{context}[]
* xref:ccompat-behavioral-differences_{context}[]
* xref:ccompat-unsupported-features_{context}[]
* xref:ccompat-migration-considerations_{context}[]

:_mod-docs-content-type: CONCEPT

[id="ccompat-overview_{context}"]
== Overview of the compatibility API

[role="_abstract"]
{registry} implements the Confluent Schema Registry REST API to provide drop-in compatibility for applications and tools designed for Confluent Schema Registry.

.Supported API versions
[%header,cols="1,2,2"]
|===
|Version
|Endpoint
|Status

|v7
|`/apis/ccompat/v7`
|Fully supported

|v8
|`/apis/ccompat/v8`
|Fully supported
|===

Applications that use Confluent Schema Registry client libraries can use {registry} as a replacement by changing the schema registry URL to point to the appropriate {registry} ccompat endpoint.

.Example configuration
[source,properties]
----
# Confluent client configuration pointing to Apicurio Registry
schema.registry.url=http://my-registry:8080/apis/ccompat/v7
----

:_mod-docs-content-type: REFERENCE

[id="ccompat-supported-features_{context}"]
== Supported features

[role="_abstract"]
{registry} fully supports the following Confluent Schema Registry features:

.Fully supported API endpoints
[%header,cols="2,3"]
|===
|Feature
|Description

|*Schemas API*
|Full support for schema management including `GET /schemas`, `GET /schemas/ids/{id}`, `GET /schemas/types`, `GET /schemas/ids/{id}/subjects`, `GET /schemas/ids/{id}/versions`, and `GET /schemas/ids/{id}/schema`. Includes pagination with `offset` and `limit` parameters.

|*Subjects API*
|Complete create, retrieve, update, and delete operations for subjects including listing, registration, lookup by content (`POST /subjects/{subject}`), lookup by version (`POST /subjects/{subject}/versions/{version}`), and deletion. Supports pagination with `offset`, `limit`, `deleted`, and `deletedOnly` parameters.

|*Compatibility API*
|Schema compatibility checking against specific versions or all versions. Supports `verbose` and `normalize` parameters. Defaults to `BACKWARD` compatibility when you do not configure an explicit rule, matching the Confluent behavior.

|*Config API*
|Global and subject-level compatibility configuration. Supports `GET`, `PUT`, and `DELETE` operations, including `defaultToGlobal` parameter for subject config. The `PUT` response includes `compatibility` and `normalize` fields.

|*Mode API*
|Global and subject-level mode management (`READWRITE`, `READONLY`, `READONLY_OVERRIDE`, `IMPORT`). Supports `force` parameter for mode changes.

|*Contexts API*
|Returns the default context for Confluent client compatibility.
|===

.Supported schema types
[%header,cols="1,2"]
|===
|Schema type
|Support status

|Apache Avro
|Fully supported

|JSON Schema
|Fully supported

|Google Protobuf
|Fully supported
|===

.v8-specific features
[%header,cols="2,3"]
|===
|Feature
|Description

|*X-Confluent-Accept-Unknown-Properties header*
|When set to `true`, the API ignores unknown JSON properties in request bodies. This provides forward compatibility for clients that send newer API requests.

|*Enhanced pagination*
|Full pagination support on schemas and subjects endpoints.
|===

**Schema ID mapping**

{registry} uses two internal ID types: `globalId` (unique per artifact version) and `contentId` (unique per content hash). Confluent Schema Registry uses a single incrementing schema ID.

The `apicurio.ccompat.legacy-id-mode.enabled` configuration property controls the mapping between Confluent schema IDs and {registry} internal IDs:

.Schema ID mode
[%header,cols="1,1,3"]
|===
|Mode
|Config value
|Behavior

|Content ID mode (default)
|`false`
|Confluent `id` maps to {registry} `contentId`. Registering the same schema content under different subjects returns the same ID, matching the Confluent behavior.

|Legacy ID mode
|`true`
|Confluent `id` maps to {registry} `globalId`. Each version registration gets a unique ID regardless of content.
|===

For most use cases, use the default content ID mode, because it matches the Confluent behavior where identical schemas share the same ID across subjects.

**Configuration properties**

.Confluent compatibility API configuration
[%header,cols="2,1,3"]
|===
|Property
|Default
|Description

|`apicurio.ccompat.legacy-id-mode.enabled`
|`false`
|Use `globalId` instead of `contentId` for Confluent schema IDs.

|`apicurio.ccompat.use-canonical-hash`
|`false`
|Always use canonical hash for schema content comparison.

|`apicurio.ccompat.max-subjects`
|`1000`
|Maximum number of subjects returned by the `/subjects` endpoint.

|`apicurio.ccompat.group-concat.enabled`
|`false`
|Enable {registry} group support by concatenating group ID and artifact ID into the subject name.

|`apicurio.ccompat.group-concat.separator`
|`:`
|Separator character used when you enable group concatenation.
|===

:_mod-docs-content-type: REFERENCE

[id="ccompat-behavioral-differences_{context}"]
== Behavioral differences from Confluent

[role="_abstract"]
Although the ccompat API provides broad compatibility, some behavioral differences exist when you migrate from Confluent Schema Registry.

**Avro schema formatting**

The ccompat API normalizes returned Avro schemas to compact single-line JSON, matching the Confluent behavior. This normalization has the following effects:

* The API returns pretty-printed Avro schemas submitted during registration in compact form.
* The API simplifies Avro primitive type wrappers (for example, `{"type": "string"}` becomes `"string"`).
* Field ordering follows the Avro canonical form.

This normalization applies only to ccompat API responses (`/apis/ccompat/*`). The native {registry} v3 API returns schemas in their original submitted format.

**Default compatibility level**

When you do not configure an explicit compatibility rule at the artifact, group, or global level, the ccompat compatibility check endpoint (`POST /compatibility/subjects/{subject}/versions/{version}`) defaults to `BACKWARD` compatibility. This matches the default behavior of Confluent Schema Registry.

NOTE: This default only applies to the compatibility _check_ endpoint. Schema registration does not enforce this default unless you explicitly configure a compatibility rule by using `PUT /config` or `PUT /config/{subject}`.

**Config response format**

The `PUT /config` and `PUT /config/{subject}` endpoints return a response with the following fields:

[source,json]
----
{
  "compatibility": "BACKWARD",
  "normalize": false
}
----

The `GET /config` endpoint returns the following response:

[source,json]
----
{
  "compatibilityLevel": "BACKWARD"
}
----

The field name differs between the update response (`compatibility`) and the get response (`compatibilityLevel`). This matches the Confluent API behavior.

**Error responses**

Error responses use Confluent-compatible error codes and message formats:

.Error codes
[%header,cols="1,2,1"]
|===
|Error code
|Meaning
|HTTP status

|40401
|Subject not found
|404

|40402
|Version not found
|404

|40403
|Schema not found
|404

|40408
|Subject-level compatibility not configured
|404

|42201
|Invalid schema
|422

|42203
|Invalid compatibility level
|422

|42206
|Schema has existing references
|422
|===

**Sorted results**

List endpoints (`GET /subjects`, `GET /schemas/ids/{id}/subjects`, `GET /schemas/ids/{id}/versions`) return results in sorted order (alphabetical for subjects, numerical for versions).

:_mod-docs-content-type: REFERENCE

[id="ccompat-unsupported-features_{context}"]
== Unsupported features

[role="_abstract"]
{registry} does not support the following Confluent Schema Registry features. Applications that rely on these features must use alternative approaches.

.Unsupported features
[%header,cols="2,2,3"]
|===
|Feature
|Behavior
|Alternative

|*Schema Linking / Exporters*
|`GET /exporters` returns an empty list. All other exporter operations return an error.
|Use {registry} native import/export functions or external replication tools.

|*KEKs (Key Encryption Keys)*
|Endpoints not present (404 error).
|Implement encryption at the application layer or use external key management.

|*DEKs (Data Encryption Keys)*
|Endpoints not present (404 error).
|Implement encryption at the application layer or use external key management.

|*Cluster Metadata API*
|Endpoints `/v1/metadata/id` and `/v1/metadata/config` not present.
|Use {registry} system API for registry information.

|*Data Contracts - Rules Enforcement*
|The ccompat API accepts `metadata` and `ruleSet` fields in requests but does not enforce or store them. The API does not execute schema rules.
|Use {registry} native Data Contracts feature (`apicurio.contracts.enabled=true`) for contract metadata and rulesets. See xref:getting-started/assembly-data-contracts.adoc[Data Contracts].
|===

**Schema Linking / Exporters**

Confluent Schema Linking uses schema exporters to replicate schemas between Schema Registry clusters. This is an enterprise feature that requires cluster-to-cluster replication infrastructure.

{registry} provides alternative approaches for schema replication:

* *Import/Export API*: Use the {registry} admin API to export all registry content to a ZIP file and import it into another instance.
* *Kafka-based storage*: Use Kafka storage to store schemas in a Kafka topic that you can replicate by using the native replication features of Kafka.
* *GitOps workflows*: Store schemas in Git and use CI/CD pipelines to synchronize across environments.

**Data Contracts**

Confluent Data Contracts provide the following governance features:

* *Metadata*: Key-value pairs attached to schemas (owner, email, tags)
* *RuleSets*: Validation and transformation rules that use Common Expression Language (CEL) or JSONata

{registry} accepts these fields in ccompat API requests for client compatibility but does not process or store them through the ccompat layer. Instead, {registry} provides its own native Data Contracts feature with more capabilities:

* *Contract Metadata*: Standardized metadata (status, owner, domain, classification, stage) managed through the `contract/metadata` REST API
* *Contract Rulesets*: Domain and migration rules at both artifact and version level, managed through the `contract/ruleset` REST API
* *Content Rules*: Validity, compatibility, and integrity rule configuration
* *Groups*: Artifact organization by group for governance

See xref:getting-started/assembly-data-contracts.adoc[Data Contracts] for full documentation about the native data contracts feature.

:_mod-docs-content-type: REFERENCE

[id="ccompat-migration-considerations_{context}"]
== Migration considerations

[role="_abstract"]
When you migrate from Confluent Schema Registry to {registry}, consider the following areas:

.Migration checklist
[%header,cols="1,3"]
|===
|Area
|Consideration

|*Basic operations*
|Schema registration, retrieval, and compatibility checks work identically. No changes required.

|*Client configuration*
|Update `schema.registry.url` to point to the {registry} ccompat endpoint.

|*Schema types*
|{registry} fully supports Avro, JSON Schema, and Protobuf.

|*Schema IDs*
|{registry} uses `contentId` by default (the same schema content produces the same ID across subjects). Set `apicurio.ccompat.legacy-id-mode.enabled=true` if your application depends on unique IDs per registration.

|*Avro schema formatting*
|Avro schemas are returned in compact JSON through ccompat endpoints. If your application compares schema strings directly, be aware of formatting differences.

|*Default compatibility*
|The compatibility check endpoint defaults to `BACKWARD` when you do not configure a rule, matching Confluent. Set an explicit global compatibility level by using `PUT /config` if you need a different default.

|*Config response parsing*
|The `PUT /config` response uses the field name `compatibility` (not `compatibilityLevel`). Update client code that parses this response.

|*Authentication*
|{registry} supports OpenID Connect (OIDC) authentication. Update client security configuration as needed.

|*Exporters / Schema Linking*
|Not supported. Use {registry} import/export API or Kafka topic replication.

|*Data Contracts*
|Metadata and rules from the ccompat API are not enforced. Use {registry} native Data Contracts feature for contract metadata and rulesets.

|*Encryption (KEK/DEK)*
|Not supported. Implement encryption at the application layer.
|===

.Example: Migrating a Kafka producer
[source,java]
----
// Before: Confluent Schema Registry
Properties props = new Properties();
props.put("schema.registry.url", "http://confluent-registry:8081");

// After: Apicurio Registry (using ccompat API)
Properties props = new Properties();
props.put("schema.registry.url", "http://apicurio-registry:8080/apis/ccompat/v7");
----

[role="_additional-resources"]
.Additional resources
* {registry-rest-api}
* link:https://docs.confluent.io/platform/current/schema-registry/develop/api.html[Confluent Schema Registry API Reference]
* link:https://docs.confluent.io/platform/current/schema-registry/fundamentals/data-contracts.html[Confluent Data Contracts Documentation]
* link:https://docs.confluent.io/platform/current/schema-registry/schema-linking-cp.html[Confluent Schema Linking Documentation]
