Docs
Search docs

Get a registry package with its tags

GET/api/owners/{handle}/packages/{package}

getPackage

The package, its tags newest push first, and each tag's push provenance: digest, media type, size, who pushed it and — when a CI job pushed it and the caller can read that run's repo — the run and the commit it built. Authorized by the same decision the pull path asks; a package the caller could not pull is a 404, indistinguishable from an unknown name.

Authentication is not described for this operation in the spec — that does not mean it is public. Check tokens and scopes.

curl

curl -X GET 'https://neosource.dev/api/owners/HANDLE/packages/PACKAGE'

fetch

fetch("https://neosource.dev/api/owners/HANDLE/packages/PACKAGE", {
  method: "GET",
});

Path parameters

handlerequired

Handle of the owner — either a user account or an organization.

string

packagerequired

The package name (the `{package}` in `/v2/{owner}/{package}`).

string

Responses

200Package detail

application/json

PackageDetailResponse

object

`GET /api/owners/{handle}/packages/{package}`.

packagerequired

PackageResponse

object

One registry package. `visibility` is the package's OWN visibility, never the linked repo's: anonymous pull is gated on this field alone (ADR 0097 §4), and a private repo may hold a public package or the reverse.

created_atrequired

integerint64

namerequired

string

The `{package}` path component. Obeys the OCI `path-component` grammar, which is narrower than a repo slug.

ownerrequired

string

Owner handle the package is served under — the `{owner}` in `/v2/{owner}/{package}`.

package_idrequired

string

pull_refrequired

string

What `docker pull` takes, without a tag: `{registry_host}/{owner}/{name}`, where the host is the registry's ADVERTISED hostname (`neocr.io` in production, ADR 0097 §1) — the forge's own host only where no separate registry host is configured.

example"neocr.io/neosource/server"

repo_id

string | null

The optional repo link. `null` for an unlinked package, and on the read routes also when the caller cannot read the linked repo (a public package may link a private one).

updated_atrequired

integerint64

visibilityrequired
RepoVisibilityInput
workspace_idrequired

string

repo

string | null

Slug of the linked repo (in the package owner's namespace); `null` for an unlinked package, or when the caller cannot read the linked repo.

tagsrequired

array

The newest 100 tags, newest push first.

items

PackageTagResponse

object

One tag with the provenance of its latest push. Every provenance field is `null` for a tag bound before provenance was recorded.

digestrequired

string

`sha256:<hex>` — the manifest digest the tag points at.

media_type

string | null

The manifest's `Content-Type` as pushed. An open vocabulary (any OCI or Docker manifest media type), hence a string.

pushed_atrequired

integerint64

When the tag was last pushed (Unix millis).

pushed_by

string | null

Handle of the account the latest push is attributed to; `null` for an actor-less run, a deleted account, a tag predating provenance, or a CI push whose `run` is hidden from the caller.

run
one of
size

integer | nullint64

Manifest size in bytes.

tagrequired

string

total_tagsrequired

integerint64

How many tags the package holds in all; more than `tags.len()` when the list was cut at 100.

403Forbidden — one of: forbidden, needs_scope

application/json

one of
  • ErrorForbidden
  • NeedsScopeError

    object

    `403` body returned when a classic OAuth token is asked for something its granted scopes do not cover — an explicit private listing without `repo`, or the one-click GitHub mirror without `admin:public_key`. `scope` names the missing grant so the client can say exactly what the token lacks. There is no elevation route to widen it any more (a re-link goes through the GitHub App, whose tokens carry no scopes), so the client's answer is to say so, never to start a handshake.

    errorrequired

    string

    Always `needs_scope` — this body exists to carry the extra fields that kind needs.

    "needs_scope"

    scoperequired

    string

    The provider scope to request via elevation (e.g. `"repo"`).

Standard errors

Bodies documented once for the whole API — see standard errors.

  • 400Bad Request — one of: invalid_input
  • 404Not Found — one of: not_found
  • 429Rate limited — retry after the `Retry-After` header
  • 500Internal server error
  • 503Service temporarily unavailable / at capacity — retry after the `Retry-After` header
  • 504Gateway timeout — the request exceeded the server's handling budget

Schemas

Referenced above. Listed here rather than expanded inline, so the same definition is not repeated at every level.

RepoVisibilityInput

string

"public""internal""private"

PackageTagRun

object

The CI run a tag's latest push came from, shown only to a caller who can read that run's repo.

commit_sha

string | null

The commit (40-char git hex) the run built; `null` for a run with no single commit target (a schedule, a legacy manual row).

ownerrequired

string

Handle of the run's repo owner.

reporequired

string

The run's repo slug.

run_idrequired

string