{"openapi":"3.1.0","info":{"title":"DAMO Market State API","version":"1.4.1","summary":"Recorded market state: 4 permanent states across 10 fixed timeframes, never recomputed.","description":"A fixed, versioned definition of market state: recorded at the time, never recomputed, verifiable by anyone. DAMO describes the state of a market across 10 fixed timeframes (1m 5m 15m 1h 4h 12h 1d 3d 1w 1M) using exactly 4 permanent state codes. Two layers: verified (closed candles, recorded once, never changed) and live (forming candles, provisional). VERIFIED states are written once into an append-only hash chain; each UTC day gets an attestation anchored on Base mainnet (contract 0x67FeC2A19B3e3eb26d80Ad87D19e33dfc39F5766). Each VERIFIED value carries its seq and hash, so an answer that cites it can be checked later against the anchored daily attestation. What does not change: the 4 state codes and 10 timeframes are permanent; any engine change is released as a new engine version (engine_version is in every VERIFIED value); recorded states are never recomputed. Not provided: prices or candles, order book, funding rates, intrabar events, forecasts or trading signals, bulk historical exports (the full recorded history is not offered as a download). Free tier: 500 state values per client per UTC day (1 state value = 1 symbol x 1 timeframe); each state response includes 'quota'. Optional timeframes selection (e.g. timeframes=15m,1h): only those are returned and counted; the vector keeps its 10 positions, others are null with status not_requested. Case-sensitive: 1m = minute, 1M = month. Time fields: verified as_of is when DAMO last wrote the record (UTC), not a candle time; each timeframe's candle close is states[tf].candle_close. live observed_at is when DAMO observed the forming candles; states[tf].candle_close_expected is when that candle will close. There is no generated_at. HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes. Optional format=compact returns only symbol, layer, time, the 10-value vector, a short citation line and the remaining quota, plus stale: true when the data is old (no per-timeframe seq, hash or engine version; batch: one citation line for all results). It is counted the same way (state values). Default format=full is for citing and checking records. Every state response is signed with Ed25519 by DAMO. HTTP: header DAMO-Signature (kid, alg, sig). MCP: tool result _meta \"com.damolive/signature\". The signature covers the fields symbol, layer, as_of, observed_at, vector_order, vector, states, engine_version and chain_head that are present in each state object (batch: {\"results\": [...]} of those objects), serialized with RFC 8785 (JCS). quota, citation and other fields are not signed. Add proof=1 to also get it in the body as 'proof'. Public keys: https://api.damolive.com/.well-known/damo-keys.json Market states are computed from the DAMO composite, built from several public crypto perpetual futures markets. DAMO publishes its own state outputs only, not raw prices or candles. VERIFIED records with engine_version 1.0 (before 2026-10-26 00:00 UTC) were computed from a single reference market; engine 1.1 and later use the DAMO composite (same calculation, new input). Use of the API and MCP server is subject to the DAMO API terms: https://damolive.com/api-terms (among others: no reverse engineering of the state engine, no use of outputs to train or calibrate a model or service that reproduces DAMO states, no systematic collection beyond your own application's needs). Privacy: https://damolive.com/privacy","termsOfService":"https://damolive.com/api-terms","contact":{"url":"https://damolive.com","email":"damoliveinfo@gmail.com"}},"servers":[{"url":"https://api.damolive.com"}],"paths":{"/v1/symbols":{"get":{"operationId":"listSymbols","summary":"Symbols covered by DAMO","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"}}}},"/v1/market-state/{symbol}":{"get":{"operationId":"getMarketState","summary":"Market state of one symbol across 10 timeframes","description":"Current DAMO state of one symbol for each of the 10 timeframes: state name, permanent state code, and a 10-value vector in fixed timeframe order. Includes 'citation' (layer, symbol, time) and 'source_url'.","parameters":[{"name":"symbol","in":"path","required":true,"schema":{"type":"string","example":"BTCUSDT"}},{"name":"layer","in":"query","required":false,"schema":{"type":"string","enum":["verified","live"],"default":"verified"},"description":"verified = closed candles, recorded and never changed. live = forming candles, provisional."},{"name":"timeframes","in":"query","required":false,"schema":{"type":"string","example":"15m,1h"},"description":"Optional timeframes selection (e.g. timeframes=15m,1h): only those are returned and counted; the vector keeps its 10 positions, others are null with status not_requested. Case-sensitive: 1m = minute, 1M = month."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["full","compact"],"default":"full"},"description":"Optional format=compact returns only symbol, layer, time, the 10-value vector, a short citation line and the remaining quota, plus stale: true when the data is old (no per-timeframe seq, hash or engine version; batch: one citation line for all results). It is counted the same way (state values). Default format=full is for citing and checking records."},{"name":"proof","in":"query","required":false,"schema":{"type":"integer","enum":[0,1],"default":0},"description":"1 = also put DAMO's Ed25519 signature in the body as 'proof' (it is always in the DAMO-Signature header)."},{"name":"if_none_match","in":"query","required":false,"schema":{"type":"string"},"description":"The ETag of your last response (quotes optional). HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"DAMO-Signature":{"description":"Every state response is signed with Ed25519 by DAMO. HTTP: header DAMO-Signature (kid, alg, sig). MCP: tool result _meta \"com.damolive/signature\". The signature covers the fields symbol, layer, as_of, observed_at, vector_order, vector, states, engine_version and chain_head that are present in each state object (batch: {\"results\": [...]} of those objects), serialized with RFC 8785 (JCS). quota, citation and other fields are not signed. Add proof=1 to also get it in the body as 'proof'. Public keys: https://api.damolive.com/.well-known/damo-keys.json","schema":{"type":"string"}},"ETag":{"description":"HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes.","schema":{"type":"string"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"},"304":{"description":"Not modified (If-None-Match matched). No body, not counted."},"400":{"description":"Bad request, e.g. bad_timeframes"}}}},"/v1/market-state":{"get":{"operationId":"getMarketStates","summary":"Market state of several symbols (max 50)","parameters":[{"name":"symbols","in":"query","required":true,"schema":{"type":"string","example":"BTCUSDT,ETHUSDT"}},{"name":"layer","in":"query","required":false,"schema":{"type":"string","enum":["verified","live"],"default":"verified"},"description":"verified = closed candles, recorded and never changed. live = forming candles, provisional."},{"name":"timeframes","in":"query","required":false,"schema":{"type":"string","example":"15m,1h"},"description":"Optional timeframes selection (e.g. timeframes=15m,1h): only those are returned and counted; the vector keeps its 10 positions, others are null with status not_requested. Case-sensitive: 1m = minute, 1M = month."},{"name":"format","in":"query","required":false,"schema":{"type":"string","enum":["full","compact"],"default":"full"},"description":"Optional format=compact returns only symbol, layer, time, the 10-value vector, a short citation line and the remaining quota, plus stale: true when the data is old (no per-timeframe seq, hash or engine version; batch: one citation line for all results). It is counted the same way (state values). Default format=full is for citing and checking records."},{"name":"proof","in":"query","required":false,"schema":{"type":"integer","enum":[0,1],"default":0},"description":"1 = also put DAMO's Ed25519 signature in the body as 'proof' (it is always in the DAMO-Signature header)."},{"name":"if_none_match","in":"query","required":false,"schema":{"type":"string"},"description":"The ETag of your last response (quotes optional). HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes."},{"name":"If-None-Match","in":"header","required":false,"schema":{"type":"string"},"description":"HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes."}],"responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}},"headers":{"DAMO-Signature":{"description":"Every state response is signed with Ed25519 by DAMO. HTTP: header DAMO-Signature (kid, alg, sig). MCP: tool result _meta \"com.damolive/signature\". The signature covers the fields symbol, layer, as_of, observed_at, vector_order, vector, states, engine_version and chain_head that are present in each state object (batch: {\"results\": [...]} of those objects), serialized with RFC 8785 (JCS). quota, citation and other fields are not signed. Add proof=1 to also get it in the body as 'proof'. Public keys: https://api.damolive.com/.well-known/damo-keys.json","schema":{"type":"string"}},"ETag":{"description":"HTTP state responses carry an ETag. Send it back as the query parameter if_none_match=<ETag> (the If-None-Match header is also accepted where your connection passes it through): if nothing changed the API answers 304 Not Modified with no body, and it is not counted against the quota (the request rate limit still applies). VERIFIED states change only when a candle closes.","schema":{"type":"string"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"},"304":{"description":"Not modified (If-None-Match matched). No body, not counted."},"400":{"description":"Bad request, e.g. bad_timeframes"}}}},"/v1/states":{"get":{"operationId":"getStateDefinitions","summary":"State definitions","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"}}}},"/v1/health":{"get":{"operationId":"getHealth","summary":"Service health","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"}}}},"/.well-known/damo-keys.json":{"get":{"operationId":"getSigningKeys","summary":"DAMO public keys for response signatures (Ed25519)","responses":{"200":{"description":"OK","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Unknown symbol"},"429":{"description":"Rate limited, or free daily quota reached (error daily_quota_exceeded)"},"503":{"description":"Data temporarily unavailable"}}}}}}