onomeoonomeoBeta

Your tools. One API key.

Connect your AI tools with one onomeo key. Choose a currently listed model and check its price; paid site models require a top-up and are billed by usage.

OpenAI-compatible

Use these details in any OpenAI-compatible tool.

Base URL
https://onomeo.com/v1
API key
Model

Integrations

Don’t see your tool? Any OpenAI-compatible app can connect.Read the docs

When it does not connect

Some tools want the base URL with /v1 on the end, some add it themselves.

401, invalid key
The key was copied with a space on the end, or that key was from a browser whose site data has since been cleared.
404, not found
The base URL has /v1 twice, or none at all. Try it the other way.
400, model not allowed
The tool sent its default model name. Paste the Model value from above in its place.
402, insufficient balance
The balance is too low; this only happens on paid models, such as Claude and GPT. The message and the ways field say what would cover it: a free model, which is not charged, or what a fresh conversation would need. To add to the balance, top up on the Pricing page.
403 or 429, free-model call limit
With account_quota, network_quota (403) or site_busy (429; 403 when this message alone exceeds the site-wide limit), the free-model calls for this window are used up, or fewer are left than this message needs. Coding tools send the whole conversation and their files every time, and a longer message counts as several calls; see Billing and limits in the docs for how length is counted. Retry after the wait the response gives, or switch to a paid big model. With too_fast, too many requests came in one minute, whatever the model; wait a moment and retry.
An empty reply
Some tools set a very low output cap. Raise it, or leave that setting blank.

API documentation

Integrate onomeo's powerful AI models into your application with a simple and unified API. Build something great.

Quick start

Make your first API request in minutes. You'll need an API key and can use any HTTP client or OpenAI-compatible SDK.

POST/v1/chat/completions

Creates a chat completion response from one of onomeo's models.

Runnable versions of everything on this page, one file each in Python, Node and curl, are on GitHub.

Authentication

Use your API key in the Authorization header. Keep your key secure and never share it in client-side code.

Authorization: Bearer YOUR_API_KEY

Your balance lives on your account, so a lost key is recoverable — sign in again and create a new one on the My account page. Still, treat the key itself as a secret: do not commit it, do not share it. A key seen in use from several places at once gets disabled.

Leaked keys

When one of your keys appears in a public GitHub repository, GitHub notifies us within seconds and the key is disabled straight away. An email then goes to the address on your account, naming the key and where it was found.

A disabled key stops working immediately: any request still carrying it is answered with 401 unauthorized. Your account, your balance and your other keys are unaffected.

What to do next

  1. Create a replacement key in the console and put it into your application.
  2. Remove the old key from your code. Deleting the line is not enough: the key remains in the repository history, so rewrite the history, or treat that key as permanently public.
  3. Keep keys out of source code altogether. Read them from an environment variable or a secrets manager, and list the file holding them in .gitignore.

If you notice a leak yourself

Disable the key yourself in the console — it takes effect at once — then create a replacement. If you suspect someone else has used it, contact us and we will go through that key's request history with you.

Chat completions

Send a list of messages to a model and receive a generated response. This is the core endpoint for conversational AI. Request and response bodies follow the OpenAI shape.

Response

Reply
{
  "model": "MODEL_ID",
  "choices": [{
    "message": { "role": "assistant",
                 "content": "..." }
  }],
  "usage": { "total_tokens": 150 }
}

Current billing rules are loading. Check the model price before sending.

Answers returned through the API to accounts without a balance end with the line "— via onomeo.com". Accounts with a balance do not get it. Tool-call answers, structured-output answers and answers that consist of a single JSON object or array are never changed. The line is not counted in usage, and calls made on your own provider key are returned as they are.

Parameters

The following parameters are commonly used with /v1/chat/completions.

ParameterTypeDescription
modelstringThe exact model ID from the current Models page.
messagesarrayA list of message objects with role and content.
temperaturenumberControls randomness. Use 0.0 for deterministic output.
max_tokensintegerCurrent output limits and billing rules are loading.
streambooleanWhether to stream the response (default: false).
import requests

response = requests.post(
    "/v1/chat/completions",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={"model": "MODEL_ID", "messages": [
        {"role": "user", "content": "Hello!"}
    ]}
)
print(response.json())

Streaming

Set stream to true and you get server-sent events, same format as the OpenAI API. Every official client handles this out of the box.

Streamed request, Python
from openai import OpenAI

client = OpenAI(api_key="YOUR_API_KEY", base_url="/v1")
stream = client.chat.completions.create(
    model="MODEL_ID",
    messages=[{"role": "user", "content": "Hello!"}],
    stream=True,
)
for chunk in stream:
    if chunk.choices:
        print(chunk.choices[0].delta.content or "", end="")

Streaming uses the same billing rules as a non-streaming request. Token-billed models include provider-reported input, output and reasoning usage; usage is not the dollar charge. See Billing and limits and the usage history for the final charge.

Images

Models that read images take pictures inside a user message: put the text and each image as parts of content, each image as a base64 data URL.

Request with an image
{
  "model": "MODEL_ID",
  "messages": [{
    "role": "user",
    "content": [
      { "type": "text", "text": "What is in this picture?" },
      { "type": "image_url",
        "image_url": { "url": "data:image/jpeg;base64,/9j/4AAQ..." } }
    ]
  }]
}

Models that read images right now: Loading the list…

Current billing rules are loading. Check the model price before sending.

Other endpoints

The same key works on the endpoints below, so a tool built for another provider's request format can be pointed at this site as well. Each is called with POST, and the key goes in the Authorization header as Bearer unless a row says otherwise.

EndpointWhat it does
/v1/messagesAnthropic format, for Claude Code and other tools that use only that format. The key may also go in the x-api-key header. It takes this site's paid models (for accounts that have topped up) and models on your own keys, not the free models.
/v1/responsesOpenAI Responses format, used by Codex. It takes the same models as chat completions.
/v1beta/models/{model}:generateContentGoogle Gemini format, for Gemini CLI and other tools that use only that format: generateContent, streamGenerateContent (add alt=sse for server-sent events) and countTokens, with the model name in the path; GET /v1beta/models lists the models. The key may also go in the x-goog-api-key header or the key query parameter.
/v1/completionsThe older text completion format. The prompt is passed to the model as one user message and the answer comes back as text. One prompt per request; echo and logprobs are not supported.
/v1/embeddingsTurns text into vectors for search and knowledge bases. Models: loading. Up to 2,048 inputs per request; only gemini-embedding-001 accepts dimensions; encoding_format may be float or base64.
/v1/rerankOrders documents by how well they match a query, with the request fields used by Jina and Cohere: model, query, documents, top_n and return_documents. Models: loading.
/v1/audio/transcriptionsTurns speech into text. Send the audio as a multipart form field named file, at most 25 MB; response_format may be json, text or verbose_json. Models: loading.
/v1/images/generationsGenerates images using the available models. See the model list for current prices. Each image is charged to your balance only after it is generated and saved; failed images are not charged. n is the number of images, size is a supported size (such as 1024x1024), and response_format may be url or b64_json. Images are saved under Mine on the Works page.
/v1/videosMakes a short video with sound from one sentence, charged to the balance by the second. See Videos below.

Videos

POST /v1/videos makes a short video with sound from one sentence. The request body is JSON with these fields:

FieldDescription
modelA video model from the table at the end of this section.
promptOne sentence describing the video.
secondsThe length in seconds, one of those the model offers.
sizeOptional. Width by height, such as "1280x720" for landscape or "720x1280" for portrait.
resolutionOptional, in place of size: one of the model's resolutions, such as "480p" or "720p".
aspect_ratioOptional, with resolution: "16:9" or "9:16".
first_frameOptional, on models that take it: the picture the video starts on, as a data:image/…;base64 string.
last_frameOptional, on models that take it, and only with first_frame: the picture the video ends on, in the same form.
reference_imagesOptional, on models that take them: an array of pictures whose people, objects and style the video follows, in the same form. Not together with first_frame or last_frame.
Start a video
curl "/v1/videos" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "MODEL_ID",
    "prompt": "A lighthouse on a cliff at dusk, waves breaking below",
    "seconds": 5,
    "size": "1280x720"
  }'

The reply comes at once. It carries the video's id, status in_progress and progress 0:

Reply
{
  "id": "video_abc123",
  "object": "video",
  "model": "MODEL_ID",
  "status": "in_progress",
  "progress": 0,
  "created_at": 1760500000,
  "seconds": 5,
  "size": "1280x720"
}

Ask GET /v1/videos/{id} until status is completed, when the reply also carries url and completed_at, or failed, when it carries error with code and message. A video usually takes one to two minutes. GET /v1/videos/{id}/content downloads the MP4 file.

Check on the video, then download it
curl "/v1/videos/video_abc123" \
  -H "Authorization: Bearer YOUR_API_KEY"

curl -L "/v1/videos/video_abc123/content" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -o video.mp4

A video is charged to the balance by the second, at the price of its resolution, only once it has been made; a video that fails is not charged. The models and their prices right now:

ModelLengthsPrice per secondPictures it takes
Loading the list…

Models

These are the models you can call right now. If free models are offered, they are not charged and are limited by number of calls. For paid models the cost column is measured, not promised: a 30-day average of what one answer cost, in dollars, so a long answer costs more and a short one less.

Models are served through independent third-party providers but use the same request shape, so switching models only changes one string in your code. The list can change without notice: read it from the models endpoint at runtime rather than hard-coding names.

ModelRough cost per reply
Loading the list…

The same list, with who made each model, is on the Models page. To list them from code, call the models endpoint with your key:

List the models
curl "/v1/models" \
  -H "Authorization: Bearer YOUR_API_KEY"

Billing and limits

Current billing rules are loading. Check the model price before sending.

Each model's price is on the Pricing page

LimitValue
Loading the limits…

Check your balance any time from the My account page, or from code. The reply gives balance in the site's internal unit; divide it by money.unitsPerUsd from GET /api/info to get dollars:

Balance
curl "/api/me" \
  -H "Authorization: Bearer YOUR_API_KEY"

Errors

Every failure comes back as JSON with a stable code field. Match on the code, not on the message text, which is written for humans and may change. Amounts in an error body are in the site's internal unit; where a body carries need or balance, it also carries needUsd or balanceUsd, the same amount in dollars. When sending the same request again would fail the same way (a bad key, an insufficient balance, a used-up quota), the response also carries the x-should-retry: false header; only 408, 409, 429 and 5xx are worth retrying. Tools that resend every refusal (Codex, omp, or any streaming request sent again unchanged within seconds of a refusal) receive the refusal as an ordinary reply that states the reason, so that they stop.

Error body
{
  "error": {
    "code": "not_enough_credit",
    "balance": 6000,
    "balanceUsd": 0.01,
    "need": 15000,
    "needUsd": 0.025,
    "reservation": true,
    "message": "Insufficient balance: the reservation ceiling for this request is $0.025 and your available balance is $0.01. Top up or reduce the request size and output limit."
  }
}
CodeHTTP statusWhat it means
bad_key401The key is invalid, or no longer exists.
not_enough_credit402Balance too low for this request; it only happens on paid models, such as Claude and GPT. The body carries balance and need (what the request needs), with balanceUsd and needUsd beside them in dollars. When reservation is true, need is a conservative reservation ceiling before cache discounts, including input and the output limit; it is not the final charge. The request was not sent and nothing was charged. When a way out can be worked out, the body also includes ways: that free models are not charged (freeOk; it describes the billing and does not mean free-model calls are left right now), and what a new conversation with only the last message would need (freshNeed).
pricing_unavailable503The current price for this model cannot be confirmed, or its billing has been paused for verification. The request is refused without a charge; choose another available model.
billing_confirmation_wait429Several paid requests were cancelled before usage could be confirmed. No charge is made for this refusal. Wait for the retryAfter number of seconds before sending another paid request.
unsupported_billing_mode400The current text-model price covers text and image input. Audio, video and provider-hosted tools are not priced on this endpoint, so the request is refused.
invalid_billing_request400An output limit is invalid. max_tokens and max_completion_tokens, when supplied, must be positive integers.
premium_daily_cap402This account has reached its daily limit on Claude, GPT and other big models; nothing is deducted. The body carries spent (used today), cap, need (this request's estimate) and buyer (whether the account has topped up).
coding_buyers_only402The DeepSeek coding line is open to accounts that have topped up. Nothing is deducted. The body carries buyUrl, where to top up.
premium_buyers_only402Claude, GPT and other big models are open to accounts that have topped up. Nothing is deducted. The body carries buyUrl, where to top up. Web-chat rewards follow their own rules; they do not authorize API access.
key_expired401This key is past its expiry date. Extend it on the My account page or use another key.
key_limit_reached402This key has reached its own spending cap; the account balance is untouched. The body carries the cap, the amount used and this request's estimate.
model_not_allowed400That model is not on the list. The body carries the allowed names.
model_paused400That model is switched off for now and returns to the list once it is back on. The body carries the names available right now. The big models the site pays for are switched off together when the balance the site keeps with their provider runs out; the body then also carries held: true.
model_no_vision400The request carries images and the model cannot read them. Pick a model that reads images, or leave the images out.
too_many_images400The request carries more images than allowed (8).
bad_image400An image is not a PNG, JPEG, WebP or GIF data URL of at most 3 MB.
request_too_large413The request body is larger than 8 MB.
ip_limit429Too many new accounts created from this network today. Returned at sign-in.
too_fast429Too many requests from this account within a minute. The body carries retryAfter in seconds; the Retry-After header carries the same value.
account_quota403This account has used its free-model calls for the current window, or has fewer left than this message needs (a longer message counts as several calls; see Billing and limits for how length is counted). Every key on the account shares the limit; Claude, GPT and other big models do not count toward it. The body carries retryAfter (seconds to wait; the Retry-After header carries the same value) and max (the window's limit); when the message needs more than one call, it also carries need (the calls this message counts as) and left (the calls left in this window). If need is above max, waiting does not help: the error message says the message is too long, and the conversation should be shortened or a new one started. While top-ups are open, an account that has not topped up also gets codingModels (the model names of the DeepSeek coding line, which is charged to the balance and not counted toward this limit) and buyUrl (where to top up).
network_quota403This network address has used its free-model calls for the current window, or has fewer left than this message needs; Claude, GPT and other big models do not count toward it. The body carries retryAfter (seconds to wait; the Retry-After header carries the same value) and max (the window's limit); when the message needs more than one call, it also carries need (the calls this message counts as) and left (the calls left in this window). If need is above max, waiting does not help: the error message says the message is too long, and the conversation should be shortened or a new one started. While top-ups are open, an account that has not topped up also gets codingModels (the model names of the DeepSeek coding line, which is charged to the balance and not counted toward this limit) and buyUrl (where to top up).
site_busy429 / 403The free-model calls shared by the whole site are used up for the current window, or fewer are left than this message needs; Claude, GPT and other big models are not affected. The body carries retryAfter (seconds to wait; the Retry-After header carries the same value); the site-wide limit and the calls left are not disclosed. If the message is larger than the whole window allows, the status is 403 and waiting does not help: the error message says the message is too long, and the conversation should be shortened or a new one started. While top-ups are open, an account that has not topped up also gets codingModels (the model names of the DeepSeek coding line, which is charged to the balance and not counted toward this limit) and buyUrl (where to top up).
premium_busy429Other answers on Claude, GPT and the other big models are still running and this request did not fit in, even after waiting about 10 seconds. The day's budget is not used up. Nothing is deducted. The body carries retryAfter in seconds; the Retry-After header carries the same value.
upstream_failed503The model provider did not answer. Nothing is deducted when this happens.
think_overrun503The model spent its whole output limit thinking and wrote no answer. For free models whose thinking can be turned off, the site first asks once more with thinking off; this error comes back only when that did not answer either. Nothing is deducted and the call is given back. Raise max_tokens, split the task into smaller parts, or pick another model. In a streamed request this error arrives before [DONE].
content_filtered400The model provider's content filter blocked this request, so there is no answer. Nothing is deducted and the call is given back. Rephrase the request, or pick another model. In a streamed request this error arrives before [DONE].
content_blocked422The last user message does not comply with the site's content policy (onomeo.com/content-policy), so it was not sent to any model. Nothing is deducted and no call is counted.
upstream_unconfigured503The service is not wired to a provider right now.
premium_budget_exhausted403The site-wide budget for Claude, GPT and other big models opens in four rounds a day (00:00, 06:00, 12:00 and 18:00 UTC), whatever a round leaves carrying over to the next. Returned while the current round is used up, until the next opens; once the whole day's budget is used up, until 00:00 UTC. The body carries resetAt (the reset time, ISO 8601) and retryAfter (seconds until then); the Retry-After header carries the same value. Nothing is deducted. Any available free models retain their own call limits. The rounds do not apply to accounts that have topped up: they get this error only once the whole day's budget is used up. In the first three rounds, an account that has not topped up gets this error once 70% of the round is used up, and the body then also carries reserved: true and buyUrl, where to top up.
premium_request_budget403The provider cannot reserve this request's maximum cost within its remaining daily key budget. Nothing is deducted. This does not pause other big-model requests; shorten the conversation or choose a lower-cost model. The provider spending cap remains enforced.
coding_line_out403The DeepSeek coding line is paused: the site's balance with DeepSeek is running low, or the day's spending limit for the line is reached. Nothing is deducted. It comes back once the site has added to its balance with DeepSeek, or the next day (UTC); pick another model meanwhile.
draw_daily_limit429Returned by the drawing page's own request (POST /api/draws), not by /v1. The account has used its free pictures for today, or fewer are left than this request asks for; nothing is drawn. The body carries today (used and max, in pictures) and resetsAt (the next 00:00 UTC, ISO 8601). Pictures drawn on your own provider key, and pictures on a model that is charged per picture, do not count.

FAQ

Can I use this in production?

No. This is a public beta with no uptime promise. Use it to try things, prototype, or run something that can fail without consequences.

What happens if I lose the key?

Nothing is lost. Sign in again and create a new key on the My account page: it is on the same account, with the same balance. Delete the old key from the My account page if you think someone else has it.

Can I create several keys?

Yes. Each account can hold up to 10 keys. They draw on the same balance and share the same call limits, so more keys do not mean more calls.

Do you keep my prompts?

For requests to the API, onomeo keeps an excerpt of each request and answer (the first 1,000 characters of the system prompt and the first 4,000 of the last user message and of the answer; the latest 100 per account, for at most 30 days), which the operator can read in the administration area; the amount used is also recorded, for billing and for counting calls. Conversations in the web chat are saved with your account (up to 50, and you can delete them). Either way, messages are forwarded to third-party model providers, and some of them, particularly on free tiers, may retain submitted content or use it to improve their services. onomeo does not use your content for training.

Is there image generation, video, audio or embeddings?

Yes. Pictures come through POST /v1/images/generations, and embeddings, rerank and speech-to-text through endpoints of their own (see Other endpoints); videos come through POST /v1/videos (see Videos). Text-to-speech is not offered, and function calling is not guaranteed on every model.

Why is my answer empty?

Current output limits and billing rules are loading.