Update a contact
update a contact; only fields present in the body are changed.
PATCH
https://api.centerfy.ai/webhooks/inbound/contacts/:id Headers
| Header | Required | Value | Description |
|---|---|---|---|
x-api-key | Yes | your sub-account API key (cfy_…) | Authenticates the request; or use Authorization: Bearer <key>. |
Content-Type | Yes | application/json | JSON request body. |
X-Webhook-Source | No | your-system-name | Optional loop-prevention label; the outbound trigger won’t echo this change back to the same source. |
Path parameters
| Name | Type | Required | Description |
|---|---|---|---|
id | string (uuid) | Yes | The contact id to update. |
Body parameters
| Name | Type | Required | Default | Description |
|---|---|---|---|---|
name | string | No | — | Full name; if omitted but first_name/last_name are given, name is rebuilt from those. |
first_name | string | No | — | Used with last_name to build name when name is not given. |
last_name | string | No | — | Used with first_name to build name when name is not given. |
email | string | No | — | New email; lowercased on save. |
phone | string | No | — | New phone; must be E.164 (e.g. +14155550123). A provided-but-invalid phone returns 400 (not silently ignored, unlike create). |
address | string | No | — | New postal/street address. |
tags | array | No | — | Array of strings; when provided it replaces the entire tag set (lowercased, trimmed, de-duped). The create endpoint does not accept tags, but PATCH does. To merge or remove instead of replace, use the /tags endpoints. |
source | string | No | — | Lead source label. |
custom_field_values | object | No | — | Custom field values keyed by field key (see GET /webhooks/inbound/custom-fields). Keys must be active fields; values must match the field type (number, boolean, YYYY-MM-DD date, a select option, or a string array for multi-select). Read-only GoHighLevel fields are rejected. |
company_id | string (uuid) | null | No | — | Company to link the contact to; must be in this sub-account. null clears it. |
assigned_user_id | string (uuid) | null | No | — | Assign the contact to an active member of this sub-account. null unassigns. |
status | string | No | — | Contact status label (max 100 characters; cannot be empty). |
Request body
{
"name": "Jane A. Doe",
"email": "[email protected]",
"phone": "+14155550199",
"address": "456 Mission St, San Francisco, CA",
"tags": [
"vip",
"renewal"
],
"source": "crm_sync"
}Example
curl -X PATCH "https://api.centerfy.ai/webhooks/inbound/contacts/{id}" \
-H "x-api-key: $CENTERFY_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Jane A. Doe",
"email": "[email protected]",
"phone": "+14155550199",
"address": "456 Mission St, San Francisco, CA",
"tags": [
"vip",
"renewal"
],
"source": "crm_sync"
}' import { CenterfyClient } from "@centerfy/sdk";
const centerfy = new CenterfyClient({ apiKey: process.env.CENTERFY_API_KEY! });
const result = await centerfy.contacts.update("<contactId>", {
"name": "Jane A. Doe",
"email": "[email protected]",
"phone": "+14155550199",
"address": "456 Mission St, San Francisco, CA",
"tags": [
"vip",
"renewal"
],
"source": "crm_sync"
});
console.log(result); centerfy contacts update <contactId> '{"name":"Jane A. Doe","email":"[email protected]","phone":"+14155550199","address":"456 Mission St, San Francisco, CA","tags":["vip","renewal"],"source":"crm_sync"}' MCP tool: centerfy_contacts_update (see MCP server)
Response
{
"status": "success",
"updated": true,
"contact_id": "3f1c2a9e-7b4d-4c8a-9e2f-1a2b3c4d5e6f"
}Errors
400— if :id is not a valid UUID, if an explicit phone is non-E.164, or if no updatable fields are provided (‘no updatable fields provided’).404— if the contact does not exist.409— if the phone is already used by another contact.
Notes
Only provided fields are changed. The extended fields (custom_field_values, company_id, assigned_user_id, status) return 400 when invalid — e.g. a company or user outside this sub-account. If the contact saves but its custom field values fail to save, the response is 500 with contact_id.