Customer types
Save a customer type
/a/CustomerType_save
Replace a customer type’s legacy name, transition rules, email triggers, colour, and edit timestamp.
When to use this endpoint
Use CustomerType_save for the complete legacy Customer Type edit form. This route applies some format checks that the mapped update endpoints do not.
Authentication and permissions
The ID and cleaned name are validated before login is required. An unauthenticated malformed request can therefore receive one of those validation errors first.
An accepted request must authenticate with signed API-key fields or a logged-in CRM session. The update is tenant-scoped and has no role check.
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
id | Integer string | Yes | Positive customer-type ID. The endpoint does not verify that a row exists after issuing the update. |
name | String | Yes | Replacement name after removing angle-bracket tag-like fragments and trimming. There is no length or uniqueness check. |
allowed_next | Comma-separated numeric values | No (send explicitly) | Replacement transition list. The code reads this key unconditionally, so omission raises a PHP notice and behaves like an empty value. Each comma-delimited token must satisfy PHP is_numeric; referenced IDs and integer syntax are not checked. Send an empty string to allow every type. |
triggers | JSON array string | No | Replacement trigger list. Invalid JSON or a decoded non-array is silently replaced with []. Verified email-trigger consumers expect objects with target, template, subject, and lowercase replyto. |
colour_hex | Seven-byte string | No | Replacement colour. Only exact byte length seven is checked; content is not checked for # or hexadecimal digits. Missing or wrong-length input becomes #ffffff. |
Example request
$saved = FM_api('CustomerType_save', [
'id' => '12',
'name' => 'Commercial',
'allowed_next' => '12,13',
'colour_hex' => '#336699',
'triggers' => json_encode([[
'target' => 'customer',
'template' => '7',
'subject' => 'Customer type changed',
'replyto' => 'office@example.test',
]]),
]);
Example response
{
"ok": 1
}
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":"missing or invalid parameter: id"} | The ID is absent, zero, negative, or nonnumeric. |
{"error":"missing or invalid parameter: name"} | The cleaned name is blank. |
{"error":"values in allowed_next must be numeric"} | A comma-delimited transition token does not satisfy PHP numeric syntax. |
Legacy application errors may be returned with HTTP 200. Check the decoded response for error, not only the HTTP status.
Behaviour and edge cases
- Numeric transition tokens can include decimals, signs, or exponent notation and need not identify real customer types. The saved text is later interpolated into the transition query, so integrations should send only comma-separated positive integer IDs.
- No existing-row check is made. A positive nonexistent ID still returns
{"ok":1}. Duplicate names are accepted. - Email triggers run later when a customer is changed to this type, not while this endpoint saves the configuration. Verified runtime paths send only entries with
target=customer; direct type-change paths also require the customer to have an email address.
Side effects
- Replaces all five saved values, writes current server time to
last_edited, and invalidates the customer-type cache. - It does not update customers, send trigger email immediately, or write the generic mapped-field audit used by
CustomerType_updateData.
See it in Fieldmotion
CRM1
Open Settings → Customer Types, edit the name, allowed transitions, triggers, or colour, and save.
CRM2
Open Settings → Customer Types and save the legacy modal actions that still call this endpoint. The configurable detail form can instead use CustomerType_updateData.
Related endpoints
CustomerTypes_listByDepartmentapplies the stored transition list.CustomerType_updateDatais the less restrictive mapped update.