Model API
Call the platform catalog's text, image, speech, video and 3D models from https://api.origingame.ai/v1 with one account API token; the API works with the official OpenAI, Anthropic and Gemini SDKs.
Base URL and authentication
Every model call goes to one host:
| Use | URL |
|---|---|
| OpenAI-compatible API | https://api.origingame.ai/v1 |
| Anthropic SDK base URL | https://api.origingame.ai |
| Gemini API | https://api.origingame.ai/v1beta |
The origingame.ai site does not forward model requests, and browsers never relay model calls through the Portal. Call api.origingame.ai directly from your server or script.
Authenticate with the account API token (it starts with og-). Create, copy or rotate it at /me/access. An account has one; rotating it invalidates the old value at once. Signed-in devices and connected apps hold their own credentials and do not use this token.
| Header | Applies to | Notes |
|---|---|---|
Authorization: Bearer og-... | every endpoint | the default |
x-api-key: og-... | /v1/messages, /v1/messages/count_tokens | the Anthropic SDK's native header |
x-goog-api-key: og-... | /v1beta/models/* | the Gemini SDK's native header; ?key= is also accepted, but query strings end up in access logs, so prefer the header |
X-Origin-Org: <organization id> | optional | bill the organization's wallet and use its private channels; requires your permission to use that organization |
sk- keys keep working until 2026-12-31; copying and rotating now only return og-.The token acts as your account and spends your balance. Keep it in server-side environment variables; never put it in a web page or a game, or commit it to a repository.
Compatible protocols and SDKs
Point the official SDK's base URL at Origin and use your og- token as the API key.
OpenAI
Chat Completions (/v1/chat/completions) and Responses (POST /v1/responses) are supported. Responses has no WebSocket transport; use HTTP.
import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'https://api.origingame.ai/v1',
apiKey: process.env.OG_API_KEY,
}) import os from openai import OpenAI client = OpenAI(base_url="https://api.origingame.ai/v1", api_key=os.environ["OG_API_KEY"])
Anthropic
Messages (/v1/messages) and the unbilled POST /v1/messages/count_tokens (returns {input_tokens, estimated}) are supported. The Anthropic SDK appends /v1 itself, so its base URL has no /v1.
import os
import anthropic
client = anthropic.Anthropic(base_url="https://api.origingame.ai", api_key=os.environ["OG_API_KEY"])
message = client.messages.create(
model="MODEL_ID",
max_tokens=1024,
messages=[{"role": "user", "content": "Hello"}],
)
print(message.content[0].text) Replace MODEL_ID with an id from Listing models whose supported_endpoint_types contains anthropic.
Gemini
POST /v1beta/models/{model}:generateContent and :streamGenerateContent are supported; other Gemini actions return 404.
curl "https://api.origingame.ai/v1beta/models/MODEL_ID:generateContent" \
-H "x-goog-api-key: $OG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"contents":[{"parts":[{"text":"Hello"}]}]}' import os
from google import genai
from google.genai import types
client = genai.Client(
api_key=os.environ["OG_API_KEY"],
http_options=types.HttpOptions(base_url="https://api.origingame.ai"),
)
response = client.models.generate_content(model="MODEL_ID", contents="Hello")
print(response.text) For MODEL_ID, pick a model whose supported_endpoint_types contains gemini.
Listing models
GET /v1/models returns the models your token can use. The catalog changes as operations configure it, and account and token model restrictions shape the result, so rely on the answer you get rather than hard-coding ids.
curl https://api.origingame.ai/v1/models \ -H "Authorization: Bearer $OG_API_KEY"
The default answer is OpenAI-shaped ({"object":"list","data":[…]}). Each entry's supported_endpoint_types names the endpoints the model serves, for example openai, openai-response, anthropic, gemini, image-generation, audio-tts, openai-video. A request carrying both x-api-key and anthropic-version gets the Anthropic shape; one carrying x-goog-api-key gets the Gemini shape ({"models":[…]}).
Prices, capabilities and per-model integration guides with samples are in the model catalog; a single model is at /tools/models/<model id>.
For native GPT-Realtime-2.1 voice, endpoint metadata uses audio-realtime (GET /v1/realtime?model={model}), distinct from audio-stt-realtime (GET /v1/realtime?intent=transcription&model={model}) for standalone transcription.
Chat and streaming
The samples use gpt-5.6-sol. If your model list does not include it, use any id from the list whose supported_endpoint_types contains openai.
curl https://api.origingame.ai/v1/chat/completions \
-H "Authorization: Bearer $OG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.6-sol","messages":[{"role":"user","content":"Introduce yourself in one sentence"}]}' For streaming, add "stream": true; the response is SSE:
curl -N https://api.origingame.ai/v1/chat/completions \
-H "Authorization: Bearer $OG_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-5.6-sol","stream":true,"messages":[{"role":"user","content":"Write a short poem about pixels"}]}' import OpenAI from 'openai'
const client = new OpenAI({
baseURL: 'https://api.origingame.ai/v1',
apiKey: process.env.OG_API_KEY,
})
const stream = await client.chat.completions.create({
model: 'gpt-5.6-sol',
messages: [{ role: 'user', content: 'Write a short poem about pixels' }],
stream: true,
})
for await (const chunk of stream) {
process.stdout.write(chunk.choices[0]?.delta?.content ?? '')
} import os
from openai import OpenAI
client = OpenAI(base_url="https://api.origingame.ai/v1", api_key=os.environ["OG_API_KEY"])
stream = client.chat.completions.create(
model="gpt-5.6-sol",
messages=[{"role": "user", "content": "Write a short poem about pixels"}],
stream=True,
)
for chunk in stream:
if chunk.choices and chunk.choices[0].delta.content:
print(chunk.choices[0].delta.content, end="", flush=True) Endpoint reference
Every path is under https://api.origingame.ai; authentication is described in Base URL and authentication. Requests and responses match each vendor's native API; per-model request samples are on the model pages of the model catalog.
Text
| Method | Path | Notes |
|---|---|---|
| POST | /v1/chat/completions | OpenAI Chat Completions, with stream |
| POST | /v1/responses | OpenAI Responses (HTTP only) |
| POST | /v1/messages | Anthropic Messages |
| POST | /v1/messages/count_tokens | counts input tokens; no generation, no charge |
| POST | /v1/embeddings | embeddings |
| POST | /v1beta/models/{model}:generateContent | Gemini; :streamGenerateContent streams |
| GET | /v1/models | model list |
Images
| Method | Path | Notes |
|---|---|---|
| POST | /v1/images/generations | text to image |
| POST | /v1/images/edits | image editing |
Speech and audio
| Method | Path | Notes |
|---|---|---|
| POST | /v1/audio/speech | text to speech (OpenAI shape); Gemini TTS models use the task flow below and may answer 202 with task metadata |
| POST | /v1/audio/speech/tasks | Gemini TTS async task; Idempotency-Key required (1–128 visible ASCII characters) |
| GET | /v1/audio/speech/tasks/{id} | speech task status |
| GET | /v1/audio/speech/tasks/{id}/content | download the generated audio (task owner only) |
| GET | /v1/audio/voices?model=... | available preset voices |
| POST | /v1/audio/transcriptions | recorded audio to text, multipart file upload (for example model=gpt-transcribe, up to 25 MiB) |
| GET | /v1/realtime?model=gpt-realtime-2.1 | native GA realtime voice WebSocket (wss://); full-session funded cap and terminal provider usage (see below) |
| POST | /v1/realtime/client_secrets | reusable Gateway ogrt_ client capability, not a provider key |
| POST | /v1/realtime/calls | WebRTC: multipart sdp/session or application/sdp with capability defaults; local owned call Location |
| GET | /v1/realtime?call_id=... | call sideband WebSocket |
| POST | /v1/realtime/calls/{id}/{action} | SIP accept, reject, refer, hangup, using the original provider call id after signed webhook admission |
| POST | /v1/realtime/webhooks/{binding} | signed provider SIP inbox; not a client-authenticated call creation route |
| GET | /v1/realtime?intent=transcription&model=gpt-live-transcribe | live transcription WebSocket (wss://), mono PCM16 at 24 kHz, at most 60 seconds per turn |
| POST | /elevenlabs/v1/text-to-speech/{voice_id} | ElevenLabs native API, plus /stream and /with-timestamps |
| POST | /elevenlabs/v1/text-to-dialogue, /elevenlabs/v1/speech-to-text, /elevenlabs/v1/speech-to-speech/{voice_id} | ElevenLabs dialogue, transcription, voice changer |
| POST | /elevenlabs/v1/sound-generation, /elevenlabs/v1/music, /elevenlabs/v1/audio-isolation, /elevenlabs/v1/forced-alignment | ElevenLabs sound effects, music, voice isolation, alignment |
| GET | /elevenlabs/v1/voices, /elevenlabs/v1/models | ElevenLabs voices and models |
| POST | /v1/sound-generation, /v1/music, /v1/music/stream, /v1/audio-isolation, /v1/audio-isolation/stream, /v1/forced-alignment, /v1/speech-to-speech/{voice_id} | prefix-free aliases of the ElevenLabs endpoints above |
The live transcription WebSocket needs an Authorization header on the handshake, which browsers cannot set, so connect from a server.
Native GPT-Realtime-2.1
This describes the current workspace implementation, not a claim of production deployment or full verification. The GA native protocol passes through events including concurrent/out-of-band responses, VAD, tools, images, audio codecs and interruptions. Sessions are capped at 60 minutes. The 32 MiB serialized WebSocket message ceiling is a Gateway limit, not a universal upstream bound. Legacy beta session endpoints are not implemented. The strict intent=transcription GPT-Live path above remains separate from native voice and its input ASR.
Client capabilities last 10–7200 seconds, are reusable, and revalidate the parent credential on use; no provider key is returned. For SIP, operators configure the root runtime secret realtime.sip_bindings array (route, project_id, channel_id, user_id, webhook_secret). Signed inbox bindings establish the tenant, never phone headers. Users receive the original OpenAI event through a separate project webhook registration. Real SIP acceptance needs a provisioned project webhook, trunk and test phone; these are not yet available or verified.
Optional X-Origin-Realtime-Budget specifies a pre-funded full-session cap in USD (conservative default: $6.144 for gpt-realtime-2.1). Prices are frozen for the session. Authoritative terminal response and ASR usage are accounted for separately, with customer settlement capped at the funded amount. The platform bears excess, unpriced or unobserved usage. Termination is requested on loss of observation or budget protection; it is not guaranteed instantaneous. Client disconnect briefly drains cancellation usage; all closes conservatively mark observation incomplete rather than inventing usage.
Video
| Method | Path | Notes |
|---|---|---|
| POST | /v1/videos | create a video task |
| GET | /v1/videos/{id} | task status |
| GET | /v1/videos/{id}/content | download the finished video |
3D
| Method | Path | Notes |
|---|---|---|
| POST | /v1/3d/tasks | Hunyuan3D task; Idempotency-Key optional (up to 256 bytes) |
| GET | /v1/3d/tasks/{id}, /v1/3d/tasks/{id}/content | task status, GLB download |
| POST | /v1/tripo/tasks | Tripo task (generation, texture, remesh, rigging, animation, conversion); Idempotency-Key required (up to 256 bytes) |
| GET | /v1/tripo/tasks/{id}, /v1/tripo/tasks/{id}/content | task status, result download |
| POST | /meshy/openapi/v2/text-to-3d | Meshy text to 3D |
| POST | /meshy/openapi/v1/{resource} | other Meshy tasks: image-to-3d, multi-image-to-3d, remesh, convert, resize, retexture, rigging, animations, uv-unwrap, text-to-motion |
| GET | /meshy/openapi/{version}/{resource}/{id} | Meshy native task status; /stream streams progress |
| GET | /meshy/openapi/v1/animations/library | Meshy animation library (not billed) |
| GET | /meshy/tasks/{id}, /meshy/tasks/{id}/content | the platform's stored Meshy task status and main result |
| GET | /meshy/tasks/{id}/artifacts, /meshy/tasks/{id}/artifacts/{name}/content | list and download every artifact of a task |
Decisions and classification
| Method | Path | Notes |
|---|---|---|
| POST | /v1/decisions | OpenAI Decisions, model gpt-6-luna-decisions; only input tokens are billed |
| POST | /v1/systemone | TypeSafe classification (jev-* models) |
Media files
| Method | Path | Notes |
|---|---|---|
| POST | /v1/media/uploads, /v1/media/upload-authorizations, /v1/media/{id}/complete | upload input files |
| GET, DELETE | /v1/media/{id} | read or delete media metadata |
| GET | /v1/media/{id}/{file} | download media content |
| POST | /v1/media/download-authorizations | get a short-lived download link, for example {"task_id":"...","kind":"speech"} |
Async tasks
Video, speech tasks and 3D are asynchronous: the create request returns a task object at once (usually 202, 200 on some video channels); you then poll the status endpoint and download the result when it is done.
- Create the task and keep the returned
id. WhereIdempotency-Keyis required, generate a unique value for each new task. - Query
.../{id}every few seconds untilstatusiscompletedorfailed. - After
completed, download the result fromresult_urlor.../{id}/content.
curl https://api.origingame.ai/v1/tripo/tasks \
-H "Authorization: Bearer $OG_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: $(uuidgen)" \
-d '{"model":"tripo-v3.1","operation":"text","parameters":{"prompt":"A low-poly treasure chest","texture":true,"pbr":true}}'
curl https://api.origingame.ai/v1/tripo/tasks/TASK_ID \
-H "Authorization: Bearer $OG_API_KEY"
curl https://api.origingame.ai/v1/tripo/tasks/TASK_ID/content \
-H "Authorization: Bearer $OG_API_KEY" -o model.bin Common states: queued, in_progress, completed, failed, submission_unknown.
- Resending the same request with the same
Idempotency-Keyreturns the original task instead of creating another; the same key with different parameters returns409. submission_unknownmeans it is not known whether the provider accepted the job. Do not resubmit under a new key, or you may pay twice; the task's hold is kept for the platform to reconcile.- Generated files are kept for the platform's retention period; copy them to your own storage promptly.
Errors
Errors keep the shape of the protocol you called. OpenAI-compatible and Gemini endpoints:
{"error":{"message":"...","type":"new_api_error","param":"","code":"..."}} /v1/messages answers in the Anthropic shape: {"type":"error","error":{"type":"...","message":"..."}}. An unknown path is 404 with error.code not_found.
| Status | Example code | Meaning and what to do |
|---|---|---|
| 400 | model_price_error | invalid request, or the model has no published price yet |
| 401 | token missing, invalid or rotated | |
| 403 | insufficient_user_quota | not enough balance or plan allowance; see Billing |
| 403 | pre_consume_token_quota_failed | this token's budget is used up |
| 403 | risk_blocked | the account is restricted by risk control |
| 403 | the token is not allowed to use this model | |
| 409 | the same Idempotency-Key was sent with different parameters | |
| 429 | rate_limited | over the rate or concurrency limit; wait the Retry-After seconds, then retry |
| 5xx | the platform or provider is temporarily unavailable; for generation, check the task status before deciding to retry |
Environment variables
The platform's scripts and skills use these two variables; reuse the same names in your own code:
| Variable | Value | Notes |
|---|---|---|
OG_API_KEY | og-... | the account API token |
OG_AI_GATEWAY | https://api.origingame.ai | the API host, without /v1; this is the default, change it only for a local or test environment |
export OG_API_KEY=og-... export OG_AI_GATEWAY=https://api.origingame.ai curl "$OG_AI_GATEWAY/v1/models" -H "Authorization: Bearer $OG_API_KEY"