Skip to main content
Glama

Save document

save_document

Create or update a WHOLE document and its header (contact, dates, type, parent); to change lines on an existing document without resending it use update_document_item, and to add one line use add_document_line. Works for documents of ANY kind — all eight document types are supported here, not just invoices: invoice, quote, recurring, debit_note, credit_note, purchase_order, bill, grn (the type enum below documents what each one is for). Credit notes and debit notes are raised through this same tool — pass the matching type and, where it relates to an existing document, its id as parent. For one document, send its fields inline (pass an id to update, omit + include type to create). To create/update many at once, send an items array — preferred over repeated calls: the whole batch is one all-or-nothing transaction with a single ledger recompute. Each item with an id updates; each without creates and must include type. This manages the document as a whole; to edit individual line items on an existing document use update_document_item (or update_document_items_bulk).

Input Schema

NameRequiredDescriptionDefault
idNoDocument id. Present → update that document; omit → create a new one (must include type).
dateNoDocument date (ISO 8601).
nameNoDisplay name / title of the document.
sentNoWhether the document has been sent to the recipient.
typeNoThe kind of document. One of: invoice — Bill a customer for goods or services. Money in.; quote — A pre-sale estimate for a customer; becomes money in once accepted.; recurring — An invoice that repeats on a schedule. Money in.; debit_note — Reduce what you owe a supplier (offsets a bill). Money in.; credit_note — Refund or reduce a customer's invoice. Money out.; purchase_order — Order goods or services from a supplier. Money out.; bill — A supplier's bill that you owe. Money out.; grn — Record stock received against a purchase order. Money out..
itemsNoVector of document objects to create/update in one all-or-nothing batch. Preferred over repeated calls. Each item with an id updates; each without creates and must include type.
notesNoFree-text notes.
clientNoClient id, or an exact client name to resolve (see list_clients).
lockedNoWhether the document is locked against further edits.
numberNoDocument number; auto-generated if omitted.
parentNoId of the parent document this one derives from (e.g. the invoice a credit note relates to).
contactNoContact id, or an exact client/supplier name to resolve (client for money-in document types, supplier for money-out; see list_clients / list_suppliers).
duedateNoPayment due date (ISO 8601).
messageNoMessage shown to the recipient on the document.
settledNoSet true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; bad debt is written off with write_off_document, which also reverses the VAT.
showvatNoWhether to display the VAT/sales-tax line on the document.
acceptedNoWhether the recipient has accepted the document (e.g. a quote).
currencyNoISO 4217 currency code (e.g. "ZAR", "USD"). Defaults to the business currency.
shippingNoShipping amount added to the document total.
showbankNoWhether to display the business's banking details on the document. Defaults to true on create; only shown to recipients on money-in documents (invoices, quotes).
supplierNoSupplier id, or an exact supplier name to resolve (see list_suppliers).
accountidNoBank/ledger account id the payment moved through (see list_accounts).
descriptionNoFree-text description of the document.
settleddateNoDate the settle entry posts, when settling an existing document (ISO 8601, YYYY-MM-DD). Omit for the default date.
showdepositNoWhether to display the deposit line on the document.
accepteddateNoDate the document was accepted (ISO 8601).
paymentnotesNoFree-text payment instructions shown on the document.
showdiscountNoWhether to display the discount line on the document.
showshippingNoWhether to display the shipping line on the document.
baseaccountidNoBase/control account id override; rarely needed — defaults from the category.
depositamountNoExplicit deposit amount; used instead of the percentage when deposituseamount is true.
invoicebankidNoPROD-2443. :bankaccount/id of one of the business's own bank accounts to show on this document instead of the default invoice bank. "$delete" clears it back to the default; null or omitted leaves it unchanged. An id the business does not own is refused.
accountpaymentNoAmount paid against the document at save time.
depositpercentNoDeposit as a percentage of the total.
discountamountNoExplicit discount amount; used instead of the percentage when discountuseamount is true.
discountpercentNoDiscount as a percentage of the subtotal.
showpaymentlinkNoWhether to include an online payment link on the document.
deposituseamountNoWhen true, use depositamount instead of the percentage.
settledaccountidNoWhere the settle gap posts, when settling an existing document: a Chart of Accounts account name or id (see list_accounts). Omit to post to Settlements, or to Foreign Exchange for a foreign-currency document.
discountuseamountNoWhen true, use discountamount instead of the percentage.

Schema Changelog

Changes observed during successful MCP inspections.

  1. Changed2 schema fields changed
    • changedInput schema / properties / items / items / properties / settled / description
      Previous value: -"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; no tool writes off bad debt, so tell the user to use Write off on the document, which also reverses the VAT."New value: +"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; bad debt is written off with write_off_document, which also reverses the VAT."
    • changedInput schema / properties / settled / description
      Previous value: -"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; no tool writes off bad debt, so tell the user to use Write off on the document, which also reverses the VAT."New value: +"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; bad debt is written off with write_off_document, which also reverses the VAT."
  2. Changed4 schema fields changed
    • addedInput schema / properties / items / items / properties / settledaccountid
      Added value: +{
      +  "description": "Where the settle gap posts, when settling an existing document: a Chart of Accounts account name or id (see list_accounts). Omit to post to Settlements, or to Foreign Exchange for a foreign-currency document.",
      +  "type": "string"
      +}
    • addedInput schema / properties / items / items / properties / settleddate
      Added value: +{
      +  "description": "Date the settle entry posts, when settling an existing document (ISO 8601, YYYY-MM-DD). Omit for the default date.",
      +  "type": "string"
      +}
    • addedInput schema / properties / settledaccountid
      Added value: +{
      +  "description": "Where the settle gap posts, when settling an existing document: a Chart of Accounts account name or id (see list_accounts). Omit to post to Settlements, or to Foreign Exchange for a foreign-currency document.",
      +  "type": "string"
      +}
    • addedInput schema / properties / settleddate
      Added value: +{
      +  "description": "Date the settle entry posts, when settling an existing document (ISO 8601, YYYY-MM-DD). Omit for the default date.",
      +  "type": "string"
      +}
  3. Changed2 schema fields changed
    • changedInput schema / properties / items / items / properties / settled / description
      Previous value: -"Whether the document has been fully settled/paid."New value: +"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; no tool writes off bad debt, so tell the user to use Write off on the document, which also reverses the VAT."
    • changedInput schema / properties / settled / description
      Previous value: -"Whether the document has been fully settled/paid."New value: +"Set true to settle: closes the balance left after the recorded payments and marks the document settled. Only for a small gap once the payment is recorded: an exchange-rate difference, a bank fee or rounding (the FX difference itself, or a few percent of the total at most); the gap posts to Settlements, or to Foreign Exchange for an FX difference. Before you set it, state the gap amount and where it posts, and ask the user to confirm, even when they already said 'settle it' or 'mark it paid'. No payment recorded yet: use record_document_payment first. Refused while an AI-matched payment is unconfirmed. Not a write-off: a large short payment, or any part the customer will not pay, is never settled; no tool writes off bad debt, so tell the user to use Write off on the document, which also reverses the VAT."
  4. Changed2 schema fields changed
    • addedInput schema / properties / invoicebankid
      Added value: +{
      +  "description": "PROD-2443. :bankaccount/id of one of the business's own bank accounts to show on this document instead of the default invoice bank. \"$delete\" clears it back to the default; null or omitted leaves it unchanged. An id the business does not own is refused.",
      +  "type": "string"
      +}
    • addedInput schema / properties / items / items / properties / invoicebankid
      Added value: +{
      +  "description": "PROD-2443. :bankaccount/id of one of the business's own bank accounts to show on this document instead of the default invoice bank. \"$delete\" clears it back to the default; null or omitted leaves it unchanged. An id the business does not own is refused.",
      +  "type": "string"
      +}
  5. First observed

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

Annotations only declare readOnlyHint=false and destructiveHint=false; the description adds the key behavioral fact that a batch is one all-or-nothing transaction with a single ledger recompute, which is real consequence information. It does not discuss whether omitted fields are cleared on update or what partial failures look like, leaving some mutation semantics unstated.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Front-loaded and information-dense, with the create/update rule and batch guidance clearly sequenced. It loses a point for redundancy: the 'edit individual line items' alternative is stated twice, once at the top and again in the final sentence.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a 40-parameter mutation tool with no output schema, the description covers the essential decision points: whole-vs-line scope, create-vs-update, batch atomicity, and document-type coverage. It relies entirely on the schema for the settle/payment interplay and does not say what the save returns.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema description coverage is 100%, so the schema already explains every parameter, including `settled` and `invoicebankid`. The description adds only modest meaning beyond it: the id-vs-type create/update contract and the credit/debit-note pattern of passing matching `type` plus `parent` id.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

States a specific verb and resource ('Create or update a WHOLE document and its header') and immediately scopes it against siblings (update_document_item, add_document_line). It also enumerates the eight supported document types, so the agent knows the tool is not invoice-only.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit routing: use this for whole-document create/update, use update_document_item/update_document_items_bulk for line edits, use add_document_line to add a line. It also states that batch `items` is preferred over repeated calls and explains the id-present/id-absent rule for each item.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Try in Browser

Glama MCP Gateway

Add one secure layer between your agents and this server.

Resources