Saltar al contenido principal

Combinar listas de contactos en una nueva

POST/v1/lists/merge

Para desarrolladores

Descripción​

Combina varias listas en una lista nueva, con todas sus columnas y una fila por contacto. Las listas de origen no cambian, salvo que pida eliminarlas.

La combinación es la importación de la lista nueva: queda en cola y la respuesta llega antes de que se lean los datos. El estado se consulta en la URL del header Location (GET /v1/lists/{id}/imports/{import_id}), igual que al subir un archivo.

Un contacto que está en varias listas se identifica y se resuelve como en un dataset, con los mismos valores de identity_field y collision_policy. La lista anterior en list_ids hace de lo ya guardado.

La lista nueva:

  • Tiene todas las columnas de las listas de origen, en el orden en que aparecen. Una fila de una lista sin esa columna la deja vacía.
  • Una columna es obligatoria solo si lo es en todas las listas. La columna de identity_field es única.
  • Su canal es la unión de los canales de las listas de origen.
  • Los valores no se vuelven a validar: cada fila ya pasó las reglas de su lista. Una fila sin valor en la columna de identity_field se conserva siempre.

Autenticación​

Authorizationbearer tokenheaderobligatorio
API key con scope list:write. Formato: Bearer <API_KEY>.
X-Instance-Slugstringheaderobligatorio
Identificador de su instancia. Ver Autenticación.

Request​

Body (application/json):

namestringobligatorio
Nombre de la lista nueva. No puede ser el de otra lista vigente, tampoco el de una lista de origen.
list_idsinteger[]obligatorio
De 2 a 10 listas, sin repetir, en el orden en que se combinan. Cada una tiene que tener datos.
identity_fieldstring, enum: `EMAIL | PHONE | UNIQUECODE`
El campo que identifica a un contacto. Si se omite, se deduce del canal de las listas: mail da EMAIL, y sms o wsp, PHONE. Es obligatorio cuando las listas tienen más de un canal o ninguno. La columna tiene que estar en todas las listas.
collision_policystring, enum: `discard | fill | update | replace`
Qué hacer con un contacto que está en varias listas. Default: fill.

Valores admitidos

discard
Conserva la fila de la primera lista en que aparece el contacto y descarta las de las listas siguientes.
fill
Conserva la fila de la primera lista y completa cada valor vacío con el de la primera lista siguiente que lo tenga.
update
Conserva la fila de la primera lista y reemplaza cada valor por el de la última lista que lo tenga. Un valor vacío en una lista siguiente no borra nada.
replace
Conserva la fila completa de la última lista en que aparece el contacto y descarta las de las listas anteriores.
delete_sourcesboolean
Si las listas de origen se eliminan cuando la combinación termina bien. Default: false.
descriptionstring
Descripción de la lista nueva.

Response​

201 CreatedDevuelve el objeto creado. El header Location trae su URL (ver Headers).
idintegersiempre presente
Identificador de la importación.
list_idintegersiempre presente
Lista a la que pertenece.
job_idstring (UUID) | null
Trabajo que ejecuta la importación; su estado se consulta en GET /v1/jobs/{id}. null mientras la lista no declara sus columnas.
statusstring, enum: `awaiting_mapping | pending | processing | completed | failed`siempre presente
awaiting_mapping mientras la lista no declara sus columnas, pending mientras espera su turno, processing mientras se lee el archivo, y completed o failed al terminar.
file_namestring | null
Nombre que tenía el archivo al subirlo.
file_bytesinteger | null
Tamaño del archivo tal como se subió, en bytes.
encodingstring | null
Codificación del archivo: la detectada en sus primeras líneas hasta que se procesa, y después la que se decidió sobre el archivo completo (utf-8, utf-16, utf-32, cp1252).
delimiterstring | null
Separador de columnas: el indicado al subirlo o el detectado.
csv_row_countinteger | null
Filas leídas del archivo, sin contar la cabecera ni las filas en blanco. En una combinación, las leídas de las listas; en una instantánea, las del dataset. null hasta que se procesa.
imported_row_countinteger | null
Filas que quedaron en la lista. 0 si la importación falló.
failed_row_countinteger | null
Filas descartadas por un valor inválido, un campo obligatorio vacío, columnas de más o caracteres que no corresponden a la codificación.
duplicated_row_countinteger | null
Filas descartadas por repetir el valor de una columna única. En una combinación, las de un contacto que ya estaba en una lista anterior; en una instantánea, las filas más antiguas de un contacto que el dataset tiene repetido.
has_rejectsbooleansiempre presente
Si hay un archivo con las filas descartadas para descargar (GET /v1/lists/{id}/imports/{import_id}/rejects).
error_messagestring | null
Por qué falló la importación, si falló (en inglés).
diagnosticsobject | null
Detalle de la importación, descrito abajo.
encoding, format
La codificación con que se leyó el archivo y su formato: plain, gzip, zip o 7z. No están en una combinación ni en una instantánea.
source
En una instantánea: dataset_id, el dataset leído, y snapshot_at, el momento en que se leyó (UTC).
reasons
Filas descartadas por motivo. Cada fila cuenta una vez, con el primer motivo que encontró: invalid_character, extra_columns, required_missing, invalid_value o duplicated.
fields
Por field_key, cuántas filas tenían ese campo vacío siendo obligatorio, inválido o repetido. Una fila con dos campos inválidos cuenta en los dos.
repaired_rows / damaged_text_rows
Filas con texto dañado por una conversión de codificación anterior (José): reparadas si la lista tiene repair_encoding, o detectadas y cargadas tal cual si no.
error
Si la importación falló: code, y field o line cuando el problema tiene un lugar en el archivo.
source_listsobject[] | null
En una combinación (POST /v1/lists/merge), las listas que se combinaron, en orden. Cada una trae list_id e import_id, que es la importación de la que salieron sus datos. null en una importación de archivo o en una instantánea.
identity_fieldstring | null
En una combinación o en una instantánea, el campo que identifica a un contacto: EMAIL, PHONE o UNIQUECODE. null en una importación de archivo.
collision_policystring | null
En una combinación, cómo se resolvió un contacto que estaba en varias listas: discard, fill, update o replace. null en una importación de archivo o en una instantánea.
delete_sourcesboolean | null
En una combinación, si las listas de origen se eliminan al terminar. null en una importación de archivo o en una instantánea.
created_atstring (date-time)siempre presente
Cuándo se subió el archivo (ISO 8601, UTC).
started_atstring (date-time) | null
Cuándo empezó a leerse.
finished_atstring (date-time) | null
Cuándo terminó, haya completado o fallado.
Notas

Errores​

CódigoCuándo
404Alguna de las listas no existe o fue eliminada (list_not_found).
409Ya existe una lista vigente con ese nombre (list_name_taken). Una lista todavía no tiene datos (list_has_no_data). Una columna corresponde a un campo desactivado (list_field_inactive). El canal de las listas no define cómo identificar a un contacto y no se indicó identity_field (list_identity_field_required). A una lista le falta la columna de identity_field (list_identity_field_missing).
422El body no es válido: menos de 2 o más de 10 listas, una lista repetida, o un valor fuera de los admitidos. También con errors[].code list_merge_too_large en /lists (ver Tamaño máximo, más abajo).
503No se pudo dejar la combinación en cola (service_unavailable). No queda nada creado: reintente.

Tamaño máximo (422 list_merge_too_large):

collision_policyTope
discard, replaceLas listas suman hasta 20 millones de filas.
fill, updateFilas por columnas de la lista nueva, hasta 50 millones: con 15 columnas son 3,3 millones de filas.

errors[].params trae rows (las filas que suman las listas) y max_rows (las que admite esta combinación). Nada se crea.

Detalle completo en Errores genéricos.

Notas
  • Una combinación que falla no toca las listas de origen y deja la lista nueva sin datos. Las listas de origen se eliminan, si se pidió, en el mismo momento en que la lista nueva recibe sus datos, y cada eliminación queda en el log de actividad a nombre de quien pidió la combinación.
  • Una lista de origen que se elimina mientras la combinación espera su turno se combina igual.
  • duplicated_row_count cuenta las filas de un contacto que ya estaba en una lista anterior: csv_row_count = imported_row_count + duplicated_row_count. Una combinación no descarta filas por otro motivo, así que failed_row_count es 0 y no hay archivo de rechazos.
Request
curl -X POST "https://$API_HOST/v1/lists/merge" \
-H "Authorization: Bearer $API_KEY" \
-H "X-Instance-Slug: $SLUG" \
-H "Content-Type: application/json" \
-d '{
"name": "Clientes marzo y abril",
"list_ids": [
4,
7
],
"collision_policy": "fill",
"delete_sources": true
}'
Response
{
"id": 31,
"list_id": 12,
"job_id": "01a13f6e-fa08-7e2a-8b3d-5f6a7b8c9d0e",
"status": "pending",
"file_name": null,
"file_bytes": null,
"encoding": null,
"delimiter": null,
"csv_row_count": null,
"imported_row_count": null,
"failed_row_count": null,
"duplicated_row_count": null,
"has_rejects": false,
"error_message": null,
"diagnostics": null,
"source_lists": [
{
"list_id": 4,
"import_id": 17
},
{
"list_id": 7,
"import_id": 22
}
],
"identity_field": "EMAIL",
"collision_policy": "fill",
"delete_sources": true,
"created_at": "2026-10-15T12:00:00Z",
"started_at": null,
"finished_at": null
}