Skip to main content
POST
/
contacts
/
upsert
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"
}

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.
workspaceId
string
Workspace UUID (required for account API keys, optional for workspace API keys)
firstName
string
First name
lastName
string
Last name
email
string
Email address (used for matching if phone is not provided)
phone
string
Phone number in E.164 format (primary matching field)
timezone
string
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.
preserveExisting
boolean
default:"false"
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.
tags
string[]
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.
customFields
object
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"
}