Schema Registry API
Qarion exposes three schema-registry surfaces:
- Catalog Schema Registry: reusable, space-scoped schema entries that products can reference instead of storing inline schema copies.
- Event Contract Registry: governed event contracts, versions, validation, compatibility checks, repository sync, and external schema registry connections.
- Runtime Event Registry: read-only access to approved, immutable Event Contract versions and schemas.
All endpoints are served under /api/v1.0. Paths below omit that prefix.
Endpoint Overview
Catalog Schema Entries
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /catalog/spaces/{slug}/schema-registry | List reusable schema entries in a space. |
| POST | /catalog/spaces/{slug}/schema-registry | Create a schema entry. |
| GET | /catalog/spaces/{slug}/schema-registry/{schema_id} | Get one schema entry. |
| PATCH | /catalog/spaces/{slug}/schema-registry/{schema_id} | Update a schema entry. |
| DELETE | /catalog/spaces/{slug}/schema-registry/{schema_id} | Delete a schema entry. |
Event Contracts
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /spaces/{slug}/event-contracts | List Event Contracts with filters. |
| POST | /spaces/{slug}/event-contracts | Create an Event Contract identity. |
| GET | /spaces/{slug}/event-contracts/{contract_id} | Get contract detail with versions. |
| PATCH | /spaces/{slug}/event-contracts/{contract_id} | Update contract metadata. |
| POST | /spaces/{slug}/event-contracts/repository-sync | Import contract files from repository content. |
| GET | /spaces/{slug}/event-contracts/{contract_id}/versions | List contract versions. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/versions | Create a draft contract version. |
| PATCH | /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id} | Update a draft version. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/validate | Validate one version. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/compatibility-check | Compare one version to the approved baseline. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/publish | Publish an approved version. |
| GET | /spaces/{slug}/event-contracts/{contract_id}/export | Export the latest contract in a target format. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/resolve-conflict | Resolve a Git/Qarion conflict. |
External Schema Registry Connections
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /spaces/{slug}/event-contracts/registry-connections | List external registry connections. |
| POST | /spaces/{slug}/event-contracts/registry-connections | Create a registry connection. |
| PATCH | /spaces/{slug}/event-contracts/registry-connections/{connection_id} | Update a registry connection. |
| DELETE | /spaces/{slug}/event-contracts/registry-connections/{connection_id} | Delete a registry connection. |
| POST | /spaces/{slug}/event-contracts/registry-connections/{connection_id}/test | Test a registry connection. |
| GET | /spaces/{slug}/event-contracts/registry-connections/{connection_id}/remote-references | Browse remote subjects, artifacts, or Iglu schemas. |
| POST | /spaces/{slug}/event-contracts/registry-connections/{connection_id}/pull-preview | Fetch a remote schema without creating a local version. |
| POST | /spaces/{slug}/event-contracts/registry-connections/{connection_id}/pull-import | Import a remote schema as a local Event Contract version. |
Registry Bindings
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings | List bindings for a contract. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings | Bind a contract to a remote registry identity. |
| PATCH | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id} | Update a binding. |
| DELETE | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id} | Delete a binding. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id}/push | Push an approved local version to the remote registry. |
| POST | /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id}/compatibility-sync | Read or set remote compatibility mode. |
Runtime Registry
| Method | Endpoint | Purpose |
|---|---|---|
| GET | /registry/events/{event_name}/latest-approved | Resolve the latest approved local Event Contract version. |
| GET | /registry/events/{event_name}/versions/{version_value} | Resolve a specific approved immutable version. |
| GET | /registry/events/{event_name}/schema | Return the latest approved schema document only. |
| GET | /registry/iglu/schemas/{vendor}/{name}/{schema_format}/{version_value} | Return an Iglu-compatible schema response. |
Permissions And Feature Gates
Event Contract routes require the event_contracts.enabled feature. They use
the event_contract resource with these actions:
| Action | Used by |
|---|---|
view | Lists, details, version lists, exports, remote-reference browsing. |
create | Creating contracts and importing a remote schema without an existing contract_id. |
edit | Updating contracts and versions, validation, compatibility checks, and importing into an existing contract. |
publish | Publishing a version. |
sync | Repository sync, registry connection CRUD/test, pull preview/import, binding CRUD, push, and compatibility sync. |
resolve_conflict | Resolving repository sync conflicts. |
Mutating registry connection and binding sync routes require a non-impersonated user. Runtime registry endpoints return only approved, non-conflicted local Event Contract versions; external registry state is evidence for sync UX, not the runtime source of truth.
Catalog Schema Entries
Catalog schema entries are reusable schema definitions scoped to a space. They are used by product details such as media manifest schema pickers and are also updated when Data Contract schema definitions are changed through contract services.
Schema Entry Shape
{
"id": "1c61ec14-8d8c-4e0d-b3c7-a1afeb52458d",
"space_id": "82d7d96a-b7f5-4d19-8bb9-42127bb6399c",
"name": "Customer Event Manifest",
"slug": "customer-event-manifest",
"description": "Reusable schema for customer event manifests.",
"version": 1,
"schema_fields": [
{
"name": "customer_id",
"type": "string",
"description": "Stable customer identifier.",
"required": true,
"enum_values": null
}
],
"raw_json_schema": null,
"created_at": "2026-06-26T09:15:22.533000Z",
"updated_at": "2026-06-26T09:15:22.533000Z"
}
Field types accepted by schema_fields[].type include string, number,
integer, boolean, array, object, date, and enum. Use
enum_values only when type is enum.
Create Schema Entry
POST /catalog/spaces/{slug}/schema-registry
Content-Type: application/json
{
"name": "Customer Event Manifest",
"description": "Reusable schema for customer event manifests.",
"schema_fields": [
{
"name": "event_type",
"type": "enum",
"required": true,
"enum_values": ["created", "updated", "deleted"]
}
],
"raw_json_schema": {
"type": "object",
"required": ["event_type"]
}
}
If slug is omitted, the service generates one from name. Updates are partial.
If a PATCH omits version, the service increments the stored version. If you
send version, that value is stored as supplied.
Event Contract Registry
Event Contracts model governed event schema identities and their versioned documents.
Contract Identity
Create a contract with either event_name or the structured
domain/entity/action identity parts.
POST /spaces/{slug}/event-contracts
Content-Type: application/json
{
"event_name": "orders.order.created",
"event_kind": "business",
"lifecycle_status": "draft",
"description": "Published when a customer order is accepted.",
"producer_product_id": "7da5fb7e-507a-4324-af2b-ffcb9d40e6f0",
"source_system_id": "72637167-f769-4ae3-b709-4560de2ee402",
"external_bindings": {
"kafka": {
"topic": "orders.order.created"
}
}
}
List filters include:
| Query parameter | Meaning |
|---|---|
status | Filter by contract lifecycle status. |
event_kind | Filter by event kind. |
producer | Filter by producer text. |
source_system | Filter by source system UUID. |
data_stream_product | Filter by data stream product UUID or slug. Unknown slugs return an empty list. |
format | Filter by version schema format. |
search | Text search. |
Versions
Create a draft version with schema_document or raw_document.
POST /spaces/{slug}/event-contracts/{contract_id}/versions
Content-Type: application/json
{
"version": "1.0.0",
"schema_format": "avro",
"schema_document": {
"type": "record",
"name": "OrderCreated",
"namespace": "com.example.orders",
"fields": [
{ "name": "order_id", "type": "string" }
]
},
"source_origin": "qarion"
}
Supported version formats are qarion, json_schema, iglu, asyncapi,
avro, and protobuf. Draft versions can be updated. Published versions become
approved runtime candidates.
Validation And Compatibility
POST /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/validate
POST /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/compatibility-check
Both endpoints return:
{
"passed": true,
"change_kind": "compatible",
"baseline_version_id": "c7a96891-092f-4d37-979b-246f42c5f449",
"checks": [
{
"guardrail": "event_contract.compatibility.format",
"passed": true,
"message": "Schema format is compatible with the approved baseline.",
"severity": "info"
}
]
}
compatibility-check compares against the latest approved version when one is
available. Publish is blocked while the contract is in a conflicted sync state.
Publish And Export
POST /spaces/{slug}/event-contracts/{contract_id}/versions/{version_id}/publish
GET /spaces/{slug}/event-contracts/{contract_id}/export?format=avro
Publish accepts optional approval_metadata. Export returns event_name,
version, format, content_type, serialized content, and checksum.
Repository Sync And Conflicts
POST /spaces/{slug}/event-contracts/repository-sync
Content-Type: application/json
{
"files": [
{
"path": "schemas/events/orders.order.created.yaml",
"content": "kind: event_contract\nmetadata:\n name: orders.order.created\n",
"commit_sha": "7c0dfb7"
}
]
}
Response counters include created, updated, conflicted, skipped,
contracts, and errors. Resolve a conflict by selecting a version or sending a
merged draft:
POST /spaces/{slug}/event-contracts/{contract_id}/resolve-conflict
Content-Type: application/json
{
"selected_version_id": "80f40209-85f8-4f3b-8018-b63952d8b6e8",
"notes": "Use the repository-authored version."
}
External Registry Connections
External connections support Confluent Schema Registry, Apicurio Registry, and Iglu Server.
| Provider | Provider value | Remote identity | Push formats | Compatibility sync |
|---|---|---|---|---|
| Confluent Schema Registry | confluent | subject | json_schema, avro, protobuf | Yes |
| Apicurio Registry | apicurio | artifact or compatible subject | json_schema, avro, protobuf, asyncapi | Yes |
| Iglu Server | iglu | iglu | iglu | No Confluent-style mode |
Create Connection
POST /spaces/{slug}/event-contracts/registry-connections
Content-Type: application/json
{
"name": "Confluent production",
"provider": "confluent",
"base_url": "https://schema-registry.example.com",
"auth_mode": "api_key",
"source_system_id": "72637167-f769-4ae3-b709-4560de2ee402",
"credential_id": "44a93342-4115-42e4-a390-e44b1fb667b1",
"connection_config": {
"api_key_header": "Authorization",
"api_key_prefix": "Bearer"
},
"default_subject_strategy": "topic_name",
"default_compatibility_mode": "BACKWARD",
"default_sync_direction": "manual",
"is_active": true
}
Supported auth_mode values are none, api_key, bearer, and basic.
Authenticated connections require an active credential. Secrets are stored in the
credential store, not on the registry connection. Responses include
has_credential and redacted connection_config.
Connections are unique by space_id and name. base_url must be a valid
external HTTP(S) URL and is stored without a trailing slash.
Connection Response
{
"id": "f74652cc-e90b-4678-a845-67438beb76d3",
"space_id": "82d7d96a-b7f5-4d19-8bb9-42127bb6399c",
"name": "Confluent production",
"provider": "confluent",
"base_url": "https://schema-registry.example.com",
"auth_mode": "api_key",
"source_system_id": "72637167-f769-4ae3-b709-4560de2ee402",
"credential_id": "44a93342-4115-42e4-a390-e44b1fb667b1",
"has_credential": true,
"connection_config": {
"api_key_header": "Authorization",
"api_key_prefix": "Bearer"
},
"default_subject_strategy": "topic_name",
"default_compatibility_mode": "BACKWARD",
"default_sync_direction": "manual",
"is_active": true,
"status": "untested",
"status_details": null,
"last_tested_at": null,
"last_synced_at": null,
"created_at": "2026-06-26T10:10:00Z",
"updated_at": "2026-06-26T10:10:00Z"
}
Test And Browse
POST /spaces/{slug}/event-contracts/registry-connections/{connection_id}/test
GET /spaces/{slug}/event-contracts/registry-connections/{connection_id}/remote-references?search=orders&limit=50
remote-references accepts limit from 1 to 200 and returns provider
references such as subjects, Apicurio artifacts, or Iglu schema coordinates.
Pull From External Registry
Preview a remote schema without creating local state:
POST /spaces/{slug}/event-contracts/registry-connections/{connection_id}/pull-preview
Content-Type: application/json
{
"remote_reference_type": "subject",
"subject": "orders.order.created-value",
"version": "latest"
}
Import the same remote schema as a local draft Event Contract version:
POST /spaces/{slug}/event-contracts/registry-connections/{connection_id}/pull-import
Content-Type: application/json
{
"remote_reference_type": "subject",
"subject": "orders.order.created-value",
"version": "latest",
"contract_id": "13db74fd-e99f-4929-aad7-32c330c707f6",
"local_version": "remote-2026-06-26",
"create_binding": true
}
If contract_id is omitted, the service creates a new Event Contract using
event_name or a name inferred from the remote schema. Imported versions use
source_origin: "schema_registry". When create_binding is true, Qarion also
creates a registry binding from the remote identity when possible.
For Apicurio, use remote_reference_type: "artifact" with artifact_group and
artifact_id. For Iglu, use remote_reference_type: "iglu" with
iglu_vendor, iglu_name, iglu_format, and iglu_version.
Registry Bindings
Bindings link one Event Contract to one remote registry identity. They are
unique by connection_id, resolved_identity, and binding_role.
Create Binding
POST /spaces/{slug}/event-contracts/{contract_id}/registry-bindings
Content-Type: application/json
{
"connection_id": "f74652cc-e90b-4678-a845-67438beb76d3",
"binding_role": "value",
"remote_reference_type": "subject",
"subject_strategy": "topic_name",
"desired_compatibility_mode": "BACKWARD"
}
binding_role values are key, value, event, and entity.
remote_reference_type values are subject, artifact, and iglu.
subject_strategy values are topic_name, record_name,
topic_record_name, and manual.
When subject_strategy is manual, subject is required. Otherwise the
service can generate a subject from contract metadata, Kafka topic binding,
record name, and binding role. Iglu bindings require vendor, name, format, and
version, either in the payload or in the current contract version's self
block.
Binding Response
{
"id": "48a0992e-b442-40a5-82ab-0c41671dbde9",
"space_id": "82d7d96a-b7f5-4d19-8bb9-42127bb6399c",
"contract_id": "13db74fd-e99f-4929-aad7-32c330c707f6",
"connection_id": "f74652cc-e90b-4678-a845-67438beb76d3",
"provider": "confluent",
"binding_role": "value",
"remote_reference_type": "subject",
"subject": "orders.order.created-value",
"resolved_identity": "subject:orders.order.created-value",
"subject_strategy": "topic_name",
"desired_compatibility_mode": "BACKWARD",
"remote_compatibility_mode": null,
"sync_status": "pending",
"remote_version": null,
"remote_schema_id": null,
"remote_global_id": null,
"remote_content_id": null,
"remote_checksum": null,
"last_pushed_version_id": null,
"last_pulled_version_id": null,
"conflict_details": null,
"last_synced_at": null,
"created_at": "2026-06-26T10:30:00Z",
"updated_at": "2026-06-26T10:30:00Z"
}
Push And Compatibility Sync
Push writes an approved local version to the remote registry:
POST /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id}/push
Content-Type: application/json
{
"version_id": "c7a96891-092f-4d37-979b-246f42c5f449",
"sync_compatibility": true
}
If version_id is omitted, Qarion uses the contract's latest approved version.
Draft versions cannot be pushed. A provider/format mismatch returns a validation
error. Successful pushes update remote IDs, checksum, last_pushed_version_id,
last_synced_at, and set sync_status to clean.
Compatibility sync reads or sets the remote compatibility mode:
POST /spaces/{slug}/event-contracts/{contract_id}/registry-bindings/{binding_id}/compatibility-sync
Content-Type: application/json
{
"desired_compatibility_mode": "BACKWARD"
}
Supported compatibility mode values are normalized to uppercase underscore
forms. If the remote mode differs from the desired mode after sync, the binding
becomes conflicted and conflict_details records the desired and remote
values. Iglu bindings skip Confluent-style compatibility sync and become
clean.
Runtime Registry
Runtime endpoints resolve approved local Event Contract versions. They do not fetch from external schema registries at request time.
GET /registry/events/orders.order.created/latest-approved?space=finance
GET /registry/events/orders.order.created/versions/1.0.0?space=finance
GET /registry/events/orders.order.created/schema?space=finance
GET /registry/iglu/schemas/com.example/orders_order_created/jsonschema/1-0-0?space=finance
Specific version and Iglu schema responses include:
Cache-Control: public, max-age=31536000, immutable
Use the optional space query parameter when event names may exist in multiple
spaces.
Error Reference
| Status | Cause |
|---|---|
400 | Invalid schema payload, unsupported provider, unsupported subject strategy, unsupported compatibility mode, missing manual subject, missing Iglu identity, unsupported provider/format push, or pushing a non-approved version. |
403 | Missing Event Contract permission or impersonated user on a non-impersonation sync route. |
404 | Space, schema entry, contract, version, connection, binding, source system, credential, or remote schema was not found. |
409 | Commonly used by service-level conflicts such as duplicate external connection names or duplicate registry identities. |
422 | Pydantic validation failure, for example an invalid UUID, invalid URL, or remote-references limit outside 1..200. |
Operational Notes
- Live external registry tests are opt in. The repository runbook is
docs/operations/event-contract-schema-registry.md. - Auth modes are
none,api_key,bearer, andbasic. API key auth can useapi_key_headerandapi_key_prefixin connection or credential config. - Confluent and Apicurio support explicit compatibility sync. Iglu uses self-describing SchemaVer schemas and does not fabricate compatibility modes.
- External registry sync is manual through pull, push, and compatibility-sync
actions.
default_sync_directionis stored for rollout policy and UI defaults.