Define line items
well_define_line_itemsRead what this workspace has already billed, and flag which of the lines the user just described equal a past line. Use it before well_create_invoice_from_data, when the invoice's lines come from the user's words ("two days of consulting, and the hosting").
Pass lines: one entry per line the user described, each with a line_key (a fresh UUID you choose for that line and keep for the whole conversation, never its position in the list), its name, its sku when the user gave one, and its quantity, unit_price and tax_rate when the user stated them ("3 days at 600" is quantity 3, unit_price 600; tax_rate is a percentage, 20 for 20%). Leave a figure out when the user did not state it. Never invent one. unit_price is in currency, the invoice's: a price the user stated in another currency ("50€ a day" on an AED invoice) is converted first with well_get_fx_quote (base the price's currency, quote the invoice currency, amount the unit price), and its converted_amount is passed as unit_price. Never leave such a price out unless the rate tool returns no_rate, never pass it unconverted, and never convert it yourself. Pass customer_id (the entity_id of the pre-selected or chosen customer) when you know the customer, so the lines already billed to them rank first. Pass currency (the invoice's ISO 4217 code, e.g. "EUR") when you know it, so only past lines billed in that currency come back and match: a price billed in another currency does not hold.
Returns items: the workspace's distinct past sales lines (one product billed in two currencies is two items), newest first (customer's own lines ahead of the rest), each with item_id, name, sku, unit_price, currency, tax_rate, times_billed (counted inside the recent window, not a lifetime total), last_billed and billed_to_customer. Returns matches: one entry per sent line, matched_on "sku" or "name" with the item_id of the past line it equals, or both null when no past line equals it, plus requested: the quantity, unit_price and tax_rate you sent for that line, echoed unchanged (null for a figure you did not send). Returns totals: items_total, tax_total and grand_total of the lines in requested, computed by Well in currency (each line's total and tax held to the currency's minor units, a line with no quantity counted once, a line with no unit_price and an exact match at the matched past item's unit_price, a line with no tax_rate at the vat_default rate), or null when you passed no currency, a line still has no unit price, or a line has no known tax rate (none stated and a null vat_default.rate). These are the figures to show the user. NEVER compute a total or a tax yourself, and never send one to a create tool: Well computes them from the lines. Well does not match on the other figures.
Returns vat_default when you passed customer_id: the VAT rate a line opens with, worked out by Well from the issuer's country and the customer's country (rate in percent, or null when a country is unknown; basis: "domestic" the issuer's own country's standard rate, "intra_eu_reverse_charge" or "intra_eu_no_vat_id" a customer in another EU country, 0, "export" a customer outside the EU, 0, "unknown" no answer). The card shows that rate on every line that has none stated, ready to edit. NEVER ask the user for a VAT rate and never type one yourself: pass tax_rate only when the user stated one in their own words. A stated rate wins over vat_default.
When the lines belong to a draft already saved (the person changes its lines, quantities or currency), pass its invoice_id and, on each line that is already on the draft, its line_id from the lines of the last invoice answer. Then a figure you did not send is the draft's saved one: requested carries the saved quantity, unit price and tax rate, and when currency differs from the draft's currency the saved prices come converted by Well at the rate of the issue date, with fx_conversion (from_currency, to_currency, rate, rate_date, source) naming the rate. In Well's chat a call without invoice_id reads the newest draft this conversation created for the same customer the same way. draft_invoice_id names the draft the figures came from, and each match of a saved line carries its line_id. NEVER ask the person for a price the draft already holds, in any currency, and never convert a price yourself. In Well's chat, write the answered lines to the draft with well_update_invoice and its line_items, never a delete and a new create.
A match is exact equality only: the same sku, or the same name once case and spacing are ignored. A null is not proof the line is new. Read items and judge whether a near name is the same thing. Only invoices this workspace issued or was paid for are read, never drafts, canceled invoices or invoices it received. A past price is a suggestion, so confirm it with the user before it goes on an invoice.
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 |
|---|---|---|---|
| limit | No | Max past items returned (default 50). | |
| lines | No | The lines to check against the history. | |
| currency | No | The invoice's ISO 4217 currency. Only past lines in it come back and match. | |
| invoice_id | No | The saved draft these lines belong to. Its saved figures fill what you did not send. | |
| customer_id | No | The customer's entity_id. Their past lines rank first. | |
| 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. | |
| 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 |
|---|---|---|---|
| error | No | ||
| items | Yes | ||
| totals | No | ||
| matches | Yes | ||
| success | Yes | ||
| vat_default | No | ||
| error_reason | No | ||
| fx_conversion | No | ||
| 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. | |
| draft_invoice_id | No | ||
| resolved_workspace | No | The workspace that answered, when the caller named none and the token authorizes several. | |
| conversation_id_note | No | Present only when the server opened a fresh lane, stating that no choice recorded earlier was read. | |
| 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. |