curl --request POST \
--url https://api.nuvia.ai/v1/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "João Silva",
"country_code": "55",
"phone_number": "11999998888",
"email": "joao.silva@exemplo.com.br",
"job_title": "Gerente de Vendas",
"city": "São Paulo",
"additional_attributes": {
"cpf": "12345678900"
}
}
'import requests
url = "https://api.nuvia.ai/v1/contacts"
payload = {
"name": "João Silva",
"country_code": "55",
"phone_number": "11999998888",
"email": "joao.silva@exemplo.com.br",
"job_title": "Gerente de Vendas",
"city": "São Paulo",
"additional_attributes": { "cpf": "12345678900" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'João Silva',
country_code: '55',
phone_number: '11999998888',
email: 'joao.silva@exemplo.com.br',
job_title: 'Gerente de Vendas',
city: 'São Paulo',
additional_attributes: {cpf: '12345678900'}
})
};
fetch('https://api.nuvia.ai/v1/contacts', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'João Silva',
'country_code' => '55',
'phone_number' => '11999998888',
'email' => 'joao.silva@exemplo.com.br',
'job_title' => 'Gerente de Vendas',
'city' => 'São Paulo',
'additional_attributes' => [
'cpf' => '12345678900'
]
]),
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"
payload := strings.NewReader("{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.nuvia.ai/v1/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nuvia.ai/v1/contacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\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>"
}Crear o actualizar contacto
Crea un contacto o, si la empresa ya tiene un contacto con el mismo teléfono, actualiza ese contacto (upsert).
- Identificación: el contacto se encuentra solo por el teléfono (
country_code+phone_number). El correo electrónico y LinkedIn no se usan para encontrar el contacto. - Respuesta: 201 tanto al crear como al encontrar un contacto existente. La respuesta no indica cuál de los dos ocurrió.
- Contacto existente: el
namese conserva.email,linkedin_identifieryadditional_attributesse actualizan; enadditional_attributesel merge es por slug, y los slugs no enviados se mantienen. - Campos de perfil:
job_title,seniority,department,country,region,cityyexperiencese guardan en la creación y, en un contacto existente, se actualizan cuando se envían. - Teléfono: solo dígitos, código de área + número, sin el código de país (el código de país va en
country_code). Un teléfono inválido devuelve 400. - additional_attributes:
{ "slug": valor }, con valor primitivo (string, number, boolean o null). Un slug inexistente, o de un custom field con contexto distinto de CONTACT, se ignora en silencio.
curl --request POST \
--url https://api.nuvia.ai/v1/contacts \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"name": "João Silva",
"country_code": "55",
"phone_number": "11999998888",
"email": "joao.silva@exemplo.com.br",
"job_title": "Gerente de Vendas",
"city": "São Paulo",
"additional_attributes": {
"cpf": "12345678900"
}
}
'import requests
url = "https://api.nuvia.ai/v1/contacts"
payload = {
"name": "João Silva",
"country_code": "55",
"phone_number": "11999998888",
"email": "joao.silva@exemplo.com.br",
"job_title": "Gerente de Vendas",
"city": "São Paulo",
"additional_attributes": { "cpf": "12345678900" }
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
name: 'João Silva',
country_code: '55',
phone_number: '11999998888',
email: 'joao.silva@exemplo.com.br',
job_title: 'Gerente de Vendas',
city: 'São Paulo',
additional_attributes: {cpf: '12345678900'}
})
};
fetch('https://api.nuvia.ai/v1/contacts', 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",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'name' => 'João Silva',
'country_code' => '55',
'phone_number' => '11999998888',
'email' => 'joao.silva@exemplo.com.br',
'job_title' => 'Gerente de Vendas',
'city' => 'São Paulo',
'additional_attributes' => [
'cpf' => '12345678900'
]
]),
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"
payload := strings.NewReader("{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\n}")
req, _ := http.NewRequest("POST", 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.post("https://api.nuvia.ai/v1/contacts")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.nuvia.ai/v1/contacts")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"name\": \"João Silva\",\n \"country_code\": \"55\",\n \"phone_number\": \"11999998888\",\n \"email\": \"joao.silva@exemplo.com.br\",\n \"job_title\": \"Gerente de Vendas\",\n \"city\": \"São Paulo\",\n \"additional_attributes\": {\n \"cpf\": \"12345678900\"\n }\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>"
}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.
Cuerpo
Nombre completo del contacto. Obligatorio. Si ya existe un contacto con el mismo teléfono, su nombre se conserva.
1Código de país para llamadas (1-3 dígitos). Ejemplos: 55 (Brasil), 1 (EE. UU.), 351 (Portugal). Junto con phone_number, identifica el contacto: si la empresa ya tiene un contacto con ese teléfono, se actualiza en lugar de crearse uno nuevo.
1 - 3^\d{1,3}$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. Un teléfono que no forma un número válido con el country_code se rechaza con 400.
1^\d+$Dirección de correo electrónico del contacto. Opcional. No se usa para encontrar el contacto; en un contacto existente, reemplaza el correo actual.
Identificador de LinkedIn del contacto (nombre del perfil). Ejemplo: joao-silva-123. No se usa para encontrar el contacto; en un contacto existente, reemplaza el valor actual.
Cargo del contacto. Ejemplo: Gerente de Ventas. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
Nivel de seniority del contacto. Ejemplo: Senior, Junior, Semi-senior. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
Departamento del contacto. Ejemplo: Comercial, TI, Marketing. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
País del contacto. Ejemplo: Brasil. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
Estado o región del contacto. Ejemplo: São Paulo. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
Ciudad del contacto. Ejemplo: São Paulo. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
Experiencia profesional del contacto. Se guarda en la creación; en un contacto existente, se actualiza cuando se envía.
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 deben ser primitivos (string, number, boolean o null). En un contacto existente, solo se actualizan los slugs enviados (merge); los demás se mantienen. Ejemplo: { "cpf": "12345678900", "data_nascimento": "1990-01-15", "valor_total": 1500.50 }
Show child attributes
Show child attributes
Respuesta
Contacto creado, o contacto existente con el mismo teléfono actualizado
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