Developer API
The MirrorHub API is a plain HTTPS/JSON interface. There is no SDK to install and no client to keep updated — every endpoint is reachable with curl, and any CI runner can call it directly.
Base URL: https://api.mirrorhub.space/v1
Authentication
Requests are authenticated with a bearer token issued per namespace. Tokens are created in the control panel or with the API itself. Read-scoped tokens are enough for CI; write-scoped tokens are required for purge and upload operations.
# Store the token as a CI secret, never in the repository
export MH_TOKEN="mhk_live_9f4c2a7be1d85c30"
# Authenticated request
curl -sS -H "Authorization: Bearer $MH_TOKEN" \
https://api.mirrorhub.space/v1/namespaces
Tokens may be restricted by source IP range and by expiry. Rotate them from the control panel; revocation takes effect within 30 seconds across all nodes.
Pulling from a private namespace
Private mirrors use the same protocol paths as the public ones. Supply the token as the password, or as an HTTP header if your client supports it.
# APT (Debian / Ubuntu) — /etc/apt/auth.conf.d/mirrorhub.conf
machine mirrorhub.space
login mh-ci
password mhk_live_9f4c2a7be1d85c30
# Docker / OCI
echo "$MH_TOKEN" | docker login de.mirrorhub.space -u mh-ci --password-stdin
docker pull de.mirrorhub.space/acme/base-image:2026.10
# npm
npm config set //de.mirrorhub.space/npm/:_authToken "$MH_TOKEN"
# pip
pip install --index-url https://mh-ci:$MH_TOKEN@de.mirrorhub.space/pypi/simple \
acme-internal-sdk
Endpoints
| Method | Path | Description |
|---|---|---|
| GET | /v1/namespaces | List namespaces the token can access, with storage and egress counters. |
| GET | /v1/namespaces/{ns}/usage | Current billing-cycle egress, storage and request count. |
| POST | /v1/namespaces/{ns}/purge | Invalidate one object, a path prefix or the whole namespace. |
| POST | /v1/namespaces/{ns}/artifacts | Upload an artifact (raw body or multipart) into a namespace. |
| GET | /v1/namespaces/{ns}/artifacts | List artifacts with sizes, checksums and last-modified timestamps. |
| GET | /v1/tokens | List tokens, their scopes and last-used time. |
| POST | /v1/tokens | Create a scoped, optionally expiring token. |
| DELETE | /v1/tokens/{id} | Revoke a token immediately. |
| GET | /v1/nodes | Public node status: location, uptime, throughput, sync age. |
Examples
# 1. Check the current billing-cycle usage
curl -sS -H "Authorization: Bearer $MH_TOKEN" \
https://api.mirrorhub.space/v1/namespaces/acme/usage
# 200 OK
# {
# "namespace": "acme",
# "period": "2026-10",
# "egress_bytes": 4219387904,
# "egress_limit_bytes": 21990232555520,
# "storage_bytes": 731208654848,
# "requests": 18422910
# }
# 2. Publish a build artifact
curl -sS -X POST \
-H "Authorization: Bearer $MH_TOKEN" \
-H "Content-Type: application/octet-stream" \
--data-binary @dist/app-2026.10.18.tar.gz \
"https://api.mirrorhub.space/v1/namespaces/acme/artifacts?path=releases/app-2026.10.18.tar.gz"
# 201 Created
# { "path": "releases/app-2026.10.18.tar.gz",
# "size": 48211304,
# "sha256": "3f1c…a907",
# "url": "https://de.mirrorhub.space/acme/releases/app-2026.10.18.tar.gz" }
# 3. Purge a stale prefix after a rebuild
curl -sS -X POST \
-H "Authorization: Bearer $MH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"prefix":"releases/latest/"}' \
https://api.mirrorhub.space/v1/namespaces/acme/purge
# 202 Accepted
# { "purged": 412, "nodes": ["de-fra-1","nl-ams-1","pl-waw-1","se-sto-1"] }
# 4. Create a short-lived token for a release pipeline
curl -sS -X POST \
-H "Authorization: Bearer $MH_TOKEN" \
-H "Content-Type: application/json" \
-d '{"name":"release-2026.10","scopes":["read"],"expires_in":86400}' \
https://api.mirrorhub.space/v1/tokens
Rate limits
Limits are applied per token and per namespace, and are returned in the response headers X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Bulk object downloads from the serving layer are not subject to API limits.
| Plan | API requests | Concurrent uploads | Purge requests |
|---|---|---|---|
| Free | 300 / min | 2 | 5 / hour |
| Team | 5,000 / min | 16 | unlimited |
| Business | from 50,000 / min | by agreement | unlimited |
Errors
Errors use standard HTTP status codes and a JSON body with a machine-readable code:
# 403 Forbidden
# { "error": "token_scope_denied",
# "message": "Token has scope 'read' but this endpoint requires 'write'." }
# 429 Too Many Requests
# { "error": "rate_limit_exceeded",
# "message": "Namespace limit reached. Retry after 2026-10-18T14:43:00Z.",
# "retry_after": 41 }
Webhooks
Teams on the Team and Business plans can register an HTTPS webhook to receive mirror.sync.stale, namespace.limit.warning and incident.opened events. Webhook payloads are signed with an HMAC-SHA256 header, X-MirrorHub-Signature, computed over the raw request body.