Hi Zoho Community,
We are running an automated batch invoicing system using the Zoho Books
API and have hit two critical bugs that are causing duplicate invoice
risk in production. Raising this here for visibility alongside a support
ticket already filed.
SETUP
We create invoices via POST /invoices using billable_expense_id to
convert individual bill line items (from Purchases > Bills) into invoice
line items. This follows the documented API behaviour.
=== BUG 1: invoiced flag not set after API invoice creation ===
After a successful invoice POST using billable_expense_id, the source
bill line item remains invoiced=false. This is inconsistent with UI
behaviour — when you create an invoice from the same bill via
Purchases > Bills > More > Create Invoice, the line item is immediately
marked invoiced=true.
This means any subsequent API call or batch run sees the same bill line
items as unbilled and creates duplicate invoices.
=== BUG 2: Invoice GET returns empty bill_id and bill_item_id ===
Fetching the created invoice via GET /invoices/{invoice_id} returns
bill_id:"" and bill_item_id:"" on every line item — even though those
lines were created from bill line items via billable_expense_id.
This breaks any writeback automation that needs to trace invoice line
items back to source bills.
Raw response received:
{
"line_item_id": "2138542000005701004",
"name": "Item Name",
"bill_id": "",
"bill_item_id": "",
"expense_id": "",
"project_id": ""
}
=== UI SYMPTOM: Projects > Create Invoice shows duplicates ===
Because invoiced=true is never set via the API route, the Projects
module > Create Invoice screen > "All bills associated with the project"
permanently shows all API-invoiced bill line items as unbilled.
Any user with Projects access can accidentally create a full duplicate
invoice for all already-billed items at any time — with no warning
in the UI.
Reproducible without API knowledge:
1. Mark a bill line item as billable to customer and project
2. Invoice it via POST /invoices using billable_expense_id (code 0)
3. Go to Projects > Create Invoice > All bills associated with project
4. Already-invoiced bill appears as unbilled — can be invoiced again
=== REPRODUCTION STEPS ===
1. Create bill in Purchases > Bills, mark line item billable to
customer and project. Note the line_item_id.
2. POST /invoices with billable_expense_id = that line_item_id.
3. Confirm code 0 success.
4. GET /bills/{bill_id} — line item shows invoiced=false [Bug 1]
5. GET /invoices/{invoice_id} — bill_id:"" and bill_item_id:"" [Bug 2]
6. Projects > Create Invoice > All bills — item still shows as
unbilled [UI symptom of Bug 1]
7. Compare: invoice same bill via UI — invoiced=true immediately,
bill_id populated, item disappears from Projects > Create Invoice
=== QUESTIONS FOR ZOHO / COMMUNITY ===
1. Is billable_expense_id the correct field to use for converting
bill line items to invoice line items via the API?
2. Is there an alternative API field or endpoint that correctly sets
invoiced=true on the source bill line item?
3. Is there a Projects-specific invoice endpoint that handles bill
invoicing through the Projects pipeline — which would correctly
update the invoiced flag?
4. Has anyone found a reliable workaround for this other than
custom fields?
A support ticket has been filed. Currently using a custom Lookup
field cf_linked_client_invoice on the Bill record as a workaround —
but this should not be necessary for documented API behaviour.
Any input from the community or Zoho team appreciated.