Jobs: lookups and details
Retrieve a job’s invoice or an empty draft
/a/Job_invoiceGet
Read an existing direct invoice for a job, or obtain the legacy empty invoice object used by invoice editors.
When to use this endpoint
Read an existing direct invoice for a job, or obtain the legacy empty invoice object used by invoice editors.
Authentication and permissions
Authenticate with signed API-key fields or a logged-in CRM session. These calls use the authenticated account’s data; the handler has no additional job-page, department, assignee or client-admin permission check unless stated below.
The handler rejects users whose crm_access bit 64 is set, before ID validation/login. Invoice_get repeats the invoice access restriction.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer string | Yes | Job ID, converted with intval; the result must be positive. This selects a physical job ID, not an app ID or job reference. |
Example request
$result = FM_api('Job_invoiceGet', ['id' => '1042']);
Example response
{"id":0,"total":"0","paid":"0","rows":"[]","notes":"","type":"0","status":"-1","discount":"0","pandp":"0","doc_no":null,"order_no":null,"discount_vat":"0","pandp_vat":"0","total_net":"0.0000","published":null}
Errors and unusual responses
| Response | Condition |
|---|---|
{"error":"not logged in"} | No authenticated tenant context is available. Invalid signed credentials can be rejected by the dispatcher before the handler runs. |
{"error":"This user does not have access to certain CRM features. Check user permissions."} | crm_access bit 64 is set. |
{"error":"missing or invalid parameter: id"} | id is absent or nonpositive. |
{"error":"invoice does not exist"} | A resolved invoice can no longer be read as active. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Looks first for a direct many-to-many invoice link (type 3) to a nondeleted invoice, then for a nondeleted invoice’s legacy job pointer. Ancillary type-4 links are not selected.
- There is no active-job existence check or deterministic ordering between multiple direct invoices. A positive nonexistent/deleted job ID can still resolve a linked invoice; otherwise it receives the empty draft shown.
- A saved invoice delegates to Invoice_get: a larger invoice object, encoded customer_details and normalized/re-encoded rows. The empty draft has integer id=0 and is not a persisted invoice.
- This lookup does not convert legacy invoice links or create an invoice. No pagination or invoice-generation action runs.
Side effects
- Invoice_get may rebuild and save a missing/invalid invoice customer_details snapshot. That write is not checked, and this helper does not advance invoice edit metadata for the refresh.
- Invoice-line normalization changes the returned rows representation, not the saved rows. No mail, payment or new link is created by this lookup.
See it in Fieldmotion
CRM1
Open a job’s Invoice view or a job invoice table. pageJobInvoice.js and widgetInvoiceTable.js call Job_invoiceGet to load existing data or the empty editor model.
CRM2
Open a job’s Invoice or Costs view. pageJobInvoice.js, pageJobCosts.js and widgetInvoiceTable.js use this route. An id=0 response is an unsaved editor model, not a creation acknowledgement.
Related endpoints
Invoice_getdocuments the full saved-invoice response and normalization.Job_getContractInvoiceablereads the contract hint separately; this route does not enforce it.Jobs_getInvoiceStatusesreturns compact status tuples rather than invoice details.