ODEN is a plain HTTPS endpoint that sends and receives JSON. No SDK is required — it works from any language with an standard HTTP client. If you prefer a structured, typed wrapper with built-in retries, copy one of these production-ready clients.
Synchronous Python client#
A single-file client with retry and typing. Drop it in as oden.py:
import os, time
from dataclasses import dataclass
import requests
@dataclass
class Citation:
title: str
url: str
score: float
snippet: str | None = None
class Oden:
def __init__(self, key: str | None = None, base: str = "https://api.oden-api.com"):
self.key = key or os.environ["ODEN_KEY"]
self.base = base
def search(self, query: str, *, answer: bool = True, depth: str = "advanced",
include_snippets: bool = False, retries: int = 3) -> dict:
body = {"query": query, "answer": answer, "depth": depth,
"include_snippets": include_snippets}
for attempt in range(retries + 1):
r = requests.post(
f"{self.base}/search",
headers={"Authorization": f"Bearer {self.key}"},
json=body, timeout=30,
)
if r.status_code == 429 and attempt < retries:
time.sleep(2 ** attempt)
continue
r.raise_for_status()
return r.json()
# Usage
oden = Oden()
data = oden.search("what is retrieval-augmented generation", include_snippets=True)
print(data["results"]["answer"])
Asynchronous Python client (httpx)#
For high-throughput async services built on FastAPI, Litestar, or AsyncIO agent loops:
import os, asyncio
import httpx
class AsyncOden:
def __init__(self, key: str | None = None, base: str = "https://api.oden-api.com"):
self.key = key or os.environ["ODEN_KEY"]
self.base = base
async def search(self, query: str, *, answer: bool = True, depth: str = "advanced",
include_snippets: bool = False, timeout: float = 25.0, retries: int = 3) -> dict:
payload = {"query": query, "answer": answer, "depth": depth, "include_snippets": include_snippets}
headers = {"Authorization": f"Bearer {self.key}"}
async with httpx.AsyncClient(timeout=timeout) as client:
for attempt in range(retries + 1):
res = await client.post(f"{self.base}/search", headers=headers, json=payload)
if res.status_code == 429 and attempt < retries:
await asyncio.sleep((2 ** attempt) + 0.5)
continue
res.raise_for_status()
return res.json()
raise RuntimeError("Async search failed: retries exhausted")
TypeScript client with timeout & abort signal#
A zero-dependency TypeScript client designed for Node 18+, Bun, Deno, and Next.js:
export interface OdenCitation {
title: string;
url: string;
score: number;
snippet?: string;
}
export interface OdenResponse {
query: string;
trace_id: string;
cached: boolean;
results: {
answer?: string;
citations: OdenCitation[];
};
}
export class Oden {
private key: string;
private base: string;
constructor(key?: string, base = "https://api.oden-api.com") {
this.key = key || process.env.ODEN_KEY || "";
this.base = base;
if (!this.key) throw new Error("Missing ODEN_KEY");
}
async search(
query: string,
opts: { answer?: boolean; depth?: "advanced" | "basic"; includeSnippets?: boolean; timeoutMs?: number } = {}
): Promise<OdenResponse> {
const { answer = true, depth = "advanced", includeSnippets = false, timeoutMs = 25000 } = opts;
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const resp = await fetch(`${this.base}/search`, {
method: "POST",
headers: {
Authorization: `Bearer ${this.key}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
query,
answer,
depth,
include_snippets: includeSnippets,
}),
signal: controller.signal,
});
if (!resp.ok) {
const err = await resp.json().catch(() => ({}));
throw new Error(`ODEN error ${resp.status}: ${err.message || resp.statusText}`);
}
return resp.json() as Promise<OdenResponse>;
} finally {
clearTimeout(timer);
}
}
}
Terminal CLI bash helper#
Add this shell function to your ~/.bashrc or ~/.zshrc for instant command-line search lookups:
oden() {
curl -s -X POST "https://api.oden-api.com/search" \
-H "Authorization: Bearer $ODEN_KEY" \
-H "Content-Type: application/json" \
-d "{\"query\": \"$*\", \"answer\": true}" | jq -r '.results.answer'
}
# Usage: oden What is the EU Artificial Intelligence Act?
Any other language#
If your language or environment can issue an HTTPS POST request with a JSON payload and an Authorization header, it integrates with ODEN seamlessly. See the Search endpoint for the HTTP specification and OpenAPI specification for code generation tools.
Next steps#
- Quickstart — the same calls, inline.
- Use cases — ODEN inside RAG, LangChain, LlamaIndex and tool-use loops.