Skip to content

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].
  • /v1 stays 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.