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.
VERSION | TYPE | <payload fields...> | TIMESTAMP | NONCE
Envelope Fields
| Field | Position | Type | Example | Description |
|---|---|---|---|---|
| VERSION | 0 | string | v1 | Format version. |
| TYPE | 1 | string | PRICE, ECON, COMMODITIES, VOLATILITY, SENTIMENT, STRESS | Attestation type — determines payload structure. |
| TIMESTAMP | N-1 | integer | 1741514400 | Unix timestamp (seconds). Always second-to-last. |
| NONCE | N | integer | 482910 | 6-digit random nonce. Always last field. |
PRICE Type
v1|PRICE|PAIR|PRICE_VALUE|CURRENCY|DECIMALS|SOURCES|METHOD|TIMESTAMP|NONCE
v1|PRICE|BTCUSD|84231.50|USD|2|binance,binance_us,bitfinex,bitstamp,coinbase,gateio,gemini,kraken,okx|median|1741514400|482910
v1|PRICE|EURUSD|1.15|USD|5|bankofcanada,bitstamp,cnb,ecb,ecbdirect,kraken,norgesbank|median|1741514400|719304
ECON Type
v1|ECON|REGION|INDICATOR|VALUE|UNIT|PERIOD|VINTAGEDATE|SOURCEAGENCY|SERIESID|SOURCEMODEL|TIMESTAMP|NONCE
v1|ECON|US|CPI|326.785|index198284100|2026-02|2026-03-14|BLS|CUUR0000SA0|directapi|1741514400|830114
v1|COMMODITIES|WTI|94.65|usdperbarrel|2026-03-09|2026-03-15|EIA|DCOILWTICO|directapi|1741514400|402341
VOLATILITY Type (MSVI)
v1|VOLATILITY|PAIR|MSVI|VALUE|INDEX|RV:{rv}:{w},IV:{iv}:{w},TS:{ts}:{w},FR:{fr}:{w},PCR:{pcr}:{w}|REGIME:{regime}|CONFIDENCE:{c}|METHOD:v{n}|{TIMESTAMP}|{NONCE}v1|VOLATILITY|BTCUSD|MSVI|49.98|INDEX|RV:42.40:0.3,IV:44.01:0.25,TS:1.03:0.15,FR:22.00:0.2,PCR:0.92:0.1|REGIME:MODERATE|CONFIDENCE:1.0000|METHOD:v1|1744416000|291847
The components field includes all five weights (RV, IV, TS, FR, PCR) allowing independent reconstruction and verification of the index value.
SENTIMENT Type (MSXI)
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}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)
v1|STRESS|MARKET|MSSI|VALUE|INDEX|VOL:{vol}:{w},STBL:{stbl}:{w},FR:{fr}:{w}|REGIME:{regime}|CONFIDENCE:{c}|METHOD:v{n}|{TIMESTAMP}|{NONCE}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.
Signing Process
canonical_bytes = canonical_string.encode("utf-8")
digest = SHA256(canonical_bytes)
signature = sign(digest, private_key)
output = base64_encode(signature)Both protocols sign the SHA-256 digest, not the raw bytes. For secp256k1 ECDSA (L402), ECDSA always operates on a hash. For Ed25519 (x402), the actual operation is Ed25519(SHA-256(canonical)) — your verification code must hash first. See Signature Verification for code examples.
Parsing
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 index types (VOLATILITY, SENTIMENT, STRESS):
elif type_id in ("VOLATILITY", "SENTIMENT", "STRESS"):
pair = fields[2] # "BTCUSD" or "MARKET"
index_name = fields[3] # "MSVI", "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"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.