Modificar Contactos
Permite modificar uno o múltiples contactos de clientes existentes en una única petición. Cada contacto viaja con su array details: los medios de contacto que ya existen se actualizan y los que no existen se agregan. Los medios de contacto nunca se eliminan por este endpoint; para retirar uno, envíelo con state: "N".
Método: POST
Endpoint
Sección titulada «Endpoint»https://api.ventasremotas.com/v1/contacts/batch-updateEncabezados de la solicitud
Sección titulada «Encabezados de la solicitud»| Header | Valor | Descripción | Requerido |
|---|---|---|---|
Content-Type |
application/json |
Indica que los datos se envían en formato JSON | Sí |
Accept |
application/json |
Indica que la respuesta debe estar en formato JSON | No |
Subscription-Key |
{subscription_key} |
Clave de suscripción para acceder a la API | Sí |
Authorization |
Bearer {access_token} |
Token de acceso obtenido del endpoint /token |
Sí* |
Parámetros del Cuerpo (Body)
Sección titulada «Parámetros del Cuerpo (Body)»El body debe ser un array de objetos, donde cada objeto representa un contacto a actualizar junto con sus medios de contacto.
Límites
Sección titulada «Límites»| Parámetro | Valor | Descripción |
|---|---|---|
| Mínimo de items | 1 | El array no puede estar vacío |
| Máximo de items | 10,000 | Número máximo de contactos por petición |
Mínimo de details por contacto |
0 | Un array vacío actualiza solo los datos del contacto, sin tocar sus medios de contacto |
El cuerpo (Body) de la solicitud debe enviarse en formato JSON y debe incluir un array con los siguientes parámetros.
Contacto
Sección titulada «Contacto»| Campo | Tipo | Nulo | Restricciones | Descripción |
|---|---|---|---|---|
code |
number | Sí | Código único del contacto en la base de datos. Llave de identificación alternativa, usada cuando erp_code es null |
|
client_id |
string (max 18) | No | No permite: espacio, #, %, &, *, {, }, \, :, <, >, ?, /, +, . |
Código del cliente al que pertenece el contacto. Acota la búsqueda: el contacto debe pertenecer a este cliente |
first_name |
string (max 100) | No | Primer nombre del contacto | |
second_name |
string (max 100) | Sí | Segundo nombre del contacto | |
first_last_name |
string (max 100) | No | Primer apellido del contacto | |
second_last_name |
string (max 100) | Sí | Segundo apellido del contacto | |
position |
string (max 100) | Sí | Cargo que ocupa el contacto | |
department |
string (max 100) | Sí | Departamento o área a la que pertenece | |
company_name |
string (max 100) | Sí | Nombre de la empresa del contacto, cuando difiere del cliente | |
relation |
string (max 100) | Sí | Relación del contacto con el cliente | |
observations |
string (max 500) | Sí | Observaciones generales del contacto | |
state |
string (max 1) | No | Valores permitidos: Y, N |
Estado del contacto (Activo/Inactivo) |
erp_code |
string (max 50) | Sí | Único por empresa | Código del contacto en el sistema ERP. Es la llave de identificación principal |
details |
array | No | Puede ser vacío | Medios de contacto a agregar o actualizar. Cada elemento sigue la tabla siguiente |
Elemento de details
Sección titulada «Elemento de details»| Campo | Tipo | Nulo | Restricciones | Descripción |
|---|---|---|---|---|
type |
int | No | Valores: 1, 2, 3, 4 |
Tipo de medio de contacto: 1 (Correo electrónico), 2 (Teléfono), 3 (Dirección), 4 (Fecha) |
value |
string (max 100) | No | Según el tipo, ver Reglas por tipo | Valor del medio de contacto. Junto con type identifica el medio de contacto a actualizar |
label |
string (max 100) | Sí | Obligatorio y no vacío cuando type es 4 |
Nombre de la fecha (Cumpleaños, Aniversario). Para los demás tipos se ignora y se guarda vacío |
state |
string (max 1) | No | Valores permitidos: Y, N |
Estado del medio de contacto (Activo/Inactivo) |
latitude |
decimal (24, 18) | Sí | Entre -90 y 90. Solo se guarda cuando type es 3 |
Latitud de la dirección georreferenciada. Debe enviarse junto con longitude |
longitude |
decimal (24, 18) | Sí | Entre -180 y 180. Solo se guarda cuando type es 3 |
Longitud de la dirección georreferenciada. Debe enviarse junto con latitude |
Reglas por tipo
Sección titulada «Reglas por tipo»type |
Medio | Regla sobre value |
label |
latitude / longitude |
|---|---|---|---|---|
1 |
Correo electrónico | Debe ser una dirección de correo válida | Se ignora, se guarda vacío | Se ignoran |
2 |
Teléfono | Solo dígitos, de 7 a 15, con + e indicativo del país opcional al inicio. Si trae +, el indicativo se separa y se guarda como indicativo de WhatsApp (por ejemplo +573001234567 → indicativo +57, número 3001234567). Sin +, se guarda tal cual como teléfono fijo |
Se ignora, se guarda el indicativo extraído o vacío | Se ignoran |
3 |
Dirección | Texto libre con la dirección física | Se ignora, se guarda vacío | Opcionales, pero deben venir ambas o ninguna |
4 |
Fecha | Fecha en formato YYYY-MM-DD |
Obligatorio y no vacío | Se ignoran |
Cómo se actualizan los details
Sección titulada «Cómo se actualizan los details»Cada elemento de details se busca dentro del contacto por type y value, tal como los devuelve Listar Contactos. En los teléfonos el indicativo forma parte de la identidad: +573001234567 y 3001234567 son dos medios de contacto distintos.
- Si existe, se actualizan
state,label(fechas) y las coordenadas (direcciones). - Si no existe, se agrega al contacto.
- Ningún medio de contacto se elimina. Para cambiar el valor de un correo, teléfono, dirección o fecha, agregue el nuevo y envíe el anterior con
state: "N". - Cualquier actualización, incluso solo de medios de contacto, actualiza la fecha de modificación del contacto, de modo que la aplicación móvil lo sincroniza.
Formato de tipos de dato
Sección titulada «Formato de tipos de dato»- string (max N): Cadena de texto con longitud máxima de
Ncaracteres. - int: Número entero.
- decimal (p, s): Número decimal donde
pes la precisión total (dígitos enteros + decimales) yses la escala (dígitos decimales).- Ejemplo:
decimal (24, 18)permite hasta 6 dígitos enteros y 18 decimales (ej:4.710988600000000000)
- Ejemplo:
- array: Lista de objetos JSON.
Ejemplo de Solicitud
Sección titulada «Ejemplo de Solicitud»Aquí tienes un ejemplo de cómo debería quedar el cuerpo de la solicitud en formato JSON. El primer contacto se identifica por erp_code: cambia su cargo, inactiva el WhatsApp anterior, agrega el nuevo y corrige el nombre de la fecha. El segundo se identifica por code y solo actualiza sus datos:
[ { "code": null, "client_id": "CLI-001", "first_name": "María", "second_name": "Fernanda", "first_last_name": "Gómez", "second_last_name": "Ríos", "position": "Gerente de Compras", "department": "Compras", "company_name": "Distribuciones El Norte S.A.S.", "relation": "Cliente", "observations": "Atiende de lunes a viernes en la mañana", "state": "Y", "erp_code": "ERP-CT-001", "details": [ { "type": 2, "value": "+573001234567", "label": null, "state": "N", "latitude": null, "longitude": null }, { "type": 2, "value": "+573109876543", "label": null, "state": "Y", "latitude": null, "longitude": null }, { "type": 4, "value": "1985-03-14", "label": "Cumpleaños", "state": "Y", "latitude": null, "longitude": null } ] }, { "code": 1024, "client_id": "CLI-001", "first_name": "Carlos", "second_name": null, "first_last_name": "Pérez", "second_last_name": null, "position": "Jefe de Bodega", "department": "Logística", "company_name": null, "relation": "Recibe mercancía", "observations": null, "state": "Y", "erp_code": null, "details": [] }]Ejemplo de Respuesta
Sección titulada «Ejemplo de Respuesta»{ "statusCode": 200, "message": "Contacts updated successfully"}{ "statusCode": 400, "errors": [ { "message": "Invalid JSON in request body" } ]}{ "statusCode": 415, "errors": [ { "message": "Content-Type: application/json is required" } ]}Errores globales (estructura del body)
Sección titulada «Errores globales (estructura del body)»Si el body no es un array:
{ "statusCode": 422, "errors": [ { "message": "Request body must be an array" } ]}Si el array está vacío:
{ "statusCode": 422, "errors": [ { "message": "Request body cannot be empty" } ]}Si excede el límite de 10,000 items:
{ "statusCode": 422, "errors": [ { "message": "Array exceeds maximum limit of 10000 items" } ]}Errores por item (validación de campos)
Sección titulada «Errores por item (validación de campos)»Los errores se agrupan por el índice del contacto en el array. Los errores de un medio de contacto indican su posición dentro de details en el campo, con la forma details[posición].campo:
{ "statusCode": 422, "errors": [ { "index": 0, "errors": [ { "field": "details", "message": "Field is required" } ] }, { "index": 1, "errors": [ { "field": "state", "message": "Value must be one of: Y, N" }, { "field": "details[0].value", "message": "Field must be a valid international phone number (e.g., +573001234567)" } ] } ]}Tipos de Errores de Validación por Campo
Sección titulada «Tipos de Errores de Validación por Campo»Errores de presencia y nulidad:
| Error | Descripción |
|---|---|
Field is required |
El campo no fue enviado en el objeto (la clave no existe). Aplica también a details |
Field cannot be null or empty |
El campo fue enviado con valor null o vacío y no acepta nulos |
Unknown field |
Se envió un campo que no existe en la configuración |
Item must be an object |
Un elemento del array, o de details, no es un objeto JSON |
Errores de details:
| Error | Descripción |
|---|---|
Field must be an array |
details no es un array |
Field must be a valid email address |
value de un type: 1 no es un correo válido |
Field must contain 7 to 15 digits, optionally prefixed with + and the country code |
value de un type: 2 tiene un formato distinto al permitido |
Field must be a valid international phone number (e.g., +573001234567) |
value de un type: 2 trae + pero el indicativo o la longitud no son posibles |
Fields latitude and longitude must be sent together |
En un type: 3 se envió solo una de las dos coordenadas |
Field must be between -90 and 90 |
latitude fuera de rango |
Field must be between -180 and 180 |
longitude fuera de rango |
Field must be a valid date (YYYY-MM-DD) |
value de un type: 4 no es una fecha válida |
Field cannot be null or empty for date details |
label vacío o nulo en un type: 4 |
Errores de tipo de dato:
| Error | Descripción |
|---|---|
Field must be a string |
El valor no es una cadena de texto |
Field must be of type integer |
El valor de type o de code no es un número entero |
Field must be a valid integer |
El valor de type o de code es un texto que no representa un entero |
Field must be of type decimal |
El valor no es un número decimal válido |
Field must be a valid decimal (e.g., 1.5, 10.25) |
El formato del decimal es inválido |
Field must be a valid decimal number |
El valor no es un número decimal válido (NaN, Infinity) |
Errores de longitud y rango:
| Error | Descripción |
|---|---|
Field exceeds maximum length of X characters |
La cadena excede la longitud máxima permitida |
Field exceeds maximum of X integer digits (precision: P, scale: S) |
La coordenada excede los dígitos enteros permitidos |
Field exceeds maximum of X decimal places |
La coordenada excede los decimales permitidos |
Field must be greater than or equal to 1 |
type es menor a 1 |
Field must be less than or equal to 4 |
type es mayor a 4 |
Errores de valores permitidos:
| Error | Descripción |
|---|---|
Value must be one of: Y, N |
El valor de state no está en la lista permitida |
Errores de formato:
| Error | Descripción |
|---|---|
Field contains forbidden characters. The following are not allowed: space, #, %, &, *, {, }, \, :, <, >, ?, /, +, . |
El campo client_id contiene caracteres prohibidos |
{ "statusCode": 423, "errors": [ { "message": "Resource is locked and cannot be accessed." } ]}Error de conexión a base de datos
Sección titulada «Error de conexión a base de datos»{ "statusCode": 500, "errors": [ { "message": "Error connecting to database" } ]}Error de operación en base de datos
Sección titulada «Error de operación en base de datos»{ "statusCode": 500, "errors": [ { "message": "Database operation failed" } ]}Error en Redis
Sección titulada «Error en Redis»{ "statusCode": 500, "errors": [ { "message": "Redis operation failed" } ]}Error inesperado
Sección titulada «Error inesperado»{ "statusCode": 500, "errors": [ { "message": "Unexpected error" } ]}Error del Servidor
Estos errores indican problemas internos en el servidor, la base de datos o el servicio de cache. Si persisten, contacta al equipo de soporte.

