Documentation Index
Fetch the complete documentation index at: https://docs.nedzo.ai/llms.txt
Use this file to discover all available pages before exploring further.
Create or update a contact based on phone (primary) or email (fallback) matching against active (non-deleted) contacts. Returns 201 for new contacts and 200 for updates.
At least one of phone or email must be provided.
Matching only considers active contacts. If the only match is a soft-deleted contact, it is ignored and a brand new contact is created — the deleted record stays deleted with its data intact.
By default, on a match, provided values in the request overwrite the existing contact’s scalar fields and custom field values; fields you omit from the request are left untouched. Set preserveExisting: true to merge instead — only empty fields and missing custom field values are filled. Tags are always additive regardless of preserveExisting.
Workspace UUID (required for account API keys, optional for workspace API keys)
Email address (used for matching if phone is not provided)
Phone number in E.164 format (primary matching field)
IANA timezone identifier (e.g. America/New_York). Used by features that respect the contact’s local time.
- Only applied when creating a new contact. When matching an existing contact, the existing timezone is preserved (or merged per
preserveExisting); auto-derivation does not run on updates.
- On create, when omitted, the timezone is auto-derived from the phone number with the workspace default as fallback. Caller-supplied values always win.
- Must be a valid IANA timezone identifier; bogus strings are rejected with
400 Bad Request.
When true, populated fields on the matched contact are preserved — only empty fields and missing custom field values are filled in. When false (default), the request values overwrite the existing fields and custom field values. Tag attachment is always additive regardless of this flag.
Tag names to attach to the contact. Tags that don’t exist yet are auto-created in your workspace. Tags are always additive — this endpoint never removes a tag from a contact, regardless of preserveExisting. Names are matched case-sensitively, trimmed, and must be 1–255 characters. Tags in the response are returned in alphabetical order.
Custom field values keyed by the custom variable name as displayed in the dashboard (e.g. "Lead Source" — including spaces and original casing; not a slug). Accepts string, number, boolean, or null (null clears a stored value). Behavior on a match follows preserveExisting: when false (default), provided values overwrite; when true, only fill custom fields the contact doesn’t have a value for. Unknown keys are rejected with a 400. Values are persisted as text and returned as strings.
This endpoint strictly validates the request body. Unknown top-level fields are rejected with 400 Bad Request. Custom field values must use the customFields object.
curl -X POST "https://api.nedzo.ai/v1/contacts/upsert" \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"phone": "+14155551234",
"email": "john@example.com",
"firstName": "John",
"lastName": "Doe",
"tags": ["vip"],
"customFields": {
"Lead Source": "Website",
"MRR": 250
}
}'
{
"id": "123e4567-e89b-12d3-a456-426614174000",
"workspaceId": "789e4567-e89b-12d3-a456-426614174000",
"firstName": "John",
"lastName": "Doe",
"email": "john@example.com",
"phone": "+14155551234",
"timezone": "America/Los_Angeles",
"tags": ["vip"],
"customFields": {
"Lead Source": "Website",
"MRR": "250"
},
"createdAt": "2024-01-15T10:30:00Z",
"updatedAt": "2024-01-15T10:30:00Z"
}