Mafdet AI Help Center中文

Embeddings

POST https://api.mafdet.ai/v1/embeddings

Turn text into vectors with gemini-embedding-2. The endpoint is OpenAI-compatible, so any OpenAI SDK works by pointing base_url at https://api.mafdet.ai/v1.

gemini-embedding-2 is the text embedding model. For image and video embeddings, use multimodal-embedding-1 (see Image embeddings and Video embeddings below). Audio and PDF embedding inputs are not enabled yet.

Request fields

FieldTypeDescription
modelstringgemini-embedding-2
inputstring | string[]A single text, or an array of texts (batch)
dimensionsnumberOptional output vector size: 768, 1536, or 3072 (default 3072)

Limits (per request): up to 100 inputs, 100,000 characters per input, 2 MB total. Empty input, an unsupported dimensions, or any non-string element is rejected before the request reaches the model.

Response fields

FieldDescription
objectlist
dataArray of { object: "embedding", embedding: number[], index }
usageprompt_tokens / total_tokens (embeddings have no completion_tokens)

Billing

Embeddings are billed on input tokens only — there is no generated output. gemini-embedding-2 sells at $0.24 per 1M input tokens (see Models overview for the live catalog price).

curl

curl https://api.mafdet.ai/v1/embeddings \
  -H "Authorization: Bearer $MAFDET_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gemini-embedding-2",
    "input": "The quick brown fox."
  }'

Python (OpenAI SDK)

from openai import OpenAI

client = OpenAI(
    base_url="https://api.mafdet.ai/v1",
    api_key="sk-mafdet-xxxxxxxxxxxxxxxx",
)
resp = client.embeddings.create(
    model="gemini-embedding-2",
    input=["first text", "second text"],
    dimensions=768,
)
print(len(resp.data), "vectors,", len(resp.data[0].embedding), "dims")

Node.js

const res = await fetch("https://api.mafdet.ai/v1/embeddings", {
  method: "POST",
  headers: {
    Authorization: `Bearer ${process.env.MAFDET_API_KEY}`,
    "Content-Type": "application/json",
  },
  body: JSON.stringify({
    model: "gemini-embedding-2",
    input: "The quick brown fox.",
  }),
});
const data = await res.json();
console.log(data.data[0].embedding.length, "dims");

Image embeddings

multimodal-embedding-1 turns an image into a 1408-dim vector in the same space as its text embeddings, for image search and multimodal retrieval. It is a separate model from gemini-embedding-2 and uses the same /v1/embeddings endpoint.

Pass each image as a data:image/...;base64,... data URI (a plain data URI string, or an array of them for up to 8 images). Text, bare base64, and image_url objects are rejected — send images as data URIs only.

# IMAGE=$(base64 -w0 photo.png)
curl https://api.mafdet.ai/v1/embeddings \
  -H "Authorization: Bearer $MAFDET_API_KEY" \
  -H "Content-Type: application/json" \
  -d "{
    \"model\": \"multimodal-embedding-1\",
    \"input\": \"data:image/png;base64,$IMAGE\"
  }"
import base64
from openai import OpenAI

client = OpenAI(base_url="https://api.mafdet.ai/v1", api_key="sk-mafdet-...")
with open("photo.png", "rb") as f:
    uri = "data:image/png;base64," + base64.b64encode(f.read()).decode()
resp = client.embeddings.create(model="multimodal-embedding-1", input=uri)
print(len(resp.data[0].embedding), "dims")  # 1408

Billing is per image: multimodal-embedding-1 sells at $0.00012 per image (1 image = 1 unit). Up to 8 images per request. Errors (400, never billed): MM_EMBEDDING_NO_IMAGE (no image data URI), MM_EMBEDDING_MODALITY_NOT_ENABLED (a non-image item was included), MM_EMBEDDING_TOO_MANY_IMAGES.

Video embeddings

multimodal-embedding-1 also embeds video into the same 1408-dim space. Unlike images, a video is passed in the Vertex-native form — an array element {"video": {"bytesBase64Encoded": "<raw base64>"}} (raw base64, not a data: URI). The provider returns one vector per interval of the clip.

Limits (per request), a staged first release: 1 video, up to 6 seconds, and up to 300 KB. The size cap matters as much as the duration one — a clip's base64 is what counts against your key's per-minute token limit (roughly 929 tokens per KB), so a short but high-bitrate clip can still be too large. Both caps are checked before the model is called, so an oversized clip is never billed.

import base64
from openai import OpenAI

client = OpenAI(base_url="https://api.mafdet.ai/v1", api_key="sk-mafdet-...")
with open("clip.mp4", "rb") as f:
    b64 = base64.b64encode(f.read()).decode()
resp = client.embeddings.create(
    model="multimodal-embedding-1",
    input=[{"video": {"bytesBase64Encoded": b64}}],
)
print(len(resp.data), "vectors,", len(resp.data[0].embedding), "dims")

Billing is per second of video: $0.0006 per second (the clip's own duration, rounded up to the whole second). A 6-second clip costs 6 × $0.0006 = $0.0036. Errors (400, never billed): VIDEO_EMBEDDING_NOT_ENABLED (video not enabled for this deployment), MM_EMBEDDING_VIDEO_TOO_LONG (over the duration cap), MM_EMBEDDING_VIDEO_TOO_LARGE (over the size cap), MM_EMBEDDING_VIDEO_UNREADABLE (not a readable mp4 — an unmeasurable clip is refused, never billed at 0), MM_EMBEDDING_TOO_MANY_VIDEOS.

Note: even within these caps, a video's base64 counts against your key's per-minute token limit — a 300 KB clip is worth roughly 279,000 tokens. A key on a lower plan can therefore still hit 429; if you plan to embed video, use a key whose tpm limit covers it.

Error codes

CodeMeaning
EMBEDDING_MODALITY_NOT_ENABLEDText model got a non-text item (use multimodal-embedding-1 for images)
EMBEDDING_INPUT_EMPTYEmpty string or empty array
EMBEDDING_ITEM_TOO_LONGAn input exceeded the per-item character limit
EMBEDDING_BATCH_TOO_LARGEMore than 100 inputs in one call
EMBEDDING_INPUT_TOO_LARGECombined input exceeded the total byte limit
EMBEDDING_DIMENSIONS_INVALIDdimensions not one of 768 / 1536 / 3072

All of the above return 400 before the provider is called, so a rejected request is never billed.

Next steps