Embeddings

POST/v1/embeddings

Vectors for text, in the OpenAI shape.

Request

modelstringbodyrequired
the name of an embedding model from GET /v1/models
inputstring|arraybodyrequired
the text, or an array of texts; the answer keeps the input order

Responses

Response

{
  "object": "list",
  "data": [
    { "object": "embedding", "index": 0, "embedding": [0.0023, -0.0091, 0.0157] }
  ],
  "usage": { "prompt_tokens": 5, "total_tokens": 5, "cost_usd": "0.0000001" }
}

moderation stopped the prompt before the model (type: content_policy_violation)

no key in the request, or the key is not ours

the balance does not cover this request's worst-case price

model_not_found — the model is switched off by the admin — it leaves GET /v1/models too

the upstream answered with a rate limit; retry with a delay

the upstream is unreachable (type: upstream_error)

a timeout waiting for the upstream: 300 s read, 60 s without bytes on a stream

Details

Needs a key in Authorization: Bearer or x-api-key.

A straight pass-through to an OpenAI-compatible upstream: this route has no logic of its own beyond the gateway-wide parts — idempotency, the disabled-model check, the balance check and the cost in the answer. Fields other than those listed (dimensions, encoding_format and the rest) are forwarded untouched. The gateway picks no model for you: model must name an embedding model from the catalog.

This request's cost arrives inside the answer: the x-teamtoken-cost-usd header and usage.cost_usd in the body. The value is a decimal string ("0.0000465"), not a number: a number would be re-displayed by the client language's own float rules (Python would show 4.65e-05), while a string reaches your code exactly as written. The cost can also fail to arrive at all — then it is in neither the header nor the field: on a non-streaming answer when the upstream did not report it, on a stream when the model has no catalog tariff. There is no streaming for embeddings: the gateway reads the whole answer. Moderation does not apply to this path — it is only armed where there is a prompt for a model.

A byte-identical request with the same key inside a short TTL (60 s by default) does not reach the model twice — the gateway returns the first answer's body and charges nothing for the second. Only a successful answer of at most 256 KB is cached; anything else goes upstream again. A replay from the cache carries no x-teamtoken-cost-usd header (nothing was charged), and the cost_usd in its body belongs to the first, paid answer. Hence the corollary: an already-paid answer is served even on an empty wallet — the balance check sits AFTER idempotency. Every error arrives in one envelope (the code field is not on every status): { "error": { "message": "...", "type": "...", "code": "PROVIDER_CODE" } }.

The answer always carries back the logical model name you asked for. If it does not fit the gateway's wait (300 s read by default, 60 s without bytes on a stream) you get a 504; the gateway marks that non-streaming attempt, and if the upstream finished and billed anyway, the reconciler credits the amount back to your balance as a compensating grant. Upstream host names are scrubbed out of error bodies, so an error's text can differ from what the upstream sent.

This path has no route of its own: one gateway handler takes every POST /v1/*, and its list of accepted paths is closed — any other /v1/* answers 404.

Code examples
# MODEL — an embedding model id from GET https://api.teamtoken.store/v1/models
curl https://api.teamtoken.store/v1/embeddings \
  -H "Authorization: Bearer sk-…" \
  -H "Content-Type: application/json" \
  -d "{\"model\": \"$MODEL\", \"input\": \"text to embed\"}"
Request
https://api.teamtoken.store/v1

The panel calls this domain; in your own code use the address above.

The key is never stored: it lives in this tab until you reload the page.

the name of an embedding model from GET /v1/models

the text, or an array of texts; the answer keeps the input order

This request really goes out and costs money at the model's tariff.

Response

Press “Send request” above and the answer shows up here.