When to use this endpoint

Use Customer_new when an integration needs a normal CRM customer record before creating jobs, assets, quotes, or invoices that refer to it. The endpoint returns the new ID; retrieve the record afterward when you need its final stored name, coordinates, timestamps, or defaults.

Do not use it as an upsert. It does not look up a customer by an external key, and duplicate-name behavior depends on tenant settings. Search or maintain your own Fieldmotion ID mapping before creating another record.

Authentication and permissions

The request must establish the tenant context with signed API-key authentication or a logged-in CRM session. The linked API user must be active.

The handler checks for an authenticated tenant but does not perform an additional page or role-permission check. A browser request may include a one-time _nonce; signed server-to-server requests normally omit it.

Parameters

Identity and contact fields

ParameterTypeRequiredDescription
nameStringYesTrimmed customer name, maximum 178 bytes. Blank values are rejected. An exact existing name may be stored with a numeric suffix; see duplicate handling below.
contact_nameStringNoPrimary contact name, trimmed; maximum 82 bytes. CRM1 requires it in its own dialog, but the endpoint does not.
landlineStringConditionalPrimary contact number, trimmed; maximum 38 bytes. It is required when the tenant's customers-require-landlines setting is enabled and must be unique among non-deleted customers when customer-landline-unique is enabled.
mobileStringNoMobile number, trimmed; maximum 40 bytes.
emailStringNoPrimary email, trimmed; maximum 64 bytes. This endpoint does not validate email syntax.
account_numberStringNoCustomer account number, trimmed; maximum 58 bytes. The endpoint does not enforce account-number uniqueness.
industryStringNoIndustry text, trimmed.
notesStringNoInitial customer notes, trimmed.

Address and coordinates

ParameterTypeRequiredDescription
street_address1StringNoFirst address line, trimmed.
street_address2StringNoSecond address line, trimmed.
townStringNoTown, trimmed; maximum 40 bytes.
cityStringNoCity, trimmed; maximum 40 bytes.
countyStringNoCounty, trimmed; maximum 299 bytes.
stateStringNoState or region, trimmed; maximum 255 bytes.
postcodeStringNoPostcode, trimmed; maximum 20 bytes.
countryStringNoCountry code, trimmed; maximum 3 bytes. When omitted, the tenant's customer-default-country value is used.
latitudeNumber stringNoConverted to a float; defaults to 0.
longitudeNumber stringNoConverted to a float; defaults to 0. If both coordinates convert to zero and any main address field is present, the endpoint attempts to geocode the address.

Relationships and structured values

ParameterTypeRequiredDescription
parent_idInteger stringNoParent customer ID. Negative values become 0; this create handler does not verify that a positive parent exists.
account_managerInteger stringNoUser ID stored as account manager; defaults to 0. This create handler does not validate the ID.
department_idInteger stringNoA positive numeric value triggers a post-insert Customer_setDepartmentId call, which validates the department and records a department change.
billing_targetInteger stringNoInvoice-sync target; defaults to 0 for account behavior. -1 means this customer, -2 means its valid parent (falling back to itself), and a positive value names a specific customer. This handler stores the value without validating the target.
custom_valuesJSON object or arrayNoCustom-field values. A JSON string is decoded, then the value is stored as JSON with arrays forced to object form. Omission stores {}.
callbackStringNoCallback date/value. When supplied blank it is stored as SQL null; when omitted the database default is retained.
email_accountingStringNoStored in customer metadata as email_accounting.
email_extraStringNoAdditional email values. Whitespace is normalized and stored in metadata as newline-separated email_extra.
account_number_sageStringNoA non-blank value is trimmed and stored in metadata as legacy account_sage.
_nonceStringNoOne-time browser form token. If supplied, it must exist and is consumed. Omit it from normal signed API integrations.

Legacy type controls

The current handler accepts type, type_id, and do_not_run_trigger. A truthy do_not_run_trigger with type writes that integer during the insert without validating it. Otherwise, the presence—not the value—of type_id can trigger a post-insert setter that reads type. These parameters are retained for compatibility, not as a stable public calling pattern.

Example request

$result = FM_api('Customer_new', [
	'name' => 'Northwind Service Centre',
	'contact_name' => 'Alex Morgan',
	'landline' => '028 9012 3456',
	'email' => 'service@example.test',
	'account_number' => 'NW-1104',
	'street_address1' => '14 Harbour Road',
	'town' => 'Belfast',
	'postcode' => 'BT1 1AA',
	'country' => 'GBR',
	'custom_values' => json_encode([
		'service_level' => 'gold',
	]),
]);

Example response

{
  "ok": 1,
  "id": 1104
}

The response contains the integer ID but not the final stored record. If duplicate names are not allowed, the stored name might be Northwind Service Centre (2); fetch the ID with Customers_getById before persisting that display name elsewhere.

Errors and unusual responses

ResponseCondition
{"error":"not logged in"}No authenticated tenant context is available.
{"error":"missing or invalid parameter: name"}name is absent or blank after trimming.
{"error":"Contact Number was not set"}The tenant requires customer contact numbers and landline is blank.
{"error":"That landline is already in use by the following customers: ..."}The tenant enforces unique contact numbers and a non-deleted customer already has the value.
{"error":"<field> parameter too long. ..."}A validated text field exceeds its endpoint limit.
{"error":"failed to insert customer into database"}The primary insert did not return a new ID.
{"error":"this form appears to have been submitted already"}A supplied _nonce is missing or has already been consumed.

Legacy API errors may be returned with HTTP 200. Validate the decoded response for error before using id.

Behaviour and edge cases

  • If customer-name-allow-duplicate is not 1, an exact case-insensitive duplicate is renamed to the first free numeric suffix beginning with (2). If the setting is 1, the exact duplicate is stored.
  • Contact-number uniqueness considers non-deleted customers only and compares the stored value exactly.
  • The endpoint does not validate parent, account-manager, billing-target, or account-number references during the primary insert.
  • If both coordinates are zero and an address is present, geocoding is attempted synchronously. Failure does not fail customer creation; the stored coordinates remain zero.
  • cdate and last_edited use the API server's current timestamp, while created_by records the authenticated user ID.
  • The base insert, optional department/type setters, and event listeners are not wrapped in one transaction. A customer can exist even if a post-insert relationship update does not succeed.

Side effects

  • Inserts the customer and invalidates the customer cache.
  • May make an external geocoding request before insertion when coordinates are absent and an address is present.
  • A positive department ID can update last_edited, write a customer change record, and add a customer audit-log entry through Customer_setDepartmentId.
  • After creation, fires the registered Customer_new event. A tenant with the Zapier customer-created hook enabled sends the full new customer row to the registered target URL; the hook may remove its subscription if the target asks to unsubscribe.

See it in Fieldmotion

CRM1

Open Customers, open browser developer tools, and select Create Customer. Submit the dialog and filter Network requests for Customer_new. CRM1 includes a one-time _nonce, requires Contact Name in the dialog, and conditionally requires Contact Number before it sends the request. The endpoint response then redirects the UI to the new customer's edit page.

CRM2

No production CRM2 JavaScript caller of Customer_new was found. CRM2's Customers → Create Customer modal uses the configurable Customer Create layout, whose create mapping calls Customer_createData instead. Do not use that screen as a wire example for this endpoint; use CRM1 or a signed API request.

Related endpoints

  • Customers_getById retrieves the completed record and its final stored name.
  • Customers_list checks existing records before creation and returns the new customer in subsequent lists.
  • Customer_setType is the safer explicit follow-up for a customer type because it validates the type and exposes trigger results.
  • Customer_createData is the layout-driven CRM2 create path and has a different contract.