Documentation

Documentation

One gateway, every client. Anthropic & OpenAI-compatible access to Claude Opus 5, Opus 4.8 and GPT 5.6.

Quick start

1
Create an account & top up
Register at /register, then top up your token wallet.
2
Copy your API key
Your key (sk-mvx-…) is on the dashboard. Keep it secret; rotate anytime.
3
Point your client at us
Use the config for your tool under Client Setup below.

Endpoints & base URL

Base URL depends on the tool. Claude Code & Anthropic-native tools want the root (they append /v1/messages). OpenAI-style SDKs want /v1. Domain is always ohhmyagent.com.
Endpoints
https://ohhmyagent.com/v1/messages          # Anthropic Messages API
https://ohhmyagent.com/v1/chat/completions   # OpenAI Chat Completions
https://ohhmyagent.com/v1/responses          # OpenAI Responses API (Codex)
https://ohhmyagent.com/v1/models             # list available models

Models

Available model IDs
ohh/claude-fable-5 # Claude Fable 5 (Fable Only wallet)
ohh/claude-opus-5         # Claude Opus 5  (GPT + Opus wallet)
ohh/claude-opus-4.8       # Claude Opus 4.8 (GPT + Opus wallet)
ohh/gpt-5.6        # GPT 5.6 auto-burst  (Sol -> Terra -> Luna)
ohh/gpt-5.6-sol    # pin GPT to the Sol deployment
ohh/gpt-5.6-terra  # pin GPT to the Terra deployment
ohh/gpt-5.6-luna   # pin GPT to the Luna deployment

Use ohh/gpt-5.6 for automatic burst routing across Sol → Terra → Luna. Add -sol/-terra/-luna only to pin a route. Fable is available only through ohh/claude-fable-5 and never falls back to GPT or Opus.

Plans, grants & scoped wallets

Purchases and admin grants create an entitlement in exactly one wallet scope. Grant Plan uses the same rules as checkout; it does not create a global balance.

Plan / grantModels unlockedEligible balance
GPT + Opusohh/gpt-5.6*, ohh/claude-opus-5, ohh/claude-opus-4.8GPT + Opus lots (all)
GPT Onlyohh/gpt-5.6*GPT Only lots first; then eligible GPT + Opus lots
Fable Onlyohh/claude-fable-5Fable lots only (fable)
Strict isolation: Fable never spends GPT Only or GPT + Opus balance. GPT/Opus never spend Fable balance. A negative balance in another wallet does not block a model while an eligible wallet still has positive balance or an active Unlimited entitlement.

Token allowances: GPT + Opus and Fable Only offer 30M / 90M / 150M / 300M / 450M. GPT Only receives its separately advertised allowance. Every token pack is stored as an independent 30-day lot; Unlimited extends only the selected scope.

API Reference

Authentication

Every request needs your API key (sk-mvx-…). Both header styles are accepted on every endpoint — send whichever your SDK produces:

Both work everywhere
# Anthropic style
x-api-key: sk-mvx-your-key
anthropic-version: 2023-06-01

# OpenAI / Bearer style
Authorization: Bearer sk-mvx-your-key
Keep keys server-side. One API key may address every public model, but access and billing follow the account's eligible scoped wallet. Rotate anytime from the dashboard — the old key dies instantly. Never embed the key in a browser/mobile app.

Request parameters

The gateway is a transparent proxy: send the native body of whichever API you call. Common fields:

FieldAPIDescription
modelbothOne of the model IDs above. Required.
messagesbothConversation array (role + content). Required.
max_tokensAnthropicMax output tokens. Required on /v1/messages.
max_completion_tokensOpenAIMax output tokens (GPT). Optional.
streambothtrue = SSE stream. Default false.
systemAnthropicSystem prompt (string or blocks).
temperature / top_pbothSampling. Ignored for Opus (thinking models strip it).
toolsbothFunction/tool definitions — see Tool calling.
reasoning_effortOpenAIGPT thinking depth: none·low·medium·high·xhigh.
output_config.effortAnthropicOpus thinking depth: low·medium·high·xhigh·max.
The dashboard does not set a reasoning effort. If your client omits the field, each model uses its native default; an explicit value in your API request is still forwarded when supported.

Response shape

You get back the native shape of the endpoint you called. The model field is our public slug (never the upstream deployment). Non-stream Anthropic example:

200 OK · /v1/messages
{
  "id": "msg_01…",
  "type": "message",
  "role": "assistant",
  "model": "ohh/claude-opus-5",
  "content": [{ "type": "text", "text": "Hello!" }],
  "stop_reason": "end_turn",
  "usage": { "input_tokens": 12, "output_tokens": 6 }
}
For Anthropic / Opus, wallet input is the full upstream prompt total counted once: fresh input_tokens + cache_creation_input_tokens + cache_read_input_tokens. GPT follows OpenAI semantics, where prompt_tokens already includes cached input. Upstream components are retained for auditing.

Streaming (SSE)

Set the stream field to true. You receive Server-Sent Events. Anthropic emits message_start → content_block_delta … → message_delta → message_stop; OpenAI emits chat.completion.chunk objects ending with [DONE]. The gateway translates transparently, so an Anthropic client streaming GPT still gets Anthropic-shaped events.

Streaming request
curl -N https://ohhmyagent.com/v1/messages \
  -H "x-api-key: sk-mvx-your-key" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"ohh/claude-opus-5","max_tokens":256,"stream":true,
       "messages":[{"role":"user","content":"Stream a haiku"}]}'
Billing on streams is charged once when the stream ends or when the client disconnects mid-stream — you always pay for tokens you received, never more.

Responses API (Codex)

The /v1/responses endpoint speaks the OpenAI Responses API (used by OpenAI Codex). Send an input (string or item array) plus optional instructions; set reasoning.effort for thinking depth. Both Opus and GPT model IDs work.

Request
curl https://ohhmyagent.com/v1/responses \
  -H "authorization: Bearer sk-mvx-your-key" \
  -H "content-type: application/json" \
  -d '{"model":"ohh/gpt-5.6",
       "input":"Write a haiku about the sea",
       "reasoning":{"effort":"medium"}}'

Regular response (non-stream) — one response object; the text is in output[].content[].text (also mirrored in output_text):

200 OK · non-stream
{
  "id": "resp_…",
  "object": "response",
  "status": "completed",
  "model": "ohh/gpt-5.6",
  "output": [
    { "type": "message", "role": "assistant",
      "content": [{ "type": "output_text", "text": "Waves…" }] }
  ],
  "output_text": "Waves…",
  "usage": { "input_tokens": 9, "output_tokens": 17, "total_tokens": 26 }
}

Streaming version — add "stream": true. You receive Responses SSE events in this order:

SSE event sequence
event: response.created
event: response.in_progress
event: response.output_item.added
event: response.content_part.added
event: response.output_text.delta      # ← repeated, the tokens
event: response.output_text.done
event: response.content_part.done
event: response.output_item.done
event: response.completed              # ← final, carries usage
Function-call tools stream as response.function_call_arguments.delta/.done between item events. GPT 5.6 also supports the Responses built-in web_search tool and emits response.web_search_call.* events; web_search_preview is accepted as a compatibility alias. Other unnamed built-in tools are not advertised as supported. Base URL for Codex is https://ohhmyagent.com/v1 with wire_api = responses — see the Codex setup under CLI Tools.

Tool / function calling

Full function calling on both endpoints, both models. The gateway maps tool_use ↔ tool_calls automatically. Anthropic form:

tools · Anthropic
{
  "model": "ohh/claude-opus-5",
  "max_tokens": 1024,
  "tools": [{
    "name": "get_weather",
    "description": "Get current weather for a city",
    "input_schema": {
      "type": "object",
      "properties": { "city": { "type": "string" } },
      "required": ["city"]
    }
  }],
  "messages": [{ "role": "user", "content": "Weather in Jakarta?" }]
}

OpenAI form uses a tools array of type:function objects and returns tool_calls. Send the tool result back as a tool_result (Anthropic) or a role:tool (OpenAI) message to continue.

Vision (images)

For image requests, use an image-capable model. Anthropic uses a base64 image block; OpenAI uses image_url (data URL or https URL).

Vision · Anthropic
{
  "model": "ohh/claude-opus-5",
  "max_tokens": 512,
  "messages": [{ "role": "user", "content": [
    { "type": "image", "source": {
      "type": "base64", "media_type": "image/png", "data": "<BASE64>" } },
    { "type": "text", "text": "What is in this image?" }
  ]}]
}

Reasoning effort

Control how hard the model thinks. Higher = deeper reasoning + more tokens.

ModelFieldValid values
Opus 5 / 4.8output_config.effortlow · medium · high · xhigh · max
GPT 5.6reasoning_effortnone · low · medium · high · xhigh
effort · Opus
{ "model":"ohh/claude-opus-5", "max_tokens":1024,
  "output_config": { "effort": "max" },
  "messages":[{"role":"user","content":"Prove there are infinitely many primes."}] }
The dashboard does not set a reasoning default. If your client omits the field, each model uses its native default; explicit per-request values are forwarded when supported.

Prompt caching

Prompt caching runs automatically upstream and speeds up repeated context. Billing is full-uncached and uniform across every model: wallet input equals the total prompt tokens the upstream reports — fresh input plus any cache creation and cache reads — with no cache discount. For Opus we automatically place cache breakpoints on stable prompt sections (system prompt, tools, older turns) and for GPT Azure caching is automatic; caching improves latency and upstream cost, but the wallet is charged on the full prompt_tokens the model processed. Keep the deployment, system prompt, tool order and older history stable for the best cache hit.

Error codes

CodeMeaningFix
400Bad request / invalid JSONCheck body & required fields.
401Invalid or missing keyVerify key; rotate on dashboard.
402Insufficient balanceTop up your token wallet.
403Account suspended / bannedOpen a support ticket.
404Wrong base URLClaude Code = root; SDKs = /v1. Never /v1/v1.
413Body exceeds the 16 MiB authenticated request safety boundaryReduce unusually large binary attachments; ordinary long agent context is accepted.
429ChatRateLimited / Rate limit exceededThe service automatically waits and retries for up to 95 seconds. If it still appears, reduce concurrency and avoid parallel bursts.
502/503Upstream hiccupAuto-retried; try again shortly.
529Upstream overloadedAuto-retried with backoff.

Rate limits & billing

Scoped billing. Fable uses only Fable lots. GPT uses GPT Only lots first, then eligible GPT + Opus lots. Opus uses only GPT + Opus lots. Wallets never cross-spend outside these rules.

Rate limits. 50 requests/minute per account (all keys share it) + 200 req/min per IP. Authenticated request body max 16 MiB. ChatRateLimited: Rate limit exceeded means your request rate exceeded the RPM controlled by our service; it is not an upstream incident.

GPT 5.6 supports burstable TPM. Sol, Terra and Luna use independent upstream deployment buckets. Very large or highly concurrent requests can still receive 429; stable prompt-cache hits help reduce additional TPM pressure.
Anthropic / Opus is not burstable. Output throughput uses an adaptive cap, typically around 3,000–6,000 output tokens per minute depending on current model and upstream conditions. Parallel long generations may be throttled even when input capacity remains available.
Context window is not TPM. Support for a large context does not mean several near-limit requests can run concurrently.

Retries. For 429, the service honors Retry-After, waits with jitter, and retries automatically for up to 95 seconds. Transient 502/503/529 use exponential backoff.

Expiry. Token packs last 30 days as independent lots, consumed nearest-expiry first. Unlimited stacks an access window instead of tokens.

Client Setup

Pick your tool. Anthropic-native tools use the root URL; OpenAI-compatible tools use /v1.

Claude CodeAnthropic native
Anthropic's official CLI + VS Code / Cursor extension.

CLI — root URL only; Claude Code appends /v1/messages.

Opus 5 · recommended
export ANTHROPIC_BASE_URL="https://ohhmyagent.com"
export ANTHROPIC_AUTH_TOKEN="sk-mvx-your-key"
export ANTHROPIC_DEFAULT_OPUS_MODEL="ohh/claude-opus-5"

claude --model opus

VS Code / Cursor extension — Windows, macOS, Linux

  1. Open Command Palette (Ctrl+Shift+P) → Preferences: Open User Settings (JSON).
  2. Paste the two keys below directly at the top level — do not nest claudeCode.environmentVariables inside itself.
  3. Run Developer: Reload Window, then start a new Claude Code session.
VS Code User settings.json
{
  "claudeCode.disableLoginPrompt": true,
  "claudeCode.environmentVariables": [
    { "name": "ANTHROPIC_BASE_URL", "value": "https://ohhmyagent.com" },
    { "name": "ANTHROPIC_AUTH_TOKEN", "value": "«redacted:sk-…»" },
    { "name": "ANTHROPIC_MODEL", "value": "ohh/claude-opus-5" },
    { "name": "ANTHROPIC_DEFAULT_OPUS_MODEL", "value": "ohh/claude-opus-5" },
    { "name": "ANTHROPIC_DEFAULT_SONNET_MODEL", "value": "ohh/claude-opus-5" },
    { "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL", "value": "ohh/claude-opus-4.8" }
  ]
}
Important: Base URL is the ROOT (no /v1). Claude Code appends /v1/messages; adding /v1 here creates a 404 at /v1/v1/messages. For GPT set DEFAULT_* values to ohh/gpt-5.6.
OpenAI Codex CLIOpenAI compatible
OpenAI's open-source terminal coding agent. Configured via ~/.codex/config.toml.
  1. Install: npm i -g @openai/codex
  2. Export your key so Codex can read it: export OHH_API_KEY="sk-mvx-your-key"
  3. Add a custom model provider in ~/.codex/config.toml:
~/.codex/config.toml
# ~/.codex/config.toml
model = "ohh/gpt-5.6"
model_provider = "ohh"

[model_providers.ohh]
name = "OhhMyAgent"
base_url = "https://ohhmyagent.com/v1"
env_key = "OHH_API_KEY"
wire_api = "responses"
Run
codex --model ohh/gpt-5.6 "Refactor this module"
codex --model ohh/claude-opus-5   "Review this diff"

Windows / VS Code integrated terminal

Windows PowerShell + %USERPROFILE%\.codex\config.toml
# %USERPROFILE%\.codex\config.toml
model = "ohh/claude-opus-5"
model_provider = "ohh"

[model_providers.ohh]
name = "OhhMyAgent"
base_url = "https://ohhmyagent.com/v1"
env_key = "OHH_API_KEY"
wire_api = "responses"

# PowerShell (current terminal)
$env:OHH_API_KEY = "«redacted:sk-…»"
# Persist for new terminals (reopen VS Code after this)
[Environment]::SetEnvironmentVariable("OHH_API_KEY", "«redacted:sk-…»", "User")
Current Codex versions require the OpenAI Responses API (wire_api = responses). On Windows, the integrated VS Code terminal uses the same %USERPROFILE%\.codex\config.toml and user environment variable. Do not use https://ohhmyagent.com here; OpenAI-compatible Codex requires https://ohhmyagent.com/v1.
CursorOpenAI compatible
AI code editor. Add an OpenAI-compatible custom key in Settings → Models.
  1. Cursor Settings → Models → scroll to OpenAI API Key → enable Override OpenAI Base URL.
  2. Base URL: https://ohhmyagent.com/v1
  3. API Key: sk-mvx-your-key
  4. Add a custom model: ohh/gpt-5.6 or ohh/claude-opus-5, then click Verify.
Cursor's agent features work best with a GPT ID (native OpenAI shape). Opus also works for chat.
ClineOpenAI compatible
Autonomous VS Code coding agent.
  1. Cline settings → API Provider → OpenAI Compatible.
  2. Base URL: https://ohhmyagent.com/v1
  3. API Key: sk-mvx-your-key
  4. Model ID: ohh/claude-opus-5 / ohh/gpt-5.6.
Roo CodeOpenAI compatible
Roo Code (Cline fork) VS Code agent.
  1. Roo Code → Settings → Provider → OpenAI Compatible.
  2. Base URL: https://ohhmyagent.com/v1 · API Key: sk-mvx-your-key.
  3. Add model ohh/gpt-5.6 or ohh/claude-opus-5 and enable it in the model list.
Kilo CodeOpenAI + Anthropic
VS Code AI agent.
  1. Settings → Providers → Add Custom Provider → OpenAI Compatible.
  2. Base URL: https://ohhmyagent.com/v1 · API Key: sk-mvx-your-key.
  3. Add models ohh/claude-opus-5, ohh/gpt-5.6.
Vision for custom Opus models: if the image badge is missing after refresh, add this model override in Kilo's custom provider config: attachment: true and modalities.input: ["text", "image"]. The model is vision-capable; this tells Kilo to expose the attachment UI.
Kilo custom model override
"claude-opus-4.8": {
  "name": "Claude Opus 4.8",
  "attachment": true,
  "modalities": { "input": ["text", "image"], "output": ["text"] }
}
Alternative: choose Anthropic Messages, Base URL https://ohhmyagent.com/v1 — Kilo calls /v1/messages. Same model IDs work.
OpenCodeOpenAI compatible
Terminal AI coding agent.
~/.config/opencode/opencode.json
{
  "$schema": "https://opencode.ai/config.json",
  "provider": {
    "ohh": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "OhhMyAgent",
      "options": { "baseURL": "https://ohhmyagent.com/v1", "apiKey": "{env:OHH_API_KEY}" },
      "models": {
        "claude-opus-5": { "name": "Claude Opus 5" },
        "gpt-5.6":       { "name": "GPT 5.6 · Auto Burst" }
      }
    }
  }
}
Run
export OHH_API_KEY="sk-mvx-your-key"
opencode run --model "ohh/claude-opus-5"  "Review this code"
opencode run --model "ohh/gpt-5.6" "Review this code"
AiderOpenAI compatible
Terminal pair-programmer. Uses OpenAI-compatible env vars.
Aider via OpenAI-compatible
export OPENAI_API_BASE="https://ohhmyagent.com/v1"
export OPENAI_API_KEY="sk-mvx-your-key"

aider --model openai/ohh/gpt-5.6
aider --model openai/ohh/claude-opus-5
Prefix the model with openai/ so Aider routes it through the OpenAI-compatible driver to our /v1 base.
Continue.devOpenAI compatible
VS Code / JetBrains AI extension. Edit ~/.continue/config.yaml.
~/.continue/config.yaml
models:
  - name: Opus 5
    provider: openai
    model: ohh/claude-opus-5
    apiBase: https://ohhmyagent.com/v1
    apiKey: sk-mvx-your-key
  - name: GPT 5.6
    provider: openai
    model: ohh/gpt-5.6
    apiBase: https://ohhmyagent.com/v1
    apiKey: sk-mvx-your-key
9Routeradvanced
Self-hosted LLM router/proxy that fronts many providers behind one endpoint. Project: decolua/9router ↗. This is the most flexible (and fiddliest) way to use us — two modes below.
Mode A — Custom Provider (API-key mode, recommended)
  1. Dashboard → Providers → Add Custom Provider.
  2. Type: OpenAI Compatible · API type: chat.
  3. Prefix: ohh · Base URL: https://ohhmyagent.com/v1 · API Key: sk-mvx-your-key.
  4. Add upstream model IDs claude-opus-5, claude-opus-4.8, gpt-5.6. 9Router exposes them as ohh/claude-opus-5 etc.
  5. For Anthropic-native routing, add a second provider node with a different prefix, type Anthropic, same /v1 base — 9Router will call /v1/messages.
Provider config
# 9router provider (conceptual)
provider: ohh
type: openai_compatible
base_url: https://ohhmyagent.com/v1
api_key: sk-mvx-your-key
models: [claude-opus-5, claude-opus-4.8, gpt-5.6]
Mode B — MITM / transparent interception

9Router can transparently intercept a tool that hard-codes api.anthropic.com / api.openai.com by installing its MITM CA and rewriting the upstream. Point the intercepted upstream to us:

  1. Enable MITM mode in 9Router and install/trust its root CA on your machine.
  2. Map the intercepted host to our upstream: api.anthropic.com → https://ohhmyagent.com (root, Anthropic) and api.openai.com/v1 → https://ohhmyagent.com/v1.
  3. Inject the auth header x-api-key: sk-mvx-your-key (or Bearer) on the rewritten request.
  4. Rewrite the model to a ohh/… ID if the tool sends an upstream-only name.
MITM mode is powerful but invasive (it decrypts your local TLS). Prefer Mode A unless a tool truly can't change its base URL. Never install a MITM CA on a shared or production machine.
LiteLLMOpenAI compatible
Python proxy/SDK unifying many LLMs. Register us as an openai-compatible model.
config.yaml
# litellm config.yaml
model_list:
  - model_name: claude-opus-5
    litellm_params:
      model: openai/ohh/claude-opus-5
      api_base: https://ohhmyagent.com/v1
      api_key: sk-mvx-your-key
  - model_name: gpt-5.6
    litellm_params:
      model: openai/ohh/gpt-5.6
      api_base: https://ohhmyagent.com/v1
      api_key: sk-mvx-your-key
Python / JS SDKofficial SDKs
Use the official Anthropic or OpenAI SDK — just change the base URL.
Python · anthropic
# Python · Anthropic SDK
from anthropic import Anthropic
client = Anthropic(api_key="sk-mvx-your-key", base_url="https://ohhmyagent.com")
msg = client.messages.create(
    model="ohh/claude-opus-5", max_tokens=512,
    messages=[{"role":"user","content":"Hello"}])
print(msg.content[0].text)
Node · openai
// Node · OpenAI SDK
import OpenAI from "openai";
const client = new OpenAI({ apiKey: "sk-mvx-your-key", baseURL: "https://ohhmyagent.com/v1" });
const r = await client.chat.completions.create({
  model: "ohh/gpt-5.6",
  messages: [{ role: "user", content: "Hello" }],
});
console.log(r.choices[0].message.content);
cURLraw HTTP
Raw HTTP — the same model IDs work on both endpoints.
Anthropic · /v1/messages
curl https://ohhmyagent.com/v1/messages \
  -H "x-api-key: sk-mvx-your-key" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"ohh/claude-opus-5","max_tokens":1024,
       "messages":[{"role":"user","content":"Hello!"}]}'
OpenAI · /v1/chat/completions
curl https://ohhmyagent.com/v1/chat/completions \
  -H "authorization: Bearer sk-mvx-your-key" \
  -H "content-type: application/json" \
  -d '{"model":"ohh/gpt-5.6",
       "messages":[{"role":"user","content":"Hello!"}]}'

FAQ

Which prefix — ohh/ or oma/?
Use ohh/. Bare canonical IDs such as claude-opus-5 / gpt-5.6 also resolve. Legacy shortened Opus IDs remain compatible, but are no longer advertised. There is no oma/.

Is GPT 5.6 OpenAI-only?
No — it works on both endpoints; we translate transparently. Pick the endpoint your SDK expects.

One key for all models?
One key can address every model ID, but the request is authorized and billed only from a wallet eligible for that model. Fable, GPT Only, and GPT + Opus balances remain separate.

Sol / Terra / Luna?
Three GPT 5.6 routes, same flat rate. ohh/gpt-5.6 auto-bursts; pin with -sol/-terra/-luna only if you want a fixed route.

Is my content stored?
No. We store only usage metadata (token counts, time, model). Conversation content is forwarded and not retained.

Troubleshooting

401 — check the key is correct & active; rotate on dashboard.

404 — wrong base URL. Claude Code = root (no /v1); SDKs = /v1. Never /v1/v1.

402 — top up your token wallet.

429 / ChatRateLimited — the request rate exceeded the service RPM limit, not an upstream issue. The service automatically waits and retries for up to 95 seconds. If it still appears, reduce concurrency, queue requests, and avoid parallel bursts.

529 — upstream busy; auto-retried — try again shortly.

wrong domain — always use ohhmyagent.com.

Still stuck? Email [email protected]