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>"
}
}
]
}Actualizar contacto
Actualiza los campos enviados de un contacto existente. Los campos no enviados no se modifican.
- additional_attributes:
{ "slug": valor }, con valor primitivo (string, number, boolean o null). Se combina con los valores actuales. Un slug inexistente, o de un custom field con contexto distinto de CONTACT, se ignora en silencio, sin error. - custom_fields:
{ "slug": valor }para camposselect(option_id),multi_select(lista de option_id) ytext. La validación es atómica: si algún valor es inválido, no se guarda ningún custom field. Un slug inexistente devuelve 404 y una opción inválida devuelve 422. Paranumberydate, useadditional_attributes. - custom_fields y additional_attributes juntos: envíelos en solicitudes separadas. En el mismo payload, el guardado de
additional_attributessobrescribe el decustom_fields. - Teléfono:
phone_numberycountry_codese pueden cambiar. El número nuevo se normaliza y, si es inválido, devuelve 400. - Identificador de otro contacto: guardar un
email,linkedin_identifiero teléfono que ya pertenece a OTRO contacto de la empresa devuelve 409CONTACT_IDENTIFIER_TAKEN(ej.:"O e-mail já pertence a outro contato."), con el contacto dueño del dato enconflicts. Un valor igual al que el propio contacto ya tiene no es conflicto. - Último identificador: quitar el último entre teléfono, correo electrónico y LinkedIn devuelve 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>"
}
}
]
}Autorizaciones
Token JWT de autenticación
Encabezados
Identificador de la empresa objetivo. Obligatorio solo para API keys globales (type=global). Se ignora para API keys de empresa y usuarios humanos.
Parámetros de ruta
ID del contacto
Cuerpo
Nombre completo del contacto. Opcional en la actualización.
Código de país para llamadas (1-3 dígitos). Ejemplos: 55 (Brasil), 1 (EE. UU.), 351 (Portugal).
Dirección de correo electrónico del contacto. Un correo que ya pertenece a otro contacto de la empresa devuelve 409.
Identificador del perfil de LinkedIn del contacto (URL o nombre del perfil). Un LinkedIn que ya pertenece a otro contacto de la empresa devuelve 409.
Número de teléfono sin formato, solo dígitos (código de área + número, sin el código de país). Ejemplo: 11999998888. El número se normaliza; si es inválido, devuelve 400. Un teléfono que ya pertenece a otro contacto de la empresa devuelve 409.
Cargo del contacto. Ejemplo: Gerente de Ventas.
Nivel de seniority del contacto. Ejemplo: Senior, Junior, Semi-senior.
Departamento del contacto. Ejemplo: Comercial, TI, Marketing.
País del contacto. Ejemplo: Brasil.
Estado o región del contacto. Ejemplo: São Paulo.
Ciudad del contacto. Ejemplo: São Paulo.
Experiencia profesional del contacto.
Habilidades del contacto.
Campos personalizados del contacto. Formato: { "slug_del_campo": valor }. Los slugs deben corresponder a custom fields registrados con contexto CONTACT. Los slugs inválidos o inexistentes se ignoran en silencio. Los valores se combinan con los atributos existentes (merge); no se reemplaza todo el objeto. Los valores deben ser primitivos (string, number, boolean o null). Ejemplo: { "cpf": "12345678900", "valor_total": 2500.00 }
Show child attributes
Show child attributes
Actualiza los valores de los campos personalizados del contacto, por slug. Cubre select ({ "slug": "<option_id>" }), multi_select ({ "slug": ["", ""] }) y text ({ "slug": "valor" }). Para number/date, use additional_attributes, que conserva el tipo nativo. Validación atómica: si algún valor es inválido, no se guarda ningún custom field. Un slug sin custom field correspondiente devuelve 404; una opción inválida devuelve 422; un valor no textual en un campo text devuelve 400. No lo envíe junto con additional_attributes en el mismo payload: el guardado de additional_attributes sobrescribe el de custom_fields. Los option_id se obtienen de GET /v1/custom-fields/{id}/options.
Show child attributes
Show child attributes
ID del Business al que pertenece el contacto (null para quitarlo).
Respuesta
Contacto actualizado correctamente
Nombre del contacto
Empresa del contacto
ID del contacto
ID del contacto (mismo valor que _id)
Código de país del número. Ausente junto con el teléfono cuando el contacto solo tiene un identificador de WhatsApp.
Email del contacto
Fecha de la última actividad del contacto
Número de teléfono del contacto. Ausente cuando el contacto solo tiene un identificador de WhatsApp.
Identificador del perfil de LinkedIn
Cargo del contacto
Nivel de seniority del contacto
Departamento del contacto
País del contacto
Estado o región del contacto
Ciudad del contacto
Experiencia profesional del contacto
Habilidades del contacto
Valores de los campos personalizados del contacto, por slug. Si se guardó vía additional_attributes, el valor viene en el envoltorio { id, value, type, updatedAt }. Si se guardó vía custom_fields (PUT), viene sin envoltorio: el option_id (select), la lista de option_id (multi_select) o el texto (text).
Show child attributes
Show child attributes
ID del Business al que pertenece el contacto
Notas registradas en el contacto
Show child attributes
Show child attributes
Opt-out de marketing por medio de comunicación (whatsapp, email, linkedin). Ausente o vacío cuando el contacto no pidió salir de ningún medio.
Show child attributes
Show child attributes
Identificador del contacto en WhatsApp (BSUID), asignado por Meta. String opaco.
@username del contacto en WhatsApp, tal como lo envía Meta
parent_user_id del contacto en WhatsApp, tal como lo envía Meta
Fecha de creación del contacto
Fecha de actualización del contacto