Skip to the content
Back to Nymbot

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.

FieldTypeRequiredDescription
modelstringYesA generator id, such as nano-banana.
promptstringYesWhat to draw. Only the first 2,000 characters are used.
nintegerNo1 to 4. Default 1. Also accepted as num_images.
sizestringNoAn 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_ratiostringNoThe same as size, and wins if both are sent.
qualitystringNoGenerator-specific, such as "low", "medium" or "high".
negative_promptstringNoWhat to leave out.
output_formatstringNo"png", "jpeg" or "webp".
response_formatstringNo"url" (the default) or "b64_json".
image_urlstringNoA 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 }
}
StatusWhen
400No 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).
402The balance cannot cover every picture asked for.
404No model by that name (model_not_found).
502The generator failed (upstream_error). Nothing is charged unless the provider billed for the attempt; then the error has charged_sats.
503Pictures 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.

FieldTypeRequiredDescription
imagefileYesThe picture to edit: PNG, JPEG, WebP or GIF, up to 20 MB. Also accepted as image[]; the first one is used.
promptstringYesWhat to change.
modelstringYesA generator with edit.
nintegerNo1 to 4.
size
aspect_ratio
quality
negative_prompt
output_format
stringNoAs for generation.
response_formatstringNo"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 }
}
StatusWhen
400No image or prompt, a file that is not a picture (invalid_image), or a generator that cannot edit (edit_unsupported).
413The picture is over 20 MB (file_too_large), or the whole request over 32 MB.
503The 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.

FieldTypeRequiredDescription
modelstringYesA video generator id from GET /api/v1/models?type=video, such as veo.
promptstringYesWhat should happen.
durationnumber or stringNoLength 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_ratiostringNoSuch as "16:9" or "9:16"; a size such as "1280x720" becomes the nearest ratio.
resolution
quality
stringNoOne 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_urlstringNoA 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.

StatusWhen
400No 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).
402The Pro balance cannot cover the video.
404No 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).
429Your nym already has 10 videos rendering (video_jobs_limit). Check on them and submit more once one finishes.
502The generator refused the job. Nothing is charged unless the provider billed for it.
503Videos 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.

FieldTypeRequiredDescription
modelstringNoA speech model from the audio models list. Default: the standard voice, @cf/myshell-ai/melotts. aura-2 is Deepgram Aura 2.
inputstringYesThe text to read: up to 800 characters for the standard voice, 2,000 for Aura 2.
voicestringNoA 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.
languagestringNoA 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_formatstringNoThe standard voice returns mp3 only. Aura 2 returns mp3 (the default), opus, aac, flac, wav or pcm.
speednumberNoAccepted 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)
StatusWhen
400No 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).
422The voice does not speak the language given, or the model has no voice for it.
502The 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.

FieldTypeRequiredDescription
languagestring (query)NoOnly voices for this language.
modelstring (query)NoOnly 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.

FieldTypeRequiredDescription
filefileYesThe 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.
modelstringNoDefault whisper, which is Whisper Large v3 Turbo. whisper-1, whisper-large-v3-turbo and @cf/openai/whisper-large-v3-turbo mean the same.
languagestringNoThe spoken language, such as en. Detected if left out.
promptstringNoWords or spellings to expect, such as names. Only the first 1,000 characters are used.
response_formatstringNojson (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.

StatusWhen
400No file, a file with no usable audio (invalid_audio), an unknown format, or a model that is not a transcription model (invalid_model).
402Neither balance can cover it.
413The 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).
502Whisper 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.

FieldTypeRequiredDescription
modelstringYesAn embedding model from GET /api/v1/models?type=embedding.
inputstring or array of stringsYesThe 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_formatstringNofloat (the default) or base64 (little-endian 32-bit floats).
dimensionsintegerNoThe 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.
ModelDimensionsContext
@cf/baai/bge-m31024, many languages8,192 tokens
@cf/qwen/qwen3-embedding-0.6b1024, many languages8,192 tokens
@cf/baai/bge-large-en-v1.51024, English512 tokens
@cf/baai/bge-base-en-v1.5768, English512 tokens
@cf/baai/bge-small-en-v1.5384, English512 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 }
}
StatusWhen
400No 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).
402The standard balance is too low. Embeddings never use the Pro balance.
404No embedding model by that name.
502The 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);