Artifact

Register a platform artifact

Changed on

Idempotent upsert. The owner nrn, the type and the identity subset of meta identify the artifact; each unique full meta blob mints (or reuses) one revision. The response carries the artifact and revision ids that package components pin.

Returns 201 when the call created the artifact or a new revision, and 200 when both already existed.

On an artifact that already exists:

  • A visible_to in the body replaces the artifact's visibility.
  • annotations aren't part of the revision identity. When the body carries annotations, they replace the stored set as a whole (last write wins), so always send the complete set. Omitting them keeps the stored set.

ℹ️ Note: For oci_image, tag is part of the revision meta: registering an existing digest under a new tag mints a new revision.

post/artifacts

Request

  • Base URL
    https://api.nullplatform.com
  • URL
    https://api.nullplatform.com/artifacts
  • Auth
    HTTP bearer

Request body

nrnstring required

The owning NRN.

type'oci_image' | 'oras_artifact' | 'git_repository' | 'blob' required

Discriminator for the meta shape.

metaArtifactMeta required

Flat meta blob. Its shape depends on type:

  • oci_image: registry and repository (strings), digest (sha256: followed by 64 lowercase hex characters), and an optional tag (an OCI tag, up to 128 characters).
  • oras_artifact: registry, repository and digest (same rules as oci_image), and an optional artifact_media_type string.
  • git_repository: url and reference (any non-empty ref, such as a commit SHA, tag or branch), and an optional path: the directory of a monorepo the artifact stands for. When present, path is part of the artifact identity, so the same url under different paths registers different artifacts, each with its own revisions. Omit it for the repository root. It must be relative to the repository root, use / as separator, have no . or .. segments and no trailing slash; a path that doesn't follow these rules is rejected, never normalized. The url must not embed credentials: a password is rejected in any form, a user is rejected over http(s) (a user such as git@ is allowed over ssh and the scp-like user@host:path form), and a url with a scheme must not carry a query string or fragment.
  • blob: location (starting with s3://, gs://, https:// or http://), sha256 (64 lowercase hex characters), and an optional size_bytes (non-negative integer).

Any key not listed for the type is rejected, and so is an explicit null value: omit the key instead.

ℹ️ Note: A git_repository artifact is a pointer only. nullplatform never stores the repository content, so never commit secrets to a referenced repository.

annotationsArtifactAnnotations

Descriptive data stored on the revision, never part of its identity. The curated changelog key must be a non-empty markdown string of up to 65,536 characters and is rendered as release notes in the console. Any other key is free-form (reverse-DNS names are encouraged) and stored verbatim. The whole object is capped at 262,144 characters once serialized as JSON.

visible_tostring[]

Defaults to [nrn]. Use ["organization=*"] to publish globally.

Example request

{
  "nrn": "organization=1:account=2",
  "meta": {
    "registry": "123456789012.dkr.ecr.us-east-1.amazonaws.com",
    "repository": "my-org/my-scope",
    "digest": "sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
    "tag": "v1.4.0"
  },
  "annotations": {
    "changelog": "## 1.4.0\n\n- Adds blue-green support",
    "org.opencontainers.image.source": "https://github.com/my-org/my-scope",
    "org.opencontainers.image.version": "v1.4.0"
  },
  "visible_to": [
    "organization=1:account=2"
  ]
}

Response

The artifact and revision already existed.

resource_idstring uuid

The parent artifact id (a package component's resource_id).

resource_revision_idstring uuid

The revision id (a package component's resource_revision_id).

type'oci_image' | 'oras_artifact' | 'git_repository' | 'blob'

The parent artifact's type.

metaArtifactMeta

Flat meta blob. Its shape depends on type:

  • oci_image: registry and repository (strings), digest (sha256: followed by 64 lowercase hex characters), and an optional tag (an OCI tag, up to 128 characters).
  • oras_artifact: registry, repository and digest (same rules as oci_image), and an optional artifact_media_type string.
  • git_repository: url and reference (any non-empty ref, such as a commit SHA, tag or branch), and an optional path: the directory of a monorepo the artifact stands for. When present, path is part of the artifact identity, so the same url under different paths registers different artifacts, each with its own revisions. Omit it for the repository root. It must be relative to the repository root, use / as separator, have no . or .. segments and no trailing slash; a path that doesn't follow these rules is rejected, never normalized. The url must not embed credentials: a password is rejected in any form, a user is rejected over http(s) (a user such as git@ is allowed over ssh and the scp-like user@host:path form), and a url with a scheme must not carry a query string or fragment.
  • blob: location (starting with s3://, gs://, https:// or http://), sha256 (64 lowercase hex characters), and an optional size_bytes (non-negative integer).

Any key not listed for the type is rejected, and so is an explicit null value: omit the key instead.

ℹ️ Note: A git_repository artifact is a pointer only. nullplatform never stores the repository content, so never commit secrets to a referenced repository.

annotationsobject nullable

The revision's annotations (see the registration body), or null when it has none.

nrnstring

The parent artifact's owning NRN.

visible_tostring[]

The parent artifact's visibility.

created_atstring date-time

When the revision was registered.

Example response

{
  "resource_id": "5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f",
  "resource_revision_id": "2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e",
  "type": "oci_image",
  "meta": {
    "registry": "123456789012.dkr.ecr.us-east-1.amazonaws.com",
    "repository": "my-org/my-scope",
    "digest": "sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945",
    "tag": "v1.4.0"
  },
  "nrn": "organization=1:account=2",
  "visible_to": [
    "organization=1:account=2"
  ],
  "created_at": "2026-09-14T12:00:00.000Z"
}

Changes