curl --request PUT \
--url https://api.nuvia.ai/v1/contacts/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"country_code": "<string>",
"email": "<string>",
"linkedin_identifier": "<string>",
"phone_number": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"custom_fields": {},
"business": "<string>"
}
'import requests
url = "https://api.nuvia.ai/v1/contacts/{id}"
payload = {
"name": "<string>",
"country_code": "<string>",
"email": "<string>",
"linkedin_identifier": "<string>",
"phone_number": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"custom_fields": {},
"business": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
country_code: '<string>',
email: '<string>',
linkedin_identifier: '<string>',
phone_number: '<string>',
job_title: '<string>',
seniority: '<string>',
department: '<string>',
country: '<string>',
region: '<string>',
city: '<string>',
experience: '<string>',
skills: '<string>',
additional_attributes: {},
custom_fields: {},
business: '<string>'
})
};
fetch('https://api.nuvia.ai/v1/contacts/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.nuvia.ai/v1/contacts/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'country_code' => '<string>',
'email' => '<string>',
'linkedin_identifier' => '<string>',
'phone_number' => '<string>',
'job_title' => '<string>',
'seniority' => '<string>',
'department' => '<string>',
'country' => '<string>',
'region' => '<string>',
'city' => '<string>',
'experience' => '<string>',
'skills' => '<string>',
'additional_attributes' => [
],
'custom_fields' => [
],
'business' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.nuvia.ai/v1/contacts/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.nuvia.ai/v1/contacts/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nuvia.ai/v1/contacts/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"name": "<string>",
"company": "<unknown>",
"_id": "<string>",
"id": "<string>",
"country_code": "<string>",
"email": "<string>",
"last_activity_at": "<unknown>",
"phone_number": "<string>",
"linkedin_identifier": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"business": "<string>",
"notes": [
{
"_id": "<string>",
"content": "<string>",
"user": "<string>",
"createdAt": "<unknown>",
"updatedAt": "<unknown>"
}
],
"marketing_opt_out": {},
"whatsapp_user_id": "<string>",
"whatsapp_username": "<string>",
"whatsapp_parent_user_id": "<string>",
"createdAt": "<unknown>",
"updatedAt": "<unknown>"
}{
"statusCode": 123,
"code": "CONTACT_IDENTITY_CONFLICT",
"message": "<string>",
"conflicts": [
{
"field": "email",
"contact": {
"_id": "<string>",
"name": "<string>",
"email": "<string>",
"phone_number": "<string>",
"country_code": "<string>",
"linkedin_identifier": "<string>"
}
}
]
}Update contact
Updates the fields sent on an existing contact. Fields not sent are left unchanged.
- additional_attributes:
{ "slug": value }, with a primitive value (string, number, boolean or null). Merged with the current values. A slug that doesn’t exist, or that belongs to a custom field whose context isn’t CONTACT, is silently ignored, with no error. - custom_fields:
{ "slug": value }forselect(option_id),multi_select(list of option_id) andtextfields. Validation is atomic: if any value is invalid, no custom field is saved. A slug that doesn’t exist returns 404 and an invalid option returns 422. Fornumberanddate, useadditional_attributes. - custom_fields and additional_attributes together: send them in separate requests. In the same payload, saving
additional_attributesoverwritescustom_fields. - Phone:
phone_numberandcountry_codecan be changed. The new number is normalized and, if invalid, returns 400. - Another contact’s identifier: saving an
email,linkedin_identifier, or phone that already belongs to ANOTHER contact in the company returns 409CONTACT_IDENTIFIER_TAKEN(e.g."O e-mail já pertence a outro contato."), with the contact that owns the value inconflicts. A value equal to what the contact itself already has isn’t a conflict. - Last identifier: removing the last one among phone, email, and LinkedIn returns 400
"O contato precisa de pelo menos um identificador.".
curl --request PUT \
--url https://api.nuvia.ai/v1/contacts/{id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "<string>",
"country_code": "<string>",
"email": "<string>",
"linkedin_identifier": "<string>",
"phone_number": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"custom_fields": {},
"business": "<string>"
}
'import requests
url = "https://api.nuvia.ai/v1/contacts/{id}"
payload = {
"name": "<string>",
"country_code": "<string>",
"email": "<string>",
"linkedin_identifier": "<string>",
"phone_number": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"custom_fields": {},
"business": "<string>"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: '<string>',
country_code: '<string>',
email: '<string>',
linkedin_identifier: '<string>',
phone_number: '<string>',
job_title: '<string>',
seniority: '<string>',
department: '<string>',
country: '<string>',
region: '<string>',
city: '<string>',
experience: '<string>',
skills: '<string>',
additional_attributes: {},
custom_fields: {},
business: '<string>'
})
};
fetch('https://api.nuvia.ai/v1/contacts/{id}', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.nuvia.ai/v1/contacts/{id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'name' => '<string>',
'country_code' => '<string>',
'email' => '<string>',
'linkedin_identifier' => '<string>',
'phone_number' => '<string>',
'job_title' => '<string>',
'seniority' => '<string>',
'department' => '<string>',
'country' => '<string>',
'region' => '<string>',
'city' => '<string>',
'experience' => '<string>',
'skills' => '<string>',
'additional_attributes' => [
],
'custom_fields' => [
],
'business' => '<string>'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.nuvia.ai/v1/contacts/{id}"
payload := strings.NewReader("{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}")
req, _ := http.NewRequest("PUT", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.put("https://api.nuvia.ai/v1/contacts/{id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nuvia.ai/v1/contacts/{id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"<string>\",\n \"country_code\": \"<string>\",\n \"email\": \"<string>\",\n \"linkedin_identifier\": \"<string>\",\n \"phone_number\": \"<string>\",\n \"job_title\": \"<string>\",\n \"seniority\": \"<string>\",\n \"department\": \"<string>\",\n \"country\": \"<string>\",\n \"region\": \"<string>\",\n \"city\": \"<string>\",\n \"experience\": \"<string>\",\n \"skills\": \"<string>\",\n \"additional_attributes\": {},\n \"custom_fields\": {},\n \"business\": \"<string>\"\n}"
response = http.request(request)
puts response.read_body{
"name": "<string>",
"company": "<unknown>",
"_id": "<string>",
"id": "<string>",
"country_code": "<string>",
"email": "<string>",
"last_activity_at": "<unknown>",
"phone_number": "<string>",
"linkedin_identifier": "<string>",
"job_title": "<string>",
"seniority": "<string>",
"department": "<string>",
"country": "<string>",
"region": "<string>",
"city": "<string>",
"experience": "<string>",
"skills": "<string>",
"additional_attributes": {},
"business": "<string>",
"notes": [
{
"_id": "<string>",
"content": "<string>",
"user": "<string>",
"createdAt": "<unknown>",
"updatedAt": "<unknown>"
}
],
"marketing_opt_out": {},
"whatsapp_user_id": "<string>",
"whatsapp_username": "<string>",
"whatsapp_parent_user_id": "<string>",
"createdAt": "<unknown>",
"updatedAt": "<unknown>"
}{
"statusCode": 123,
"code": "CONTACT_IDENTITY_CONFLICT",
"message": "<string>",
"conflicts": [
{
"field": "email",
"contact": {
"_id": "<string>",
"name": "<string>",
"email": "<string>",
"phone_number": "<string>",
"country_code": "<string>",
"linkedin_identifier": "<string>"
}
}
]
}Authorizations
JWT authentication token
Headers
Target company identifier. Required only for global API keys (type=global). Ignored for company API keys and human users.
Path Parameters
Contact ID
Body
The contact's full name. Optional on update.
Country calling code (1-3 digits). Examples: 55 (Brazil), 1 (USA), 351 (Portugal).
The contact's email address. An email that already belongs to another contact in the company returns 409.
The contact's LinkedIn profile identifier (URL or profile name). A LinkedIn that already belongs to another contact in the company returns 409.
Phone number without formatting, digits only (area code + number, without the country code). Example: 11999998888. The number is normalized; if invalid, returns 400. A phone that already belongs to another contact in the company returns 409.
The contact's job title. Example: Sales Manager.
The contact's seniority level. Example: Senior, Junior, Mid-level.
The contact's department. Example: Sales, IT, Marketing.
The contact's country. Example: Brazil.
The contact's state or region. Example: São Paulo.
The contact's city. Example: São Paulo.
The contact's professional experience.
The contact's skills.
The contact's custom fields. Format: { "field_slug": value }. Slugs must match custom fields registered with the CONTACT context. Invalid or nonexistent slugs are silently ignored. Values are merged with the existing attributes; the whole object is not replaced. Values must be primitives (string, number, boolean or null). Example: { "cpf": "12345678900", "valor_total": 2500.00 }
Show child attributes
Show child attributes
Updates the contact's custom field values, by slug. Covers select ({ "slug": "<option_id>" }), multi_select ({ "slug": ["", ""] }) and text ({ "slug": "value" }). For number/date, use additional_attributes, which keeps the native type. Atomic validation: if any value is invalid, no custom field is saved. A slug with no matching custom field returns 404; an invalid option returns 422; a non-text value in a text field returns 400. Don't send it together with additional_attributes in the same payload: saving additional_attributes overwrites custom_fields. The option_id values come from GET /v1/custom-fields/{id}/options.
Show child attributes
Show child attributes
ID of the Business the contact belongs to (null to remove).
Response
Contact updated successfully
Contact name
Contact's company
Contact ID
Contact ID (same value as _id)
Country code of the number. Absent, along with the phone, when the contact only has a WhatsApp identifier.
Contact's email
Date of the contact's last activity
The contact's phone number. Absent when the contact only has a WhatsApp identifier.
LinkedIn profile identifier
Contact's job title
Contact's seniority level
Contact's department
Contact's country
Contact's state or region
Contact's city
Contact's professional experience
Contact's skills
Values of the contact's custom fields, by slug. When saved via additional_attributes, the value comes in the envelope { id, value, type, updatedAt }. When saved via custom_fields (PUT), it comes raw: the option_id (select), the list of option_id (multi_select) or the text (text).
Show child attributes
Show child attributes
ID of the Business the contact belongs to
Notes recorded on the contact
Show child attributes
Show child attributes
Marketing opt-out per communication channel (whatsapp, email, linkedin). Absent or empty when the contact hasn't opted out of any channel.
Show child attributes
Show child attributes
The contact's WhatsApp identifier (BSUID), assigned by Meta. Opaque string.
The contact's WhatsApp @username, as Meta sends it
The contact's WhatsApp parent_user_id, as Meta sends it
Contact creation date
Contact update date