Canonical Format

The v1 pipe-delimited canonical payload specification — the string that gets signed.

Envelope Format

Every attestation follows a two-layer structure: a fixed envelope wrapping type-specific payload fields. Signing and verification operate on the complete canonical string.

envelope structure
VERSION | TYPE | <payload fields...> | TIMESTAMP | NONCE

Envelope Fields

FieldPositionTypeExampleDescription
VERSION0stringv1Format version.
TYPE1stringPRICE, ECON, VOLATILITY, SENTIMENT, STRESS, GAS, GAS_INDEX, WEATHERAttestation type — determines payload structure. COMMODITIES use TYPE=ECON with REGION=COMMODITIES.
TIMESTAMPN-1integer1741514400Unix timestamp (seconds). Always second-to-last.
NONCENinteger4829106-digit random nonce. Always last field.

PRICE Type

PRICE format
v1|PRICE|PAIR|PRICE_VALUE|CURRENCY|DECIMALS|SOURCES|METHOD|TIMESTAMP|NONCE
BTC/USD example
v1|PRICE|BTCUSD|84231.50|USD|2|binance,binance_us,bitfinex,bitstamp,coinbase,gateio,gemini,kraken,okx|median|1741514400|482910
EUR/USD example
v1|PRICE|EURUSD|1.15000|USD|5|bankofcanada,bitstamp,cnb,ecb,ecbdirect,kraken,norgesbank|median|1741514400|719304
Numeric precision rules

PRICE_VALUE is always zero-padded to exactly DECIMALS decimal places (e.g. 84231.50 not 84231.5). Default decimals: JPY pairs = 0, USD/EUR/GBP/CHF/CNY/CAD = 2. Some pairs override this (e.g. EUR/USD uses 5). SOURCES are always lexicographically sorted (ASCII order). Any deviation in precision or ordering will cause signature verification to fail.

ECON Type

ECON format
v1|ECON|REGION|INDICATOR|VALUE|UNIT|PERIOD|VINTAGEDATE|SOURCEAGENCY|SERIESID|SOURCEMODEL|TIMESTAMP|NONCE
US CPI example
v1|ECON|US|CPI|326.785|index198284100|2026-02|2026-03-14|BLS|CUUR0000SA0|directapi|1741514400|830114

COMMODITIES (ECON subtype)

COMMODITIES format
v1|ECON|COMMODITIES|SYMBOL|VALUE|UNIT|PERIOD|VINTAGEDATE|SOURCEAGENCY|SERIESID|directapi|TIMESTAMP|NONCE
WTI crude example
v1|ECON|COMMODITIES|WTI|94.65|usdperbarrel|2026-03-09|2026-03-15|EIA|DCOILWTICO|directapi|1741514400|402341
COMMODITIES vs regional ECON

COMMODITIES shares the ECON TYPE but uses COMMODITIES in the REGION field, followed by SYMBOL (e.g. WTI, BRENT, NATGAS) in the INDICATOR position. The SOURCEMODEL is always directapi. Regional ECON uses a country code (US, EU) in the REGION field and a variable SOURCEMODEL.

VOLATILITY Type (MSVI)

VOLATILITY format
v1|VOLATILITY|PAIR|MSVI|VALUE|UNIT|30D|RV:{rv}:{w},IV:{iv}:{w},TS:{ts}:{w},FR:{fr}:{w},PCR:{pcr}:{w}|CONFIDENCE:{c}|METHOD:v{n}|{TIMESTAMP}|{NONCE}
BTC/USD example
v1|VOLATILITY|BTCUSD|MSVI|15.65|index|30D|RV:38.99:0.3,IV:38.39:0.25,TS:0.909:0.15,FR:20.02:0.2,PCR:0.651:0.1|CONFIDENCE:0.6765|METHOD:v1|1744416000|291847
MSVI differences from MSXI/MSSI

VOLATILITY canonicals include a 30D window field and omit REGIME. The UNIT field uses lowercase index. Component values use the raw value (e.g. RV = realized vol percentage), not the normalizedValue from the preview response.

The components field includes all five weights (RV, IV, TS, FR, PCR) allowing independent reconstruction and verification of the index value.

SENTIMENT Type (MSXI)

SENTIMENT format
v1|SENTIMENT|PAIR|MSXI|VALUE|INDEX|FR:{fr}:{w},SKEW:{skew}:{w},PCR:{pcr}:{w},TS:{ts}:{w},BASIS:{basis}:{w}|REGIME:{regime}|CONFIDENCE:{c}|METHOD:v{n}|{TIMESTAMP}|{NONCE}
BTC/USD example
v1|SENTIMENT|BTCUSD|MSXI|-9.88|INDEX|FR:-0.00:0.3,SKEW:-4.12:0.25,PCR:0.863:0.2,TS:0.923:0.15,BASIS:0.049:0.1|REGIME:NEUTRAL|CONFIDENCE:1.0000|METHOD:v1|1744416000|382910

Positive values indicate bullish positioning, negative values bearish. The components field includes all five weights (FR, SKEW, PCR, TS, BASIS) allowing independent reconstruction.

STRESS Type (MSSI)

STRESS format
v1|STRESS|MARKET|MSSI|VALUE|INDEX|VOL:{vol}:{w},STBL:{stbl}:{w},FR:{fr}:{w}|REGIME:{regime}|CONFIDENCE:{c}|METHOD:v{n}|{TIMESTAMP}|{NONCE}
Market example
v1|STRESS|MARKET|MSSI|64.32|INDEX|VOL:61.81:0.35,STBL:0.00:0.3,FR:38.57:0.35|REGIME:HIGH|CONFIDENCE:1.0000|METHOD:v1|1744416000|571923

Market-wide single number — not per-pair. The components field includes all three weights (VOL, STBL, FR) allowing independent reconstruction and stress source identification.

Index Numeric Precision

Component decimal places

Index values are always formatted to 2 decimal places. Component values use fixed precision per key: FR, SKEW, RV, IV, VOL, STBL use 2dp. PCR, TS use 3dp. BASIS uses 4dp. Weights are unformatted floats. Any deviation in decimal precision will cause signature verification to fail. When a component is unavailable, it is encoded as KEY:NA:weight.

Signing Process

pseudocode
canonical_bytes = canonical_string.encode("utf-8")
signature       = Ed25519_sign(private_key, canonical_bytes)   # RFC 8032, no pre-hash
output          = hex_encode(signature)                         # 64 bytes, 128 hex characters
Standard Ed25519 (RFC 8032)

The signature is standard Ed25519 over the canonical string's UTF-8 bytes, with no pre-hash: Ed25519 already hashes internally (SHA-512) as part of the algorithm, so any standard library verifies it directly. Pass the canonical bytes, the hex-decoded signature and the node's public key. Signatures and public keys are hex-encoded. Every signed data response uses this one scheme, on either payment rail. DLC attestations are separate: they use BIP-340 Schnorr, described in the DLC documentation.

python
from nacl.signing import VerifyKey

# PUBKEY: the published key of the node that signed (see Public Keys)
VerifyKey(bytes.fromhex(PUBKEY)).verify(
    response["canonical"].encode("utf-8"),
    bytes.fromhex(response["signature"]),
)  # raises BadSignatureError if the signature is invalid
Verify against the published key

Two nodes sign, each with its own key, and the pubkey field names which one. Check that it matches a key on the Public Keys page before trusting the signature: a response will always verify against a key it supplies itself. See Signature Verification for JavaScript and Go.

Responses signed before 19 September 2026

Until 19 September 2026 several services signed a SHA-256 or SHA-512 digest of the canonical instead of the canonical itself, with the signature hex- or base64-encoded. Archived responses from before the change verify under the scheme they were signed with; every response since verifies under the standard above.

Parsing

python
fields    = canonical.split("|")
version   = fields[0]    # "v1"
type_id   = fields[1]    # "PRICE" or "ECON"
payload   = fields[2:-2] # type-specific fields
timestamp = fields[-2]   # Unix integer
nonce     = fields[-1]   # 6-digit nonce

# For PRICE type:
if type_id == "PRICE":
    pair    = fields[2]  # "BTCUSD"
    price   = fields[3]  # "84231.50"
    sources = fields[6].split(",")  # ["binance", ...]

# For VOLATILITY (no REGIME, has 30D window):
elif type_id == "VOLATILITY":
    pair       = fields[2]  # "BTCUSD"
    index_name = fields[3]  # "MSVI"
    value      = fields[4]  # index value
    unit       = fields[5]  # "index"
    window     = fields[6]  # "30D"
    components = fields[7]  # "RV:38.99:0.3,IV:38.39:0.25,..."
    confidence = fields[8].split(":")[1]  # "0.6765"

# For SENTIMENT and STRESS (have REGIME, no window):
elif type_id in ("SENTIMENT", "STRESS"):
    pair       = fields[2]  # "BTCUSD" or "MARKET"
    index_name = fields[3]  # "MSXI" or "MSSI"
    value      = fields[4]  # index value
    components = fields[6]  # "FR:-0.00:0.3,SKEW:-4.12:0.25,..."
    regime     = fields[7].split(":")[1]  # "NEUTRAL"

# For ECON (includes COMMODITIES where region="COMMODITIES"):
elif type_id == "ECON":
    region     = fields[2]  # "US", "EU", or "COMMODITIES"
    indicator  = fields[3]  # "CPI", "WTI", etc.
    value      = fields[4]
    unit       = fields[5]
    period     = fields[6]
    source     = fields[8]  # "BLS", "EIA", etc.

# GAS and WEATHER types have distinct formats — see dedicated docs.
Always use the canonical field directly

Never reconstruct the canonical string from other response fields. The nonce is server-generated and cannot be reproduced. Always verify against the canonical field returned in the response.

SYNOPSIS Type

Used by /oracle/synopsis/market. 15-signal market state snapshot.

canonical format
v1|SYNOPSIS|MARKET|mssi|{value}|{regime}|msti|{value}|{regime}|msxi_btc|{value}|{regime}|msvi_btc|{value}|{regime}|funding_btc|{value}|oi_delta_1h|{value}|liq_1h|{value}|btc|{price}|eth|{price}|{timestamp}|{nonce}

PERP_REGIME Type

Used by /oracle/perp/btc, /oracle/perp/eth, /oracle/perp/sol.

canonical format
v1|PERP_REGIME|{CURRENCY}|regime|{perp_regime}|bias|{bias}|confidence|{confidence}|funding|{funding_pct}|msxi|{msxi}|msvi|{msvi}|{timestamp}|{nonce}

MACRO_RISK Type

Used by /oracle/intel/macro/risk.

canonical format
v1|MACRO_RISK|MARKET|score|{risk_score}|regime|{risk_regime}|mssi|{value}|mssi_regime|{regime}|msti|{value}|msti_regime|{regime}|high_impact|{count}|{timestamp}|{nonce}