Journal des modifications
Ce qui a changé, et quand.
Les notes de version sont tenues dans le dépôt et publiées ici. Les changements d'API suivent la politique de compatibilité : additifs dans /api/v1, changements incompatibles uniquement dans une nouvelle version, avec préavis.
-
Help and support requests, from every page
- Ask for help without leaving the page. Help (bottom-right, or the ? in the top bar on phones) opens one message box: pick Problem, Question or Feedback, write what happened, and optionally add a screenshot (paste it, drop it, or choose a file). No account is needed; when you are signed out you can leave an email for the reply.
- See exactly what is sent. The page you wrote from, your browser and screen size are attached so you don't have to describe them, and the widget lists them before you send. Your documents are never attached.
- Your requests, with our replies. Your requests lists every request with its status (Received, In progress, Waiting on you, Resolved) and the full conversation. You can reply, add a screenshot, mark a request resolved and tell us whether it was solved.
- A bell for replies. The bell in the menu shows how many requests have a new reply. Requests sent while signed out stay on that browser, and can be added to your account after you sign in.
-
Clearer uploads, cleaner exports
- Uploads say what happened, once. An empty file is refused as soon as you choose it. A PDF saved with an image extension is read as the PDF it is. A password-protected PDF says so and how to fix it, instead of "may be corrupt". The early "Processing started" message that could appear next to an error is gone.
- The JSON export is your data. Structured data (JSON) in Export now contains the structured result (the same as Download JSON on the result), not internal processing details. Raw JSON in Processing details no longer shows internal keys or token counts, and field locations read "Page 1" (coordinates appear with Show evidence details).
- Where AI processing runs. Your profile states where AI extraction for your account runs, instead of asking you to contact an administrator.
- Smaller fixes. A mistyped address shows a "page not found" page instead of raw data. Possible duplicate is always shown in Documents, including for documents that need review. MCP is no longer offered in the navigation while its installation is unavailable.
-
Templates in every workspace; batches and results keep their place
- Your personal templates work inside a workspace. The Saved template picker lists the active workspace's templates and your personal ones, grouped by owner, and a personal template can be run while a workspace is active (it used to be missing from the picker and could not be run). Every template in Templates has Use template, and its ⋯ menu shows its icon again. Templates now has its own page title.
- Several documents at once, visibly. When you analyze several files separately, the list of documents stays on screen from the first file to the last, each with its state, and the count (2/4) moves as they finish; the page no longer goes blank between files, and one summary message replaces a message per file.
- Links keep their place. A batch has its own address, so a reload shows it again and Back from a document you opened out of it returns to the list. A new result gets its document address as soon as it is saved, so a reload reopens it instead of an empty upload form. If you try to leave while an edit is still open, the browser asks first.
- Accessibility. In Saved template mode, "1 Select template" now also comes before "2 Upload document" for screen readers and the keyboard. The Done button is announced as "Done". A message shown while a dialog is open appears above the dialog instead of behind it.
-
The analytics dashboard opens again
- Fix: the Analytics dashboard no longer opens to a blank page. Its code was loaded twice under two addresses, so the page crashed before it could draw. It now loads once, and if anything on the dashboard ever fails to display, the page says so and offers Reload and Go to Documents instead of going blank.
-
Corrections you can undo, counts you can trust
- A correction keeps what was extracted. After you edit a value, its details show Extracted: with the original value and Restore extracted value, which brings back the value together with its place in the document. The restore is recorded in the document's history.
- Editing is not verifying. An edited value stays in the not yet verified count until someone confirms it, and no longer shows OK. A value you type no longer keeps highlighting the text its old value was read from.
- Safer review keys. The review shortcuts (j / k, c, Enter) act only on fields you can see; with the field panel collapsed they do nothing. Clicking a field's name opens its details without an editor, so the shortcuts are never typed into a value. Esc or Cancel discards an open edit, and while an edit is open the panel says Unsaved change - press Done to save it instead of "All changes saved".
- Supplier notes are learned only from a finished review. Notes are learned when you complete a review in which you corrected a supplier's details (name, address, tax number, currency, payment method), from the extracted value to your final one. An edit you undo, and a document's own values (totals, dates, invoice numbers), are never learned; notes of that kind learned earlier are no longer used. A result now says which notes it used (Supplier notes for Northwind GmbH: Payment method), the notes dialog opened from it lists that supplier only, and deleting a note asks for confirmation.
- Line-item flags say why. Instead of "The line-item table still needs review", the reason names the problem, for example rows without a quantity or price, a row that does not add up, or no document total to check against, and what to do. The Issues list no longer says No open issues when the open issue is the line-item table.
- Renaming. An empty name is refused with Enter a name. instead of being ignored, and the sidebar's Recent list shows the new name right away.
-
The pages you are shown, read and charged agree
- The AI reads every page you are charged for. The first 5 pages of each document are analyzed: the number stated before upload, the number charged, and now also the number the AI reads (it used to read only the first 3). A longer document says Only the first 5 of 6 pages were analyzed and needs Accept partial analysis before it can be Ready. Re-analyzing a saved document reads the same 5 pages. The pricing page, user guide, product tour and privacy policy state the same limit. API: in
GET /api/v1/capabilities,max_llm_pagesnow equalsmax_pages_analyzed. - A blank page is not a result. When nothing can be read from a document, it is Failed with Nothing could be read from this document. Upload a clearer or complete copy., and it is not charged (the same bounded allowance as results the AI could not produce).
- Usage lists what was actually charged. Profile → Usage & pages now shows each charge as recorded: the pages charged per document (0 when nothing was charged), AI sensitivity scans on their own line, and deleted documents as Deleted document, so the list adds up to Pages used.
- The sharing scan costs what it says. The AI sensitivity scan costs 1 page per document, charged once (opening the share dialog again does not charge again) and only when the AI scan runs. After the check, the dialog says which it was: AI sensitivity scan · 1 page for this document or Checked with the built-in rules · no page charged.
- Clearer allowance wording. An API key's monthly limit is shown as a Key cap that uses your page allowance, and the Free plan is described as a one-time page allowance.
- The AI reads every page you are charged for. The first 5 pages of each document are analyzed: the number stated before upload, the number charged, and now also the number the AI reads (it used to read only the first 3). A longer document says Only the first 5 of 6 pages were analyzed and needs Accept partial analysis before it can be Ready. Re-analyzing a saved document reads the same 5 pages. The pricing page, user guide, product tour and privacy policy state the same limit. API: in
-
Dates and amounts are typed on every result
- Automatic results are normalized. For invoices, receipts, purchase orders and the other built-in document types, the structured data (screen, API, webhooks, exports) now gives dates as
2026-09-15and amounts as1156.68, with the value as printed shown beside it (As printed: 1,156.68). API:structured_output.data_formatis"typed-v1"for these results, with the printed value instructured_output.field_metadata. Generic documents (other, contracts, forms) are unchanged:"as-extracted". - An invalid value is never Ready. A date that does not exist (for example
2026-02-30typed by hand) or an amount that is not a number now makes the result Review required with a plain reason (This is not a valid calendar date.) and a Fix field action. The review cannot be completed, and the value is not accepted in bulk, until it is corrected. - Dates are read from the document itself.
03/04/2026is read as March 4 when the same document prints03/19/2026, and as 3 April on a German, French, Spanish, Italian or Polish document. When nothing on the document settles it, the result asks you to enter the date asYYYY-MM-DDinstead of guessing. - Exports use the normalized values. UBL e-invoices carry valid dates, amounts, UN/ECE unit codes and only the IBAN as the payment account; Xero, QuickBooks and CSV exports use
YYYY-MM-DDdates; DATEV rows useTTMMdates and a decimal comma; XLSX stores numbers and dates as real cells, with the printed value in its own column. A value that cannot be read is left out and named in a warning, and Xero, QuickBooks and DATEV exports say what the target still needs before an import (account codes, tax types). - The header follows your edits. The date and total under the document title update as soon as a correction is saved.
- Templates started from a document type keep their types. Dates start as Date and amounts as Amount instead of Text.
- Receipt and German formats are read correctly. Short years (
21.09.26), a weekday before the date (Di. 24.09.2026) and zero-cent amounts (1.234,-) are normalized instead of flagged. - No value is filled in from text the AI did not read. When the AI finds no total, no VAT rate or no payment method, the field stays empty (a required one is listed as an issue) instead of being filled from a text search over the page - which could pick up a subtotal from a page the AI never saw, or read "7.25%" as "25%".
- A source highlight means what it shows. A value is highlighted only on text that says it: a percentage needs its "%", and a number is never located on a longer number. Locations found by approximate matching are marked Located approximately with a dotted outline, apart from exact matches.
- Automatic results are normalized. For invoices, receipts, purchase orders and the other built-in document types, the structured data (screen, API, webhooks, exports) now gives dates as
-
One consistent model: status, result, exceptions, evidence
- Ready never also says "Needs review". In Documents, the first chip is the result's status and nothing else. A person's progress appears beside it in its own words (In review, Reviewed, Approval pending), never as a second status.
- The blocker comes first. When a result needs review, Fix field and Show in document open the field panel on an Issues view that lists only the fields the issues name, with the editor of the one you picked already focused. Values that nobody has confirmed yet stay under Extracted and are reported as optional verification, never counted as issues.
- Reverse charge is one decision. When the document itself shows reverse charge and prints no VAT amount, the issue reads VAT status with Confirm reverse charge, Enter VAT amount instead and Show in document, instead of a "required field missing" message.
- Source highlighting shows where, not how sure. Boxes on the document mark mapped values, the selected field and fields with an open issue. The confidence legend and confidence colours are gone, including in the annotated PDF export; per-field percentages appear only with Show evidence details.
- Failed results offer Run again. A failed extraction shows Run again as its one action (the same extraction, on the stored document; the new result is linked to the old one), no success message, and no fallback wording. In Documents, a failed result that was run again says it was replaced by a newer run. Re-analysis no longer waits forever when the new result needs review.
- Processing and approval are separate. In a workspace with approvals, a Ready result says Ready - no processing issues and names the approval that is still required, with Start review leading to it.
- Template labels are the template's. A Saved Template field keeps its own name and label everywhere (for example, Amount Due stays Amount Due next to Total Amount).
- Queue counts stay current. The sidebar's review count updates as soon as a result becomes Ready or needs review, and Documents shows up to 200 documents per view, saying so when a queue holds more.
- Batches count review and failures apart. Review N exceptions counts only documents that need review; failed documents have their own count and Show N failed documents. The completion message no longer turns green when a document failed.
- Demos match real results. The public demos and in-app samples now carry the same status, issues and structured data a real result has.
- Processing details. "Technical details" is now Processing details: status, mode, template and version, document type, pages and time, and whether text recognition was used, without naming the engines behind them.
-
The structured result comes first
- Ready, review required or failed, first. Every result, including Automatic ones, now opens with its status: Ready (all required checks passed, no action needed), Review required with each issue listed, or Extraction failed. The structured data follows as a key/value table with Copy JSON and Download JSON. The document viewer and per-field checks sit behind Show source document and open on their own when you fix an issue.
- One issue, one action. Each issue names the field and the problem, with Fix field (opens the field's editor next to the document) and Show in document. When there is a single issue, its own Fix is the one action on screen.
- Sign-off is optional unless your workspace requires it. Ready means the automated checks passed. Verifying values and accepting the result is an optional record that a person checked it; in a workspace with approvals, the header says the review and approval are still required. Per-field confidence percentages are no longer shown on these results.
- A review queue in Documents. History is now Documents, with All · Needs review · Ready · Failed filters and counts. Each row shows the result's status and its first issue, so you can find every document that needs a person without opening them one by one. The sidebar shows how many documents need review. API:
GET /api/v1/history?processing_status=review_required&include_counts=1. - Several documents at once, without Advanced settings. Drop several files on the upload area to analyze each one; the button says how many. The results list shows Ready / Needs review / Failed counts, and Review N exceptions narrows it to the documents that need a person. Background processing for very large uploads stays under Advanced settings.
- Templates in the sidebar. Templates opens the saved-template library directly. Each template shows its version, field count, required fields and API ID, and Use template starts a new analysis with it. New analysis also remembers the last template you analyzed with.
- Scan to PDF moved. It is no longer listed next to the three extraction modes (it extracts no data); open it from Scan to PDF under the upload area.
- Clearer navigation. The sidebar separates Help (User Guide, Pricing) from Developer (API, Webhooks, MCP, Benchmarks).
-
Results describe the outcome, not the engine
- Deprecated: `llm.provider` and `llm.model`. These keys on analysis results (and
llm_provider/llm_modelon history list items) identify internal runtime configuration and are not needed to interpret a result. They remain in v1 responses under the API compatibility policy, but do not build logic on them: usellm.status,processing_statusandprocessing_reasons. No removal date is set yet. A removal will be announced here with at least the notice the policy requires. - Exports no longer name the AI model. The JSON export keeps
metadata.llm_modelandmetadata.llm_providerfor shape compatibility, but they are now alwaysnull. The XLSX Metadata sheet no longer has those two rows. - The web app no longer shows the model. Technical details, the raw JSON view, the validated-JSON download and the history list no longer show which AI model produced a result. The report builder no longer offers "LLM model" as a grouping or filter. Saved reports that already use it keep working.
- `GET /api/v1/runtime` is a plain authentication probe. It returns
{"status": "ok"}(plus the operationalscan_cleanupflag) and no longer names the active provider or model.
- Deprecated: `llm.provider` and `llm.model`. These keys on analysis results (and
-
Review decisions you can rely on
- Fix: a re-save can no longer change the template contract. Saving an edited result derives
processing_statusfrom the stored template contract (required fields, types,base_type) and validation context, not from the copy the browser sends back. Previously an edited copy that marked a required field optional could reportreadyin the save response and webhook while the stored result was stillreview_required. The save response, the stored result,GETand the webhook now always agree. - Fix: accepting a partial analysis clears the blocker. After a reviewer accepts a page-capped analysis,
partial_processing_unacceptedgoes away. The result becomesreadyif nothing else blocks it, anddocument.processing_status_changedfires with triggerpartial_analysis_accepted. Previously the reason came back on every read. - Fix: status changes are measured from the real previous state.
previous_processing_statusand the audit trail now use the decision derived from the record as stored before the action, so older records no longer report a change fromnull, and an outdated stored copy cannot invent or hide a change. - One status on template results. On Saved Template and Custom extraction results, the header badge, message and primary action follow
processing_status: Ready or Review required, with each reason listed. Per-field confirmation is shown as optional verification and no longer makes a Ready result look blocked. A template without a base type no longer asks you to confirm the document type. - Reasons lead to the field. Each review reason has a Fix action that opens the field's editor, and the primary button reads "Fix N issues". After a correction, the field shows its saved state ("Entered manually") and the header confirms when the document becomes ready, or when it needs review again.
- Smaller fixes. In Saved Template mode, pressing Analyze without a file now shows the message next to the button and moves focus to "Browse files", and once a file is chosen there is a single "Analyze with this template" button. On the Developer page, each webhook event and API-key scope checkbox sits next to its label, and each event says when it fires. Editors are announced as invalid only when the value is actually invalid. On phones, a result that needs review opens on the fields. Dark mode has better contrast for small status badges and links.
- Clearer Ready and Failed results. A Ready template result always keeps a visible next action (Export), opens its field list on the extracted values, and shows per-field confirmation as a quiet, optional action. A template run that could not be applied no longer announces "analyzed successfully": it shows Extraction failed straight away and does not offer to verify values that are not the template's result. Records saved from data the server did not analyze no longer show a model, provider or token usage. An analysis started before this update must be re-run before it can be saved.
- Webhook ordering note. Deliveries are not totally ordered. A late
document.completeddescribes the result at job completion and must not overwrite a newer status.GET /api/v1/history/{result_id}is the authoritative current state.
- Fix: a re-save can no longer change the template contract. Saving an edited result derives
-
Status-change webhook and complete template snapshots
- New webhook: `document.processing_status_changed`. When a reviewer's correction, reclassification or re-save changes a saved result's
processing_status(for examplereview_required→ready, or back after an invalid edit), subscribers receive the new status,previous_processing_status,processing_reasonsand the currentstructured_output, plus a reference to the original job. It fires only when the status changes, never for a change of reasons alone. It uses the same signing, retries, delivery log and replay as every other event, and is queued in the same transaction as the correction, so a subscriber outage never undoes a correction. - Opt-in. Existing webhooks do not receive the new event. Add
document.processing_status_changedto a webhook'sevent_types(API or Developer settings) to receive it. - Job history stays as it was. A job's
statusandprocessing_statusremain the values at completion; the current decision is on the saved result (GET /api/v1/history/{result_id}). - Template versions record their base type. Every newly saved template version now stores the template's
base_typewith its fields. Versions saved earlier are unchanged and are not backfilled. Running a past template version is still not supported.
- New webhook: `document.processing_status_changed`. When a reviewer's correction, reclassification or re-save changes a saved result's
-
Structured-output contract hardening
- Typed values in `structured_output.data`. Each Saved Template / Custom field now arrives in its declared type's canonical form: amounts as decimal strings (
"1.190,00"→"1190.00"), dates as ISO 8601, booleans and numbers as JSON values, identifiers exactly as printed.data_format: "typed-v1"marks it. Nothing is guessed: an ambiguous reading such as"1.190"or"03/04/2026"staysnullwith the newambiguous_valuereason, and a value that is not its type staysnullwithinvalid_value. The printed text is kept instructured_output.field_metadataand inextracted_fields. - Corrections update the decision. When a reviewer fixes a field,
processing_statusandprocessing_reasonsare re-derived on the server and saved with the edit, so filling a missing required value turnsreview_requiredintoready. The Structured data panel updates immediately, and the audit trail records the change. Every read also returns the decision for the record's current values. - Job status and result decision are separate. A template job that ran now always finishes as
completed;GET /api/v1/jobs/{id}also returnsprocessing_status. A result whose template could not be applied (processing_status: failed) no longer sendsdocument.review_required, because there is nothing for a reviewer to fix. Every job webhook carriesjob_status. Jobs without a template are unchanged. - Template discovery. The Saved Template picker shows the template ID with a Copy ID button next to the version. API keys with the
extractscope can list and read their personal templates (GET /api/v1/templates[/{id}]) as a contract view without ownership data or model hints. Workspace templates stay unavailable to API keys. - Clearer errors. API errors add
error.reason(for exampletemplate_not_found,template_version_mismatch,insufficient_scope) anderror.details(for example the requested and current version). Existingcodeanddetailvalues are unchanged. - Fix. On desktop, missing required fields in the review panel could collapse out of sight when the field list was long, so they could not be filled in. They are shown again.
- Typed values in `structured_output.data`. Each Saved Template / Custom field now arrives in its declared type's canonical form: amounts as decimal strings (
-
Saved Templates as output contracts
- Structured output on every result. Results, job results, history records,
document.*webhooks and the JSON export carrystructured_output. Itsdataholds exactly your Saved Template's keys, in order, withnullfor missing values.contractnames the template id, version and fingerprint that produced it. - Automated decision.
processing_statusisready,review_requiredorfailed, andprocessing_reasonsgives stable codes (required_field_missing,invalid_value,totals_inconsistent,extraction_failed, …). The decision does not use per-field confidence. - Templates on the async lane.
POST /api/v1/jobsacceptstemplate_id. The contract is frozen at submit, and every template job that ran finishes ascompletedwith itsprocessing_statusbeside it. - Version pinning. Send
template_versionwithtemplate_idto get409 TEMPLATE_VERSION_MISMATCHinstead of a silently different payload after someone edits the template. - Template picker shows the contract. The picker shows the version, the field count and the required count. "View output structure" lists every key and shows an example output. Template results open with a "Structured data" panel with Copy JSON and Download JSON; the document and review tools stay below.
- Fix. A template without a base document type is no longer validated as whatever type the model guessed. Previously such a template could demand invoice fields (buyer, line items) it never declared.
- Integration guide. New
docs/INTEGRATION_GUIDE.mdwalks through a Saved Template integration end to end: pinning a version, submitting a job, readingstructured_output.data, routing onprocessing_status, consuming the webhook, and upgrading from one template version to the next. It includes curl, Python and TypeScript examples and lists the current limitations./docsnow documentstemplate_id,template_versionandTEMPLATE_VERSION_MISMATCH, and the Postman collection has the new fields. - Docs corrections. The streaming lane ends with a
completeevent, notresult. A template job whose extraction failed sendsdocument.completed(withprocessing_status: failed), notdocument.failed. To retry it, submit with a newIdempotency-Key. API keys can use personal templates only. The 401 challenge realm isDocSolved.
- Structured output on every result. Results, job results, history records,
-
Webhook scope and pre-deploy hardening
- `webhooks` API-key scope. Managing webhook endpoints (
/api/v1/webhooks*,/api/v1/webhook-outbox*) now requires a key with thewebhooksscope; every key that existed before this change was granted it automatically, so nothing running breaks. Choose scopes when creating a key in Developer settings. - Same-day fix. The automatic
webhooksgrant did not apply on the production database at the first deploy (keys created earlier briefly received 403 on webhook management). Corrected in the follow-up deploy; every key created before that deploy now carries the scope. - Analyze page stops waiting for a stalled server. If no progress arrives for four minutes the analysis is cancelled with a clear message instead of spinning forever. Nothing is retried automatically.
- Reduced-accuracy notice. When the text-recognition service is unavailable the result says so, instead of only hiding text highlighting.
- Changelog in production. The
/changelogpage reads its entries inside the container build (they were left out of the image).
- `webhooks` API-key scope. Managing webhook endpoints (
-
Launch-readiness pass
- Security page.
/securityis now a page, not a redirect: encryption, authentication, isolation, retention, deletion, subprocessors and open items, each marked verified, provider-stated or open./.well-known/security.txtpublished. - API errors carry the request id. Every error envelope on
/api/v1/*now includesrequest_id(also theX-Request-IDheader); unhandled server errors return the same envelope withINTERNAL_ERROR. Every 429 carriesRetry-After. - Capabilities advertise rate limits.
GET /api/v1/capabilitiesgainedrate_limits, so clients stop hardcoding them. - Docs.
/docsopens with a three-language quickstart for the async job lane; the scope needed to read a job result is documented correctly (extractis enough). Compatibility policy published (docs/API_COMPATIBILITY_POLICY.md). - Demo pages. Unknown demo slugs render an HTML 404 with links to the real demos; a failed sample load is reported in the demo header; demo result JSON is cacheable.
- MCP. The
/mcppage shows install commands again (@synairodocai/docai-mcp@next, beta.6 on npm). - Changelog. This page.
- Security page.
-
MCP beta.5 and beta.6
docai_get_usagetool: remaining page budget for the configured key, free to call.GET /api/v1/capabilitiesis unauthenticated;GET /api/v1/usagereports both the page allowance and the key's monthly window.extract-only keys can read their own job results.- Error envelopes pass through
error.reason(for exampleapi_key_monthlyvspage_allowance).
-
Scan to PDF
- New Scan to PDF mode in the analyze screen and
POST /api/v1/scan: repair phone photos (edge detection, perspective correction, enhancement) and merge them into a PDF. No OCR, no AI, no pages charged. - Camera-photo cleanup runs at every upload boundary so OCR, AI vision and the on-page overlays all see the same image.
- Landing and pricing layout fixes on mobile.
- New Scan to PDF mode in the analyze screen and
-
MCP for coding agents
- Public
/mcppage and the@synairodocai/docai-mcpstdio server: capabilities, integration guide, extract a workspace file, fetch a job result. Installer anddoctorfor Codex CLI, Claude Code and Gemini CLI. - Agent-facing API surface:
GET /api/v1/capabilities,Idempotency-KeyonPOST /api/v1/jobsbound to the request payload (409 on conflict), stableerror.codeenvelope.
- Public
-
Feedback and measurement
- Result feedback widget on every analysis; retention configurable by the operator.
- Consent-gated, first-party product analytics bus with optional analytics provider adapters (off by default). Privacy, legal and consent copy discloses providers only when they are configured.
- First-value milestone recorded server-side when your own document completes.
-
Public site
- Landing page split from the app (
/analyze), three live demos (/demo/vat-invoice,/demo/receipt-photo,/demo/ksef-xml),/ksefpage for Polish e-invoices,/benchmarkswith dated OCR and split-detection numbers. - Self-hosted fonts and a strict, nonce-based Content-Security-Policy.
- Landing page split from the app (