Gab AI API endpoint reference: requests, tools and usage
Find request formats, parameters and response examples for text, media, files and account operations.
Choose the request format for your app
Use the format your client expects: Chat Completions, Responses or Messages. The table gives each base URL and endpoint. Authenticated API calls require Plus and applicable credits; Authentication Docs covers access and keys. Use these response shapes as a reference for your integration.
Protocol base URLs and endpoints
| Request format | Client base URL | Request endpoint |
|---|---|---|
| Chat Completions | https://gab.ai/v1 | POST /v1/chat/completions |
| Responses | https://gab.ai/v1 | POST /v1/responses |
| Messages | https://gab.ai for clients that append /v1/messages | POST /v1/messages |
Base URL
Use https://gab.ai/v1 as the base_url / baseURL in OpenAI-compatible SDKs. Individual requests append an endpoint such as /chat/completions. GET https://gab.ai/v1/models lists current model IDs and aliases (authentication optional).
- https://gab.ai/v1
Chat Completions
Generate a response from an AI model based on a conversation history. This is the primary endpoint for text generation and follows the OpenAI chat completions format.
You can pass a tools array and optional tool_choice in the request body (see the table above). Supported models can then request one or more tool calls; you run the tools and send the results back in follow-up requests. Tools are only used when you send tools and the model supports function calling (see model capabilities below).
Assistant messages in messages may include tool_calls: an array of objects with id, type: "function", and function: { name, arguments }. Tool result messages use role: "tool" and must include tool_call_id (matching the id of the corresponding tool call) and content (the tool’s result string).
choices[0].message may include content (string or null) and/or tool_calls (array with the same shape: id, type, function.name, function.arguments). choices[0].finish_reason may be "tool_calls" when the model is requesting tool use (in addition to "stop", "length", etc.).
Stream chunks may include delta.tool_calls (array of tool call deltas). The final chunk may have finish_reason: "tool_calls" when the model is requesting tool use.
Send messages plus optional tools and tool_choice. If the response has finish_reason: "tool_calls" and message.tool_calls, run each tool, append the assistant message (including its tool_calls) to messages, append one message per result with role "tool", tool_call_id, and content, then call the API again with the updated messages. Repeat until finish_reason is "stop" or another non–tool-call reason.
Vision-capable models accept images in the messages array using OpenAI's multimodal content format: a user message's content can be an array of parts, where each part is either {'{ type: "text", text }'} or {'{ type: "image_url", image_url: { url } }'}. The image URL may be a public HTTPS URL, a base64 data URL, or a { file_id } returned by /v1/files.
Use /v1/models to discover vision-capable models — look for capabilities.image_input: true. Passing images to a model that does not support image input returns a 400 unsupported_image_input error.
Pass response_format to constrain output to valid JSON, either freely (json_object) or against a strict JSON Schema (json_schema). The shape uses OpenAI-style structured-output fields; validate the selected model and client.
POST /chat/completions
- Request Body
- Tool and function calling
- Request messages
- Response (non-streaming)
- Response (streaming)
- Multi-turn tool flow
- Image input (vision)
- Structured outputs (JSON mode)
Request Body
model (string, required)
Model ID or alias (e.g. "arya", "gpt-6-sol", "openai/gpt-6-sol", "claude-sonnet-4-5", "anthropic/claude-sonnet-4-5"), or "auto" / "gab/auto" to classify the kickoff. Display names like "Claude Opus 4.8" will not match. GET /v1/models lists ids and aliases. Responses include X-Gab-Routed-Model, X-Gab-Router-Intent, and X-Gab-Router-Coding-Tier when model is auto. The slug Auto maps to each coding tier is configurable and can change — read those headers rather than assuming a particular engine.
messages (array, required)
Array of message objects with role and content. Assistant messages may include tool_calls; tool result messages use role "tool" with tool_call_id and content.
temperature (number, optional)
Sampling temperature (0-2, default 1)
max_tokens (integer, optional)
Maximum tokens to generate
stream (boolean, optional)
Enable streaming responses (default false)
top_p (number, optional)
Nucleus sampling parameter (0-1)
tools (array, optional)
List of tools the model may call. Each item has type: "function" and a function object with name, description, and parameters (JSON Schema). Same structure as OpenAI's tools parameter.
tool_choice (string | object, optional)
How the model should use tools: "auto" (let the model decide), "none" (disable tools), "required", or { type: "function", function: { name: "<tool_name>" } } to force a specific tool.
parallel_tool_calls (boolean, optional)
Forwarded to OpenAI-compatible providers that support parallel tool calls.
reasoning_effort (string, optional)
For reasoning models: "minimal", "low", "medium", or "high". Also accepts reasoning: { effort }. On Anthropic models this is mapped to thinking.budget_tokens.
response_format (object, optional)
Structured output mode. Supports OpenAI's shape: { type: "text" } (default), { type: "json_object" }, or { type: "json_schema", json_schema: { name, strict?, schema } } where schema is a JSON Schema. Best results on models with capabilities.function_calling: true.
web_search (boolean, optional)
Set to true to let the platform perform a live web search for the request and supply the results to the model (with citations). Only takes effect on models that advertise capabilities.web_search: true (for example "arya") — it is ignored for other models. You can also trigger a search without this flag by asking in plain language (e.g. "search the web for ..."); for ordinary questions that merely need fresh information, pass web_search: true explicitly.
web_search_options (object, optional)
OpenAI-compatible alternative to web_search. Providing this object (even an empty {}) enables web search on web-search-capable models, the same as web_search: true.
const response = await fetch('https://gab.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'arya',
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is the capital of France?' }
],
temperature: 0.7,
max_tokens: 1000
})
});{
"id": "chatcmpl-abc123",
"object": "chat.completion",
"created": 1704067200,
"model": "arya",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "The capital of France is Paris."
},
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 25,
"completion_tokens": 12,
"total_tokens": 37,
"credits_used": 1
}
}{
"model": "arya",
"web_search": true,
"messages": [
{ "role": "user", "content": "Where can I watch the new film Citizen Vigilante in Australia?" }
]
}{
"model": "arya",
"messages": [
{ "role": "user", "content": "What is the weather in Paris?" }
],
"tools": [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a location.",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string", "description": "City name" }
},
"required": ["location"]
}
}
}
],
"tool_choice": "auto"
}{
"id": "chatcmpl-xyz",
"object": "chat.completion",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": {
"name": "get_weather",
"arguments": "{\\"location\\": \\"Paris\\"}"
}
}
]
},
"finish_reason": "tool_calls"
}
],
"usage": { "prompt_tokens": 20, "completion_tokens": 25, "total_tokens": 45, "credits_used": 1 }
}{
"model": "arya",
"messages": [
{ "role": "user", "content": "What is the weather in Paris?" },
{
"role": "assistant",
"content": null,
"tool_calls": [
{
"id": "call_abc123",
"type": "function",
"function": { "name": "get_weather", "arguments": "{\\"location\\": \\"Paris\\"}" }
}
]
},
{
"role": "tool",
"tool_call_id": "call_abc123",
"content": "Sunny, 22°C"
}
],
"tools": [
{ "type": "function", "function": { "name": "get_weather", "description": "Get weather for a location.", "parameters": { "type": "object", "properties": { "location": { "type": "string" } }, "required": ["location"] } } }
],
"tool_choice": "auto"
}{
"model": "arya",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "What's in this image?" },
{ "type": "image_url", "image_url": { "url": "https://example.com/photo.jpg" } }
]
}
]
}{
"model": "arya",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "Describe this receipt." },
{ "type": "image_url", "image_url": { "url": "data:image/png;base64,iVBORw0KGgoAAAA..." } }
]
}
]
}{
"model": "arya",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "Summarize this diagram." },
{ "type": "image_url", "image_url": { "file_id": "<FILE_ID_FROM_V1_FILES>" } }
]
}
]
}{
"model": "arya",
"messages": [
{ "role": "system", "content": "Extract the user's name and age. Reply with JSON only." },
{ "role": "user", "content": "Hi, I'm Alice and I'm 30." }
],
"response_format": { "type": "json_object" }
}{
"model": "arya",
"messages": [
{ "role": "user", "content": "Extract the user's name and age from: 'Hi, I'm Alice and I'm 30.'" }
],
"response_format": {
"type": "json_schema",
"json_schema": {
"name": "person",
"strict": true,
"schema": {
"type": "object",
"properties": {
"name": { "type": "string" },
"age": { "type": "integer" }
},
"required": ["name", "age"],
"additionalProperties": false
}
}
}
}Reusing Prompts Across Agent Turns
Send a stable X-Gab-Session-Id for one conversation or agent run. On supported routes, this helps keep successive requests on the same provider so repeated prompt content can reuse its cache. Choose a different value for each independent conversation; use 1–256 characters without control characters. Keep shared instructions and reference material at the beginning of the prompt, with the changing question near the end.
Cache availability depends on the model, provider, prompt size, and cache lifetime. Check usage.prompt_tokens_details.cached_tokens when reported and usage.credits_used for the actual charge. A session ID does not prevent a request from running again. For an identical retry, reuse the same Idempotency-Key and request body; use a new idempotency key for each new agent turn.
X-Gab-Session-Id: conversation-123Read usage and output budgets
Read usage.credits_used for a completed request and GET /v1/usage for API history. API usage is separate from included in-app Chat. The requested output budget can affect credit authorization; choose a reasonable max_tokens and inspect the completed result. Reasoning can consume that output budget.
OpenAI Responses
Gab AI supports OpenAI's newer Responses API shape for Codex-style agent clients and SDKs that use input / output items instead of chat messages. The endpoint maps Responses API function calls onto the same tool-calling pipeline as chat completions.
Streaming responses emit Responses-style events such as response.created, response.output_text.delta, response.function_call_arguments.delta, response.function_call_arguments.done, and response.completed.
Pass previous_response_id to continue a stored turn without resending the full transcript. Retrieve a stored result with GET /v1/responses/{id} (24-hour TTL).
POST /responses
GET /responses/{id}
- Request Body
Request Body
model (string, required)
Model ID such as "arya", "gpt-6-sol", or "claude-sonnet-4-5", or "auto" / "gab/auto". Auto classifies the kickoff and sticks the model across previous_response_id turns. Inspect X-Gab-Routed-Model and X-Gab-Router-Coding-Tier.
input (string | array, optional)
A plain prompt string or Responses API input items: message, function_call, and function_call_output. Required unless previous_response_id is set.
previous_response_id (string, optional)
Continue from a stored Responses result instead of resending the full input. Pair with GET /v1/responses/{id}.
reasoning_effort (string, optional)
"minimal", "low", "medium", or "high". Also accepts reasoning: { effort }.
max_output_tokens (integer, optional)
Maximum output tokens. Also accepts max_tokens for compatibility.
temperature (number, optional)
Sampling temperature.
top_p (number, optional)
Nucleus sampling parameter.
stream (boolean, optional)
Enable Responses-style server-sent events.
tools (array, optional)
Responses API function tools: { type: "function", name, description, parameters }.
tool_choice (string | object, optional)
"auto", "none", "required", or { type: "function", name: "tool_name" }.
web_search (boolean, optional)
Set to true (or pass web_search_options) to let the platform perform a live web search and supply the results to the model with citations. Only takes effect on models with capabilities.web_search: true (for example "arya"); ignored for other models. A plain-language request such as "search the web for ..." also triggers a search.
{
"model": "arya",
"input": [
{
"role": "user",
"content": [
{ "type": "input_text", "text": "What is the weather in Paris?" }
]
}
],
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get weather for a location.",
"parameters": {
"type": "object",
"properties": {
"location": { "type": "string" }
},
"required": ["location"]
}
}
],
"tool_choice": { "type": "function", "name": "get_weather" }
}{
"id": "resp_abc123",
"object": "response",
"status": "completed",
"model": "arya",
"output": [
{
"id": "fc_abc123",
"type": "function_call",
"status": "completed",
"call_id": "call_abc123",
"name": "get_weather",
"arguments": "{\\"location\\":\\"Paris\\"}"
}
],
"usage": {
"input_tokens": 80,
"output_tokens": 25,
"total_tokens": 105,
"credits_used": 1
}
}{
"model": "arya",
"input": [
{
"role": "user",
"content": [{ "type": "input_text", "text": "What is the weather in Paris?" }]
},
{
"id": "fc_abc123",
"type": "function_call",
"call_id": "call_abc123",
"name": "get_weather",
"arguments": "{\\"location\\":\\"Paris\\"}"
},
{
"type": "function_call_output",
"call_id": "call_abc123",
"output": "{\\"temperature\\":22,\\"unit\\":\\"celsius\\",\\"condition\\":\\"sunny\\"}"
}
],
"tools": [
{
"type": "function",
"name": "get_weather",
"description": "Get weather for a location.",
"parameters": {
"type": "object",
"properties": { "location": { "type": "string" } },
"required": ["location"]
}
}
]
}Anthropic Messages
Gab AI also exposes an Anthropic-compatible Messages API for tools and SDKs that expect Anthropic's native format, including Claude Code. Use the root base URL https://gab.ai for Anthropic-compatible clients because they append /v1/messages themselves.
cache_control on system, tools, and content blocks is honored. If the caller does not set a breakpoint, agentic requests auto-mark the last tool (and system text) as ephemeral. Usage includes cache_read_input_tokens when the provider reports a cache hit.
Anthropic-compatible clients may call /v1/messages/count_tokens to estimate input tokens before sending a message. The response returns input_tokens.
POST /messages
POST /messages/count_tokens
- Request Body
- Count Tokens
Request Body
model (string, required)
Model ID. You may use a Gab slug such as "claude-sonnet-4-5", the provider model name such as "claude-sonnet-4-5-20250929", or "auto". When Auto is used, the response model field is the actual routed slug. POST /v1/messages/count_tokens accepts auto without creating route state.
messages (array, required)
Anthropic messages array. User/assistant messages use content blocks; assistant tool requests use type "tool_use"; tool results are user messages with type "tool_result".
system (string | array, optional)
Anthropic system prompt. String content and text blocks are supported. cache_control on blocks is passed through; a string system is auto-marked as a cache breakpoint for agentic requests.
thinking (object, optional)
Anthropic extended thinking, e.g. { type: "enabled", budget_tokens: 8192 }. reasoning_effort on the request is mapped to thinking when this field is omitted.
max_tokens (integer, optional)
Maximum tokens to generate. Forwarded to Claude-compatible models.
temperature (number, optional)
Sampling temperature.
top_p (number, optional)
Nucleus sampling parameter.
top_k (number, optional)
Top-k sampling parameter for Anthropic models.
stream (boolean, optional)
Enable Anthropic-style server-sent events.
tools (array, optional)
Anthropic tool definitions with name, description, and input_schema. cache_control on a tool is passed through. If none is set, the last tool is auto-marked as a cache breakpoint.
tool_choice (object, optional)
Anthropic tool choice, such as { type: "auto" }, { type: "any" }, { type: "none" }, or { type: "tool", name: "tool_name" }.
web_search (boolean, optional)
Set to true (or pass web_search_options) to let the platform perform a live web search and supply the results to the model with citations. Only takes effect on models with capabilities.web_search: true (for example "arya"); ignored for models that lack the capability. A plain-language request such as "search the web for ..." also triggers a search.
export ANTHROPIC_BASE_URL="https://gab.ai"
export ANTHROPIC_AUTH_TOKEN="YOUR_GAB_API_KEY"
claude{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"system": "You are a helpful coding assistant.",
"messages": [
{
"role": "user",
"content": [
{ "type": "text", "text": "Read package.json and summarize the scripts." }
]
}
],
"tools": [
{
"name": "read_file",
"description": "Read a file from the current workspace.",
"input_schema": {
"type": "object",
"properties": {
"path": { "type": "string" }
},
"required": ["path"]
}
}
],
"tool_choice": { "type": "auto" }
}{
"id": "msg_abc123",
"type": "message",
"role": "assistant",
"model": "claude-sonnet-4-5-20250929",
"content": [
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "read_file",
"input": { "path": "package.json" }
}
],
"stop_reason": "tool_use",
"stop_sequence": null,
"usage": {
"input_tokens": 120,
"output_tokens": 32
}
}{
"model": "claude-sonnet-4-5",
"max_tokens": 1024,
"messages": [
{
"role": "user",
"content": [{ "type": "text", "text": "Read package.json and summarize the scripts." }]
},
{
"role": "assistant",
"content": [
{
"type": "tool_use",
"id": "toolu_abc123",
"name": "read_file",
"input": { "path": "package.json" }
}
]
},
{
"role": "user",
"content": [
{
"type": "tool_result",
"tool_use_id": "toolu_abc123",
"content": "{\\"scripts\\":{\\"start\\":\\"node server.js\\"}}"
}
]
}
],
"tools": [
{
"name": "read_file",
"description": "Read a file from the current workspace.",
"input_schema": {
"type": "object",
"properties": { "path": { "type": "string" } },
"required": ["path"]
}
}
]
}curl https://gab.ai/v1/messages/count_tokens \\
-H "Content-Type: application/json" \\
-H "x-api-key: YOUR_GAB_API_KEY" \\
-d '{
"model": "claude-sonnet-4-5",
"messages": [
{ "role": "user", "content": [{ "type": "text", "text": "Hello!" }] }
]
}'Streaming Responses
Set stream: true to receive responses as server-sent events (SSE) for real-time output:
const response = await fetch('https://gab.ai/v1/chat/completions', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'arya',
messages: [{ role: 'user', content: 'Tell me a 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);
// Parse SSE data and handle tokens
console.log(chunk);
}Embeddings
Generate vector embeddings for text inputs. Embeddings are useful for semantic search, retrieval-augmented generation (RAG), clustering, and classification tasks. The endpoint shape mirrors OpenAI's /v1/embeddings.
POST /embeddings
- Request Body
Request Body
model (string, required)
Embedding model ID — must be a slug from /v1/models?type=embedding.
input (string | array, required)
Text to embed. A single string or an array of strings (max 2048 items).
dimensions (integer, optional)
Output vector dimensions. Forwarded to the upstream provider for models that support reduced dimensionality.
encoding_format (string, optional)
Encoding format: "float" (default) or "base64"
curl "https://gab.ai/v1/models?type=embedding" \\
-H "Authorization: Bearer YOUR_API_KEY" \\
| jq '.data[].id'const response = await fetch('https://gab.ai/v1/embeddings', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'text-embedding-3-small',
input: 'The quick brown fox jumps over the lazy dog'
})
});from openai import OpenAI
client = OpenAI(
api_key="YOUR_API_KEY",
base_url="https://gab.ai/v1"
)
response = client.embeddings.create(
model="text-embedding-3-small",
input=["First document", "Second document"]
)
for item in response.data:
print(f"Index {item.index}: {len(item.embedding)} dimensions"){
"object": "list",
"data": [
{
"object": "embedding",
"embedding": [0.0023, -0.0091, 0.0152, ...],
"index": 0
}
],
"model": "text-embedding-3-small",
"usage": {
"prompt_tokens": 9,
"total_tokens": 9,
"credits_used": 1
}
}Check Credits
Check your current credit balance including monthly allotment and purchased credits.
GET /credits
curl https://gab.ai/v1/credits \\
-H "Authorization: Bearer YOUR_API_KEY"{
"object": "credit_balance",
"monthly_credits": 2000,
"monthly_used": 450,
"monthly_remaining": 1550,
"purchased_credits": 500,
"total_available": 2050,
"resets_at": "2026-02-01T00:00:00Z"
}Usage History
Fetch a per-request log of your API usage. Each record is a single billable transaction with its own tx_id, model, token counts and credit cost — useful for auditing billing, building dashboards, or reconciling spend. Records are returned newest-first.
GET /usage
- Query Parameters
Query Parameters
after (string, optional)
tx_id cursor — return records strictly newer than this one. When polling, pass the previous page's first_id (the newest tx in that response, same as data[0].id) — not last_id.
before (string, optional)
tx_id cursor — return records strictly older than this one. Use to walk backward through history.
start_date (string | number, optional)
Inclusive lower bound on created time. ISO 8601 (e.g. "2026-04-01") or unix timestamp (seconds or milliseconds).
end_date (string | number, optional)
Inclusive upper bound on created time. Same formats as start_date.
endpoint (string, optional)
Filter to a specific endpoint, e.g. "/v1/chat/completions".
model (string, optional)
Filter to a specific model slug (e.g. "arya").
limit (integer, optional)
Records per page. 1–1000, default 100.
# Last 100 requests
curl https://gab.ai/v1/usage \\
-H "Authorization: Bearer YOUR_API_KEY"
# Poll for new activity since the last tx_id you've seen
curl "https://gab.ai/v1/usage?after=65f2a1b3c4d5e6f7a8b9c0d1" \\
-H "Authorization: Bearer YOUR_API_KEY"
# All chat.completions usage for March 2026
curl "https://gab.ai/v1/usage?start_date=2026-03-01&end_date=2026-03-31&endpoint=/v1/chat/completions&limit=1000" \\
-H "Authorization: Bearer YOUR_API_KEY"{
"object": "list",
"data": [
{
"id": "65f2a1b3c4d5e6f7a8b9c0d1",
"object": "usage_record",
"created": 1712345678,
"endpoint": "/v1/chat/completions",
"model": "arya",
"credits_used": 1,
"tokens": {
"prompt": 842,
"completion": 156,
"total": 998
},
"context_tokens": 842,
"response_time_ms": 1245,
"status_code": 200,
"success": true
}
],
"has_more": false,
"first_id": "65f2a1b3c4d5e6f7a8b9c0d1",
"last_id": "65f2a1b3c4d5e6f7a8b9c0d1"
}List Models
List all available models. Authentication is optional. Optionally filter by type to get only text, image, video, audio, or embedding models. Each model includes aliases, context_window, max_output_tokens, capabilities, recommended_for, and credit_cost.
GET /models
GET /models/{id}
- Query Parameters
Query Parameters
type (string, optional)
Filter by model type: "text", "image", "video", "audio", or "embedding"
# Get all models (key optional)
curl https://gab.ai/v1/models
# Get only image models
curl "https://gab.ai/v1/models?type=image"
# Look up a slug or alias
curl https://gab.ai/v1/models/gpt-6-sol{
"object": "list",
"data": [
{
"id": "claude-sonnet-4-5",
"object": "model",
"created": 1700000000,
"owned_by": "Anthropic",
"aliases": ["claude-sonnet-4.5", "anthropic/claude-sonnet-4-5", "anthropic/claude-sonnet-4.5"],
"recommended_for": ["coding", "agents"],
"capabilities": {
"text": true,
"streaming": true,
"thinking": true,
"function_calling": true,
"image_input": true
},
"context_window": 200000,
"max_output_tokens": 64000,
"credit_cost": { "base_cost": 5 },
"is_plus_only": true
}
]
}Find setup instructions for your client version
GET /v1/agent-setup provides client examples from the catalog. Match the generated configuration to your installed version: OpenCode v1 uses provider/npm/options, while v2 uses providers/package/settings. GET /openapi.json and /llms-full.txt provide API and model discovery.
curl "https://gab.ai/v1/agent-setup?client=opencode"
curl https://gab.ai/openapi.json
curl https://gab.ai/llms-full.txtImage Generation
Generate images from text prompts using various AI image models. Each item in data includes a public url you can download and an id you can pass to delete the stored copy.
API-generated images are not added to your Gab AI Files library in the app. The UUID in the CDN URL is the storage filename, not the file id — that is why DELETE on the URL filename alone used to fail.
POST /images/generations
DELETE /images/:id
DELETE /images?url=
- Request Body
- Deleting generated media
Request Body
model (string, optional)
Image model slug (e.g., "gpt-image-2", "gpt-image-1-mini", "image-generator", "nano-banana-2", "seedream-4-5", "seedream-4-0", "qwen-image-2", "qwen-image", "flux-2-pro"). Defaults to "gpt-image-1-mini". Use GET /v1/models?type=image for the live list.
prompt (string, required)
Text description of the image to generate. Maximum length is model-specific (characters). If exceeded, the API returns 400 with code prompt_too_long. Use GET /v1/models?type=image and max_prompt_characters on each model (e.g. image-generator: 2,048; gpt-image-2: 32,000).
n (integer, optional)
Number of images to generate (1-4, default 1). Some models cap n=1 internally.
size (string, optional)
Image size, model-dependent. Common values: "1024x1024", "1792x1024", "1024x1792".
quality (string, optional)
Quality level: "standard" (default) or "hd". Forwarded to providers that support it.
const response = await fetch('https://gab.ai/v1/images/generations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'gpt-image-2',
prompt: 'A serene mountain landscape at sunset with a lake reflection',
n: 1,
size: '1024x1024',
quality: 'hd'
})
});{
"created": 1704067200,
"data": [
{
"id": "6650f0a1b2c3d4e5f6a7b8c9",
"url": "https://cdn.gab.ai/users/USER_ID/uploads/30066743-5e4a-4b8c-b4cd-1b41c41caa68.png",
"revised_prompt": "A serene mountain landscape at sunset..."
}
],
"usage": {
"credits_used": 5
}
}curl -X DELETE https://gab.ai/v1/images/6650f0a1b2c3d4e5f6a7b8c9 \
-H "Authorization: Bearer YOUR_API_KEY"
# Same effect via the files endpoint:
curl -X DELETE https://gab.ai/v1/files/6650f0a1b2c3d4e5f6a7b8c9 \
-H "Authorization: Bearer YOUR_API_KEY"
# Older images that only returned a URL — pass the full CDN URL:
curl -G -X DELETE https://gab.ai/v1/images \
-H "Authorization: Bearer YOUR_API_KEY" \
--data-urlencode "url=https://cdn.gab.ai/users/USER_ID/uploads/30066743-5e4a-4b8c-b4cd-1b41c41caa68.png"{
"id": "6650f0a1b2c3d4e5f6a7b8c9",
"object": "image",
"deleted": true
}Image Editing (Reference Images)
Edit one or more existing images from a text prompt — the API equivalent of attaching a reference image in the Gab web UI. Use this endpoint whenever the model advertises capabilities.image_input: true (for example flux-2-pro) and you need the model to see a source image.
Supply source images either as multipart uploads on the image field, or as file id(s) previously returned by POST /v1/files with purpose "vision". CDN URLs and base64 are not accepted on this endpoint; upload first, then pass the file id.
POST /images/edit (also accepts POST /images/edits)
GET /images/edits/:jobId
- Request Body
- Async mode
Request Body
prompt (string, required)
Text description of the edit or reference-guided generation (e.g. "Generate this same character waving").
image (file | string | string[], required)
Source image(s). Multipart: repeat the image field (up to 10). JSON: a file id string, or an array of file ids, from POST /v1/files with purpose "vision".
model (string, optional)
Image model slug. Defaults to "gpt-image-1-mini". Recommended for edits: "gpt-image-1-mini", "gpt-image-2", "nano-banana-2", "flux-2-pro". Use GET /v1/models?type=image for the live list.
n (integer, optional)
Number of edited images to return (1-4, default 1).
size (string, optional)
Output image size. Default: "1024x1024".
quality (string, optional)
"standard" (default) or "hd".
async (boolean, optional)
When true, returns 202 immediately with a job id; poll GET /v1/images/edits/:jobId. background is accepted as an alias. Recommended for longer edits (flux-2-pro, gpt-image-2, large sizes) to avoid gateway timeouts.
# 1) Upload the reference image
curl https://gab.ai/v1/files \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "purpose=vision" \
-F "file=@./character.png"
# -> { "id": "6a69157fce666acc87cba76f", ... }
# 2) Edit / generate with that reference (async recommended)
curl https://gab.ai/v1/images/edit \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_API_KEY" \
-d '{
"model": "flux-2-pro",
"prompt": "Generate this same character waving",
"image": "6a69157fce666acc87cba76f",
"async": true
}'
# -> 202 { "id": "<jobId>", "status": "processing", ... }
# 3) Poll until completed
curl https://gab.ai/v1/images/edits/<jobId> \
-H "Authorization: Bearer YOUR_API_KEY"curl https://gab.ai/v1/images/edit \
-H "Authorization: Bearer YOUR_API_KEY" \
-F "model=flux-2-pro" \
-F "prompt=Generate this same character waving" \
-F "async=true" \
-F "image=@./character.png"const response = await fetch('https://gab.ai/v1/images/edit', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'flux-2-pro',
prompt: 'Generate this same character waving',
image: '6a69157fce666acc87cba76f', // file id from POST /v1/files
async: true
})
});{
"created": 1704067200,
"data": [
{
"id": "6650f0a1b2c3d4e5f6a7b8c9",
"url": "https://cdn.gab.ai/users/USER_ID/uploads/edited123.png",
"revised_prompt": "Generate this same character waving..."
}
],
"usage": {
"credits_used": 5
}
}Files
Upload a file once and reference it by file_id in other API calls — as an image input to /v1/chat/completions, or as the image field on /v1/images/edit. Files are scoped to the authenticated user (the owner of the API key) and are not accessible to other users. The response shape is OpenAI-compatible.
API uploads and API-generated media are not shown in the in-app Files library. GET /v1/files lists those API-created files. Delete generated images with DELETE /v1/images/:id or DELETE /v1/files/:id. Both accept the File id from the generation response, the UUID filename from the CDN URL, or the full CDN URL via ?url=.
Upload a file using multipart/form-data. Returns a file object with an id you can use as file_id in subsequent requests.
List files created through the API for the current user. Optionally filter by purpose.
Retrieve metadata for a single file. fileId may be the File id, the storage filename, or a URL-encoded CDN URL.
Delete a file. Removes the stored object and marks the file as deleted. Any outstanding references (e.g., file_id in a chat message) will fail with file_not_found after deletion.
POST /files
GET /files
GET /files/:fileId
DELETE /files/:fileId
DELETE /images/:id
- Form Fields
- Query Parameters
Form Fields
file (file, required)
The binary file to upload (multipart field "file").
purpose (string, optional)
What the file will be used for: "vision" (image for chat completions or /v1/images/edit), "assistants", "user_data" (default), "batch", or "fine-tune". Purpose "vision" requires an image file.
Query Parameters
limit (integer, optional)
Page size (1-100, default 20).
purpose (string, optional)
Filter by purpose (e.g., "vision").
curl -X POST https://gab.ai/v1/files \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-F "purpose=vision" \\
-F "file=@./photo.png"const form = new FormData();
form.append('purpose', 'vision');
form.append('file', fileBlob, 'photo.png');
const res = await fetch('https://gab.ai/v1/files', {
method: 'POST',
headers: { 'Authorization': 'Bearer YOUR_API_KEY' },
body: form,
});
const uploaded = await res.json();
// uploaded.id — use as file_id in /v1/chat/completions, or as "image" on /v1/images/editfrom openai import OpenAI
client = OpenAI(api_key="YOUR_API_KEY", base_url="https://gab.ai/v1")
uploaded = client.files.create(
file=open("photo.png", "rb"),
purpose="vision",
)
chat = client.chat.completions.create(
model="arya",
messages=[{
"role": "user",
"content": [
{"type": "text", "text": "What's in this image?"},
{"type": "image_url", "image_url": {"file_id": uploaded.id}},
],
}],
)
print(chat.choices[0].message.content){
"id": "67a1b2c3d4e5f6a7b8c9d0e1",
"object": "file",
"bytes": 184523,
"created_at": 1704067200,
"filename": "photo.png",
"purpose": "vision",
"mime_type": "image/png",
"file_type": "image",
"url": "https://cdn.gab.ai/users/abc/files/photo.png",
"status": "active"
}curl "https://gab.ai/v1/files?purpose=vision&limit=50" \\
-H "Authorization: Bearer YOUR_API_KEY"curl https://gab.ai/v1/files/FILE_ID \\
-H "Authorization: Bearer YOUR_API_KEY"curl -X DELETE https://gab.ai/v1/files/FILE_ID \\
-H "Authorization: Bearer YOUR_API_KEY"{ "id": "FILE_ID", "object": "file", "deleted": true }Video Generation
Generate videos from text prompts. Video generation is asynchronous—you'll receive a job ID and poll for the result.
Start a video generation job. Returns a job ID to poll for completion.
Check the status of a video generation job. Poll this endpoint until status is "completed" or "failed".
POST /videos/generations
GET /videos/:jobId
- Request Body
Request Body
model (string, optional)
Video model slug (e.g., "veo-3-1", "veo-3-1-fast", "kling-3-0-pro", "kling-2-5-turbo-pro", "hailuo-2-3-pro", "wan-2-5", "seedance-2-0"). Defaults to "veo-3-1-fast". Use GET /v1/models?type=video for the live list.
prompt (string, required)
Text description of the video to generate
duration (integer, optional)
Video duration in seconds (model dependent)
aspect_ratio (string, optional)
Aspect ratio: "16:9", "9:16", "1:1"
const response = await fetch('https://gab.ai/v1/videos/generations', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'veo-3-1-fast',
prompt: 'A golden retriever running through a field of flowers',
duration: 5,
aspect_ratio: '16:9'
})
});{
"id": "video_job_xyz789",
"object": "video.generation",
"status": "processing",
"created": 1704067200,
"model": "veo-3-1-fast",
"prompt": "A golden retriever running through a field of flowers",
"usage": {
"credits_used": 20
}
}curl https://gab.ai/v1/videos/video_job_xyz789 \\
-H "Authorization: Bearer YOUR_API_KEY"{
"id": "video_job_xyz789",
"object": "video.generation",
"status": "completed",
"created": 1704067200,
"completed_at": 1704067320,
"model": "veo-3-1-fast",
"data": [
{
"id": "6650f0a1b2c3d4e5f6a7b8c9",
"url": "https://cdn.gab.ai/users/USER_ID/uploads/xyz789.mp4",
"duration": 5,
"thumbnail": "https://cdn.gab.ai/videos/thumbnails/xyz789.jpg"
}
]
}Text-to-Speech
Convert text to natural-sounding speech. Unlike OpenAI's TTS endpoint, Gab AI returns a JSON object with a CDN URL to the generated audio (rather than streaming raw audio bytes). You can fetch the URL to download the file.
POST /audio/speech
- Request Body
Request Body
model (string, optional)
TTS model slug. Currently "elevenlabs-tts-v4" (the default if omitted); "elevenlabs-tts-v3", "qwen-audio-3-0-tts-flash" and "gpt-4o-mini-tts" are also available. Use GET /v1/models?type=audio to discover others.
input (string, required)
The text to convert to speech (max 4096 chars)
voice (string, optional)
Voice ID. For elevenlabs-tts-v4: "Rachel" (default), "Roger", "Aria", "Sarah" and other ElevenLabs voices listed by GET /v1/models. For qwen-audio-3-0-tts-flash: "longanhuan_v3.6", "loongjohn". For gpt-4o-mini-tts: "alloy", "ash", "ballad", "coral", "echo", "fable", "nova", "onyx", "sage", "shimmer", "verse".
response_format (string, optional)
Audio format: "mp3" (default), "opus", "aac", "flac".
speed (number, optional)
Speaking speed (0.25 to 4.0, default 1.0)
instructions (string, optional)
Optional voice/style instructions forwarded to the model (e.g., "Speak in a calm, slow voice").
const response = await fetch('https://gab.ai/v1/audio/speech', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer YOUR_API_KEY'
},
body: JSON.stringify({
model: 'elevenlabs-tts-v4',
input: 'Hello! Welcome to Gab AI. How can I help you today?',
voice: 'Rachel',
response_format: 'mp3'
})
});
const { url } = await response.json();
// Fetch the generated audio
const audio = await fetch(url).then(r => r.blob());
const audioUrl = URL.createObjectURL(audio);import requests
resp = requests.post(
"https://gab.ai/v1/audio/speech",
headers={"Authorization": "Bearer YOUR_API_KEY"},
json={
"model": "elevenlabs-tts-v4",
"voice": "Rachel",
"input": "Hello! Welcome to Gab AI.",
},
).json()
# Download the generated audio
with open("output.mp3", "wb") as f:
f.write(requests.get(resp["url"]).content){
"url": "https://cdn.gab.ai/audio/generated/abc123.mp3",
"content_type": "audio/mp3",
"usage": { "credits_used": 1 }
}API Key Management
Programmatically manage your API keys. List existing keys, create new ones, or revoke keys that are no longer needed.
List all API keys associated with your account. Keys are returned with masked values for security.
Create a new API key. The full key is only shown once in the response—store it securely.
Revoke an API key. The key will immediately stop working for all requests.
GET /api-keys
POST /api-keys
DELETE /api-keys/:keyId
- Request Body
Request Body
name (string, optional)
A friendly name for the key (e.g., "Production", "Dev Server")
curl https://gab.ai/v1/api-keys \\
-H "Authorization: Bearer YOUR_API_KEY"{
"object": "list",
"data": [
{
"id": "65f2a1b3c4d5e6f7a8b9c0d1",
"object": "api_key",
"key": "YOUR_GAB_API_KEY",
"name": "Production Key",
"is_active": true,
"created": 1704067200,
"last_used": 1704672000,
"usage": { "requests": 4815, "tokens": 162342 }
},
{
"id": "65f2a1b3c4d5e6f7a8b9c0d2",
"object": "api_key",
"key": "YOUR_GAB_API_KEY",
"name": "Development Key",
"is_active": true,
"created": 1704153600,
"last_used": null,
"usage": { "requests": 0, "tokens": 0 }
}
]
}curl -X POST https://gab.ai/v1/api-keys \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-H "Content-Type: application/json" \\
-d '{"name": "New Production Key"}'{
"id": "65f2a1b3c4d5e6f7a8b9c0d3",
"object": "api_key",
"key": "YOUR_GAB_API_KEY",
"name": "New Production Key",
"is_active": true,
"created": 1704067200,
"message": "Save this key securely. It will not be shown again."
}curl -X DELETE https://gab.ai/v1/api-keys/65f2a1b3c4d5e6f7a8b9c0d1 \\
-H "Authorization: Bearer YOUR_API_KEY"{
"id": "65f2a1b3c4d5e6f7a8b9c0d1",
"object": "api_key",
"deleted": true
}Use the complete issued key
Send the key exactly as issued. Do not add a prefix or try to reconstruct a masked secret. Authentication Docs explains creating, storing and revoking a key.
Account Data Export
Export supported account records as JSON or ZIP, including profile details, conversations, memories, files, custom bots, collections, voice sessions, bookmark folders, automated tasks, purchases, credit purchases, referrals and feedback. Use the export for backups, data portability or your own analysis. The endpoint also powers Settings → Download your data.
The ZIP wraps the same data in a structure that’s easy to browse without writing code. The manifest includes a schema version so consumers can detect breaking changes.
GET /account/export
- Query Parameters
- ZIP Layout (`format=zip`)
Query Parameters
format (string, optional)
Either "json" (default for the developer API — one big JSON document) or "zip" (a user-friendly archive with per-collection JSON files, individual conversation markdown files, a README, and a manifest).
include_messages (boolean, optional)
When set to "false", conversations are returned without their (often very large) messages array. Defaults to true so you get the full archive.
# JSON bundle (default)
curl https://gab.ai/v1/account/export \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-o gab-ai-account-data.json
# ZIP archive (same shape the Settings UI downloads)
curl "https://gab.ai/v1/account/export?format=zip" \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-o gab-ai-account-data.zip
# Slim JSON — metadata only, no message bodies
curl "https://gab.ai/v1/account/export?include_messages=false" \\
-H "Authorization: Bearer YOUR_API_KEY" \\
-o gab-ai-account-data-slim.json{
"object": "account_data_export",
"exported_at": "2026-05-02T18:00:00.000Z",
"user_id": "65f2a1b3c4d5e6f7a8b9c0d1",
"counts": {
"conversations": 412,
"memories": 87,
"files": 23,
"agents": 4,
"collections": 6,
"voice_sessions": 18,
"purchases": 3,
"credit_purchases": 11,
"referrals": 2,
"feedback": 1,
"inference_tasks": 0,
"bookmark_folders": 5,
"api_keys": 2
},
"truncated": {},
"data": {
"user": { "_id": "...", "email": "...", "username": "...", "...": "..." },
"conversations": [ /* full conversation rows with messages */ ],
"memories": [ /* memory rows (embeddings stripped) */ ],
"files": [ /* file metadata + cdn paths */ ],
"agents": [ /* your custom bots */ ],
"collections": [ /* your collections */ ],
"voice_sessions": [ /* voice mode session metadata */ ],
"purchases": [ /* Plus subscription purchases */ ],
"credit_purchases": [ /* one-time credit packs */ ],
"referrals": [ /* referrals you sent or received */ ],
"feedback": [ /* feedback you've submitted */ ],
"inference_tasks": [ /* scheduled / recurring tasks */ ],
"bookmark_folders": [ /* bookmark organization */ ],
"api_keys": [ /* metadata only — secret values are never re-exported */ ]
}
}gab-ai-account-data-2026-05-02.zip
├── README.md # human-readable overview, counts, layout
├── manifest.json # exported_at, counts, truncated, schema_version
├── profile.json # your account profile
├── conversations.json # raw bundle of every conversation
├── conversations/ # one .md file per conversation, easy to read
│ ├── 2026-05-01-untitled-conversation-abc123.md
│ └── ...
├── memories.json # raw memory bundle
├── memories.txt # one memory per line, easy to grep
├── files.json
├── agents.json
├── collections.json
├── voice_sessions.json
├── bookmark_folders.json
├── inference_tasks.json
├── purchases.json
├── credit_purchases.json
├── referrals.json
├── feedback.json
└── api_keys.json # metadata onlyMessage Roles
The messages array in chat completions supports these roles:
system
Sets the behavior and context for the assistant. API requests do NOT inherit the API key owner's profile (name, location, etc.), so if you want the assistant to know who the end user is, describe them here (e.g. "You are chatting with Jane from Austin.").
user
The human user's messages
assistant
Previous AI responses (for context). May include tool_calls: array of { '{ id, type: "function", function: { name, arguments } }' } when using tools.
tool
Tool result messages. Must include tool_call_id (matching the tool call id) and content (the tool’s result string).
- Sets the behavior and context for the assistant. API requests do NOT inherit the API key owner's profile (name, location, etc.), so if you want the assistant to know who the end user is, describe them here (e.g. "You are chatting with Jane from Austin.").
- The human user's messages
- Previous AI responses (for context). May include tool_calls: array of { '{ id, type: "function", function: { name, arguments } }' } when using tools.
- Tool result messages. Must include tool_call_id (matching the tool call id) and content (the tool’s result string).
Error Codes
All errors follow a consistent format with an error object containing message, type, and code:
The error.code field gives a stable machine-readable identifier independent of the HTTP status. The most common ones:
- Common error codes
- 400 — Bad request — Invalid parameters or malformed request
- 401 — Unauthorized — Invalid or missing API key
- 402 — Payment required — Insufficient credits
- 403 — Forbidden — Access denied to this resource
- 404 — Not found — Invalid model, endpoint, or resource
- 429 — Rate limited — Too many requests, check rate limit headers
- 500 — Server error — Internal error, try again later
- 502 — Bad upstream response — e.g. invalid_tool_calls (auto-refunded)
- 503 — Service unavailable — Model temporarily unavailable
- missing_api_key — Authorization header not provided.
- invalid_api_key — API key is invalid or revoked.
- credits_exhausted — No credits remaining on the account.
- plus_required — Model requires a Gab AI Plus subscription.
- rate_limit_exceeded — Daily request limit reached.
- invalid_model — Model not found or disabled.
- unsupported_tool_calling — tools was passed to a model with function_calling: false. Check /v1/models capabilities.
- unsupported_image_input — image_url / input_image part was passed to a model with image_input: false.
- invalid_tool_calls — Every tool_call returned by the model was malformed (invalid JSON args, unknown tool name, etc.). The inference is automatically refunded; offending calls are included in the error payload.
- file_not_found — A file_id reference could not be resolved or is not owned by the API key user.
- inference_failed — Upstream model provider failed to generate a response.
{
"error": {
"message": "Insufficient credits to complete request",
"type": "insufficient_credits",
"code": "credits_exhausted",
"param": null
}
}Rate Limit Headers
All API responses include rate limit headers to help you manage your usage:
- X-RateLimit-Limit — Maximum requests allowed per day (10,000 for Plus)
- X-RateLimit-Remaining — Number of requests remaining in the current period
- X-RateLimit-Reset — Unix timestamp when the rate limit resets
Resolve an error or incomplete response
Read the HTTP status, error.code and message, then correct the relevant key, account, model or request field. Check the endpoint’s completion status as well as HTTP success. Authentication Docs covers credentials and daily limits; the quickstart shows a complete request and follow-up.