API Documentation
Everything you need to integrate AIHub into your applications.
OpenAI-compatible API
AIHub is fully compatible with the OpenAI API format. If you already use OpenAI, migration takes less than a minute — just swap the base URL and API key.
Quickstart
Get started with AIHub in just a few lines of code.
1. Get your API key
Go to the API Keys page and create a new key. Keep it secret — never commit it to version control.
sk-aihub-••••••••••••••••••••••••••••••••Keep secret2. Install the SDK (optional)
npm install @aihub/sdk3. Make your first request
import { AIHub } from '@aihub/sdk';
const client = new AIHub({
apiKey: process.env.AIHUB_API_KEY,
defaultHeaders: {
'HTTP-Referer': '<YOUR_SITE_URL>', // Optional
'X-AIHub-Title': '<YOUR_SITE_NAME>', // Optional
},
});
const completion = await client.chat.send({
model: 'openai/gpt-4o',
messages: [
{
role: 'user',
content: 'What is the meaning of life?',
},
],
stream: false,
});
console.log(completion.choices[0].message.content);The HTTP-Referer and X-AIHub-Title headers are optional but recommended — they help with analytics and attribution.
Authentication
All API requests must include your API key in the Authorization header using the Bearer scheme.
Authorization: Bearer <YOUR_API_KEY>Example with fetch
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer sk-aihub-xxxxxxxxxxxxxxxxxxxx',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Hello!' }],
}),
});Hardcode your API key in client-side JavaScript or commit it to a public repository.
Store your key in an environment variable (AIHUB_API_KEY) and access it server-side only.
Models
AIHub gives you access to hundreds of AI models from leading providers through a single unified endpoint.
| Model ID | Provider | Context | Input / 1M tokens |
|---|---|---|---|
| openai/gpt-4o | OpenAI | 128k | $5.00 |
| openai/gpt-4o-mini | OpenAI | 128k | $0.15 |
| anthropic/claude-3.5-sonnet | Anthropic | 200k | $3.00 |
| google/gemini-1.5-pro | 1M | $3.50 | |
| meta-llama/llama-3.1-70b | Meta | 128k | $0.52 |
| mistralai/mistral-large | Mistral AI | 128k | $2.00 |
Listing Models
const response = await fetch('https://api.aihub.io/v1/models', {
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
},
});
const { data } = await response.json();
console.log(data); // Array of available modelsSelecting a Model
Pass the model ID in the model field of your request. Use the format provider/model-name.
// Use any model by its ID
const body = {
model: 'anthropic/claude-3.5-sonnet', // or 'openai/gpt-4o', etc.
messages: [{ role: 'user', content: 'Hello!' }],
};Chat Completions
The POST /v1/chat/completions endpoint is the core of the AIHub API.
Basic Request
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'Explain quantum computing in simple terms.' },
],
temperature: 0.7,
max_tokens: 1024,
}),
});
const data = await response.json();
console.log(data.choices[0].message.content);Streaming
Set stream: true to receive tokens as they are generated via Server-Sent Events.
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Tell me a short story.' }],
stream: true,
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
const chunk = decoder.decode(value);
const lines = chunk.split('\n').filter(line => line.startsWith('data: '));
for (const line of lines) {
const json = line.replace('data: ', '');
if (json === '[DONE]') break;
const parsed = JSON.parse(json);
process.stdout.write(parsed.choices[0]?.delta?.content || '');
}
}Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| model | string | required | ID of the model to use (e.g. openai/gpt-4o). |
| messages | array | required | Array of message objects with role and content. |
| stream | boolean | optional | If true, tokens are streamed via SSE. |
| temperature | number | optional | Sampling temperature between 0 and 2. Default: 1. |
| max_tokens | integer | optional | Maximum number of tokens to generate. |
| top_p | number | optional | Nucleus sampling probability. Default: 1. |
| stop | string | array | optional | Stop sequences to end generation. |
Multimodal
Text, images, audio, files — all through one API.
Vision — Image Input
Send images alongside text to vision-capable models. Images can be provided as a public URL or as a base64-encoded string.
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [
{
role: 'user',
content: [
{
type: 'text',
text: 'What is in this image? Describe it in detail.',
},
{
type: 'image_url',
image_url: {
url: 'https://example.com/photo.jpg',
detail: 'high', // 'low' | 'high' | 'auto'
},
},
],
},
],
max_tokens: 1024,
}),
});
const data = await response.json();
console.log(data.choices[0].message.content);Image detail levels
lowFaster & cheaper. Resizes image to 512×512. Good for simple tasks.
highFull resolution analysis. Uses more tokens. Best for detailed inspection.
autoModel decides based on image size. Recommended default.
Image Generation
Generate images from text prompts using POST /v1/images/generations.
const response = await fetch('https://api.aihub.io/v1/images/generations', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/dall-e-3', // or 'stability/stable-diffusion-xl'
prompt: 'A futuristic city at sunset, cyberpunk style, ultra-detailed, 8k',
n: 1, // number of images (1–4)
size: '1024x1024', // '256x256' | '512x512' | '1024x1024' | '1792x1024' | '1024x1792'
quality: 'hd', // 'standard' | 'hd'
style: 'vivid', // 'vivid' | 'natural'
response_format: 'url', // 'url' | 'b64_json'
}),
});
const data = await response.json();
console.log(data.data[0].url); // Image URL| Parameter | Type | Description |
|---|---|---|
| model | string | openai/dall-e-3, openai/dall-e-2, stability/sdxl, etc. |
| prompt | string | Text description of the image to generate. |
| n | integer | Number of images to generate (1–4). Default: 1. |
| size | string | 256x256 | 512x512 | 1024x1024 | 1792x1024 | 1024x1792 |
| quality | string | standard | hd. HD uses more tokens. |
| style | string | vivid (dramatic) | natural (realistic). DALL-E 3 only. |
| response_format | string | url (default) | b64_json |
Audio — TTS & Speech-to-Text
Convert text to speech or transcribe audio files to text.
// Text-to-Speech
const response = await fetch('https://api.aihub.io/v1/audio/speech', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/tts-1-hd',
input: 'Hello! Welcome to AIHub, your unified AI gateway.',
voice: 'nova', // 'alloy' | 'echo' | 'fable' | 'onyx' | 'nova' | 'shimmer'
speed: 1.0, // 0.25 – 4.0
response_format: 'mp3', // 'mp3' | 'opus' | 'aac' | 'flac' | 'wav'
}),
});
// Save audio to file
const buffer = await response.arrayBuffer();
fs.writeFileSync('output.mp3', Buffer.from(buffer));File & Document Analysis
Send PDFs, spreadsheets, or other documents to models with large context windows for analysis, summarization, or Q&A.
// Send a PDF or document for analysis
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'google/gemini-1.5-pro', // Models with large context windows work best
messages: [
{
role: 'user',
content: [
{ type: 'text', text: 'Summarize the key points of this document.' },
{
type: 'file',
file: {
url: 'https://example.com/report.pdf',
mime_type: 'application/pdf',
},
},
],
},
],
}),
});Supported Models by Modality
| Model | Text | Vision | Image Gen | Audio | Files |
|---|---|---|---|---|---|
| openai/gpt-4o | |||||
| openai/gpt-4o-mini | |||||
| openai/dall-e-3 | |||||
| openai/tts-1-hd | |||||
| openai/whisper-1 | |||||
| anthropic/claude-3.5-sonnet | |||||
| google/gemini-1.5-pro | |||||
| stability/stable-diffusion-xl |
Advanced Parameters
Fine-tune model behavior with precision.
Below is a complete request body showing every available parameter with inline comments.
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
// ── Core ──────────────────────────────────────────
model: 'openai/gpt-4o',
messages: [
{ role: 'system', content: 'You are a concise technical assistant.' },
{ role: 'user', content: 'Explain REST APIs.' },
],
// ── Sampling ──────────────────────────────────────
temperature: 0.7, // 0–2. Controls randomness. Default: 1
top_p: 0.9, // 0–1. Nucleus sampling. Default: 1
top_k: 40, // Integer. Top-K sampling (model-dependent)
min_p: 0.05, // Minimum probability threshold
// ── Output length ─────────────────────────────────
max_tokens: 2048, // Max tokens to generate
max_completion_tokens: 2048, // Alias for max_tokens (newer models)
// ── Repetition control ────────────────────────────
frequency_penalty: 0.3, // -2 to 2. Penalizes repeated tokens
presence_penalty: 0.2, // -2 to 2. Penalizes tokens already used
repetition_penalty: 1.1, // >1 discourages repetition (some models)
// ── Stop sequences ────────────────────────────────
stop: ['###', '\n\n---'], // Stop generation at these strings
// ── Streaming ─────────────────────────────────────
stream: false, // true = SSE streaming
stream_options: {
include_usage: true, // Include token usage in final SSE chunk
},
// ── Reproducibility ───────────────────────────────
seed: 42, // Integer. Same seed = same output (best-effort)
// ── Logprobs ──────────────────────────────────────
logprobs: true, // Return log probabilities
top_logprobs: 5, // Number of top tokens to return logprobs for
// ── Response format ───────────────────────────────
response_format: {
type: 'json_object', // 'text' | 'json_object' | 'json_schema'
},
// ── Tools / Function calling ──────────────────────
tools: [
{
type: 'function',
function: {
name: 'get_weather',
description: 'Get current weather for a city',
parameters: {
type: 'object',
properties: {
city: { type: 'string', description: 'City name' },
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['city'],
},
},
},
],
tool_choice: 'auto', // 'none' | 'auto' | { type: 'function', function: { name: '...' } }
}),
});Temperature
Controls the randomness of the output. Range: 0 – 2. Default: 1. Lower values produce more focused, deterministic responses; higher values produce more creative, varied outputs.
0 – 0.3
Precise
Factual Q&A, code generation, data extraction
0.5 – 0.9
Balanced
Summarization, translation, chat assistants
1.0 – 2.0
Creative
Storytelling, brainstorming, poetry
// Low temperature → focused, deterministic
const precise = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'What is 2 + 2?' }],
temperature: 0.1, // Near 0: very deterministic
}),
});
// High temperature → creative, varied
const creative = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Write a poem about the ocean.' }],
temperature: 1.4, // Higher: more creative and varied
}),
}Top P & Top K
| Parameter | Range | Default | Description |
|---|---|---|---|
| top_p | 0 – 1 | 1 | Nucleus sampling. Only considers tokens whose cumulative probability ≥ top_p. Lower = more focused. |
| top_k | 1 – ∞ | model default | Only considers the top K most likely tokens at each step. Lower = more deterministic. |
| min_p | 0 – 1 | 0 | Minimum probability threshold relative to the top token. Filters out very unlikely tokens. |
Best practice: Adjust either temperature or top_p, not both simultaneously. Combining them can produce unpredictable results.
Repetition Penalties
| Parameter | Range | Default | Description |
|---|---|---|---|
| frequency_penalty | -2 to 2 | 0 | Penalizes tokens proportionally to how often they have appeared. Reduces word repetition. |
| presence_penalty | -2 to 2 | 0 | Penalizes tokens that have appeared at all (binary). Encourages topic diversity. |
| repetition_penalty | > 0 | 1 | Multiplicative penalty. Values > 1 discourage repetition; < 1 encourage it. (Some models only) |
Streaming (SSE) — Advanced
Full streaming implementation with usage tracking and proper error handling.
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Write a detailed essay on AI.' }],
stream: true,
stream_options: { include_usage: true }, // Get token count at the end
}),
});
const reader = response.body!.getReader();
const decoder = new TextDecoder();
let fullText = '';
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = decoder.decode(value).split('\n');
for (const line of lines) {
if (!line.startsWith('data: ')) continue;
const raw = line.slice(6);
if (raw === '[DONE]') {
console.log('\n\nStream complete. Full text:', fullText);
break;
}
try {
const chunk = JSON.parse(raw);
const delta = chunk.choices?.[0]?.delta;
if (delta?.content) {
fullText += delta.content;
process.stdout.write(delta.content); // Real-time output
}
// Final chunk includes usage when stream_options.include_usage = true
if (chunk.usage) {
console.log('\nTokens used:', chunk.usage);
}
} catch (_) { /* skip malformed lines */ }
}
}Tools & Function Calling
Allow the model to call external functions. The model decides when to call a tool and returns structured arguments you can execute.
// Step 1: Send request with tools defined
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'What is the weather in Paris right now?' }],
tools: [{
type: 'function',
function: {
name: 'get_weather',
description: 'Returns current weather for a given city',
parameters: {
type: 'object',
properties: {
city: { type: 'string' },
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['city'],
},
},
}],
tool_choice: 'auto',
}),
});
const data = await response.json();
const toolCall = data.choices[0].message.tool_calls?.[0];
if (toolCall) {
const args = JSON.parse(toolCall.function.arguments);
// Step 2: Execute your function
const weatherResult = await getWeather(args.city, args.unit);
// Step 3: Send result back to the model
const followUp = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [
{ role: 'user', content: 'What is the weather in Paris right now?' },
data.choices[0].message,
{
role: 'tool',
tool_call_id: toolCall.id,
content: JSON.stringify(weatherResult),
},
],
}),
});
const final = await followUp.json();
console.log(final.choices[0].message.content);
}System Prompt
The system role message sets the model's behavior, persona, and constraints for the entire conversation.
const messages = [
{
role: 'system',
content: `You are a senior TypeScript engineer.
Rules:
- Always use strict TypeScript types, never use 'any'.
- Prefer functional patterns over classes.
- Keep responses concise and include code examples.
- If unsure, say so rather than guessing.`,
},
{ role: 'user', content: 'How do I type a generic fetch wrapper?' },
];Seed & Reproducibility
Set seed to an integer to get deterministic outputs. Same seed + same inputs = same output (best-effort, not guaranteed across model updates).
// Reproducible generation
const body = {
model: 'openai/gpt-4o',
messages: [{ role: 'user', content: 'Give me a random number between 1 and 100.' }],
seed: 42,
temperature: 0,
};
// The system_fingerprint in the response tells you if the model changed
// { ..., "system_fingerprint": "fp_44709d6fcb" }Structured Output (JSON Mode)
Force the model to return valid JSON by setting response_format.
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: { 'Authorization': 'Bearer <YOUR_API_KEY>', 'Content-Type': 'application/json' },
body: JSON.stringify({
model: 'openai/gpt-4o',
messages: [
{
role: 'system',
content: 'You are a data extractor. Always respond with valid JSON.',
},
{
role: 'user',
content: 'Extract: name, email, and company from: "Hi, I am Alice (alice@acme.com) from Acme Corp."',
},
],
response_format: { type: 'json_object' },
temperature: 0,
}),
});
const data = await response.json();
const extracted = JSON.parse(data.choices[0].message.content);
// { name: "Alice", email: "alice@acme.com", company: "Acme Corp" }API Response Format
Understand every field returned by the API.
Chat Completion Response
Full annotated response object from POST /v1/chat/completions.
{
"id": "chatcmpl-abc123xyz",
"object": "chat.completion",
"created": 1720000000,
"model": "openai/gpt-4o",
"system_fingerprint": "fp_44709d6fcb",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The meaning of life is a profound philosophical question...",
"tool_calls": null, // Populated when the model calls a tool
"refusal": null // Non-null if the model refused to answer
},
"logprobs": null, // Populated when logprobs: true
"finish_reason": "stop" // See Finish Reasons section
}
],
"usage": {
"prompt_tokens": 15,
"completion_tokens": 87,
"total_tokens": 102,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
}
}| Field | Type | Description |
|---|---|---|
| id | string | Unique identifier for this completion (chatcmpl-…). |
| object | string | Always "chat.completion" for non-streaming responses. |
| created | integer | Unix timestamp (seconds) when the completion was created. |
| model | string | The model that generated the response. |
| system_fingerprint | string | Identifies the model configuration. Changes when the model is updated. |
| choices | array | Array of completion choices. Usually 1 unless n > 1. |
| choices[].index | integer | Index of this choice (0-based). |
| choices[].message | object | The generated message with role and content. |
| choices[].message.role | string | Always "assistant" in responses. |
| choices[].message.content | string | null | The text content. Null when tool_calls is populated. |
| choices[].message.tool_calls | array | null | Tool calls requested by the model. |
| choices[].message.refusal | string | null | Non-null if the model refused to answer. |
| choices[].logprobs | object | null | Log probabilities. Populated when logprobs: true. |
| choices[].finish_reason | string | Why generation stopped. See Finish Reasons. |
| usage | object | Token usage statistics for this request. |
Streaming Response Chunks
When stream: true, the API sends Server-Sent Events. Each event is a JSON chunk with a delta instead of a full message.
// Each SSE chunk looks like:
data: {
"id": "chatcmpl-abc123xyz",
"object": "chat.completion.chunk",
"created": 1720000000,
"model": "openai/gpt-4o",
"choices": [
{
"index": 0,
"delta": {
"role": "assistant", // Only in the first chunk
"content": "The " // Incremental token(s)
},
"finish_reason": null // null until the last chunk
}
]
}
// ... more chunks ...
// Last content chunk:
data: {
"choices": [{ "delta": { "content": "." }, "finish_reason": null }]
}
// Final chunk (finish_reason set):
data: {
"choices": [{ "delta": {}, "finish_reason": "stop" }],
"usage": { "prompt_tokens": 15, "completion_tokens": 87, "total_tokens": 102 }
}
// Stream end marker:
data: [DONE]Usage Object
The usage object tells you exactly how many tokens were consumed — which directly maps to your billing.
{
"usage": {
"prompt_tokens": 15, // Tokens in your input (messages + system)
"completion_tokens": 87, // Tokens generated by the model
"total_tokens": 102, // prompt_tokens + completion_tokens
// Detailed breakdown (newer models)
"prompt_tokens_details": {
"cached_tokens": 0, // Tokens served from cache (billed at reduced rate)
"audio_tokens": 0 // Audio input tokens
},
"completion_tokens_details": {
"reasoning_tokens": 0, // Internal reasoning tokens (o1 models)
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
}
}Finish Reasons
The finish_reason field tells you why the model stopped generating.
| Value | Meaning | Action |
|---|---|---|
| stop | Model finished naturally or hit a stop sequence. | Normal — response is complete. |
| length | Hit the max_tokens limit before finishing. | Increase max_tokens or summarize context. |
| tool_calls | Model wants to call one or more tools. | Execute the tool and send result back. |
| content_filter | Content was filtered by safety systems. | Revise your prompt or use a different model. |
| null | Streaming: generation is still in progress. | Keep reading chunks until finish_reason is set. |
Tool Call Response
// When the model decides to call a tool, finish_reason = "tool_calls"
{
"id": "chatcmpl-abc123xyz",
"object": "chat.completion",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\"city\": \"Paris\", \"unit\": \"celsius\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
],
"usage": { "prompt_tokens": 82, "completion_tokens": 18, "total_tokens": 100 }
}SDKs & Libraries
Use our official SDK or any OpenAI-compatible library to interact with the AIHub API.
Install the AIHub JavaScript/TypeScript SDK:
npm install @aihub/sdkimport { AIHub } from '@aihub/sdk';
const client = new AIHub({
apiKey: process.env.AIHUB_API_KEY,
defaultHeaders: {
'HTTP-Referer': '<YOUR_SITE_URL>', // Optional
'X-AIHub-Title': '<YOUR_SITE_NAME>', // Optional
},
});
const completion = await client.chat.send({
model: 'openai/gpt-4o',
messages: [
{
role: 'user',
content: 'What is the meaning of life?',
},
],
stream: false,
});
console.log(completion.choices[0].message.content);Error Handling
When an error occurs, the API returns a JSON object with an error field.
{
"error": {
"code": 401,
"message": "Invalid API key. Please check your credentials.",
"type": "authentication_error"
}
}| HTTP Status | Error Type | Description |
|---|---|---|
| 400 | bad_request | Malformed request body or missing required fields. |
| 401 | authentication_error | Invalid or missing API key. |
| 402 | payment_required | Insufficient credits. Top up your balance. |
| 403 | permission_denied | Your key does not have access to this resource. |
| 404 | not_found | The requested model or resource does not exist. |
| 429 | rate_limit_exceeded | Too many requests. Implement exponential backoff. |
| 500 | server_error | Internal server error. Retry after a short delay. |
Handling errors in code
try {
const response = await fetch('https://api.aihub.io/v1/chat/completions', {
method: 'POST',
headers: {
'Authorization': 'Bearer <YOUR_API_KEY>',
'Content-Type': 'application/json',
},
body: JSON.stringify({ model: 'openai/gpt-4o', messages: [...] }),
});
if (!response.ok) {
const error = await response.json();
console.error('API Error:', error.error.message);
// Handle specific error codes
if (response.status === 429) {
console.log('Rate limit hit — please wait before retrying.');
}
return;
}
const data = await response.json();
console.log(data.choices[0].message.content);
} catch (err) {
console.error('Network error:', err);
}Rate Limits
Rate limits are applied per API key and vary by plan. When exceeded, the API returns a 429 status code.
| Plan | Requests / min | Tokens / min | Concurrent |
|---|---|---|---|
| Free | 10 | 40,000 | 2 |
| Starter | 60 | 200,000 | 10 |
| Pro | 300 | 1,000,000 | 50 |
| Enterprise | Custom | Custom | Custom |
Exponential backoff recommended
When you receive a 429, wait 1s, then 2s, then 4s before retrying. Most client libraries handle this automatically.
FAQ
Frequently asked questions about the AIHub API.