---
title: "Register a platform artifact"
method: POST
path: "/artifacts"
tags: ["Artifact"]
---

# Register a platform artifact

`POST /artifacts`

## Request

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

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.

## Request body

- ArtifactRegistration
  - `nrn` string, required: The owning NRN.
  - `type` 'oci_image' | 'oras_artifact' | 'git_repository' | 'blob', required: Discriminator for the meta shape.
  - `meta` ArtifactMeta, 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.
  - `annotations` ArtifactAnnotations: 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_to` string[]: Defaults to [nrn]. Use ["organization=*"] to publish globally.

## Response `200`

The artifact and revision already existed.

- ArtifactRevision: One immutable revision, identified by the ids a package component pins.
  - `resource_id` string, uuid: The parent artifact id (a package component's resource_id).
  - `resource_revision_id` string, uuid: The revision id (a package component's resource_revision_id).
  - `type` 'oci_image' | 'oras_artifact' | 'git_repository' | 'blob': The parent artifact's type.
  - `meta` ArtifactMeta: 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.
  - `annotations` object, nullable: The revision's annotations (see the registration body), or null when it has none.
  - `nrn` string: The parent artifact's owning NRN.
  - `visible_to` string[]: The parent artifact's visibility.
  - `created_at` string, date-time: When the revision was registered.

## Other responses

- `201`: The call created the artifact or a new revision.
- `4XX`: Client error responses due to invalid input, missing parameters or insufficient permissions.
- `5XX`: Server error responses.

## Changes

- **2026-09-17** `43b3c1ecdfd8`: 1 info
  - endpoint added

[Operation history](https://skmtc.dev/nullplatform/apis/nullplatform-api/changes/artifacts/post.md)

---

[API](https://skmtc.dev/nullplatform/apis/nullplatform-api.md) - [All operations](https://skmtc.dev/nullplatform/apis/nullplatform-api/llms.txt) - [OpenAPI document](https://skmtc.dev/nullplatform/apis/nullplatform-api/revisions/d3f66bc633d4?raw)
