Skip to content

Embeddings

Turn text into vectors to compare meaning: the call, what the response carries, the limits and the cost.

Updated on Aug 10, 2026

hinow/hiembed turns text into a list of numbers — the embedding. Texts that mean the same thing produce similar lists, even without a single word in common. That is what makes it possible to search by meaning instead of searching for an exact term.

It answers at POST https://api.hinow.ai/v1/embeddings, with the same key and the same base URL as the rest of the API. Pricing is per input token — US$ 0.05 per million.

What it is for

An embedding does not answer questions or write text: it measures closeness in meaning. Every use grows from that.

  • Semantic search — finding the right answer even when the user writes it in other words.
  • RAG — selecting the passages that go into the language model's context before it answers.
  • Recommendation — "similar to this one" across products, articles, job posts or tickets.
  • Clustering and triage — grouping messages about the same subject, with no hand-written list of categories.
  • Deduplication — finding the ticket already opened, the repeated record, the question that already has an answer.

The first call

The text goes in input and the model id in model:

curl https://api.hinow.ai/v1/embeddings \
  -H "Authorization: Bearer $HINOW_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "hinow/hiembed",
    "input": "Como redefinir minha senha?"
  }'

The response, with the vector trimmed to fit the page:

{
  "object": "list",
  "model": "hinow/hiembed",
  "data": [
    {
      "object": "embedding",
      "index": 0,
      "embedding": [-0.006066, 0.021058, -0.054192, -0.038931, "... mais 1020 números"]
    }
  ],
  "usage": { "prompt_tokens": 10, "total_tokens": 10 }
}

Three fields matter:

  • data[].embedding — the vector, with 1024 numbers.
  • data[].index — the position in input of the text that produced that vector. It is how you recover the order when sending a batch.
  • usage.prompt_tokens — what was charged.

The cost does not come in the response

Unlike /v1/images, /v1/embeddings does not return a cost field. The bill comes from usage.prompt_tokens multiplied by the model price: US$ 0.05 per million tokens. Record the usage of each call if you need to reconcile consumption.

Already using the OpenAI SDK?

The endpoint is compatible: switch the baseURL to https://api.hinow.ai/v1, use your HINOW key and set model to hinow/hiembed. The rest of the code stays the same. See the client SDKs.

What the vector is

It is 1024 numbers between -1 and 1. None of them means anything on its own: there is no "position 42 is the finance topic". The vector only takes on meaning when compared with another vector from the same model.

hiembed vectors already arrive normalised — the norm is exactly 1. That has a practical consequence which saves code: the dot product between two vectors is already the cosine similarity, with no need to divide by any norm.

conferindo.pypython
vetor = resposta["data"][0]["embedding"]

len(vetor)                              # 1024
vetor[:4]                               # [-0.006066, 0.021058, -0.054192, -0.038931]
sum(x * x for x in vetor) ** 0.5        # 1.0  -> já normalizado

The same text does not return the same vector

Twenty calls with the same sentence produced slightly different vectors — the largest difference in a single component was 0.00016, and the similarity between them stayed at 0.999999. For comparison that is irrelevant; for equality it is not: do not use the vector as a cache key, and do not look for duplicates by testing whether two vectors are equal. Compare by the text, or by similarity with a threshold.

Comparing two texts

Cosine similarity ranges from -1 to 1: the higher it is, the closer the meanings. Since the vectors arrive normalised, the whole function fits on one line:

def similaridade(a, b):
    return sum(x * y for x, y in zip(a, b))

# Com numpy, sobre muitos vetores de uma vez:
# import numpy as np
# scores = np.array(vetores) @ np.array(consulta)

The numbers below are the real output of those calls — look at the distance between the bands, not at the values themselves:

Pair of textsSimilarity
"Delivery takes 3 to 5 business days." × "The delivery takes three to five business days."**0.9598**
"cartão de crédito" × "cartao de credito"0.8950
"Delivery takes 3 to 5 business days." × "We accept Pix and bank slips."0.4872

A full paraphrase lands above 0.95 without repeating a single word in the same form. A missing accent barely changes the result — which handles much of Portuguese search with no text processing at all. And two different subjects drop to around 0.48.

What an embedding does not capture

"The cat climbed on the roof" and "The roof climbed on the cat" have a similarity of 0.9558: same words, swapped roles, opposite meaning. An embedding measures subject, not assertion. Do not use it to check facts, to tell a negation from its affirmative counterpart, or to compare numbers, dates and identifiers — that is what exact filters are for, and they are cheaper.

Several texts in one call

input accepts a list. The response carries one item per text, and index says which one each vector came from — do not trust the array order, trust index:

textos = [
    "Para trocar a senha, abra Configurações › Segurança.",
    "O prazo de entrega padrão é de 3 a 5 dias úteis.",
    "Aceitamos cartão de crédito, Pix e boleto bancário.",
]

resposta = requests.post(
    "https://api.hinow.ai/v1/embeddings",
    headers={"Authorization": f"Bearer {os.environ['HINOW_API_KEY']}"},
    json={"model": "hinow/hiembed", "input": textos},
).json()

vetores = [item["embedding"] for item in sorted(resposta["data"], key=lambda i: i["index"])]
print(len(vetores), resposta["usage"]["prompt_tokens"])

The gain is in the network, not in the price: a token costs the same on its own or in a batch. In a measurement of 500 short texts in a single call, the whole response took 2.0 s — against 500 round trips had they been separate calls.

A text has a size ceiling

Each input item fits around 8,192 tokens. An 8,003-token text went through; above that the call fails with a provider error, not with a 400 explaining why. Split the document into passages before sending — which you will want to do anyway for search to work well.

Dimensions

The default is 1024 dimensions. The dimensions parameter asks for a smaller vector, which reduces memory and index size — useful when there are millions of vectors stored.

The saving charges a price in quality, and it is not linear. On the same search, over the same base:

dimensionsObserved result
1024 (default)First result correct, with a 0.04 margin over the second
512First result correct, same order as the default
128**First result wrong** — the right passage falls out of the top

Ask for the dimension, but check what came back

dimensions is not always honoured: in one measurement, a request for 256 returned a 1024 vector. Vectors of different sizes in the same index cannot be compared — read len(embedding) in the response and reject anything that does not match the index.

When something goes wrong

SituationResponse
A chat model on this endpoint400Model '...' does not support embeddings
input missing or an empty list400input is required
A model that does not exist404Model '...' not found
encoding_format: "base64"502 — not supported; use the default number format

Empty text is not refused

"input": "" returns 200, with a valid vector, and is charged. Nothing in the response indicates the text was empty. Filter empty strings before assembling the batch — otherwise they enter the index and start showing up in searches.

What it costs

US$ 0.05 per million input tokens. Only what you send counts; there is no output charge, because the output is the vector.

In the numbers of a real case: indexing 10 thousand passages of roughly 200 tokens each gives 2 million tokens — US$ 0.10, once. After that, each search costs the embedding of the question: a 10-token sentence comes to US$ 0.0000005. The cost of a semantic search is in the storage and the server, not in the API.

Keep the vectors

Generating the embedding again costs again. A generated vector is your data: store it alongside the source text, with the model id and the dimension. That is what lets you reprocess only what changed — and find out, on the day you switch models, what needs redoing.

Next steps

Was this page helpful?