API reference
Base URL http://127.0.0.1:3001/v1. Authenticate with Authorization: Bearer $YOURBRAND_KEY or x-api-key: $YOURBRAND_KEY, on every model endpoint.
Overview
Requests and responses are JSON over HTTPS unless the endpoint says otherwise. The endpoints speak the OpenAI and the Anthropic formats, so existing SDKs and agents work after a base URL change. A field we don't support gets a 400 rather than being dropped.
- Base URL
http://127.0.0.1:3001/v1- Authentication
Authorization: Bearerorx-api-keywith your key, on every model endpoint.GET /v1/modelstakes no key.- Forwarded requests
- Some models are forwarded to providers with a no-logs policy. Every key starts in strict mode: requests go only to GPUs we run or to providers with a no-logs policy, and are refused rather than sent elsewhere. You can turn it off per key.
user,metadataandsafety_identifierare stripped first, and your IP and headers are never passed on. - Rate limits
- Parallel requests per plan. No per-minute or per-token cap.
- Streaming
- Server-sent events on chat completions, Responses and Messages.
- Errors
- The error shape of the endpoint's family, with a 4xx or 5xx status. See Errors.
Chat
Chat completions and Responses take OpenAI's format, Messages takes Anthropic's. All three stream and take the same models.
POST/v1/chat/completionsCreate a chat completionBearer · x-api-key
Creates a reply for a conversation. The request and response bodies match OpenAI's, so the OpenAI SDKs and any tool built on them work unchanged.
Parameters
| Field | Type | Notes |
|---|---|---|
model | string | Required. A model id from Models. |
messages | array | Required. Objects with role (system, developer, user, assistant, tool) and content. |
stream | boolean | Send the reply as server-sent events. Defaults to false. |
temperature | number | 0 to 2. Without it, the model's default applies. |
max_tokens | integer | Caps the reply length. Limited by the model's max output. |
tools | array | Function definitions, on models that support tool calls. |
Example request
curl http://127.0.0.1:3001/v1/chat/completions \ -H "Authorization: Bearer $YOURBRAND_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3.8-27b-abliterated","messages":[{"role":"user","content":"hello"}]}'
import OpenAI from "openai"; const client = new OpenAI({ apiKey: process.env.YOURBRAND_KEY, baseURL: "http://127.0.0.1:3001/v1" }); const res = await client.chat.completions.create({ model: "qwen3.8-27b-abliterated", messages: [{ role: "user", content: "hello" }], });
import os from openai import OpenAI client = OpenAI(api_key=os.environ["YOURBRAND_KEY"], base_url="http://127.0.0.1:3001/v1") res = client.chat.completions.create( model="qwen3.8-27b-abliterated", messages=[{"role": "user", "content": "hello"}], )
using System.Net.Http.Json; var key = Environment.GetEnvironmentVariable("YOURBRAND_KEY"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("Authorization", $"Bearer {key}"); var res = await http.PostAsJsonAsync("http://127.0.0.1:3001/v1/chat/completions", new { model = "qwen3.8-27b-abliterated", messages = new[] { new { role = "user", content = "hello" } }, }); Console.WriteLine(await res.Content.ReadAsStringAsync());
#include <cpr/cpr.h> #include <cstdlib> #include <iostream> int main() { std::string key = std::getenv("YOURBRAND_KEY"); auto res = cpr::Post( cpr::Url{"http://127.0.0.1:3001/v1/chat/completions"}, cpr::Header{{"Authorization", "Bearer " + key}, {"Content-Type", "application/json"}}, cpr::Body{R"({ "model": "qwen3.8-27b-abliterated", "messages": [{"role":"user","content":"hello"}] })"}); std::cout << res.text << "\n"; }
require "json" require "net/http" res = Net::HTTP.post( URI("http://127.0.0.1:3001/v1/chat/completions"), { model: "qwen3.8-27b-abliterated", messages: [{ role: "user", content: "hello" }], }.to_json, "Authorization" => "Bearer #{ENV['YOURBRAND_KEY']}", "Content-Type" => "application/json", ) puts res.body
package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := `{ "model": "qwen3.8-27b-abliterated", "messages": [{"role":"user","content":"hello"}] }` req, _ := http.NewRequest("POST", "http://127.0.0.1:3001/v1/chat/completions", strings.NewReader(body)) req.Header.Set("Authorization", "Bearer "+os.Getenv("YOURBRAND_KEY")) req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() out, _ := io.ReadAll(res.Body) fmt.Println(string(out)) }
Response
{
"id": "chatcmpl-8f1c…",
"object": "chat.completion",
"created": 1793282400,
"model": "qwen3.8-27b-abliterated",
"choices": [{
"index": 0,
"message": { "role": "assistant", "content": "Hello! What are you building?" },
"finish_reason": "stop"
}],
"usage": { "prompt_tokens": 9, "completion_tokens": 8, "total_tokens": 17 }
}
Streaming
With "stream": true each event is a data: line holding a chat.completion.chunk. The last chunk carries usage, then the stream ends with data: [DONE].
POST/v1/responsesCreate a responseBearer · x-api-key
OpenAI's Responses shape, streaming included, so client.responses.create() works.
Example request
curl http://127.0.0.1:3001/v1/responses \ -H "Authorization: Bearer $YOURBRAND_KEY" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3.8-27b-abliterated","input":"hello"}'
POST/v1/messagesCreate a messageBearer · x-api-key
The Anthropic Messages shape, streaming included. Point the Anthropic SDK at http://127.0.0.1:3001, without /v1: it adds /v1/messages itself.
Parameters
| Field | Type | Notes |
|---|---|---|
model | string | Required. A model id from Models. |
max_tokens | integer | Required. Caps the reply length. |
messages | array | Required. role is user or assistant; content is a string or a list of {"type": "text"} blocks. |
system | string | System prompt, kept outside messages. |
stream | boolean | Send the reply as named server-sent events. Defaults to false. |
temperature | number | 0 to 1. Without it, the model's default applies. |
Example request
curl http://127.0.0.1:3001/v1/messages \ -H "x-api-key: $YOURBRAND_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3.8-27b-abliterated","max_tokens":1024,"messages":[{"role":"user","content":"hello"}]}'
import Anthropic from "@anthropic-ai/sdk"; const client = new Anthropic({ apiKey: process.env.YOURBRAND_KEY, baseURL: "http://127.0.0.1:3001" }); const msg = await client.messages.create({ model: "qwen3.8-27b-abliterated", max_tokens: 1024, messages: [{ role: "user", content: "hello" }], });
import os import anthropic client = anthropic.Anthropic(api_key=os.environ["YOURBRAND_KEY"], base_url="http://127.0.0.1:3001") msg = client.messages.create( model="qwen3.8-27b-abliterated", max_tokens=1024, messages=[{"role": "user", "content": "hello"}], )
using System.Net.Http.Json; var key = Environment.GetEnvironmentVariable("YOURBRAND_KEY"); using var http = new HttpClient(); http.DefaultRequestHeaders.Add("x-api-key", key); http.DefaultRequestHeaders.Add("anthropic-version", "2023-06-01"); var res = await http.PostAsJsonAsync("http://127.0.0.1:3001/v1/messages", new { model = "qwen3.8-27b-abliterated", max_tokens = 1024, messages = new[] { new { role = "user", content = "hello" } }, }); Console.WriteLine(await res.Content.ReadAsStringAsync());
#include <cpr/cpr.h> #include <cstdlib> #include <iostream> int main() { std::string key = std::getenv("YOURBRAND_KEY"); auto res = cpr::Post( cpr::Url{"http://127.0.0.1:3001/v1/messages"}, cpr::Header{{"x-api-key", key}, {"anthropic-version", "2023-06-01"}, {"Content-Type", "application/json"}}, cpr::Body{R"({ "model": "qwen3.8-27b-abliterated", "max_tokens": 1024, "messages": [{"role":"user","content":"hello"}] })"}); std::cout << res.text << "\n"; }
require "json" require "net/http" res = Net::HTTP.post( URI("http://127.0.0.1:3001/v1/messages"), { model: "qwen3.8-27b-abliterated", max_tokens: 1024, messages: [{ role: "user", content: "hello" }], }.to_json, "x-api-key" => "#{ENV['YOURBRAND_KEY']}", "anthropic-version" => "2023-06-01", "Content-Type" => "application/json", ) puts res.body
package main import ( "fmt" "io" "net/http" "os" "strings" ) func main() { body := `{ "model": "qwen3.8-27b-abliterated", "max_tokens": 1024, "messages": [{"role":"user","content":"hello"}] }` req, _ := http.NewRequest("POST", "http://127.0.0.1:3001/v1/messages", strings.NewReader(body)) req.Header.Set("x-api-key", os.Getenv("YOURBRAND_KEY")) req.Header.Set("anthropic-version", "2023-06-01") req.Header.Set("Content-Type", "application/json") res, err := http.DefaultClient.Do(req) if err != nil { panic(err) } defer res.Body.Close() out, _ := io.ReadAll(res.Body) fmt.Println(string(out)) }
Response
{
"id": "msg_4e1a…",
"type": "message",
"role": "assistant",
"model": "qwen3.8-27b-abliterated",
"content": [{ "type": "text", "text": "Hello! What are you building?" }],
"stop_reason": "end_turn",
"stop_sequence": null,
"usage": { "input_tokens": 9, "output_tokens": 8 }
}
Stream events, in order
message_startThe message with empty content and input token usage.content_block_startOpens text block 0.content_block_deltaRepeated. Each carries atext_delta.content_block_stopCloses block 0.message_deltastop_reasonand output token usage.message_stopThe stream is done.
POST/v1/messages/count_tokensCount tokensBearer · x-api-key
How many input tokens a Messages request would use, without running it.
Example request
curl http://127.0.0.1:3001/v1/messages/count_tokens \ -H "x-api-key: $YOURBRAND_KEY" \ -H "anthropic-version: 2023-06-01" \ -H "Content-Type: application/json" \ -d '{"model":"qwen3.8-27b-abliterated","messages":[{"role":"user","content":"hello"}]}'
Response
{ "input_tokens": 9 }
Embeddings and audio
One request, one complete response. Example requests for each model are on Models.
POST/v1/embeddingsCreate embeddingsBearer · x-api-key
Embeddings for one or more inputs, in input order, in OpenAI's format.
POST/v1/rerankRerank documentsBearer · x-api-key
The documents you send, ordered by relevance to a query, each with its index and score, most relevant first.
POST/v1/audio/speechCreate speechBearer · x-api-key
The spoken audio of a text, in OpenAI's format. The response is the audio file, not JSON.
POST/v1/audio/transcriptionsTranscribe audioBearer · x-api-key
The text of an audio file, in OpenAI's format. The file is sent as multipart form data.
Images and video
Images come back in the same call. Videos run as jobs you poll, then download. Example requests for each model are on Models.
POST/v1/images/generationsGenerate imagesBearer · x-api-key
The generated images, inline, in OpenAI's format.
POST/v1/videosCreate a videoBearer · x-api-key
Returns a job id at once. Poll GET /v1/videos/{id} until the job is completed, then download the video from GET /v1/videos/{id}/content. The video is stored encrypted and deleted with its job an hour after it completes.
Models
Every model in the catalog. No key needed.
GET/v1/modelsList models
Every model id in OpenAI's list format, so client.models.list() works.
Example request
curl http://127.0.0.1:3001/v1/models
Response
{ "object": "list", "data": [{ "id": "qwen3.8-27b-abliterated", "object": "model", "owned_by": "yourbrand" }, …] }
Errors
Each endpoint answers in its own family's error shape, so SDK error handling works unchanged.
| Status | Type | What to do |
|---|---|---|
400 | invalid_request_error | Fix the request. The message names the bad field, or a field we don't support. A request blocked for content the law forbids also gets a 400, and isn't charged. |
401 | authentication_error | Check the key and the auth header. |
404 | not_found_error | The model id or endpoint doesn't exist. |
429 | rate_limit_error | Over your plan's parallel limit. Wait Retry-After seconds. |
500 | api_error | Something failed on our side. Retry with backoff. |
503 | — | The model isn't serving right now. Retry, or switch models. |
OpenAI format, every other endpoint
{ "error": {
"message": "Model `nope` does not exist.",
"type": "not_found_error" } }Anthropic format, Messages and count_tokens
{ "type": "error",
"error": {
"type": "not_found_error",
"message": "model: nope does not exist." } }Rate limits
Limits count requests in flight, not requests per minute: a 429 means you're over your plan's parallel limit. There's no token-per-minute cap. Each 429 carries Retry-After in seconds.
| Plan | Parallel requests | Monthly |
|---|---|---|
| Pay as you go | 2 | — |
| Starter | 3 | $15 |
| Pro | 5 | $39 |
| Max | 8 | $99 |
Requests in flight
Retry code is in the error-handling guide.