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.
On this page
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.
| Host | Serves | Authentication |
|---|---|---|
api.parcelgrid.mywire.org | Metadata, search, tokens, npm and OCI registries | Workspace token |
cdn.parcelgrid.mywire.org | Package index and artifact downloads | Signed 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
| Purpose | Endpoint | Notes |
|---|---|---|
| Health check | GET https://api.parcelgrid.mywire.org/v1/health | Anonymous, returns {"status":"ok"} |
| Workspace info | GET https://api.parcelgrid.mywire.org/v1/workspace | Token required |
| Package search | GET https://api.parcelgrid.mywire.org/v1/packages?q= | Token required |
| Usage report | GET https://api.parcelgrid.mywire.org/v1/usage?period=30d | Token required, JSON or CSV |
| npm registry | https://api.parcelgrid.mywire.org/v1/npm/ | Token required |
| OCI registry | https://api.parcelgrid.mywire.org/v1/oci/ | Token required |
| PyPI simple index | https://cdn.parcelgrid.mywire.org/simple/ | Token or signed URL |
| Artifact download | https://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.
- Validity. 15 minutes from issue; a URL cannot be extended.
- Binding. Workspace, object digest and expiry are part of the signature.
- Rejections. An unsigned or expired request is answered with
403 {"error":"forbidden"}, a path that does not exist in the workspace with404 {"error":"not_found"}. - Integrity. The
ETagof a download is the object digest, socurl -Ofollowed bysha256sumis a complete verification.
Rate limits and retries
| Operation | Limit | Answer when exceeded |
|---|---|---|
| Metadata requests, per token | 600 per minute | 429 + Retry-After |
| Artifact downloads, per workspace | 1200 per minute | 429 + Retry-After |
| Concurrent streams, per token | 32 | 429 |
| Token creation, per workspace | 20 per hour | 429 |
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 see | Why | What to do |
|---|---|---|
401 {"error":"unauthorized","message":"missing API key"} | No token, or the header was stripped by a proxy | Export PARCELGRID_TOKEN and check that the header survives the proxy |
403 {"error":"forbidden"} | Download URL is unsigned or expired | Ask the registry for the artifact again instead of reusing a stored URL |
404 {"error":"not_found"} | The path is not part of this workspace | Check the package name and that the version exists upstream |
429 | Rate limit reached | Respect Retry-After or move to a higher plan |
502 / 504 | Upstream registry did not answer and nothing is cached | Retry 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.