---
id: artifact-register
title: "Register a platform artifact"
description: "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."
sidebar_label: "Register a platform artifact"
hide_title: true
hide_table_of_contents: true
api: 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
sidebar_class_name: "post api-method"
info_path: docs/api/artifact
custom_edit_url: null
---

import MethodEndpoint from "@theme/ApiExplorer/MethodEndpoint";
import ParamsDetails from "@theme/ParamsDetails";
import RequestSchema from "@theme/RequestSchema";
import StatusCodes from "@theme/StatusCodes";
import OperationTabs from "@theme/OperationTabs";
import TabItem from "@theme/TabItem";
import Heading from "@theme/Heading";

<Heading
  as={"h1"}
  className={"openapi__heading"}
  children={"Register a platform artifact"}
>
</Heading>

<MethodEndpoint
  method={"post"}
  path={"/artifacts"}
  context={"endpoint"}
>
  
</MethodEndpoint>



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.


<Heading
  id={"request"}
  as={"h2"}
  className={"openapi-tabs__heading"}
  children={"Request"}
>
</Heading>

<ParamsDetails
  parameters={undefined}
>
  
</ParamsDetails>

<RequestSchema
  title={"Body"}
  body={{"content":{"application/json":{"schema":{"type":"object","required":["nrn","type","meta"],"properties":{"nrn":{"type":"string","description":"The owning NRN.","example":"organization=1:account=2"},"type":{"type":"string","enum":["oci_image","oras_artifact","git_repository","blob"],"description":"Discriminator for the meta shape."},"meta":{"type":"object","additionalProperties":true,"description":"Flat meta blob. Its shape depends on `type`:\n\n- `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).\n- `oras_artifact`: `registry`, `repository` and `digest` (same rules as `oci_image`), and an optional `artifact_media_type` string.\n- `git_repository`: `url` and `reference` (any non-empty ref, such as a commit SHA, tag or branch). 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.\n- `blob`: `location` (starting with `s3://`, `gs://`, `https://` or `http://`), `sha256` (64 lowercase hex characters), and an optional `size_bytes` (non-negative integer).\n\nAny key not listed for the type is rejected, and so is an explicit `null` value: omit the key instead.\n\n> ℹ️ **Note:** A `git_repository` artifact is a pointer only. nullplatform never stores the repository content, so never commit secrets to a referenced repository.\n","example":{"registry":"123456789012.dkr.ecr.us-east-1.amazonaws.com","repository":"my-org/my-scope","digest":"sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945","tag":"v1.4.0"},"title":"artifactMeta"},"annotations":{"type":"object","additionalProperties":true,"description":"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.","example":{"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"},"title":"artifactAnnotations"},"visible_to":{"type":"array","items":{"type":"string"},"description":"Defaults to [nrn]. Use [\"organization=*\"] to publish globally.","example":["organization=1:account=2"]}},"title":"artifactRegistration"}}}}}
>
  
</RequestSchema>

<StatusCodes
  id={undefined}
  label={undefined}
  responses={{"200":{"description":"The artifact and revision already existed.","content":{"application/json":{"schema":{"type":"object","description":"One immutable revision, identified by the ids a package component pins.","properties":{"resource_id":{"type":"string","format":"uuid","description":"The parent artifact id (a package component's resource_id).","example":"5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f"},"resource_revision_id":{"type":"string","format":"uuid","description":"The revision id (a package component's resource_revision_id).","example":"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e"},"type":{"type":"string","enum":["oci_image","oras_artifact","git_repository","blob"],"description":"The parent artifact's type.","example":"oci_image"},"meta":{"type":"object","additionalProperties":true,"description":"Flat meta blob. Its shape depends on `type`:\n\n- `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).\n- `oras_artifact`: `registry`, `repository` and `digest` (same rules as `oci_image`), and an optional `artifact_media_type` string.\n- `git_repository`: `url` and `reference` (any non-empty ref, such as a commit SHA, tag or branch). 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.\n- `blob`: `location` (starting with `s3://`, `gs://`, `https://` or `http://`), `sha256` (64 lowercase hex characters), and an optional `size_bytes` (non-negative integer).\n\nAny key not listed for the type is rejected, and so is an explicit `null` value: omit the key instead.\n\n> ℹ️ **Note:** A `git_repository` artifact is a pointer only. nullplatform never stores the repository content, so never commit secrets to a referenced repository.\n","example":{"registry":"123456789012.dkr.ecr.us-east-1.amazonaws.com","repository":"my-org/my-scope","digest":"sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945","tag":"v1.4.0"},"title":"artifactMeta"},"annotations":{"type":"object","additionalProperties":true,"nullable":true,"description":"The revision's annotations (see the registration body), or null when it has none."},"nrn":{"type":"string","description":"The parent artifact's owning NRN.","example":"organization=1:account=2"},"visible_to":{"type":"array","items":{"type":"string"},"description":"The parent artifact's visibility.","example":["organization=1:account=2"]},"created_at":{"type":"string","format":"date-time","description":"When the revision was registered.","example":"2026-09-14T12:00:00.000Z"}},"title":"artifactRevision"}}}},"201":{"description":"The call created the artifact or a new revision.","content":{"application/json":{"schema":{"type":"object","description":"One immutable revision, identified by the ids a package component pins.","properties":{"resource_id":{"type":"string","format":"uuid","description":"The parent artifact id (a package component's resource_id).","example":"5c6d7e8f-9a0b-4c1d-8e2f-3a4b5c6d7e8f"},"resource_revision_id":{"type":"string","format":"uuid","description":"The revision id (a package component's resource_revision_id).","example":"2b3c4d5e-6f7a-4b8c-9d0e-1f2a3b4c5d6e"},"type":{"type":"string","enum":["oci_image","oras_artifact","git_repository","blob"],"description":"The parent artifact's type.","example":"oci_image"},"meta":{"type":"object","additionalProperties":true,"description":"Flat meta blob. Its shape depends on `type`:\n\n- `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).\n- `oras_artifact`: `registry`, `repository` and `digest` (same rules as `oci_image`), and an optional `artifact_media_type` string.\n- `git_repository`: `url` and `reference` (any non-empty ref, such as a commit SHA, tag or branch). 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.\n- `blob`: `location` (starting with `s3://`, `gs://`, `https://` or `http://`), `sha256` (64 lowercase hex characters), and an optional `size_bytes` (non-negative integer).\n\nAny key not listed for the type is rejected, and so is an explicit `null` value: omit the key instead.\n\n> ℹ️ **Note:** A `git_repository` artifact is a pointer only. nullplatform never stores the repository content, so never commit secrets to a referenced repository.\n","example":{"registry":"123456789012.dkr.ecr.us-east-1.amazonaws.com","repository":"my-org/my-scope","digest":"sha256:4f53cda18c2baa0c0354bb5f9a3ecbe5ed12ab4d8e11ba873c2f11161202b945","tag":"v1.4.0"},"title":"artifactMeta"},"annotations":{"type":"object","additionalProperties":true,"nullable":true,"description":"The revision's annotations (see the registration body), or null when it has none."},"nrn":{"type":"string","description":"The parent artifact's owning NRN.","example":"organization=1:account=2"},"visible_to":{"type":"array","items":{"type":"string"},"description":"The parent artifact's visibility.","example":["organization=1:account=2"]},"created_at":{"type":"string","format":"date-time","description":"When the revision was registered.","example":"2026-09-14T12:00:00.000Z"}},"title":"artifactRevision"}}}},"4XX":{"description":"Client error responses due to invalid input, missing parameters or insufficient permissions.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","description":"HTTP status code.","example":400},"code":{"type":"string","description":"Machine-readable error code.","example":"bad_request"},"error":{"type":"string","description":"Short error name.","example":"Bad Request"},"message":{"type":"string","description":"Human-readable explanation.","example":"meta.digest must match sha256:<64-hex>"}},"title":"errorResponse"}}}},"5XX":{"description":"Server error responses.","content":{"application/json":{"schema":{"type":"object","properties":{"statusCode":{"type":"integer","description":"HTTP status code.","example":400},"code":{"type":"string","description":"Machine-readable error code.","example":"bad_request"},"error":{"type":"string","description":"Short error name.","example":"Bad Request"},"message":{"type":"string","description":"Human-readable explanation.","example":"meta.digest must match sha256:<64-hex>"}},"title":"errorResponse"}}}}}}
>
  
</StatusCodes>


      