# Saikotech AI API Router — usage guide One OpenAI-compatible endpoint for every Saikotech app. You don't pick a provider or a model: the router looks up your app's settings (provider, model, defaults) by its token and routes the request. Admins can change those settings live, without a deploy on your side or ours. Base URL: https://ai.internal.saikotechsolutions.com/v1 ## 1. Get a token Ask an admin for a router token for your app's hostname. Local development uses the shared dev token. Tokens look like `air_…`. Keep it server-side: put it in your backend's env (for example `AI_ROUTER_TOKEN`). Never ship it in frontend code, since anyone could read it and spend the key. ## 2. Call it Any OpenAI SDK works. Set its base URL to `https://ai.internal.saikotechsolutions.com/v1` and its API key to your router token. `model` is required by most SDKs but ignored by the router, so send anything (for example "default"). ### curl curl https://ai.internal.saikotechsolutions.com/v1/chat/completions \ -H "Authorization: Bearer $AI_ROUTER_TOKEN" \ -H "Content-Type: application/json" \ -d '{ "model": "default", "messages": [ {"role": "system", "content": "You are a helpful assistant."}, {"role": "user", "content": "Say hello in Tagalog."} ] }' ### Ruby (official `openai` gem) client = OpenAI::Client.new(api_key: ENV["AI_ROUTER_TOKEN"], base_url: "https://ai.internal.saikotechsolutions.com/v1") completion = client.chat.completions.create( model: "default", messages: [{ role: "user", content: "Say hello in Tagalog." }] ) completion.choices.first.message.content ### JavaScript / TypeScript (`openai` package, server-side only) import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.AI_ROUTER_TOKEN, baseURL: "https://ai.internal.saikotechsolutions.com/v1" }); const completion = await client.chat.completions.create({ model: "default", messages: [{ role: "user", content: "Say hello in Tagalog." }], }); completion.choices[0].message.content; ### Python (`openai` package) from openai import OpenAI client = OpenAI(api_key=os.environ["AI_ROUTER_TOKEN"], base_url="https://ai.internal.saikotechsolutions.com/v1") completion = client.chat.completions.create( model="default", messages=[{"role": "user", "content": "Say hello in Tagalog."}], ) completion.choices[0].message.content ## 3. What's supported Endpoints - POST /v1/chat/completions - GET /v1/models lists the one model your app is routed to Request fields - messages (required) roles: system, developer, user, assistant. content: a string, or an array of {"type": "text"} parts. System/developer messages are combined into one system prompt. - temperature, top_p optional; override your app's defaults - max_tokens / max_completion_tokens - stop string or array of strings Not supported yet (the router answers 400 instead of quietly ignoring them) - stream: true - tools / function calling - images, audio, or other non-text content - response_format other than text (JSON mode) - n greater than 1 Your app's settings may also add a system prompt ahead of yours. ## 4. Responses and errors Successful responses are standard OpenAI chat completions: `choices[0].message.content`, `choices[0].finish_reason` (stop, length, content_filter), and `usage`. Errors use OpenAI's shape: {"error": {"message", "type", "param", "code"}} 400 your request is invalid or uses an unsupported feature (see `param`) 401 missing or wrong token 403 your app is disabled on the router 429 the provider's rate limit or quota was hit. Back off and retry. (Dev uses free-tier keys, so expect this under load.) 502 provider error or router misconfiguration. Not your fault; tell an admin. 504 the provider took too long Every response carries an `X-Request-Id` header. Include it when you report a problem; admins can find the exact request with it. ## 5. Privacy Requests and responses may be logged for debugging (admins can turn this off per app), and dev/demo traffic goes through free-tier provider keys, whose terms let the provider use the data. Don't send real customer or member data through the dev token.