# ChatQT API Documentation ChatQT provides a unified, OpenAI-compatible RESTful API that gives you access to dozens of AI models (GPT, Claude, Gemini, DeepSeek and more) through a single endpoint. You can get started in just a few lines of code using your favorite SDK or framework. - **Base URL (OpenAI SDK and most compatible clients):** `https://api.chatqt.com/api/v1` - **Chat completions endpoint:** `https://api.chatqt.com/api/v1/chat/completions` - **Claude CLI (Anthropic-compatible) base URL:** `https://api.chatqt.com/api` (the path without `/v1`) - **Authentication:** every API request requires an API key sent in the `Authorization` header: ```bash Authorization: Bearer YOUR_API_KEY ``` Get your API key from the ChatQT console at https://console.chatqt.com/dashboard/api-keys. Billing is pay-as-you-go: see usage at https://console.chatqt.com/dashboard/usage and your balance at https://console.chatqt.com/dashboard/wallet. The full, up-to-date models list is at https://console.chatqt.com/dashboard/models. --- ## Quickstart ChatQT provides a unified API that gives you access to dozens of AI models through a single endpoint. Get started in just a few lines of code using your favorite SDK or framework. ### Using the OpenAI SDK ```python from openai import OpenAI client = OpenAI( base_url="https://api.chatqt.com/api/v1", api_key="", ) completion = client.chat.completions.create( model="openai/gpt-4.1", messages=[ { "role": "user", "content": "معنی زندگی چیست؟" } ] ) print(completion.choices[0].message.content) ``` ### Direct API usage ```python import requests import json response = requests.post( url="https://api.chatqt.com/api/v1/chat/completions", headers={ "Authorization": "Bearer ", }, data=json.dumps({ "model": "openai/gpt-4.1", "messages": [ { "role": "user", "content": "معنی زندگی چیست؟" } ] }) ) ``` The API also supports streaming (see the Streaming section). ### JavaScript / Node.js ```javascript import OpenAI from 'openai'; const openai = new OpenAI({ baseURL: 'https://api.chatqt.com/api/v1', apiKey: process.env.CHATQT_API_KEY }); const completion = await openai.chat.completions.create({ model: 'openai/gpt-4.1', messages: [{ role: 'user', content: 'این یک تست است' }], }); console.log(completion.choices[0].message); ``` ### cURL ```bash curl https://api.chatqt.com/api/v1/chat/completions \ -H "Content-Type: application/json" \ -H "Authorization: Bearer " \ -d '{ "model": "openai/gpt-4.1", "messages": [ {"role": "user", "content": "سلام!"} ] }' ``` --- ## API Overview The ChatQT API provides a RESTful interface that gives you access to hundreds of AI models through a single endpoint. All chat requests must be sent to: ``` https://api.chatqt.com/api/v1/chat/completions ``` ### Authentication All API requests require an API key, which must be sent in the `Authorization` header: ```bash Authorization: Bearer YOUR_API_KEY ``` ### Request format Here is the request schema as a TypeScript type. This will be the body of your POST request to the endpoint: ```typescript type Request = { // "messages" is required messages?: Message[]; // If "model" is unspecified, uses the user's default model?: string; // See "Supported Models" section stop?: string[]; stream?: boolean; // Enable streaming // See LLM Parameters max_tokens?: number; // Range: [1, context_length) temperature?: number; // Range: [0, 2] // Advanced optional parameters top_p?: number; // Range: (0, 1] frequency_penalty?: number; // Range: [-2, 2] presence_penalty?: number; // Range: [-2, 2] }; ``` Message types: ```typescript type TextContent = { type: 'text'; text: string; }; type Message = { role: 'user' | 'assistant' | 'system'; content: TextContent[]; }; ``` Tool types (used with tool calling): ```typescript type FunctionDescription = { description?: string; name: string; parameters: object; // JSON Schema object }; type Tool = { type: 'function'; function: FunctionDescription; }; type ToolChoice = | 'none' | 'auto' | { type: 'function'; function: { name: string; }; }; ``` ### Request example Here is an example of a complete request to the ChatQT API: ```javascript fetch('https://api.chatqt.com/api/v1/chat/completions', { method: 'POST', headers: { Authorization: 'Bearer ', 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'openai/gpt-4.1', messages: [ { role: 'user', content: 'معنی زندگی چیست؟', }, ], }), }); ``` ### Response format The API returns a JSON response with the following structure: ```json { "id": "chatcmpl-123", "object": "chat.completion", "created": 1677652288, "model": "openai/gpt-4.1", "choices": [ { "index": 0, "message": { "role": "assistant", "content": "معنی زندگی موضوعی پیچیده و فلسفی است که نظرات مختلفی در مورد آن وجود دارد..." }, "finish_reason": "stop" } ] } ``` --- ## Models ### API Endpoint Retrieve the list of all available models with full details. - **Method:** `GET` - **URL:** `https://api.chatqt.com/api/v1/models` - **Response type:** `application/json` ```bash curl -X GET "https://api.chatqt.com/api/v1/models" ``` ### Models API standard The models API makes the most important information about all LLMs available for free as soon as they are approved. The response is a JSON object with a `data` array of model objects. Each model object has this shape: ```typescript interface Model { id: string; name: string; created: number; description: string; context_length: number; architecture: { input_modalities: string[]; output_modalities: string[]; tokenizer: string; instruct_type: string | null; }; pricing: { prompt: string; completion: string; request: string; image: string; web_search: string; internal_reasoning: string; input_cache_read: string; input_cache_write: string; }; top_provider: { context_length: number; max_completion_tokens: number; is_moderated: boolean; }; per_request_limits: any; supported_parameters: string[]; } ``` ### Model object fields | Field | Type | Description | |---|---|---| | `id` | string | The unique model ID used in API requests | | `name` | string | A human-readable name for displaying the model | | `created` | number | The Unix time the model was added to ChatQT | | `description` | string | A detailed description of the model's capabilities and features | | `context_length` | number | The maximum context window size in tokens | | `architecture` | Object | An object describing the model's technical capabilities | | `pricing` | Object | The pricing structure for the lowest cost of using this model | | `top_provider` | Object | Configuration details for the primary provider | ### An important note about tokenization Different models tokenize text in different ways. Some models split text into multi-character chunks (GPT, Claude, Llama, etc.), while others tokenize by character (PaLM). This means the number of tokens (and therefore costs) will differ between models, even when the inputs and outputs are identical. --- ## Text Generation (Generations API) The generations management API is a powerful tool for monitoring and analyzing the performance of requests processed by AI models. It provides two main endpoints that give full access to generation data: - `GET https://api.chatqt.com/api/v1/generation?page=1` — retrieve the full list of generations with pagination for better data-volume management. - `GET https://api.chatqt.com/api/v1/generation?id=` — retrieve complete analytical details of a specific generation, including token stats, cost and performance data. Key notes: - All requests require authentication with a Bearer token. - Responses include precise token usage and calculated costs. - You can filter and search generations by date and model. - All timestamps are provided in ISO 8601 format. ### Generations list This endpoint lets you retrieve a complete list of generations with pagination. You can view the full history of your requests and review overall performance stats. Available parameters: | Parameter | Description | |---|---| | `page` | Page number (default: 1) | | `limit` | Items per page (default: 20, max: 100) | | `model` | Filter by model name | | `from_date` | Filter from a specific date (format: YYYY-MM-DD) | | `to_date` | Filter up to a specific date (format: YYYY-MM-DD) | cURL request: ```bash curl --request GET \ --url 'https://api.chatqt.com/api/v1/generation?page=1' \ --header 'Authorization: Bearer ' ``` JavaScript request: ```javascript fetch('https://api.chatqt.com/api/v1/generation?page=1', { method: 'GET', headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, }); ``` Sample response shape: ```json { "page": "1", "result": [] } ``` ### Generation details This endpoint retrieves detailed analytical information for a specific generation by its unique Request ID. It includes precise token-usage stats, calculated costs and model performance details. Use cases for this API: - Performance analysis and token-usage optimization - Precise cost calculation for each request - Reviewing the quality and response speed of models - Tracing and debugging specific requests - Producing detailed usage reports cURL request: ```bash curl --request GET \ --url 'https://api.chatqt.com/api/v1/generation?id=' \ --header 'Authorization: Bearer ' ``` JavaScript request: ```javascript fetch('https://api.chatqt.com/api/v1/generation?id=', { method: 'GET', headers: { 'Authorization': 'Bearer ', 'Content-Type': 'application/json', }, }); ``` Sample response shape: ```json { "result": {} } ``` ### Response structure and data model Each generation item includes the comprehensive details below, enabling precise analysis of performance and costs: | Field | Category | Description | |---|---|---| | `request_id` | Identification | Unique request ID for tracing | | `model` | Identification | Name and version of the AI model used | | `created_at` | Identification | Exact request creation date and time (ISO 8601) | | `prompt_tokens` | Token usage | Number of input (prompt) tokens | | `completion_tokens` | Token usage | Number of tokens generated in the response | | `reasoning_tokens` | Token usage | Reasoning and internal-processing tokens of the model | | `total_tokens` | Token usage | Total tokens consumed | | `cost` | Cost | Total request cost in US dollars | | `cached_tokens` | Cost | Cached tokens for cost optimization | --- ## Streaming The ChatQT API supports streaming, allowing you to receive responses incrementally and in real time. This is useful for a better user experience and for displaying responses in real time. To enable streaming, add the `stream: true` parameter to your request. ### How to enable streaming ```javascript const response = await fetch('https://api.chatqt.com/api/v1/chat/completions', { method: 'POST', headers: { Authorization: 'Bearer ', 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'openai/gpt-4.1', messages: [{ role: 'user', content: 'سلام' }], 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'); for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') return; try { const parsed = JSON.parse(data); console.log(parsed.choices[0]?.delta?.content || ''); } catch (e) { // Handle parsing errors } } } } ``` ### Streaming response format When using streaming, responses are sent as Server-Sent Events (SSE). Each chunk contains a piece of the final response: ```text data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":"سلام"}}]} data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":"! چطور"}}]} data: {"id":"chatcmpl-123","object":"chat.completion.chunk","created":1677652288,"model":"openai/gpt-4.1","choices":[{"index":0,"delta":{"content":" می‌تونم"}}]} data: [DONE] ``` ### Best practices - **Error handling:** always use try-catch when parsing JSON to avoid potential errors. - **End of stream:** when you receive the `[DONE]` message, streaming has finished. - **Buffer management:** you may receive several chunks in one message, so parse them correctly. --- ## Multimodal The ChatQT multimodal API lets you work with images in two main modes: - **Image analysis** — send images to AI models and receive descriptions, analysis and text responses. - **Image generation** — generate high-quality images from text descriptions with adjustable aspect ratios. Key notes: - You need specific models to use these features. - Images can be sent as a URL or Base64. - Maximum image size: 20MB. - Supported formats: PNG, JPEG, WebP, GIF. ### Image analysis Image-analysis capabilities: - **Detection and description:** identify objects, people and scenes, and fully describe image content. - **Text extraction:** read and extract text contained in images (OCR). - **Artistic analysis:** analyze style, color and artistic elements of images. - **Specialized uses:** analyze medical, engineering and scientific images. Supported vision models (examples): `google/gemini-3.1-flash-lite`, `openai/gpt-5.5`, `anthropic/claude-opus-4.7`, `google/gemini-3.1-pro-preview` #### Sending an image by URL For images that are publicly accessible on the internet. cURL: ```bash curl -X POST "https://api.chatqt.com/api/v1/chat/completions" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/gemini-3.1-flash-lite", "messages": [ { "role": "user", "content": [ { "type": "text", "text": "این تصویر چیست؟ توضیح کاملی ارائه دهید." }, { "type": "image_url", "image_url": { "url": "https://example.com/image.jpg" } } ] } ] }' ``` Python: ```python import requests import json def analyze_image(image_url, prompt, api_key): """ تحلیل تصویر با استفاده از URL """ url = "https://api.chatqt.com/api/v1/chat/completions" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } payload = { "model": "google/gemini-3.1-flash-lite", "messages": [ { "role": "user", "content": [ { "type": "text", "text": prompt }, { "type": "image_url", "image_url": { "url": image_url } } ] } ] } try: response = requests.post(url, headers=headers, json=payload) response.raise_for_status() result = response.json() return result["choices"][0]["message"]["content"] except requests.exceptions.RequestException as e: print(f"خطا در تحلیل تصویر: {e}") raise # استفاده api_key = "YOUR_API_KEY" image_url = "https://example.com/image.jpg" prompt = "این تصویر چیست؟ جزئیات کاملی ارائه دهید." result = analyze_image(image_url, prompt, api_key) print("نتیجه تحلیل:", result) ``` JavaScript: ```javascript import axios from 'axios'; const analyzeImage = async (imageUrl, prompt) => { try { const response = await axios.post('https://api.chatqt.com/api/v1/chat/completions', { model: 'google/gemini-3.1-flash-lite', messages: [ { role: 'user', content: [ { type: 'text', text: prompt }, { type: 'image_url', image_url: { url: imageUrl } } ] } ] }, { headers: { 'Authorization': `Bearer ${YOUR_API_KEY}`, 'Content-Type': 'application/json' } }); return response.data.choices[0].message.content; } catch (error) { console.error('خطا در تحلیل تصویر:', error); throw error; } }; // استفاده analyzeImage( 'https://example.com/image.jpg', 'این تصویر چیست؟ جزئیات کاملی ارائه دهید.' ).then(result => { console.log('نتیجه تحلیل:', result); }); ``` #### Sending an image as Base64 For local or private images that need encoding. Python (Base64): ```python import requests import base64 import json from pathlib import Path def encode_image_to_base64(image_path): """ Encode an image file to base64 string """ try: with open(image_path, "rb") as image_file: encoded_string = base64.b64encode(image_file.read()).decode('utf-8') # Determine the image type image_extension = Path(image_path).suffix.lower() if image_extension == '.jpg' or image_extension == '.jpeg': mime_type = 'image/jpeg' elif image_extension == '.png': mime_type = 'image/png' elif image_extension == '.gif': mime_type = 'image/gif' elif image_extension == '.webp': mime_type = 'image/webp' else: mime_type = 'image/jpeg' # Default return f"data:{mime_type};base64,{encoded_string}" except Exception as e: print(f"Error encoding image: {e}") return None def analyze_base64_image(base64_image, prompt): """ Analyze a base64 encoded image using ChatQT API """ url = "https://api.chatqt.com/api/v1/chat/completions" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } payload = { "model": "google/gemini-3-pro-image-preview", "messages": [ { "role": "user", "content": [ { "type": "text", "text": prompt }, { "type": "image_url", "image_url": { "url": base64_image } } ] } ] } try: response = requests.post(url, headers=headers, json=payload) response.raise_for_status() result = response.json() return result["choices"][0]["message"]["content"] except requests.exceptions.RequestException as e: print(f"Error: {e}") return None # Usage image_path = "path/to/your/image.jpg" base64_image = encode_image_to_base64(image_path) if base64_image: prompt = "Describe what you see in this image" analysis = analyze_base64_image(base64_image, prompt) print(analysis) ``` JavaScript (Base64): ```javascript import fs from 'fs'; import path from 'path'; const encodeImageToBase64 = (imagePath) => { const imageBuffer = fs.readFileSync(imagePath); const base64Image = imageBuffer.toString('base64'); const mimeType = path.extname(imagePath) === '.png' ? 'image/png' : 'image/jpeg'; return `data:${mimeType};base64,${base64Image}`; }; const analyzeLocalImage = async (imagePath, prompt) => { const base64Image = encodeImageToBase64(imagePath); const response = await fetch('https://api.chatqt.com/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${YOUR_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'google/gemini-3.1-flash-lite', messages: [ { role: 'user', content: [ { type: 'text', text: prompt }, { type: 'image_url', image_url: { url: base64Image } } ] } ] }) }); const result = await response.json(); return result.choices[0].message.content; }; ``` ### Image generation Create high-quality images from text descriptions with adjustable aspect ratios. Include `"modalities": ["image", "text"]` in the request and optionally an `image_config` with an `aspect_ratio`. Image-generation capabilities: - **Artistic generation:** create artworks, paintings and creative designs. - **Varied aspect ratios:** support for different ratios from square to panorama. - **Fast generation:** generate images in under 10 seconds. - **Streaming processing:** receive images via streaming. Image-generation models (examples): `google/gemini-3-pro-image-preview`, `google/gemini-2.5-flash-image` Supported aspect ratios: | Ratio | Resolution | |---|---| | 1:1 | 1024×1024 | | 2:3 | 832×1248 | | 3:2 | 1248×832 | | 16:9 | 1408×792 | | 9:16 | 792×1408 | Simple request (cURL): ```bash curl -X POST "https://api.chatqt.com/api/v1/chat/completions" \ -H "Authorization: Bearer YOUR_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "google/gemini-3-pro-image-preview", "messages": [ { "role": "user", "content": "یک منظره زیبا از غروب خورشید در کوهستان ایران ایجاد کن" } ], "modalities": ["image", "text"] }' ``` Advanced (Python): ```python import requests import json def generate_image(prompt, api_key, aspect_ratio="1:1"): """ تولید تصویر از متن """ url = "https://api.chatqt.com/api/v1/chat/completions" headers = { "Authorization": f"Bearer {api_key}", "Content-Type": "application/json" } payload = { "model": "google/gemini-3-pro-image-preview", "messages": [ { "role": "user", "content": prompt } ], "modalities": ["image", "text"], "image_config": { "aspect_ratio": aspect_ratio } } try: response = requests.post(url, headers=headers, json=payload) response.raise_for_status() result = response.json() if result.get("choices") and result["choices"][0]["message"].get("images"): image_url = result["choices"][0]["message"]["images"][0]["image_url"]["url"] return image_url else: raise Exception("تصویری تولید نشد") except requests.exceptions.RequestException as e: print(f"خطا در تولید تصویر: {e}") raise # استفاده api_key = "YOUR_API_KEY" prompt = "یک منظره زیبا از غروب خورشید در کوهستان ایران" image_url = generate_image(prompt, api_key, "16:9") print(f"تصویر تولید شده: {image_url}") ``` Advanced (JavaScript): ```javascript const generateImage = async (prompt, aspectRatio = '1:1') => { try { const response = await fetch('https://api.chatqt.com/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${YOUR_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'google/gemini-3-pro-image-preview', messages: [ { role: 'user', content: prompt } ], modalities: ['image', 'text'], image_config: { aspect_ratio: aspectRatio } }) }); const result = await response.json(); if (result.choices && result.choices[0].message.images) { return result.choices[0].message.images[0].image_url.url; } throw new Error('تصویری تولید نشد'); } catch (error) { console.error('خطا در تولید تصویر:', error); throw error; } }; // استفاده generateImage( 'یک منظره زیبا از غروب خورشید در کوهستان ایران', '16:9' ).then(imageUrl => { console.log('تصویر تولید شده:', imageUrl); // نمایش تصویر در صفحه const img = document.createElement('img'); img.src = imageUrl; document.body.appendChild(img); }); ``` Streaming image generation (Python): ```python import requests import json # Your API key API_KEY = "your-api-key-here" url = "https://api.chatqt.com/api/v1/chat/completions" headers = { "Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json" } payload = { "model": "google/gemini-3-pro-image-preview", "messages": [ { "role": "user", "content": "Create an image of a futuristic city" } ], "modalities": ["image", "text"], "stream": True } response = requests.post(url, headers=headers, json=payload, stream=True) for line in response.iter_lines(): if line: line = line.decode('utf-8') if line.startswith('data: '): data = line[6:] if data != '[DONE]': try: chunk = json.loads(data) if chunk.get("choices"): delta = chunk["choices"][0].get("delta", {}) if delta.get("images"): for image in delta["images"]: print(f"Generated image: {image['image_url']['url'][:50]}...") except json.JSONDecodeError: continue ``` Streaming image generation (JavaScript): ```javascript const generateImageStreaming = async (prompt) => { const response = await fetch('https://api.chatqt.com/api/v1/chat/completions', { method: 'POST', headers: { 'Authorization': `Bearer ${YOUR_API_KEY}`, 'Content-Type': 'application/json' }, body: JSON.stringify({ model: 'google/gemini-3-pro-image-preview', messages: [ { role: 'user', content: prompt } ], modalities: ['image', 'text'], 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'); for (const line of lines) { if (line.startsWith('data: ')) { const data = line.slice(6); if (data === '[DONE]') return; try { const parsed = JSON.parse(data); if (parsed.choices && parsed.choices[0].delta && parsed.choices[0].delta.images) { const imageUrl = parsed.choices[0].delta.images[0].image_url.url; console.log('تصویر تولید شد:', imageUrl); return imageUrl; } } catch (e) { // ادامه پردازش } } } } }; ``` ### Response structure Multimodal API responses differ based on the request type (image analysis or generation): **Image-analysis response** — for image-analysis requests, the response contains explanatory text: | Field | Description | |---|---| | `choices` | An array of generated responses | | `message.content` | The image analysis and description text | **Image-generation response** — for image-generation requests, the response contains the URL of the generated image: | Field | Description | |---|---| | `choices` | An array of generated responses | | `message.images` | An array of generated images | | `image_url.url` | URL of the generated image | ### Best practices Image analysis: - Use high-quality images with adequate resolution. - State your questions clearly and specifically. - Use Base64 for sensitive images. - Optimize image size before sending. Image generation: - Provide precise and detailed descriptions. - Choose an aspect ratio suitable for your use case. - Use keywords related to your desired style. - Use streaming for large projects. --- ## Embeddings Convert text into numeric vectors (embeddings) — for semantic search, clustering, RAG and recommendation systems. The embeddings endpoint takes one or more texts and returns a numeric vector for each. These vectors represent the semantic distance between texts and are the basis of semantic search, clustering and similarity-based retrieval (RAG). The request and response structure is fully compatible with OpenAI's embeddings endpoint. - **Method:** `POST` - **URL:** `https://api.chatqt.com/api/v1/embeddings` Unlike `chat/completions`, this endpoint has no streaming and always returns the full response in a single JSON body. ### Authentication Like the other endpoints, put your API key in the `Authorization` header. Get the key from API keys in the console (https://console.chatqt.com/dashboard/api-keys). ```bash Authorization: Bearer ``` ### Body parameters | Parameter | Type | Required | Description | |---|---|---|---| | `model` | string | required | The embedding model ID (e.g. `openai/text-embedding-3-small`) | | `input` | string \| string[] | required | A single text, or an array of texts for batch processing in one request | ### Supported models A sample of embedding models (get the complete, up-to-date list from the models endpoint): - `openai/text-embedding-3-small` - `openai/text-embedding-3-large` - `google/gemini-embedding-001` - `qwen/qwen3-embedding-8b` ### Request examples cURL: ```bash curl --request POST \ --url 'https://api.chatqt.com/api/v1/embeddings' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "openai/text-embedding-3-small", "input": "متن نمونه برای تبدیل به بردار" }' ``` Python (OpenAI SDK): ```python from openai import OpenAI client = OpenAI( base_url="https://api.chatqt.com/api/v1", api_key="", ) response = client.embeddings.create( model="openai/text-embedding-3-small", input="متن نمونه برای تبدیل به بردار", ) # بردار حاصل vector = response.data[0].embedding print(len(vector), "بعد") print(response.usage) ``` Python (requests): ```python import requests response = requests.post( "https://api.chatqt.com/api/v1/embeddings", headers={ "Authorization": "Bearer ", "Content-Type": "application/json", }, json={ "model": "openai/text-embedding-3-small", # ارسال چند متن در یک درخواست "input": ["اولین متن", "دومین متن"], }, ) data = response.json() for item in data["data"]: print(item["index"], len(item["embedding"])) ``` JavaScript: ```javascript const response = await fetch('https://api.chatqt.com/api/v1/embeddings', { method: 'POST', headers: { Authorization: 'Bearer ', 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'openai/text-embedding-3-small', input: 'متن نمونه برای تبدیل به بردار', }), }); const data = await response.json(); const vector = data.data[0].embedding; console.log(vector.length, 'بعد'); ``` ### Batch input To convert multiple texts in one request, pass an array instead of a string to `input`. The order of vectors in the response matches the input order, indicated by the `index` field. ```bash curl --request POST \ --url 'https://api.chatqt.com/api/v1/embeddings' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "openai/text-embedding-3-small", "input": [ "اولین متن", "دومین متن", "سومین متن" ] }' ``` ### Response The response contains a `data` array, each member of which has a vector along with an `index`, and a `usage` field showing the number of tokens consumed. ```json { "object": "list", "data": [ { "object": "embedding", "index": 0, "embedding": [ 0.0023064255, -0.009327292, 0.015797347, "... (بقیه ابعاد بردار)" ] } ], "model": "openai/text-embedding-3-small", "usage": { "prompt_tokens": 8, "total_tokens": 8 } } ``` ### Response fields | Field | Type | Description | |---|---|---| | `data[].embedding` | number[] | The numeric vector of the input text. The vector length depends on the chosen model | | `data[].index` | number | The position of the corresponding text in the input array | | `model` | string | The model used to generate the vectors | | `usage.total_tokens` | number | The number of tokens consumed, used to calculate the cost charged to the wallet | ### Errors | Status | Name | Description | |---|---|---| | 400 | Bad Request | The request body is invalid — e.g. `input` or `model` is missing | | 401 | Unauthorized | The API key is invalid | | 402 | Insufficient Balance | The wallet balance is insufficient to make the request | | 404 | Model Not Found | The requested embedding model is not available | --- ## Audio Transcriptions Convert an audio file to text — for subtitles, meeting notes and voice assistants. The audio transcription endpoint takes an audio file and returns its spoken text. The request body is JSON, and the audio file is sent as a base64 string inside the `input_audio` field. - **Method:** `POST` - **URL:** `https://api.chatqt.com/api/v1/audio/transcriptions` This endpoint has no streaming and returns the full response in a single JSON body. ### Authentication Like the other endpoints, put your API key in the `Authorization` header. Get the key from API keys in the console (https://console.chatqt.com/dashboard/api-keys). ```bash Authorization: Bearer ``` ### Body parameters | Parameter | Type | Required | Description | |---|---|---|---| | `model` | string | required | The transcription model ID (e.g. `openai/whisper-large-v3-turbo`) | | `input_audio.data` | string | required | The audio file content as a base64 string | | `input_audio.format` | string | required | The audio file format (e.g. `wav`, `mp3`) | ### Supported models A sample of transcription models (get the complete, up-to-date list from the models endpoint): - `openai/whisper-large-v3-turbo` - `openai/whisper-1` - `openai/gpt-4o-transcribe` ### Request examples cURL: ```bash # فایل صوتی را به base64 تبدیل کنید AUDIO_BASE64=$(base64 < audio.wav | tr -d '\n') curl --request POST \ --url 'https://api.chatqt.com/api/v1/audio/transcriptions' \ --header 'Authorization: Bearer ' \ --header 'Content-Type: application/json' \ --data '{ "model": "openai/whisper-large-v3-turbo", "input_audio": { "data": "'"$AUDIO_BASE64"'", "format": "wav" } }' ``` Python (requests): ```python import base64 import requests with open("audio.wav", "rb") as f: audio_b64 = base64.b64encode(f.read()).decode() response = requests.post( "https://api.chatqt.com/api/v1/audio/transcriptions", headers={ "Authorization": "Bearer ", "Content-Type": "application/json", }, json={ "model": "openai/whisper-large-v3-turbo", "input_audio": {"data": audio_b64, "format": "wav"}, }, ) print(response.json()["text"]) ``` JavaScript: ```javascript import { readFileSync } from 'node:fs'; const audioBase64 = readFileSync('audio.wav').toString('base64'); const response = await fetch('https://api.chatqt.com/api/v1/audio/transcriptions', { method: 'POST', headers: { Authorization: 'Bearer ', 'Content-Type': 'application/json', }, body: JSON.stringify({ model: 'openai/whisper-large-v3-turbo', input_audio: { data: audioBase64, format: 'wav' }, }), }); const data = await response.json(); console.log(data.text); ``` ### Response The response contains a `text` field holding the transcribed text of the audio file: ```json { "text": "متن استخراج‌شده از فایل صوتی." } ``` ### Errors | Status | Name | Description | |---|---|---| | 400 | Bad Request | The request body is invalid — e.g. `input_audio` or `model` is missing | | 401 | Unauthorized | The API key is invalid | | 402 | Insufficient Balance | The wallet balance is insufficient to make the request | | 404 | Model Not Found | The requested transcription model is not available | --- ## Parameters A complete guide to all parameters available in the ChatQT API. The ChatQT API offers a variety of parameters to control model behavior and customize responses. ### Required parameters **`messages`** — Required An array of messages that make up the conversation. Either this or `prompt` must be sent. - Type: `Message[]` - Example: ```json [ { "role": "system", "content": "شما یک دستیار مفید هستید." }, { "role": "user", "content": "سلام!" } ] ``` **`model`** — Optional The ID of the model to use. If not specified, the user's default model is used. - Type: `string` - Example: `"openai/gpt-4.1"` ### Text-generation parameters | Parameter | Type | Required | Range | Default | Description | |---|---|---|---|---|---| | `max_tokens` | number | optional | `[1, context_length)` | No limit | The maximum number of tokens to generate in the response | | `temperature` | number | optional | `[0, 2]` | 1 | Controls the randomness of responses. Higher values produce more creative responses. Values near 0: more predictable responses; values near 2: more creative responses | | `top_p` | number | optional | `(0, 1]` | 1 | Nucleus sampling. An alternative to temperature | | `stop` | string \| string[] | optional | — | — | A string or array of strings that stop text generation. Example: `["\n", ".", "!"]` | ### Advanced parameters | Parameter | Type | Required | Range | Default | Description | |---|---|---|---|---|---| | `frequency_penalty` | number | optional | `[-2, 2]` | 0 | Reduces the likelihood of repeating words based on their frequency in the text | | `presence_penalty` | number | optional | `[-2, 2]` | 0 | Reduces the likelihood of repeating words based on their presence in the text | | `seed` | integer | optional | — | — | An integer for producing reproducible results. Example: `12345` | --- ## Tool Calls ChatQT standardizes the tool-calling interface across all models and providers, making it easy to integrate external tools with any supported model. ### Request body examples Tool calling with ChatQT involves three key steps. Here are the essential request body formats for each step. **Step 1: Inference request with tools** ```json { "model": "openai/gpt-4.1-mini", "messages": [ { "role": "user", "content": "What are the titles of some James Joyce books?" } ], "tools": [ { "type": "function", "function": { "name": "search_gutenberg_books", "description": "Search for books in the Project Gutenberg library", "parameters": { "type": "object", "properties": { "search_terms": { "type": "array", "items": {"type": "string"}, "description": "List of search terms to find books" } }, "required": ["search_terms"] } } } ] } ``` **Step 2: Tool execution (client side)** After receiving the model's response with `tool_calls`, run the requested tool locally and prepare the result: ```javascript // مدل با tool_calls پاسخ می‌دهد، شما ابزار را به صورت محلی اجرا می‌کنید const toolResult = await searchGutenbergBooks(["James", "Joyce"]); ``` **Step 3: Inference request with tool results** ```json { "model": "openai/gpt-4.1-mini", "messages": [ { "role": "user", "content": "What are the titles of some James Joyce books?" }, { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "search_gutenberg_books", "arguments": "{\"search_terms\": [\"James\", \"Joyce\"]}" } } ] }, { "role": "tool", "tool_call_id": "call_abc123", "content": "[{\"id\": 4300, \"title\": \"Ulysses\", \"authors\": [{\"name\": \"Joyce, James\"}]}]" } ], "tools": [ { "type": "function", "function": { "name": "search_gutenberg_books", "description": "Search for books in the Project Gutenberg library", "parameters": { "type": "object", "properties": { "search_terms": { "type": "array", "items": {"type": "string"}, "description": "List of search terms to find books" } }, "required": ["search_terms"] } } } ] } ``` > **Note:** the `tools` parameter must be included in each request (steps 1 and 3) so the router can validate the tool schema on every call. ### Tool-calling example Here is Python code that gives large language models the ability to call an external API — in this case Project Gutenberg, to search for books. Initial setup: ```python import json, requests from openai import OpenAI API_KEY = f"" # شما می‌توانید از هر مدلی که از tool calling پشتیبانی می‌کند استفاده کنید MODEL = "openai/gpt-4.1-mini" openai_client = OpenAI( base_url="https://api.chatqt.com/api/v1", api_key=API_KEY, ) task = "What are the titles of some James Joyce books?" messages = [ { "role": "system", "content": "You are a helpful assistant." }, { "role": "user", "content": task, } ] ``` Tool definition — the tool is requested by the model, but the code we write here is ultimately responsible for executing the call and returning the results to the model: ```python def search_gutenberg_books(search_terms): search_query = " ".join(search_terms) url = "https://gutendex.com/books" response = requests.get(url, params={"search": search_query}) simplified_results = [] for book in response.json().get("results", []): simplified_results.append({ "id": book.get("id"), "title": book.get("title"), "authors": book.get("authors") }) return simplified_results tools = [ { "type": "function", "function": { "name": "search_gutenberg_books", "description": "Search for books in the Project Gutenberg library based on specified search terms", "parameters": { "type": "object", "properties": { "search_terms": { "type": "array", "items": { "type": "string" }, "description": "List of search terms to find books" } }, "required": ["search_terms"] } } } ] ``` --- ## Error Handling A complete guide to error handling and HTTP status codes in the ChatQT API. On error, the ChatQT API returns standard HTTP codes and detailed error messages. All errors are sent as JSON with a consistent structure. Always check the HTTP status code and response body to determine the error type. ### HTTP status codes **400 — Bad Request.** Invalid request — the sent parameters are wrong, missing or invalid. Common causes: - Missing required parameters (e.g. `messages` or `model`) - Invalid JSON format - Parameter values out of the allowed range - Incorrect data type for parameters **401 — Unauthorized.** The API key is invalid, missing or expired. Common causes: - The API key was not sent - The API key is invalid or incorrect - The API key has expired - The Authorization header format is wrong **403 — Forbidden.** Access to the requested resource is not allowed. Common causes: - Access to a specific model is restricted - Insufficient account balance - Geographic restrictions **429 — Rate Limited.** The request rate limit was exceeded. Solutions: - Wait a moment and try again - Use exponential backoff - Reduce the number of concurrent requests - Upgrade your plan **500 — Internal Server Error.** An internal server error occurred. Solutions: - Wait a few moments and try again - If the problem persists, contact support - Use retry logic with backoff ### Error response format All errors are sent with the same JSON structure: ```json { "error": { "message": "", "type": "", "code": "" } } ``` ### Best practices Always implement retry logic with exponential backoff for transient errors (5xx, 429). - **Retry strategy:** for 429 and 5xx errors, use retries with exponential delay. - **Error logging:** log all errors with full details (including the request ID). - **User experience:** show user-friendly error messages and avoid exposing technical errors. --- ## Wallet Check the current wallet balance for your account. - **Method:** `GET` - **URL:** `https://api.chatqt.com/api/v1/wallet/balance` ### Authentication This request requires an API key, which must be sent in the Authorization header: ```bash Authorization: Bearer YOUR_API_KEY ``` ### Request examples cURL: ```bash curl --request GET \ --url https://api.chatqt.com/api/v1/wallet/balance \ --header 'Authorization: Bearer YOUR_API_KEY' ``` JavaScript: ```javascript fetch('https://api.chatqt.com/api/v1/wallet/balance', { method: 'GET', headers: { 'Authorization': 'Bearer YOUR_API_KEY', 'Content-Type': 'application/json' } }) .then(response => response.json()) .then(data => console.log(data)) .catch(error => console.error('Error:', error)); ``` ### Response format The API returns a JSON response with the following structure: ```json { "balance": 3.1752, "status": "OK" } ``` ### Response fields | Field | Type | Description | |---|---|---| | `balance` | number | The current wallet balance in US dollars (USD) | | `status` | string | The request status — "OK" on success | > **Note:** all amounts are shown in US dollars (USD). ### Errors | Status | Name | Description | |---|---|---| | 401 | Unauthorized | The API key is invalid or missing | | 403 | Forbidden | Access to this endpoint is not allowed | | 500 | Internal Server Error | Internal server error | --- ## API Key Usage (Token Usage) Read the aggregated usage cost of a specific API key (in USD) without logging into the dashboard. - **Method:** `GET` - **URL:** `https://api.chatqt.com/api/v1/token/usage` The `token` query parameter is the ID of the API key whose usage you want to see. ### Authentication The `Authorization` header must be the same API key (usually matching the `token` parameter value). Get the key from API keys in the console (https://console.chatqt.com/dashboard/api-keys). ```bash Authorization: Bearer ``` ### Query parameters | Parameter | Type | Required | Description | |---|---|---|---| | `token` | string | required | The API key ID (e.g. `sk-or-v1-…`) whose usage is returned | ### Request examples cURL: ```bash curl --request GET \ --url 'https://api.chatqt.com/api/v1/token/usage?token=' \ --header 'Authorization: Bearer ' ``` JavaScript: ```javascript fetch( 'https://api.chatqt.com/api/v1/token/usage?token=' + encodeURIComponent(apiKey), { method: 'GET', headers: { Authorization: 'Bearer ' + apiKey, }, } ) .then((res) => res.json()) .then((data) => console.log(data)); ``` ### Response A successful response includes the request status and the value of the `usage` field — the aggregated cost in US dollars (USD): ```json { "status": "OK", "usage": 32.805454476 } ``` ### Response fields | Field | Type | Description | |---|---|---| | `usage` | number | The aggregated usage cost of that API key in US dollars (USD) | | `status` | string | The request status — `OK` on success | This endpoint only returns the dollar cost. For token counts, model and request history, use usage in the dashboard (https://console.chatqt.com/dashboard/usage) or the generations endpoints (see Text Generation). ### Errors | Status | Name | Description | |---|---|---| | 401 | Unauthorized | The API key is invalid or does not match the token parameter | | 403 | Forbidden | Access to this key's usage is not allowed | | 404 | Not Found | The API key was not found | --- ## Claude CLI Integration By pointing Claude CLI to an Anthropic-compatible endpoint, you can use Claude models (and others) in your terminal with the same ChatQT API key. This uses a custom provider / OpenAI-compatible endpoint — for custom APIs such as ChatQT or OpenRouter. ### Prerequisites - Claude Code / Claude CLI (https://docs.anthropic.com/en/docs/claude-code) must be installed on your system. - Have an API key from the ChatQT console (https://console.chatqt.com/dashboard/api-keys). ### Create the config file Create or edit the `~/.claude/settings.json` file: ```bash mkdir -p ~/.claude nano ~/.claude/settings.json ``` ### Example settings Replace `YOUR_TOKEN` with your API key from API keys (https://console.chatqt.com/dashboard/api-keys). You can find model IDs in the models list (https://console.chatqt.com/dashboard/models). Note that Claude CLI uses the base URL **without** `/v1`: ```json { "env": { "ANTHROPIC_AUTH_TOKEN": "YOUR_TOKEN", "ANTHROPIC_BASE_URL": "https://api.chatqt.com/api", "ANTHROPIC_DEFAULT_OPUS_MODEL": "anthropic/claude-opus-4.7", "ANTHROPIC_DEFAULT_SONNET_MODEL": "anthropic/claude-sonnet-4.5", "ANTHROPIC_DEFAULT_HAIKU_MODEL": "anthropic/claude-haiku-4.5" } } ``` ### Get started After saving the file, close and reopen your terminal, then run `claude`. Requests are sent through ChatQT's infrastructure and are visible in usage (https://console.chatqt.com/dashboard/usage). --- ## n8n Integration In n8n workflows, use the OpenAI node with a custom credential — enter the ChatQT API key and Base URL, and call GPT, Claude and other models. ### Why ChatQT? Instead of a direct OpenAI account that is often unavailable, configure the same OpenAI node with the ChatQT-compatible endpoint — dozens of models from a single credential. - **OpenAI-compatible:** workflow requests go from your n8n server to `api.chatqt.com` — no direct OpenAI account required. - **Stable access:** ChatQT provides a reliable endpoint for your production workflows. - **Transparent payment & usage:** API key from https://console.chatqt.com/dashboard/api-keys; cost based on usage. ### Prerequisites 1. An n8n instance (Cloud or self-hosted) with access to Credentials. 2. A ChatQT account and an API key from the console (https://console.chatqt.com/dashboard/api-keys). 3. Basic familiarity with building workflows in n8n. Official docs: https://docs.n8n.io ### Create an OpenAI credential In n8n, create a credential of type **OpenAI API**. Instead of the OpenAI key, enter the ChatQT key and override the base URL: 1. In n8n go to **Credentials** → **Add credential**. 2. Select the **OpenAI API** type. 3. In the **API Key** field, paste the key from API keys (https://console.chatqt.com/dashboard/api-keys). 4. Set the **Base URL** field (in some versions **Host** or **Override URL**) to the address below. 5. Save and test the credential in a workflow. ```text API Key: YOUR_CHATQT_API_KEY Base URL: https://api.chatqt.com/api/v1 ``` For the OpenAI SDK and most compatible clients, the path is `/api/v1`. ### Add the OpenAI node to a workflow After creating the credential, add the **OpenAI** node and pick the model by its console ID: 1. A new or existing workflow → **+** → search for **OpenAI**. 2. Set Resource to **Message a model** (or Chat / Text). 3. Select the credential created in the previous step. 4. In the **Model** field, enter the exact ID from the console (e.g. `openai/gpt-4.1`). 5. Fill in Prompt / Messages and save the workflow. **Simple example:** Manual Trigger → OpenAI (Message a model) → display the output. To start, test a fixed message in the node. Popular models: | Model | ID in the node | |---|---| | GPT 4.1 | `openai/gpt-4.1` | | Claude Sonnet 4.5 | `anthropic/claude-sonnet-4.5` | | DeepSeek V4 Pro | `deepseek/deepseek-v4-pro` | The complete and up-to-date list of models is in the models list (https://console.chatqt.com/dashboard/models). ### Test the workflow 1. Click **Test workflow** or run the node manually. 2. The output should show the model's response; see usage in the ChatQT console under usage (https://console.chatqt.com/dashboard/usage). Troubleshooting: - **401 error (Unauthorized):** check the API key in the credential; it should be copied from the ChatQT console with no extra spaces. - **Model not found:** copy the model ID exactly from the console (e.g. `openai/gpt-4.1`) — the display name is not the same as the API slug. - **Connection fails:** the Base URL must be `https://api.chatqt.com/api/v1` (with `/v1` at the end). ### FAQ **Why the OpenAI node and not a separate ChatQT node?** The ChatQT API is OpenAI-compatible; by overriding the Base URL, the standard n8n node is enough and you don't need to install a community node. **Where is the models list?** All usable IDs are shown in the models list (https://console.chatqt.com/dashboard/models) — write the same slug in the Model field. **What's the difference between `/api` and `/api/v1`?** For n8n and the OpenAI SDK use `/api/v1`. Claude CLI uses the path without v1 (`https://api.chatqt.com/api`) — see the Claude CLI guide and the API docs. **How is the cost calculated?** Like other API requests — pay as you go. See usage at https://console.chatqt.com/dashboard/usage and your balance in the wallet at https://console.chatqt.com/dashboard/wallet.