---
title: "Importar un lote de contactos (máx 500). Preserva user_ns y line_id, y no toca uChat. `apply_tags` etiqueta todas las filas del lote; `on_existing` define qué pasa con los que ya existen (fill = rellenar vacíos, por defecto; overwrite = manda el archivo; skip = no tocarlos; registration = solo avanzar la misma sesión de alta). Las etiquetas siempre se suman a las que el contacto ya tenía."
method: POST
path: "/contacts/import"
tags: ["Contacts"]
---

# Importar un lote de contactos (máx 500). Preserva user_ns y line_id, y no toca uChat. \`apply_tags\` etiqueta todas las filas del lote; \`on_existing\` define qué pasa con los que ya existen (fill = rellenar vacíos, por defecto; overwrite = manda el archivo; skip = no tocarlos; registration = solo avanzar la misma sesión de alta). Las etiquetas siempre se suman a las que el contacto ya tenía.

`POST /contacts/import`

## Request

- Base URL: `https://api.met.meteor.com.co/api/v1`
- URL: `https://api.met.meteor.com.co/api/v1/contacts/import`
- Auth: one of:
  - `bearer` (a scheme the document does not define)
  - HTTP bearer

El lote tope **500 filas**. Lo que decide el resultado es `on_existing`: `fill` (por defecto) solo rellena lo que estaba vacío, `overwrite` deja mandar al archivo y `skip` no toca a los que ya existen. `registration` crea teléfonos nuevos y, para uno existente, solo acepta una etapa de la misma `registration_source` + `registration_id`, sin retrocesos y mientras la sesión siga abierta. Una reinscripción se descarta completa. Las etiquetas de `apply_tags` **siempre se suman**, nunca reemplazan las que el contacto ya tenía. Si una fila trae `line_id`, se valida contra las líneas WhatsApp del workspace y se conserva como metadato de origen/emisión. A diferencia de `POST /contacts`, no crea suscriptores en el CRM externo. `line_id` es metadato de origen/emisión y no divide la identidad: el mismo teléfono importado por dos líneas actualiza una sola ficha.

## Request body

- ImportContactsDto
  - `apply_tags` string[]: Etiquetas que se aplican a TODAS las filas del lote, además de las que traiga la columna `tags` de cada fila. Es la acción masiva del import: el archivo del cliente casi nunca trae una columna de etiquetas, y sin esto la única forma de etiquetar lo importado era abrir contacto por contacto.
  - `contacts` ImportContactRow[], required
    - `custom` object: Campos personalizados del workspace, con su `field_key` PELADO como clave (`{ etapa: 'Nuevo', monto: '6300000' }`) — la convención de `items.data`: sistema con `$`, personalizados sin nada. Existe porque el archivo del cliente casi nunca trae las columnas con nuestros nombres: el frontend mapea sus encabezados a campos y manda acá lo que no es de sistema. Solo se aceptan claves que YA existen como field-definition del workspace; el resto se descarta (importBatch valida).
    - `email` string
    - `first_name` string
    - `gender` string
    - `image` string
    - `last_message_at` string
    - `last_name` string
    - `line_id` string: Línea de WhatsApp (phone_number_id de Meta) de origen o emisión. Cuando viene se valida, pero no divide la identidad: un teléfono conserva una sola ficha global dentro del workspace.
    - `locale` string
    - `name` string
    - `phone` string
    - `registration_complete` boolean: Cierra la sesión: eventos posteriores de registro ya no pueden tocarla.
    - `registration_id` string: Identificador estable de una misma alta (por ejemplo, el id de AveOnline).
    - `registration_stage` number: Posición monotónica de la etapa dentro de esa alta.
    - `status` string
    - `summary` string
    - `tags` string
    - `user_ns` string
  - `on_existing` 'fill' | 'overwrite' | 'skip' | 'registration': Política para los contactos que ya existen. Default `fill`.
  - `registration_source` string: Namespace de la fuente cuando `on_existing=registration`.

## Response `201`

- object: Sobre en el que viaja toda respuesta correcta de la API. El recurso está en `data`. Los SDKs oficiales lo desenvuelven por ti; un cliente hecho a mano tiene que leer `.data`.
  - `success` true, required: Siempre `true` en una respuesta 2xx.
  - `data` ContactImportResultDto, required
    - `created` number, required
    - `errors` ContactImportErrorDto[], required
      - `reason` string, required
      - `row` number, required: Posición de la fila dentro del array `contacts` que mandaste (base 0).
    - `skipped` number, required
    - `updated` number, required: Existían y se les rellenaron los campos vacíos (merge fill-only).

## Other responses

- `400`: La request no es válida: un campo no pasa validación, falta un parámetro requerido o el recurso no admite la transición solicitada.
- `401`: API key ausente, inválida, revocada o expirada — o el workspace está bloqueado.
- `403`: La key está autenticada pero no puede ejecutar esta operación: scope faltante, capacidad deshabilitada, modo test restringido o recurso fuera de su cartera.
- `404`: El recurso no existe o no está disponible dentro del alcance de la key. No revela la existencia de recursos de otros tenants.
- `409`: La operación entra en conflicto con el estado actual o con un Idempotency-Key en uso. No reintentes con el mismo key y un body distinto.
- `429`: Se superó el límite por minuto de la key o la cuota del plan. Respeta `Retry-After`; el SDK ya reintenta solo.
- `500`: Error del servidor o del Met que ejecutaba. El SDK reintenta los 5xx con backoff.

---

[API](https://skmtc.dev/meteor/apis/met-public-api.md) · [All operations](https://skmtc.dev/meteor/apis/met-public-api/llms.txt) · [OpenAPI document](https://skmtc.dev/meteor/apis/met-public-api/revisions/fc6d3aad75de?raw)
