Skip to content

Cache and response headers

The edge cache answers GET and HEAD requests at the edge: a hit never reaches the WAF or your origin, and only responses that passed the WAF are stored. Response headers and CORS are set at the edge as well. Its place in the request path: pipeline. Requests need API access.

Endpoints

Method Path Key Purpose
GET /services/{fqdn}/cache/purge read Recent purges
POST /services/{fqdn}/cache/purge write Purge the cache
GET /services/{fqdn}/cache/stats read Cache hit ratio and volume

GET /services/{fqdn}/cache/purge

Returns: 200, Purges

Answer 200
{
  "generation": 1,
  "all": [
    {
      "generation": 1,
      "at": "2026-10-23T10:13:25.538807+00:00",
      "by": "API key ci"
    }
  ],
  "urls": [
    {
      "id": "58dc70c951364ae1b5577905bb6980af",
      "host": "a.example.com",
      "url": "/img/logo.png?v=2",
      "at": "2026-10-23T10:13:25.418554+00:00",
      "by": "API key ci"
    }
  ],
  "prefixes": []
}

POST /services/{fqdn}/cache/purge

Body: CachePurge
Returns: 202, PurgeResult

Request: url
{
  "url": "/img/logo.png?v=2"
}
Request: prefix
{
  "prefix": "/img/"
}
Request: all
{
  "all": true
}
Answer 202: url
{
  "type": "url",
  "id": "58dc70c951364ae1b5577905bb6980af",
  "host": "a.example.com",
  "url": "/img/logo.png?v=2",
  "at": "2026-10-23T10:13:25.418554+00:00",
  "by": "key:TGloIsNcCavQ"
}
Answer 202: prefix
{
  "type": "prefix",
  "id": "9e37874cfe68",
  "prefix": "/img/",
  "at": "2026-10-23T10:13:25.468399+00:00",
  "by": "key:TGloIsNcCavQ"
}
Answer 202: all
{
  "type": "all",
  "generation": 1,
  "at": "2026-10-23T10:13:25.538807+00:00",
  "by": "key:TGloIsNcCavQ"
}

GET /services/{fqdn}/cache/stats

Parameter In Meaning
range query Time window; one of 1h, 6h, 24h; default "24h"

Returns: 200, CacheStats

Answer 200
{
  "range": "24h",
  "requests": {
    "HIT": 7
  },
  "bytes": {
    "HIT": 7
  },
  "hit_ratio": 1.0,
  "byte_share": 1.0,
  "token_denied": null
}

Fields

Part of the service: send them with PATCH /services/{fqdn}.

Field Type Notes
cache CachePatch may be null; Edge cache
response_headers ResponseHeadersPatch may be null; Response headers set at the edge
content_negotiation ContentNegotiationPatch may be null; Pre-compressed static files

Cache

Field Type Notes
enabled boolean default true; Edge cache for GET and HEAD requests. Off: every request goes to your origin
engine string one of haproxy, ats; read-only; Cache engine at the edge. Set by support on request; ignored when you send it
stale_if_error integer 0–86400; Seconds an expired object may still be served while your origin fails, 0 to 86400. Default 86400; 0: never
stale_while_revalidate integer 0–300; Seconds an expired object is still served while the edge fetches a fresh copy, 0 to 300. Default 30; 0: off
min_hits integer 2–10; may be null; Store an object only from its Nth request on, 2 to 10, to keep one-off requests out. Null: from the first request
purge_all_interval integer 60–86400; may be null; read-only; Set by support on request; ignored when you send it
negative_ttl integer 1–3600; may be null; Seconds a 404 or 410 from your origin is served from the cache, 1 to 3600. Null: never
large_files boolean may be null; Cache video, audio, archives, installers, disk images and PDFs (by file extension) in 4 MB blocks; your origin must answer Range requests
key CacheKey What the cache key holds besides hostname, path and scheme
rules list of CacheRule at most 25; Up to 25 rules on the request path, the first match wins; a path no rule matches follows your origin's headers
token_gate CacheTokenGate read-only; Set by support on request; ignored when you send it

CacheKey

Field Type Notes
params string one of all, include, none; all (the default): every query parameter except ignore_params. include: only include_params. none: no parameter, so ?x=1 is no cache miss
ignore_params list of string at most 20; Query parameters left out of the key, such as per-viewer tokens; a name ending in * matches a prefix (utm_*). Up to 20
include_params list of string at most 20; With params include: the only query parameters in the key; a name ending in * matches a prefix. Up to 20
sort_params boolean Sort the query parameters first, so ?a=1&b=2 and ?b=2&a=1 are one object

CacheRule

Field Type Notes
path (required) string Glob on the request path, starting with / or *; * matches any characters, / included
action (required) string one of cache, bypass; cache: cache matching responses, for ttl when set. bypass: matching requests go to your origin without the cache
ttl integer 1–31536000; may be null; Seconds the edge keeps a matching response, 1 to 31536000, whatever max-age or Expires your origin sends, also when it sends none. Null: your origin decides. cache rules only
cookie string may be null; bypass rules only: apply only when the request carries this cookie; a name ending in * matches a prefix (wordpress_logged_in_*)
header string may be null; bypass rules only: apply only when the request carries this header
browser_ttl integer 0–31536000; may be null; Cache-Control max-age in seconds sent to browsers on matching 200 responses, 0 to 31536000; never on private, no-store or Set-Cookie responses. cache rules only

CacheTokenGate

Field Type Notes
enabled boolean default false; Only requests with a token your origin confirmed get cached objects; all others go to your origin uncached
params list of string at most 5; Query parameters carrying the viewer token, up to 5; their URL-decoded values together are the token
ttl integer 10–86400; default 60; Seconds a token stays confirmed after your origin last answered it with 2xx, 10 to 86400; a 401 or 403 from your origin ends it at once
unknown_per_10s integer 1–100000; default 500; GET and HEAD requests per 10 s a source may send without a confirmed token; above it the edge answers 429
outage_grace integer 0–86400; default 1800; Seconds a confirmation outlives ttl while every origin fails its health check, 0 to 86400. Default 1800

CachePurge

Field Type Notes
url string Path and query string of one object, starting with /
host string Alias the URL belongs to; default the vService
prefix string Purge every object whose path starts with this, any query string, on the vService and its aliases. Starts with /, not / alone
all boolean true: purge every cached object of the vService and its aliases

ResponseHeaders

Field Type Notes
hsts Hsts Strict-Transport-Security
cors Cors CORS
x_frame_options string one of DENY, SAMEORIGIN; may be null; X-Frame-Options on the responses the edge passes on, replacing your origin's; null: the edge sets none
x_content_type_options boolean default false; Set X-Content-Type-Options: nosniff on the responses the edge passes on
referrer_policy string one of no-referrer, no-referrer-when-downgrade, origin, origin-when-cross-origin, same-origin, strict-origin, strict-origin-when-cross-origin, unsafe-url; may be null; Referrer-Policy on the responses the edge passes on, replacing your origin's; null: the edge sets none

Cors

Field Type Notes
enabled boolean default false; Answer CORS at the edge with the rules
rules list of CorsRule at most 10; Up to 10 rules; the first whose origin and method match applies. The edge answers its preflight with 204; a request no rule matches passes to your origin unchanged, and CORS headers your origin sets win

CorsRule

Field Type Notes
allowed_origins (required) list of string at most 20; Origins the rule covers, case-insensitive: * for any, or http(s)://host[:port], where * in the host stands for any letters, digits, dots and dashes. The edge echoes the request's Origin, or answers * when the list holds *
allowed_methods (required) list of string at most 5; Methods the rule covers, also its Access-Control-Allow-Methods
allowed_headers list of string at most 20; Access-Control-Allow-Headers of the preflight answer; * repeats the headers the browser asked for
expose_headers list of string at most 20; Access-Control-Expose-Headers on responses
max_age_seconds integer 0–86400; default 3600; Access-Control-Max-Age of the preflight answer in seconds, 0 to 86400; 0 leaves it out

ContentNegotiation

Field Type Notes
enabled boolean default false; For the listed file types, request the compressed copy the client accepts (app.css.zst, app.css.gz, app.css.br) and set Content-Encoding. Your origin must hold every copy: the edge does not fall back to the original
encodings list of string at most 3; Encodings in order of preference: zstd (.zst), gzip (.gz), br (.br); the first the client's Accept-Encoding names wins
file_types list of string at most 8; File extensions served pre-compressed

Example

Purge everything under /img/:

curl -s -X POST -H "Authorization: Bearer $ZP_KEY" -H 'Content-Type: application/json' \
  $API/services/www.example.com/cache/purge -d '{"prefix": "/img/"}'

Behaviour

  • Lifetime follows your origin: Cache-Control: max-age/s-maxage or Expires; only Last-Modified keeps an object one hour; private or no-store is never cached.
  • X-ZP-Cache on the response: HIT, EXPIRED (revalidated, or served stale), MISS, BYPASS. Requests a bypass rule matches, and other methods, go to the origin without it.
  • Key: host, path and scheme always. params: all (default) minus ignore_params, include only include_params, or none. A name ending in * matches a prefix (utm_*); sort_params makes ?a=1&b=2 and ?b=2&a=1 one object. Your origin always gets the full query string.
  • rules match the path as a glob (* includes /), top to bottom, first match wins; no match follows the origin's headers. cache: ttl at the edge, browser_ttl as Cache-Control: max-age on 200 responses that are not private, no-store or setting a cookie. bypass: optionally only with a cookie (name or prefix*, e.g. wordpress_logged_in_*) or header.
  • Defaults: stale_if_error one day, stale_while_revalidate 30 s, negative_ttl (404/410) off, min_hits off (stores on the first request). large_files caches video, audio, archives, installers, disk images and PDFs in 4 MB blocks; your origin must answer Range requests, and X-ZP-Cache shows the first block.
  • token_gate (streaming with viewer tokens in the URL) and purge_all_interval are set by support. With a token gate, segments go only to viewers whose token your origin accepted recently; too many unconfirmed tokens from one source get 429 (token-unknown in the log).
  • Purge one url (with host for an alias), a prefix or all; every edge applies it within a minute. Per service: URLs 30 per minute, prefixes 50 until the next full purge, everything once every 5 minutes unless support set another interval. GET …/cache/purge lists recent purges and who triggered them.
  • cache/stats: hit ratio among lookups (hit, revalidated, miss, bypass), share of bytes from the cache and token-gate rejections, for 1h, 6h or 24h.
  • content_negotiation rewrites app.css to app.css.zst (zstd) or .gz (gzip) and adds Vary: Accept-Encoding; default types css, js, html, json, svg, xml. Your deploy places the variants next to the originals; a missing one returns 404.
  • CORS: the first rule whose origin (exact, https://*.example.com or *) and method match applies; the origin is echoed (with Vary: Origin) or *. Preflights get 204 at the edge, before proof-of-work and the WAF. No match: unchanged to your origin. CORS headers your origin sets win.

In the portal: Caching tab; purge on Advanced, statistics on Metrics.