Embeddings and vectorization
Turn text into vectors with POST /v1/embeddings for semantic search, RAG retrieval, and clustering.
POST /v1/embeddings turns text into a fixed-length vector — the building block for semantic
search, RAG retrieval, clustering, and dedup. It's OpenAI-compatible and single-shot: send
model and input, get a data array of vectors back in the same response.
Two models, priced per input token
bge-m3 and qwen3-embedding-4b both serve /v1/embeddings. There's no generated text, so
billing is prompt tokens only — usage.prompt_tokens equals usage.total_tokens on every
response.
Embed a single string
Pass input as a plain string for one vector back:
import OpenAI from "openai";
const client = new OpenAI({
baseURL: "https://gateway.venna.net/v1",
apiKey: process.env.VENNA_API_KEY,
});
const embedding = await client.embeddings.create({
model: "bge-m3",
input: "Venna routes inference across a decentralized node fleet.",
});
console.log(embedding.data[0].embedding.length);
console.log(embedding.usage.total_tokens);import os
from openai import OpenAI
client = OpenAI(
base_url="https://gateway.venna.net/v1",
api_key=os.environ["VENNA_API_KEY"],
)
embedding = client.embeddings.create(
model="bge-m3",
input="Venna routes inference across a decentralized node fleet.",
)
print(len(embedding.data[0].embedding))
print(embedding.usage.total_tokens)curl https://gateway.venna.net/v1/embeddings \
-H "Authorization: Bearer $VENNA_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"model": "bge-m3",
"input": "Venna routes inference across a decentralized node fleet."
}'Batch an array of strings
input also accepts an array — one request embeds a whole batch instead of one round trip per
string. Chunk a document, embed every chunk together, and let the response order tell you which
vector belongs to which chunk:
const batch = await client.embeddings.create({
model: "bge-m3",
input: [
"Venna routes inference across a decentralized node fleet.",
"Nodes stake collateral and get paid per token served.",
"The gateway is OpenAI-compatible at the API layer.",
],
});
console.log(batch.data.length); // 3Read the response
data[i].embedding lines up with input[i] by data[i].index — don't assume array order alone
if you reorder or filter results downstream. usage.prompt_tokens is what you're billed for:
for (const item of batch.data) {
console.log(item.index, item.embedding.slice(0, 4)); // first 4 dims
}
console.log(batch.model); // "bge-m3"
console.log(batch.usage.prompt_tokens, batch.usage.total_tokens);Swap model to qwen3-embedding-4b for the alternate embedding model — same request and
response shape, different vector space. Don't mix vectors from the two models in one index;
similarity scores aren't comparable across models.
Semantic search and RAG retrieval
The typical pipeline: embed your corpus once (docs, chunks, product rows) and store the vectors
in a vector index or a Postgres column with pgvector. At query time, embed the user's question
with the same model, then rank stored vectors by cosine similarity to find the closest matches.
Feed the top-k chunks into a chat completion as
context — that's retrieval-augmented generation.
Re-embed only what changed; embeddings are deterministic per model, so unchanged text never needs
a new call.
Next steps
- API reference: Embeddings — full request/response schema.
- Quickstart — point any OpenAI-compatible client at the gateway and make your first call.