REST Reference
Six endpoints under /v1/*. Every endpoint accepts the same auth modes (Bearer key or x402 micropayment), gates on the same per-key tier table, and returns either a strict MindResponse shape or the error envelope.
Base URL: https://api.cloven.cloud
All endpoints are GET (the cite endpoint accepts both GET and POST). All responses are application/json except /v1/subscribe, which is text/event-stream.
GET /v1/fresh
Latest compacted Mind State + brief + citations + freshness.
Query params.
| Param | Required | Notes |
|---|---|---|
pack | yes | Pack id — crypto (live), ai / markets (Phase 1.5). Defaults to crypto if omitted. |
query | no | Free-text refinement for the upstream brief (Phase 1.5 narrows state to matching slice). |
Response (200).
{
"state": { "...": "pack-specific schema" },
"brief": "Bitcoin holding above 95k [1]. ETH funding rates flipped negative...",
"citations": [
{
"ref": 1,
"sourceId": "coingecko",
"url": "https://www.coingecko.com",
"fetchedAt": "2026-05-24T11:58:46Z"
}
],
"freshness": {
"generatedAt": "2026-05-24T11:58:46Z",
"ageSeconds": 134
}
}Errors. 401 invalid_token, 402 payment_required, 403 pack_access_denied, 404 pack_not_found, 429 quota_exhausted, 503 state_unavailable (first-pulse race).
GET /v1/brief
Brief-only. Identical contract to /v1/fresh minus the state field. Cheaper when the caller already has a state cache.
Query params. pack (required).
Response (200).
{
"brief": "Bitcoin holding above 95k [1]...",
"citations": [ ... ],
"freshness": { "generatedAt": "...", "ageSeconds": 134 }
}GET /v1/search
Top-k case-insensitive walk over the cached state JSON tree. Word-boundary matches score 1.0; substring matches score 0.5. Returns paths into the state with their values.
Query params.
| Param | Required | Notes |
|---|---|---|
pack | yes | Pack id. |
q | yes | Search query (non-empty). |
k | no | Max results, 1–50. Default 10. |
Response (200).
{
"matches": [
{ "path": "top_movers[3].symbol", "value": "ETH", "score": 1 },
{ "path": "narratives[1].evidence[0]", "value": "ETH funding flipped...", "score": 0.5 }
],
"total": 12,
"freshness": { "generatedAt": "...", "ageSeconds": 134 }
}GET /v1/snapshot
Time-travel — historical Mind State at the requested timestamp.
Query params.
| Param | Required | Notes |
|---|---|---|
pack | yes | Pack id. |
at | yes | ISO8601 timestamp. Truncated to minute precision. |
Response (200). Same shape as /v1/fresh, with freshness.generatedAt pinned to the historical pulse. brief is empty for snapshots — use /v1/brief for current prose. Pro+ tiers can read 30 days back; Team+ tiers 365 days.
Errors. 404 snapshot_not_found (the requested minute is outside the hot window or before the pack existed), 400 invalid_at.
GET /v1/subscribe
SSE pulse stream. Headers cannot be set on the browser EventSource API, so the API key is passed as the token query param. x402 is not supported on SSE — there is no per-call payment model for a long-lived stream.
Query params.
| Param | Required | Notes |
|---|---|---|
pack | yes | Pack id. |
token | yes | API key (same value you'd pass as Authorization: Bearer …). |
Response. text/event-stream with three event types:
event: pulse
data: { "pack": "crypto", "state": {...}, "ts": "2026-05-24T11:58:46Z" }
event: delta
data: { "pack": "crypto", "state": {...}, "ts": "2026-05-24T12:03:46Z" }
: keepalive 1716552134000pulse fires every 15s with the latest cached state. delta fires when the cached generatedAt advances (a fresh compaction landed). : keepalive is a comment frame that stops proxies from closing idle connections. The stream stays open until the client disconnects or the auth key is revoked.
Details: SSE subscribe.
GET /v1/cite
Resolve a [N] citation anchor (1-indexed) to its underlying source. The anchor index matches the order of pack.sources — stable across the lifetime of the pack version.
Query params.
| Param | Required | Notes |
|---|---|---|
pack | yes | Pack id. |
ref | yes | Positive integer in the range 1..N where N = pack.sources.length. |
Response (200).
{
"citation": {
"ref": 1,
"sourceId": "coingecko",
"url": "https://www.coingecko.com",
"fetchedAt": "2026-05-24T11:58:46Z"
},
"source": {
"id": "coingecko",
"name": "CoinGecko",
"publicUrl": "https://www.coingecko.com"
},
"freshness": { "generatedAt": "...", "ageSeconds": 134 }
}Errors. 404 citation_not_found (ref out of range), 400 invalid_ref.
Common headers
| Header | Where | Meaning |
|---|---|---|
Authorization: Bearer cv_… | request | API key auth (credit-balance path). |
x-payment: <base64 proof> | request | x402 payment proof. |
X-402-Payer-Hint: 0x… | request | Optional — request a discounted quote. |
X-Mind-Freshness: 2m14s | response | Same value as freshness.ageSeconds, human-formatted. |
X-402-Settled: 0xabc… | response | Tx hash that paid for this request (x402 mode). |
Retry-After: <seconds> | response | Set on 429 — seconds until quota window rolls. |
TypeScript types
The same MindResponse and Citation interfaces used inside the codebase ship as part of @cloven/sdk — see the SDK reference for import paths. Pack-specific state shapes live under @cloven/sdk/packs/<id>.