API overview
On this page
The Mortar API is served by the data plane: the gateway that runs the model, whether in Mortar's cloud or in yours. The chat-completions and model endpoints follow the OpenAI API; the rest are Mortar's own.
Base URL
https://api.mortar.one/v1The health and readiness checks are the only endpoints outside /v1. With Bring Your Own Cloud, your deployment has its own base URL inside your network, and every path on this page works the same there.
Endpoints
| Endpoint | Purpose | Key needed |
|---|---|---|
POST /v1/chat/completions |
Generate a reply, whole or streamed | Yes |
POST /v1/generations/{id}/stop |
Stop a reply that is still being generated | Yes |
GET /v1/models |
List the models in the catalog | Yes |
POST /v1/cost/analyze |
Find what a prompt wastes on prefill | No |
POST /v1/cost/estimate |
Project a monthly bill at a cache hit rate | No |
GET /v1/rooms |
List saved conversations | Yes |
POST /v1/rooms |
Start a conversation | Yes |
PATCH /v1/rooms/{id} |
Rename or end a conversation | Yes |
DELETE /v1/rooms/{id} |
Delete a conversation | Yes |
GET /v1/rooms/{id}/messages |
Page through a conversation | Yes |
POST /v1/rooms/{id}/messages |
Save a message | Yes |
GET /v1/telemetry/stream |
Follow routing, cache and cost events | No |
GET /v1/metrics/stream |
Follow fleet-wide counters | No |
GET /v1/fleet |
Read sample deployments, quotas and KPIs | Yes |
GET /v1/platform |
Read the sample organization and catalog | No |
GET /v1/suggestions |
Read starter prompts | No |
GET /health |
Check that the data plane is up | No |
GET /readyz |
Check whether an instance should get traffic | No |
Authentication
Send an API key as a bearer token on every endpoint marked above. Authentication covers creating and revoking keys.
Authorization: Bearer $MORTAR_API_KEYRequests
Send request bodies as JSON with Content-Type: application/json. A body in any other format is refused with 415. Bodies are limited to 1 MiB; a larger one is refused with 413.
Successful JSON responses carry a weak ETag. Send it back in If-None-Match and Mortar answers 304 Not Modified with no body when nothing changed. JSON responses of 512 bytes or more are gzip-compressed when you send Accept-Encoding: gzip; event streams are never compressed.
Request IDs
Every response carries an X-Request-Id header. Send your own X-Request-Id and Mortar echoes it back; otherwise it generates one. Log it next to your own request: it's the fastest way to find a request when you contact support.
| Header | Direction | Meaning |
|---|---|---|
X-Request-Id |
Request and response | Correlates one request across your logs and Mortar's. |
X-Mortar-Request-Id |
Response | The chat completion's own ID, also returned as id in the body. |
Errors
Errors use the same envelope as the OpenAI API, so SDK error handling works unchanged.
{
"error": {
"message": "The model `gpt-4o` does not exist.",
"type": "invalid_request_error",
"code": "model_not_found"
}
}message is written for a person. Branch on code where there is one, otherwise on the HTTP status; code is present only when there's something specific you can do about the error.
Status codes
| Status | Type | Code | Meaning |
|---|---|---|---|
| 200 | The request succeeded. | ||
| 201 | A conversation or message was created. | ||
| 304 | Your cached copy is current. | ||
| 400 | invalid_request_error |
context_length_exceeded |
The body or a header isn't valid, or the prompt leaves too little room for a reply. |
| 401 | authentication_error |
missing_api_key, invalid_api_key |
The key is missing or not valid. |
| 403 | forbidden_origin |
A browser request came from a site Mortar doesn't trust. | |
| 404 | invalid_request_error |
not_found, model_not_found |
The endpoint, conversation or model doesn't exist. |
| 405 | invalid_request_error |
method_not_allowed |
The path exists but not with this method. |
| 409 | invalid_request_error |
room_limit_reached |
You've reached the limit of 200 saved conversations. |
| 413 | invalid_request_error |
input_too_large |
The body is larger than 1 MiB, or the cost analyser was sent more than 64 KiB of text. |
| 415 | unsupported_media_type |
The body isn't JSON. | |
| 429 | rate_limit |
You've sent more than 600 requests in a minute. | |
| 500 | server_error |
Something failed inside Mortar. Retry, and quote the request ID if it persists. | |
| 502 | upstream_error |
upstream_error, upstream_auth_error |
The model server failed or refused Mortar's credentials. |
| 503 | invalid_request_error, upstream_error, authentication_error, draining |
model_not_available, upstream_unavailable, verifier_unavailable |
The model or a service it depends on is unavailable, or the instance is shutting down. Retry with backoff. |
| 504 | upstream_error |
upstream_timeout |
The model server didn't answer in time. |
Rate limits
Each API key may send 600 requests per minute to a data-plane replica. Requests without a key are counted by client IP address instead. The window is fixed: it starts with your first request and resets one minute later.
Over the limit, Mortar answers 429 with a Retry-After: 60 header. Wait that long before retrying.
{
"error": {
"message": "Too many requests. Slow down and try again shortly.",
"type": "rate_limit"
}
}The cost analyser has a tighter limit of its own: 30 requests per minute, counted the same way.
When Mortar proxies to a model server that is itself rate limiting, the response is 429 with type rate_limit_error and code upstream_rate_limited, and Retry-After carries the model server's own value when it sent one.
OpenAI compatibility
Point an OpenAI SDK at the base URL above and chat completions work unchanged, with these differences:
- Streaming is the default. A request without
streamgets an event stream. Passstream: falsefor a single JSON response. - Supported fields. Mortar reads
model,messages,stream,stream_options.include_usage,max_tokens,user,tools,tool_choiceandparallel_tool_calls, and the tool calls and tool results messages carry. Other request fields, such astemperature, are accepted and ignored. - Text only. Message content may be a string or an array of parts; only the text parts are used.
- Default model. Leave out
modeland the request goes toQwen/Qwen2.5-7B-Instruct. - Prompt optimizer. Mortar can remove insignificant whitespace from JSON in system prompts and tool results before it processes a request. Unless your deployment turns it on, or off, it runs in shadow mode: it measures what it would remove and leaves the prompt unchanged. The
X-Mortar-Optimizerresponse header reports what it did or would have done, andX-Mortar-Optimize: offopts a request out. See chat completions. - Two OpenAI endpoints. Mortar implements
POST /v1/chat/completionsandGET /v1/models. Calls to other OpenAI endpoints, such as embeddings, return404.