Get value added tax by period
well_get_vat_summaryRead the VAT position of a workspace over a window of whole months, grouped by the date of its entries and invoices, straight from its book (VAT on posted invoices, which is the debit basis): per month, for the whole window as a CA3 by rate, and as totals with the net VAT payable. A French workspace gets that CA3; any other workspace, or a window with nothing posted, is answered from its draft entries and invoices (see below). It also lists the invoices whose lines or supplier leave the figure unreliable. It reads the book and computes nothing a reader has to trust blind: every amount is a decimal string in major units of currency, such as "5000.00" for five thousand euros, ready to state as returned. State each amount with its currency exactly as given. Never convert, scale or recompute one.
Use it for "what is my VAT this quarter", "how much VAT can I deduct", "is my VAT return ready" and "which invoices are hurting my VAT". Do not use it to sum invoices (well_sum_invoices) or to browse journal entries (well_query_records).
The window is whole months. from is the first day of the first month and to is the first day of the month AFTER the last one, both as YYYY-MM-01, so the second quarter of 2026 is 2026-04-01 to 2026-07-01. On basis: "posted", name both or neither: with neither, the call reads the current calendar quarter only: the quarter in progress, not the last four quarters and not the last complete one. On basis: "possibilities", name both always: a call with neither is refused invalid_period with the current quarter's bounds in error, so the caller can ask again for them. To read any other period, work out from and to from today's date and pass both. A window shorter than one month, longer than 12 months, or with a bound inside a month returns status: "invalid_period" with the reason in error. It is refused, never widened.
months holds one row per calendar month, oldest first: collected (output VAT), deductible (input VAT, a positive magnitude), net (collected minus deductible, positive is payable), and reverse_charge (the self-assessed VAT on reverse-charge purchases, kept out of collected and deductible). month_ended: false marks a month still running, whose figures can still move. unattributed_collected and unattributed_deductible are VAT on lines that name no tax rate. unmapped_rate_tax is the signed net VAT (collected positive) on a rate the return has no slot for, such as 8.50 or 13.00. These three are in none of collected, deductible and net, so state them beside any total that is not zero. The monthly collected, deductible and net add up to the window totals.
ca3 is the return by rate over the WHOLE window, built once from every entry in it, not summed from the monthly rows. complete: false means the ledger holds a figure the return cannot place: read blocking_reasons (unattributed_collected_vat, unattributed_deductible_vat, unmapped_rate_percent, directionless_taxable_base) and say so before quoting any total as final. Box numbers are deliberately absent: Well does not guess a printed CA3 box.
totals.net_due is the net VAT payable: collected minus deductible over the window, on the rates the return has a slot for (it leaves out unattributed_* and unmapped_rate_tax), with position as payable, credit or nil. A credit means the state owes the workspace, so never present it as a payment.
The figure is on the debit basis. It counts VAT when the invoice is posted. Entries are placed by their entry date, in the month of the date, never by their fiscal period, so an entry posted into a later return still shows in its own month and a filed return can differ from this figure; basis_note says so. On the receipts basis (TVA sur les encaissements), the default for services, VAT follows payments, so the amount payable can differ from this figure. The figure is the same whatever VAT regime is saved. State the basis beside the net figure, and say "the posted ledger shows X net VAT payable", never "you owe X".
A posted answer carries basis: "posted" and currency_basis, which names how the answer currency was resolved. excluded.unposted_invoice_count counts in-window VAT-bearing invoice documents whose VAT is not represented by a posted VAT-role line; state the count beside the posted figure and never add those documents to it. excluded.other_currency_line_count and excluded.null_currency_line_count count posted ledger lines left out because their accounting currency differs from currency or is missing. They are never converted. excluded.other_company_entry_count counts posted VAT entries stamped to another books company, which are left out of the figure, and excluded.unstamped_entry_count counts posted VAT entries with no company stamp, whose amounts stay in the figure.
A window with nothing posted is not refused. When the window holds no posted ledger entry that carries VAT, the call answers from the possibilities read of the same window instead: status: "ok", basis: "possibilities", with a basis_note saying that nothing is posted in the window yet, that the figures come from draft entries and invoices, and that the filed figure comes from closing the books. State that note beside the figures. It is NOT a nil return: never say no VAT is due. When that read finds nothing either, the answer is no_vat_found.
Pass basis: "possibilities" when the question is what VAT the current documents and in-progress book could become. The read includes the VAT-role entries in every state, plus invoice-header tax only when no live VAT-role entry exists for that invoice. The entries' state is a bookkeeping detail: entries.validated_count and entries.draft_count split entry_count by the books' state: read them, never state them, and never word an entry or an amount as validated, draft, « validé » or « brouillon » (a money answer has no validation step). Never mention validation or draft status anywhere in a money answer, including a declaration being validated or a connector's state; in French, never use « validé », « validée », « validées » or « brouillon ». If the count is useful, write only N VAT entries from entry_count. It groups the evidence by calendar quarter (quarters follow the entry date of each entry and the issue date of each document, never the fiscal period, and a filed return can differ), keeps domestic purchases, purchases to check, sales and unsided documents separate, counts the documents between two other companies apart (not_ours), and reads a document in another currency in the read currency only when its stored accounting tax is in that currency; an unconverted other-currency document, or any document with no currency, is excluded and counted in excluded. A purchase is domestic when its registry country is France, or, only for a French workspace with no registry country, its stored SIREN, SIRET or French VAT number passes full validation; otherwise it stays to check. When excluded.identity_grouping_truncated is true, the identifier check read only part of the suppliers, so some French purchases may still sit in purchases to check: every amount stays whole, only that split is less precise, so say purchases to check may hold French suppliers. Utility bills (document type 901) count as purchase documents; expense receipts (902) and pro formas (325) remain out. Documents with no issue date are counted in excluded.undated_count but never placed in a quarter or amount; that count covers the whole workspace, not the window, so it is the same on every window. Replacement documents are counted but excluded from the money lines, and make the quarter incomplete. A quarter's presentation is computed (both sides evidenced, each by an entry or a document, with at least one ledger entry in the quarter and nothing unread: net and position are set), evidence_only (one side only, or documents alone), incomplete (unsided, other-currency, null-currency or replacement evidence, or entry VAT with no attributed or mapped rate, sits beside the figures) or no_evidence (the quarter is in the window but holds no VAT-role entry and no invoice VAT: it is returned with every amount, net and position null and a note; state it as no evidence found for that quarter, never as zero VAT and never as a nil position); net and position are null unless computed; a quarter that holds sales evidence and is not computed carries net_estimate (collected minus deductible from those entries and documents, with deductible_missing: true and a null net when no purchase evidence exists): state it only as an estimate from invoices, not the filed figure, never as the position and never as a payment due; entries.unplaced is the entry VAT that neither side carries: reverse charge is only reported, while unattributed and unmapped-rate VAT make the quarter incomplete; purchases to check are reported beside a computed position and never added to it, and a side without evidence (purchase_evidence or sales_evidence false) is absent, never zero. Ledger entries booked in another or an unstated accounting currency are counted in excluded and not summed. A window over twelve months answers range_too_large with the window you asked for; nothing is narrowed. Documents between two other companies (both parties known, neither one a company of this workspace) are counted in counts.not_ours, ordinary and replacing ones alike, and the VAT of those whose tax is stated in currency is in documents.not_ours of the quarter, which sums only the documents with a readable VAT, so a quarter's count can be larger than the documents behind its amount. possibilities.not_ours_note is the ready sentence for them: their count, quarter by quarter, how many of each have a readable VAT, and that VAT. Relay it as its own sentence beside the figures, in the language of the answer and with its numbers unchanged; compose none of your own, never add that VAT to a figure or put it inside the deductible sentence, and never call a quarter incomplete for them. A null documents.not_ours means none of the quarter's such documents has a VAT stated in currency (an unconverted other-currency document, a document with no currency, a replacement): the note then says none is readable, and no amount is ever 0.00. A document with no party at all is not one of them: it stays unsided. Documents whose side rests on an inference, not on proof (a company of this workspace on one leg, or a provider claim with no holder), are counted in counts.estimated_side, replacing ones included, and their VAT is in documents.estimated of the quarter, by kind (purchase_domestic, purchase_to_check, sales); it is never in deductible, collected, net or position. possibilities.estimated_side_note is the ready sentence for them: relay it once, as its own sentence beside the figures, in the language of the answer and with its numbers unchanged, never as proven, and compose none of your own. An inferred side alone never makes a quarter incomplete: a quarter that holds only such documents is evidence_only, while a replacement, unsided, other-currency or no-currency document still makes it incomplete; state the returned presentation unchanged. A null amount in documents.estimated means none is stated, never 0.00. Possibilities carry no ca3 or totals, and no top-level months. Each quarter that holds evidence carries its own months (the calendar months that hold evidence, oldest first, each with collected, deductible, their sales_evidence and purchase_evidence flags, purchase_to_check, unsided and the entry and document counts; no month net) and rates (the quarter's collected and deductible by line rate, highest rate first). A month's amounts add up to the quarter's, and state a month side only when its evidence flag is true, never as 0.00. A document is split by rate only when its line tax adds up to its header tax to the cent; the rest of the quarter amount sits in rate_unread (signed, per side), which with the rates equals the quarter's collected and deductible: state it as VAT whose rate was not read, only when it is not 0.00. A rates side that is null has no VAT at that rate. excluded.rate_grouping_truncated true means the rate read was cut: more of the quarter sits in rate_unread. With no accounting country, purchases remain to check and no jurisdiction is inferred, unless estimated_country_code is set (see below). With no configured or country currency, the mode of eligible non-null document currencies is used, ties break alphabetically, and no eligible currency returns no_vat_found; existing ledger amounts are never relabelled. currency_basis says what currency rests on: settings (the workspace's books currency), country (the default currency of its accounting country), display_fallback on a posted read (the display currency when neither is set) or documents_mode on a possibilities read (the most common currency of its invoices, because neither is set); it is null, beside no currency, when no denomination exists. Name it only when it is not settings. status: "no_vat_found" means neither VAT-role entries nor document evidence were found in any quarter of the window (the quarters it looked at come back as no_evidence rows), or no denomination can be selected; it is not a nil return.
The VAT balance. Every possibilities quarter row that holds an invoice or a VAT entry on either side carries balance: the VAT to set aside (direction: "set_aside") or to recover ("recover"), as amount, from collected minus deductible. It answers "how much VAT do I set aside or recover this month": read the one month as the window (from its first day, to the first day of the next) and its row is that month. Unlike net and net_estimate, it counts the purchases to check and the invoices whose side is inferred, and it is set whatever the presentation, with or without an own company, a VAT regime or a posted entry. sales_invoice_count and purchase_invoice_count are the invoices it counts; unsided_invoice_count invoices are in neither side. It is an estimate from invoices, never the filed figure and never a payment due.
anomalies lists invoices in the window, purchases and sales, that carry a billed line with no VAT rate (line_without_vat_rate). A purchase that names no supplier company also lists as supplier_unattributed; a sale never does. direction says which side an invoice is on, from the workspace's own company: a purchase names a supplier, sales names a customer, and label uses that party. unanchored means the invoice does not name the own company on exactly one side, so it has no direction and no party. total counts every such invoice, items holds the first anomaly_limit (default 20, at most 50), and truncated: true means more exist than items shows. Name an invoice by its label, never by invoice_id. An invoice with no rate is not necessarily missing VAT: the fix is to set the rate or supplier on the invoice, not to adjust the return.
A workspace outside France, or with no accounting country, is not refused either. It is answered from the possibilities read, with filing: null (no CA3, no CA3 slots) and a basis_note that names the gap: VAT filing for its country is not mapped in Well, or the workspace has no accounting country, and the figures are the VAT the books and invoices carry. State that note beside the figures. With no configured country, estimated_country_code is the majority registry country of the workspace's own documents, an estimate stated as one: the domestic split and the French-identifier check run on it, and basis_note / estimated_country says so. country_code stays null: nothing configured is asserted. estimated_country_truncated is true when more of its documents would vote than the estimate reads, so only the newest voted, and basis_note then says the country leads among the newest documents read, never a majority of all of them. The estimate reads the twelve months up to today, whatever window the call names. When no country emerges, the read infers no jurisdiction and places purchases in to check.
filing is the periodic VAT return (CA3) of the workspace's own company, by the rule the tax calendar dates the CA3 with. It is null when the legal form is not set or not covered, when the country is not covered, when the saved profile owes no CA3 (the VAT franchise, the simplified regime or an annual filing frequency, for any legal form: the calendar's not_owed then holds fr-vat-ca3), and for a micro-entrepreneur whose VAT regime is not saved. When the saved VAT regime is the franchise (vat_regime: "franchise"), filing_note (code vat_franchise) says beside the null filing that the company files no VAT return. cadence is the saved filing frequency (monthly or quarterly), the same one filing_frequency resolves, or null when the profile does not hold a periodic frequency: the CA3 is then monthly or quarterly, and Well does not know which. Well stores no deadline: due_rule is the published window, with the source to name beside any date, and due_window is the window that rule gives for THIS read's period, the days of the month after it. It is null unless the read covers exactly one calendar month or one calendar quarter. The administration sets the exact day per company inside the window. State a date only when cadence is set and the person has confirmed it, and name the source with it.
filing_frequency and period_note ride on every possibilities answer. filing_frequency is the company's stored VAT filing frequency as its tax profile resolves it (monthly, quarterly or annual; null when unset or when the company is in the VAT franchise and files no return); period_note is mandatory and is copied once as the first sentence of the VAT block, before any quarter figure, including a detail follow-up. It says the unit of the grouping. The read groups by calendar quarter whatever the frequency.
vat_number_present and vat_regime ride, on both bases, on every ok and no_vat_found block and on every range_too_large block of a window that holds too many entries, each beside its country_code; a failed block and a window refused before any read carry neither. vat_number_present is true when the own company, or the workspace's accounting settings, stores an EU VAT number, false when neither does (a stored SIREN alone is not one), and null when the workspace has no own company and its settings store none. The number itself is never returned. vat_regime is the VAT regime the workspace saved (franchise, simplified or normal), or null when none is saved.
provider_booked is set on a possibilities answer: the VAT the connected Pennylane accounting provider booked, summed from its retained ledger lines on named FR VAT accounts, or null when there is nothing to state (no Pennylane line on those accounts, a workspace that is not French, one whose books currency is not set explicitly, or one whose country is only estimated). State by_quarter as a check beside the figures: never add it to the position and never present it as the filed figure. Show 44564 as VAT deductible on payment and 44574 as VAT collected on receipt in the separate pending bucket, pending until paid, never implied as due and never netted into a quarter. When unavailable is true, the booked VAT could not be read this time: state note once and say it is unknown, not absent and not zero, and state no booked amount. When it is null, say nothing about it.
scope. Omit it, or pass "this_workspace", to read the workspace the call runs in. Pass "my_companies" on WhatsApp to read every company workspace of the person's company family in one call, without moving the chat: the family is the membership the chat runs in, or the company's parent membership, and its company workspaces. A workspace counts only when the signed-in person holds a live membership in it, checked again before each read, and Well finds them from the signed-in person: a workspace is never named in the call. The result then carries workspaces, one block per company workspace (at most 10, workspaces_truncated: true when more exist), each with its workspace_name, company_name and the same fields as a single read, its own status first. Answer each block on its own: never add, net or compare two blocks into one figure. A block for a workspace outside France or without a country answers like any other and carries its own basis_note; state it with that block. workspaces_unreadable counts the company workspaces a failed lookup left out unnamed: their position is unknown, not nil. An empty workspaces with workspaces_unreadable at 0 means the person has no company workspace they can read; with it above 0 it means the read failed. On any other host the read refuses the scope with status: "failed": read one company per call there.
status: "range_too_large" means the window holds more posted entries than one call reads (5000). Ask again with a shorter window. It is never answered with a partial sum. status: "failed" means the read failed and the position is UNKNOWN, not nil.
Unread invoice-header VAT. On the possibilities basis, excluded.header_tax_unread_count counts live eligible invoices with no header tax where both item and grand totals are present and differ. It is a count of VAT the header cannot read, not an amount. excluded.tax_unknown_count (present when above 0) counts every live eligible invoice in the window with no header tax, whatever its totals say (tax_unknown_split gives the equal, missing and differing totals; the differing ones are header_tax_unread_count). When it is present, the answer says once how many invoices in the window have VAT that could not be read, as a count for the window as a whole: never inside a quarter, never as nil, zero or no VAT, never as an amount, and never added to another count.
Currency exclusions on a posted answer. When either currency-line count is above zero, state currency_exclusion_note once and give both counts. The figure is partial and ca3.complete is false. If no posted VAT line remains in the selected currency, keep basis: "posted", state that no position is available in that currency and give no amount. Do not answer from possibilities or say that nothing is posted.
When the token authorizes one workspace, call this directly — no workspace call is needed first. When it authorizes several, this read will not guess which one you mean: pass workspace_id on the call.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| to | No | EXCLUSIVE end of the window: the first day of the month after the last one you want, YYYY-MM-01. Give it with `from`. | |
| from | No | Inclusive start of the window: the first day of a month, YYYY-MM-01. Give it with `to`, or omit both only to read the current quarter in progress on `basis: "posted"` (a `basis: "possibilities"` call always names both); for any other period name both. | |
| basis | No | Evidence basis. Omit or use `posted` for the existing posted-ledger VAT return; use `possibilities` for draft, posted and document-header evidence grouped by quarter, each quarter split by month and by rate. | posted |
| scope | No | Which workspaces the read covers. Omit it for the workspace the call runs in. "my_companies" reads every company workspace of the person's family, one block each, and runs on WhatsApp only. | |
| workspace_id | No | Target workspace. Omit when the token authorizes one workspace. Required when it authorizes several: this read reports one workspace's own figures and will not choose which. | |
| anomaly_limit | No | How many anomalous invoices to list, at most 50. Defaults to 20; `anomalies.total` counts all of them. | |
| conversation_id | No | The conversation id returned by the previous Well result, in its meta under well/conversation_id, in its structuredContent, or in its JSON text block. Pass it back on every call in the same conversation, including a call a card makes, so the chosen workspace and the earlier answers still apply. It decides the conversation on its own: nothing the host states about the session replaces it. Omit it only on the first call of a conversation. | |
| workspace_scope | No | Restrict this call to the family: the token's primary workspace plus the company workspaces under it that you are a member of. Unrelated authorized workspaces drop out of the read; row reads merge across the family, while a per-workspace figure still reports exactly one workspace. |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
| ca3 | No | ||
| basis | No | The evidence basis used by the read. `posted` means posted ledger entries only; `possibilities` reads draft, posted and document-header evidence. | |
| error | No | ||
| scope | No | Set on a `my_companies` read, whose figures are in `workspaces` and never at the top level. | |
| filing | No | The periodic VAT return (CA3) of the own company, or null when the company files none: no legal form or one Well does not cover, a saved profile on the franchise, the simplified regime or an annual frequency, or a micro-entrepreneur whose VAT regime is not saved. Well stores no deadline. | |
| months | No | ||
| status | Yes | Where the call ended. `ok` carries a figure or a currency-exclusion note; `no_vat_found` is not a nil return. | |
| totals | No | ||
| window | No | ||
| success | Yes | True only when `status` is `ok`. | |
| currency | No | ISO-4217 code every amount below is denominated in. | |
| excluded | No | Counts of evidence excluded from a posted VAT answer. These counts are never added to its figures. | |
| anomalies | No | ||
| basis_note | No | A sentence to state beside the figures. On a posted `ok` read: entries are grouped by the month of their entry date, so an entry posted into a later return still shows in its own month and a filed return can differ. On a possibilities read that stands in for a posted one: nothing is posted yet, or the workspace's country is not mapped for VAT filing, or it has no country, or its country is the majority country of its documents stated as an estimate. | |
| vat_regime | No | On every ok and no_vat_found block, and on a range_too_large block of a window that holds too many entries; never on a failed block: the VAT regime the workspace saved, `franchise`, `simplified` or `normal`; null when none is saved. Under `franchise`, `filing` is null and `filing_note` says why. | |
| workspaces | No | One block per company workspace of the person's family, family root first. Each carries its own status and figures. Never add two blocks together. | |
| filing_note | No | A sentence to state beside a `filing` that is null on purpose: the workspace saved the VAT franchise, so the company files no VAT return. Absent otherwise. | |
| period_note | No | On every possibilities-carrying block: one mandatory sentence saying which unit the company files its VAT return in and that the figures are grouped by calendar quarter. Copy it once as the first sentence before any quarter figure, including a detail follow-up. It promises no due date. Absent on a posted read. | |
| country_code | No | The workspace's accounting country. Set on `ok`; null when none is configured. | |
| possibilities | No | ||
| currency_basis | No | What `currency` rests on: on a posted read, `settings`, `country` or `display_fallback`; on a possibilities read, `settings`, `country` or `documents_mode`. Null when no denomination exists, beside no `currency`. | |
| basis_note_code | No | Stable code of `basis_note`: `nothing_posted`, `country_not_mapped`, `no_country`, `estimated_country` or `entry_date_basis`. | |
| conversation_id | No | The conversation this result belongs to. Pass it back as the conversation_id argument on every later Well call in the same conversation. | |
| newly_connected | No | Tools that connected to this workspace since the last result and that no session was told about yet, oldest first. Present only when at least one tool is new. The connected-line rule says when to tell an entry; when it does, one line per entry, in the person's language: "<name> is connected.". Never fold several entries into one sentence. Each entry comes back once, on one result only: never repeat its line later. | |
| provider_booked | No | On a possibilities answer: the VAT the connected Pennylane accounting provider booked on named FR VAT accounts, summed from its retained ledger lines, or null when there is nothing to state. When `unavailable` is true, the read could not finish: state `note` and no amount, because the booked VAT is unknown, not absent and not zero. A check beside the figures, never added to them and never the filed figure. Absent on a posted read. | |
| filing_frequency | No | On every possibilities-carrying block: the company's VAT filing frequency as its tax profile resolves it, `monthly`, `quarterly` or `annual`; null when the profile states none or the company is in the VAT franchise and files no return. The read groups by calendar quarter whatever it is. Absent on a posted read. | |
| filing_note_code | No | Stable code of `filing_note`: `vat_franchise`. | |
| resolved_workspace | No | The workspace that answered, when the caller named none and the token authorizes several. | |
| vat_number_present | No | On every ok and no_vat_found block, and on a range_too_large block of a window that holds too many entries; never on a failed block: true when the own company or the workspace's accounting settings stores an EU VAT number, false when neither does (a SIREN alone is not one), null when the workspace has no own company and its settings store none. The number itself is never returned. | |
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| workspaces_truncated | No | True when the family holds more than 10 company workspaces and the rest are not read. | |
| workspaces_unreadable | No | How many company workspaces of the family could not be checked or read because a lookup failed. They are not named and their position is unknown, not nil. Above zero, never say the person has no company workspace. | |
| company_exclusion_note | No | Mandatory when `excluded.other_company_entry_count` is above zero. State this sentence once and state the count. It says the posted figure is partial, or that no posted position for this company remains in the window. | |
| conversation_id_source | No | Where the conversation id came from: the host's own request meta, the caller's argument, or a fresh lane the server opened. | |
| estimated_country_code | No | The registry country a strict majority of the workspace's own documents of the last 12 months carries, set only when no accounting country is configured and one country holds that majority. An estimate stated as one — `country_code` stays null beside it — on every possibilities-carrying block; null when a configured country exists or no majority emerges. | |
| currency_exclusion_note | No | Mandatory when either posted currency-line count is above zero. State this sentence once and state both excluded counts. It says the posted figure is partial, or that no posted position remains in the selected currency. | |
| estimated_country_truncated | No | True when more of the workspace's own documents of the last 12 months were eligible than the estimated country reads, so only the newest ones voted; false otherwise. Set beside `estimated_country_code` on every possibilities-carrying block. |