verified.create

verified.create

The hero endpoint: grounded generation with verbatim citations and ungrounded claims removed.

  • SDK: mx.verified.create(params)
  • HTTP: POST https://api.maxmodel.com/v1/verified
  • Auth: Authorization: Bearer <MAXMODEL_KEY>

Parameters

FieldTypeDefaultNotes
modelstringAny model your gateway key can call (e.g. gpt-5.5-pro).
messages{ role, content }[]role is system | user | assistant.
sources{ id, text }[]Your own chunks. id is yours and is echoed back in citations. MaxModel does not retrieve in v1.
mode'strict' | 'lenient''strict'How quotes are matched. See How verification works.
minCoveragenumber0 (off)If the grounded share (coverage) is below this, the result is flagged abstained.
retrynumber0Re-generate up to N more times while any claim is unsupported; stops early when fully grounded. usage.modelCalls reflects the attempts.
checkNumbersboolean | 'source' | 'row'falseRequire numbers in a claim to appear verbatim in its source. true/'source' = anywhere in the source. 'row' = in the same table cell / line as the claim’s row+column context — catches the right number, wrong row/column error in tables (e.g. grabbing Q3 revenue as Q3 profit). A claim with an ungrounded number → unsupported with number_not_found.
allowUngroundedbooleanfalseIf true and a question can’t be grounded, return a flagged plain answer instead of erroring.
temperaturenumberPassed through to the gateway.
maxTokensnumberPassed through to the gateway.

The total size of sources text has a budget (~100k chars). Over-budget requests return 400 sources_too_large.

Request (HTTP)

{
  "model": "gpt-5.5-pro",
  "messages": [{ "role": "user", "content": "What is our refund policy?" }],
  "sources": [
    { "id": "refunds.md", "text": "Full refunds within 30 days. No refunds after 30 days." },
    { "id": "pricing.md", "text": "Pro is $29/month, billed annually." }
  ],
  "mode": "strict",
  "allow_ungrounded": false
}

Over HTTP the fields are snake_case (allow_ungrounded, max_tokens). The TypeScript SDK uses camelCase (allowUngrounded, maxTokens) and converts for you.

Response

{
  "id": "vfd_abc123",
  "model": "gpt-5.5-pro",
  "text": "Full refunds are available within 30 days [refunds.md]. After 30 days, no refunds [refunds.md].",
  "citations": [
    {
      "claim": "Full refunds are available within 30 days",
      "quote": "Full refunds within 30 days",
      "source": "refunds.md",
      "range": [0, 27]
    }
  ],
  "unsupported": [
    { "claim": "We also offer a 14-day free trial", "reason": "quote_not_found" }
  ],
  "grounded": true,
  "usage": { "prompt_tokens": 812, "completion_tokens": 143, "total_tokens": 955, "model_calls": 1 }
}

Response fields

FieldTypeNotes
textstringThe grounded answer, with inline [sourceId] markers.
citations[]CitationOne per grounded claim.
citations[].claimstringThe grounded statement.
citations[].quotestringThe verbatim span copied from the source.
citations[].sourcestringThe Source.id it came from.
citations[].range[number, number]Char offsets [start, end) into that source’s text — usable for highlighting.
unsupported[]UnsupportedClaims that could not be grounded — caught before your users see them.
unsupported[].reason'quote_not_found' | 'unknown_source' | 'number_not_found'Why it was dropped (number_not_found only when checkNumbers is on).
coveragenumberGrounded claims / total claims (deterministic). 0 when there are no claims.
abstainedbooleantrue when minCoverage > 0 and coverage < minCoverage.
groundedbooleanfalse only when allowUngrounded=true and we fell back to a plain answer.
usage.modelCallsnumberA verified call routes ≥ 1 model call through the gateway.

In the SDK, usage is camelCase: promptTokens, completionTokens, totalTokens, modelCalls.

Table / cell-level number grounding

Financial, legal, and medical answers live in tables, where the classic failure is the right number from the wrong row or column. With checkNumbers: 'row', a number must appear in the table cell whose row label and column header the claim names (or, for prose, the same line as the claim’s context) — else the claim is dropped:

const out = await mx.verified.create({
  model: 'gpt-5.5-pro',
  checkNumbers: 'row',
  messages: [{ role: 'user', content: 'What was Q3 revenue?' }],
  sources: [{ id: 'fin.md', text:
`| Quarter | Revenue | Profit |
|---|---|---|
| Q3 | $12.4M | $3.1M |
| Q2 | $9.8M | $2.0M |` }],
})
// "Q3 revenue was $12.4M [fin.md]" survives.
// "Q3 profit was $12.4M" or "Q3 revenue was $9.8M" would be dropped (wrong cell).

Deterministic, markdown tables, no LLM. Keep one fact per claim for the tightest cell binding.

Highlighting with range

Each citation carries the exact character offsets [start, end) of the verbatim quote in the original source text (computed by the same string match that verified it — exact, not fuzzy). That makes it trivial to render source-highlighted UIs, footnotes, or audit logs:

const out = await mx.verified.create({ model, messages, sources })
 
for (const c of out.citations) {
  const src = sources.find((s) => s.id === c.source)!
  const [start, end] = c.range
  // src.text.slice(start, end) === c.quote   ← always true, by construction
  console.log(highlight(src.text, start, end)) // wrap the span in <mark>, etc.
}

Because the offsets come from the deterministic match (not from the model), they’re safe to use for click-to-source highlighting and never drift from the text.

Streaming

/v1/verified is non-streaming in v1 — verification needs the complete claim set before it can return a trustworthy answer. Use chat.completions.create if you need token streaming without verification. Streaming verified output is a later item.

TypeScript types

interface VerifiedParams {
  model: string
  messages: { role: 'system' | 'user' | 'assistant'; content: string }[]
  sources: { id: string; text: string }[]
  mode?: 'strict' | 'lenient'
  allowUngrounded?: boolean
  temperature?: number
  maxTokens?: number
}
 
interface VerifiedResult {
  id: string
  model: string
  text: string
  citations: { claim: string; quote: string; source: string; range: [number, number] }[]
  unsupported: { claim: string; reason: 'quote_not_found' | 'unknown_source' }[]
  grounded: boolean
  usage: { promptTokens: number; completionTokens: number; totalTokens: number; modelCalls: number }
}