API access¶
Everything you configure in ZERO-PROTECT is a field or an endpoint of this API; the pages in this section follow it resource by resource. The portal uses the same settings.
| Base URL | https://api.zeroservices.eu/v1/protect |
| Authentication | Authorization: Bearer zsk_… |
| OpenAPI document | openapi.json, current version at https://api.zeroservices.eu/v1/protect/openapi.json |
export API=https://api.zeroservices.eu/v1/protect
export ZP_KEY='zsk_…'
curl -s -H "Authorization: Bearer $ZP_KEY" $API/keys/me
Keys¶
Create keys in the portal under ZERO-PROTECT → API keys. API access is switched on per account; ask support if the page says it is not enabled.
| Field | Content |
|---|---|
| Access | Read only (GET) or Read and write |
| Addresses | 1 to 16 single public IPv4 or IPv6 addresses, no ranges |
| Expires | at most 365 days ahead |
- The key is shown once. A request from an address the key is not bound to gets
401; a dual-stack host needs both addresses bound, or one family forced (curl -4). - Single addresses, a year at most and the portal as the only place to create a key are deliberate: a stolen key is useless from anywhere else, and no key can create its successor. Serverless functions and CI runners without a fixed address cannot use the API.
- The primary account creates keys for the whole account. Members of a delegation create keys that see only the delegated services and follow the delegation. Team members with full access cannot create keys.
- At most 50 active keys per account. Revoking takes effect with the next request.
- Team, delegations and keys are managed in the portal only.
Limits¶
| Limit | Value |
|---|---|
| Requests per key | 4 per second, bursts up to 60 |
| Concurrent requests per key | 4 |
| Logs, charts, history, the service list, service health and IP pools | 0.5 per second per key, bursts up to 10 |
| Of those, in flight at once across all keys | 4 |
| Requests per client address (IPv6: per /64), before the key is checked | 20 per second, bursts up to 120 |
| Request body | 10 MB |
Every answer reports the bucket the request was charged to: X-RateLimit-Limit (its size),
X-RateLimit-Remaining and X-RateLimit-Reset (seconds until it is full again). Heavy reads
report their own, smaller bucket.
429 means your key is over its limit; 503 means the platform is busy, not your key. Both
carry Retry-After in seconds.
Errors¶
Every error is JSON with a message for people and a stable code for programs:
{"error": "…", "code": "…"}. Validation errors add details with the failing field.
Branch on code, not on the message; a code you do not know yet is handled by its status.
| Status | code |
Meaning |
|---|---|---|
400 |
bad_request |
malformed request |
401 |
invalid_key |
key missing, malformed, unknown, expired or revoked; address not bound; API access not enabled. One answer for all of these on purpose |
403 |
insufficient_scope, not_available_with_key |
read-only key on a write; a portal-only endpoint |
404 |
not_found |
unknown path, or not one of your services |
405 |
method_not_allowed |
the path does not offer this method |
409 |
service_exists, origin_exists, acme_in_progress, idempotency_key_reused |
conflicts with the current state |
409 |
cache_disabled, purge_all_interval, url_purge_rate, prefix_purge_limit |
cache purge refused; purge_all_interval has details.retry_after_seconds |
413 |
too_large |
upload too large |
422 |
validation_failed |
see details |
429 |
rate_limited, too_many_concurrent |
your key's limit; retry after Retry-After |
503 |
busy, unavailable |
the platform is busy; retry after Retry-After |
If the API itself cannot be reached, the edge answers instead, with
{"error", "status", "ray"}; quote the ray to support.
Idempotency¶
Send an Idempotency-Key header with VIP operations and when you
add an origin: repeating the same request returns the first result with 200
instead of applying it twice. A replayed origin carries Idempotent-Replayed: true. The
same key with a different body is 409 (idempotency_key_reused). Keys of origins hold
for 24 hours.
Times and versions¶
- Times are RFC 3339 (
2026-10-23T05:12:01+00:00); raw log lines have nanoseconds. Only the points of a chart are[unix seconds, value]. /v1stays compatible: new fields, endpoints and error codes may be added, so ignore fields you do not know. A breaking change comes as a new version.