api reference
POST /v1/signal/crypto-equity
Returns a BTC/QQQ correlation z-score, paid per call in USDC via the X402 protocol. No API key required — payment is embedded in the request header.
Quick start
Copy the snippet below and replace the envelope with a real on-chain payment.
$ curl \ -X GET 'https://strataql.polsia.app/api/v1/signal/crypto-equity' \ -H 'X-PAYMENT: {"payer":"0x000000000000000000000000000000000000dead","amount":"1000000","asset":"USDC","network":"base","tx_hash":"0x1111111111111111111111111111111111111111111111111111111111111111","nonce":"demo-nonce-0001"}'important — raw JSON, not base64
The X-PAYMENT value must be a raw JSON object literal — not base64-encoded. The server calls JSON.parse() directly on the header value. A base64 string will produce HTTP 402 with details: "X-Payment header is not valid JSON". Some X402-spec clients base64-encode by default; disable that option when calling this endpoint.
Response · 200 OK
On a valid paid request the server returns Content-Type: application/json with the following shape.
{ "pair": "BTC/QQQ", "correlation": 0.2741, "z_score": 1.83, "timestamp": "2026-01-15T00:00:00.000Z", "settlement_tx": "0x89a27a6615c2a783f4db8612da0a843efdbd8d68e414b6840aaa204ebbecbc64", "settlement_rail": "hedera" }
| Field | Type | Constraint | Sample |
|---|---|---|---|
| pair | string literal | always "BTC/QQQ" | "BTC/QQQ" |
| correlation | number | finite float | 0.2741 |
| z_score | number | finite float | 1.83 |
| timestamp | string | ISO-8601 UTC ending Z | "2026-01-15T00:00:00.000Z" |
| settlement_tx | string | 0x + 32-byte hex (66 chars) | "0x89a27a66…" |
| settlement_rail | enum | "base" | "hedera" | "hedera" |
X-PAYMENT envelope
Two settlement rails are supported. Pass the envelope as a raw JSON string in the X-PAYMENT HTTP header. The server picks the cheaper rail automatically — the network field is your rail selector.
{ "payer": "0x000000000000000000000000000000000000dead", "amount": "1000000", "asset": "USDC", "network": "base", "tx_hash": "0x1111111111111111111111111111111111111111111111111111111111111111", "nonce": "demo-nonce-0001" }
| Field | Constraint |
|---|---|
| network | "base" — discriminator |
| payer | 0x + 20-byte hex EVM address |
| amount | base-units integer string; "1000000" = $1.00 USDC |
| asset | "USDC" literal |
| tx_hash | 0x + 32-byte hex transaction hash |
| nonce | any non-empty string; use UUID or counter |
{ "payer": "0.0.12345", "amount": "1000000", "asset": "USDC", "network": "hedera", "tx_hash": "0.0.12345-1700000000-000000001", "nonce": "demo-nonce-0002" }
| Field | Constraint |
|---|---|
| network | "hedera" — discriminator |
| payer | Hedera account id: 0.0.<num> |
| amount | base-units integer string; "1000000" = $1.00 USDC |
| asset | "USDC" literal |
| tx_hash | Hedera tx id: 0.0.<num>-<seconds>-<seq> or @-form |
| nonce | any non-empty string |
amount uses USDC base units (6 decimal places). "1000000" = 1 USDC. Do not pass "1.00" — the validator rejects non-integer strings.
Error responses
Every error body follows the shape { "error": "...", "details": "..." }. The table below documents every code the endpoint currently emits plus planned codes for the full API contract.
| HTTP | error | details / message | When | Status |
|---|---|---|---|---|
| 402 | payment_required | "missing X-Payment header" | Header absent | live |
| 402 | payment_required | "empty X-Payment header" | Header present but blank | live |
| 402 | payment_required | "X-Payment header is not valid JSON" | Value is not parseable JSON (includes base64) | live |
| 402 | payment_required | "invalid X-Payment envelope: <reason>" | JSON parsed but fails schema validation | live |
| 503 | service_unavailable | "Strataql is temporarily offline for maintenance." | MAINTENANCE_MODE=1 on server | live |
| 402 | invalid_payment | — | Signature or on-chain verification failure | planned |
| 429 | rate_limited | — | Per-caller call-rate exceeded | planned |
| 408 | stale_signal | — | Signal TTL exceeded | planned |
| 500 | internal_error | — | Unhandled server fault | planned |
The invalid_payment, stale_signal, rate_limited, and internal_error codes are part of the planned Strataql API contract but are not yet emitted by the current implementation. Build your client to handle any 4xx/5xx gracefully.
Rerun policy
The current implementation has no server-side cache. Every call that passes the X-PAYMENT check re-executes the full compute path and bills as a separate paid call. The Cache-Control: no-store header on every 200 response confirms this.
The settlement_tx field IS byte-stable across identical envelopes because computeSettlementTx is a deterministic SHA-256 over the canonical sorted-key envelope JSON — NOT because of caching. A Hedera and a Base envelope with the same amount/nonce produce different settlement_tx values because the network field differs.
A TTL-based deduplication layer (same signal hash within TTL = one billed call) is on the roadmap. This page will be updated when it ships.
Settlement rails
Base L2, EVM-compatible USDC transfer. Pass "network": "base" in the envelope. Settlement in ~2 seconds.
Hedera Token Service. Pass "network": "hedera" in the envelope. Settlement in ~2 seconds. Uses Hedera account ids and transaction ids.
The server picks the cheaper rail on every call using a deterministic fee-estimate table. settlement_rail in the response body identifies which rail was used. The caller does not choose the rail.
get in touch
Questions about the API?
Reach out at strataql@polsia.app for integration help, API access, or feature requests.