Canonical Format

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

Format

canonical string
v1|PAIR|PRICE|CURRENCY|DECIMALS|TIMESTAMP|NONCE|SOURCES|METHOD

Field Definitions

PosFieldTypeExampleDescription
0Versionstringv1Format version. Always "v1" currently.
1PairstringBTCUSDTrading pair without slash.
2Pricestring84231.50Aggregated price as decimal string.
3CurrencystringUSDQuote currency (USD or EUR).
4Decimalsstring2Decimal places in the price.
5Timestampstring2026-02-28T07:51:00ZISO 8601 UTC timestamp.
6Noncestring890123Server-generated nonce. Cannot be reproduced.
7Sourcesstringbinance,bitstamp,...Comma-separated, alphabetically sorted sources.
8MethodstringmedianAggregation method: median or vwap.

Real Example

BTC/USD canonical
v1|BTCUSD|67125.10|USD|2|2026-03-03T14:07:07Z|890123|binance,binance_us,bitfinex,bitstamp,coinbase,gateio,gemini,kraken,okx|median

Signing Process

pseudocode
canonical_bytes = canonical_string.encode("utf-8")
digest          = SHA256(canonical_bytes)
signature       = sign(digest, private_key)
output          = base64_encode(signature)
Pre-hashed signing

Both protocols sign the SHA-256 digest, not the raw bytes. For Ed25519 (x402), the actual operation is Ed25519(SHA-256(canonical)). See Signature Verification for details.

Parsing

python
fields = canonical.split("|")
price     = fields[2]   # "67125.10"
sources   = fields[7].split(",")  # ["binance", ...]
timestamp = fields[5]   # "2026-03-03T14:07:07Z"
Source ordering

Sources are always sorted alphabetically for deterministic canonical strings — the same set of sources always produces the same string regardless of fetch order.