Core APIsEmbeddings

Embeddings

Vector embeddings via the OpenAI wire format. Float or base64. Variable dimensions.

POST /v1/embeddings turns text into a vector. The wire format is the OpenAI embeddings spec, so any storage layer that already speaks OpenAI (pgvector, Pinecone, Qdrant, LangChain stores) works unchanged.

At a glance

EndpointPOST /v1/embeddings
Default modelcohere/embed-v4
Encodingfloat (default) or base64
DimensionsFixed per model, or truncatable on cohere/embed-v4

Single string

embed-one.ts
import { createCleverRouter } from '@cleverrouter/sdk';

const cr = createCleverRouter({ apiKey: process.env.CLEVERROUTER_API_KEY! });

const res = await cr.embed('Hello from the EU.', {
  model: 'cohere/embed-v4',
});

const vector = res.data[0]!.embedding as number[];
console.log(vector.length); // → e.g. 1024

Batch

embed-batch.ts
const res = await cr.embed(
  ['First document.', 'Second document.', 'Third document.'],
  { model: 'cohere/embed-v4' },
);

for (const entry of res.data) {
  console.log(entry.index, (entry.embedding as number[]).length);
}

Batching matters: one batched call is dramatically cheaper than N serial calls — both in HTTP overhead and in cents.

float vs base64

The default encoding_format: 'float' returns number[]. Switch to 'base64' for a compact string, handy for JSON-heavy pipes or direct bytea storage:

const res = await cr.embed('Hello', { encoding_format: 'base64' });
const compact = res.data[0]!.embedding as string;

Variable dimensions

Models with Matryoshka-style truncation (e.g. cohere/embed-v4) accept dimensions to shrink the output:

await cr.embed('Hello', {
  model: 'cohere/embed-v4',
  dimensions: 512, // instead of the model default of 1024
});

Smaller dimensions trade a little recall for cheaper storage and faster vector search.

Options

interface EmbeddingOpts {
  model?: string;                       // default: 'cohere/embed-v4'
  encoding_format?: 'float' | 'base64'; // default: 'float'
  dimensions?: number;
  user?: string;                        // forwarded for upstream audit logs
  provider?: 'scaleway' | 'tensorix' | 'bedrock';
}

Response shape

interface EmbeddingResponse {
  object: 'list';
  data: Array<{
    index: number;
    object: 'embedding';
    embedding: number[] | string; // string when encoding_format='base64'
  }>;
  model: string;
  usage?: { prompt_tokens?: number; total_tokens?: number };
}

Provider options

ModelProviderRegion
cohere/embed-v4Bedrockeu-central-1
baai/bge-multilingual-gemma2ScalewayParis
qwen/qwen3-embeddingScaleway, TensorixParis, Frankfurt

Pin a provider when you need it:

await cr.embed(['hello'], { provider: 'scaleway' });

Multilingual?

cohere/embed-v4 and baai/bge-multilingual-gemma2 handle ~100 languages each with consistent vector geometry. For English-only workloads, smaller English-only models are cheaper.

cURL

curl https://api.cleverouter.eu/v1/embeddings \
  -H "Authorization: Bearer $CLEVERROUTER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "cohere/embed-v4",
    "input": ["Hello from the EU.", "Bonjour from Paris."]
  }'

Common gotchas

  • Don't mix models. Vectors from cohere/embed-v4 and qwen/qwen3-embedding live in different spaces. Pick one per index and stick with it.
  • Re-embed on dimension change. Truncating from 1024 → 512 is a property of the call, not the store. Re-embed everything if you change dimensions.
  • Batch size limits. ~96 strings per call is a safe upper bound. The gateway accepts more but upstream providers cap at provider- specific numbers; chunk yourself for portability.