-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathdocs.html
More file actions
760 lines (702 loc) · 51.2 KB
/
docs.html
File metadata and controls
760 lines (702 loc) · 51.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Integration Docs | Headless Oracle V5</title>
<meta name="description" content="Integration documentation for Headless Oracle V5. REST API, MCP server, batch queries, billing, and verification SDK. All endpoints documented.">
<meta name="robots" content="index, follow">
<meta property="og:type" content="website">
<meta property="og:url" content="https://headlessoracle.com/docs">
<meta property="og:title" content="Integration Docs | Headless Oracle V5">
<meta property="og:description" content="REST API, MCP server, batch queries, billing, and verification SDK. Full documentation for Headless Oracle V5.">
<meta property="og:image" content="https://headlessoracle.com/og-image.png">
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:title" content="Integration Docs | Headless Oracle">
<meta name="twitter:description" content="REST API, MCP server, batch queries, billing, and verification SDK. Full documentation.">
<meta name="twitter:image" content="https://headlessoracle.com/og-image.png">
<link rel="canonical" href="https://headlessoracle.com/docs">
<link rel="alternate" type="application/json" href="/openapi.json" title="OpenAPI 3.1 specification">
<link rel="alternate" type="text/plain" href="/llms.txt" title="llms.txt — machine-readable API summary">
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;600;700&display=swap" rel="stylesheet">
<style>
body { font-family: 'Inter', sans-serif; background-color: #0f172a; color: #cbd5e1; }
.glass { background: rgba(30, 41, 59, 0.7); border: 1px solid rgba(51, 65, 85, 0.5); }
pre { background: #1e293b; padding: 1rem; border-radius: 0.5rem; overflow-x: auto; font-family: 'Menlo', monospace; font-size: 0.85rem; border: 1px solid #334155; }
code { color: #60a5fa; }
h2 { color: white; font-weight: 700; margin-top: 2rem; margin-bottom: 1rem; font-size: 1.5rem; }
h3 { color: #e2e8f0; font-weight: 600; margin-top: 1.5rem; margin-bottom: 0.5rem; font-size: 1.1rem; }
.badge { background: #1e293b; color: #60a5fa; padding: 2px 8px; border-radius: 4px; font-size: 0.75rem; border: 1px solid #334155; }
table { width: 100%; border-collapse: collapse; font-size: 0.85rem; }
th { text-align: left; padding: 8px 12px; color: #94a3b8; font-weight: 600; border-bottom: 1px solid #334155; }
td { padding: 8px 12px; border-bottom: 1px solid #1e293b; }
tr:hover td { background: #1e293b; }
</style>
</head>
<body class="min-h-screen flex flex-col">
<nav class="w-full border-b border-slate-800 bg-slate-900/80 backdrop-blur-md fixed top-0 z-50">
<div class="max-w-5xl mx-auto px-6 h-16 flex justify-between items-center">
<a href="/" class="font-bold text-white tracking-wider">HEADLESS<span class="text-blue-500">ORACLE</span></a>
<div class="flex items-center gap-4 text-xs">
<a href="/docs" class="text-white font-semibold">Docs</a>
<a href="/status" class="text-slate-400 hover:text-white transition">Status</a>
<a href="/pricing" class="text-slate-400 hover:text-white transition">Pricing</a>
<a href="/standards" class="text-slate-400 hover:text-white transition">Standards</a>
<a href="/blog" class="text-slate-400 hover:text-white transition">Blog</a>
<a href="https://github.com/LembaGang" class="text-slate-400 hover:text-white transition" target="_blank" rel="noopener">GitHub</a>
</div>
</div>
</nav>
<main class="flex-grow max-w-5xl mx-auto px-6 py-24 w-full grid grid-cols-1 md:grid-cols-4 gap-12">
<aside class="hidden md:block col-span-1 border-r border-slate-800 pr-6 h-[calc(100vh-100px)] sticky top-24">
<div class="space-y-4 text-sm font-medium text-slate-400">
<a href="#complexity" class="block hover:text-white transition">Edge Cases</a>
<a href="#quickstart" class="block hover:text-white transition">Quick Start</a>
<a href="#exchanges" class="block hover:text-white transition">Supported Exchanges</a>
<a href="#endpoints" class="block hover:text-white transition">Endpoints</a>
<a href="#health" class="block pl-4 hover:text-white transition text-xs">↳ /v5/health</a>
<a href="#batch" class="block pl-4 hover:text-white transition text-xs">↳ /v5/batch</a>
<a href="#schema" class="block hover:text-white transition">Response Schema</a>
<a href="#verification" class="block hover:text-white transition">Verification Logic</a>
<a href="#fail-closed" class="block hover:text-white transition">Fail-Closed Architecture</a>
<a href="#overrides" class="block hover:text-white transition">Circuit Breaker Overrides</a>
<a href="#mcp" class="block hover:text-white transition">MCP Integration</a>
<a href="#billing" class="block hover:text-white transition">API Keys & Billing</a>
<a href="#standards" class="block hover:text-white transition">Open Standards</a>
<a href="/docs/quickstart" class="block hover:text-white transition text-blue-400">MCP Setup →</a>
<a href="/docs/x402-payments" class="block hover:text-white transition text-blue-400">x402 Payments →</a>
</div>
</aside>
<div class="col-span-1 md:col-span-3">
<h1 class="text-4xl font-bold text-white mb-6">Integration Guide</h1>
<p class="text-lg text-slate-400 mb-8">
Headless Oracle provides a cryptographically verifiable defensive execution layer for autonomous agents operating across global markets.
</p>
<!-- EDGE CASES -->
<section id="complexity" class="mb-12 border-b border-slate-800 pb-12">
<h2>28 exchanges. Global 24/7 coverage.</h2>
<p class="text-sm text-slate-400 mb-6">The scheduling complexity a timezone library was not built to solve.</p>
<div class="flex flex-wrap justify-center gap-3 mb-6">
<div class="glass p-5 rounded-xl text-center w-[calc(50%-6px)] md:w-auto md:flex-1">
<div class="text-3xl font-bold text-white mb-2">67</div>
<div class="text-xs text-slate-400 leading-snug">exchange-specific<br>holidays<br><span class="text-slate-600 text-xs">different per country, non-overlapping</span></div>
</div>
<div class="glass p-5 rounded-xl text-center w-[calc(50%-6px)] md:w-auto md:flex-1">
<div class="text-3xl font-bold text-white mb-2">18</div>
<div class="text-xs text-slate-400 leading-snug">early close<br>days<br><span class="text-slate-600 text-xs">NYSE closes at 1:00 PM, not 4:00 PM</span></div>
</div>
<div class="glass p-5 rounded-xl text-center w-[calc(50%-6px)] md:w-auto md:flex-1">
<div class="text-3xl font-bold text-white mb-2">8</div>
<div class="text-xs text-slate-400 leading-snug">DST<br>transitions<br><span class="text-slate-600 text-xs">incl. 3-week US/EU phantom window</span></div>
</div>
<div class="glass p-5 rounded-xl text-center w-[calc(50%-6px)] md:w-auto md:flex-1">
<div class="text-3xl font-bold text-white mb-2">490</div>
<div class="text-xs text-slate-400 leading-snug">lunch break<br>sessions<br><span class="text-slate-600 text-xs">Tokyo 11:30–12:30, HK 12:00–13:00</span></div>
</div>
<div class="glass p-5 rounded-xl text-center w-[calc(50%-6px)] md:w-auto md:flex-1">
<div class="text-3xl font-bold text-white mb-2">728</div>
<div class="text-xs text-slate-400 leading-snug">weekend days<br>across 7 venues<br><span class="text-slate-600 text-xs">per calendar year</span></div>
</div>
</div>
<div class="p-4 bg-slate-800/40 border border-slate-700/80 rounded-lg mb-8 text-center">
<p class="text-sm font-mono text-slate-300">A timezone library handles zero of these. Headless Oracle handles all of them.</p>
</div>
<h3>Think it's simple?</h3>
<p class="text-sm text-slate-500 mb-4">Common assumptions about market schedules, and what the data actually shows.</p>
<div class="overflow-x-auto">
<table>
<thead>
<tr>
<th style="width:38%">What you assume</th>
<th>What actually happens</th>
</tr>
</thead>
<tbody>
<tr>
<td class="font-mono text-xs align-top text-slate-300">NYSE closes at 4pm ET</td>
<td class="align-top">Except Good Friday (1pm), day before July 4th (1pm), Christmas Eve (1pm), and emergency halts at any time</td>
</tr>
<tr>
<td class="font-mono text-xs align-top text-slate-300">Tokyo is open 9am–3pm JST</td>
<td class="align-top">There's a lunch break 11:30–12:30 every trading day. Your bot thinks it's open. It's not.</td>
</tr>
<tr>
<td class="font-mono text-xs align-top text-slate-300">"Just use a timezone library"</td>
<td class="align-top">pytz handles DST. It doesn't handle that NYSE closes for Juneteenth but LSE doesn't, or that Hong Kong closes for Lunar New Year but Singapore doesn't.</td>
</tr>
<tr>
<td class="font-mono text-xs align-top text-slate-300">"I'll hardcode the holidays"</td>
<td class="align-top">Which year? 2026 holidays differ from 2027. When a holiday falls on a weekend, some exchanges shift to Friday, others Monday, others don't shift.</td>
</tr>
<tr>
<td class="font-mono text-xs align-top text-slate-300">"I'll check once at market open"</td>
<td class="align-top">Circuit breaker at 2:47pm. Your cached "OPEN" is now wrong. Your bot trades into a halted market.</td>
</tr>
</tbody>
</table>
</div>
</section>
<!-- QUICK START -->
<section id="quickstart" class="mb-12 border-b border-slate-800 pb-12">
<h2>Quick Start</h2>
<p class="mb-4 text-sm">
Using Claude Code? <a href="/docs/quickstart" class="text-blue-400 hover:text-blue-300 underline">Add Headless Oracle to Claude Code in 3 steps →</a>
Copy one <code class="text-xs bg-slate-800 px-1 rounded">.mcp.json</code> file and your agent has pre-trade verification instantly.
</p>
<p class="mb-4 text-sm">Try the public demo endpoint instantly — no API key needed:</p>
<pre class="text-blue-300">curl https://headlessoracle.com/v5/demo
# Any supported exchange:
curl "https://headlessoracle.com/v5/demo?mic=XLON"
curl "https://headlessoracle.com/v5/demo?mic=XJPX"</pre>
<p class="mt-4 mb-4 text-sm">For production use, fetch a signed attestation with your API key:</p>
<pre class="text-blue-300">curl -X GET "https://headlessoracle.com/v5/status?mic=XNYS" \
-H "X-Oracle-Key: YOUR_API_KEY"</pre>
<p class="mt-4 mb-4 text-sm">Check when the next session opens (no auth required):</p>
<pre class="text-blue-300">curl "https://headlessoracle.com/v5/schedule?mic=XNYS"</pre>
<p class="mt-4 mb-4 text-sm">Verify Oracle's signing infrastructure is live:</p>
<pre class="text-blue-300">curl "https://headlessoracle.com/v5/health"</pre>
</section>
<!-- SUPPORTED EXCHANGES -->
<section id="exchanges" class="mb-12 border-b border-slate-800 pb-12">
<h2>Supported Exchanges</h2>
<p class="text-sm text-slate-400 mb-4">
28 exchanges across 7 regions (including derivatives and 24/7 crypto). All DST transitions are handled server-side using IANA timezone data — no hardcoded UTC offsets.
</p>
<div class="overflow-x-auto">
<table>
<thead>
<tr>
<th>MIC</th>
<th>Exchange</th>
<th>Local Hours</th>
<th>Timezone</th>
<th>DST</th>
</tr>
</thead>
<tbody>
<tr>
<td class="font-mono text-blue-400">XNYS</td>
<td>New York Stock Exchange</td>
<td class="font-mono text-xs">09:30 – 16:00</td>
<td class="text-xs text-slate-500">America/New_York</td>
<td class="text-xs text-yellow-500">Mar 8</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XNAS</td>
<td>NASDAQ</td>
<td class="font-mono text-xs">09:30 – 16:00</td>
<td class="text-xs text-slate-500">America/New_York</td>
<td class="text-xs text-yellow-500">Mar 8</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XBSP</td>
<td>B3 (São Paulo Stock Exchange)</td>
<td class="font-mono text-xs">10:00 – 17:00</td>
<td class="text-xs text-slate-500">America/Sao_Paulo</td>
<td class="text-xs text-yellow-500">Brazil (Nov)</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XLON</td>
<td>London Stock Exchange</td>
<td class="font-mono text-xs">08:00 – 16:30</td>
<td class="text-xs text-slate-500">Europe/London</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XPAR</td>
<td>Euronext Paris</td>
<td class="font-mono text-xs">09:00 – 17:30</td>
<td class="text-xs text-slate-500">Europe/Paris</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSWX</td>
<td>SIX Swiss Exchange</td>
<td class="font-mono text-xs">09:00 – 17:30</td>
<td class="text-xs text-slate-500">Europe/Zurich</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XMIL</td>
<td>Borsa Italiana (Milan)</td>
<td class="font-mono text-xs">09:00 – 17:30</td>
<td class="text-xs text-slate-500">Europe/Rome</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XHEL</td>
<td>Nasdaq Helsinki</td>
<td class="font-mono text-xs">10:00 – 18:30</td>
<td class="text-xs text-slate-500">Europe/Helsinki</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSTO</td>
<td>Nasdaq Stockholm</td>
<td class="font-mono text-xs">09:00 – 17:30</td>
<td class="text-xs text-slate-500">Europe/Stockholm</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XIST</td>
<td>Borsa Istanbul</td>
<td class="font-mono text-xs">10:00 – 18:00</td>
<td class="text-xs text-slate-500">Europe/Istanbul</td>
<td class="text-xs text-yellow-500">Mar 29</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSAU</td>
<td>Saudi Exchange (Tadawul) <span class="text-slate-500 text-xs">Sun–Thu</span></td>
<td class="font-mono text-xs">10:00 – 15:00</td>
<td class="text-xs text-slate-500">Asia/Riyadh</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XDFM</td>
<td>Dubai Financial Market <span class="text-slate-500 text-xs">Sun–Thu</span></td>
<td class="font-mono text-xs">10:00 – 14:00</td>
<td class="text-xs text-slate-500">Asia/Dubai</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XJSE</td>
<td>Johannesburg Stock Exchange</td>
<td class="font-mono text-xs">09:00 – 17:00</td>
<td class="text-xs text-slate-500">Africa/Johannesburg</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSHG</td>
<td>Shanghai Stock Exchange</td>
<td class="font-mono text-xs">09:30 – 15:00 <span class="text-slate-500">(lunch 11:30–13:00)</span></td>
<td class="text-xs text-slate-500">Asia/Shanghai</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSHE</td>
<td>Shenzhen Stock Exchange</td>
<td class="font-mono text-xs">09:30 – 15:00 <span class="text-slate-500">(lunch 11:30–13:00)</span></td>
<td class="text-xs text-slate-500">Asia/Shanghai</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XHKG</td>
<td>Hong Kong Exchanges and Clearing</td>
<td class="font-mono text-xs">09:30 – 16:00 <span class="text-slate-500">(lunch 12:00–13:00)</span></td>
<td class="text-xs text-slate-500">Asia/Hong_Kong</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XJPX</td>
<td>Japan Exchange Group (Tokyo)</td>
<td class="font-mono text-xs">09:00 – 15:30 <span class="text-slate-500">(lunch 11:30–12:30)</span></td>
<td class="text-xs text-slate-500">Asia/Tokyo</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XKRX</td>
<td>Korea Exchange (Seoul)</td>
<td class="font-mono text-xs">09:00 – 15:30</td>
<td class="text-xs text-slate-500">Asia/Seoul</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XBOM</td>
<td>BSE Ltd (Bombay Stock Exchange)</td>
<td class="font-mono text-xs">09:15 – 15:30</td>
<td class="text-xs text-slate-500">Asia/Kolkata</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XNSE</td>
<td>National Stock Exchange of India</td>
<td class="font-mono text-xs">09:15 – 15:30</td>
<td class="text-xs text-slate-500">Asia/Kolkata</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XSES</td>
<td>Singapore Exchange</td>
<td class="font-mono text-xs">09:00 – 17:00</td>
<td class="text-xs text-slate-500">Asia/Singapore</td>
<td class="text-xs text-slate-500">None</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XASX</td>
<td>Australian Securities Exchange (Sydney)</td>
<td class="font-mono text-xs">10:00 – 16:00</td>
<td class="text-xs text-slate-500">Australia/Sydney</td>
<td class="text-xs text-yellow-500">Oct (AU)</td>
</tr>
<tr>
<td class="font-mono text-blue-400">XNZE</td>
<td>New Zealand Exchange (Auckland)</td>
<td class="font-mono text-xs">10:00 – 16:45</td>
<td class="text-xs text-slate-500">Pacific/Auckland</td>
<td class="text-xs text-yellow-500">Oct (NZ)</td>
</tr>
</tbody>
</table>
</div>
<p class="text-xs text-slate-500 mt-3">All times are local to the exchange. Retrieve the full exchange directory programmatically at <code>/v5/exchanges</code>.</p>
<div class="mt-6 p-4 bg-yellow-900/20 border border-yellow-800/40 rounded-lg">
<p class="text-sm text-yellow-300 font-semibold mb-1">2026 DST Risk Events</p>
<p class="text-xs text-slate-400">Any bot using hardcoded UTC offsets will compute incorrect hours after these dates:</p>
<ul class="text-xs text-slate-400 mt-2 space-y-1">
<li><span class="text-yellow-400 font-mono">Mar 8</span> — US clocks spring forward (EST → EDT). Affects XNYS, XNAS.</li>
<li><span class="text-yellow-400 font-mono">Mar 29</span> — UK/EU clocks spring forward (GMT/CET → BST/CEST). Affects XLON, XPAR.</li>
<li><span class="text-yellow-400 font-mono">Oct 25</span> — UK/EU clocks fall back. Affects XLON, XPAR.</li>
<li><span class="text-yellow-400 font-mono">Nov 1</span> — US clocks fall back. Affects XNYS, XNAS.</li>
</ul>
<p class="text-xs text-slate-500 mt-2">Headless Oracle handles all transitions automatically.</p>
</div>
</section>
<!-- ENDPOINTS -->
<section id="endpoints" class="mb-12 border-b border-slate-800 pb-12">
<h2>Available Endpoints</h2>
<div class="space-y-8">
<div>
<h3 class="text-blue-400">GET /v5/status <span class="text-xs text-slate-500 ml-2">Authenticated</span></h3>
<p class="text-sm mb-2">Primary endpoint for production market status checks.</p>
<pre>Header: X-Oracle-Key: YOUR_API_KEY
Query: mic=XNYS (or any of the 28 supported MIC codes — see /v5/exchanges)</pre>
</div>
<div>
<h3 class="text-blue-400">GET /v5/demo <span class="text-xs text-slate-500 ml-2">Public</span></h3>
<p class="text-sm mb-2">Returns a signed receipt for any exchange. No auth required. Use this for integration testing and verification development.</p>
<pre>Query: mic=XNYS (optional, defaults to XNYS)</pre>
</div>
<div>
<h3 class="text-blue-400">GET /v5/schedule <span class="text-xs text-slate-500 ml-2">Public</span></h3>
<p class="text-sm mb-2">Returns the next scheduled open and close times for any exchange. Includes <code>lunch_break</code> for exchanges with midday breaks (XJPX, XHKG). Does not reflect real-time halts or manual overrides.</p>
<pre class="text-xs">{
"mic": "XJPX",
"name": "Japan Exchange Group (Tokyo)",
"timezone": "Asia/Tokyo",
"queried_at": "2026-03-10T01:00:00.000Z",
"current_status": "OPEN",
"next_open": "2026-03-10T03:30:00.000Z",
"next_close": "2026-03-10T06:30:00.000Z",
"lunch_break": { "start": "11:30", "end": "12:30" },
"note": "Times are UTC. lunch_break times are local exchange time (see timezone field)."
}
// Exchanges without a lunch break return lunch_break: null
// { ..., "lunch_break": null, ... }</pre>
</div>
<div>
<h3 class="text-blue-400">GET /v5/exchanges <span class="text-xs text-slate-500 ml-2">Public</span></h3>
<p class="text-sm mb-2">Returns the full directory of supported exchanges with MIC codes, names, and timezones.</p>
</div>
<div>
<h3 class="text-blue-400">GET /v5/keys <span class="text-xs text-slate-500 ml-2">Public</span></h3>
<p class="text-sm mb-2">Returns the current Ed25519 public key registry and the canonical payload specification for independent signature verification.</p>
<pre class="text-xs">{
"keys": [{
"key_id": "key_2026_v1",
"algorithm": "Ed25519",
"format": "hex",
"public_key": "03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178",
"valid_from": "2026-01-01T00:00:00Z",
"valid_until": null
}],
"canonical_payload_spec": { ... }
}
// valid_until is null when no key rotation is scheduled.
// It will be set in advance of any planned rotation.</pre>
</div>
<div id="batch">
<h3 class="text-blue-400">GET /v5/batch <span class="text-xs text-slate-500 ml-2">Authenticated</span></h3>
<p class="text-sm mb-2">Fetch signed status receipts for multiple exchanges in one request. Each receipt is independently signed and verifiable in isolation.</p>
<pre>Header: X-Oracle-Key: YOUR_API_KEY
Query: mics=XNYS,XNAS,XLON (comma-separated, deduplicated)</pre>
<p class="text-xs text-slate-500 mt-2">All MICs are validated up front — one invalid MIC returns 400 for the whole request. Tier 3 signing failure fails the whole batch.</p>
</div>
<div id="health">
<h3 class="text-blue-400">GET /v5/health <span class="text-xs text-slate-500 ml-2">Public</span></h3>
<p class="text-sm mb-2">Signed liveness probe. Use this to distinguish <em>Oracle is down</em> from <em>market is genuinely UNKNOWN</em>. A valid signed response means the signing infrastructure is alive.</p>
<pre class="text-xs">{
"receipt_id": "uuid-v4",
"issued_at": "2026-03-10T13:00:00.000Z",
"expires_at": "2026-03-10T13:01:00.000Z",
"status": "OK",
"source": "SYSTEM",
"public_key_id": "key_2026_v1",
"signature": "hex_string"
}
// 200 + valid signature = Oracle is alive
// 500 CRITICAL_FAILURE = signing system offline</pre>
</div>
</div>
</section>
<!-- SCHEMA -->
<section id="schema" class="mb-12 border-b border-slate-800 pb-12">
<h2>Response Schema</h2>
<pre>{
"receipt_id": "uuid-v4",
"issued_at": "ISO-8601-Timestamp (UTC)",
"expires_at": "ISO-8601-Timestamp (UTC, issued_at + 60s)",
"mic": "XNYS",
"status": "OPEN", // OPEN | CLOSED | HALTED | UNKNOWN
"source": "SCHEDULE", // SCHEDULE | OVERRIDE | SYSTEM
"schema_version": "v5.0",
"public_key_id": "key_2026_v1",
"signature": "hex_string"
}
// Do not act on a receipt whose expires_at has passed.</pre>
<h3 class="mt-6">Status Values</h3>
<ul class="list-disc pl-5 space-y-2 text-slate-400 text-sm">
<li><strong class="text-green-400">OPEN:</strong> Market is in an active trading session. Safe to execute.</li>
<li><strong class="text-red-400">CLOSED:</strong> Market is outside trading hours — weekend, holiday, or after close.</li>
<li><strong class="text-orange-400">HALTED:</strong> Market has been manually halted (circuit breaker or emergency override). Treat identically to CLOSED.</li>
<li><strong class="text-yellow-400">UNKNOWN:</strong> Oracle cannot determine status. <strong>Treat as CLOSED. Halt all execution.</strong></li>
</ul>
<h3 class="mt-6">Source Values</h3>
<ul class="list-disc pl-5 space-y-2 text-slate-400 text-sm">
<li><strong class="text-slate-200">SCHEDULE:</strong> Status derived from the exchange holiday/hours calendar.</li>
<li><strong class="text-orange-300">OVERRIDE:</strong> Status set manually. Active during circuit breakers or emergency halts. Includes a <code>reason</code> field.</li>
<li><strong class="text-slate-500">SYSTEM:</strong> Internal fallback — returned when an error occurred in the primary logic. Always paired with UNKNOWN.</li>
</ul>
</section>
<!-- VERIFICATION -->
<section id="verification" class="mb-12 border-b border-slate-800 pb-12">
<h2>Verification Logic</h2>
<p class="mb-4">To confirm a receipt is authentic, reconstruct the signed payload and verify the Ed25519 signature against the <a href="ed25519-public-key.txt" class="text-blue-400 underline">published public key</a>.</p>
<h3 class="text-xs text-slate-500 uppercase tracking-widest mb-2">1. Reconstruct the Payload</h3>
<p class="text-sm mb-4">The signature covers all fields in the receipt <em>except</em> <code>signature</code> itself, with keys sorted alphabetically, minified (no spaces).</p>
<pre class="text-blue-300">// Remove signature, sort remaining keys alphabetically, then stringify
const { signature, ...payload } = receipt;
const sorted = {};
for (const key of Object.keys(payload).sort()) sorted[key] = payload[key];
const canonical = JSON.stringify(sorted); // no spaces, alphabetical keys</pre>
<h3 class="text-xs text-slate-500 uppercase tracking-widest mt-8 mb-2">2. Implementation Samples</h3>
<div class="space-y-6">
<div>
<p class="text-xs font-mono text-slate-500 mb-1">Python (PyNaCl)</p>
<pre class="text-xs">import json, requests
from nacl.signing import VerifyKey
PUBLIC_KEY_HEX = "03dc27993a2c90856cdeb45e228ac065f18f69f0933c917b2336c1e75712f178"
def verify_and_check(mic="XNYS"):
receipt = requests.get(
f"https://headlessoracle.com/v5/status?mic={mic}",
headers={"X-Oracle-Key": "YOUR_KEY"},
timeout=4
).json()
sig = receipt.pop("signature")
canonical = json.dumps(receipt, sort_keys=True, separators=(",", ":"))
VerifyKey(bytes.fromhex(PUBLIC_KEY_HEX)).verify(
canonical.encode(), bytes.fromhex(sig)
)
return receipt["status"] == "OPEN"</pre>
</div>
<div>
<p class="text-xs font-mono text-slate-500 mb-1">JavaScript (Web Crypto API)</p>
<pre class="text-xs">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)));
}</pre>
</div>
</div>
<p class="text-sm mt-4 text-slate-400">
Or use the <a href="/verify" class="text-blue-400 underline">browser-based verifier</a> — paste any receipt and verify the Ed25519 signature instantly with zero server calls.
</p>
</section>
<!-- FAIL-CLOSED -->
<section id="fail-closed" class="mb-12 border-b border-slate-800 pb-12">
<h2>Fail-Closed Architecture</h2>
<p class="text-slate-400 mb-4">
The oracle uses a three-tier safety cascade. If anything fails at any tier, the response always defaults to <code>UNKNOWN</code> — never a false <code>OPEN</code>.
</p>
<div class="space-y-2 text-sm mb-6">
<div class="flex gap-3 items-start"><span class="text-orange-400 font-mono font-bold w-16 shrink-0">TIER 0</span><span>Manual override active — returns HALTED or CLOSED with signed reason.</span></div>
<div class="flex gap-3 items-start"><span class="text-blue-400 font-mono font-bold w-16 shrink-0">TIER 1</span><span>Schedule-based calculation — checks holidays, weekends, trading hours, half-days, lunch breaks.</span></div>
<div class="flex gap-3 items-start"><span class="text-yellow-400 font-mono font-bold w-16 shrink-0">TIER 2</span><span>Fail-closed safety net — any Tier 1 error returns a signed UNKNOWN receipt.</span></div>
<div class="flex gap-3 items-start"><span class="text-red-400 font-mono font-bold w-16 shrink-0">TIER 3</span><span>Catastrophic — signing system offline. Returns unsigned CRITICAL_FAILURE with HTTP 500.</span></div>
</div>
<div class="p-4 bg-red-900/20 border border-red-800/40 rounded-lg">
<p class="text-sm text-red-300 font-semibold">Integrator Rule (Binding)</p>
<p class="text-sm text-slate-400 mt-1">Execute <em>only</em> if <code>status === 'OPEN'</code> AND the Ed25519 signature is valid. Any other result — CLOSED, HALTED, UNKNOWN, timeout, network error, or invalid signature — must halt execution. This is a contractual obligation under the <a href="/terms" class="text-blue-400 underline">Terms of Service</a>.</p>
</div>
</section>
<!-- MCP -->
<section id="mcp" class="mb-12 border-b border-slate-800 pb-12">
<h2>MCP Integration</h2>
<p class="text-slate-400 mb-4">
Headless Oracle exposes an MCP (Model Context Protocol) server at <code>POST /mcp</code>. Any agent framework that supports MCP tool calling — Claude Desktop, Cursor, or custom agents built on the MCP spec — can call Oracle directly without writing HTTP client code.
</p>
<h3 class="text-blue-400">POST /mcp <span class="text-xs text-slate-500 ml-2">Public · JSON-RPC 2.0</span></h3>
<p class="text-sm mb-4">Protocol version: <code>2024-11-05</code> (MCP Streamable HTTP transport). No authentication required for MCP tool calls.</p>
<h3>Available MCP Tools</h3>
<div class="space-y-4 text-sm mb-6">
<div class="p-4 bg-slate-800/50 rounded-lg border border-slate-700">
<p class="font-semibold text-white mb-1"><code>get_market_status</code></p>
<p class="text-slate-400 mb-2">Check whether a stock exchange is currently open or closed. Returns a cryptographically signed receipt. MANDATORY: treat UNKNOWN or HALTED as CLOSED and halt execution.</p>
<p class="text-xs text-slate-500">Input: <code>{ "mic": "XNYS" }</code> — any of the 28 supported MIC codes.</p>
</div>
<div class="p-4 bg-slate-800/50 rounded-lg border border-slate-700">
<p class="font-semibold text-white mb-1"><code>get_market_schedule</code></p>
<p class="text-slate-400 mb-2">Get next open and close times for an exchange. Includes lunch break windows for XJPX and XHKG. Not cryptographically signed — does not reflect real-time halts.</p>
<p class="text-xs text-slate-500">Input: <code>{ "mic": "XJPX" }</code></p>
</div>
<div class="p-4 bg-slate-800/50 rounded-lg border border-slate-700">
<p class="font-semibold text-white mb-1"><code>list_exchanges</code></p>
<p class="text-slate-400 mb-2">Returns all 28 supported exchanges with MIC codes, names, and timezones.</p>
<p class="text-xs text-slate-500">No input required.</p>
</div>
</div>
<h3>Setup: Claude Desktop <span class="text-xs text-slate-500 font-normal ml-2">~30 seconds</span></h3>
<p class="text-sm text-slate-400 mb-2">Add this to your Claude Desktop config file, then restart Claude Desktop:</p>
<p class="text-xs text-slate-500 mb-1">
<strong class="text-slate-400">macOS:</strong>
<code>~/Library/Application Support/Claude/claude_desktop_config.json</code>
</p>
<p class="text-xs text-slate-500 mb-2">
<strong class="text-slate-400">Windows:</strong>
<code>%APPDATA%\Claude\claude_desktop_config.json</code>
</p>
<pre class="text-xs">{
"mcpServers": {
"headless-oracle": {
"url": "https://headlessoracle.com/mcp"
}
}
}</pre>
<p class="text-xs text-slate-500 mt-2">After restarting Claude Desktop, Headless Oracle tools will appear automatically. No API key required for the demo tools.</p>
<h3 class="mt-6">Example Prompts</h3>
<p class="text-sm text-slate-400 mb-3">Try these after setup:</p>
<ul class="list-none space-y-2 text-sm text-slate-400">
<li><span class="text-slate-600 mr-2">›</span><em>"Is the NYSE open right now?"</em></li>
<li><span class="text-slate-600 mr-2">›</span><em>"Check if any Asian markets are currently in their lunch break"</em></li>
<li><span class="text-slate-600 mr-2">›</span><em>"What time does the London Stock Exchange close today?"</em></li>
<li><span class="text-slate-600 mr-2">›</span><em>"Are there any market holidays this week across all exchanges?"</em></li>
<li><span class="text-slate-600 mr-2">›</span><em>"Before I execute this trade — verify XNYS is open and give me the signed receipt"</em></li>
</ul>
<h3 class="mt-6">Key Provenance</h3>
<p class="text-sm text-slate-400">The Ed25519 public key for verifying receipts returned by MCP tools is published at <a href="/.well-known/oracle-keys.json" class="text-blue-400 underline">/.well-known/oracle-keys.json</a> (RFC 8615 standard).</p>
</section>
<!-- API KEYS & BILLING -->
<section id="billing" class="mb-12 border-b border-slate-800 pb-12">
<h2>API Keys & Billing</h2>
<p class="text-slate-400 mb-4">
Production access to <code>/v5/status</code>, <code>/v5/batch</code>, and <code>/v5/account</code> requires an API key passed in the <code>X-Oracle-Key</code> header. All other endpoints are public.
</p>
<h3>Get an API Key</h3>
<p class="text-sm mb-4 text-slate-400">Subscribe via anonymous Paddle checkout — no account creation required. Your API key is emailed to you after payment and is shown once.</p>
<pre class="text-blue-300">curl -X POST https://headlessoracle.com/v5/checkout
# Returns: { "url": "https://checkout.paddle.com/..." }
# Redirect the user (or open the URL) to complete payment.</pre>
<p class="text-xs text-slate-500 mt-2">Keys are prefixed <code>ok_live_</code> for easy identification in logs and environment variables.</p>
<h3 class="mt-6">Check Your Account</h3>
<pre class="text-blue-300">curl https://headlessoracle.com/v5/account \
-H "X-Oracle-Key: YOUR_API_KEY"
# Returns: { "plan": "pro", "status": "active", "key_prefix": "ok_live_..." }</pre>
<h3 class="mt-6">Error Codes</h3>
<ul class="list-disc pl-5 space-y-2 text-slate-400 text-sm">
<li><strong class="text-red-400">401 API_KEY_REQUIRED:</strong> No key in header.</li>
<li><strong class="text-red-400">403 INVALID_API_KEY:</strong> Key not found. Check for typos or use <code>/v5/account</code> to confirm it's active.</li>
<li><strong class="text-yellow-400">402 PAYMENT_REQUIRED:</strong> Subscription is suspended or cancelled. Update billing to restore access.</li>
</ul>
</section>
<!-- OPEN STANDARDS -->
<section id="standards" class="mb-12 border-b border-slate-800 pb-12">
<h2>Open Standards</h2>
<p class="text-slate-400 text-sm mb-6">Headless Oracle publishes the protocols it implements as Apache 2.0 open standards. Any operator can implement these independently — the value is in the interoperability, not the lock-in.</p>
<div class="space-y-4">
<div class="glass rounded-xl p-5 border border-blue-500/20">
<div class="flex items-start justify-between gap-4 mb-2">
<div>
<span class="text-xs font-mono text-blue-400 uppercase tracking-wider">SMA Protocol</span>
<h3 class="text-white font-semibold mt-1 mb-0">Signed Market Attestation</h3>
</div>
<a href="https://github.com/LembaGang/sma-protocol" target="_blank" rel="noopener" class="text-xs font-mono text-blue-400 hover:text-blue-300 whitespace-nowrap">GitHub →</a>
</div>
<p class="text-sm text-slate-400 mb-2">Defines the canonical JSON schema for a cryptographically signed market-state receipt: fields, Ed25519 signing algorithm, canonical payload serialisation (alphabetical key sort), 60-second TTL, and fail-closed UNKNOWN semantics.</p>
<div class="flex gap-3 flex-wrap">
<a href="https://headlessoracle.com/docs/sma-protocol/rfc-001" class="text-xs text-blue-400 hover:text-blue-300">RFC-001 (hosted) →</a>
<a href="https://headlessoracle.com/v5/compliance" class="text-xs text-slate-400 hover:text-white font-mono">/v5/compliance →</a>
<a href="https://headlessoracle.com/v5/conformance-vectors" class="text-xs text-slate-400 hover:text-white font-mono">/v5/conformance-vectors →</a>
</div>
</div>
<div class="glass rounded-xl p-5 border border-purple-500/20">
<div class="flex items-start justify-between gap-4 mb-2">
<div>
<span class="text-xs font-mono text-purple-400 uppercase tracking-wider">MPAS-1.0</span>
<h3 class="text-white font-semibold mt-1 mb-0">Multi-Party Attestation Aggregation</h3>
</div>
<a href="https://github.com/LembaGang/mpas-spec" target="_blank" rel="noopener" class="text-xs font-mono text-purple-400 hover:text-purple-300 whitespace-nowrap">GitHub →</a>
</div>
<p class="text-sm text-slate-400 mb-2">Defines how N independent oracle operators' SMA receipts are aggregated into a single <code>AggregatedAttestation</code> with quorum consensus. A 2-of-3 quorum means no single compromised operator can produce a forged result. Includes consumer verification algorithm, operator registration conventions, and on-chain verification sketch.</p>
<div class="flex gap-3 flex-wrap">
<a href="https://headlessoracle.com/docs/mpas" class="text-xs text-purple-400 hover:text-purple-300">Spec (hosted) →</a>
<a href="https://github.com/LembaGang/mpas-spec/blob/main/IMPLEMENTATIONS.md" target="_blank" rel="noopener" class="text-xs text-slate-400 hover:text-white">IMPLEMENTATIONS.md →</a>
</div>
</div>
<div class="glass rounded-xl p-5 border border-green-500/20">
<div class="flex items-start justify-between gap-4 mb-2">
<div>
<span class="text-xs font-mono text-green-400 uppercase tracking-wider">APTS-1.0</span>
<h3 class="text-white font-semibold mt-1 mb-0">Agent Pre-Trade Safety Standard</h3>
</div>
<a href="https://github.com/LembaGang/agent-pretrade-safety-standard" target="_blank" rel="noopener" class="text-xs font-mono text-green-400 hover:text-green-300 whitespace-nowrap">GitHub →</a>
</div>
<p class="text-sm text-slate-400 mb-2">A vendor-neutral 6-step checklist every autonomous trading agent must complete before executing: fetch signed attestation → verify circuit breakers → verify settlement window → verify TTL → verify Ed25519 signature → halt on any failure. Includes CI badge, CHECKLIST.yaml, and conformance table.</p>
<div class="flex gap-3 flex-wrap">
<a href="https://headlessoracle.com/v5/compliance" class="text-xs text-slate-400 hover:text-white font-mono">/v5/compliance →</a>
</div>
</div>
</div>
</section>
<!-- OVERRIDES -->
<section id="overrides">
<h2>Circuit Breaker Overrides</h2>
<p class="text-slate-400 mb-4">
The <code>OVERRIDE</code> source tier allows manual status injection — used to broadcast HALTED during exchange circuit breakers, emergency closures, or scheduled maintenance windows.
</p>
<p class="text-sm text-slate-400 mb-4">
When an override is active, the receipt includes a <code>reason</code> field explaining the override:
</p>
<pre class="text-xs">{
"receipt_id": "uuid-v4",
"issued_at": "2026-03-09T19:30:00.000Z",
"expires_at": "2026-03-09T19:31:00.000Z",
"mic": "XNYS",
"status": "HALTED",
"source": "OVERRIDE",
"reason": "NYSE circuit breaker Level 1 triggered",
"schema_version": "v5.0",
"public_key_id": "key_2026_v1",
"signature": "hex_string"
}</pre>
<p class="text-sm text-slate-500 mt-4">
Override receipts are signed with the same Ed25519 key as schedule-based receipts. Verification logic is identical. Your bot does not need to handle overrides differently — treat HALTED identically to CLOSED.
</p>
</section>
</div>
</main>
<footer class="border-t border-slate-800 py-12 text-center text-slate-500 text-sm">
<a href="/" class="hover:text-white">Home</a> •
<a href="/docs" class="hover:text-white">Docs</a> •
<a href="/pricing" class="hover:text-white">Pricing</a> •
<a href="/standards" class="hover:text-white">Standards</a> •
<a href="/blog" class="hover:text-white">Blog</a> •
<a href="/llms.txt" class="hover:text-white">llms.txt</a> •
<a href="/terms" class="hover:text-white">Terms</a> •
<a href="/privacy" class="hover:text-white">Privacy</a> •
<a href="https://github.com/LembaGang" class="hover:text-white" target="_blank" rel="noopener">GitHub</a>
</footer>
<script src="https://cdn.paddle.com/paddle/v2/paddle.js"></script>
<script src="/js/paddle-init.js"></script>
</body>
</html>