ParcelGrid

Home / Documentation

Documentation

Everything a pipeline needs: mirror endpoints, workspace tokens, per-ecosystem configuration, signed downloads and the error codes you are likely to see.

Overview

A workspace owns one cache per ecosystem. Requests are addressed with the workspace token, so two teams on the same account never share a namespace. The first request for a package version pulls it from the public registry, verifies the published digest and stores an immutable copy; every later request is answered from an edge cache.

HostServesAuthentication
api.parcelgrid.mywire.orgMetadata, search, tokens, npm and OCI registriesWorkspace token
cdn.parcelgrid.mywire.orgPackage index and artifact downloadsSigned URL or workspace token

Both hosts answer over TLS 1.3 with a public certificate; HTTP/2 is required for streaming downloads, HTTP/1.1 is accepted for metadata requests.

Quick start

Create a token in the console (Workspace → Tokens → Create), then export it in the pipeline. The token is shown once; a revoked token stops working within seconds.

export PARCELGRID_TOKEN="pgw_..."     # workspace token, keep it in the CI secret store

Then point each package manager at the mirror:

# npm
npm config set registry https://api.parcelgrid.mywire.org/v1/npm/
npm config set //api.parcelgrid.mywire.org/v1/npm/:_authToken "$PARCELGRID_TOKEN"

# pip
pip config set global.index-url https://cdn.parcelgrid.mywire.org/simple/
pip config set global.extra-index-url https://pypi.org/simple

Endpoints

PurposeEndpointNotes
Health checkGET https://api.parcelgrid.mywire.org/v1/healthAnonymous, returns {"status":"ok"}
Workspace infoGET https://api.parcelgrid.mywire.org/v1/workspaceToken required
Package searchGET https://api.parcelgrid.mywire.org/v1/packages?q=Token required
Usage reportGET https://api.parcelgrid.mywire.org/v1/usage?period=30dToken required, JSON or CSV
npm registryhttps://api.parcelgrid.mywire.org/v1/npm/Token required
OCI registryhttps://api.parcelgrid.mywire.org/v1/oci/Token required
PyPI simple indexhttps://cdn.parcelgrid.mywire.org/simple/Token or signed URL
Artifact downloadhttps://cdn.parcelgrid.mywire.org/<workspace>/<artifact>Signed URL only

Authentication and tokens

Tokens are scoped to one workspace and carry one role: read (fetch packages), write (publish internal packages) or admin (tokens and workspace settings). Send the token in the Authorization header:

curl -s -H "Authorization: Bearer $PARCELGRID_TOKEN" \
     https://api.parcelgrid.mywire.org/v1/workspace

Authentication is evaluated before routing, so a request carrying no token is answered the same way whether the path exists or not:

HTTP/2 401
content-type: application/json

{"error":"unauthorized","message":"missing API key"}

Rotate tokens in the console or with DELETE /v1/tokens/<id>. A revoked token stops working within a few seconds. Only the first six characters of a token are written to the audit trail; the rest never appears in logs.

PyPI mirror

The index is compatible with the PyPI simple API, so no plugin is required. Versions that nobody requests are evicted after the workspace retention window (90 days on Team), while pinned versions are kept as long as the pin exists.

# pip.conf
[global]
index-url = https://cdn.parcelgrid.mywire.org/simple/
extra-index-url = https://pypi.org/simple
timeout = 30
retries = 3

Keep the credential out of the file and pass it through the environment:

export PIP_INDEX_URL="https://token:$PARCELGRID_TOKEN@cdn.parcelgrid.mywire.org/simple/"

Wheels, sdists and index metadata are mirrored, and the hashes published upstream are re-checked, so --require-hashes and pip-audit behave as usual.

npm registry mirror

The registry speaks the npm protocol: scoped packages, dist-tags, tarball metadata and audit endpoints.

# .npmrc — safe to commit, the token comes from the environment
registry=https://api.parcelgrid.mywire.org/v1/npm/
//api.parcelgrid.mywire.org/v1/npm/:_authToken=${PARCELGRID_TOKEN}
always-auth=true

Metadata returned by the registry rewrites dist.tarball to a signed download URL that is valid for 15 minutes, so lockfiles keep resolving even when a dependency registry is unreachable from the build network.

OCI images

Container base layers are mirrored through a standard registry endpoint:

echo "$PARCELGRID_TOKEN" | docker login https://api.parcelgrid.mywire.org/v1/oci/ \
  --username pg --password-stdin
docker pull api.parcelgrid.mywire.org/v1/oci/library/python:3.12-slim

Downloads and signed URLs

Artifacts are served from cdn.parcelgrid.mywire.org and never straight from the public registry. The mirror signs each URL for the requesting workspace, and the signature covers the object digest, so a URL cannot be redirected at a different file.

Rate limits and retries

OperationLimitAnswer when exceeded
Metadata requests, per token600 per minute429 + Retry-After
Artifact downloads, per workspace1200 per minute429 + Retry-After
Concurrent streams, per token32429
Token creation, per workspace20 per hour429

Honour Retry-After: the value is in seconds and never below five. A failed upstream lookup is retried once automatically, and the cached copy is served in the meantime when one exists.

Troubleshooting

What you seeWhyWhat to do
401 {"error":"unauthorized","message":"missing API key"}No token, or the header was stripped by a proxyExport PARCELGRID_TOKEN and check that the header survives the proxy
403 {"error":"forbidden"}Download URL is unsigned or expiredAsk the registry for the artifact again instead of reusing a stored URL
404 {"error":"not_found"}The path is not part of this workspaceCheck the package name and that the version exists upstream
429Rate limit reachedRespect Retry-After or move to a higher plan
502 / 504Upstream registry did not answer and nothing is cachedRetry later, or seed the cache from a machine that reaches the upstream

Before blaming the network, check the service itself: curl -s https://api.parcelgrid.mywire.org/v1/health must return {"status":"ok"}.

Support

Write to support@parcelgrid.mywire.org with the workspace name, the request timestamp and the request id from the response headers. Incidents are tracked on the status page; contractual terms and data handling are described in the terms of service and the privacy policy.

Last updated 28 October 2026.