Skip to main content
Estimates share the same line-item shape as invoices, but they’re deliberately simpler under the hood: no stock deduction, no expense-linking, no effect on a client’s balance. This guide covers what’s different from invoicing, since most of what you already know from Create and send an invoice about line items still applies.

Create an estimate

Line items follow the same rules as invoices: each needs an item_id or a description, qty must be greater than 0, rate must be 0 or more.
One difference from invoices: a line item on an estimate can’t carry expense_id. There’s no expense-linking on this resource at all, since bb_estimate has no balance or paid columns to reconcile against, only invoices affect accounts receivable. Sending expense_id on an estimate line gets rejected by validation.
Totals (subtotal, discount, taxtotal, nettotal) are computed the same way as invoices: always server-side from items, any submitted total-shaped value in the request body is ignored.

Update an estimate

As with invoices, items is a full replace on update, not a patch, submit the complete desired line set every time. Every other field is a genuine partial patch.

Converting an estimate to an invoice

There’s no dedicated “convert” endpoint on this API. To turn an accepted estimate into a bill, create a new invoice through the Invoices endpoint using the same client_id and line items. That keeps the two resources’ side effects properly separated: the estimate itself never touches stock or client balance, only the resulting invoice does.

Deleting an estimate

There’s no guard rail on this delete at all, not even a payment or approval-state check. An estimate that’s already been marked accepted, or that a related invoice was already created from, can still be deleted outright through this endpoint. Unlike Invoices (which blocks deletion if a payment exists) or Clients and Items (which block deletion if they’re referenced elsewhere), Estimates has no equivalent protection. If your workflow depends on approved estimates staying around as a record, don’t rely on the API to enforce that, check the estimate’s status yourself before calling delete.

What’s next