TypeScript
A typed helper for creating and polling OptimAI Search from server-side TypeScript.
type SearchMode = "search" | "agent"
type SearchRequest = {
query: string
search_mode?: SearchMode
}
type Search = {
id: string
status: string
result?: {
answer?: string
citations?: Array<{ title?: string; url: string; snippet?: string }>
}
}
const baseUrl = "https://api-onchain.optimai.network/external/v1"
export async function searchOptimAI(
input: SearchRequest,
idempotencyKey: string,
): Promise<Search> {
const apiKey = process.env.OPTIMAI_API_KEY
if (!apiKey) throw new Error("OPTIMAI_API_KEY is required")
const createdResponse = await fetch(`${baseUrl}/search`, {
method: "POST",
headers: {
"X-API-Key": apiKey,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey,
},
body: JSON.stringify(input),
})
if (!createdResponse.ok) {
throw new Error(
`Search creation failed: ${createdResponse.status} ${await createdResponse.text()}`,
)
}
const created = (await createdResponse.json()) as Search
while (true) {
const response = await fetch(`${baseUrl}/search/${created.id}`, {
headers: { "X-API-Key": apiKey },
})
if (!response.ok) {
throw new Error(`Search polling failed: ${response.status} ${await response.text()}`)
}
const search = (await response.json()) as Search
if (search.status === "completed") return search
if (["failed", "cancelled"].includes(search.status)) {
throw new Error(`Search ended with status ${search.status}`)
}
await new Promise((resolve) => setTimeout(resolve, 2_000))
}
}Omit search_mode for Standard Search (1 credit), or set it to "agent" for
longer multi-step web, social, and crypto research (2 credits). Agent mode is
text-only. Use a different idempotency key when changing the request or mode.