When to use this endpoint

Use a positive row ID returned by InvoiceRow_list. Position lookup exists only for legacy callers that do not yet retain row IDs.

Authentication and permissions

The request must use a logged-in CRM session or valid signed API credentials and is scoped to that tenant.

Users whose legacy crm_access mask contains bit 64 receive {"error":"no permission to access api"}. No record-owner check is made.

Parameters

ParameterTypeRequiredDescription
invoice_id / idPositive integer-compatibleYesActive invoice ID.
row_id / invoice_row_idPositive integer-compatibleNormallyActive row-table ID scoped to this invoice.
positionInteger-compatibleIf no row IDLegacy zero-based position lookup. Negative/missing position with no row ID is rejected.

Example request

$result = FM_api('InvoiceRow_delete', ['invoice_id' => 981, 'row_id' => 441]);

Example response

{
  "ok": 1,
  "total_net": 50,
  "total": 60,
  "row_id": 441
}

Errors and unusual responses

ResponseCondition
{"error":"not logged in"}No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs.
{"error":"invoice row does not exist"}A positive row ID is absent, deleted, or belongs to another invoice.
{"error":"cannot edit invoices that are marked Paid"}Invoice status is Paid.

Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.

Behaviour and edge cases

  • If legacy position lookup finds no row, the route returns {"ok":1,"warning":"invoice row did not exist","row_id":0}; a missing positive row ID instead returns an error.
  • Surviving row positions are not compacted after deletion. List ordering remains position then row ID.

Side effects

  • Sets row deleted=1 with deletion/edit timestamps, recalculates invoice totals/edit metadata, fires Invoice_edit, and updates linked-job totals including the former owning job. It does not write the tenant object-deletion stream.

See it in Fieldmotion

CRM1

Job Invoice, the invoice table widget, and the main Invoices editor delete persisted rows through this route.

CRM2

Configurable invoice and Job Costs table widgets call it with a positive row ID.

Related endpoints

  • InvoiceRow_list supplies stable row IDs and positions before a targeted edit.
  • Invoice_setRows replaces the complete row collection for compatibility callers.