CacheHaul

API reference

Everything the console does is an API call. Zones, cache rules and purges share one set of endpoints, so the same workflow fits into a deploy pipeline.

Base URL

All endpoints live under one host and are versioned in the path. Only HTTPS is served; a plain HTTP request is redirected.

https://app.cachehaul.com/api/v1

Request and response bodies are JSON. Send Content-Type: application/json on any request that carries a body.

Authentication

Requests carry a bearer token. Tokens are created in the console under Settings → API tokens and are scoped to one or more zones, so a build pipeline holds only the rights it needs.

curl https://app.cachehaul.com/api/v1/zones \
  -H "Authorization: Bearer $CACHEHAUL_TOKEN"

A token is shown once at creation and stored as a hash afterwards. A lost token is replaced, not recovered. Revoking a token takes effect on the next request.

Zones

A zone binds a hostname to an origin and holds its cache configuration. The zone id appears in every nested path.

GET/zones

POST/zones

GET/zones/{zone}

PATCH/zones/{zone}

Create a zone

curl -X POST https://app.cachehaul.com/api/v1/zones \
  -H "Authorization: Bearer $CACHEHAUL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "hostname": "www.example.com",
        "origin": "origin.example.com",
        "shield": true
      }'

Response

{
  "zone": "z8f31ca",
  "hostname": "www.example.com",
  "origin": "origin.example.com",
  "shield": true,
  "state": "awaiting_dns",
  "verify": {
    "type": "CNAME",
    "name": "www.example.com",
    "value": "z8f31ca.edge.cachehaul.com"
  }
}

A zone stays in awaiting_dns until the record above resolves. Once it does, the state moves to active and a certificate is issued for the hostname. No traffic is served while the zone is awaiting DNS.

Cache rules

Rules decide what is cached and for how long. They are evaluated in order; the first match wins, and a request matching nothing falls back to the origin's own cache headers.

GET/zones/{zone}/rules

PUT/zones/{zone}/rules

PUT replaces the whole ordered list, which keeps the rule set reproducible from version control.

curl -X PUT https://app.cachehaul.com/api/v1/zones/z8f31ca/rules \
  -H "Authorization: Bearer $CACHEHAUL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
        "rules": [
          { "match": "/assets/*", "ttl": 31536000, "ignore_query": true },
          { "match": "/api/*",    "cache": false },
          { "match": "/*",        "ttl": 300, "vary": ["Accept-Encoding"] }
        ]
      }'
Rule fields
FieldTypeMeaning
match string Path pattern. A trailing * matches a prefix.
ttl integer Seconds an entry stays fresh at the edge.
cache boolean false passes the request through untouched.
ignore_query boolean Drop the query string from the cache key.
vary array Request headers added to the cache key.

Purges

A purge drops entries from the edge without waiting for their TTL. The call returns as soon as the purge is accepted; propagation across nodes continues in the background.

POST/zones/{zone}/purge

GET/zones/{zone}/purge/{purge}

Purge the paths a release replaced

curl -X POST https://app.cachehaul.com/api/v1/zones/z8f31ca/purge \
  -H "Authorization: Bearer $CACHEHAUL_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"paths": ["/static/app.css", "/img/*"]}'

Response

{
  "purge": "pg41d9b0",
  "state": "propagating",
  "paths": 2
}

Poll the purge id to follow it; the state becomes done when every node has dropped the entries. Passing {"everything": true} clears the whole zone, which refills the cache from the origin and is worth avoiding on a busy site.

Response headers

Cached responses carry two headers that are useful when checking a rule change by hand.

HeaderValues
Ch-Cache HIT, MISS, STALE, BYPASS
Ch-Age Seconds the entry has been held at the edge.
curl -sI https://www.example.com/assets/app.css | grep -i '^ch-'

Errors

Failures use the matching status code and a body with a stable error.code slug, safe to branch on, plus a human-readable message that may be reworded.

{
  "error": {
    "code": "zone_not_found",
    "message": "No zone with id z0000000."
  }
}
StatusWhen
400Malformed body or an unknown field.
401Missing, expired or revoked token. Returned for any call outside the open endpoints until a workspace token is issued.
403Token not scoped to the zone in the path.
404No such zone, rule set or purge.
409Hostname already claimed by another zone.
429Rate limit reached; see below.

Rate limits

Limits are per token. A limited response carries Retry-After in seconds, and a client that honours it needs no backoff of its own. Purges are counted separately from reads, so polling a purge never costs the budget for issuing the next one.

An endpoint missing here, or a limit that does not fit a pipeline? support@cachehaul.com