Update a Contact

Partially updates an existing contact.

POSThttps://api.audienceful.com/v2/people
curl --location --request POST 'https://api.audienceful.com/v2/people' \
--header 'Content-Type: application/json' \
--header 'X-Api-Key: <your-api-key>' \
--data-raw '{
    "email": "person@example.com",
    "tags": ["vip"],
    "publications": ["The Weekly"],
    "extra_data": { "plan": "enterprise" }
}'
{
  "id": "jQKdwqp3YRRtTrwqUJEp7d",
  "email": "person@example.com",
  "tags": ["vip"],
  "notes": "",
  "extra_data": {
    "plan": "pro"
  },
  "created_at": "2026-07-04T12:00:00Z",
  "updated_at": "2026-07-04T12:00:00Z",
  "last_activity": "2026-07-04T12:00:00Z",
  "country": "US",
  "status": "active",
  "source": "api",
  "open_rate": 0.42,
  "click_rate": 0.11
}

Requires the people:write scope. This is a partial update — send only the fields you want to change.

Address the contact in the request body, with either their id or their email. Posting an email you already have on file updates that contact and returns 200; posting one you don't creates it and returns 201. That makes this the same call as Create a Contact — one upsert you can call repeatedly without first checking whether the contact exists.

The identifier goes in the body, not the URL. Email addresses do not belong in a URL path: they end up in access logs, proxy caches and browser history, and the characters that are legal in an address but structural in a URL — /, ?, #, % — have to be percent-encoded, which client libraries do for you everywhere except the path.

Body

idstring
The contact's opaque id. Takes precedence over email when both are supplied — so sending id and email together is how you change a contact's email address. An id that doesn't match a contact returns a 404; unlike email, it never creates one.
emailstring
The contact's email address (case-insensitive), used to address them when you don't hold their id. If you're addressing the contact by id, this is instead the new email to set. Changing it to one already used by another contact in the workspace returns a 409 (conflict_error).
tagsarray[string]
A list of tag names to add to the contact. Tags that don't exist yet are created. Tags are always additive — on this and every other endpoint that writes them, a tag you leave out is left in place, so two integrations tagging the same contact can't clobber each other's work.
publicationsarray[string]
A list of publications (consent streams) to subscribe the contact to. Each entry is a publication's id or its name; unknown values return a 400. Unlike tags, this does not replace the contact's current subscriptions — it only ever grants consent, and a publication you leave out is left untouched. To withdraw consent, use Update a Contact's Publications, which accepts false per publication.
notesstring
Notes associated with this contact.
extra_dataobject
Custom field values to update, keyed by each field's data_name. Custom fields may also be sent as top-level keys.
Properties
custom_fieldstring | boolean | number
An example of a custom field you may have for your audience. The data_name for each field is used as the key.
double_opt_instring
Update the contact's double opt-in status (not_required, required, or complete).

Also available: PATCH /v2/people/{id}

The path form still works and is not deprecated. Same field semantics — including additive tags and publications — differing only in that it addresses the contact by URL and returns a 404 instead of creating one:

Bash
curl --location --request PATCH 'https://api.audienceful.com/v2/people/jQKdwqp3YRRtTrwqUJEp7d' \
  --header 'Content-Type: application/json' \
  --header 'X-Api-Key: <your-api-key>' \
  --data-raw '{ "notes": "updated" }'

Reach for it when you already hold the contact's id and want a resource-shaped URL.

Response

Returns the updated contact. 200 when an existing contact was updated, 201 when a new one was created.

idstring
The contact's opaque, unique identifier. Send it as id in the body of the update, delete, opt-in, unsubscribe and publications endpoints to address this contact, or use it in the path of the resource-shaped routes. The sequential integer primary key is never exposed.
emailstring
The contact's email address.
tagsarray[string]
The names of the tags applied to this contact — a flat list of strings.
notesstring
Notes associated with this contact. HTML string or plain string.
extra_dataobject
All custom field values for the contact, keyed by each field's data_name (never the internal field id).
Properties
custom_fieldstring | boolean | number
An example of a custom field you may have for your audience. The data_name for each field is listed here. See Fields.
created_atstring
The datetime (UTC) at which the contact was created.
updated_atstring
The datetime (UTC) at which the contact was last updated.
last_activitystring or null
The datetime (UTC) of this contact's last activity. Example activities that update this field are: creation, opening an email, clicking an email, and unsubscribing.
countrystring or null
The contact's two-letter country code, if known.
statusstring
The single subscription/deliverability indicator for the contact.
Values
active
The contact is active and subscribed.
unconfirmed
The contact has not confirmed their double opt-in email.
bounced
The contact's email failed to deliver (permanent).
unsubscribed
The contact has unsubscribed.
not_subscribed
The contact is not subscribed to marketing.
cleaned
The contact was cleaned from the list (repeatedly undeliverable).
sourcestring
How the contact entered your audience (e.g. api, import, form).
open_ratenumber
The contact's historical email open rate, from 0 to 1.
click_ratenumber
The contact's historical email click rate, from 0 to 1.
Last updated: July 31, 2026