Skip to main content

Python examples

Each example reads your key from the TAURIC_API_KEY environment variable, set as in the quickstart.

Choose a client​

you want touseaddress
read data: quotes, history, filings, macro, newsHTTPX (any HTTP client)https://api.tauric.ai/v1/…
run a full research report on a companyHTTPX, streamed/v1/research/agentic/analyze
ask the managed copilot about the stored dataHTTPX/v1/agents/copilot/runs
run the model with your own messages and toolsthe OpenAI SDK/v1/chat/completions, /v1/responses
find and restore your sessions of a Tauric application (session archive)HTTPX/v1/applications/{application}/sessions
give an agent the data as toolsthe MCP SDK or your MCP clienthttps://mcp.tauric.ai/mcp

The OpenAI SDK covers only model inference; everything else is plain REST. There is no Tauric SDK.

pip install httpx openai "mcp>=2"

Read data​

The REST examples on this page use this client and error helper, which turns the error envelope into an exception:

import os
import httpx

api = httpx.Client(
base_url="https://api.tauric.ai",
headers={"Authorization": f"Bearer {os.environ['TAURIC_API_KEY']}"},
timeout=30.0,
)


def get(path, **params):
response = api.get(path, params=params)
if response.is_error:
error = response.json()["error"]
raise RuntimeError(f"{response.status_code} {error['code']}: {error['message']}")
return response.json()

Data reads need the data entitlement (entitlements).

Find an instrument​

Search by name or ticker to get an instrument's key (find an instrument).

for item in get("/v1/instruments", q="nvidia", limit=3)["data"]:
print(item["key"], item["name"], item["maintenance"]["state"])

Get several quotes at once​

POST /v1/quotes prices any mix of instruments in one request; an instrument key it cannot price is listed under errors (batch quotes).

keys = ["security:AAPL", "fx:EURUSD", "crypto:BTC-USDT", "series:us.treasury.yield_index.10y"]
response = api.post("/v1/quotes", json={"instruments": keys})
response.raise_for_status()
batch = response.json()
for key, quote in batch["quotes"].items():
print(key, quote["price"], quote["instrument"]["currency"], quote["source_time"])
print("not priced:", batch["errors"])

Page back through daily history​

A history read returns the newest window. coverage.continue_end is where the next older window ends, and it is null at the start of the history (price history).

page = get("/v1/securities/AAPL/history", period="1mo")
bars = page["bars"]
if page["coverage"]["continue_end"]:
older = get("/v1/securities/AAPL/history", period="1mo", end=page["coverage"]["continue_end"])
bars = older["bars"] + bars
print(len(bars), bars[0]["date"], bars[-1]["date"], bars[-1]["close"], bars[-1]["status"])

Read company financials​

Values are reported per XBRL concept (us-gaap:…), newest period first, each citing its filing (filings and financials).

facts = get("/v1/securities/MSFT/financials", concepts="us-gaap:NetIncomeLoss,us-gaap:Assets",
period_type="annual", limit=3)
for name, concept in facts["concepts"].items():
for value in concept["values"]:
print(name, value["period_end"], value["value"], concept["unit"], value["form"], value["accession"])

A concept with no value is listed under missing with its reason.

Read macro and rates series​

Series are named by what they measure, and each observation carries its period (economic and market series). GET /v1/series lists every series.

cpi = get("/v1/series/us.cpi.all_items.sa/observations", limit=3)
print(cpi["series"]["name"], cpi["series"]["frequency"], "through", cpi["freshness"]["observed_through"])
for observation in cpi["observations"]:
print(observation["period"]["label"], observation["value"])

Search and read the news​

Search ranks articles by meaning, and each hit's id reads the full article (news and events).

hits = get("/v1/news/search", q="semiconductor export controls", limit=3)["data"]
for hit in hits:
print(hit["article"]["article_time"], hit["article"]["title"])
article = get(f"/v1/news/{hits[0]['article']['id']}")
print(article["title"], article["url"])

Run a research report​

Stream a research run on one company: the run event names it, unnamed data: frames carry the report text, and completion gives the verdict. It uses your AI pool.

import datetime
import json

payload = {"symbol": "MSFT", "date": datetime.date.today().isoformat()}
report, event = [], None
with api.stream("POST", "/v1/research/agentic/analyze", json=payload,
timeout=httpx.Timeout(30.0, read=900.0)) as stream:
for line in stream.iter_lines():
if line.startswith("event: "):
event = line[len("event: "):]
elif line.startswith("data: ") and line != "data: [DONE]":
data = json.loads(line[len("data: "):])
if event == "run":
run_id = data["id"]
elif event == "completion":
print("complete:", data["complete"], data["reason"], data["usage"]["charged_credits"])
elif event is None and "choices" in data:
report.append(data["choices"][0]["delta"].get("content") or "")
elif line == "":
event = None
print(len("".join(report)), "characters, run", run_id)

A completed report is stored: read it again with get(f"/v1/research/runs/{run_id}/report").

Ask the copilot​

The copilot runs its own tools over the stored data, so you send only your message (copilot). The examples reuse the api client from read data, with a longer timeout.

run = api.post("/v1/agents/copilot/runs", json={"input": "What is the 10-year Treasury yield today?"},
timeout=600).json()
print(run["status"], run["x_tauric"]["composition"])
for item in run["output"]:
if item["type"] == "message":
print(item["content"][0]["text"])

composition is explained in answer composition.

To print the answer as it is written, stream the run and read the text deltas:

import json

with api.stream("POST", "/v1/agents/copilot/runs", timeout=600,
json={"input": "How did the 2-year yield move this week?", "stream": True}) as stream:
for line in stream.iter_lines():
if not line.startswith("data: "):
continue
event = json.loads(line[len("data: "):])
if event["type"] == "response.output_text.delta":
print(event["delta"], end="", flush=True)
elif event["type"] in ("response.completed", "response.incomplete", "response.failed"):
print("\n", event["response"]["status"])

Run the model with the OpenAI SDK​

Set the OpenAI SDK's base_url to https://api.tauric.ai/v1; a tool call comes back for your code to run (model inference). This needs the ai entitlement and uses your AI credits.

import os
from openai import OpenAI

# max_retries=0: each retry would be a new charged request
ai = OpenAI(api_key=os.environ["TAURIC_API_KEY"], base_url="https://api.tauric.ai/v1", max_retries=0)
reply = ai.chat.completions.create(
model="tauric",
messages=[{"role": "system", "content": "Answer in one sentence."},
{"role": "user", "content": "What does a yield-curve inversion usually signal?"}],
max_tokens=200,
)
print(reply.choices[0].message.content)
print(reply.usage.completion_tokens, "output tokens")

ai.responses.create(...) works the same way. Model inference covers function tools for both.

Connect an agent over MCP​

The data operations and research runs are also MCP tools (use with AI assistants).

import asyncio
import os
import httpx
from mcp import ClientSession
from mcp.client.streamable_http import streamable_http_client


async def main():
headers = {"Authorization": f"Bearer {os.environ['TAURIC_API_KEY']}"}
async with httpx.AsyncClient(headers=headers, timeout=60) as http:
async with streamable_http_client("https://mcp.tauric.ai/mcp", http_client=http) as (read, write):
async with ClientSession(read, write) as session:
await session.initialize()
tools = await session.list_tools()
print(len(tools.tools), "tools")
result = await session.call_tool("get_security_quote", {"symbol": "AAPL"})
if result.is_error:
print(result.content[0].text)
else:
print(result.structured_content["price"], result.structured_content["source_time"])


asyncio.run(main())

An error result (is_error) carries the typed error as JSON text. A missing or malformed key is refused at the transport, and the SDK raises (tool errors).