Response Schema
Complete JSON response format for each protocol and endpoint type.
Critical: No top-level price field
Oracle responses do not have a top-level price field. The price is embedded in the canonical string at position 2. Extract it with canonical.split("|")[2].
L402 Response (secp256k1)
Returned by the L402 proxy. This is the raw backend response passed through unchanged.
json
{
"domain": "BTCUSD",
"canonical": "v1|BTCUSD|84231.50|USD|2|2026-02-28T07:51:00Z|890123|binance,binance_us,bitfinex,bitstamp,coinbase,gateio,gemini,kraken,okx|median",
"signature": "<base64-DER-encoded-secp256k1-ECDSA>",
"pubkey": "<33-byte-compressed-hex-secp256k1>"
}
| Field | Type | Description |
|---|---|---|
domain | string | Pair identifier without slash (e.g., "BTCUSD") |
canonical | string | Pipe-delimited canonical string that was signed. See format spec → |
signature | string | Base64-encoded DER signature over SHA-256(canonical) |
pubkey | string | Compressed secp256k1 public key, hex-encoded (33 bytes) |
x402 Response (Ed25519)
Returned by the x402 proxy after successful USDC payment. The canonical string is from the backend, but the signature is re-signed with Ed25519.
json
{
"domain": "BTCUSD",
"canonical": "v1|BTCUSD|84231.50|USD|2|2026-02-28T07:51:00Z|890123|binance,...|median",
"signature": "<base64-raw-ed25519-64-bytes>",
"signing_scheme": "ed25519",
"pubkey": "<32-byte-hex-ed25519>"
}
| Field | Type | Description |
|---|---|---|
domain | string | Pair identifier without slash |
canonical | string | Pipe-delimited canonical string (same format as L402) |
signature | string | Base64-encoded raw Ed25519 signature (64 bytes) over SHA-256(canonical) |
signing_scheme | string | Always "ed25519". Absent in L402 responses. |
pubkey | string | Ed25519 public key, hex-encoded (32 bytes) |
Protocol detection
To determine which signature scheme to use for verification: if the response contains "signing_scheme": "ed25519", use Ed25519. If the field is absent, the signature is secp256k1 ECDSA (L402 path).
402 Payment Required (x402)
json
{
"x402Version": 1,
"accepts": [{
"scheme": "exact",
"network": "base",
"maxAmountRequired": "1000",
"resource": "https://api.myceliasignal.com/oracle/btcusd",
"description": "BTC/USD spot price — Ed25519-signed attestation",
"payTo": "0x...",
"asset": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
"maxTimeoutSeconds": 60
}],
"error": "X-PAYMENT header is required"
}
402 Payment Required (L402)
The L402 402 response uses the WWW-Authenticate HTTP header rather than a JSON body:
http header
WWW-Authenticate: L402 macaroon="AgELbXljZWxpYS...", invoice="lnbc100n1pj..."
Extracting Data
python
# Extract price from response price = response["canonical"].split("|")[2] # Extract sources sources = response["canonical"].split("|")[7].split(",") # Extract timestamp timestamp = response["canonical"].split("|")[5]