API Reference

POST /match

Determine whether pairs of menu item names refer to the same dish. Uses a two-stage pipeline: fast bi-encoder cosine similarity, then a specialized cross-encoder reranker for high-accuracy match decisions.

Handles misspellings, transliterations, noise, and language differences. "Kadhai Chicken" and "Karahi Chiken" are the same dish. "Butter Chicken" and "Dal Makhani" are not.

Request

ParameterTypeRequiredDescription
pairsobject[]YesArray of pairs to compare. 1-100 pairs. Each has text_a and text_b (max 500 chars each).
cosine_thresholdfloatNoSimilarity threshold for match decision. Default: 0.85.
{
  "pairs": [
    {"text_a": "Kadhai Chicken", "text_b": "Karahi Chiken"},
    {"text_a": "Butter Chicken", "text_b": "Dal Makhani"}
  ],
  "cosine_threshold": 0.85
}

Response

FieldTypeDescription
resultsobject[]One result per input pair, in submission order

Each result:

FieldTypeDescription
text_astringFirst item (as submitted)
text_bstringSecond item (as submitted)
cosinefloatCosine similarity between embeddings (0-1)
reranker_scorefloat or nullReranker confidence (0-1), null if pair didn't pass cosine gate
matchboolTrue if the items refer to the same dish
dietary_conflictboolTrue if one item is veg and the other non-veg
protein_conflictboolTrue if items have conflicting proteins (e.g. chicken vs paneer)
{
  "results": [
    {
      "text_a": "Kadhai Chicken",
      "text_b": "Karahi Chiken",
      "cosine": 0.94,
      "reranker_score": 0.97,
      "match": true,
      "dietary_conflict": false,
      "protein_conflict": false
    },
    {
      "text_a": "Butter Chicken",
      "text_b": "Dal Makhani",
      "cosine": 0.72,
      "reranker_score": 0.12,
      "match": false,
      "dietary_conflict": false,
      "protein_conflict": false
    }
  ]
}

Example

import requests

response = requests.post("https://embed.statode.com/match",
    headers={"X-API-Key": "YOUR_KEY", "Content-Type": "application/json"},
    json={
        "pairs": [
            {"text_a": "Kadhai Chicken", "text_b": "Karahi Chiken"},
            {"text_a": "Butter Chicken", "text_b": "Dal Makhani"},
            {"text_a": "Cafe Latte", "text_b": "Caffe Latte (Regular)"}
        ]
    }
)

for result in response.json()["results"]:
    status = "MATCH" if result["match"] else "NO MATCH"
    print(f"{result['text_a']} vs {result['text_b']}: {status} (cosine={result['cosine']:.2f})")

Cost

1.0 credits per pair.

Notes

  • The reranker only fires for pairs that clear the cosine gate. If cosine similarity is very low, the pair is rejected without invoking the reranker, and reranker_score will be null.
  • dietary_conflict catches cases like "Classic Burger" vs "Veggie Burger" that look similar but shouldn't be merged.
  • protein_conflict catches cases like "Chicken Momos" vs "Paneer Momos".
  • For bulk deduplication of an entire menu, use /dedup instead of calling /match for every possible pair.