← back to terminal

XISOB TERMINAL · API v3

The same JSON that powers the frontend. Hermes (or any agent) can subscribe to /ws for live push, query /api/agent/ask in natural language, register webhooks, and manage alerts. All /api/* endpoints require a bearer token (or pass ?token=...); local callers from 127.0.0.1 skip auth.

Authentication

Authorization: Bearer demo-token-please-change
# or  ?token=demo-token-please-change

Set the token via env: XISOB_TOKEN=... python3 app.py

Endpoints

GET/api/health
Liveness + counts. No auth required.
GET/api/snapshot
The single endpoint the main UI polls. Returns the full tape (including quiet listings), market stats, official UZSE session phase, FX date, news count, and last refresh. Refreshed every 12 s on the server.
GET/api/coverage
Ticker coverage audit: listed, displayable, live, quiet, missing ticker, missing ISIN, and the quiet ticker list. Useful for Hermes health checks.
GET/api/quote/<ticker>
Single-ticker deep dive: live screener record when traded, daily OHLC history (6 mo), related news, and disclosures payload (OpenInfo report records + PDFs, tagged news, and search fallbacks).
GET/api/disclosures/<ticker>
Per-issuer corporate disclosures: real OpenInfo organization profiles, report pages, and PDF download links from the public v2 API, plus tagged news and external search fallbacks. Lookups use INN first because not every OpenInfo organization exposes an exchange ticker.

OpenInfo report documents public

The terminal reads annual, quarterly, audit, and IFRS records from https://new-api.openinfo.uz/api/v2/reports/... without credentials. Direct media files and generated PDF links are cached per company for 15 minutes.

GET/api/fx
CBU official UZS FX rates, all currencies, with daily diff.
GET/api/indices
UZSE composite index history (daily) + latest value.
GET/api/news
Merged local feed from OpenInfo corporate filings, RSS, and curated Telegram channels. Filters: ?q=, ?ticker=URTS, ?sentiment=positive, ?source=OpenInfo, ?category=corporate, ?type=disclosure, ?limit=100.
GET/api/analytics
Top issuers by transactions, total accounts, total volume/value for today.

Alerts real-time

GET/api/alerts
List all alert rules + recent firings.
POST/api/alerts
Create an alert. Types: price_above, price_below, change_pct, news_keyword.
curl -X POST http://localhost:8000/api/alerts \
  -H "Authorization: Bearer demo-token-please-change" \
  -H "Content-Type: application/json" \
  -d '{"type":"price_above","ticker":"URTS","threshold":9000}'
DEL/api/alerts/<id>
Delete an alert by id.

Webhooks push

POST/api/webhooks
Register a URL to receive POST events when alerts fire.
curl -X POST http://localhost:8000/api/webhooks \
  -H "Authorization: Bearer demo-token-please-change" \
  -H "Content-Type: application/json" \
  -d '{"url":"https://your-server/uzx-hook"}'
When a webhook fires, you'll get a JSON body: {"event":"alert","alert":{...}}
GET/api/webhooks
List registered webhooks.
DEL/api/webhooks/<id>
Delete a webhook.

WebSocket live

ws://localhost:8000/ws?token=demo-token-please-change&channels=screener,news,alerts,fx,indices
# or all channels:
ws://localhost:8000/ws?token=demo-token-please-change

You'll receive JSON frames like: {"channel":"screener","data":{"count":69},"ts":...} on every server-side refresh (every 12 s for the tape, 5 min for news, 30 min for FX). Initial hello + snapshot frame on connect.

Agent — natural language

POST/api/agent/ask
Ask the terminal a question. Returns structured JSON with the answer + raw data Hermes can use.
curl -X POST http://localhost:8000/api/agent/ask \
  -H "Authorization: Bearer demo-token-please-change" \
  -H "Content-Type: application/json" \
  -d '{"q":"what is the biggest mover today?"}'

Recognized queries

PatternReturns
biggest mover, mover, largest changetop absolute % change
gainers, loserstop 10 of each
top volume, top valuetop 5 by volume / value
USD, EUR, RUB, CNY, GBPCBU rate
index, UZSEcomposite index + history
newslatest 10 headlines
any 3–6 letter uppercase token (e.g. URTS)quote for that ticker

Hermes integration example

Subscribe to live tape updates and react to large moves:

import asyncio, json, websockets, requests

TOKEN = "demo-token-please-change"
BASE  = "http://localhost:8000"
WS    = "ws://localhost:8000/ws"

# 1) Get current snapshot
snap = requests.get(f"{BASE}/api/snapshot",
                    headers={"Authorization": f"Bearer {TOKEN}"}).json()
print(f"Traded: {snap['market']['traded_issues']}, "
      f"gainers: {snap['market']['gainers']}, "
      f"losers: {snap['market']['losers']}")

# 2) Ask a question
ans = requests.post(f"{BASE}/api/agent/ask",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={"q": "biggest mover"}).json()
print(ans["answer"], "->", ans["data"]["ticker"])

# 3) Set an alert
alert = requests.post(f"{BASE}/api/alerts",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={"type": "change_pct", "ticker": "URTS", "threshold": 5}).json()
print("alert:", alert["alert"]["id"])

# 4) Register a webhook
hook = requests.post(f"{BASE}/api/webhooks",
    headers={"Authorization": f"Bearer {TOKEN}"},
    json={"url": "https://hermes.example/uzx"}).json()
print("webhook:", hook["webhook"]["id"])

# 5) Stream live updates
async def stream():
    url = f"{WS}?token={TOKEN}"
    async with websockets.connect(url) as ws:
        async for msg in ws:
            m = json.loads(msg)
            if m["channel"] == "screener":
                # re-pull snapshot
                ...

asyncio.run(stream())

Data sources

SourceEndpointWhat
UZSE / OpenInfo/api/v2/iuzse/stock-screener/?mkt_id=STK&page_size=100Live OHLC, per-trade timestamp, change
UZSE / OpenInfo/api/v2/iuzse/stock-screener/?mkt_id=BND&page_size=100Bond tape
UZSE / OpenInfo/api/v2/iuzse/price-indices/UZSE composite index
UZSE / OpenInfo/api/v2/iuzse/trade-analytics/?start_date=...&end_date=...Top issuers by trades
UZSE / OpenInfo/api/v2/iuzse/conclusions/?isu_cd=...&start_date=...&end_date=...Per-issuer daily OHLC history
OpenInfo public v2 APIhttps://new-api.openinfo.uz/api/v2/reports/...Annual, quarterly, audit, and IFRS documents + PDFs (no auth)
UZSE official schedulehttps://www.uzse.uz/exchange/schedule?locale=en09:30 orders, 10:00–15:30 continuous trading, closing execution up to 16:02
CBU (Central Bank)https://cbu.uz/ru/arkhiv-kursov-valyut/json/Official UZS FX rates
RSSuzdaily.uz, gazeta.uz, uza.uzNews headlines
Telegramt.me/s/<channel>Public channel preview (HTML)

XISOB Terminal · local Bloomberg for Uzbek markets · v3 · hisob-kitob (accounting/calculation)