API documentation
TokenKiln speaks the OpenAI API shape. Anything that works with the OpenAI SDKs works here — change the base URL and key, keep your code.
Quickstart
Your base URL is your deployment origin plus /api/v1. Create an API key from the dashboard, then:
curl https://your-gateway.up.railway.app/api/v1/chat/completions \
-H "Authorization: Bearer tk_..." \
-H "Content-Type: application/json" \
-d '{
"model": "tokenkiln/default",
"messages": [{"role": "user", "content": "Hello!"}]
}'Python (openai ≥ 1.0):
from openai import OpenAI
client = OpenAI(
base_url="https://your-gateway.up.railway.app/api/v1",
api_key="tk_...",
)
response = client.chat.completions.create(
model="tokenkiln/default",
messages=[{"role": "user", "content": "Hello!"}],
)
print(response.choices[0].message.content)JavaScript / TypeScript:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://your-gateway.up.railway.app/api/v1",
apiKey: "tk_...",
});
const stream = await client.chat.completions.create({
model: "tokenkiln/default",
messages: [{ role: "user", content: "Hello!" }],
stream: true,
});
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
}Authentication
Pass your key as a bearer token: Authorization: Bearer tk_…. Keys are shown once at creation and stored only as SHA-256 hashes. Revoke a key at any time from the dashboard; revocation is immediate.
Streaming
Set "stream": truefor server-sent events, token by token, identical to OpenAI's format (terminated by data: [DONE]). Usage is metered from the engine's own token counts. If you also want the usage summary chunk in your stream, pass "stream_options": {"include_usage": true}.
Embeddings
POST /embeddingsis proxied to the same backend and billed at the model's input-token rate.
curl https://your-gateway.up.railway.app/api/v1/embeddings \
-H "Authorization: Bearer tk_..." \
-H "Content-Type: application/json" \
-d '{"model": "your/embedding-model", "input": "The quick brown fox"}'Models
GET /models lists available models. Catalog models carry a pricing extension field (USD per million tokens). See the models page for the human-readable version.
Billing model
- Credits are prepaid; balances are tracked in micro-dollars.
- Before dispatch, the gateway checks your balance against a worst-case estimate (request size +
max_tokens). - After the response, you're charged for actual engine-reported usage — never the estimate.
- Failed upstream requests are never billed.
- Each response carries an
x-request-idheader that matches your dashboard activity log.
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Missing, malformed, or revoked API key. |
| 402 | insufficient_quota | Prepaid balance can't cover the request's worst-case cost. Top up. |
| 404 | model_not_found | The model isn't in the catalog. |
| 429 | rate_limit_error | Too many requests per minute for this key. Honor Retry-After. |
| 429 | monthly_key_limit_exceeded | The key's monthly spend cap is exhausted. |
| 502/504 | server_error | The GPU backend failed or timed out. You are not charged. |
Error bodies follow the OpenAI shape: { "error": { "message", "type", "code" } }