API reference
Base URL https://cache.rucdn.pro/v1. JSON in, JSON out, except the raw object
body. Bearer token in Authorization. Everything is idempotent on
Idempotency-Key except the raw PUT.
Objects
| Method | Path | Purpose |
|---|---|---|
| PUT | /v1/objects/{key} | Store or replace an object |
| GET | /v1/objects/{key} | Fetch metadata, not the bytes |
| GET | /o/{key} | Fetch the cached bytes, byte-range aware |
| DELETE | /v1/objects/{key} | Purge immediately |
| POST | /v1/warm | Pull a key from origin ahead of first request |
States
fresh → stale → revalidating → fresh, or
evicted with a reason string. There is no intermediate percentage; ask
for ?expand=origin if you want the last upstream response code.
Example
GET /v1/objects/obj_e371bd33?expand=origin
{
"key": "obj_e371bd33",
"state": "fresh",
"size_bytes": 145409,
"etag": "\"obj_69a44ae4\"",
"ttl_seconds": 3600,
"origin": {"status": 200, "cache_control": "max-age=3600"}
}
Warm ahead of traffic
POST /v1/warm
{"key":"obj_69a44ae4","origin_url":"https://example.org/reports/annual.pdf"}
# -> {"key":"obj_69a44ae4","state":"revalidating"}
The warmer follows at most three redirects and refuses anything larger than the configured object ceiling.
Rules
A rule is a named TTL policy in config.toml. Changing a rule does not touch
objects already cached under it — call warm again if you want the new TTL
applied immediately.
[rule.reports]
match = "/reports/*"
ttl_seconds = 3600
stale_while_revalidate = 600
respect_origin_headers = true
Byte ranges
Range requests are served straight from the on-disk copy once an object is fresh; a partial
object is never served as complete. Conditional GET with If-None-Match returns
304 without touching the origin.
Webhooks
| Event | When |
|---|---|
| object.warmed | Object pulled from origin and marked fresh |
| object.evicted | Removed by TTL, LRU pressure or explicit purge |
| origin.error | Origin responded with 5xx or timed out during warm |
Delivery is at-least-once with exponential backoff for six hours. Signature is
X-Signature: sha256=<hex> over the raw body.
Errors
| Code | Meaning |
|---|---|
| 400 invalid_request | Body failed validation, see field |
| 401 unauthenticated | Missing or unknown token |
| 404 not_cached | Key has no entry and no origin_url was given to warm it |
| 413 object_too_large | Above limits.max_object_bytes |
| 502 origin_unreachable | Origin did not respond within the warm timeout |
| 429 slow_down | Per-token bucket empty, honour Retry-After |
Limits
Defaults, all configurable: 512 MB per object, 200 GB total cache floor before LRU eviction kicks in, 600 API requests per minute per token. Byte-range GETs are not counted against the API bucket.