WHATOTP / DEVELOPERS

From idea to first request.

Set up your account, choose a model and get your first response. Runnable examples and an API reference for text-based Chat Completions.

01. Send your first request

  1. Create an account and verify your email. You can resend the verification email from Settings.
  2. Create a key in API Keys, copy it when shown and save it as WHATOTP_API_KEY in your server environment.
  3. Install the SDK with npm install openai for Node.js or pip install openai for Python. cURL needs no SDK.
Base URLhttps://whatotp.com/v1

The SDK base URL ends in /v1. The address below comes from this installation’s APP_URL setting. Save the Node.js example as hello-world.mjs and run node hello-world.mjs; run the Python example with python hello-world.py.

The cURL examples use Bash/zsh syntax. In PowerShell, use curl.exe and read the environment variable with $env:WHATOTP_API_KEY.

Go to API keys
hello-world.mjs
import OpenAI from "openai";
const ai = new OpenAI({
apiKey: process.env.WHATOTP_API_KEY,
baseURL: "https://whatotp.com/v1",
maxRetries: 0
});
const response = await ai.chat.completions.create({
model: "auto",
messages: [{ role: "user", content: "Hello, world!" }]
});
console.log(response.choices[0]?.message.content);
A familiar start with the OpenAI SDK

02. Authentication and keys

Send the Authorization: Bearer header with every API request. Your dashboard browser session does not replace a /v1 API key. Keys are shown only at creation; store them in a server environment variable.

Authorization: Bearer $WHATOTP_API_KEY

Standard accounts need a verified email to create keys and use live models. Keys can have an expiration date and model restrictions. Revoked or expired keys return 401 on new requests; a disallowed model returns 403.

03. Choose a model from the catalog

GET/v1/models

The response has the shape { object: "list", data: [...] }. Use an id from data as your model. The catalog lists enabled live models; an empty data array means no live model is currently listed.

cURL · GET /v1/models
curl "https://whatotp.com/v1/models" -H "Authorization: Bearer $WHATOTP_API_KEY"

auto selects the first enabled live model allowed by your key; it does not automatically retry another model on failure. Send an explicit catalog ID to keep using the same model. gpt-6-astra is also a public model alias; its visibility depends on configuration.

The catalog is not filtered by your key’s model permissions and does not guarantee a successful response. Key restrictions are enforced on completion requests; provider quotas or temporary outages may affect listed models.

04. Chat Completions

POST/v1/chat/completions

Use Content-Type: application/json. The entire request body must not exceed 1,000,000 bytes. Only the top-level fields below are supported; additional fields return 400.

FieldDescription
modelOptional string, 1–200 characters. A catalog id or auto. Defaults to auto, selecting the first enabled live model allowed by your key.
messagesRequired, 1–2000 messages. Roles: system, developer, user, assistant, tool. content is a string or text blocks. Assistants carry tool_calls; tool messages carry tool_call_id.
tools / tool_choice / parallel_tool_callsFunction tool definitions; auto, none, required or named tool selection; parallel call preference. Tools execute on the client; the provider/model must support tool calling.
top_p / stop / max_completion_tokensSampling, stop sequences and an alternative output budget. Use fields supported by your model.
response_format / seed / n / usertext, json_object or json_schema output format; seed; n=1 only; user label. Depends on provider support.
presence_penalty / frequency_penaltyOptional repetition penalties between -2 and 2.
streamOptional boolean; defaults to false. Set true for an SSE stream.
stream_optionsOptional { include_usage: boolean }. Send { include_usage: true } to request streaming usage. Availability depends on the provider.
temperatureOptional number between 0 and 2. The selected model may support a narrower range.
max_tokensOptional positive integer. Defaults and actual output limits depend on the provider; reasoning tokens may consume this budget.

Include conversation history in messages on every request; the API does not remember earlier messages for you. Read response text from choices[0].message.content.

Example response · model and usage values are illustrative
{
  "id": "req_example",
  "created": 1789257600,
  "object": "chat.completion",
  "model": "gpt-6-astra",
  "choices": [
    {
      "index": 0,
      "message": {
        "role": "assistant",
        "content": "Hello!"
      },
      "finish_reason": "stop"
    }
  ],
  "usage": {
    "prompt_tokens": 12,
    "completion_tokens": 3,
    "total_tokens": 15
  }
}

finish_reason: length indicates the output budget was reached. content may be empty or null; HTTP 200 alone does not guarantee usable text. usage is present when supplied by the provider.

05. Stream the response

With stream: true the response uses text/event-stream (SSE). Append choices[0].delta.content from data: events. choices may be empty in a usage event; not every event contains text.

stream.mjs
import OpenAI from "openai";
const ai = new OpenAI({
apiKey: process.env.WHATOTP_API_KEY,
baseURL: "https://whatotp.com/v1",
maxRetries: 0
});
const response = await ai.chat.completions.create({
model: "auto",
messages: [{ role: "user", content: "Hello, world!" }],
stream: true,
stream_options: { include_usage: true }
});
try {
for await (const chunk of response) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? "");
if (chunk.usage) console.error(chunk.usage);
}
} catch (error) {
console.error("Stream failed:", error);
} finally {
response.controller.abort();
}
A familiar start with the OpenAI SDK

In raw SSE, [DONE] is the completion marker. Handle error events and disconnects as failures; a stream can fail after the initial HTTP 200. Consume the SDK iterator with try/catch and keep partial replies distinct from completed ones.

Cancel generation with response.controller.abort() in Node.js or response.close() in Python. Close the connection when the user leaves. Network chunks may not match SSE event boundaries; buffer events when implementing a raw client.

06. Limits and usage records

  • Up to 15 completion requests per minute and 2 concurrent requests per user; up to 20 concurrent requests across the application. A user’s keys and Playground share these limits.
  • Provider/model limits may be lower and shared across users. This release applies no platform daily request/token quota or usage fee.
  • SDK automatic retries are disabled in the examples. For 429, wait for Retry-After when supplied; it may be seconds or an HTTP date. Retries also consume capacity.

Include X-Request-Id in support requests when available. Request history shows model, status, duration and token usage; ≈ means estimated usage. The dashboard can estimate missing provider usage; the API response does not always include usage. Early validation/authorization failures may not appear in history.

Check service status

07. Identify and handle errors

Example error response
{
  "error": {
    "message": "Invalid or revoked API key",
    "type": "authentication_error",
    "code": "invalid_api_key"
  }
}
HTTPCode / action
400invalid_request / model_not_found

Check JSON syntax, supported fields and the model ID in the catalog.

401invalid_api_key / unauthorized

The key may be missing, invalid, expired or revoked; the account must be active.

403email_verification_required / model_access_denied

Verify your email or choose a model allowed by your key.

413body_too_large

Reduce the request body to 1,000,000 bytes or less.

429rate_limited / concurrency_limit / upstream_error

Reduce request rate or concurrency. Respect Retry-After when present; otherwise use bounded retries with increasing delays.

499provider_unavailable

The client cancelled the request. Since the connection is closed, this may appear in request history rather than an HTTP response.

502upstream_error / provider_unavailable

The provider returned an error, was unreachable or sent an invalid response/stream. An upstream 503 can be returned by this API as 502.

503model_unavailable / provider_not_configured / gateway_unavailable / service_unavailable

No eligible live model is available, access is disabled, or discovery/service is unavailable. Check the catalog and status page.

504provider_timeout

The provider did not finish within the time limit. Try a shorter request or another model.

Without a live connection, Playground may offer a labeled demo; the public completion API does not generate demo replies and returns 503. Status-page measurements are historical observations.

08. SDK compatibility and scope

Available endpoints: GET /v1/models, POST /v1/chat/completions, POST /v1/messages, POST /v1/messages/count_tokens and POST /v1/responses. All three generation protocols support text, function tools, tool results and SSE. Tools execute on the client; the selected provider must also support tool calling.

Adapter scope: text and function tools. Images, files, server-side tools, extended thinking and persistent Responses sessions are unsupported. Use store=false and send full history in input; previous_response_id is unsupported. Reasoning/verbosity preferences are not forwarded to Chat Completions. Token counting is estimated (X-WhatOTP-Token-Count: estimated). Provider names may be replaced in response text; tool names and JSON arguments are preserved.

Get integration support

09. How to add a custom API to OpenCode, Claude Code and Codex

A custom API setup starts with three values: the service address (base URL), an API key and a model ID. This guide shows how to configure coding tools running in a terminal or your editor’s integrated terminal.

Protocol adapters are built into WhatOTP; connect directly with the same WhatOTP key. Text and tool-call flows are covered by automated tests; real client/model compatibility depends on the selected provider’s tool support. Disable extended thinking in Claude Code; use stateless Codex requests carrying full conversation history.

ToolRequired protocolStatus with this API
OpenCodeChat Completions/v1/chat/completions · tools + streaming
Claude CodeAnthropic Messages/v1/messages · tool_use + tool_result
CodexOpenAI Responses/v1/responses · function_call + function_call_output

Preparation: verify your key and model

  1. Verify your email and create a key in the dashboard’s API Keys section.
  2. Replace YOUR_WHATOTP_API_KEY below with your own key. These variables apply only to the current terminal session; launch the tool from that terminal.
  3. List the models. Use auto for the first connection check; for a fixed model, choose an id from data that your key is allowed to access.
macOS / Linux · Bash / zsh
export WHATOTP_API_KEY="YOUR_WHATOTP_API_KEY"
export WHATOTP_BASE_URL="https://whatotp.com/v1"
curl "$WHATOTP_BASE_URL/models" \
  -H "Authorization: Bearer $WHATOTP_API_KEY"
Windows · PowerShell
$env:WHATOTP_API_KEY = "YOUR_WHATOTP_API_KEY"
$env:WHATOTP_BASE_URL = "https://whatotp.com/v1"
Invoke-RestMethod -Uri "$env:WHATOTP_BASE_URL/models" -Headers @{
  Authorization = "Bearer $env:WHATOTP_API_KEY"
}

The base URL ends in /v1; do not append /chat/completions. For a local installation, use http://localhost:3000/v1. In OpenCode’s whatotp/auto selection, whatotp is the local provider name; only auto is sent as the API model. A successful model listing does not verify text generation or tool calls.

First connection test: request a short code explanation

Run the following request in the same terminal. A successful response should contain text in choices[0].message.content. This checks your WhatOTP key and text generation before configuring the editor.

Bash / zsh · POST /v1/chat/completions
curl "$WHATOTP_BASE_URL/chat/completions" \
  -H "Authorization: Bearer $WHATOTP_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"auto","messages":[{"role":"user","content":"Explain JavaScript Array.map in two sentences."}]}'
PowerShell · POST /v1/chat/completions
$body = @{
  model = "auto"
  messages = @(@{
    role = "user"
    content = "Explain JavaScript Array.map in two sentences."
  })
} | ConvertTo-Json -Depth 5
$response = Invoke-RestMethod -Method Post -Uri "$env:WHATOTP_BASE_URL/chat/completions" -Headers @{
  Authorization = "Bearer $env:WHATOTP_API_KEY"
} -ContentType "application/json" -Body $body
$response.choices[0].message.content

10. OpenCode: configure a custom provider

If OpenCode is not installed, install it from a terminal with Node.js/npm using the command below. Then create opencode.json in your project root or merge the settings into your existing file. For all projects, use ~/.config/opencode/opencode.json, or $HOME/.config/opencode/opencode.json on Windows.

Install OpenCode
npm install -g opencode-ai
opencode.json · Chat Completions
{
  "$schema": "https://opencode.ai/config.json",
  "model": "whatotp/auto",
  "small_model": "whatotp/auto",
  "provider": {
    "whatotp": {
      "npm": "@ai-sdk/openai-compatible",
      "name": "WhatOTP",
      "options": {
        "baseURL": "https://whatotp.com/v1",
        "apiKey": "{env:WHATOTP_API_KEY}"
      },
      "models": {
        "auto": {
          "name": "WhatOTP Auto"
        }
      }
    }
  }
}
  1. Run opencode in the terminal where WHATOTP_API_KEY is set.
  2. Open /models and select WhatOTP Auto. Its presence confirms that the configuration loaded.
  3. For a specific model, replace the auto key under models with its catalog id, and set model and small_model to whatotp/MODEL_ID.

The @ai-sdk/openai-compatible package selects the Chat Completions protocol. Keep {env:WHATOTP_API_KEY} exactly as shown; OpenCode reads it from the environment. You do not need to put the key in JSON or additionally use /connect.

tools, tool_choice, parallel tool calls and tool messages are supported. OpenCode executes file and terminal operations in its own environment; WhatOTP carries tool calls and results to the model. Select a tool-capable model and verify the connection with a small file-reading task.

OpenCode custom provider reference

11. Claude Code: connect through a gateway

Claude Code’s Anthropic Messages requests are translated to Chat Completions by the built-in /v1/messages adapter. Use the WhatOTP root URL for ANTHROPIC_BASE_URL; the client appends /v1/messages.

Install Claude Code from its official guide. Use your WhatOTP key and a tool-capable catalog model. auto selects the first available model; pinning a specific model is more consistent.

Bash / zsh · WhatOTP
export ANTHROPIC_BASE_URL="https://whatotp.com/"
export ANTHROPIC_AUTH_TOKEN="YOUR_WHATOTP_API_KEY"
export ANTHROPIC_MODEL="auto"
export ANTHROPIC_DEFAULT_HAIKU_MODEL="auto"
export ANTHROPIC_DEFAULT_SONNET_MODEL="auto"
export ANTHROPIC_DEFAULT_OPUS_MODEL="auto"
export MAX_THINKING_TOKENS="0"
claude --model "$ANTHROPIC_MODEL"
PowerShell · WhatOTP
$env:ANTHROPIC_BASE_URL = "https://whatotp.com/"
$env:ANTHROPIC_AUTH_TOKEN = "YOUR_WHATOTP_API_KEY"
$env:ANTHROPIC_MODEL = "auto"
$env:ANTHROPIC_DEFAULT_HAIKU_MODEL = "auto"
$env:ANTHROPIC_DEFAULT_SONNET_MODEL = "auto"
$env:ANTHROPIC_DEFAULT_OPUS_MODEL = "auto"
$env:MAX_THINKING_TOKENS = "0"
claude --model $env:ANTHROPIC_MODEL

The local root URL is http://localhost:3000. Both Authorization: Bearer and x-api-key are accepted. Point auxiliary model variables at a catalog model as well. Also disable extended thinking in the client settings.

Text, tool_use, tool_result, parallel tools and SSE events are supported. Image/PDF blocks, server tools and extended thinking are unsupported. cache_control hints do not guarantee caching. count_tokens returns an estimate.

Use the same gateway in the VS Code extension

Open Preferences: Open User Settings (JSON) in VS Code and merge these settings. Enter your key and model, then restart the extension. value fields do not automatically expand shell variables.

VS Code · settings.json · WhatOTP
{
  "claudeCode.environmentVariables": [
    {
      "name": "ANTHROPIC_BASE_URL",
      "value": "https://whatotp.com/"
    },
    {
      "name": "ANTHROPIC_AUTH_TOKEN",
      "value": "YOUR_WHATOTP_API_KEY"
    },
    {
      "name": "ANTHROPIC_MODEL",
      "value": "auto"
    },
    {
      "name": "ANTHROPIC_DEFAULT_HAIKU_MODEL",
      "value": "auto"
    },
    {
      "name": "ANTHROPIC_DEFAULT_SONNET_MODEL",
      "value": "auto"
    },
    {
      "name": "ANTHROPIC_DEFAULT_OPUS_MODEL",
      "value": "auto"
    },
    {
      "name": "MAX_THINKING_TOKENS",
      "value": "0"
    }
  ]
}

In the CLI, use /status to check the Anthropic base URL and credential source, then send a short message. If the gateway only accepts the x-api-key header, use ANTHROPIC_API_KEY instead of ANTHROPIC_AUTH_TOKEN; AUTH_TOKEN sends Authorization: Bearer.

12. Codex: custom provider settings

Use wire_api = "responses" for Codex. WhatOTP’s /v1/responses adapter connects text, function_call, function_call_output and streaming events to the Chat Completions provider.

Install Codex CLI
npm install -g @openai/codex

Your user file is ~/.codex/config.toml, or $HOME/.codex/config.toml on Windows. Place model and model_provider before table headers. Select a tool-capable catalog model.

~/.codex/config.toml · WhatOTP Responses
model = "auto"
model_provider = "whatotp"
disable_response_storage = true

[model_providers.whatotp]
name = "WhatOTP"
base_url = "https://whatotp.com/v1"
env_key = "WHATOTP_API_KEY"
wire_api = "responses"
macOS / Linux · Bash / zsh
export WHATOTP_API_KEY="YOUR_WHATOTP_API_KEY"
codex
Windows · PowerShell
$env:WHATOTP_API_KEY = "YOUR_WHATOTP_API_KEY"
codex

Codex appends /responses to base_url. env_key names the environment variable. The adapter is stateless: use store=false and full input history. previous_response_id, server-side compaction, custom tool types and WebSocket transport are unsupported; use HTTP/SSE and function tools.

For the IDE extension, open the user configuration and select the same provider; the editor process running the extension must also receive the environment variable. Defining it in an already-open editor’s terminal does not pass it to a running extension. Fully close the application and restart it from the terminal where the variable is set.

Current Codex configuration reference

13. Check the setup and troubleshoot

First run the simple text request in Quickstart, then check the tool configuration. This distinguishes key/model errors from protocol incompatibility. An agent launching or listing a model does not establish a successful integration.

  • 401 / 403: Check key expiration, email verification, model permissions and whether the environment variable is set for the correct process. With a gateway, client → gateway and gateway → WhatOTP credentials may differ.
  • 404 or an HTML response: Claude Code uses the root URL; OpenCode/Codex use the /v1 URL. Check for duplicated paths such as /v1/v1.
  • 400 invalid_request: An unsupported feature such as images, extended thinking, custom tool types or persistent Responses history may have been sent. Check the text/function-tool scope and client settings.
  • Model missing: Check the OpenCode models entry and provider/model ID. A gateway’s exposed model name may differ from the upstream WhatOTP ID.
  • 429 / 503: Reduce concurrent requests, wait for Retry-After when present and check the status page. Auxiliary agent requests share the user’s limits.

Configuration sources for these examples were checked on September 13, 2026. As tool versions change, consult the official references linked above. To verify the currently supported connection, use the Node.js, Python or cURL Chat Completions examples.

Back to runnable API examples