Skip to main content

POST /v1/ask

POST /v1/ask asks a natural-language question over every document in your workspace and returns a cited, verified answer. One flat credit per question, no RAG stack.

POST /v1/ask is the natural-language front door to your document corpus: send a question, get back an answer grounded in your own documents, with a citation for every load-bearing claim and a verification verdict on the answer as a whole. There is no index to build, no embeddings to manage, and no retrieval pipeline to tune. Every document you ingest with ingestion_target: "ingest" (the default on [POST /v1/run](run-spec)) is askable, and the question runs over the entire workspace corpus, not a top-k slice of it.

Only one field is required: question, up to 20,000 characters. The optional fields narrow, route, shape, or thread the turn: scope restricts it to a slice of the workspace as a hard filter, conversation_id continues a thread, model and model_class pick the model, output_format shapes the answer, and on_behalf_of applies a named user's compartment visibility. All of them are covered in depth in [Scope, Models & Access](ask-scoping). The endpoint answers 202 Accepted immediately with an ask_id, a poll_url, a stream_url, and the conversation_id the turn threads into; the answer itself is produced asynchronously and collected via [GET /v1/ask/:id](ask-results) or streamed live via [GET /v1/ask/:id/stream](ask-streaming). A turn typically takes 10 to 60 seconds, which is why the surface is async-only by design: a synchronous response would sit inside edge and proxy timeouts. Authentication is a standard tlnc_ Bearer key with the read scope. The key must be workspace-scoped: asks are tenant-isolated end to end.

Why this replaces a RAG stack

A conventional RAG pipeline embeds document chunks, retrieves the top-k nearest ones, and hopes the answer is inside that slice. An ask on Talonic instead runs a read-only agent turn over a corpus that was structured at ingestion. The agent retrieves across three planes at once: a semantic match against the field registry (the deduplicated graph of every field concept discovered in your documents), a lexical match over the extracted cell values themselves, and semantic plus full-text search over the raw document text through a persistent chunk index. A question about a number, a date, or a counterparty does not depend on the right paragraph landing in a context window: the value was already extracted, typed, and bound to a canonical concept.

On top of retrieval, the agent runs read-only SQL over the structured cell plane. Questions RAG is structurally bad at, such as "how many of our contracts auto-renew?" or "what is the total value of invoices from Q2?", become aggregate queries over extracted cells with the denominator taken from real corpus coverage, never estimated from a handful of retrieved chunks. And the corpus improves as it is questioned: when a question exposes a coverage gap, the platform extracts and persists at query time, promoting or mining the concept into the structured plane, so the second time anyone asks, the answer is a plain SQL read. Your corpus gets faster and cheaper to query the more it is used, which is the opposite of a RAG stack.

Two more properties matter for trust. First, the coverage plane turns absence into evidence: "no document in the workspace mentions a termination penalty" is a checkable statement backed by corpus-wide coverage, not a guess from an empty retrieval. Second, every answer passes through a post-answer verification step that re-checks the answer's claims against the evidence the turn itself gathered, and the verdict ships in the response. See [Citations & Verification](ask-citations-verification) for how to consume both.

An ask never modifies your workspace. The turn runs under a least-privilege read-only role: documents, schemas, pipelines, and settings cannot be changed by a question, and every mutating tool is denied before it executes.
POST/v1/ask

Request body (JSON)

question*stringThe natural-language question, up to 20,000 characters. Markdown is fine; the agent reads it as plain intent.
scopeobjectRestrict the turn to a slice of the workspace: document_ids (max 1000), schema_id, pipeline_id, data_product_id, document_type, source_id, tags (max 100), ingested_after, ingested_before. Present fields are ANDed and enforced as a SQL predicate, not a hint. An empty document_ids array matches nothing.
conversation_iduuidContinue this conversation; the agent answers with the prior turns in view. Absent, a fresh conversation is created and its id returned.
modelstringRun the turn on a specific model, e.g. claude-opus. A model the workspace AI policy denies fails loudly; it is never silently substituted.
model_classstringRun the turn on a model class, e.g. complex. Used when model is absent.
output_formatobjectShape the final answer: instruction (free-text format instruction, max 4,000 chars), template (a markdown skeleton the answer keeps, max 20,000 chars). Constrains form only, never grounding.
on_behalf_ofuuidAnswer as this workspace user would see it, applying that user's compartment and classification visibility. Opt-in per request; the default reads workspace-wide. See Scope, Models & Access.

curl

curl -s -X POST https://api.talonic.com/v1/ask \
  -H "Authorization: Bearer $TALONIC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"question": "Which of our agreements auto-renew, and what notice period does each one require?"}'

Response (202)

{
  "ask_id": "7c2f0a4e-9d31-4b8a-b3e6-2f1c5d9a8e07",
  "status": "processing",
  "poll_url": "/v1/ask/7c2f0a4e-9d31-4b8a-b3e6-2f1c5d9a8e07",
  "stream_url": "/v1/ask/7c2f0a4e-9d31-4b8a-b3e6-2f1c5d9a8e07/stream",
  "conversation_id": "8c4f2a1e-0b6d-4e2f-9a3c-5d7e1f2a3b4c"
}

Conversations

Every ask belongs to a conversation. Pass conversation_id to continue a thread, and the agent answers with the prior questions and answers in view, so follow-ups like "and only the ones above 50,000 EUR?" resolve against the earlier turn. Omit it and the platform creates a fresh conversation, returning its id on the 202 so the very first ask of a session already gives you the handle to thread the next one. Conversations are listed, read, renamed, and deleted through the [Conversations](agent-conversations) endpoints.

Pricing

Each accepted ask charges one flat agent_ask credit unit: 100 credits, or 0.10 EUR (1,000 credits = 1 EUR). The charge is taken when the ask is accepted and is keyed to the turn, so it is idempotent: a network retry of the same submission, or polling the result any number of times, never bills twice. There is no per-token or per-document component; a question over 10 documents and a question over 10,000 cost the same. The completed response reports the charge back in usage.credits_charged, and the full catalog is public at [GET /v1/pricing](pricing-overview).

When your balance cannot cover one unit, the ask is rejected up front with 402 insufficient_credits before any work starts. The 402 body follows the platform's agent-actionable credits contract: it names the unit, the shortfall, and a buy_credits_url, so an autonomous integration can top up and resubmit without human interpretation.

Rate limits

Ask submissions are metered in their own daily rate-limit namespace, ask, separate from extraction and platform reads. Polling GET /v1/ask/:id counts against the general read namespace, never against the ask budget, so tight polling loops are free with respect to this cap. Stream connects are metered in the separate ask_stream namespace, sized above ask to leave room for reconnects, and direct tool invocations in agent_tools; both are documented on [Streaming](ask-streaming) and [Invoke a Tool](agent-invoke-tool).

Daily ask caps by plan

freetier200 asks per day.
individualtier100 asks per day.
protier5,000 asks per day.
enterprisetierUnlimited.

Getting a key and a corpus

If your workspace already has documents, any read-scoped key works immediately. On deployments where self-serve signup is enabled, there is a zero-dashboard path from email to first answer: POST /v1/auth/register with your email sends a magic link, and following it (GET /v1/auth/register/confirm) returns a scoped tlnc_ key together with a seeded workspace containing two example documents, a Northwind invoice and an Acme/Globex master services agreement, so your very first POST /v1/ask has something real to answer against. To make your own documents askable, ingest them via [POST /v1/run](run-spec) with the default ingestion_target: "ingest".

Errors

Error responses

400validation_errorMissing or over-length question, or the API key is not workspace-scoped.
401unauthorizedMissing or invalid API key.
402insufficient_creditsBalance cannot cover one agent_ask unit. Body includes the shortfall and a buy_credits_url.
403insufficient_scopeThe key lacks the read scope.
429rate_limit_exceededDaily ask cap for your plan exhausted. Retry after the period in the Retry-After header.

Frequently asked questions

How is /v1/ask different from RAG?+
RAG embeds chunks and answers from the top-k retrieved slice. An ask runs a read-only agent turn over a corpus that was structured at ingestion: it retrieves across the field registry, the extracted cell values, and the full document text simultaneously, runs read-only SQL for aggregate questions, and extracts missing concepts at query time so repeat questions become plain structured reads. Every claim is cited to an exact source span and the answer is re-verified against the turn's own evidence.
What does an ask cost?+
One flat agent_ask unit per accepted question: 100 credits, or 0.10 EUR. The charge is idempotent per turn, so retries and polling never double-bill, and there is no per-token or per-document component.
Why is there no synchronous mode?+
A turn takes 10 to 60 seconds depending on how much retrieval, SQL, and verification the question needs. That exceeds common edge and proxy timeouts, so the surface is async-only: submit, get 202 with an ask_id, then either poll GET /v1/ask/:id roughly every 2 seconds or hold GET /v1/ask/:id/stream open for server-sent events.
Can I restrict a question to specific documents or a pipeline?+
Yes. Pass a scope object on the request: document_ids, schema_id, pipeline_id, data_product_id, document_type, source_id, tags, and ingestion-date bounds. The scope is enforced as a SQL predicate on every retrieval plane, so the model cannot read outside it. Note that an empty document_ids array matches nothing rather than meaning unscoped.
How do multi-turn conversations work?+
Every ask threads into a conversation. Pass conversation_id to continue one and the agent sees the prior turns; omit it and a fresh conversation is created, with its id returned on the 202. Conversations are listed and managed via the /v1/agent/conversations endpoints.
Can an ask change anything in my workspace?+
No. The turn runs under a least-privilege read-only role. Mutating tools are denied before execution, so documents, schemas, pipelines, and settings are never modified by a question.
Which documents can the agent see?+
Every document in the workspace the API key belongs to, and only those. Asks are tenant-isolated: an ask_id from another workspace reads as 404. Documents become askable when ingested with ingestion_target "ingest" (the default on POST /v1/run); markdown-only ingestion ("extract") keeps them out of the askable corpus.