Knowledge base Developers
Images, audio and embeddings
The generators from the app, and the building blocks for search: pictures, video, speech, transcription and embeddings, each billed per use from your balance.
Generating images
Makes one to four pictures from a prompt and returns them when they are done. It is the same
set of generators as ?image in the app.
POST https://nymbot.ai/api/v1/images/generations — needs an API key, or a Lightning payment per request.
Ids come from GET /api/v1/models?type=image. The standard generator,
@cf/black-forest-labs/flux-1-schnell, costs a flat 5 standard credits (50 sats) a
picture. Every other generator spends Pro credits at its own price, with the usual fee and
margin, as in the app. n pictures cost
n times as much. A field a generator does not take is dropped rather than refused;
the standard generator uses the prompt only.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | A generator id, such as nano-banana. |
prompt | string | Yes | What to draw. Only the first 2,000 characters are used. |
n | integer | No | 1 to 4. Default 1. Also accepted as num_images. |
size | string | No | An aspect ratio such as "16:9", or an OpenAI size such as "1792x1024", which becomes the nearest of 1:1, 16:9, 9:16, 4:3, 3:4, 3:2, 2:3, 21:9, 5:4 and 4:5. "auto" leaves it to the generator. |
aspect_ratio | string | No | The same as size, and wins if both are sent. |
quality | string | No | Generator-specific, such as "low", "medium" or "high". |
negative_prompt | string | No | What to leave out. |
output_format | string | No | "png", "jpeg" or "webp". |
response_format | string | No | "url" (the default) or "b64_json". |
image_url | string | No | A picture to start from: an https:// link of at most 4,096 characters with no user name or password in it, or a data:image/…;base64 URL (PNG, JPEG, WebP or GIF; not SVG). Only for generators with edit; required by those with requires_image_url. |
resolution is not used: each generator makes its own size. With url,
each picture is uploaded to a public Blossom host and you get its link (a few generators only
hand back a link of their own, which is passed on). Anyone with the link can open it and it
cannot be taken down again; see what the API can see. With
b64_json the picture comes back in the response and is never uploaded. A picture
sent as a data: URL in image_url is checked the same way as an
edit and uploaded to Blossom first so the generator can fetch it; it
is deleted again if the request fails unbilled.
If some of the n pictures fail, you get the ones that worked, are charged only for
those (plus any the provider billed despite failing), and nymbot.failed says how
many are missing. If all fail, the request returns 502.
Response
{
"created": 1790726400,
"model": "nano-banana",
"cost": 0.2126,
"data": [
{
"url": "https://blossom.example/5c0e4b7d3a91f2e8...c4.png",
"content_type": "image/png"
}
],
"nymbot": { "balance": "pro", "charged_credits": 1.817, "charged_sats": 181.7, "balance_credits": 410.608, "balance_sats": 41060.8 }
}
| Status | When |
|---|---|
400 | No prompt; n outside 1 to 4 (invalid_value); a bad size (invalid_size) or picture (invalid_image, invalid_image_url); a model that exists but is not an image generator (invalid_model); a picture for a generator that cannot edit (edit_unsupported); no picture for one that needs it (image_required). |
402 | The balance cannot cover every picture asked for. |
404 | No model by that name (model_not_found). |
502 | The generator failed (upstream_error). Nothing is charged unless the provider billed for the attempt; then the error has charged_sats. |
503 | Pictures cannot be hosted right now (media_hosting_unavailable). b64_json still works. |
cURL
curl https://nymbot.ai/api/v1/images/generations \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "nano-banana",
"prompt": "A lighthouse at dusk, oil painting",
"size": "16:9"
}'
Python
import os
import requests
res = requests.post(
"https://nymbot.ai/api/v1/images/generations",
headers={"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]},
json={"model": "nano-banana", "prompt": "A lighthouse at dusk, oil painting", "size": "16:9"},
)
res.raise_for_status()
print(res.json()["data"][0]["url"])
JavaScript
const res = await fetch("https://nymbot.ai/api/v1/images/generations", {
method: "POST",
headers: {
"Authorization": "Bearer " + process.env.NYMBOT_API_KEY,
"Content-Type": "application/json",
},
body: JSON.stringify({ model: "nano-banana", prompt: "A lighthouse at dusk, oil painting", size: "16:9" }),
});
const body = await res.json();
console.log(body.data[0].url);
Editing images
Changes a picture you upload, following a prompt. This is OpenAI's edit endpoint, so the OpenAI
SDKs' images.edit works as it is. Only Pro generators with edit in the
model list accept it.
POST https://nymbot.ai/api/v1/images/edits — needs an API key, or a Lightning payment per request. The body is multipart/form-data, up to 32 MB.
| Field | Type | Required | Description |
|---|---|---|---|
image | file | Yes | The picture to edit: PNG, JPEG, WebP or GIF, up to 20 MB. Also accepted as image[]; the first one is used. |
prompt | string | Yes | What to change. |
model | string | Yes | A generator with edit. |
n | integer | No | 1 to 4. |
sizeaspect_ratioqualitynegative_promptoutput_format | string | No | As for generation. |
response_format | string | No | "b64_json" (the default here) or "url". |
The picture you upload is checked to be a well-formed PNG, JPEG, WebP or GIF, sent on as its real type, and put on a public Blossom host, because the generators fetch their input by link. Treat it as public. If the edit fails and nothing is charged, the hosted copy is deleted again. The response has the same shape as for generation. Pricing is the generator's price, which for some generators includes a charge for the input picture.
Response
{
"created": 1790726460,
"model": "nano-banana",
"cost": 0.2126,
"data": [{ "b64_json": "iVBORw0KGgoAAAANSUhEUgAA..." }],
"nymbot": { "balance": "pro", "charged_credits": 1.817, "charged_sats": 181.7, "balance_credits": 408.791, "balance_sats": 40879.1 }
}
| Status | When |
|---|---|
400 | No image or prompt, a file that is not a picture (invalid_image), or a generator that cannot edit (edit_unsupported). |
413 | The picture is over 20 MB (file_too_large), or the whole request over 32 MB. |
503 | The picture cannot be hosted right now (media_hosting_unavailable). |
cURL
curl https://nymbot.ai/api/v1/images/edits \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-F model=nano-banana \
-F [email protected] \
-F prompt="Make it a snowy evening"
Python
import base64, os
from openai import OpenAI
client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])
with open("photo.png", "rb") as f:
result = client.images.edit(model="nano-banana", image=f, prompt="Make it a snowy evening")
with open("edited.png", "wb") as out:
out.write(base64.b64decode(result.data[0].b64_json))
JavaScript
import fs from "node:fs";
import { writeFile } from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });
const result = await client.images.edit({
model: "nano-banana",
image: fs.createReadStream("photo.png"),
prompt: "Make it a snowy evening",
});
await writeFile("edited.png", Buffer.from(result.data[0].b64_json, "base64"));
Video
A video takes minutes, so it runs in the background. You submit it, get an id straight away, and ask about the id until it is done. Every video generator spends the Pro balance.
POST https://nymbot.ai/api/v1/videos — needs an API key, or a Lightning payment per request. Returns 202.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | A video generator id from GET /api/v1/models?type=video, such as veo. |
prompt | string | Yes | What should happen. |
duration | number or string | No | Length in seconds, more than 0 and up to 60. Used only by generators that let you choose the length; the others make their usual length, which is what seconds in the response and the price follow. |
aspect_ratio | string | No | Such as "16:9" or "9:16"; a size such as "1280x720" becomes the nearest ratio. |
resolutionquality | string | No | One of the generator's resolutions in the model list, such as "720p" or "1080p". It sets the price. Anything else is refused with unsupported_resolution. |
image_url | string | No | A picture to start from: an https:// link or a data:image/… URL, which is uploaded to a public Blossom host first. Required by generators with requires_image_url. |
The price is fixed when you submit, from the generator, resolution and length, so it is
charged from your Pro balance as soon as the provider accepts the job, and shown as
cost, estimated_cost and nymbot. If the provider refuses
the job, nothing is charged. If the render later fails, or the finished clip cannot be stored
and the provider did not bill for it, the charge is refunded once, automatically. A render that
is still going after an hour is given up, and keeps its charge, because the provider bills a
render once it accepts it. A refund returns the credits but does not lower the key's spend
count.
Response (202)
{
"id": "vid_3e9a51c07b2f4d86e0a1c4f2",
"object": "video",
"model": "veo",
"status": "in_progress",
"created": 1790726400,
"seconds": 8,
"resolution": "1080p",
"estimated_cost": 3.18,
"expires_at": 1790812800,
"cost": 3.18,
"nymbot": { "balance": "pro", "charged_credits": 31.8, "charged_sats": 3180, "balance_credits": 378.808, "balance_sats": 37880.8 }
}
status starts as in_progress, or completed with the video
already in data when the generator returned it straight away.
Checking on a video
GET https://nymbot.ai/api/v1/videos/{id} — needs a key belonging to the nym that submitted it. A key that has reached its cap can still check.
It answers 202 while the video is being made and 200 once it is
finished or has failed. Ask every 5 to 10 seconds. Each check asks the provider once and answers
at once; it never waits for the video. A job is kept for 24 hours after it was submitted.
GET /api/v1/videos lists the key's last 50 jobs as
{"object": "list", "data": […]}.
Response (200)
{
"id": "vid_3e9a51c07b2f4d86e0a1c4f2",
"object": "video",
"model": "veo",
"status": "completed",
"created": 1790726400,
"seconds": 8,
"resolution": "1080p",
"estimated_cost": 3.18,
"expires_at": 1790812800,
"completed_at": 1790726590,
"data": { "url": "https://blossom.example/9b41d0c2e7a3f658...1e.mp4", "content_type": "video/mp4" },
"cost": 3.18,
"nymbot": { "balance": "pro", "charged_credits": 31.8, "charged_sats": 3180 }
}
status is in_progress, completed or failed. A
failed job carries error ({"code": "generation_failed", "message": …});
if it was refunded, cost is 0 and nymbot adds
refunded_credits and refunded_sats. The finished video is on a public
Blossom host, like generated pictures.
| Status | When |
|---|---|
400 | No prompt; a duration outside 0 to 60 (invalid_value); a resolution the generator does not offer (unsupported_resolution); no picture for a generator that needs one (image_required); a model that is not a video generator (invalid_model). |
402 | The Pro balance cannot cover the video. |
404 | No such generator (model_not_found), or no job by that id for your nym, or it is more than 24 hours old (video_not_found). |
429 | Your nym already has 10 videos rendering (video_jobs_limit). Check on them and submit more once one finishes. |
502 | The generator refused the job. Nothing is charged unless the provider billed for it. |
503 | Videos cannot be delivered or stored right now (media_hosting_unavailable, service_unavailable). |
cURL
curl https://nymbot.ai/api/v1/videos \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "veo", "prompt": "Waves rolling onto a beach at sunrise", "duration": 8, "aspect_ratio": "16:9"}'
curl https://nymbot.ai/api/v1/videos/vid_3e9a51c07b2f4d86 \
-H "Authorization: Bearer $NYMBOT_API_KEY"
Python
import os, time
import requests
headers = {"Authorization": "Bearer " + os.environ["NYMBOT_API_KEY"]}
job = requests.post(
"https://nymbot.ai/api/v1/videos",
headers=headers,
json={"model": "veo", "prompt": "Waves rolling onto a beach at sunrise", "duration": 8, "aspect_ratio": "16:9"},
).json()
while True:
time.sleep(8)
status = requests.get("https://nymbot.ai/api/v1/videos/" + job["id"], headers=headers).json()
if status["status"] in ("completed", "failed"):
break
print(status["data"]["url"] if status["status"] == "completed" else status["error"])
JavaScript
const headers = {
"Authorization": "Bearer " + process.env.NYMBOT_API_KEY,
"Content-Type": "application/json",
};
const job = await (await fetch("https://nymbot.ai/api/v1/videos", {
method: "POST",
headers,
body: JSON.stringify({ model: "veo", prompt: "Waves rolling onto a beach at sunrise", duration: 8, aspect_ratio: "16:9" }),
})).json();
let status;
do {
await new Promise((r) => setTimeout(r, 8000));
status = await (await fetch("https://nymbot.ai/api/v1/videos/" + job.id, { headers })).json();
} while (status.status !== "completed" && status.status !== "failed");
console.log(status.status === "completed" ? status.data.url : status.error);
Text to speech
Reads text aloud and returns the audio file itself, not a link. It is OpenAI's speech endpoint,
so audio.speech.create in the OpenAI SDKs works.
POST https://nymbot.ai/api/v1/audio/speech — needs an API key, or a Lightning payment per request.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | No | A speech model from the audio models list. Default: the standard voice, @cf/myshell-ai/melotts. aura-2 is Deepgram Aura 2. |
input | string | Yes | The text to read: up to 800 characters for the standard voice, 2,000 for Aura 2. |
voice | string | No | A voice id from the voices list: an Aura speaker such as luna (or aura-2-luna-en), or a MeloTTS language (en, es, fr, zh). OpenAI voice names such as alloy are accepted and give the model's default voice. |
language | string | No | A language code such as es. Without a voice, it picks one for that language. A voice that speaks another language returns 422 voice_language_mismatch, and a language the model has no voice for 422 unsupported_language. |
response_format | string | No | The standard voice returns mp3 only. Aura 2 returns mp3 (the default), opus, aac, flac, wav or pcm. |
speed | number | No | Accepted and ignored. |
The standard voice costs a flat 3 standard credits (30 sats) a request, as in the app. Aura 2
is Pro, priced by the characters you send. The response body is the audio, with a matching
Content-Type; the cost is in the X-Nymbot-Cost-Sats header. If the
speech model fails, nothing is charged.
Response
HTTP/1.1 200 OK
Content-Type: audio/mpeg
X-Nymbot-Cost-Sats: 4.2
X-Nymbot-Balance-Sats: 41055.6
(audio bytes)
| Status | When |
|---|---|
400 | No input; input over the model's limit (input_too_long); a format the model cannot produce (unsupported_response_format); an unknown voice (invalid_voice); a model that is not a speech model (invalid_model). |
422 | The voice does not speak the language given, or the model has no voice for it. |
502 | The speech model failed. Nothing is charged. |
cURL
curl https://nymbot.ai/api/v1/audio/speech \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "aura-2", "voice": "luna", "input": "Your invoice has been paid."}' \
--output speech.mp3
Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])
audio = client.audio.speech.create(
model="aura-2",
voice="luna",
input="Your invoice has been paid.",
)
audio.write_to_file("speech.mp3")
JavaScript
import { writeFile } from "node:fs/promises";
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });
const audio = await client.audio.speech.create({
model: "aura-2",
voice: "luna",
input: "Your invoice has been paid.",
});
await writeFile("speech.mp3", Buffer.from(await audio.arrayBuffer()));
Audio models and voices
Two public lists for picking a speech model and voice, or a transcription model. There are 41 Aura 2 English speakers and four MeloTTS languages.
GET https://nymbot.ai/api/v1/audio/models — no key needed.
GET https://nymbot.ai/api/v1/audio/voices?language=en — no key needed.
| Field | Type | Required | Description |
|---|---|---|---|
language | string (query) | No | Only voices for this language. |
model | string (query) | No | Only voices for this model. |
Response (voices)
{
"object": "list",
"data": [
{ "id": "luna", "name": "Luna", "provider": "deepgram", "model_id": "aura-2", "models": ["aura-2"], "language": "en", "description": "Aura 2 English voice", "gender": "female", "preview_url": null },
{ "id": "en", "name": "MeloTTS English", "provider": "myshell", "model_id": "@cf/myshell-ai/melotts", "models": ["@cf/myshell-ai/melotts", "melotts"], "language": "en", "description": "English (MeloTTS)", "gender": null, "preview_url": null }
]
}
The models list answers {"object": "list", "data": {"tts": […], "stt": […]}}.
Each speech model gives its balance, price, max_input_chars,
response_formats, languages and default_voice; the
transcription model gives its aliases, max_file_bytes, max_seconds,
formats and price per minute.
cURL
curl https://nymbot.ai/api/v1/audio/models
curl "https://nymbot.ai/api/v1/audio/voices?language=en"
Python
import requests
print(requests.get("https://nymbot.ai/api/v1/audio/models").json())
for voice in requests.get("https://nymbot.ai/api/v1/audio/voices", params={"language": "en"}).json()["data"]:
print(voice["id"], voice["model_id"])
JavaScript
console.log(await (await fetch("https://nymbot.ai/api/v1/audio/models")).json());
const voices = await (await fetch("https://nymbot.ai/api/v1/audio/voices?language=en")).json();
for (const v of voices.data) console.log(v.id, v.model_id);
Speech to text
Turns a recording into text with Whisper. This is OpenAI's transcription endpoint, so
audio.transcriptions.create works.
POST https://nymbot.ai/api/v1/audio/transcriptions — needs an API key, or a Lightning payment per request. The body is multipart/form-data.
| Field | Type | Required | Description |
|---|---|---|---|
file | file | Yes | The recording, from 256 bytes to 25 MB and up to 30 minutes: WAV, WebM, MP4 or M4A, Ogg or Opus, MP3 and the other formats Whisper reads. MP3 and other formats whose length cannot be read up front are limited to 1.8 MB. |
model | string | No | Default whisper, which is Whisper Large v3 Turbo. whisper-1, whisper-large-v3-turbo and @cf/openai/whisper-large-v3-turbo mean the same. |
language | string | No | The spoken language, such as en. Detected if left out. |
prompt | string | No | Words or spellings to expect, such as names. Only the first 1,000 characters are used. |
response_format | string | No | json (the default), text, srt, vtt or verbose_json. |
For WAV, WebM, MP4 and Ogg files the length is read from the file before anything runs, so a
recording over 30 minutes is refused up front (with 3 seconds' grace). A WAV file's length comes
from its sample rate, channels and sample size. The length of other formats, such as MP3, cannot
be read up front, so they are limited by size: at the lowest bitrate Nymbot assumes, 8 kbps,
30 minutes is 1.8 MB, and a larger file in such a format is refused with 413
audio_too_long before anything runs. Send longer recordings as WAV, WebM, MP4 or Ogg.
If Whisper then reports more than 30 minutes anyway, the request is refused with
413 audio_too_long, and since Whisper did run, 30 minutes are
charged.
You pay for the length of the audio, rounded up to the second: the longest of the length read
from the file, the length Whisper reports, and the least the file's size allows, at Whisper's per-minute price
with the usual fee and margin, and at least 0.05 credit a request. It is paid from the standard
balance when that can cover the hold, and from Pro otherwise; a 402 gives what each
balance would need. In the app, transcribing a voice message may be free; on the API it is
always charged. If Whisper fails, nothing is charged.
Response
{
"text": "Your invoice has been paid.",
"usage": { "type": "duration", "seconds": 3 },
"nymbot": { "balance": "standard", "charged_credits": 0.05, "charged_sats": 0.5, "balance_credits": 120.35, "balance_sats": 1203.5 }
}
text returns plain text, srt and vtt return subtitles, and
verbose_json adds the language, duration and timed segments. For the three that are
not JSON, the cost is in the headers.
| Status | When |
|---|---|
400 | No file, a file with no usable audio (invalid_audio), an unknown format, or a model that is not a transcription model (invalid_model). |
402 | Neither balance can cover it. |
413 | The file is over 25 MB (file_too_large) or the recording over 30 minutes, or, in a format whose length cannot be read up front, over 1.8 MB (audio_too_long). |
502 | Whisper could not process the audio. Nothing is charged. |
cURL
curl https://nymbot.ai/api/v1/audio/transcriptions \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-F [email protected] \
-F model=whisper \
-F response_format=json
Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])
with open("memo.m4a", "rb") as f:
transcript = client.audio.transcriptions.create(model="whisper", file=f)
print(transcript.text)
JavaScript
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });
const transcript = await client.audio.transcriptions.create({
model: "whisper",
file: fs.createReadStream("memo.m4a"),
});
console.log(transcript.text);
Translating speech to English
POST https://nymbot.ai/api/v1/audio/translations — needs an API key, or a Lightning payment per request. The body is multipart/form-data.
The same as transcription, with the same fields apart from language, limits and
price, but the text comes back in English whatever language was spoken. The OpenAI SDKs call
it with audio.translations.create.
cURL
curl https://nymbot.ai/api/v1/audio/translations \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-F [email protected] \
-F model=whisper
Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])
with open("nota.m4a", "rb") as f:
translation = client.audio.translations.create(model="whisper", file=f)
print(translation.text)
JavaScript
import fs from "node:fs";
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });
const translation = await client.audio.translations.create({
model: "whisper",
file: fs.createReadStream("nota.m4a"),
});
console.log(translation.text);
Embeddings
Turns text into vectors for search, clustering and deduplication. The models run on Cloudflare and spend the standard balance.
POST https://nymbot.ai/api/v1/embeddings — needs an API key, or a Lightning payment per request.
| Field | Type | Required | Description |
|---|---|---|---|
model | string | Yes | An embedding model from GET /api/v1/models?type=embedding. |
input | string or array of strings | Yes | The text to embed, up to 100 non-empty strings. Token arrays are refused (token_input_unsupported). Each input has to fit the model's context_length, counted as about four bytes a token. |
encoding_format | string | No | float (the default) or base64 (little-endian 32-bit floats). |
dimensions | integer | No | The model's own size, or for a model with supported_dimensions one of those; the vector is then shortened and normalized. Anything else is refused. |
| Model | Dimensions | Context |
|---|---|---|
@cf/baai/bge-m3 | 1024, many languages | 8,192 tokens |
@cf/qwen/qwen3-embedding-0.6b | 1024, many languages | 8,192 tokens |
@cf/baai/bge-large-en-v1.5 | 1024, English | 512 tokens |
@cf/baai/bge-base-en-v1.5 | 768, English | 512 tokens |
@cf/baai/bge-small-en-v1.5 | 384, English | 512 tokens |
The models list is the source of truth for which are available and what they cost; Google's EmbeddingGemma, with shorter vectors on request, appears there too when the catalog has a price for it. Embeddings are metered per input token, and the 0.05-credit minimum applies to each request, not to each input, so batching many texts into one request is much cheaper than sending them one at a time.
Response
{
"object": "list",
"data": [
{ "object": "embedding", "index": 0, "embedding": [0.0213, -0.0487, 0.0112] }
],
"model": "@cf/baai/bge-m3",
"usage": { "prompt_tokens": 9, "total_tokens": 9 },
"nymbot": { "balance": "standard", "charged_credits": 0.05, "charged_sats": 0.5, "balance_credits": 1204.35, "balance_sats": 12043.5 }
}
| Status | When |
|---|---|
400 | No input or an empty one; token arrays (token_input_unsupported); more than 100 inputs (too_many_inputs); an input longer than the model takes (input_too_long); a size the model cannot give (unsupported_dimensions). |
402 | The standard balance is too low. Embeddings never use the Pro balance. |
404 | No embedding model by that name. |
502 | The model failed. Nothing is charged. |
cURL
curl https://nymbot.ai/api/v1/embeddings \
-H "Authorization: Bearer $NYMBOT_API_KEY" \
-H "Content-Type: application/json" \
-d '{"model": "@cf/baai/bge-m3", "input": ["Lightning invoices expire.", "Invoices on Lightning have a time limit."]}'
Python
import os
from openai import OpenAI
client = OpenAI(base_url="https://nymbot.ai/api/v1", api_key=os.environ["NYMBOT_API_KEY"])
result = client.embeddings.create(
model="@cf/baai/bge-m3",
input=["Lightning invoices expire.", "Invoices on Lightning have a time limit."],
)
print(len(result.data), len(result.data[0].embedding))
JavaScript
import OpenAI from "openai";
const client = new OpenAI({ baseURL: "https://nymbot.ai/api/v1", apiKey: process.env.NYMBOT_API_KEY });
const result = await client.embeddings.create({
model: "@cf/baai/bge-m3",
input: ["Lightning invoices expire.", "Invoices on Lightning have a time limit."],
});
console.log(result.data.length, result.data[0].embedding.length);