API Reference
POST/v1/understand

Intent Engine

Classifies what a caller or chat user is trying to do — a bank-dispute flow, a connectivity complaint, a yes/no confirmation — without a round trip through an LLM. Built for IVR and voice-bot turns where you need a routing decision in single-digit milliseconds and a cost per call far below a chat completion, reserving the LLM for free-form conversation rather than classification.

Preview: currently ships with one demo intent pack (ATM/banking disputes and telecom connectivity flows) to validate the contract end-to-end. Contact support@inferexai.in to have your own intents, phrasing examples, and canned responses loaded as a pack.

How it works

Every call to /v1/understand runs the same pipeline against your text:

1. Dialogue act + entities
Runs on every turn regardless of classification outcome. Dialogue act tags the turn as a statement, question, confirm, deny, greeting, etc. Entity extraction pulls out amount, phone, email, and date values deterministically (regex-based, not a model call).
2. Bare confirmation check
If the session has a pending yes/no question (see "Decision" below) and this turn is just confirmation or denial, it is resolved directly against that context — a classifier has no way to know what a bare "yes" refers to, so this never goes through classification at all.
3. Classification cascade
Otherwise, text is classified in stages, cheapest first: a deterministic lexical matcher runs first; only if it doesn’t clear the confidence threshold does a heavier stage run. Each stage can resolve the turn — later stages exist only for what the previous one left AMBIGUOUS or UNKNOWN.
4. Decision engine
A resolved intent maps to a next action and state — e.g. CREATE_DISPUTE, ESCALATE, ASK, CLOSE — defined per-intent in the pack, with a separate action/state for the confirmed path vs. the initial ask.
5. Response reference
The decision names a response_id, not rendered text. Your application resolves response_id → copy (in the requested language/channel) from its own template store or ours — see "Response is a reference" below.

classifier_used tells you which stage actually resolved the turn — deterministic, local_model, context (the yes/no shortcut above), llm_fallback, or none when nothing resolved it. It never names a specific third-party model, the same abstraction every other model type in this gateway holds to.

Request body (JSON)

ParameterTypeDescription
modelrequiredstringIntent model ID. Call GET /v1/models and pick a model with type "intent".
session_idrequiredstringYour own conversation/call ID. Scoped to your API key — reusing the same string on a different key never shares context, so it’s safe to generate these however is convenient for you (a UUID, your call-record ID, etc).
textrequiredstringThe caller or user turn to classify — a transcript segment, a chat message.
languagestringBCP-47 hint (e.g. "hi-IN"). Defaults to "en-IN". Affects dialogue-act and entity detection, and which language a resolved response_id is tagged with.

Example

bash
curl https://api.inferexai.in/v1/understand \
  -H "Authorization: Bearer sk-live-your-key" \
  -H "Content-Type: application/json" \
  -d '{
    "model": "inferex-intent-demo",
    "session_id": "a3f9c2e1-...",
    "text": "ATM se paisa nahi nikla par account se kat gaya",
    "language": "hi-IN"
  }'
response.json
{
  "model": "inferex-intent-demo",
  "session_id": "a3f9c2e1-...",
  "request_id": "req_abc123",
  "classification": "KNOWN",
  "intent": { "id": "BANKING.ATM.CASH_WITHDRAWAL.CASH_DEBITED_NOT_RECEIVED", "confidence": 0.86, "band": "HIGH" },
  "candidate_intents": [
    { "id": "BANKING.ATM.CASH_WITHDRAWAL.CASH_DEBITED_NOT_RECEIVED", "score": 0.86, "source": "rules" }
  ],
  "entities": {},
  "dialogue_act": "STATEMENT",
  "decision": {
    "action": "CREATE_DISPUTE",
    "next_state": "AWAITING_ACCOUNT_NUMBER",
    "response_id": "banking.atm.cash_debited_not_received.ask_account"
  },
  "response": { "response_id": "banking.atm.cash_debited_not_received.ask_account", "language": "hi-IN", "channel": "text" },
  "classifier_used": "deterministic",
  "latency_ms": 4
}

Classification values

intent is non-null if and only if classification is KNOWN — there is no "low-confidence guess" to accidentally read as a match.

KNOWNMatched a specific intent with enough confidence to act on. intent is populated.
AMBIGUOUSMultiple candidates scored close together — see candidate_intents. intent is null; consider asking a clarifying question.
UNKNOWNNothing in the pack matched. intent is null — this text is outside what the pack currently covers.
OUT_OF_SCOPERecognized as outside this pack’s domain entirely (e.g. small talk during a banking flow). intent is null.

Entities

entities is a flat object keyed by type — currently amount, phone, email, and date — populated when found in the turn, omitted otherwise:

JSON
{
  "...": "...",
  "entities": { "amount": 5000, "phone": "9876543210" }
}

Multi-turn / confirmation

When a decision.next_state indicates the pack is waiting on a yes/no, send the next turn with the same session_id — a bare confirmation is resolved from context, not re-classified, and decision.action/response_id on the confirmed path can differ from the initial ask:

next turn, same session_id
{
  "model": "inferex-intent-demo",
  "session_id": "a3f9c2e1-...",
  "text": "haan",
  "language": "hi-IN"
}

Response is a reference, not text

response.response_id identifies a reply template — it is not the reply text itself. Resolve it (in response.language, over response.channel: text, voice, …) against your own copy store, or ask us to ship your pack with its response copy included so you can request the rendered string in a future version. This keeps wording changes (tone, script updates, a copy fix) out of the classification contract entirely.

Cost

Billed per call to /v1/understand — one charge regardless of which cascade stage resolved the turn (the deterministic stage resolves the large majority of turns in-domain, which is what keeps the per-call cost well below an LLM chat completion). The live rate for your account is on GET /v1/models / the Billing page, same as every other model type — there is no separate pricing surface for intent.

Error codes

400
missing_input
session_id or text missing from the request body.
401
invalid_api_key
Missing or invalid API key.
402
insufficient_credit
Wallet is empty. Top up before retrying.
403
kyc_required / insufficient_scope
KYC verification is required, or the key lacks the "intent" scope.
404
model_not_found
The model ID does not exist or is not available to your account.
503
model_unavailable
The classification service did not respond. Retry after a short wait.