Update Contact & Entity Fields
Surgically patch one or more fields on an existing contact or entity without resending the entire record.
Update specific fields on a CRM contact, entity, or both in a single call. Supports all standard fields, boolean flags, custom fields, and tags with intelligent merge behavior.
Requires a valid `api_key` and `developer_secret` in the JSON request body. Requests must originate from a whitelisted IP address.
Tip:
This endpoint is built for targeted updates — toggling a flag, changing a status, appending tags, or updating custom fields. For creating new contacts or full upsert operations, use the **Add or Update Contact** API instead.
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
api_key |
body | string |
Yes | Your Zyntro API key. |
developer_secret |
body | string |
Yes | Your developer secret (zdk_XXX). Issued during developer onboarding. |
org_id |
body | string |
Yes | Your organization UUID. |
contact_id |
body | string |
No | The UUID of the contact to update. At least one of `contact_id` or `entity_id` is required. |
entity_id |
body | string |
No | The UUID of the entity to update. At least one of `contact_id` or `entity_id` is required. |
fields |
body | object |
Yes | An object containing one or more field names (camelCase) and their new values. Contact-specific fields apply to the contact; entity-specific fields apply to the entity. See the field reference tables below. |
Info:
**Help mode:** Send `{"help": true}` as your request body to receive the complete field reference, sample payloads, and usage notes directly from the API — no authentication required.
Request Body
Content-Type: application/json
Schema
json
{
"fields": {
"fieldName": "value",
"customFields": {
"cf_tag": "value"
}
},
"org_id": "string (required)",
"api_key": "string (required)",
"entity_id": "string (conditional)",
"contact_id": "string (conditional)",
"developer_secret": "string (required)"
}
Example
json
{
"fields": {
"tags": "vip,priority",
"status": "Warm",
"autoEngage": 0,
"customFields": {
"cf_lead_source": "Conference 2025",
"cf_company_size": "Enterprise"
},
"primaryPhone": "+1 555-123-4567"
},
"org_id": "your-org-uuid",
"api_key": "your_zyntro_api_key",
"contact_id": "contact-uuid-to-update",
"developer_secret": "your_developer_secret"
}
Code Samples
bash
curl -X POST https://app.zyntrohq.com/apis/v2/public/crm/updateFieldData \
-H "Content-Type: application/json" \
-d '{
"api_key": "your_zyntro_api_key",
"developer_secret": "your_developer_secret",
"org_id": "your-org-uuid",
"contact_id": "contact-uuid",
"fields": {
"autoEngage": 0,
"status": "Warm",
"tags": "vip,priority"
}
}'
bash
curl -X POST https://app.zyntrohq.com/apis/v2/public/crm/updateFieldData \
-H "Content-Type: application/json" \
-d '{
"api_key": "your_zyntro_api_key",
"developer_secret": "your_developer_secret",
"org_id": "your-org-uuid",
"entity_id": "entity-uuid",
"fields": {
"name": "Acme Corporation",
"status": "Active",
"website": "https://acme.com",
"score": 85.5
}
}'
bash
curl -X POST https://app.zyntrohq.com/apis/v2/public/crm/updateFieldData \
-H "Content-Type: application/json" \
-d '{
"api_key": "your_zyntro_api_key",
"developer_secret": "your_developer_secret",
"org_id": "your-org-uuid",
"contact_id": "contact-uuid",
"entity_id": "entity-uuid",
"fields": {
"status": "Client",
"autoEngage": 1,
"customFields": {
"cf_onboarding_complete": "true"
}
}
}'
php
$response = file_get_contents(
'https://app.zyntrohq.com/apis/v2/public/crm/updateFieldData',
false,
stream_context_create([
'http' => [
'method' => 'POST',
'header' => 'Content-Type: application/json',
'content' => json_encode([
'api_key' => 'your_zyntro_api_key',
'developer_secret' => 'your_developer_secret',
'org_id' => 'your-org-uuid',
'contact_id' => 'contact-uuid',
'fields' => [
'autoEngage' => 0,
'status' => 'Warm',
],
]),
],
])
);
$result = json_decode($response, true);
javascript
const response = await fetch(
'https://app.zyntrohq.com/apis/v2/public/crm/updateFieldData',
{
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
api_key: 'your_zyntro_api_key',
developer_secret: 'your_developer_secret',
org_id: 'your-org-uuid',
contact_id: 'contact-uuid',
fields: {
autoEngage: 0,
status: 'Warm',
tags: 'vip,priority',
},
}),
}
);
const result = await response.json();
Response
200
All requested fields were updated successfully.
json
{
"data": {
"message": "5 fields updated successfully",
"entity_id": null,
"contact_id": "contact-uuid",
"updated_fields": [
"autoEngage",
"status",
"tags",
"primaryPhone",
"customFields"
]
},
"status": "success"
}
200
Partial success — some fields updated, others had validation errors. The `warnings` array contains the validation messages for the fields that failed.
json
{
"data": {
"message": "1 field updated successfully",
"warnings": [
"primaryEmail is not a valid email address"
],
"entity_id": null,
"contact_id": "contact-uuid",
"updated_fields": [
"status"
]
},
"status": "success"
}
200
All field validations failed — nothing was updated.
json
{
"data": [
"primaryEmail is not a valid email address",
"stageId must be a number"
],
"status": "error"
}
200
The specified contact or entity was not found in the organization.
json
{
"data": "Contact not found",
"status": "error"
}
200
Missing required parameters.
json
{
"data": [
"Missing API key",
"Missing org_id"
],
"status": "error"
}
Warning:
**Shared field names:** When you pass both `contact_id` and `entity_id`, field names that exist in both maps — like `status` and `customFields` — are applied to **both** records. Contact-only fields like `autoEngage` only affect the contact; entity-only fields like `score` only affect the entity.
Important:
**How tags work:** Tags on contacts are always **appended**, never replaced. The API performs case-insensitive deduplication, so adding `VIP` when the contact already has `vip` will not create a duplicate. To remove tags, use the CRM interface directly.
**How custom fields work:** The `customFields` object is **merged** with the contact's existing custom fields. Only the keys you include are updated — all other custom field values are preserved. Custom field tags must start with `cf_` (auto-prefixed if omitted).
**How empty values work:** Passing `null` or an empty string for any field will **not** overwrite existing data. The field is simply skipped. This means you can safely pass a partial `fields` object without worrying about blanking out data you did not intend to change.
**How names work:** When you update `firstName` or `lastName`, the full `name` field is automatically recalculated from the current first and last name values.
**How custom fields work:** The `customFields` object is **merged** with the contact's existing custom fields. Only the keys you include are updated — all other custom field values are preserved. Custom field tags must start with `cf_` (auto-prefixed if omitted).
**How empty values work:** Passing `null` or an empty string for any field will **not** overwrite existing data. The field is simply skipped. This means you can safely pass a partial `fields` object without worrying about blanking out data you did not intend to change.
**How names work:** When you update `firstName` or `lastName`, the full `name` field is automatically recalculated from the current first and last name values.
Errors
| Code | Message | Resolution |
|---|---|---|
MISSING_API_KEY |
Missing API key The `api_key` field was not included in the request body. |
Include your Zyntro API key. Find it under **Me > API Keys** in your account. |
INVALID_API_KEY |
Invalid API Key The provided API key does not match any active Zyntro account. |
Verify the API key is correct and that the associated account is active. |
MISSING_DEVELOPER_SECRET |
Missing developer_secret The `developer_secret` field is missing or empty. |
Include your developer secret in the request body. This is issued during developer onboarding. |
INVALID_DEVELOPER_SECRET |
Invalid developer_secret The developer secret does not match any active key. |
Verify your developer secret. If lost, have your client revoke and reissue the key. |
IP_NOT_WHITELISTED |
IP address not whitelisted The request originated from an IP not in the key's allowed list. |
Contact your client to add your IP to the developer key whitelist. |
MISSING_ORG_ID |
Missing org_id The `org_id` field was not included in the request body. |
Include your organization UUID. |
MISSING_TARGET |
At least one of contact_id or entity_id is required Neither `contact_id` nor `entity_id` was provided. |
Include at least one record identifier to specify what to update. |
MISSING_FIELDS |
fields object is required and must contain at least one field to update The `fields` key was missing, empty, or not an object. |
Pass a `fields` object with at least one key-value pair. |
CONTACT_NOT_FOUND |
Contact not found No contact with the given UUID exists in the specified organization. |
Verify the `contact_id` and `org_id` are correct. |
ENTITY_NOT_FOUND |
Entity not found No entity with the given UUID exists in the specified organization. |
Verify the `entity_id` and `org_id` are correct. |
VALIDATION_ERROR |
Field-specific validation error A field value did not pass type validation (e.g. invalid email format, value exceeds max length, non-numeric value for an integer field). These are returned as an array in the `data` field or in a `warnings` array if other fields succeeded. |
Check the field type requirements in the tables above and correct the value. |
Tip:
**Readonly fields are safe to include.** If you pass `id`, `orgId`, or `createdAt` in the `fields` object, they are silently ignored — no error is returned. Similarly, unknown field names that are not in the field map are skipped without error. This makes it safe to forward a partial contact object from another system without stripping fields first.