Factuarea APIDevelopers

Importaciones de contactos

Previsualiza archivos de contactos, consulta resultados confirmados por fila y descarga informes de errores autorizados.

Previsualiza antes de escribir

Envía el archivo a POST /v1/contacts/import/preview e impórtalo después con POST /v1/contacts/import usando un nuevo Idempotency-Key. Ambos requieren contacts:write. HTTP admite CSV, TXT, XLSX y XLS hasta 10 MB; MCP preview_contacts_import e import_contacts admiten CSV base64 hasta 10 MB. Esta actualización no añade ODS a estos contratos públicos de subida.

La previsualización conserva las clasificaciones planificadas create, update, add_role, merge_candidate, conflict e invalid. Resuelve primero los conflictos de identidad fiscal. Una actualización conserva los campos omitidos en el archivo: omitir bank_accounts conserva las cuentas y un [] explícito las vacía. dry_run=true siempre devuelve HTTP 200 sin reservar ni consumir filas; import_uuid, el status de ejecución y los contadores son null.

Rellena la plantilla descargada

Descarga la plantilla de contactos con GET /v1/contacts/import/template (contacts:read), conserva sus cabeceras y escribe un contacto por fila de datos. El CSV descargado usa UTF-8 con BOM y comas. Si conviertes la plantilla a XLSX, conserva sus cabeceras originales. Sube el archivo rellenado, revisa la correspondencia de columnas y previsualiza las filas antes de aplicar la importación.

Una plantilla que sólo contiene cabeceras es válida para previsualizar: HTTP devuelve 200, total=0, rows=[] y source_headers en el orden original. Las columnas vacías se conservan, también cuando una hoja no tiene filas de datos. dry_run=true se comporta igual y no crea un registro de importación.

Aplicar un archivo sin filas de datos devuelve HTTP 422: error.code=business_rule_violation, error.subcode=empty_import y error.param=file. Rellena la plantilla y vuelve a intentarlo. No se crea un registro de importación ni se encola trabajo. Las herramientas MCP conservan la misma distinción entre previsualizar y aplicar; estos códigos de estado corresponden a HTTP.

Consulta la importación aceptada

Se cuentan registros CSV lógicos, incluidos los registros entrecomillados con saltos de línea. HTTP ejecuta hasta 199 registros de forma síncrona con 200; 200 o más se aceptan con 202 y queued=true. Ambos caminos devuelven import_uuid. Las respuestas encoladas tienen status=queued y contadores de ejecución null; aceptar no significa que todas las filas hayan terminado. MCP devuelve el mismo payload JSON; 200/202 son códigos del transporte HTTP.

Usa GET /v1/contacts/imports/{id}, pasando el import_uuid recibido como id. Requiere contacts:read y devuelve object=contact_import, entity_type=business_contacts, el estado persistido, contadores y outcomes. La empresa procede de la credencial autenticada. Los UUID de otra empresa, inexistentes o de otro módulo devuelven el mismo 404 import_not_found; sin scope de lectura devuelve 403 insufficient_scope.

CampoSignificado
total_rows / totalRegistros de origen en GET y en las respuestas de preview/síncronas. El payload inmediato encolado conserva total=0; consulta el total aceptado con GET.
added_countFilas aplicadas create, update y add_role confirmadas.
skipped_count / failed_countFilas omitidas o rechazadas confirmadas.
unprocessed_countRegistros de origen sin un resultado confirmado.
status / failure_reasonEstado persistido real, incluidos los trabajos fallidos que conservan progreso parcial.

Una importación terminal puede tener status=failed aunque failed_count=0: la infraestructura o el mantenimiento pueden cerrar un trabajo con escrituras confirmadas y filas pendientes. La respuesta síncrona usa ese mismo estado persistido. Su total conserva los registros de origen, pero rows y las categorías incluyen sólo filas confirmadas; cada una incluye result como applied, skipped o failed. Las filas de previsualización omiten result.

Por ejemplo, el mantenimiento cerró esta importación síncrona después de una fila confirmada. La fila pendiente no se presenta como aplicada:

{
  "data": {
    "rows": [
      {
        "row": 2,
        "action": "create",
        "result": "applied",
        "target_uuid": "0198f4d1-a492-7e05-9a35-000000000001",
        "errors": [],
        "warnings": []
      }
    ],
    "source_headers": ["name", "tax_id", "roles"],
    "total": 2,
    "create": 1,
    "update": 0,
    "add_role": 0,
    "merge_candidate": 0,
    "conflict": 0,
    "invalid": 0,
    "dry_run": false,
    "queued": false,
    "import_uuid": "0198f4d1-a492-7e05-9a35-000000000201",
    "added_count": 1,
    "skipped_count": 0,
    "failed_count": 0,
    "unprocessed_count": 1,
    "status": "failed",
    "failure_reason": "stale_timeout"
  }
}

Descarga los diagnósticos originales

GET /v1/contacts/imports/{id}/errors.csv requiere contacts:read y devuelve bytes CSV UTF-8 con BOM y las cabeceras row_number,field,code,message. Conserva la coordenada del origen: CSV usa el número de registro lógico con cabecera=1; las hojas de cálculo usan el índice físico de fila. Un informe ausente devuelve 404 import_not_found.

Los informes están disponibles para importaciones terminales durante la retención configurada, 90 días por defecto. El estado deja de anunciar error_report_url al vencer, incluso antes de la limpieza física. Si falta el CSV o no se puede leer, los diagnósticos confirmados lo reconstruyen sin escribir otro archivo. Las importaciones sin diagnósticos de fila no tienen informe de errores.

En MCP, usa get_contact_import para consultar el progreso y download_contact_import_errors para recibir id, filename, mime_type, hash y file_base64. Ambos requieren contacts:read; los bytes descodificados coinciden con HTTP y hash es SHA-256. Las descargas requieren autenticación y no generan URL anónimas.

Cuota mensual de filas

Las nuevas admisiones de contactos comparten la cuota mensual de filas de importación del plan. Las filas aplicadas create, update y add_role la consumen; las omitidas, rechazadas y pendientes no. Las reservas concurrentes protegen la cuota antes de escribir o encolar. Las importaciones admitidas bajo la exención anterior de contactos la conservan.

Una cuota agotada devuelve HTTP 429 import_row_quota_exceeded, con tipo de error rate_limit_error, antes de escribir contactos o encolar. Esta cuota es independiente de los bytes subidos y de los límites de peticiones HTTP.

Operaciones relacionadas

En esta página

¿Te echamos una mano?Contactar con soporte