Invoices
Create an invoice from mapped layout data
/a/Invoice_createData
Create an invoice from CRM2 mapped layout values, including line items, recurrence settings, custom fields, and calculated totals.
When to use this endpoint
Use this from a configurable Invoice Create layout. Unlike Invoice_new, it accepts the field-map and widget payloads produced by CRM2 and sends create notices and notifications.
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.
The handler requires add permission for pageInvoices. A legacy CRM1 account with no role row is allowed by the compatibility fallback; an equivalent CRM2 request is denied until a role grants the permission.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
customer / formID | Picker object / integer | Yes | Invoice target and invoice-form selection. A target picker contains id and type. |
cdate / dueDate / num | Date strings / string | No | Invoice date, explicit due date, and number. Missing due date uses customer then tenant terms; missing number uses the configured numbering method. |
widgetTableInvoice | Widget object | No | CRM2 line-item widget payload. Rows are normalized and used to calculate gross and net totals. |
widgetInvoiceRecurrence / widgetFormField | Widget objects | No | Optional recurrence creation and invoice-form field values. Recurrence creation occurs before the invoice insert. |
pandp / pandpVat / taxType / nominalID / nominalCode | Mixed | No | Delivery charge and tax plus the canonical header nominal selection. Conflicting nominal ID/code pairs are rejected. |
Example request
$invoice = FM_api('Invoice_createData', [
'customer' => ['id' => '1042', 'type' => 0],
'formID' => '17',
'cdate' => '2026-10-02',
]);
Example response
{
"ok": 1,
"id": 981
}
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":"permission denied"} | A CRM1 caller lacks add permission. |
{"error":"...refer to different accounts..."} | The supplied nominal ID and code conflict. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- The stored initial status is always
-1(Draft), regardless of a submitted status value. - Blank account-wide and customer due-date terms leave
due_dateunset; explicit zero-day terms mean the invoice date. - If recurrence creation succeeds but the invoice insert or later row storage fails, the recurrence is not rolled back.
Side effects
- Creates the invoice, optionally creates an invoice recurrence, stores normalized rows, snapshots historical customer/asset details, sends mention notices and a create notification, and fires
Invoice_edit.
See it in Fieldmotion
CRM1
CRM1 creates ordinary invoices through Invoice_new; no production CRM1 caller of this mapped route was found.
CRM2
Open Invoices and choose Create Invoice. The configurable layoutInvoiceCreate display submits this endpoint through the shared layout save helper.
Related endpoints
Invoices_getDataTablesupplies paginated CRM2 invoice rows and IDs.Invoices_getDTis the CRM1 invoice-list counterpart.