Guide

Invoices and bills

Add a customer or vendor, optionally a job, then create an invoice or bill, add its lines, post it to Receivable or Payable, and unpost or duplicate it.

An invoice is what you send a customer to ask for payment; a bill is what a vendor sends you. Both are documents: a list of lines (entries) with prices, taxes and discounts, which you edit freely until you post it. Posting turns it into a transaction against your Accounts Receivable (invoice) or Accounts Payable (bill), and opens a lot that payments will close. Before this, set the book up as in Set up the business features.

Steps

  1. Add the other party with customer.create or vendor.create: a name, a currency, and optionally billing terms, a taxTable and a discount. Its ID comes from the counter unless you give one.
  2. Add a job with job.create if the work is for a particular project; its rate becomes the default price of its lines. A job's documents belong to the job's owner.
  3. Create the document with invoice.create. The owner decides what it is: a customer makes an invoice, a vendor a bill, an employee an expense voucher, a job whatever its owner is. Give billingId (your customer's order number, or the vendor's invoice number). The number comes from the counter.
  4. Add lines with invoice.addEntry: description, quantity, price, account (the income or expense account) and, on invoices, discount and tax. A line takes the owner's tax table and discount unless it says otherwise.
  5. Check the figures with invoice.totals: subtotal, tax per tax account, and total.
  6. Post it with invoice.post: the Receivable or Payable account in the document's currency, and the postDate. The due date comes from the billing term unless you give dueDate. The result names the transaction and the lot.
  7. Posted by mistake? invoice.unpost deletes the transaction and makes the document editable again, as long as no payment has been applied.
  8. Another one like it? invoice.duplicate copies a document's lines to a new, unposted one.
  9. Find documents with invoice.list and read one with invoice.get.

Example

An invoice and a bill, in a book that already has a customer, a vendor, tax tables and Receivable and Payable accounts.

Example: with a copy of the synthetic/business-editable example book open as book.gnucash, at 2024-03-10T12:00:00Z.

JSON-RPC

Request:

{"jsonrpc":"2.0","id":1,"method":"customer.create","params":{"name":"Globex","currency":"EUR","terms":"Net30"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 1,
  "result": {
    "id": "000002",
    "name": "Globex",
    "currency": "CURRENCY::EUR",
    "active": true,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":2,"method":"invoice.create","params":{"owner":"5b22073fa4e34411b07c14a77147ce6b","billingId":"PO-5"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 2,
  "result": {
    "id": "000003",
    "type": "invoice",
    "posted": false,
    "billingId": "PO-5",
    "entryCount": 0,
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":3,"method":"invoice.addEntry","params":{"invoice":"00ed0000000000000000000000000002","description":"Design","quantity":"4","price":"90.00","account":"Income"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 3,
  "result": {
    "description": "Design",
    "quantity": {
      "num": "4",
      "denom": "1"
    },
    "…": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":4,"method":"invoice.totals","params":{"invoice":"00ed0000000000000000000000000002"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 4,
  "result": "…"
}

Request:

{"jsonrpc":"2.0","id":5,"method":"invoice.post","params":{"invoice":"00ed0000000000000000000000000002","account":"Assets:Receivable","postDate":"2024-03-10"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 5,
  "result": {
    "transaction": "…",
    "lot": "…",
    "due": "…"
  }
}

Request:

{"jsonrpc":"2.0","id":6,"method":"invoice.create","params":{"owner":"9697710198334d558a9bfde219bb1e41","billingId":"INV-8841"}}

Response:

{
  "jsonrpc": "2.0",
  "id": 6,
  "result": {
    "id": "000002",
    "type": "bill",
    "posted": false,
    "…": "…"
  }
}

Command line

red-ale exec --book book.gnucash --script - <<'EOF'
customer.create {"name":"Globex","currency":"EUR","terms":"Net30"}
invoice.create {"owner":"5b22073fa4e34411b07c14a77147ce6b","billingId":"PO-5"}
invoice.addEntry {"invoice":"00ed0000000000000000000000000002","description":"Design","quantity":"4","price":"90.00","account":"Income"}
invoice.totals {"invoice":"00ed0000000000000000000000000002"}
invoice.post {"invoice":"00ed0000000000000000000000000002","account":"Assets:Receivable","postDate":"2024-03-10"}
invoice.create {"owner":"9697710198334d558a9bfde219bb1e41","billingId":"INV-8841"}
EOF

It prints:

[
  {
    "id": "000002",
    "name": "Globex",
    "currency": "CURRENCY::EUR",
    "active": true,
    "…": "…"
  },
  {
    "id": "000003",
    "type": "invoice",
    "posted": false,
    "billingId": "PO-5",
    "entryCount": 0,
    "…": "…"
  },
  {
    "description": "Design",
    "quantity": {
      "num": "4",
      "denom": "1"
    },
    "…": "…"
  },
  "…",
  {
    "transaction": "…",
    "lot": "…",
    "due": "…"
  },
  {
    "id": "000002",
    "type": "bill",
    "posted": false,
    "…": "…"
  }
]

MCP tool call

Tool call:

{"name":"customer.create","arguments":{"name":"Globex","currency":"EUR","terms":"Net30"}}

Result:

{
  "structuredContent": {
    "id": "000002",
    "name": "Globex",
    "currency": "CURRENCY::EUR",
    "active": true,
    "…": "…"
  }
}

Tool call:

{"name":"invoice.create","arguments":{"owner":"5b22073fa4e34411b07c14a77147ce6b","billingId":"PO-5"}}

Result:

{
  "structuredContent": {
    "id": "000003",
    "type": "invoice",
    "posted": false,
    "billingId": "PO-5",
    "entryCount": 0,
    "…": "…"
  }
}

Tool call:

{"name":"invoice.addEntry","arguments":{"invoice":"00ed0000000000000000000000000002","description":"Design","quantity":"4","price":"90.00","account":"Income"}}

Result:

{
  "structuredContent": {
    "description": "Design",
    "quantity": {
      "num": "4",
      "denom": "1"
    },
    "…": "…"
  }
}

Tool call:

{"name":"invoice.totals","arguments":{"invoice":"00ed0000000000000000000000000002"}}

Result:

{
  "content": [
    {
      "type": "text",
      "text": "\"…\""
    }
  ]
}

Tool call:

{"name":"invoice.post","arguments":{"invoice":"00ed0000000000000000000000000002","account":"Assets:Receivable","postDate":"2024-03-10"}}

Result:

{
  "structuredContent": {
    "transaction": "…",
    "lot": "…",
    "due": "…"
  }
}

Tool call:

{"name":"invoice.create","arguments":{"owner":"9697710198334d558a9bfde219bb1e41","billingId":"INV-8841"}}

Result:

{
  "structuredContent": {
    "id": "000002",
    "type": "bill",
    "posted": false,
    "…": "…"
  }
}