Section 01
One Gateway, Two Request Protocols
Mortera Cloud accepts OpenAI-style chat completions and Anthropic-style messages. The gateway resolves the requested catalog model, reserves one eligible billing mode, selects a healthy provider source, and settles against reported usage after delivery.
Supported Public Contract
Use GET /v1/models, POST /v1/chat/completions, POST /v1/messages, POST /v1/responses, POST /v1/completions, POST /v1/embeddings, GET /v1/key (the calling key's billing modes, allowed models, and tier), or GET /v1/credits (current PAYG balance and Token-package credits available to the calling key). Mortera Cloud does not expose image, audio, batch, or Assistants endpoints.
Section 02
Send a First Request
- 01
Create a Key
Create your key in Panel > API Keys and copy it anytime from the key list.
- 02
Read the Catalog
Call /v1/models and use an exact visible model id. Catalog availability is dynamic.
- 03
Generate a Unique Key
Optionally send a unique Idempotency-Key per logical request to protect retries from duplicate settlement; one is generated automatically when absent.
curl https://mortera.cloud/v1/chat/completions \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "YOUR_MODEL_ID", "messages": [{"role": "user", "content": "Hello from Mortera Cloud"}], "stream": false }'Section 03
Create and Protect API Keys
Keys are scoped to allowed billing modes and can also restrict models. Authentication accepts either a Bearer token or x-api-key. Do not send both.
mrt-...Every key starts with mrt- followed by a random secret. There is one key type: it works everywhere - production clients, the playground, any integration. Its allowed billing modes and model scope govern what it can do, and usage is billed to your account exactly the same either way.
Keys Stay Copyable
Keys are stored encrypted at rest, so you can copy the full value again from the API Keys console. They are still secrets: redact them from logs and never share them.
Section 04
Use the Exact Production Base URL
Mortera Cloud is served over HTTPS at mortera.cloud, which is the only host that exposes the API. OpenAI clients usually include /v1 in baseURL; Anthropic clients append /v1/messages themselves and therefore use the origin. Requests addressed to panel.mortera.cloud never reach the gateway.
| Client | Configured Base URL |
|---|---|
| OpenAI SDK | https://mortera.cloud/v1 |
| Anthropic SDK | https://mortera.cloud |
Every Endpoint Mortera Cloud Serves
| Endpoint | What It Supports |
|---|---|
/v1/chat/completions | The primary surface: OpenAI Chat Completions with streaming (SSE), tools, tool results, parallel tool calls, reasoning, JSON/schema output, and idempotency. Non-streaming and streaming are both first-class - the stream field on your request alone decides which one you get. |
/v1/messages | Anthropic Messages: the same full pipeline (wallet, routing, failover, tools, billing) with Anthropic-native wire shapes, streaming events, and prompt-cache markers on caching-capable models. |
/v1/models | The live catalog: every routable model with context window, output cap, modalities, supported parameters, capabilities, and pricing. |
/v1/responses | OpenAI Responses API: input items (text, images, function calls, function outputs), instructions, tools, reasoning effort, and the full streaming event grammar (response.created through response.completed). Translated at the edge onto the same routing, failover, and billing pipeline as chat. |
/v1/completions | The legacy text-completions surface: prompt in, text_completion out, streaming chunk deltas included - for older CLIs and scripts that never moved to chat. |
/v1/embeddings | OpenAI-shaped text embeddings for every embeddings model in the catalog (text-embedding-3-large, text-embedding-3-small, pplx-embed-v1-4b). Send a string or an array; the answer is the standard list shape with normalized prompt and total token usage. |
/v1/images/generations | OpenAI Images contract for image models such as gpt-image-2: prompt, optional size/quality/count. Finished images return inline as base64 PNG (or a hosted url), and usage rides the same mortera-billing header as chat. |
/v1/videos | OpenAI Sora-style video tasks for models such as seedance-2.0. POST /v1/videos creates a task and returns a Mortera Cloud vid_ id; poll GET /v1/videos/{id} until completed, then stream GET /v1/videos/{id}/content. Billing settles on the first completed poll. The gateway detects each source's task dialect automatically. |
/v1/key | The key you presented: its name, billing modes, model allow-list, caps, and fallback chain. |
/v1/credits | Wallet and Token balances for the key's account, in Rupiah and credits. |
You Decide Streaming - And Whether Usage Rides It
Nothing on the gateway forces a transport: the stream field on your request alone decides streamed or non-streamed, on every endpoint that accepts it. Inside a stream, stream_options.include_usage selects whether usage appears: omitted or true keeps usage frames (the gateway's default so dashboards always settle), while an explicit false removes every usage frame from your stream per the OpenAI convention - billing is unaffected either way, Mortera Cloud always captures usage upstream.
Section 05
Request Headers
All five API endpoints require authentication. The two generation routes also accept an optional unique Idempotency-Key - when absent, one is generated automatically. Header names are case-insensitive.
| Header | Requirement | Purpose |
|---|---|---|
Authorization: Bearer <key> | Required | Preferred authentication form for OpenAI-compatible callers. |
x-api-key: <key> | Alternative | Alternative authentication form, commonly used by Anthropic clients. |
Idempotency-Key: <unique> | Optional | Identifies one logical request and protects retries from duplicate settlement. Generated automatically when absent. |
Content-Type: application/json | Generation routes | Declares the JSON request body. |
x-mortera-locale: en | id | zh-CN | Optional | Overrides localized gateway error messages; otherwise the account locale is used. |
X-Title: <app name> | Optional | Names your app on the public Apps & Tools Leaderboard, the same app attribution header OpenRouter reads. |
HTTP-Referer: <https://your.app> | Optional | Your app's site. Credits the app by its domain when X-Title is absent. |
Section 06
OpenAI-Compatible Chat Completions
POST /v1/chat/completions accepts the common chat shape: model, messages (text and images), system messages, temperature, top_p, stop, max_tokens or max_completion_tokens, stream, tools, tool_choice, and parallel_tool_calls. All of these bridge correctly to an Anthropic-protocol source, multi-turn tool-call history included. response_format/structured_outputs, n, logprobs/top_logprobs, and provider-specific sampling extras (frequency_penalty, presence_penalty, seed, logit_bias) have no Anthropic equivalent and are only honored on a native OpenAI route - bridged to Anthropic, they are dropped rather than mistranslated.
curl https://mortera.cloud/v1/chat/completions \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "YOUR_MODEL_ID", "messages": [ {"role": "system", "content": "Answer concisely."}, {"role": "user", "content": "What is idempotency?"} ], "max_tokens": 300, "stream": false }'Section 07
Anthropic-Compatible Messages
POST /v1/messages accepts model, system, messages (text and images), max_tokens, temperature, top_p, stop_sequences, stream, tools, and tool_choice (including disable_parallel_tool_use). All of these bridge correctly to an OpenAI-protocol source, multi-turn tool-call history included. Extended thinking content and provider-specific tool types (for example built-in web search) have no OpenAI equivalent and are only honored on a native Anthropic route.
curl https://mortera.cloud/v1/messages \ -H "x-api-key: $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "YOUR_MODEL_ID", "max_tokens": 300, "system": "Answer concisely.", "messages": [{"role": "user", "content": "What is idempotency?"}], "stream": false }'Section 08
Discover Available Models
GET /v1/models returns active models that are visible in the picker, permitted by the key, and backed by at least one provider route that can serve them right now. Anything the catalog lists is dispatchable, so a listed id never fails with 422 model_unavailable for want of a route. It requires authentication but does not require Idempotency-Key.
curl https://mortera.cloud/v1/models \ -H "Authorization: Bearer $MORTERA_API_KEY"Catalog Response
Each item includes its canonical id, provider label, context window, capabilities, and current Pay As You Go and Token pricing metadata.
{ "object": "list", "data": [{ "id": "MODEL_ID", "object": "model", "owned_by": "provider", "created": 1786900000, "context_window": 128000, "capabilities": {}, "pricing": { "payg_per_1m_idr": { "in": 0, "out": 0, "cache": 0 }, "credit_per_1m": 2.5 } }]}Section 09
Read Responses, Usage, and Billing
Non-streaming success responses preserve the requested inbound protocol. Mortera Cloud normalizes usage and appends a mortera object describing the selected billing mode and the applicable settled amount.
OpenAI
{ "id": "chatcmpl_...", "object": "chat.completion", "model": "YOUR_MODEL_ID", "choices": [{ "index": 0, "message": { "role": "assistant", "content": "..." }, "finish_reason": "stop" }], "usage": { "prompt_tokens": 42, "completion_tokens": 18, "prompt_tokens_details": { "cached_tokens": 0 } }}# response header: mortera-billing: {"mode":"payg","charge_idr":125.5}Anthropic
{ "id": "msg_...", "type": "message", "role": "assistant", "model": "YOUR_MODEL_ID", "content": [{ "type": "text", "text": "..." }], "stop_reason": "end_turn", "usage": { "input_tokens": 42, "output_tokens": 18 }}# response header: mortera-billing: {"mode":"token","credits_used":0.52}Billing Fields Depend on the Selected Mode
Pay As You Go includes charge_idr and Token includes token_credit_used. Zero or inapplicable fields can be omitted.
Section 10
Streaming Is Server-Sent Events
Set stream: true on either generation endpoint. Mortera Cloud responds with text/event-stream, relays chunks as they arrive, and settles asynchronously from usage found in the stream.
Cross-Protocol Streaming Is Transformed Live
The gateway bridges JSON and streamed SSE between OpenAI and Anthropic alike. When the selected source speaks the other protocol, each event is translated into your inbound protocol's own wire format as it arrives - content, tool calls, and the final usage and stop reason all carry through, with no buffering beyond the translation itself. Anthropic-protocol sources automatically receive prompt-cache markers on the stable prefix when the model supports caching; requests that already manage cache markers are left untouched.
If a stream omits final usage, Mortera Cloud still bills the output already delivered - from the provider's mid-stream counts when they arrived, otherwise from the streamed characters. A completed stream idempotency record replays as a small non-stream JSON marker, so do not reconnect a completed stream with the same key.
Section 11
Basic Tool Calling
Native protocol requests pass tool definitions through. The bridge converts function/tool definitions, tool_choice, and tool results in both directions, and reconstructs tool calls in the target protocol's own shape - OpenAI tool_calls become Anthropic tool_use blocks and back, including every prior turn in multi-turn history, single or parallel calls, and both non-streaming responses and live streams.
{ "model": "YOUR_MODEL_ID", "messages": [{"role": "user", "content": "Weather in Jakarta?"}], "tools": [{ "type": "function", "function": { "name": "get_weather", "description": "Get the current weather", "parameters": { "type": "object", "properties": { "city": { "type": "string" } }, "required": ["city"] } } ]}Recursive Tool Schemas Are Flattened Automatically
Agent clients (ZCode, Claude Code, Cline, Kilo, OpenClaw, Hermes, and similar) routinely send tool definitions whose JSON Schemas reference themselves through local "$ref" pointers, plus assistant history that echoes reasoning blocks, and many upstream providers reject those outright. Mortera Cloud normalizes all of it before dispatch: local schema references are expanded inline with a bounded depth (remaining cycles become a permissive node), inert reasoning-echo content parts are dropped, tool results without content become empty text, and object-valued tool arguments are serialized - so agent tool calling and structured outputs work against every model on both protocols without any client-side changes. Requests that already conform are passed through untouched.
Provider-Specific Tool Types and Extended Thinking Stay Native
Function/tool calling - single or parallel, any tool_choice mode - is bridged reliably in both directions, streaming included. Provider-specific tool types (for example Anthropic's built-in web search) and extended thinking content have no equivalent on the other protocol and are not reconstructed across it. For those, route to a source matching your inbound protocol, or execute tools in your application and send the result in the next request (with a fresh Idempotency-Key if you rely on retry protection).
Section 12
Images, Video, And Embeddings
One key covers every modality, and every request names the canonical Mortera Cloud model id. Responses carry normalized usage and never reveal which source served the request - the catalog's output modalities tell you which surface a model speaks.
Text Embeddings
Send a string or an array of strings; the response carries one vector per input plus prompt and total token usage.
curl https://mortera.cloud/v1/embeddings \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "text-embedding-3-large", "input": "Mortera Cloud, one key for every modality" }'{ "object": "list", "data": [{ "object": "embedding", "index": 0, "embedding": [-0.08142313, -0.01452982, ...] }], "model": "text-embedding-3-large", "usage": { "prompt_tokens": 9, "total_tokens": 9 }}Image Generation
Images return inline as base64 PNG data (or a hosted url). Size, quality, and count are optional; usage is normalized into the same token model as chat.
curl https://mortera.cloud/v1/images/generations \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "gpt-image-2", "prompt": "a red circle on white", "n": 1, "size": "1024x1024", "quality": "low" }'Image Models Work From Chat Too
You do not have to call this endpoint from a special integration: send a normal chat completion to an image model - your message is the prompt - and Mortera Cloud routes it through the images pipeline internally, with the same billing and the same model list. Video models keep the dedicated task API below, because a video is a polled job rather than a single response.
Video Generation
Video generation is asynchronous: create a task, poll its status until completed, then stream the finished mp4 from the content endpoint. The id Mortera Cloud returns is the only one you ever see - the upstream task id stays internal. Billing settles on the first completed poll; an abandoned task's reserve is released automatically.
# 1. Create the task - the id Mortera Cloud mints is the only id you ever see.curl https://mortera.cloud/v1/videos \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "model": "seedance-2.0", "prompt": "a cat walks across a sunny room", "seconds": 5, "size": "480p" }'# -> {"id":"vid_...","object":"video","model":"seedance-2.0","status":"queued","created_at":...} # 2. Poll until completed.curl https://mortera.cloud/v1/videos/vid_... \ -H "Authorization: Bearer $MORTERA_API_KEY" # 3. Stream the finished mp4.curl https://mortera.cloud/v1/videos/vid_.../content \ -H "Authorization: Bearer $MORTERA_API_KEY" \ -o video.mp4Always Canonical
Every error, every model name, and every id in a media response is Mortera Cloud's own. Provider identities, status codes, and raw upstream bodies never appear in a customer response.
Section 13
Billing Modes, Reserve, and Fallback
Every admitted request uses exactly one billing mode. Mortera Cloud walks the modes allowed by the API key, ordered by the account's mode preference. Modes the key still allows are always tried, even if they are missing from the account preference.
Pay As You Go
Reserves estimated IDR from available balance, then debits actual input, output, and cache usage at the model's price snapshot.
Token
Reserves credits using the model's credit rate, then burns (input + output + cache) / 1M × credits-per-1M from actual usage - cache counts at full weight.
Admission Reserves Before Provider Dispatch
Input is estimated from request content and output from max_tokens or configured defaults. That estimate sizes the hold; it does not reject a request that still has leftover funds. A remaining Pay As You Go balance or Token credit of any amount greater than zero still admits. The hold is the smaller of the estimate and what remains. The request is rejected with insufficient_quota only when remaining funds are actually zero. On success the actual amount settles and unused reserve is released. Provider 4xx responses and all-source failures release the hold with no customer debit.
Billing Fallback Is Ordered, Not Split
If the first allowed mode cannot reserve the request, because the wallet is empty or a per-key spend ceiling is reached, Mortera Cloud tries the next mode allowed on that API key. One request never splits across modes or Token packages. Lock a key to one wallet by disabling the other mode on the key.
Section 14
Provider Routing and Failover
The public model id stays constant while Mortera Cloud chooses among configured sources for that model.
- Only active, enabled, priced, credentialed, margin-safe, and circuit-healthy sources are eligible.
- Subscription-first sources with allowance lead when configured; remaining candidates are ordered by estimated provider cost.
- Network errors, provider 5xx, and provider 429 responses advance to the next candidate in the same request.
- Provider 4xx responses other than 429 do not fail over; they return as invalid_request with upstreamStatus details.
- Optional cacheAffinityKey or cache_affinity_key can prefer the last healthy source for the same user and model for up to one hour when its estimated cost remains within the configured delta. Mortera Cloud strips this field before dispatch.
- Send a stable cacheAffinityKey (or cache_affinity_key) per conversation: it keeps prompt-cache-affine traffic on the same source, so follow-up turns skip cold caches and first tokens arrive markedly faster.
- Reasoning models think before the first token. When speed matters more than depth, send a lower reasoning_effort (or the provider's equivalent) - Mortera Cloud forwards it untouched.
Section 15
Idempotency and Safe Retries
Idempotency is scoped by user, API key, endpoint, and key value. The gateway hashes the complete JSON body and retains records for the configured security window.
Same Key, Same Body
A completed non-stream request replays its stored status and response without a second provider call or debit.
Same Key, Different Body
Returns 409 idempotency_conflict. Never recycle keys across logical requests.
Request Still Running
Returns 409 request_in_progress. Wait and retry the identical body with the same key.
Retry Algorithm
Reuse the same key and exact body after a transport failure, 500, or 502. Honor Retry-After when present and apply bounded exponential backoff with jitter.
Section 16
Balance Is The Only Usage Gate
A request is admitted when the account has Pay As You Go balance or Token credits that cover the reserved estimate. There is no requests-per-minute ceiling, no concurrent-stream slot, no burst throttle, and no daily spend quota.
| Limit | Scope | Behavior |
|---|---|---|
| Wallet Balance | Per account, Pay As You Go rupiah plus remaining Token credits | 429 insufficient_quota when neither mode has spendable funds. An in-flight request is reserved at admission and settled against actual usage; if the provider delivers output without a usage frame, tokens are estimated from the delivered bytes so the hold is never frozen. |
Check Your Panel And Credits Endpoint
GET /v1/credits reports the calling key's current Pay As You Go balance and Token credits. Mortera Cloud does not emit remaining-rate-limit counters because there is no request-rate limit.
Section 17
Canonical Errors and Retry Policy
Gateway failures use a stable error.code and localized message. Some errors add details. Retry-After is sent only when the gateway has a concrete reset delay.
{ "error": { "code": "insufficient_quota", "message": "This account has no remaining Pay As You Go balance or Token credits.", "details": {} }}| HTTP | Code | Meaning | Action |
|---|---|---|---|
| 400 | invalid_request | Malformed JSON body, invalid parameters, or a malformed Idempotency-Key in a Mortera Cloud request. | Fix before retrying |
| 400 | context_window_exceeded | The estimated input plus requested output tokens exceed the Mortera Cloud model's context window. Shorten the prompt, lower max tokens, or use a larger-context model. | Fix before retrying |
| 401 | unauthorized | The Mortera Cloud API key is missing, invalid, revoked, or unknown. | Fix before retrying |
| 403 | forbidden | The Mortera Cloud account is inactive, or the key is not permitted to use the requested model. | Fix before retrying |
| 404 | model_not_found | The model id is absent from the Mortera Cloud catalog, inactive, retired, or admin-only. | Fix before retrying |
| 404 | not_found | The path or method does not exist on Mortera Cloud - check the endpoint path against the reference table above. | Fix before retrying |
| 409 | idempotency_conflict | This Idempotency-Key was already used at Mortera Cloud with a different request body. | Fix before retrying |
| 409 | request_in_progress | An identical Idempotency-Key request is still in flight at Mortera Cloud and has not reached terminal state. | Retry same body and key |
| 413 | request_too_large | The request body exceeds the 32 MB limit Mortera Cloud accepts; split or shrink the payload. | Fix before retrying |
| 421 | invalid_host | The request's Host header is not mortera.cloud - check the base URL your Mortera Cloud client is configured with. | Fix before retrying |
| 422 | model_unavailable | Mortera Cloud maintenance is active, or every eligible source failed three full walks of the chain. The model is marked Degraded until a later request succeeds. | Back off; same body and key |
| 429 | rate_limited | A Mortera Cloud authentication-attempt throttle fired, or every eligible upstream source is temporarily benched after upstream rate limiting. Honor Retry-After when present. API keys themselves have no requests-per-minute or stream-slot ceiling. | Honor Retry-After |
| 429 | insufficient_quota | The Mortera Cloud wallet cannot cover the request's maximum cost - top up, or send a smaller prompt or max_tokens, then retry. | Add quota or change allowed mode |
| 429 | quota_exceeded | Unused. Daily spend quotas were removed from Mortera Cloud; a request without funds returns insufficient_quota. | Honor Retry-After |
| 500 | internal_error | An unexpected Mortera Cloud gateway failure occurred. | Retry same body and key |
| 502 | upstream_error | A Mortera Cloud routing attempt failed without completing three full walks (timeout, drop, or unknown dispatch). Exhausting every round returns model_unavailable instead. | Retry same body and key |
A provider-side customer error can retain its HTTP status while using code invalid_request and details.upstreamStatus. Do not retry it unchanged.
invalid_host is an edge guard that fires before authentication when a request's Host header isn't mortera.cloud. A correctly configured client pointed at https://mortera.cloud should never see it.
Section 18
Production Security Practices
Mortera Cloud authenticates every public model route by hashing the presented key. Keys are stored encrypted at rest so they stay copyable; your application is still responsible for secret handling and prompt-data policy.
- Keep keys on trusted servers. Never expose them in browser bundles, mobile binaries, screenshots, or public repositories.
- Redact Authorization, x-api-key, and full mrt- key values from logs and support reports.
- Use separate keys per environment or integration. Rotate immediately after suspected exposure and revoke the old key.
- Limit each key to only the models and billing modes it needs.
- Use only https://mortera.cloud in production and reject invalid TLS certificates.
- Prompt content and required request metadata are sent to the selected third-party AI provider. Do not submit data you are not authorized to process.
Section 19
Coding Tool Integrations
Any coding tool that speaks the OpenAI Chat Completions or Anthropic Messages protocol works against Mortera Cloud directly: point it at the Mortera Cloud base URL, paste a Mortera Cloud key, and pick a model id from /v1/models. No proxy or shim is required.
Idempotency Is Handled For You - never pin one fixed key
Mortera Cloud's generation routes treat Idempotency-Key as optional: when a client omits it, the gateway generates a unique key server-side, which is why every tool below works out of the box. Clients that can rotate the key per logical request (most SDKs and agents do) additionally get retry deduplication for free. The one anti-pattern is a client that attaches the same fixed key to every distinct prompt - that triggers 409 idempotency_conflict after the first prompt.
| Client | Protocol | Configured In |
|---|---|---|
| Claude Code | Anthropic Messages | Shell environment variables |
| Cline / Roo Code | OpenAI Chat Completions | VS Code extension settings |
| Cursor | OpenAI Chat Completions | Cursor Settings → Models |
| Continue | OpenAI Chat Completions | ~/.continue/config.yaml |
| Codex CLI | OpenAI Chat Completions (wire_api = "chat") | ~/.codex/config.toml |
| OpenCode | OpenAI Chat Completions | opencode.json (project root) |
| Kilo Code | OpenAI Chat Completions | VS Code extension settings |
Claude Code
Shell environment variables
- Point Claude Code at Mortera Cloud by exporting ANTHROPIC_BASE_URL and authenticating with a Mortera Cloud key through ANTHROPIC_AUTH_TOKEN.
- Optionally pin the main model with ANTHROPIC_MODEL and the lightweight background model with ANTHROPIC_SMALL_FAST_MODEL - any id from /v1/models works, not just Claude models.
- Start a new terminal so the variables are loaded, then run claude inside your project.
# ~/.zshrc or ~/.bashrc - Mortera Cloud keys come from the panelexport ANTHROPIC_BASE_URL="https://mortera.cloud"export ANTHROPIC_AUTH_TOKEN="mrt-..."export ANTHROPIC_MODEL="claude-opus-5"export ANTHROPIC_SMALL_FAST_MODEL="deepseek-v4-flash" claudeRequires Node.js 18+ (the Claude Code runtime). Requests land on Mortera Cloud's /v1/messages route and bill exactly like a direct API call.
Cline / Roo Code
VS Code extension settings
- Open the extension settings and set API Provider to OpenAI Compatible.
- Set Base URL to https://mortera.cloud/v1, paste your mrt- key, and enter a model id such as claude-opus-5.
- Save, then start a task - streaming and tool use are relayed as-is.
Cline and Roo Code are configured identically; both are listed here because their settings screens differ slightly.
Cursor
Cursor Settings → Models
- Open Cursor Settings → Models, scroll to the OpenAI API Key section, and paste your Mortera Cloud key.
- Enable Override OpenAI Base URL and enter https://mortera.cloud/v1.
- Add the Mortera Cloud model ids you want (for example claude-opus-5) under Custom Models and enable them.
Custom models power Chat, Cmd+K, and manual model selection. Cursor's Tab completion and some background agent features always run on Cursor's own infrastructure and are not billed through Mortera Cloud.
Continue
~/.continue/config.yaml
- Add the two models below to your Continue config - one for chat and edits, one inexpensive model for autocomplete.
- Reference your Mortera Cloud key through Continue's secrets syntax so the key never lands in the file.
- Reload the Continue extension; the models appear in the model picker immediately.
# ~/.continue/config.yamlname: Mortera Cloud Assistantversion: 1.0.0models: - name: Mortera Cloud Chat provider: openai model: claude-opus-5 apiBase: https://mortera.cloud/v1 apiKey: ${{ secrets.MORTERA_API_KEY }} roles: [chat, edit, apply] - name: Mortera Cloud Autocomplete provider: openai model: deepseek-v4-flash apiBase: https://mortera.cloud/v1 apiKey: ${{ secrets.MORTERA_API_KEY }} roles: [autocomplete]Roles control where each entry is offered: chat, edit, and apply for the main model, autocomplete for the fast one.
Codex CLI
~/.codex/config.toml
- Export your Mortera Cloud key as MORTERA_API_KEY in your shell profile.
- Register Mortera Cloud as a model provider in ~/.codex/config.toml with wire_api = "chat" - Mortera Cloud serves the OpenAI Chat Completions surface, and the Responses API is not part of the gateway yet.
- Run Codex CLI in your project; prompts are sent to the model you pinned (gpt-5.6-sol below).
# ~/.codex/config.tomlmodel = "gpt-5.6-sol"model_provider = "mortera" [model_providers.mortera]name = "Mortera Cloud"base_url = "https://mortera.cloud/v1"env_key = "MORTERA_API_KEY"wire_api = "chat"Because Codex CLI drives coding-agent loops, watch consumption in the panel: long sessions with large context windows burn tokens (and therefore credits or balance) faster than single-shot requests.
OpenCode
opencode.json (project root)
- Create an opencode.json in your project root that registers Mortera Cloud as an OpenAI-compatible provider.
- The apiKey field reads MORTERA_API_KEY from your environment, so the key stays out of the repository.
- List the model ids you want in the picker, then start opencode.
// opencode.json (project root){ "$schema": "https://opencode.ai/config.json", "provider": { "mortera": { "npm": "@ai-sdk/openai-compatible", "name": "Mortera Cloud", "options": { "baseURL": "https://mortera.cloud/v1", "apiKey": "{env:MORTERA_API_KEY}" }, "models": { "claude-opus-5": { "name": "Claude Opus 5 (Mortera Cloud)" }, "gpt-5.6-sol": { "name": "GPT-5.6 Sol (Mortera Cloud)" } } } }}The npm field must stay @ai-sdk/openai-compatible - that is the adapter OpenCode uses to speak the plain Chat Completions protocol.
Kilo Code
VS Code extension settings
- Open the Kilo Code panel settings and set API Provider to OpenAI Compatible.
- Fill in Base URL https://mortera.cloud/v1, your Mortera Cloud key, and a model id from /v1/models.
- Save the profile and start a task.
Kilo Code is a Cline fork, so the configuration matches Cline's and the same profile works in both.
Three Checks When a Tool Misbehaves
- Model ids are Mortera Cloud catalog ids, not upstream vendor spellings - list them with GET /v1/models. A wrong id returns 404 model_not_found.
- Generation needs funds: an active Pay As You Go balance or a Token package that covers the model. Without one you get 429 insufficient_quota.
- If you ever set Idempotency-Key yourself, it must be unique per logical request and reused across its retries - never one constant value.
Section 20
Troubleshooting
Every message code the API can answer with, and what each one means - the complete reference for decoding any error response.
| Code | Code | Meaning |
|---|---|---|
| 400 | invalid_request | Malformed JSON body, invalid parameters, or a malformed Idempotency-Key in a Mortera Cloud request. |
| 400 | context_window_exceeded | The estimated input plus requested output tokens exceed the Mortera Cloud model's context window. Shorten the prompt, lower max tokens, or use a larger-context model. |
| 401 | unauthorized | The Mortera Cloud API key is missing, invalid, revoked, or unknown. |
| 403 | forbidden | The Mortera Cloud account is inactive, or the key is not permitted to use the requested model. |
| 404 | model_not_found | The model id is absent from the Mortera Cloud catalog, inactive, retired, or admin-only. |
| 404 | not_found | The path or method does not exist on Mortera Cloud - check the endpoint path against the reference table above. |
| 409 | idempotency_conflict | This Idempotency-Key was already used at Mortera Cloud with a different request body. |
| 409 | request_in_progress | An identical Idempotency-Key request is still in flight at Mortera Cloud and has not reached terminal state. |
| 413 | request_too_large | The request body exceeds the 32 MB limit Mortera Cloud accepts; split or shrink the payload. |
| 421 | invalid_host | The request's Host header is not mortera.cloud - check the base URL your Mortera Cloud client is configured with. |
| 422 | model_unavailable | Mortera Cloud maintenance is active, or every eligible source failed three full walks of the chain. The model is marked Degraded until a later request succeeds. |
| 429 | rate_limited | A Mortera Cloud authentication-attempt throttle fired, or every eligible upstream source is temporarily benched after upstream rate limiting. Honor Retry-After when present. API keys themselves have no requests-per-minute or stream-slot ceiling. |
| 429 | insufficient_quota | The Mortera Cloud wallet cannot cover the request's maximum cost - top up, or send a smaller prompt or max_tokens, then retry. |
| 429 | quota_exceeded | Unused. Daily spend quotas were removed from Mortera Cloud; a request without funds returns insufficient_quota. |
| 500 | internal_error | An unexpected Mortera Cloud gateway failure occurred. |
| 502 | upstream_error | A Mortera Cloud routing attempt failed without completing three full walks (timeout, drop, or unknown dispatch). Exhausting every round returns model_unavailable instead. |
Use the API Key Checker at /checker to verify a key authenticates and see its allowed models, without spending a request or touching your prompt content.
Section 21
Contact Support
For account, billing, or gateway incidents, contact Mortera Cloud support.
Include the incident time, endpoint, model id, HTTP status, error code, and Idempotency-Key. Never include your full API key or sensitive prompt content.