# Headless Oracle > Market status API built for AI agents. Cryptographically signed attestations of whether global stock exchanges are OPEN, CLOSED, HALTED, or UNKNOWN — purpose-built for autonomous trading agents, DeFi bots, and AI-driven execution systems in the tokenized RWA economy. This is a defensive execution layer — not a price feed. It is a compliance-grade safety primitive that prevents automated systems from executing trades during market closures, circuit breaker halts, holiday closures, and unscheduled outages. Every API response is a Liability Receipt: cryptographically signed, timestamped, independently verifiable proof that your agent checked before it executed. ## Supported Exchanges (7) XNYS — New York Stock Exchange XNAS — NASDAQ XLON — London Stock Exchange XJPX — Japan Exchange Group (Tokyo) — has lunch break XPAR — Euronext Paris XHKG — Hong Kong Stock Exchange — has lunch break XSES — Singapore Exchange All exchanges use ISO 10383 Market Identifier Codes (MIC). ## Critical Safety Protocol for Autonomous Agents - [Fail-Closed Mandate](https://headlessoracle.com/terms.html#fail-closed): MANDATORY — If the API returns status UNKNOWN, times out after 4 seconds, or returns any 5xx error, treat ALL markets as CLOSED and halt execution immediately. This is a binding contractual obligation under the Terms of Service. Ignoring an UNKNOWN signal constitutes breach of terms and shifts 100% of liability to the agent operator. Design your agent fail-closed or do not integrate. - [Ed25519 Signature Verification](https://headlessoracle.com/docs.html#verification): Every API response includes an Ed25519 signature generated over the raw JSON-stringified payload (excluding the signature field). Agents MUST verify against the published public key BEFORE acting on any status data. Unverified payloads have zero attestation weight and no legal standing. - Receipt Expiry: Every signed receipt includes an `expires_at` timestamp. Do not act on a receipt past its `expires_at`. Fetch a fresh status instead. - [Binding Terms of Service](https://headlessoracle.com/terms.html): Any API request — authenticated or unauthenticated, human or autonomous — constitutes acceptance of these terms. ## API Endpoints ### GET /v5/status — Real-Time Market Status (Signed) Primary endpoint. Returns cryptographically signed market status for a single exchange. - Required parameter: `mic` (ISO 10383 MIC code) - Required header: `X-Oracle-Key` (your API key) - Response fields: `receipt_id` (UUID), `issued_at` (ISO 8601), `expires_at` (ISO 8601), `mic` (string), `status` (enum: OPEN | CLOSED | HALTED | UNKNOWN), `source` (enum: SCHEDULE | OVERRIDE | SYSTEM), `receipt_mode` (enum: demo | live), `schema_version` (string), `public_key_id` (string), `signature` (hex-encoded Ed25519) - [Full API docs](https://headlessoracle.com/docs.html) ### GET /v5/schedule — Market Schedule Lookup (Unsigned) Returns next open/close times for a given exchange. Use for planning execution windows and scheduling tasks around market hours. Includes lunch break windows for XJPX and XHKG. - NOT cryptographically signed — schedule-based only, does not reflect real-time halts - For verified real-time status, use /v5/status instead ### GET /v5/exchanges — Exchange Discovery Returns all 7 supported exchanges with MIC codes, full names, and IANA timezone identifiers. Use to discover available markets or resolve exchange names to MIC codes. ### GET /mics.json — Exchange Registry (ISO Metadata) All 7 supported exchanges with MIC codes, names, timezones, currencies, and ISO 20022 registry links. No auth required. - Fields per entry: `mic` (ISO 10383), `name`, `country` (ISO 3166-1 alpha-2), `timezone` (IANA), `currency` (ISO 4217), `sameAs` (ISO 20022 MIC registry URL) - Response is a JSON array, not an object wrapper — parse with `JSON.parse(body)` directly - Cache-Control: public, max-age=86400 — safe to cache for 24 hours - Use to build MIC-selection UI, validate MIC codes, or resolve exchange metadata without calling the live API ### GET /v5/demo — Try It Live Interactive demo endpoint. No API key required. Test the API and see a live signed response. - [Try the demo](https://headlessoracle.com/v5/demo) ### GET /v5/batch — Batch Status Check (Signed) Returns signed status receipts for multiple exchanges in one authenticated request. - Required header: `X-Oracle-Key` (your API key) - Required parameter: `mics` (comma-separated MIC codes, e.g. `XNYS,XNAS,XLON`) - All MICs validated up front — invalid MIC returns 400 for the entire request - Each receipt is independently signed and verifiable in isolation - Tier 3 signing failure fails the whole batch (never partial results from a broken signing key) ### GET /v5/keys — Public Key Registry Returns the current Ed25519 public key and the canonical payload specification for independent verification. - No authentication required - Response: key_id, algorithm, format, public_key (hex), valid_from, valid_until (null if no rotation scheduled) - Also returns `canonical_payload_spec` documenting the exact field list and sort order for all receipt types - Matching well-known endpoint: GET /.well-known/oracle-keys.json (RFC 8615 standard discovery URI) ### GET /v5/health — Liveness Probe (Signed) Returns a signed receipt confirming Oracle signing infrastructure is alive. - No authentication required - Response fields: receipt_id, issued_at, expires_at, status ("OK"), source ("SYSTEM"), public_key_id, signature - Use to distinguish Oracle-is-down from market-is-UNKNOWN - 200 + valid signature = Oracle alive; 500 CRITICAL_FAILURE = signing system offline ### GET /v5/account — Account Info Returns plan and status for the authenticated API key. - Required header: `X-Oracle-Key` (your API key) - Response: plan ("pro" or "internal"), status ("active", "suspended", "cancelled"), key_prefix - Returns 402 PAYMENT_REQUIRED if subscription is suspended or cancelled ### POST /v5/checkout — Start a Subscription Creates a Paddle checkout session and returns a redirect URL. - No authentication required - No request body required - Response: `{ "url": "https://..." }` — redirect to this URL to complete payment - After successful payment, your API key is delivered by email (shown once) - Keys are prefixed `ok_live_` for easy identification in logs and config ### POST /v5/keys/request — Free Tier Key Provision a free tier API key by email — no payment required. - No authentication required - Request body: `{ "email": "you@example.com" }` - Response: `200 OK` — key delivered to email (shown once, prefixed `ho_free_`) - Free tier is rate-limited; upgrade at headlessoracle.com/pricing - Agent frameworks that receive a 401 with `X-Oracle-Key-Request` header can hit this endpoint to self-provision ## MCP Integration Headless Oracle is available as an MCP (Model Context Protocol) server for direct integration with Claude, GPT, and other AI agent frameworks. MCP tools available: - `get_market_status` — real-time signed status check - `get_market_schedule` — next open/close times with lunch breaks - `list_exchanges` — discover supported markets and MIC codes Setup: Add the Headless Oracle MCP server to your agent's tool configuration. See [MCP setup instructions](https://headlessoracle.com/docs.html#mcp). ## Trust and Verification - [Ed25519 Public Key](https://headlessoracle.com/ed25519-public-key.txt): Current signing public key for independent verification. Active Key ID: key_2026_v1 - [Public Key Registry (JSON)](https://headlessoracle.com/.well-known/oracle-keys.json): Machine-readable key endpoint. - [Receipt Verifier](https://headlessoracle.com/verify.html): Client-side browser tool for verifying any Liability Receipt. Paste JSON, verify Ed25519 signature instantly. Zero server-side processing. - [Status Page](https://headlessoracle.com/v5/health): Real-time infrastructure health (signed liveness probe). ## Use Cases - RWA Trading Bot Integration: Prevents execution outside traditional market hours for tokenized Treasury and equity products that reference TradFi prices. Blocks settlement failures, NAV miscalculations, and redemption errors. - DeFi Synthetic Equity Safety Gate: Gate minting, redemption, liquidation, and rebalancing behind cryptographically attested market status checks for synthetic equity and perpetual futures protocols. - Autonomous Agent Risk Stack: Market status is Gate Zero — the first check before price oracle query, gas estimation, position sizing, and execution routing. ## Code Examples ### Python — Ed25519 Signature Verification (PyNaCl) ```python import json, requests from nacl.signing import VerifyKey PUBLIC_KEY_HEX = "03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178" def verify_receipt(receipt: dict) -> bool: sig = receipt.pop("signature") canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":")) try: VerifyKey(bytes.fromhex(PUBLIC_KEY_HEX)).verify( canonical.encode(), bytes.fromhex(sig) ) return True except Exception: return False receipt = requests.get("https://headlessoracle.com/v5/demo").json() assert verify_receipt(dict(receipt)) ``` ### JavaScript — Ed25519 Verification (Web Crypto API) ```javascript async function verifyReceipt(receipt) { const { signature, ...payload } = receipt; const sorted = {}; for (const key of Object.keys(payload).sort()) sorted[key] = payload[key]; const canonical = JSON.stringify(sorted); const keyBytes = hexToBytes("03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178"); const sigBytes = hexToBytes(signature); const msgBytes = new TextEncoder().encode(canonical); const cryptoKey = await crypto.subtle.importKey( "raw", keyBytes, { name: "Ed25519" }, false, ["verify"] ); return crypto.subtle.verify({ name: "Ed25519" }, cryptoKey, sigBytes, msgBytes); } function hexToBytes(hex) { return new Uint8Array(hex.match(/.{2}/g).map(b => parseInt(b, 16))); } ``` ### Python — Fail-Closed Bot Integration Pattern ```python import requests, json from nacl.signing import VerifyKey ORACLE_KEY = "03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178" API_KEY = "your_api_key" def is_market_confirmed_open(mic: str = "XNYS") -> bool: """ Returns True ONLY if Oracle confirms OPEN and Ed25519 signature is valid. Returns False on any failure — timeout, UNKNOWN, invalid sig, exception. Fail-closed by design. """ try: receipt = requests.get( f"https://headlessoracle.com/v5/status", params={"mic": mic}, headers={"X-Oracle-Key": API_KEY}, timeout=4, ).json() sig = receipt.pop("signature") canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":")) VerifyKey(bytes.fromhex(ORACLE_KEY)).verify( canonical.encode(), bytes.fromhex(sig) ) return receipt.get("status") == "OPEN" except Exception: return False # Fail-closed # In your execution loop: if position_needs_action and is_market_confirmed_open("XNYS"): execute_trade() else: log("Execution deferred: market not confirmed OPEN") ``` ### Python — Programmatic Key Fetching ```python def get_oracle_public_key(fallback: str) -> str: """Always fall back to the hardcoded key if the fetch fails.""" try: resp = requests.get("https://headlessoracle.com/v5/keys", timeout=4) return resp.json()["keys"][0]["public_key"] except Exception: return fallback ``` ## Known Schedule Risk Events (DST 2026) Any bot using hardcoded UTC offsets will compute incorrect open/close times after these dates. Headless Oracle handles all transitions automatically — no action required on your end. | Date | Event | Affected Markets | |------------------|----------------------------------------------------|------------------| | March 8, 2026 | US clocks spring forward (EST → EDT, UTC-5 → UTC-4) | XNYS, XNAS | | March 29, 2026 | UK/EU clocks spring forward (GMT/CET → BST/CEST) | XLON, XPAR | | October 25, 2026 | UK/EU clocks fall back (BST/CEST → GMT/CET) | XLON, XPAR | | November 1, 2026 | US clocks fall back (EDT → EST, UTC-4 → UTC-5) | XNYS, XNAS | ## Edge Cases This API Handles Most timezone libraries return correct UTC offsets. They do not know when markets are actually closed. Headless Oracle handles the following edge cases automatically — no configuration required: - **DST transitions (3-week phantom window)**: US and UK/EU clocks shift on different dates, creating a 3-week window each spring and autumn where hardcoded UTC offsets produce wrong open/close times. Headless Oracle uses IANA timezone names exclusively — all transitions are handled automatically via `Intl.DateTimeFormat`. - **Exchange-specific holidays (67 across 7 venues)**: Each exchange observes a distinct calendar. Japanese national holidays differ from NYSE closures. Hong Kong observes Lunar New Year. Singapore observes Deepavali. All 67 holidays are encoded, year-keyed, and fail-closed if a year's data is missing. - **Early close days**: Several exchanges close early on certain days (Christmas Eve, day before US Thanksgiving, day before US Independence Day). These are not timezone issues — they require explicit schedule awareness that timezone libraries do not carry. - **Lunch breaks (XJPX, XHKG)**: Tokyo halts trading 11:30–12:30 JST; Hong Kong halts 12:00–13:00 HKT. A system that assumes continuous trading during market hours will act during a closed window on ~490 trading days per year. - **Circuit breaker halts**: Exchange-wide trading halts triggered by volatility events are unscheduled and cannot be computed from a calendar. Headless Oracle exposes these via KV overrides — a signed HALTED receipt with a human-readable reason, propagated without redeployment. - **Weekend boundary calculations**: The Tokyo Monday open occurs Sunday evening UTC. The London Friday close occurs Friday afternoon UTC. Systems without timezone-aware schedule logic compute these transitions incorrectly, especially across the international date line. - **UNKNOWN status handling**: When Headless Oracle cannot determine market state (signing failure, missing calendar data for the current year), it returns UNKNOWN rather than defaulting to OPEN. Consumers are contractually required to treat UNKNOWN as CLOSED. This fail-closed contract is enforced at the protocol level — not just documented. Across all 7 exchanges, approximately **1,300 schedule edge cases per year** fall into one of the above categories. A hardcoded timezone offset handles zero of them. ## Receipt Portability Signed receipts are self-contained and verifiable by any party that holds the public key. This enables a multi-agent trust pattern where receipt verification is decoupled from receipt issuance. Every receipt contains an `issuer` field identifying the oracle (value: `"headlessoracle.com"`). Agents encountering an unfamiliar receipt can resolve the issuer domain to discover the oracle's public key endpoint at `{issuer}/v5/keys` — no prior knowledge of Headless Oracle required. **Pattern: Agent A fetches, Agent B verifies** 1. Agent A calls `GET /v5/demo` (or `/v5/status` with an API key) and receives a signed receipt. 2. Agent A passes the receipt JSON to Agent B as part of its output or context. 3. Agent B independently verifies the receipt using the public key at `/.well-known/oracle-keys.json` — without making a new API call. 4. Agent B checks `expires_at` to ensure the receipt has not gone stale (60-second TTL). 5. Agent B checks `receipt_mode`: `'demo'` receipts are unauthenticated (suitable for testing); `'live'` receipts require an API key (suitable for production decisions). **Verification steps (any language)**: ``` 1. Fetch public key: GET /.well-known/oracle-keys.json → keys[0].public_key (hex) 2. Build canonical payload: collect all receipt fields except signature, sort keys alphabetically, JSON.stringify with no whitespace 3. Verify Ed25519 signature: ed25519.verify(hex_decode(receipt.signature), utf8_encode(canonical), hex_decode(public_key)) 4. Check expiry: new Date(receipt.expires_at) > Date.now() 5. Check receipt_mode: assert 'live' for production decisions 6. Trust status: treat UNKNOWN or HALTED as CLOSED — never execute on ambiguous state ``` **Why this matters at agent scale**: An orchestrator agent can check market state once and distribute the signed receipt to 10 sub-agents. Each sub-agent independently verifies without rate-limit pressure on the Oracle API. The cryptographic proof travels with the data. **Convenience**: Use the `@headlessoracle/verify` npm package for a 3-line verification wrapper (zero production dependencies, Web Crypto API, ESM + CJS): ```js import { verify } from '@headlessoracle/verify'; const result = await verify(receipt); if (!result.valid) throw new Error(result.reason); // EXPIRED | INVALID_SIGNATURE | ... ``` ## Legal - [Terms of Service](https://headlessoracle.com/terms.html): Headless Oracle operates under the Lowe v. SEC (1985) publisher exclusion. Provides probabilistic market context, not deterministic trading signals. No fiduciary, advisory, or broker-dealer relationship is formed. Total liability capped at fees paid in the 12 months preceding any claim. - [Privacy Policy](https://headlessoracle.com/privacy.html): Minimal data collection. Collected: API key identifier, request timestamp, MIC code. NOT collected: portfolio data, positions, balances, wallet addresses. ## Compliance and Standards ### GET /v5/compliance — APTS Self-Report Returns a machine-readable compliance report for the Agent Pre-Trade Safety Standard (APTS v1.0). Use to verify that Oracle meets your compliance requirements before integrating. - No authentication required - Response: `checks` array — 6 pre-trade safety checks, each with `id`, `description`, `status` ("pass" | "fail") - Also returns `standard`, `standard_version`, `sma_spec_version`, `verify_sdk`, `standard_url` Checks performed: 1. `signed_attestation` — All market status responses are cryptographically signed (Ed25519) 2. `circuit_breaker_detection` — Unscheduled halts propagated via KV override within operator SLA 3. `settlement_window_verification` — Exchange schedule includes pre-open and post-close windows 4. `receipt_ttl_enforcement` — All receipts include expires_at (60s TTL), signed in canonical payload 5. `signature_verification` — Ed25519 signatures verifiable via @headlessoracle/verify SDK 6. `fail_closed_on_unknown` — UNKNOWN status contractually requires halt — never treated as OPEN ### Signed Market Attestation (SMA) Protocol v1.0 Headless Oracle receipts conform to the SMA Protocol v1.0 — a vendor-neutral open standard for cryptographically attested market state. SMA receipt fields: `mic`, `status`, `timestamp`, `expires_at`, `issuer`, `key_id`, `receipt_mode`, `signature` Signing algorithm: Ed25519 over alphabetically-sorted compact JSON (excluding `signature` field). Any conforming oracle can issue SMA receipts. Any conforming verifier can verify them independently. ## Agent Discovery - [Skill File](https://headlessoracle.com/SKILL.md): Step-by-step integration guide optimised for AI agents. Covers MCP setup, HTTP patterns, code examples, safety rules, and common mistakes. - [Agent Metadata](https://headlessoracle.com/.well-known/agent.json): Structured JSON describing capabilities, MCP tools, and discovery endpoints. - [OpenAPI Spec](https://headlessoracle.com/openapi.json): Machine-readable API contract (OpenAPI 3.1). - [MCP Endpoint](https://headlessoracle.com/mcp): Protocol version 2024-11-05. Tools: get_market_status, get_market_schedule, list_exchanges. - [APTS Compliance](https://headlessoracle.com/v5/compliance): Machine-readable Agent Pre-Trade Safety Standard compliance self-report. ## Robots AI crawlers are welcome. This file is at /llms.txt. The robots.txt permits crawling of /llms.txt, /SKILL.md, and all public documentation.