Managing Apicurio Registry content using the REST API

Client applications can use Apicurio Registry REST API operations to manage schema and API artifacts in Apicurio Registry, for example, in a CI/CD pipeline deployed in production.

The Core Registry API v3 provides operations for artifacts, versions, metadata, and rules stored in Apicurio Registry. For detailed information, see the Apicurio Registry REST API documentation.

Prerequisites

Managing schema and API artifacts using Apicurio Registry REST API commands

Use the Core Registry API v3 to add and retrieve a schema artifact in Apicurio Registry.

Prerequisites
  • Apicurio Registry is installed and running in your environment.

Procedure
  1. Add an artifact to Apicurio Registry using the /groups/{groupId}/artifacts operation. The following example curl command adds a schema artifact for a share price application:

    $ curl -X POST MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-raw '{
        "artifactId": "share-price",
        "artifactType": "AVRO",
        "firstVersion": {
            "content": {
                "content": "{\"type\":\"record\",\"name\":\" p\",\"namespace\":\"com.example\", \"fields\":[{\"name\":\"symbol\",\"type\":\"string\"},{\"name\":\"price\",\"type\":\"string\"}]}",
                "contentType": "application/json"
            }
        }
    }'
    • This example adds an Apache Avro schema artifact with an artifact ID of share-price. If you do not specify a unique artifact ID, Apicurio Registry generates one automatically as a UUID.

    • MY-REGISTRY-URL is the hostname on which Apicurio Registry is deployed. For example: http://localhost:8080.

    • This example specifies a group ID of my-group in the API path. If you do not specify a unique group ID, you must specify ../groups/default in the API path.

  2. Verify that the response includes the expected JSON body to confirm that the artifact was added. For example:

    {"artifact":{"owner":"","createdOn":"2024-09-26T17:24:21Z","modifiedBy":"","modifiedOn":"2024-09-26T17:24:21Z","artifactType":"AVRO","groupId":"my-group","artifactId":"share-price"},"version":{"version":"1","owner":"","createdOn":"2024-09-26T17:24:21Z","artifactType":"AVRO","globalId":2,"state":"ENABLED","groupId":"my-group","contentId":2,"artifactId":"share-price"}}
    • You did not specify a version when adding the artifact, so the default version 1 is created automatically.

    • This was the second artifact added to Apicurio Registry, so the global ID and content ID have a value of 2.

  3. Retrieve the artifact version content from Apicurio Registry using its artifact ID in the API path. In this example, the specified ID is share-price:

    $ curl -H "Authorization: Bearer $ACCESS_TOKEN" \
     MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts/share-price/versions/1/content
     {"type":"record","name":"price","namespace":"com.example",
      "fields":[{"name":"symbol","type":"string"},{"name":"price","type":"string"}]}

Managing schema and API artifact versions using Apicurio Registry REST API commands

If you do not specify an artifact version number when adding schema and API artifacts using the Core Registry API v3, Apicurio Registry generates a version number automatically. The default version when creating a new artifact is 1.

Apicurio Registry also supports custom versioning where you can specify a version number when creating the artifact or artifact version. Specifying a custom version value overrides the default version normally assigned when creating an artifact or artifact version. You can then use this version value when running REST API operations that require a version number.

Use the Core Registry API v3 to add and retrieve a custom Apache Avro schema version in Apicurio Registry. You can specify custom version numbers to create artifacts, or to add artifact versions.

Prerequisites
  • Apicurio Registry is installed and running in your environment.

Procedure
  1. Add an artifact version in the registry using the /groups/{groupId}/artifacts operation. The following example curl command adds an artifact for a share price application:

    $ curl -X POST MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-raw '{
        "artifactId": "my-share-price",
        "artifactType": "AVRO",
        "firstVersion": {
            "version": "1.1.1",
            "content": {
                "content": "{\"type\":\"record\",\"name\":\" p\",\"namespace\":\"com.example\", \"fields\":[{\"name\":\"symbol\",\"type\":\"string\"},{\"name\":\"price\",\"type\":\"string\"}]}",
                "contentType": "application/json"
            }
        }
    }'
    • This example adds an Avro schema artifact with an artifact ID of my-share-price and version of 1.1.1. If you do not specify a version, Apicurio Registry automatically generates a default version of 1.

    • MY-REGISTRY-URL is the hostname on which Apicurio Registry is deployed. For example: http://localhost:8080.

    • This example specifies a group ID of my-group in the API path. If you do not specify a unique group ID, you must specify ../groups/default in the API path.

  2. Verify that the response includes the expected JSON body to confirm that the custom artifact version was added. For example:

    {"artifact":{"owner":"","createdOn":"2024-09-26T17:06:21Z","modifiedBy":"","modifiedOn":"2024-09-26T17:06:21Z","artifactType":"AVRO","groupId":"my-group","artifactId":"my-share-price"},"version":{"version":"1.1.1","owner":"","createdOn":"2024-09-26T17:06:21Z","artifactType":"AVRO","globalId":4,"state":"ENABLED","groupId":"my-group","contentId":4,"artifactId":"my-share-price"}}
    • You specified a custom version of 1.1.1 when adding the artifact.

    • This was the fourth artifact added to the registry, so the global ID and content ID have a value of 4.

  3. Retrieve the artifact content from the registry using its artifact ID and version in the API path. In this example, the specified ID is my-share-price and the version is 1.1.1:

    $ curl -H "Authorization: Bearer $ACCESS_TOKEN" \
        MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts/my-share-price/versions/1.1.1/content
    {"type":"record","name":"price","namespace":"com.example",
      "fields":[{"name":"symbol","type":"string"},{"name":"price","type":"string"}]}

Registering base64-encoded content using the REST API

You can send UTF-8 schema or API content as base64 in a JSON request to avoid escaping quotation marks and line breaks in the content. Set encoding to base64 in the VersionContent object. Apicurio Registry decodes the content before processing it.

Prerequisites
  • Apicurio Registry is running, and you have permission to create artifacts in my-group.

  • The my-group group exists.

  • You have installed curl, base64, and jq.

  • The schema.json file contains an Apache Avro schema.

  • The REGISTRY_URL environment variable contains the registry URL, and ACCESS_TOKEN contains a valid access token if authentication is enabled.

Procedure
  1. Create the request body from your schema file:

    $ base64 < schema.json | tr -d '\r\n' > schema.base64
    $ jq -n --rawfile content schema.base64 '{
        artifactId: "encoded-schema",
        artifactType: "AVRO",
        firstVersion: {
            version: "1.0.0",
            content: {
                content: $content,
                contentType: "application/json",
                encoding: "base64"
            }
        }
    }' > request.json

    contentType describes the decoded schema, not the base64 text. The encoding value is case-sensitive. Omit encoding when sending unencoded content.

  2. Register the artifact:

    $ curl --fail-with-body -X POST \
      "$REGISTRY_URL/apis/registry/v3/groups/my-group/artifacts" \
      -H "Content-Type: application/json" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-binary @request.json

    You can also set encoding in the content object when creating a version of an existing artifact. Invalid base64 content returns HTTP 400.

Verification
  • Retrieve the version content and confirm that it contains the decoded schema:

    $ curl --fail-with-body \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      "$REGISTRY_URL/apis/registry/v3/groups/my-group/artifacts/encoded-schema/versions/1.0.0/content"

Managing schema and API artifact references using Apicurio Registry REST API commands

Some Apicurio Registry artifact types can include artifact references from one artifact file to another. You can create efficiencies by defining reusable schema or API artifacts, and then referencing them from multiple locations in artifact references.

The following artifact types support artifact references:

  • Apache Avro

  • Google Protobuf

  • JSON Schema

  • OpenAPI

  • AsyncAPI

  • XML Schema (XSD)

  • WSDL (1.1 and 2.0)

For XSD and WSDL artifacts, the reference name must equal the literal value of the schemaLocation attribute (xs:import, xs:include, xs:redefine, and xs:override, including schemas embedded in WSDL types) or the location attribute (wsdl:import, and WSDL 2.0 import and include). An xs:import element that specifies only a namespace, without a schemaLocation, does not require a reference mapping.

Use the Core Registry API v3 to add and retrieve an artifact reference in Apicurio Registry.

This example first creates a schema artifact named ItemId:

ItemId schema

{
    "namespace":"com.example.common",
    "name":"ItemId",
    "type":"record",
    "fields":[
        {
            "name":"id",
            "type":"int"
        }
    ]
}

This example then creates a schema artifact named Item, which includes a reference to the nested ItemId artifact.

Item schema with nested ItemId schema

{
    "namespace":"com.example.common",
    "name":"Item",
    "type":"record",
    "fields":[
        {
            "name":"itemId",
            "type":"com.example.common.ItemId"
        }
    ]
}

Dereference

In some situations, having an artifact’s content with the referenced content inlined might be helpful. For those situations, the Core Registry API v3 supports the references parameter in certain operations.

This support is currently implemented for Avro, JSON Schema, Protobuf, OpenAPI, and AsyncAPI when the parameter is present in a particular API operation. XSD and WSDL artifacts support the parameter with REWRITE only; requesting DEREFERENCE for XSD or WSDL returns HTTP 400. The parameter is not supported in other schema types.

references=REWRITE is currently supported for JSON Schema, OpenAPI, AsyncAPI, XSD, and WSDL. For XSD and WSDL artifacts, REWRITE replaces each mapped schemaLocation or location value with the Apicurio Registry content URL of the referenced artifact. For Avro and Protobuf artifacts, requesting references=REWRITE returns HTTP 400 (DereferencingNotSupportedException). For XSD and WSDL artifacts, requesting references=DEREFERENCE returns HTTP 400 (DereferencingNotSupportedException).
Prerequisites
  • Apicurio Registry is installed and running in your environment.

Procedure
  1. Add the ItemId schema artifact that you want to create the nested artifact reference to using the /groups/{groupId}/artifacts operation:

    $ curl -X POST MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts \
       -H "Content-Type: application/json" \
       -H "Authorization: Bearer $ACCESS_TOKEN" \
       --data '{"artifactId":"ItemId","artifactType":"AVRO","firstVersion":{"version":"1.0.0","content":{"content":"{\"namespace\":\"com.example.common\",\"name\":\"ItemId\",\"type\":\"record\",\"fields\":[{\"name\":\"id\",\"type\":\"int\"}]}","contentType":"application/json"}}}'
    • This example adds an Avro schema artifact with an artifact ID of ItemId. If you do not specify a unique artifact ID, Apicurio Registry generates one automatically as a UUID.

    • MY-REGISTRY-URL is the hostname on which Apicurio Registry is deployed. For example: http://localhost:8080.

    • This example specifies a group ID of my-group in the API path. If you do not specify a unique group ID, you must specify ../groups/default in the API path.

  2. Verify that the response includes the expected JSON body to confirm that the artifact was added. For example:

    {"artifact":{"owner":"","createdOn":"2024-09-26T16:27:38Z","modifiedBy":"","modifiedOn":"2024-09-26T16:27:38Z","artifactType":"AVRO","groupId":"my-group","artifactId":"ItemId"},"version":{"version":"1.0.0","owner":"","createdOn":"2024-09-26T16:27:38Z","artifactType":"AVRO","globalId":2,"state":"ENABLED","groupId":"my-group","contentId":2,"artifactId":"ItemId"}}
  3. Add the Item schema artifact that includes the artifact reference to the ItemId schema using the /groups/{groupId}/artifacts operation:

    $ curl -X POST MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts \
    -H 'Content-Type: application/json' \
    -H "Authorization: Bearer $ACCESS_TOKEN" \
    --data-raw '{
    	"artifactId": "Item",
    	"artifactType": "AVRO",
    	"firstVersion": {
    		"version": "1.0.0",
    		"content": {
    			"content": "{\"namespace\":\"com.example.common\",\"name\":\"Item\",\"type\":\"record\",\"fields\":[{\"name\":\"itemId\",\"type\":\"com.example.common.ItemId\"}]}",
    			"contentType": "application/json",
    			"references": [
    				{
    					"name": "com.example.common.ItemId",
    					"groupId": "my-group",
    					"artifactId": "ItemId",
    					"version": "1.0.0"
    				}
    			]
    		}
    	}
    }'
  4. Verify that the response includes the expected JSON body to confirm that the artifact was created with the reference. For example:

    {"artifact":{"owner":"","createdOn":"2024-09-26T16:28:45Z","modifiedBy":"","modifiedOn":"2024-09-26T16:28:45Z","artifactType":"AVRO","groupId":"my-group","artifactId":"Item"},"version":{"version":"1.0.0","owner":"","createdOn":"2024-09-26T16:28:45Z","artifactType":"AVRO","globalId":3,"state":"ENABLED","groupId":"my-group","contentId":3,"artifactId":"Item"}}
  5. Retrieve the artifact reference from Apicurio Registry by specifying the coordinates of the artifact that includes the reference:

    $ curl -H "Authorization: Bearer $ACCESS_TOKEN" MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts/Item/versions/1.0.0/references
  6. Verify that the response includes the expected JSON body for this artifact reference. For example:

    [{"groupId":"my-group","artifactId":"ItemId","version":"1.0.0","name":"com.example.common.ItemId"}]
  7. Retrieve the dereferenced (inlined) schema content:

    $ curl -H "Authorization: Bearer $ACCESS_TOKEN" MY-REGISTRY-URL/apis/registry/v3/groups/my-group/artifacts/Item/versions/1.0.0/content?references=DEREFERENCE
  8. Verify that the response includes the expected JSON body for this artifact content with the references inlined. For example:

    {"type":"record","name":"Item","namespace":"com.example.common","fields":[{"name":"itemId","type":{"type":"record","name":"ItemId","fields":[{"name":"id","type":"int"}]}}]}

    This support is currently implemented only for Avro, Protobuf, OpenAPI, AsyncAPI, and JSON Schema artifacts when the dereference parameter is specified in the API operation. This parameter is not supported for any other artifact types. For XSD and WSDL artifacts, dereferencing returns HTTP 400.

    For Protobuf artifacts, dereferencing content is supported only when all the schemas belong to the same package.
    Some artifact types (for example, JSON Schema) allow circular dependencies, but Apicurio Registry does not support them.

Inspecting artifact reference graphs using the REST API

You can retrieve a reference graph to inspect the dependencies of an artifact version and the versions that depend on it. The graph includes indirect references, node and edge counts, and cycle information.

Prerequisites
  • Apicurio Registry is running, and the artifact version exists.

  • You have permission to read the artifact.

  • The REGISTRY_URL environment variable contains the registry URL, and ACCESS_TOKEN contains a valid access token if authentication is enabled.

Procedure
  • Request the reference graph for an artifact version:

    $ curl --fail-with-body \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      "$REGISTRY_URL/apis/registry/v3/groups/my-group/artifacts/Item/versions/1.0.0/references/graph?direction=BOTH&depth=3"

    The direction parameter accepts the following values:

    • OUTBOUND: Versions that the requested version references. This is the default.

    • INBOUND: Versions that reference the requested version.

    • BOTH: References in both directions.

      The default depth is 3. Use depth=1 for direct references or depth=0 for unlimited traversal. A larger graph can take longer to retrieve.

Verification
  • Inspect the response fields:

    • root identifies the requested artifact version.

    • nodes lists artifact versions, including the root, with their group ID, artifact ID, and version.

    • edges links sourceNodeId to targetNodeId and includes the reference name.

    • metadata contains totalNodes, totalEdges, maxDepth, and hasCycles.

      The graph reports the references traversed within the requested depth. A hasCycles value of false does not rule out cycles beyond that depth.

Exporting a Protobuf schema with its dependencies

You can download a Protobuf artifact version and its direct and indirect dependencies as a ZIP archive for use with the protoc compiler. Apicurio Registry organizes the files by package name and rewrites import statements to match those paths.

Prerequisites
  • Apicurio Registry contains the Protobuf artifact version and all its registered references.

  • You have permission to read the artifact.

  • You have installed curl and unzip.

  • The REGISTRY_URL environment variable contains the registry URL, and ACCESS_TOKEN contains a valid access token if authentication is enabled.

Procedure
  1. Download the schema package:

    $ curl --fail-with-body \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      "$REGISTRY_URL/apis/registry/v3/groups/my-group/artifacts/my-schema/versions/1.0.0/export" \
      --output my-schema-1.0.0.zip

    This operation supports only PROTOBUF artifacts. For another artifact type, the server returns HTTP 400. The registry resolves registered references while it streams the ZIP response. If a reference cannot be resolved, the download ends early with a truncated or invalid archive rather than an error status, so verify that the archive extracts cleanly.

  2. Extract the archive:

    $ unzip my-schema-1.0.0.zip -d my-schema

    For example, a schema with artifact ID my-schema and package com.example appears at com/example/my-schema.proto. The archive contains separate files for dependencies, including schemas in different packages.

Verification
  • List the archive entries and check that the schema and its dependencies are present:

    $ unzip -l my-schema-1.0.0.zip

    This archive contains Protobuf source files. Use the administrative export operation to create an archive for the registry import operation.

Searching for schema and API artifacts using Apicurio Registry REST API commands

You can use the Apicurio Registry REST API search endpoints to find artifacts, versions, and groups. Search filters match exactly by default, and you can use the * wildcard for pattern matching.

Procedure
  1. Search for artifacts with an exact filter value:

    $ curl "http://localhost:8080/apis/registry/v3/search/artifacts?artifactId=my-artifact"
  2. To match patterns, include the * wildcard anywhere in the groupId, artifactId, or labels filter values:

    $ curl "http://localhost:8080/apis/registry/v3/search/artifacts?artifactId=my-*"
    $ curl "http://localhost:8080/apis/registry/v3/search/artifacts?labels=env*:prod*"

    The * character is the only supported wildcard.

  3. To search by name, use an exact value or a leading or trailing * wildcard. The name filter matches against the artifact name or the artifact ID, and behaves the same on the artifact and version search endpoints:

    $ curl "http://localhost:8080/apis/registry/v3/search/versions?name=*payment*"

    The description filter is different: it always matches substrings.

  4. Optional: To improve performance on large result sets, set the skipCount parameter to true. The registry then skips the expensive total count query, and the count field in the response is 0:

    $ curl "http://localhost:8080/apis/registry/v3/search/artifacts?limit=50&skipCount=true"

    The skipCount parameter is available on the artifact and version search endpoints, and on the endpoints that list the artifacts of a group and the versions of an artifact.

Canonicalizing content using the Apicurio Registry REST API

You can use the Apicurio Registry REST API to convert schema or API content to its canonical form without storing it. Canonical content is useful for comparing schemas independently of formatting differences.

Procedure
  1. Send the content to the canonicalization endpoint. The artifactType query parameter is required:

    $ curl -X POST -H "Content-Type: application/json" --data @schema.json \
      "http://localhost:8080/apis/registry/v3/content/canonicalize?artifactType=AVRO"

    The response body contains the canonicalized content. An empty request body or an unknown artifact type produces a 400 error response.

  2. To retrieve the canonical form of a stored artifact version with its references resolved, use the canonical parameter on the version content endpoint instead:

    $ curl "http://localhost:8080/apis/registry/v3/groups/my-group/artifacts/my-artifact/versions/1.0.0/content?canonical=true"

    The canonicalization endpoint operates on the content exactly as provided and does not resolve external references. To canonicalize content that uses references, store the content first and use the canonical parameter.

Exporting and importing registry data using Apicurio Registry REST API commands

As an administrator, you can use the Core Registry API v3 to export data from one Apicurio Registry instance and import into another Apicurio Registry instance, so you can migrate data between different instances.

The export operation creates a ZIP archive containing registry data and metadata. By default, it includes all groups and global rules. You can limit the export to a single group by specifying the groupId query parameter.

Prerequisites
  • Apicurio Registry is installed and running in your environment.

  • Apicurio Registry instances have been created:

    • The source instance that you want to export data from contains at least one schema or API artifact.

    • The target instance that you want to import data into is empty to preserve unique IDs.

Procedure
  1. Export the Apicurio Registry data from your existing source Apicurio Registry instance:

    $ curl MY-REGISTRY-URL/apis/registry/v3/admin/export \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --output my-registry-data.zip

    MY-REGISTRY-URL is the hostname on which the source Apicurio Registry is deployed. For example: http://my-source-registry:8080.

    To export only one group, add the groupId query parameter instead:

    $ curl --fail-with-body --get MY-REGISTRY-URL/apis/registry/v3/admin/export \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-urlencode "groupId=my-group" \
      --output my-group-data.zip

    A group export excludes global rules and artifacts in other groups. If the group’s artifacts reference artifacts in another group, include those dependencies in your migration plan. The specified group must exist.

  2. Import the registry data into your target Apicurio Registry instance:

    $ curl -X POST "MY-REGISTRY-URL/apis/registry/v3/admin/import" \
      -H "Content-Type: application/zip" -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-binary @my-registry-data.zip

    MY-REGISTRY-URL is the hostname on which the target Apicurio Registry is deployed. For example: http://my-target-registry:8080.

    When importing a group export, use the file name my-group-data.zip instead. By default, the target registry must be empty, and the import preserves global IDs and content IDs. To import into a nonempty registry, set requireEmptyRegistry=false and set both X-Registry-Preserve-GlobalId and X-Registry-Preserve-ContentId headers to false to generate IDs on the target. These options do not resolve conflicts between existing artifact coordinates.

Verification
  • Retrieve the imported artifacts and versions from the target registry and compare their content with the source. Check the server log for failed or skipped entities because an import can skip an individual entity without failing the entire request.

Registry import archive format

The administrative import operation accepts a ZIP archive of registry entities, including metadata and schema content. An archive of schema files alone does not contain the metadata required for import. You can use the version 3 archive format to prepare data outside Apicurio Registry.

Table 1. Archive entries
Entry pattern Purpose

manifest-<timestamp>.Manifest.json

Export format and source system metadata. The archive must contain one manifest.

content/<hash>.Content.json

Content ID, content hash, canonical hash or artifact type, media type, and serialized references.

content/<hash>.Content.data

Raw schema or API bytes. Each content metadata file has a matching data file with the same name before the extension.

groups/<groupId>.Group.json

Group metadata.

groups/<groupId>/artifacts/<artifactId>/MetaData.Artifact.json

Artifact metadata, including the artifact type.

groups/<groupId>/artifacts/<artifactId>/versions/<version>.ArtifactVersion.json

Version metadata, including its global ID and the content ID that links it to a content entry.

groups/<groupId>/artifacts/<artifactId>/branches/<branchId>.Branch.json

Branch metadata and an ordered list of version strings.

rules/<ruleType>.GlobalRule.json

A global rule. Group exports exclude these entries.

groups/<groupId>/rules/<ruleType>.GroupRule.json

A group rule.

groups/<groupId>/artifacts/<artifactId>/rules/<ruleType>.ArtifactRule.json

An artifact rule.

groups/<groupId>/artifacts/<artifactId>/contract-rules/<name>.ContractRule.json

A contract rule. Each entry has a distinct name.

comments/<name>.Comment.json

A comment associated with a version’s global ID.

The entity type suffix, such as .ArtifactVersion.json, is case-sensitive. The importer reads entity fields from the JSON body and processes entities in dependency order, independently of their order in the archive. The default group uses default in archive paths and null for the groupId field in entity JSON.

Table 2. Core entity fields
Entity Fields and relationships

Manifest

exportVersion identifies the archive format, for example, 3.0. systemVersion identifies the source registry version, for example, 3.0.0. Other fields include systemName, systemDescription, exportedOn, exportedBy, and dbVersion.

Content

contentId identifies the content entry. contentType describes the raw bytes. contentHash is the SHA-256 hash of the bytes followed by the UTF-8 serializedReferences string when references exist. The registry canonical hash uses canonical content bytes followed by the serialized references when present. For content without references, you can omit canonicalHash and supply artifactType so that the importer computes the canonical hash.

Group and artifact

groupId identifies the group. An artifact also has artifactId and artifactType. Metadata fields include owner, createdOn, modifiedBy, modifiedOn, description, and labels. Artifact metadata can also include name.

Version

groupId, artifactId, and version identify the version. globalId is unique across versions. contentId refers to a content entry. versionOrder records the numeric creation order within the artifact. state contains a version state such as ENABLED. Version metadata can also include name, description, labels, ownership, and timestamps.

Branch

groupId, artifactId, and branchId identify the branch. versions contains version strings in branch order. systemDefined identifies system branches, including latest. Ownership and timestamps describe the branch.

Entity timestamps such as createdOn and modifiedOn use milliseconds since the Unix epoch. The serializedReferences field contains a JSON-encoded string, not a JSON array. Each reference includes name, groupId, artifactId, and version. For content without references, omit this field or use null.

For content with references, always supply a canonicalHash that matches the registry’s canonicalization and reference serialization. Do not rely on the automatic computation: the importer computes the hash from the canonical content bytes only, without appending the serialized references, so the computed value never matches the hash that the registry computes when it registers content with references. A registry export includes the stored canonical hashes.

An import preserves IDs by default. The archive must use consistent content IDs, global IDs, and artifact coordinates across related entries, even when the import generates new IDs. Branches require explicit branch entries; importing versions alone does not populate the latest branch.

Preparing a registry import archive from a schema file

You can build a version 3 import archive from a local schema without first exporting data from a registry. This example creates one Apache Avro artifact, one version, and a latest branch.

Prerequisites
  • You have installed Python 3 and curl.

  • The schema.json file contains a valid Apache Avro schema without external references.

  • The target registry is empty, and you have administrator access.

  • The REGISTRY_URL environment variable contains the target registry URL, and ACCESS_TOKEN contains a valid access token if authentication is enabled.

Procedure
  1. Save the following script as create-import.py:

    import hashlib
    import json
    import time
    import zipfile
    from pathlib import Path
    
    content = Path("schema.json").read_bytes()
    content_hash = hashlib.sha256(content).hexdigest()
    timestamp = int(time.time() * 1000)
    metadata = {
        "owner": "import-user",
        "createdOn": timestamp,
        "modifiedBy": "import-user",
        "modifiedOn": timestamp,
    }
    coordinates = {"groupId": "import-example", "artifactId": "my-schema"}
    artifact_path = "groups/import-example/artifacts/my-schema"
    entries = {
        "manifest.Manifest.json": {
            "exportVersion": "3.0",
            "systemVersion": "3.0.0",
            "systemName": "Offline import",
            "exportedOn": timestamp,
        },
        f"content/{content_hash}.Content.json": {
            "contentId": 1,
            "contentHash": content_hash,
            "contentType": "application/json",
            "artifactType": "AVRO",
        },
        "groups/import-example.Group.json": {
            **metadata, "groupId": "import-example",
        },
        f"{artifact_path}/MetaData.Artifact.json": {
            **metadata, **coordinates, "artifactType": "AVRO",
        },
        f"{artifact_path}/versions/1.0.0.ArtifactVersion.json": {
            **metadata, **coordinates,
            "globalId": 1, "contentId": 1,
            "version": "1.0.0", "versionOrder": 1, "state": "ENABLED",
        },
        f"{artifact_path}/branches/latest.Branch.json": {
            **metadata, **coordinates,
            "branchId": "latest", "systemDefined": True, "versions": ["1.0.0"],
        },
    }
    with zipfile.ZipFile("registry-import.zip", "w", zipfile.ZIP_DEFLATED) as archive:
        for name, entity in entries.items():
            archive.writestr(name, json.dumps(entity))
        archive.writestr(f"content/{content_hash}.Content.data", content)

    The example uses matching contentId values in the content and version entries. It supplies artifactType so that the importer computes the canonical hash. The manifest identifies version 3 archive data, independently of the target registry’s minor version.

  2. Run the script:

    $ python3 create-import.py
  3. Import the archive:

    $ curl --fail-with-body -X POST \
      "$REGISTRY_URL/apis/registry/v3/admin/import" \
      -H "Content-Type: application/zip" \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      --data-binary @registry-import.zip
Verification
  • Retrieve the imported version and compare it with schema.json:

    $ curl --fail-with-body \
      -H "Authorization: Bearer $ACCESS_TOKEN" \
      "$REGISTRY_URL/apis/registry/v3/groups/import-example/artifacts/my-schema/versions/1.0.0/content"

    Check the server log for import warnings if the artifact, version, or content is missing.