---
title: "Packages and registries"
description: "The npm and cargo registries your packages are published to and installed from, and the reads behind the Packages pages."
order: 8
---

The npm and cargo registries your packages are published to and installed from, and the reads behind the Packages pages.

## `GET /api/v1/packages`

Every claimed name in the projects the caller belongs to.

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | [EstatePackagesResponse](#estatepackagesresponse) |

## `GET /api/v1/projects/{slug}/modules`

The modules the project publishes, with the projects that use them.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `slug` | path | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | [ProjectModulesResponse](#projectmodulesresponse) |
| 403 | Your role does not allow this |  |
| 404 | No such project |  |

## `GET /api/v1/projects/{slug}/modules/{name}/notes`

Every recorded release's notes for one module, newest first. A module with no notes answers an empty list; a name the project never recorded is a 404.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `slug` | path | string |  |
| `name` | path | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | array of [ModuleNotes](#modulenotes) |
| 403 | Your role does not allow this |  |
| 404 | No such project or module |  |

## `GET /api/v1/projects/{slug}/packages`

One project's Packages page: its images, its npm names, its crates, and the three urls the "How to publish" text prints.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `slug` | path | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | [ProjectPackagesResponse](#projectpackagesresponse) |
| 403 | Your role does not allow this |  |
| 404 | No such project |  |

## `GET /api/v1/projects/{slug}/packages/{registry}`

One registry's names in one project.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `slug` | path | string |  |
| `registry` | path | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | array of [PackageSummary](#packagesummary) |
| 403 | Your role does not allow this |  |
| 404 | No such project or registry |  |

## `GET /api/v1/projects/{slug}/packages/{registry}/{name}`

One name and every version published under it.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `slug` | path | string |  |
| `registry` | path | string |  |
| `name` | path | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | [PackageDetailResponse](#packagedetailresponse) |
| 403 | Your role does not allow this |  |
| 404 | No such project, registry or package |  |

## `GET /cargo/1/{name}`

The index entry of a crate with a one letter name: one line for each version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `name` | path | string | A one character crate name |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The index file, one JSON object per line |  |
| 304 | The client already holds this file |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such crate |  |

## `GET /cargo/2/{name}`

The index entry of a crate with a two letter name: one line for each version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `name` | path | string | A two character crate name |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The index file, one JSON object per line |  |
| 304 | The client already holds this file |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such crate |  |

## `GET /cargo/3/{first}/{name}`

The index entry of a crate with a three letter name: one line for each version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `first` | path | string | The first character of the name |
| `name` | path | string | A three character crate name |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The index file, one JSON object per line |  |
| 304 | The client already holds this file |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such crate |  |

## `PUT /cargo/api/v1/crates/new`

Publish one version of a crate. `cargo publish --registry ops` sends it.

| Status | Means | Body |
| --- | --- | --- |
| 200 | Published |  |
| 400 | The length prefixed body or its metadata is malformed |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Unclaimed, or not allowed to publish |  |
| 409 | That version is already published |  |
| 413 | Larger than the body limit |  |

## `GET /cargo/api/v1/crates/{name}/{version}/download`

Download one crate version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `name` | path | string | The crate name |
| `version` | path | string | The version, as published |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The .crate archive |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such crate or version |  |

## `PUT /cargo/api/v1/crates/{name}/{version}/unyank`

Undo a yank.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `name` | path | string | The crate name |
| `version` | path | string | The version, as published |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Unyanked |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to publish in this project |  |
| 404 | No such version |  |

## `DELETE /cargo/api/v1/crates/{name}/{version}/yank`

Yank one crate version, so new lockfiles stop choosing it. Lockfiles that already name it keep working.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `name` | path | string | The crate name |
| `version` | path | string | The version, as published |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Yanked |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to publish in this project |  |
| 404 | No such version |  |

## `GET /cargo/config.json`

Where cargo downloads crates from and publishes to. Cargo reads it first.

| Status | Means | Body |
| --- | --- | --- |
| 200 | The sparse registry's discovery document |  |

## `GET /cargo/{prefix}/{infix}/{name}`

The index entry of a crate with a name of four letters or more: one line for each version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `prefix` | path | string | The first two characters of the name |
| `infix` | path | string | The next two characters of the name |
| `name` | path | string | A crate name of four characters or more |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The index file, one JSON object per line |  |
| 304 | The client already holds this file |  |
| 401 | No live ops token in the bare Authorization header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such crate |  |

## `GET /npm/{pkg}`

The npm package document: every version of the package and where to download it. npm and pnpm read it on install.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `pkg` | path | string | The scoped name, one percent encoded segment |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The packument |  |
| 401 | No live ops token in the Bearer header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such package |  |

## `PUT /npm/{pkg}`

Publish one version of an npm package. `npm publish` and `pnpm publish` send it.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `pkg` | path | string | The scoped name, one percent encoded segment |

| Status | Means | Body |
| --- | --- | --- |
| 201 | Published |  |
| 401 | No live ops token in the Bearer header |  |
| 403 | Out of scope, unclaimed, or not allowed to publish |  |
| 409 | That version is already published |  |
| 413 | Larger than the body limit |  |
| 422 | The publish body is not one version with one tarball |  |

## `GET /npm/{pkg}/-/{file}`

Download the tarball of one npm package version.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `pkg` | path | string | The scoped name, one percent encoded segment |
| `file` | path | string | The filename the packument advertised |

| Status | Means | Body |
| --- | --- | --- |
| 200 | The archive bytes |  |
| 401 | No live ops token in the Bearer header |  |
| 403 | Not allowed to read this project's packages |  |
| 404 | No such package or version |  |

## `GET /v2/token`

A short lived token for the image registry, in exchange for an ops token sent as the password. `docker login` and `docker push` ask for it.

| Parameter | In | Type | About |
| --- | --- | --- | --- |
| `service` | query | string |  |
| `scope` (optional) | query | string |  |

| Status | Means | Body |
| --- | --- | --- |
| 200 | Done | [RegistryTokenResponse](#registrytokenresponse) |
| 400 | Unknown registry service |  |
| 401 | The basic credential is not a live ops token |  |
| 503 | No issuer key is configured |  |

## Types

### EstatePackagesResponse

It carries no images, because an image belongs to a service and a service belongs to one project.

| Field | Type | About |
| --- | --- | --- |
| `cargo` | array of [PackageSummary](#packagesummary) |  |
| `npm` | array of [PackageSummary](#packagesummary) |  |

### ProjectModulesResponse

| Field | Type | About |
| --- | --- | --- |
| `modules` | array of [ModuleSummary](#modulesummary) |  |
| `version` (optional) | string or null | The tag version the list was recorded at; `null` until a `modules/` tree has published, which is also what a project that publishes no modules answers. |

### ModuleNotes

One release's patch notes, Markdown as the CHANGELOG.md section holds it.

| Field | Type | About |
| --- | --- | --- |
| `notes` | string |  |
| `version` | string |  |

### ProjectPackagesResponse

One project's Packages page: the two claimed name lists, the images derived from its builds, and the three urls the "How to publish" text prints.

| Field | Type | About |
| --- | --- | --- |
| `cargo` | array of [PackageSummary](#packagesummary) |  |
| `cargo_index_url` | string |  |
| `images` | array of [ImageRepoSummary](#imagereposummary) |  |
| `npm` | array of [PackageSummary](#packagesummary) |  |
| `npm_registry_url` | string | The absolute npm and cargo base urls the "How to publish" text prints. |
| `registry_host` | string | The registry host, "" when OPS_REGISTRY is unset. |

### PackageSummary

| Field | Type | About |
| --- | --- | --- |
| `bytes` | integer |  |
| `latest` (optional) | string or null | The newest version by published_at; `null` when the name is claimed and empty. |
| `name` | string |  |
| `project` | string |  |
| `published_at` (optional) | string or null |  |
| `publisher` (optional) | string or null |  |
| `registry` | string | "npm" or "cargo". |
| `versions` | integer |  |
| `yanked` | integer |  |

### PackageDetailResponse

One name and everything published under it. `blob_key`, `shasum` and the stored manifest stay out: the first is an object key nothing outside ops may address, and the other two are wire fields the packument rebuilds.

| Field | Type | About |
| --- | --- | --- |
| `dist_tags` | map of string | npm only; empty for a crate. |
| `name` | string |  |
| `project` | string |  |
| `registry` | string |  |
| `shared_with` | array of string | Empty on almost every claim, and the page prints "null" for it. |
| `versions` | array of [PackageVersionSummary](#packageversionsummary) |  |

### RegistryTokenResponse

What a docker client reads. `access_token` duplicates `token`: older clients read one field, newer ones the other, and Distribution's own realm sends both.

| Field | Type | About |
| --- | --- | --- |
| `access_token` | string |  |
| `expires_in` | integer |  |
| `issued_at` | string |  |
| `token` | string |  |

### ModuleSummary

One module: the folder's name, the two published names it groups, its place in the framework's graph and who uses it.

| Field | Type | About |
| --- | --- | --- |
| `consumers` | array of [ModuleConsumer](#moduleconsumer) |  |
| `crate_name` (optional) | string or null | `syncronet-<name>` on the cargo registry, when the module has a crate. |
| `description` | string |  |
| `layer_name` (optional) | string or null | The npm name, when the module has a layer. |
| `name` | string |  |
| `requires` | array of string | The other modules its crate depends on. |

### ImageRepoSummary

| Field | Type | About |
| --- | --- | --- |
| `commit` | string |  |
| `digest` | string | The newest digest ops pushed, "sha256:…". |
| `environments` | array of string | Environments currently running this digest, in environment order. |
| `pushed_at` (optional) | string or null |  |
| `repository` | string | "{project}/{service}", the repository name in the registry. |
| `service` | string |  |
| `size_bytes` (optional) | integer or null |  |

### PackageVersionSummary

| Field | Type | About |
| --- | --- | --- |
| `digest` | string | The archive's SHA-256, lowercase hex, no "sha256:" prefix. |
| `integrity` (optional) | string or null | npm only. |
| `published_at` | string |  |
| `publisher` | string |  |
| `size_bytes` | integer |  |
| `version` | string |  |
| `yanked` | boolean |  |

### ModuleConsumer

A project whose newest default branch build resolved one of the module's halves.

| Field | Type | About |
| --- | --- | --- |
| `package` | string | The published name it resolved, `syncronet-auth` or `@syncronet/nuxt-auth`. |
| `project` | string |  |
| `version` | string |  |
