Для получения чистого Markdown любой страницы добавьте .md к URL страницы.
Для полного индекса документации см. https://api.vega.chat/docs/llms.txt.
Для полного содержания документации см. https://api.vega.chat/docs/llms-full.txt.
Для интеграции AI‑клиентов (Claude Code, Cursor и др.) подключитесь к MCP‑серверу по адресу https://api.vega.chat/docs/_mcp/server.
Потоковая передача
VEGA API позволяет передавать ответы в режиме потока от любой модели. Это удобно для создания чат‑интерфейсов или других приложений, где UI должен обновляться по мере генерации ответа моделью.
Чтобы включить потоковую передачу, установите параметр stream в true в вашем запросе. Модель будет передавать ответ клиенту кусками, а не возвращать весь ответ сразу.
Ниже пример того, как потокировать ответ и обрабатывать его:
import { OpenRouter } from '@openrouter/sdk';
const client = new OpenRouter({
apiKey: '{{API_KEY_REF}}',
});
const question = 'How would you build the tallest building ever?';
const stream = await client.chat.send({
model: '{{MODEL}}',
messages: [{ role: 'user', content: question }],
stream: true,
});
for await (const chunk of stream) {
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
console.log(content);
}
// Финальный кусок содержит статистику использования
if (chunk.usage) {
console.log('Usage:', chunk.usage);
}
}import requests
import json
question = "How would you build the tallest building ever?"
url = "https://api.vega.chat/api/v1/chat/completions"
headers = {
"Authorization": f"Bearer {{API_KEY_REF}}",
"Content-Type": "application/json"
}
payload = {
"model": "{{MODEL}}",
"messages": [{"role": "user", "content": question}],
"stream": True
}
buffer = ""
with requests.post(url, headers=headers, json=payload, stream=True) as r:
for chunk in r.iter_content(chunk_size=1024, decode_unicode=True):
buffer += chunk
while True:
try:
# Находим следующую полную строку SSE
line_end = buffer.find('\n')
if line_end == -1:
break
line = buffer[:line_end].strip()
buffer = buffer[line_end + 1:]
if line.startswith('data: '):
data = line[6:]
if data == '[DONE]':
break
try:
data_obj = json.loads(data)
content = data_obj["choices"][0]["delta"].get("content")
if content:
print(content, end="", flush=True)
except json.JSONDecodeError:
pass
except Exception:
breakconst question = 'How would you build the tallest building ever?';
const response = await fetch('https://api.vega.chat/api/v1/chat/completions', {
method: 'POST',
headers: {
Authorization: `Bearer ${API_KEY_REF}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [{ role: 'user', content: question }],
stream: true,
}),
});
const reader = response.body?.getReader();
if (!reader) {
throw new Error('Response body is not readable');
}
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
// Добавляем новый кусок к буферу
buffer += decoder.decode(value, { stream: true });
// Обрабатываем полные строки из буфера
while (true) {
const lineEnd = buffer.indexOf('\n');
if (lineEnd === -1) break;
const line = buffer.slice(0, lineEnd).trim();
buffer = buffer.slice(lineEnd + 1);
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') break;
try {
const parsed = JSON.parse(data);
const content = parsed.choices[0].delta.content;
if (content) {
console.log(content);
}
} catch (e) {
// Игнорируем некорректный JSON
}
}
}
}
} finally {
reader.cancel();
}Дополнительная информация
Для SSE (Server-Sent Events) потоков VEGA иногда отправляет комментарии, чтобы предотвратить тайм‑ауты соединения. Такие комментарии выглядят так:
: OPENROUTER PROCESSINGПолезную нагрузку комментариев можно безопасно игнорировать в соответствии со спецификацией SSE. Тем не менее, при желании вы можете использовать их для улучшения UX, например, показывая динамический индикатор загрузки.
Идентификатор генерации возвращается в заголовке ответа X-Generation-Id для всех конечных точек (chat completions, completions, responses и messages) и может быть полезен для отладки и корреляции запросов.
Некоторые реализации SSE‑клиентов могут не разбирать полезную нагрузку согласно спецификации, что приводит к необработанной ошибке при JSON.stringify не‑JSON данных. Мы рекомендуем использовать следующие клиенты:
Отмена потока
Запросы с потоковой передачой можно отменить, прервав соединение. Для поддерживаемых провайдеров это немедленно останавливает обработку модели и биллинг.
Поддерживается
- OpenAI, Azure, Anthropic
- Fireworks, Mancer, Recursal
- AnyScale, Lepton, OctoAI
- Novita, DeepInfra, Together
- Cohere, Hyperbolic, Infermatic
- Avian, XAI, Cloudflare
- SFCompute, Nineteen, Liquid
- Friendli, Chutes, DeepSeek
В данный момент не поддерживается
- AWS Bedrock, Groq, Modal
- Google, Google AI Studio, Minimax
- HuggingFace, Replicate, Perplexity
- Mistral, AI21, Featherless
- Lynn, Lambda, Reflection
- SambaNova, Inflection, ZeroOneAI
- AionLabs, Alibaba, Nebius
- Kluster, Targon, InferenceNet
Для реализации отмены потока:
import { OpenRouter } from '@openrouter/sdk';
const client = new OpenRouter({
apiKey: '{{API_KEY_REF}}',
});
const controller = new AbortController();
try {
const stream = await client.chat.send({
model: '{{MODEL}}',
messages: [{ role: 'user', content: 'Write a story' }],
stream: true,
}, {
signal: controller.signal,
});
for await (const chunk of stream) {
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
console.log(content);
}
}
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream cancelled');
} else {
throw error;
}
}
// Чтобы отменить поток:
controller.abort();import requests
from threading import Event, Thread
def stream_with_cancellation(prompt: str, cancel_event: Event):
with requests.Session() as session:
response = session.post(
"https://api.vega.chat/api/v1/chat/completions",
headers={"Authorization": f"Bearer {{API_KEY_REF}}"},
json={"model": "{{MODEL}}", "messages": [{"role": "user", "content": prompt}], "stream": True},
stream=True
)
try:
for line in response.iter_lines():
if cancel_event.is_set():
response.close()
return
if line:
print(line.decode(), end="", flush=True)
finally:
response.close()
# Пример использования:
cancel_event = Event()
stream_thread = Thread(target=lambda: stream_with_cancellation("Write a story", cancel_event))
stream_thread.start()
# Чтобы отменить поток:
cancel_event.set()const controller = new AbortController();
try {
const response = await fetch(
'https://api.vega.chat/api/v1/chat/completions',
{
method: 'POST',
headers: {
Authorization: `Bearer ${{{API_KEY_REF}}}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [{ role: 'user', content: 'Write a story' }],
stream: true,
}),
signal: controller.signal,
},
);
// Обрабатываем поток...
} catch (error) {
if (error.name === 'AbortError') {
console.log('Stream cancelled');
} else {
throw error;
}
}
// Чтобы отменить поток:
controller.abort();Отмена работает только для запросов с потоковой передачей у поддерживаемых провайдеров. Для запросов без потоковой передачи или у неподдерживаемых провайдеров модель продолжит обработку, и вы будете выставлены за полный ответ.
Обработка ошибок во время потоковой передачи
VEGA обрабатывает ошибки по‑разному в зависимости от того, когда они происходят в процессе потоковой передачи:
Ошибки до отправки любых токенов
Если ошибка происходит до того, как какие‑либо токены были переданы клиенту, VEGA возвращает стандартный JSON‑ответ об ошибке с соответствующим HTTP‑статусом. Формат ошибки выглядит так:
{
"error": {
"code": 400,
"message": "Invalid model specified"
}
}Распространённые коды статуса:
- 400: Bad Request (некорректные параметры)
- 401: Unauthorized (неверный API‑ключ)
- 402: Payment Required (недостаточно кредитов)
- 429: Too Many Requests (превышен лимит запросов)
- 502: Bad Gateway (ошибка провайдера)
- 503: Service Unavailable (нет доступных провайдеров)
Ошибки после отправки токенов (Mid-Stream)
Если ошибка происходит после того, как часть токенов уже передана клиенту, VEGA не может изменить HTTP‑статус (уже отправлен 200 OK). Вместо этого ошибка передаётся как Server‑Sent Event (SSE) с унифицированной структурой:
data: {"id":"cmpl-abc123","object":"chat.completion.chunk","created":1234567890,"model":"openai/gpt-4o","provider":"openai","error":{"code":"server_error","message":"Provider disconnected unexpectedly"},"choices":[{"index":0,"delta":{"content":""},"finish_reason":"error"}]}Ключевые особенности ошибок mid‑stream:
- Ошибка появляется на верхнем уровне вместе со стандартными полями ответа (id, object, created и т.д.)
- В массиве
choicesприсутствуетfinish_reason: "error"для корректного завершения потока - HTTP‑статус остаётся 200 OK, так как заголовки уже отправлены
- После этого события поток завершается
Примеры кода
Ниже показано, как правильно обрабатывать оба типа ошибок в реализации потоковой передачи:
import { OpenRouter } from '@openrouter/sdk';
const client = new OpenRouter({
apiKey: '{{API_KEY_REF}}',
});
async function streamWithErrorHandling(prompt: string) {
try {
const stream = await client.chat.send({
model: '{{MODEL}}',
messages: [{ role: 'user', content: prompt }],
stream: true,
});
for await (const chunk of stream) {
// Проверяем наличие ошибки в куске
if ('error' in chunk) {
console.error(`Stream error: ${chunk.error.message}`);
if (chunk.choices?.[0]?.finish_reason === 'error') {
console.log('Stream terminated due to error');
}
return;
}
// Обрабатываем обычный контент
const content = chunk.choices?.[0]?.delta?.content;
if (content) {
console.log(content);
}
}
} catch (error) {
// Обрабатываем ошибки до начала потока
console.error(`Error: ${error.message}`);
}
}import requests
import json
async def stream_with_error_handling(prompt):
response = requests.post(
'https://api.vega.chat/api/v1/chat/completions',
headers={'Authorization': f'Bearer {{API_KEY_REF}}'},
json={
'model': '{{MODEL}}',
'messages': [{'role': 'user', 'content': prompt}],
'stream': True
},
stream=True
)
# Проверяем начальный HTTP‑статус для ошибок до начала потока
if response.status_code != 200:
error_data = response.json()
print(f"Error: {error_data['error']['message']}")
return
# Обрабатываем поток и учитываем ошибки mid‑stream
for line in response.iter_lines():
if line:
line_text = line.decode('utf-8')
if line_text.startswith('data: '):
data = line_text[6:]
if data == '[DONE]':
break
try:
parsed = json.loads(data)
# Проверяем наличие ошибки mid‑stream
if 'error' in parsed:
print(f"Stream error: {parsed['error']['message']}")
if parsed.get('choices', [{}])[0].get('finish_reason') == 'error':
print("Stream terminated due to error")
break
# Обрабатываем обычный контент
content = parsed['choices'][0]['delta'].get('content')
if content:
print(content, end='', flush=True)
except json.JSONDecodeError:
passasync function streamWithErrorHandling(prompt: string) {
const response = await fetch(
'https://api.vega.chat/api/v1/chat/completions',
{
method: 'POST',
headers: {
'Authorization': `Bearer ${{{API_KEY_REF}}}`,
'Content-Type': 'application/json',
},
body: JSON.stringify({
model: '{{MODEL}}',
messages: [{ role: 'user', content: prompt }],
stream: true,
}),
}
);
// Проверяем начальный HTTP‑статус для ошибок до начала потока
if (!response.ok) {
const error = await response.json();
console.error(`Error: ${error.error.message}`);
return;
}
const reader = response.body?.getReader();
if (!reader) throw new Error('No response body');
const decoder = new TextDecoder();
let buffer = '';
try {
while (true) {
const { done, value } = await reader.read();
if (done) break;
buffer += decoder.decode(value, { stream: true });
while (true) {
const lineEnd = buffer.indexOf('\n');
if (lineEnd === -1) break;
const line = buffer.slice(0, lineEnd).trim();
buffer = buffer.slice(lineEnd + 1);
if (line.startsWith('data: ')) {
const data = line.slice(6);
if (data === '[DONE]') return;
try {
const parsed = JSON.parse(data);
// Проверяем наличие ошибки mid‑stream
if (parsed.error) {
console.error(`Stream error: ${parsed.error.message}`);
if (parsed.choices?.[0]?.finish_reason === 'error') {
console.log('Stream terminated due to error');
}
return;
}
// Обрабатываем обычный контент
const content = parsed.choices[0].delta.content;
if (content) {
console.log(content);
}
} catch (e) {
// Игнорируем ошибки парсинга
}
}
}
}
} finally {
reader.cancel();
}
}Специфическое поведение API
Разные конечные точки API могут слегка различаться в обработке ошибок потоковой передачи:
- OpenAI Chat Completions API: возвращает
ErrorResponseнапрямую, если ни один кусок не был обработан, либо включает информацию об ошибке в ответ, если часть кусков уже отправлена. - OpenAI Responses API: может преобразовать некоторые коды ошибок (например,
context_length_exceeded) в успешный ответ сfinish_reason: "length"вместо того, чтобы рассматривать их как ошибки.