Calling models
The API follows OpenAI's chat completions format, so existing SDKs and tools work by changing the base URL and key.
Authentication
Create a key in Dashboard → API keys and send it as a bearer token. Requests are billed to the account that owns the key, from prepaid credits.
Authorization: Bearer ws_...
Endpoints
| Method | Path | What it does |
|---|---|---|
| POST | /v1/chat/completions | Chat completion. Supports stream, max_tokens, temperature, top_p, stop, seed and response_format. |
| POST | /v1/completions | Plain text completion. |
| GET | /v1/models | Public models with their prices and current status. |
| GET | /v1/usage?days=30 | Your spend by day and model, your balance, and this key's spend this month. |
curl https://api.weightship.com/v1/chat/completions \
-H "Authorization: Bearer $WEIGHTSHIP_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "alice/legal-qwen-8b", "stream": true,
"messages": [{"role": "user", "content": "Summarise clause 4"}]}'Structured outputs
Add response_format and the model can only produce text of that shape: every token is checked against the format as it's generated, so a reply can't come back with a missing field, an extra sentence or a code fence. It works the same as OpenAI's parameter, with a regex option on top.
| response_format | What you get |
|---|---|
| {"type": "json_schema", "json_schema": {"schema": {...}}} | JSON matching your schema exactly: the fields you list, the types and allowed values you set. The best choice for apps. |
| {"type": "json_object"} | Any JSON object. Say in your prompt which fields you want, or the model may answer with an empty object. |
| {"type": "regex", "regex": "(yes|no)"} | Text matching a pattern, for labels, codes and short fixed answers. |
curl https://api.weightship.com/v1/chat/completions -H "Authorization: Bearer $WEIGHTSHIP_API_KEY" -H "Content-Type: application/json" -d '{"model": "you/support-bot",
"messages": [{"role": "user", "content": "Can I return an opened blender?"}],
"response_format": {"type": "json_schema", "json_schema": {"schema": {
"type": "object",
"properties": {"answer": {"type": "string"}, "confidence": {"type": "string", "enum": ["low", "medium", "high"]}},
"required": ["answer", "confidence"], "additionalProperties": false}}}}'The format fixes the shape, not the content: a small model can still give a wrong answer in perfect JSON. Set max_tokens high enough for the whole object, because a reply cut off by the limit ends mid-JSON (its finish_reason is length). The same schema can be a rule when you train, and then the model learns the format too.
Billing behaviour
- You pay the model's input and output price per million tokens, as shown on its page.
- If
max_tokenswould cost more than your balance, we lower it to what you can afford. With no balance the API returns 402. - Each key can have a monthly spend limit (set it on the API keys page). Requests are capped to what's left of it, and once it's used up the key gets 429 with code
key_limit_reacheduntil the next month or a higher limit. - Streams that you close early are billed for the tokens already sent.
- Responses carry
x-ws-request-id; non-streaming responses also carryx-ws-cost-micros(1,000,000 = $1).
Rulebench API and MCP server
Test a system prompt's rules from code or from an agent. Part of Rulebench Pro; model calls are paid from credit, or from a connected provider key when you pass its key_id. Setup for Claude Code, Cursor and GitHub Actions is on the agents page.
| Method | Path | What it does |
|---|---|---|
| POST | /v1/rulebench/audits | Body {prompt, models?, messages?, name?, key_id?, wait?}. Reads the rules, writes the tests, starts one run per model. wait (seconds, up to 55) waits for results. |
| GET | /v1/rulebench/audits/:id?wait=50 | Scores per model, per-rule results and the failing replies. status is done when every run has finished. |
| POST | /v1/rulebench/audits/:id/retest | Same tests and models; with prompt it tests the new prompt as a revision, without it reruns the original. |
| POST | /v1/rulebench/audits/:id/fix | A revised prompt that fixes what broke, with a list of changes. |
| PUT | /v1/rulebench/audits/:id/schedule | Body {schedule: "daily" | "weekly" | null}: monitoring with email alerts. |
| POST | /mcp | The MCP server (streamable HTTP), with the same API key as a bearer token. |
Errors
| Status | Code | Meaning |
|---|---|---|
| 401 | invalid_api_key | Missing, wrong or revoked key. |
| 402 | insufficient_quota | Balance too low. Add credits. |
| 400 | bad_response_format | The response_format isn't usable: an unknown type, a schema that isn't an object, or a pattern that doesn't compile. |
| 404 | model_not_found | No such model, or it's private to someone else. |
| 429 | rate_limit_error | Too many requests on this key. Back off and retry. |
| 429 | insufficient_quota · key_limit_reached | This key reached its monthly spend limit. |
| 503 | pool_starting | The model's GPU was asleep and is starting. Retry in about a minute (see Retry-After). Nothing is charged. |
| 503 | pool_unavailable | The GPU pool is starting or unreachable. Retry with backoff. |