API reference
Echo Token Station base URLs and authentication, the base URL for each SDK and tool, available endpoints, format conversion, streaming and main parameters.
Echo's API supports the OpenAI format and the Anthropic format. This page covers the endpoints (the URLs you call for each feature), authentication, streaming and the main parameters. For the details of requests and responses, follow each provider's API documentation.
Base URL and authentication
| Format | Base URL | Header that carries the key |
|---|---|---|
| OpenAI format | https://token.echohub.io/v1 | Authorization: Bearer KEY |
| Anthropic format | https://token.echohub.io | x-api-key: KEY or Authorization: Bearer KEY |
- The
x-api-keyheader works on the Anthropic-format endpoints (/v1/messages, and/v1/modelswhen it returns the Anthropic-format list). Other endpoints use theAuthorizationheader - The Anthropic format also requires the
anthropic-versionheader (for example2023-06-01). The Anthropic SDK sends it automatically - Only HTTPS is accepted
- If the path you call has no
/v1, you get HTTP 404 (the website's HTML page, not JSON) even with a correct key. If it has/v1twice, you get HTTP 404 (a JSONInvalid URLerror)
Base URL for each SDK and tool
Some SDKs need /v1 in the base URL and some add /v1 themselves. In the "Checked" column, "Yes" means we confirmed calls in Echo's test environment on 2026-09-27, and "No" means the value is based on the tool's official documentation.
| SDK or tool | Setting | Value | Checked |
|---|---|---|---|
| OpenAI SDK (Python, Node.js) | base_url, baseURL | https://token.echohub.io/v1 | Yes |
| Anthropic SDK (Python, Node.js) | base_url, baseURL | https://token.echohub.io | Yes |
Vercel AI SDK @ai-sdk/openai-compatible | baseURL | https://token.echohub.io/v1. To receive token counts, also set includeUsage: true | Yes |
Vercel AI SDK @ai-sdk/openai | baseURL | https://token.echohub.io/v1. The default is the Responses API; .chat() uses the Chat Completions API | Yes |
Vercel AI SDK @ai-sdk/anthropic | baseURL | https://token.echohub.io/v1. Unlike the Anthropic SDK, include /v1 | Yes |
LangChain ChatOpenAI | base_url (configuration.baseURL in TypeScript) | https://token.echohub.io/v1 | Yes |
LangChain ChatAnthropic | base_url (clientOptions.baseURL in TypeScript) | https://token.echohub.io | Yes |
LlamaIndex OpenAILike | api_base | https://token.echohub.io/v1. Also set is_chat_model=True and context_window | Yes |
LlamaIndex Anthropic | base_url | https://token.echohub.io. Only model names that LlamaIndex knows can be used | Yes |
| Claude Code | Environment variable ANTHROPIC_BASE_URL | https://token.echohub.io (Claude Code) | Yes |
| Codex CLI | base_url in config.toml | https://token.echohub.io/v1, wire_api = "responses" (Codex CLI) | Yes |
| Cursor, Cline, Dify, Continue, Roo Code, n8n | The base URL setting (Base URL or similar) | https://token.echohub.io/v1 | No |
Endpoints
| Method and path | Format | What it does | Models offered |
|---|---|---|---|
POST /v1/chat/completions | OpenAI | Continues a conversation (Chat Completions API) | Model list |
POST /v1/responses | OpenAI | Generates a response (Responses API) | Model list |
POST /v1/messages | Anthropic | Continues a conversation (Messages API) | Model list |
GET /v1/models | OpenAI, Anthropic | Returns the models the key can use | — |
POST /v1/embeddings | OpenAI | Converts text into a sequence of numbers (embeddings) | Model list |
POST /v1/completions | OpenAI | Continues a text (the older Completions API) | Model list |
POST /v1/images/generations | OpenAI | Generates images | Model list |
POST /v1/audio/speech | OpenAI | Turns text into speech | Model list |
POST /v1/moderations | OpenAI | Checks whether text violates a usage policy | Model list |
POST /v1/videos | OpenAI | Submits a video generation task | Video generation |
GET /v1/videos/{task ID} | OpenAI | Returns the progress of a video generation task | — |
GET /v1/videos/{task ID}/content | OpenAI | Returns the finished video file | — |
Not available
| Feature | Status |
|---|---|
Token counting (POST /v1/messages/count_tokens) | Not supported. Returns HTTP 404 |
Files (/v1/files), Batch API (/v1/batches), fine-tuning | Not supported. POST /v1/batches returns HTTP 404 and GET /v1/files returns HTTP 400 |
Image variations (POST /v1/images/variations) | Not supported |
Gemini format (/v1beta/models/...) | Not supported. Returns HTTP 401 |
Balance (/v1/dashboard/billing/...) | Not supported. Returns HTTP 404. Check your balance in the console |
Information about one model (GET /v1/models/{モデル ID}) | May return incorrect results. Even for a model we offer, it can return HTTP 200 with an error body saying does not exist. Use GET /v1/models to check models |
Not tested
| Feature | Status |
|---|---|
POST /v1/responses/compact | Passed to the upstream API as is. The response has not been checked |
Speech to text (POST /v1/audio/transcriptions) | Not checked |
Realtime API (/v1/realtime) | Not checked |
Model IDs
Put the ID of the model to call in model in the request. Echo model IDs are written the same way as the names used in the provider's API (for example deepseek-flash, claude-sonnet-5). The exact IDs are listed on each model's page in the model list.
You can also get the IDs of the models your key can use with GET /v1/models. With both the x-api-key and anthropic-version headers it returns the Anthropic-format list; otherwise it returns the OpenAI-format list.
curl "https://token.echohub.io/v1/models" \
-H "Authorization: Bearer $ECHO_API_KEY"Formats and models
You can call a model in a format different from its provider's. In that case, Echo's server converts the request and the response. After conversion, some parameters have no effect and some response fields differ from the provider's specification. We recommend calling each model in its provider's format.
| Model | Recommended format |
|---|---|
| Claude (Anthropic) | Anthropic format (/v1/messages) |
| OpenAI | OpenAI format (/v1/chat/completions or /v1/responses) |
| Others | OpenAI format (/v1/chat/completions) |
What changes with conversion (checked in Echo's test environment on 2026-09-27):
| Combination | What changes |
|---|---|
Calling a Claude model with /v1/chat/completions | response_format (structured output) has no effect. reasoning_effort is replaced with Claude's thinking setting. If you do not set max_tokens, it is 8,192. Input token counts are returned the OpenAI way, including cached tokens |
Calling a Claude or Gemini model with /v1/responses | Works, but some response fields differ from the OpenAI specification |
Calling an OpenAI or Gemini model with /v1/messages | Text, tool calls and streaming work. Some response fields differ from the Anthropic specification |
| Any combination | usage in the response may contain fields that are not in the provider's specification. Do not use those fields |
This conversion also happens when you call a Claude model from a tool that only uses the OpenAI format, such as Cline, Cursor and Dify.
Call the Anthropic format with curl
curl "https://token.echohub.io/v1/messages" \
-H "x-api-key: $ECHO_API_KEY" \
-H "anthropic-version: 2023-06-01" \
-H "content-type: application/json" \
-d '{
"model": "claude-sonnet-5",
"max_tokens": 1024,
"messages": [{"role": "user", "content": "日本の首都はどこですか?"}]
}'Call the Responses API
import os
from openai import OpenAI
client = OpenAI(
base_url="https://token.echohub.io/v1",
api_key=os.environ["ECHO_API_KEY"],
)
response = client.responses.create(
model="gpt-6-sol",
input="日本の首都はどこですか?",
)
print(response.output_text)Streaming
Streaming means receiving the answer piece by piece while the model writes it. Add "stream": true to the request and the answer is returned as SSE (a mechanism for receiving data from the server one event at a time). Echo forwards the data from the upstream API in order, without buffering it.
| Format | What arrives |
|---|---|
| OpenAI format (Chat Completions) | A series of data: {...} lines, ending with data: [DONE]. With include_usage set to true in stream_options, token counts arrive before [DONE] |
| OpenAI format (Responses API) | Events such as response.created, response.output_text.delta and response.completed |
| Anthropic format | message_start, content_block_start, content_block_delta, content_block_stop, message_delta and message_stop, in that order. ping may arrive in between. Token counts are in message_delta |
What arrives when the upstream API returns an error or the connection is cut in the middle of an answer, and how to check, is in "When streaming stops partway" in Errors and fixes.
curl -N "https://token.echohub.io/v1/chat/completions" \
-H "Authorization: Bearer $ECHO_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "deepseek-flash",
"stream": true,
"stream_options": {"include_usage": true},
"messages": [{"role": "user", "content": "自己紹介を 3 文でしてください。"}]
}'import os
from openai import OpenAI
client = OpenAI(
base_url="https://token.echohub.io/v1",
api_key=os.environ["ECHO_API_KEY"],
)
stream = client.chat.completions.create(
model="deepseek-flash",
messages=[{"role": "user", "content": "自己紹介を 3 文でしてください。"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True)import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://token.echohub.io/v1",
apiKey: process.env.ECHO_API_KEY,
});
const stream = await client.chat.completions.create({
model: "deepseek-flash",
messages: [{ role: "user", content: "自己紹介を 3 文でしてください。" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}import os
import anthropic
client = anthropic.Anthropic(
base_url="https://token.echohub.io",
api_key=os.environ["ECHO_API_KEY"],
)
with client.messages.stream(
model="claude-sonnet-5",
max_tokens=1024,
messages=[{"role": "user", "content": "自己紹介を 3 文でしてください。"}],
) as stream:
for text in stream.text_stream:
print(text, end="", flush=True)import Anthropic from "@anthropic-ai/sdk";
const client = new Anthropic({
baseURL: "https://token.echohub.io",
apiKey: process.env.ECHO_API_KEY,
});
const stream = client.messages.stream({
model: "claude-sonnet-5",
max_tokens: 1024,
messages: [{ role: "user", content: "自己紹介を 3 文でしてください。" }],
});
stream.on("text", (text) => {
process.stdout.write(text);
});
await stream.finalMessage();Main parameters
The available parameters and value ranges differ by model. Follow each provider's documentation.
Chat Completions (POST /v1/chat/completions)
| Parameter | Required | Description |
|---|---|---|
model | Required | Model ID |
messages | Required | The conversation so far: pairs of role (system, user, assistant and so on) and content |
stream | true to stream | |
stream_options | {"include_usage": true} to receive token counts at the end of a stream | |
max_completion_tokens | The maximum number of output tokens. The older max_tokens is deprecated by OpenAI | |
temperature, top_p | How varied the output is | |
stop | Strings that stop the output | |
tools, tool_choice | Definitions and selection for tool calls (the model calling external functions) | |
response_format | The output format, such as JSON. Has no effect on Claude models (see "Formats and models" above) | |
reasoning_effort | How deeply the model reasons before answering. Supported models only |
Messages (POST /v1/messages)
| Parameter | Required | Description |
|---|---|---|
model | Required | Model ID |
messages | Required | The conversation so far: pairs of role (user, assistant) and content |
max_tokens | Required | The maximum number of output tokens |
system | The system prompt (background instructions for the model) | |
stream | true to stream | |
temperature, top_p, top_k | How varied the output is. Anthropic's documentation deprecates temperature and top_k for newer models | |
stop_sequences | Strings that stop the output | |
tools, tool_choice | Definitions and selection for tool calls | |
thinking | Settings for extended thinking (reasoning before answering). Supported models only | |
metadata | Information attached to the request, such as an ID that identifies the user. Echo passes it to the upstream unchanged |
Echo removes three parameters, inference_geo, service_tier and speed, before passing the request to the upstream. The processing region is fixed for each model (Data handling).
Responses (POST /v1/responses)
| Parameter | Required | Description |
|---|---|---|
model | Required | Model ID |
input | The input: a string or an array of conversation items | |
instructions | Instructions for the system | |
stream | true to stream | |
max_output_tokens | The maximum number of output tokens | |
tools, tool_choice | Definitions and selection for tool calls | |
reasoning | Reasoning settings. Supported models only | |
store | Whether the upstream API stores the response. Echo passes it on unchanged. In the OpenAI API it defaults to true (stored) | |
previous_response_id | Treats the request as a continuation of an earlier response (not tested through Echo) |
Embeddings
curl "https://token.echohub.io/v1/embeddings" \
-H "Authorization: Bearer $ECHO_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "[埋め込みモデルの ID]", "input": "東京は日本の首都です。"}'You can find models that support embeddings in the model list. Both number arrays and base64 are supported.
Balance, usage and limits
- Check your balance and usage in the console (API keys and usage). There is currently no way to get your balance through the API
- Per-key spending limits, rate limits and the request size limit are in Limits and rate limits
Sources
| What | Source | Checked |
|---|---|---|
Calls to each endpoint, unavailable features and their HTTP statuses, 401 and 404 depending on /v1, the base URL for each SDK and tool (rows marked "Yes"), what changes with format conversion, forwarding of streams, removal of inference_geo and others, passing store on unchanged | Measured in Echo's test environment, with the same relay settings as production and a server that returns test responses in place of the upstream API | 2026-09-27 |
The three video generation endpoints (/v1/videos) | Measured in Echo's test environment (as above, with a server that returns test responses in place of the provider's API) | 2026-10-01 |
| The base URL settings of Cline, Cursor, Dify, Continue, Roo Code and n8n | https://docs.cline.bot/provider-config/openai-compatible , https://cursor.com/docs/settings/api-keys , https://github.com/langgenius/dify-official-plugins/tree/main/models/openai_api_compatible , https://docs.continue.dev/customize/model-providers/top-level/openai , https://roocodeinc.github.io/Roo-Code/providers/openai-compatible , https://docs.n8n.io/integrations/builtin/credentials/openai | 2026-09-27 |
Chat Completions parameters, stream_options and [DONE], deprecation of max_tokens | https://developers.openai.com/api/reference/resources/chat | 2026-09-26 |
| Streaming events of the Responses API | https://developers.openai.com/api/docs/guides/streaming-responses | 2026-09-26 |
The default of store in the Responses API (true when not set) | https://developers.openai.com/api/reference/resources/responses/methods/create | 2026-09-27 |
| Messages API parameters | https://platform.claude.com/docs/en/api/messages | 2026-09-26 |
Messages API streaming events, messages.stream in the SDK | https://platform.claude.com/docs/en/build-with-claude/streaming | 2026-09-26 |