Text similarity
Two sentences can share zero words and mean the same thing, or share most words and mean something different. The Semantic Similarity API scores how closely two texts align in meaning, returning a numeric score per pair rather than a keyword-overlap count, so matching, deduplication and search logic can rely on what a passage actually says.
Run it online
Run this on our servers with your account. Free tools run in your browser; this one bills your KIT balance per the price above.
The problem with matching on words alone
Keyword overlap and simple string distance are cheap and fast, but they fail in both directions: 'the invoice is overdue' and 'payment hasn't arrived yet' share almost no vocabulary and mean roughly the same thing, while 'the report is not final' and 'the report is final' share nearly every word and mean opposites. Anyone building search, deduplication, or matching logic on top of naive text comparison eventually hits this wall. This endpoint scores meaning directly, so the comparison holds up on paraphrase, translation-adjacent wording, and negation, not just verbatim overlap.
How a request and response work
You POST one or more text pairs to /text/semantic-similarity. The task runs asynchronously, and each pair in the batch comes back with a similarity score once processing finishes, delivered by webhook or a signed link. Sending pairs in bulk is the normal pattern here — the endpoint is priced and built for scoring many comparisons in one call rather than a single pair at a time.
Where the idea of semantic distance comes from
The underlying concept — that meaning can be represented as a position in a high-dimensional space, where distance corresponds to relatedness — has roots in distributional semantics research from the 1990s, long before it became a standard building block of modern search and recommendation systems. It formalizes an old linguistic intuition: 'you shall know a word by the company it keeps.' The score this endpoint returns is a practical, numeric version of that same idea, applied to full passages rather than single words.
Where it slots into an automated system
Because scoring is async and priced per pair, it's built to sit inside larger logic: a deduplication job scores every new support ticket against recent ones to flag likely duplicates, or a search relevance layer re-ranks results by meaning rather than raw keyword hits. A failed batch is retried automatically up to three times and never billed if it doesn't complete, so running this at the scale of thousands of pairs stays predictable.
What the score does and doesn't capture
The score reflects closeness in meaning, not factual agreement or tone — two texts can score highly similar while disagreeing on a fact, and score lower while agreeing but phrased very differently. It's a signal for ranking and filtering at scale, best paired with a threshold you tune for your own use case rather than treated as an absolute judgment of correctness.
What you can do with it
Duplicate detection in support tickets
A helpdesk scores incoming tickets against open ones to surface likely duplicates even when customers phrase the same issue differently.
Search relevance re-ranking
A knowledge base re-orders search results by meaning-based similarity to the query instead of relying only on keyword matches.
Paraphrase and plagiarism screening
An education platform flags submissions that closely paraphrase a reference text without copying it word for word.
FAQ and content deduplication
A content team scores draft articles against the existing library to catch near-duplicate topics before publishing.
FAQ
How does the semantic similarity API work?
You send one or more text pairs to /text/semantic-similarity, the task runs asynchronously, and each pair gets a similarity score delivered by webhook or a signed link.
Is there a free tier for this text similarity API?
There's no free tier — free tiers get abused and slow everyone down. Access runs on a prepaid ForHosting KIT balance: top up from $10.00 (it never expires) and each request is charged at its published price, so a call with no balance returns HTTP 402. No subscription, no tokens, no invented credits, and a failed task is never charged.
How is semantic similarity priced?
$0.002 per request plus $0.002 per text pair scored, charged only on successful completion.
Can I send many pairs in one request?
Yes, batching pairs into a single call is the normal and cost-efficient way to use this endpoint at scale.
What does the similarity score actually mean?
It reflects closeness in meaning between two texts, not shared vocabulary or factual agreement, so paraphrased text can score highly even with different wording.
Does it work across different phrasing or paraphrases?
Yes, that's the core use case — it's designed to score meaning even when the two texts share little to no vocabulary.
What happens if a similarity task fails?
It's retried automatically up to three times and is never charged if it doesn't complete successfully.
How and when are results delivered?
Via a signed webhook, recommended for automation, or a signed link valid for 24 hours; input text is deleted after retention and never used for training.
For developers — API access
Everything on this page is available programmatically. This section is for teams who want to wire it into their own systems; everyone else can just use the tool above.
API endpoint
Prefer to automate it? One authenticated POST creates the task; the result comes back by webhook or a signed link. The same capability also runs here on the web, and soon from our app, email and Telegram.
Call it from your stack
curl -X POST https://api.kit.forhosting.com/text/semantic-similarity \
-H "Authorization: Bearer $KIT_KEY" \
-H "Content-Type: application/json" \
-d '{"input":"…"}'const res = await fetch("https://api.kit.forhosting.com/text/semantic-similarity", {
method: "POST",
headers: {
"Authorization": `Bearer ${process.env.KIT_KEY}`,
"Content-Type": "application/json"
},
body: JSON.stringify({
"input": "…"
})
});
const { task_id } = await res.json();import os, requests
res = requests.post(
"https://api.kit.forhosting.com/text/semantic-similarity",
headers={"Authorization": f"Bearer {os.environ['KIT_KEY']}"},
json={
"input": "…"
},
)
task_id = res.json()["task_id"]<?php
$res = file_get_contents("https://api.kit.forhosting.com/text/semantic-similarity", false, stream_context_create([
"http" => [
"method" => "POST",
"header" => "Authorization: Bearer " . getenv("KIT_KEY") . "\r\nContent-Type: application/json",
"content" => '{"input":"…"}',
],
]));
$task = json_decode($res, true);body := bytes.NewBufferString(`{"input":"…"}`)
req, _ := http.NewRequest("POST", "https://api.kit.forhosting.com/text/semantic-similarity", body)
req.Header.Set("Authorization", "Bearer "+os.Getenv("KIT_KEY"))
req.Header.Set("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)Example request
{
"input": "…"
}Example response
{
"task_id": "tsk_a1b2c3d4e5f6a1b2c3d4e5f6",
"type": "text.semantic_similarity",
"status": "queued",
"_links": {
"result": "/tasks/tsk_…/result"
}
}The API is asynchronous: the call returns a task_id immediately and the result arrives by webhook. Polling is capped at 1 req/s per task.
Pricing
Published price — no tokens, no invented credits. A failed task is never charged.
Limits
max_tokens | 20000 |
Errors
| HTTP | Code | Meaning |
|---|---|---|
401 | unauthorized | Missing or invalid API key. |
402 | insufficient_balance | Your balance doesn't cover the task price. |
404 | unknown_type | That task type doesn't exist. |
429 | rate_limited | Too many requests. Use the webhook instead of polling. |