# Embeddings

Turn text into vectors for search, clustering and retrieval. The endpoint is compatible with the OpenAI Embeddings API, so the official OpenAI SDKs work with only a new base URL.

`POST /v1/embeddings`

Only embedding models are served here. Calling it with a chat model returns `400`. List the current embedding models with a public call that needs no key:

```bash
curl "https://kenari.id/v1/models?modality=embedding"
```

A plain `GET /v1/models` does not list embedding, rerank, moderation or System One models. It does list chat, image, speech, transcription and video models. The examples below use `bge-m3`. Swap in any id the call above returns. Prices are on [Models and pricing](/en/docs/models).

## Request

| Field | Type | Required | Description |
| --- | --- | --- | --- |
| `model` | string | yes | An embedding model id. |
| `input` | string or array of strings | yes | One text, or several texts in one request. An array needs at least one text, and every text must be a string with some non-whitespace content. Up to 2,048 texts and 1 MiB of text in total. |

Other OpenAI fields, such as `encoding_format`, are passed on to the provider. Whether one has an effect depends on the model.

## Response

The response has the OpenAI shape. The example vector is shortened for readability. A real vector has many more values. `object` is `"list"`, `model` is the id you requested, and `data` holds one entry per input, in the same order, with an `index` and the `embedding` vector. A `usage` object appears only when the provider reports token counts.

```json
{
  "object": "list",
  "model": "bge-m3",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0123, -0.0456] }
  ]
}
```

## Examples

### curl

```bash
curl https://kenari.id/v1/embeddings \
  -H "Authorization: Bearer $KENARI_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "bge-m3",
    "input": "a cat sitting on a rug"
  }'
```

### Python

```python
import os
from openai import OpenAI

client = OpenAI(
    base_url="https://kenari.id/v1",
    api_key=os.environ["KENARI_API_KEY"],
)

result = client.embeddings.create(
    model="bge-m3",
    input="a cat sitting on a rug",
)

print(result.data[0].embedding[:5])
```

### JavaScript

```js
import OpenAI from "openai";

const client = new OpenAI({
  baseURL: "https://kenari.id/v1",
  apiKey: process.env.KENARI_API_KEY,
});

const result = await client.embeddings.create({
  model: "bge-m3",
  input: "a cat sitting on a rug",
});

console.log(result.data[0].embedding.slice(0, 5));
```

## Billing

Embeddings are billed per input token. kenari estimates the count from the text you send, so the charge does not depend on what the provider reports. See [How billing works](/en/docs/billing) for balance and price dimensions.

## Errors

| Status | Code | When |
| --- | --- | --- |
| 400 | `bad_request` | `model` is unknown or is not an embedding model, `input` is missing, is an empty array, or contains an empty, whitespace-only or non-string item, or the request is over the 2,048 text or 1 MiB limit. |
| 400 | `model_not_found` | The model is listed but no provider serves it right now. Retry later. |
| 503 | `upstream_error`, `all_providers_failed` | No provider returned a usable response. You are not charged. Retry. |

When `model` is not an embedding model, the error message lists the embedding ids that are available. See [Errors](/en/docs/errors) for the other codes.

## See also

- [Models and pricing](/en/docs/models)
- [Rerank](/en/docs/rerank)
- [Authentication and API keys](/en/docs/authentication)
