POST
Customer.Update
Update an existing customer. The method validates folder permission, validates custom fields from User.Basic, blocks duplicate email/phone/mobile/company_id/name conflicts, pushes the changed customer to the team, and runs customer.updated automation when enabled.
Permissions
- User must be allowed to edit this customer.
- If folder_id is changed, user must be allowed to see this folder or be owner/manager in the organization.
Action
- Updates the customer row.
- Validates folder/status access.
- Validates custom fields from User.Basic.
- Blocks duplicate email, phone, mobile, company_id, or name conflicts.
Push Service
Pushes the changed customer to team members that can see this customer.
Automation
Runs automation event customer.updated with customer_id and changed fields when enabled.
Special Instructions
- If a sent email/phone/company id belongs to another customer, the response returns existing_customer_id and duplicate details.
Required Parameters
| Name | Type | Sample | Explanation |
|---|---|---|---|
customer_idpost | int | 123 | Customer id to update. You may also send cust_id. |
Optional Parameters
| Name | Type | Sample | What it gives |
|---|---|---|---|
namepost | string | John Demo Updated | Customer name. |
emailpost | string | [email protected] | Customer email. If another customer already has this email, the route returns exists=1 with duplicate_by=email and existing_customer_id. |
second_emailpost | string | [email protected] | Updates the secondary email when this field is enabled. |
phonepost | string | 0500000000 | Primary customer phone. Saved to the customer mobile field after normalization. If another customer already has this phone/mobile, the route returns duplicate_by=phone or duplicate_by=mobile. |
mobilepost | string | 0500000000 | Alias for the primary customer phone. It participates in the same duplicate check as phone. |
second_phonepost | string | 0500000001 | Updates the secondary phone. Saved to the customer phone field after normalization. |
companypost | string | Demo Ltd | Updates the customer company/business name. |
company_idpost | string | 123456789 | Updates the company identifier. If checkUnique=company_id and another customer already has this value, the route returns duplicate_by=company_id. |
checkUniquepost | string | email | Duplicate check mode for the edited values: email, phone, mobile, or company_id. Default follows the same customer rules as Customer.Add. |
sourcepost | string | website | Updates the lead/customer source. |
websitepost | string | https://example.com | Updates the website field when enabled. |
passwordpost | string | customer-pass | Updates the customer password/reference field when enabled. |
notepost | string | Updated note | Updates the customer note. |
addresspost | string | 12 Demo Street | Updates the address. |
citypost | string | Tel Aviv | Updates the city. |
folder_idpost | int | 1 | Moves the customer to a folder/status id from User.Basic folders/statuses. |
folderpost | int|string | 1 | Alias for folder_id. Multiple folders can be sent as comma-separated ids. |
status_idpost | int | 1 | Updates the customer status when the account uses status_id. |
tagpost | string | 1,2 | Replaces/updates comma-separated tag ids from User.Basic tags. |
extra_fieldspost | json | {"vip_level":"silver"} | JSON object for customer custom fields. Allowed keys/types come from User.Basic field_settings.customer.extra_fields. |
extra_fields[field_name]post | mixed | silver | Alternative form-data style for one custom field value. Replace field_name with a key from User.Basic field_settings.customer.extra_fields. |
cf-field_namepost | mixed | silver | Custom-field alias. Replace field_name with a configured custom field key from User.Basic field_settings.customer.extra_fields. Unknown custom fields are rejected. |
sub_list_datapost | string | 5 | Folder sub-status value. Requires folder/folder_id. |
sub_list_data_namepost | string | stage | Name/key used for folder_sub_status when sub_list_data is sent. |
internal_sub_status_listpost | string | 2 | Internal sub-status value saved under folder_sub_internal_status when sub_list_data is sent. |
parent_customer_idpost | int | 456 | Moves/keeps this customer under a parent customer relation. Also accepts parent_cust_IIId. |
parent_cust_IIIdpost | int | 456 | Alias for parent_customer_id. |
room_customer_namepost | int | 1 | When 1 and name is sent, duplicate detection also checks whether another customer already has the same cleaned name. |
followuppost | datetime | 2026-07-20 10:00:00 | UTC follow-up date/time saved on the customer. Send UTC date/time as Y-m-d H:i:s, for example 2026-07-20 10:00:00. The SDK converts user local Date/local datetime input to UTC before posting. |
Authentication
Send the bearer token returned by Login in the request header.
Authorization: Bearer YOUR TOKEN
Sample Request
{
"url": "\/app\/Customer.Update",
"method": "POST",
"headers": {
"Authorization": "Bearer YOUR TOKEN"
},
"body": {
"customer_id": "123",
"name": "John Demo Updated",
"email": "[email protected]",
"checkUnique": "email",
"extra_fields": "{\"vip_level\":\"silver\"}"
},
"url_user": "https:\/\/{user}.bull36.com\/app\/Customer.Update",
"url_domain": "https:\/\/{domain}\/app\/Customer.Update"
}Endpoint
POST /app/Customer.Update
POST https://{user}.bull36.com/app/Customer.Update
POST https://{domain}/app/Customer.UpdateSample Output
{
"success": 1,
"exists": 0,
"is_new": 0,
"message": "Customer Updated",
"customer_id": "123",
"id": "123",
"automation_event": "customer.updated",
"socket_event": "customer.updated"
}Existing Customer Response
{
"success": 0,
"exists": 1,
"is_new": 0,
"message": "Customer already exists",
"customer_id": "123",
"existing_customer_id": "456",
"duplicate_by": "email",
"duplicate_value": "[email protected]",
"duplicate_reason": "same email"
}Fail Response
{
"success": 0,
"message": "Customer not found or permission denied"
}JavaScript Example
const token = 'YOUR TOKEN';
const body = new URLSearchParams({
customer_id: '123',
name: 'John Demo Updated',
email: '[email protected]',
checkUnique: 'email',
extra_fields: JSON.stringify({ vip_level: 'silver' })
});
const res = await fetch('/app/Customer.Update', {
method: 'POST',
headers: { Authorization: `Bearer ${token}` },
body
});
const data = await res.json();
if (data.exists) {
console.log('cannot update because another customer already exists', {
editing_customer_id: data.customer_id,
existing_customer_id: data.existing_customer_id,
duplicate_by: data.duplicate_by,
duplicate_value: data.duplicate_value,
duplicate_reason: data.duplicate_reason
});
} else {
console.log('updated customer id', data.customer_id || data.id);
}
console.log(data);Error Example
{
"success": 0,
"exists": 1,
"is_new": 0,
"already": 1,
"already_id": "456",
"existing_customer_id": "456",
"duplicate_customer_id": "456",
"duplicate_by": "email",
"duplicate_value": "[email protected]",
"duplicate_reason": "same email",
"customer_id": "123",
"id": "123",
"message": "Customer already exists"
}