Combinar listas de contactos en una nueva
/v1/lists/mergePara 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_fieldes ú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_fieldse 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:
maildaEMAIL, ysmsowsp,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
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}.nullmientras la lista no declara sus columnas. statusstring, enum: `awaiting_mapping | pending | processing | completed | failed`siempre presenteawaiting_mappingmientras la lista no declara sus columnas,pendingmientras espera su turno,processingmientras se lee el archivo, ycompletedofailedal 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.
nullhasta que se procesa. imported_row_countinteger | null- Filas que quedaron en la lista.
0si 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,zipo7z. No están en una combinación ni en una instantánea. source- En una instantánea:
dataset_id, el dataset leído, ysnapshot_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_valueoduplicated. 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 tienerepair_encoding, o detectadas y cargadas tal cual si no. error- Si la importación falló:
code, yfieldolinecuando 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 traelist_ideimport_id, que es la importación de la que salieron sus datos.nullen 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,PHONEoUNIQUECODE.nullen 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,updateoreplace.nullen 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.
nullen 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.
- Mismos campos que
GET /v1/lists/{id}/imports/{import_id}. - La importación de la lista nueva nace en estado
pending.list_ides la lista nueva yjob_idel trabajo que ejecuta la combinación, que se consulta enGET /v1/jobs/{id}.
Errores
| Código | Cuándo |
|---|---|
| 404 | Alguna de las listas no existe o fue eliminada (list_not_found). |
| 409 | Ya 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). |
| 422 | El 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). |
| 503 | No 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_policy | Tope |
|---|---|
discard, replace | Las listas suman hasta 20 millones de filas. |
fill, update | Filas 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.
- 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_countcuenta 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í quefailed_row_countes0y no hay archivo de rechazos.
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
}'
{
"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
}