Skip to content · تخطَّ إلى المحتوى
نبرة Nabra

Using the API

Structured responses

Field status, confidence, missing fields, confirmation — and `data`.

200 OK
{
  "requestId": "req_3f9c2a1b7d10",
  "schema": "restaurant_order",
  "schemaVersion": "1.0",
  "locale": "ar-JO",
  "sessionId": null,
  "transcription": {
    "text": "بدي ٢ شاورما ووجبة زنجر والتوصيل لخلدا، اسمي محمد ورقمي 0791234567",
    "language": "ar", "confidence": 0.9, "audioSeconds": 7.4
  },
  "fields": {
    "customerName": { "value": "محمد", "type": "person", "status": "extracted", "confidence": 0.86, "requiresConfirmation": false },
    "phone":        { "value": "0791234567", "type": "phone", "status": "extracted", "confidence": 0.93, "requiresConfirmation": false },
    "items": {
      "value": [ { "name": "شاورما", "quantity": 2 }, { "name": "وجبة زنجر", "quantity": 1 } ],
      "type": "array", "status": "extracted", "confidence": 0.86, "requiresConfirmation": false, "issues": []
    },
    "address":      { "value": "خلدا", "type": "address", "status": "extracted", "confidence": 0.86, "requiresConfirmation": false },
    "notes":        { "value": null, "type": "text", "status": "missing", "confidence": 0, "requiresConfirmation": false }
  },
  "data": {
    "customerName": "محمد", "phone": "0791234567",
    "items": [ { "name": "شاورما", "quantity": 2 }, { "name": "وجبة زنجر", "quantity": 1 } ],
    "address": "خلدا", "notes": null
  },
  "missingFields": [],
  "fieldsRequiringConfirmation": [],
  "complete": true,
  "language": {
    "requested": "auto", "detected": "ar", "locale": "ar-JO", "dialect": "jordanian", "dialectGroup": "levantine",
    "direction": "rtl", "mixedLanguage": false, "secondaryLanguages": [], "source": "detected",
    "evidence": ["بدي", "خلدا"]
  },
  "clarification": null,
  "warnings": [],
  "timings": { "uploadMs": 0.4, "transcriptionMs": 3120, "extractionMs": 3410, "validationMs": 1.1, "totalMs": 6533 },
  "models": { "speechToText": "faster-whisper:large-v3-turbo", "extraction": "ollama:qwen2.5:7b" }
}

The contract is the same for every schema and every language. data holds just the values — the JSON your application uses. fields explains each one, language says what language and dialect the input was in, and clarification is the next question to ask the user, in their language (or null).

Field status

StatusvalueMeaning
extractedsetSaid, and verified against what was said.
uncertainsetHas a value, but a person should check it: the role was inferred, the spelling adjusted, am/pm assumed, the model flagged it… `reason` says which.
invalidnullSomething was said for it, but not a valid value (a phone a digit short, «بكرا» without a reference time). `heard` holds exactly what was said.
rejectednullThe model proposed it, but it is not supported by what was said. Never returned as a value.
missingnullNot said.
defaultedsetNot said; the schema's `default` is used.
confirmedsetConfirmed or set by your application through a session review.

Confidence

confidence is computed by the service — how the value was verified, scaled by speech-recognition confidence — not reported by the model. Don't rely on it alone: the status and requiresConfirmation say what to do.

Missing fields and confirmation

  • missingFields — required fields without a value. complete is true when there are none.
  • fieldsRequiringConfirmation — money, fields the schema marks, every uncertain, invalid or rejected field, and missing required ones.
  • reason explains a status (am_pm_assumed, needs_reference_time, mapped_by_model…); heard holds what was said when it could not be used; issues lists problems inside lists and objects.

Recommended UI

  • Fill your form from data.
  • For invalid fields, put heard in the input so the user fixes one digit instead of retyping.
  • Ask clarification.message: it covers missing, invalid, ambiguous and uncertain fields, in the user's language.
  • Render text with dir="auto" (or language.direction): Arabic is right-to-left, English left-to-right, mixed input both.
  • Resolve addresses with your own place search — the API returns text, never coordinates.
  • Let the user review, then submit through your own backend.
invalid phone
"phone": {
  "value": null,
  "type": "phone",
  "status": "invalid",
  "heard": "078824021",
  "confidence": 0.3,
  "requiresConfirmation": true,
  "reason": "invalid_number_heard"
}