Connect

Sincronizar conexión SII

Sincroniza los alcances solicitados (rcv, boletas, guias, boletas_honorarios, documentos, f29) para un período en una sola sesión.

Tool IDsii.conexion.sincronizar
Nombre MCPsii__conexion__sincronizar
Conectorsii
Planoread
Alcancesrcv, boletas, guias, boletas_honorarios, documentos, carpeta_tributaria, f29
Scope (permiso)sii:read
Authconnection_credentials
Versión10
Sensiblesí
Deprecadono
ComportamientoreadOnly=false, destructive=false, idempotent=true, openWorld=true

Requiere conexión. Indica cuál en cada llamada: header X-Connect-Connection en REST, campo connectionId en el execute_write de MCP y en las opciones del SDK. No hay resolución implícita, ni siquiera con una sola conexión activa: la conexión es la empresa. El id sale de conexiones.estado.consultar.

Qué hace

En la prueba solo se cargan los 3 meses más recientes; los anteriores requieren un plan activo. Guías: solo los últimos 6 meses.

Entrada

CampoTipoRequeridoDescripción
periodostring ^\d{4}-\d{2}$síEl mes que se va a sincronizar, en formato AAAA-MM y en calendario chileno (por ejemplo '2026-07'). Traer varios meses son varias llamadas, una por mes.
alcanceslista de "rcv" · "boletas" · "guias" · "boletas_honorarios" · "documentos" · "carpeta_tributaria" · …síQué módulos de datos traer en esta corrida, al menos uno. Todos se sincronizan sobre UNA sola sesión, así que pedir varios en una llamada cuesta menos que llamar una vez por cada uno. Un alcance debe estar habilitado en la conexión; si no lo está, la llamada responde 'alcance_not_enabled'.
collectionRequestIdstring ^ctr_.*noSolicitud puntual autorizada; solo para el worker de carpeta tributaria.
JSON Schema de entrada
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "periodo": {
      "type": "string",
      "pattern": "^\\d{4}-\\d{2}$",
      "description": "El mes que se va a sincronizar, en formato AAAA-MM y en calendario chileno (por ejemplo '2026-07'). Traer varios meses son varias llamadas, una por mes."
    },
    "alcances": {
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "rcv",
          "boletas",
          "guias",
          "boletas_honorarios",
          "documentos",
          "carpeta_tributaria",
          "f29"
        ]
      },
      "description": "Qué módulos de datos traer en esta corrida, al menos uno. Todos se sincronizan sobre UNA sola sesión, así que pedir varios en una llamada cuesta menos que llamar una vez por cada uno. Un alcance debe estar habilitado en la conexión; si no lo está, la llamada responde 'alcance_not_enabled'."
    },
    "collectionRequestId": {
      "description": "Solicitud puntual autorizada; solo para el worker de carpeta tributaria.",
      "type": "string",
      "pattern": "^ctr_.*"
    }
  },
  "required": [
    "periodo",
    "alcances"
  ]
}

Ejemplo

curl
curl -X POST https://connect.emisso.ai/api/v1/tools/sii.conexion.sincronizar/execute \
  -H "Authorization: Bearer connect_sk_…" \
  -H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
  -H "Content-Type: application/json" \
  -d '{"input":{"periodo":"2026-07","alcances":["rcv","boletas"]}}'
SDK TypeScript
const data = await connect.tools.sii.conexion.sincronizar({ periodo: "2026-07", alcances: ["rcv", "boletas"] }, { connectionId: "conn_9tKfR2mQx4Vb" });
MCP · meta-tool execute
{
  "tool": "sii.conexion.sincronizar",
  "params": {
    "periodo": "2026-07",
    "alcances": [
      "rcv",
      "boletas"
    ]
  },
  "connectionId": "conn_9tKfR2mQx4Vb"
}

Salida esperada (200):

{
  "data": {
    "periodo": "2026-07",
    "estado": "encolado",
    "jobId": "sjb_9f2kc0q8w1m4x7t3p6b5d",
    "yaEnCurso": false
  },
  "meta": {
    "request_id": "req_…",
    "tool_id": "sii.conexion.sincronizar",
    "plane": "read",
    "latency_ms": 58240,
    "audit_status": "recorded"
  }
}

Todos los alcances pedidos comparten una sola sesión contra el SII: un login al empezar y un logout al final. Los contadores adicionales varían por alcance; 'boletas' solo reporta 'recordsSynced'.

Salida

CampoTipoRequeridoDescripción
periodostringsíEco del período que se pidió, para poder correlacionar la respuesta sin guardarlo tú.
estado"encolado" · "completado"sí'encolado' = la sincronización quedó en cola y va a empezar enseguida; esta respuesta NO trae datos todavía, y el trabajo se sigue por 'jobId'. 'completado' = la sincronización ya corrió y su resumen por alcance viene en 'results'. Un cliente recibe siempre 'encolado': un sync abre una sesión real contra el sistema externo y puede tardar minutos, así que no se te hace esperar por él.
jobIdstringnullno
yaEnCursobooleanono'true' significa que ya había una sincronización viva para esa conexión y ese período, y que 'jobId' es la de ella. No es un error ni un rechazo: pedir dos veces el mismo período es inofensivo y te devuelve el trabajo que ya está andando. Ojo con el otro lado: 'false' NO garantiza que la hayas creado tú: dos llamadas a la vez pueden recibir las dos 'false' y el MISMO 'jobId'. Lo que sí vale siempre es que hay una sola sincronización activa por conexión y período, así que el 'jobId' que recibes es el trabajo que cubre tu pedido, lo hayas encolado tú o no.
resultslista de objetonoEl resumen por alcance, una fila por alcance sincronizado. AUSENTE cuando 'estado' es 'encolado': el trabajo todavía no corrió. Ausente no es lo mismo que vacío: un arreglo vacío significaría que se miró y no había nada.
results[].alcancestringsíCuál de los alcances pedidos describe esta fila. Hay una fila por alcance solicitado, en el orden canónico del conector, no en el orden en que los pediste.
results[].marcadorstringnoDetalle técnico, cuando el conector pudo componer uno. En una fila que falló dice en qué paso ocurrió y qué se encontró (conteos, status HTTP, content-type); en una que terminó incompleta, qué no se pudo cubrir. Sirve para diagnosticar sin volver a reproducirlo, y nunca contiene datos del contribuyente.
results[].status"ok" · "partial" · "failed"sí'ok' = el alcance terminó bien; que 'recordsSynced' sea 0 no lo vuelve un fallo. 'partial' = trajo datos pero alguna casilla quedó incompleta, y 'incompletos' dice cuántas: lo sincronizado sirve, y reintentar el mismo período más tarde puede completarlo. 'failed' = no terminó bien, y la causa va en 'error'; mira igual 'recordsSynced', porque un 'failed' no garantiza que no se haya escrito nada. Y revisa fila por fila: un alcance puede fallar mientras los otros de la misma corrida terminan bien.
results[].recordsSyncedenterosíCuántos registros de este alcance escribió ESTA corrida. Es el trabajo de esta llamada, no el total acumulado que tienes guardado: para saber cuánto hay, consulta. Un 0 no significa por sí solo «no hay datos»; cuando el cero tiene una explicación, viene en 'detalle'.
results[].incompletosenteronoCuántas casillas de este alcance quedaron sin traer. Es lo que vuelve 'partial' al status: lo sincronizado sirve, y reintentar el mismo período más tarde puede completarlo. Una casilla legítimamente vacía no cuenta.
results[].completobooleanono'true' sólo si ninguna casilla de este alcance falló. No alcanza por sí solo para dar el período por cerrado: revísalo junto con 'reconMismatches' y 'filasDescartadas', porque un documento puede faltar por esas dos vías sin que 'completo' se entere.
results[].reconMismatchesenteronoVeces que las filas del detalle no coincidieron con el total que el resumen del SII declaraba. Es observabilidad y no detiene el sync, pero un valor distinto de 0 dice que el período puede estar incompleto.
results[].dedupCollisionsenteronoCuántas filas llegaron repetidas dentro de esta misma corrida (misma clave natural) y se colapsaron en una. No se cuentan dos veces en 'recordsSynced'.
results[].filasDescartadasenteronoFilas que llegaron con una forma inesperada (sin tipo ni folio resoluble) y no se pudieron guardar. Un valor distinto de 0 significa que el alcance corrió entero pero se perdieron filas, aunque 'completo' diga 'true'.
results[].fueraDeVentanaenteronoSólo en 'guias': cuántas direcciones cayeron fuera de la ventana de 6 meses que el SII conserva. No es una falla y el status igual sale 'ok', pero es lo único que distingue 'no había guías' de 'no pudimos verlas'. Reintentar no lo arregla.
results[].diferidosenteronoSólo en 'rcv': cuántos grupos (estado y tipo de documento) superaron el límite del detalle en línea del SII, unos 1.000 documentos, y se bajaron completos como archivo. No es una falla: esos documentos están guardados.
results[].totalesenteronoSólo en 'rcv': cuántos totales del mes se guardaron (boletas, comprobantes de pago con tarjeta y otros tipos que el SII informa sólo como total, no documento por documento). Se leen con 'sii.rcv_totales.consultar'.
results[].agregadosEnDetalleenteronoSólo en 'rcv': filas del detalle con forma de total del mes (sin fecha ni razón social) en un tipo que el SII declaró como documentos. No debería pasar; si es distinto de 0, avísale a soporte.
results[].incompletosPorMotivolista de objetonoSólo en 'rcv', y siempre en ese alcance aunque quede vacía: el porqué de las casillas que cuenta 'incompletos'. La suma de 'casillas' es 'incompletos'.
results[].incompletosPorMotivo[].motivostringsíPor qué no se trajeron. Estable: 'presupuesto' y 'tope' (se acabó el tiempo; el próximo sync lo reintenta), 'recaptcha', 'detalle_vacio', 'resumen_<código>', 'filas_no_calzan', 'csv_<motivo>', 'transporte', 'tipo_solo_resumen_<tipo>' (un tipo que el SII solo informa totalizado, por ejemplo 48), entre otros. La lista es abierta.
results[].incompletosPorMotivo[].casillasenterosíCuántas casillas quedaron sin traer por ese motivo.
results[].perspectivasFallidaslista de objetonoEn 'guias' y 'boletas_honorarios': qué direcciones fallaron, con su código de error. Esos dos alcances la emiten siempre, aunque quede vacía; ningún otro la emite.
results[].perspectivasFallidas[].perspectiva"emitidas" · "recibidas"síQué lado falló: 'emitidas' son las que emitió esta empresa y 'recibidas' las que le emitieron.
results[].perspectivasFallidas[].codestringsíEl código del catálogo de errores que explica por qué falló ese lado. Decide por el código, nunca por el texto.
results[].totalenteronoSólo en 'documentos': cuántos DTE anunció el índice del SII para el período. Es el conteo CRUDO del portal, con sus repetidos, así que restarle 'documentos' NO da el hueco. Para eso está 'faltantes'.
results[].ventanasenteronoSólo en 'documentos': cuántas ventanas de descarga (hasta 20 folios cada una) hicieron falta para bajar el período.
results[].ventanasRechazadasenteronoSólo en 'documentos': cuántas ventanas de descarga rechazó el portal. Lo que sí bajó se guarda igual y el período sale 'partial'; el detalle del rechazo viaja en 'marcador'.
results[].documentosenteronoSólo en 'documentos': cuántos DTE se descargaron de verdad. El hueco es 'faltantes'; la resta contra 'total' NO lo da, porque 'total' viene con los repetidos del portal.
results[].faltantesenteronoSólo en 'documentos': cuántos DTE prometió el índice y la descarga no trajo. Es lo que distingue un hueco del SII de un hueco nuestro; lo que sí bajó se guarda igual.
results[].sinIndiceenteronoSólo en 'documentos': cuántos DTE se descargaron sin que su clave apareciera en el índice del listado. Significa que el índice quedó corto, distinto de que la fila no trajera estado (eso llega como 'estado' en null).
results[].hashMismatchesenteronoSólo en 'documentos': cuántos documentos repetidos traían un XML distinto. Un DTE firmado es inmutable, así que un valor distinto de 0 es una anomalía para reportar, nunca un documento que cambió.
results[].declaracionesenteronoSólo en 'f29': cuántas declaraciones vigentes muestra el SII en su grilla, que cubre el año en curso y los seis anteriores. El período pedido no la acota: el F29 se revisa entero.
results[].nuevasenteronoSólo en 'f29': cuántas declaraciones se leyeron completas en esta corrida por primera vez.
results[].pendientesenteronoSólo en 'f29': cuántas declaraciones quedaron sin leer (por tiempo o porque su formulario no se pudo leer). Se retoman solas en la revisión siguiente; un valor distinto de 0 vuelve 'partial' el status.
results[].errorstringnoPor qué este alcance no terminó bien. Presente solo cuando 'status' es 'failed'. Normalmente es un código del catálogo de errores; cuando el sistema externo truncó el listado es una etiqueta de resultado ('movimientos_truncated', 'cartolas_truncated') que no está en ese catálogo y que significa «se escribió lo que alcanzó a venir». Decide por el valor, nunca por el texto libre.
JSON Schema de salida
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "periodo": {
      "type": "string",
      "description": "Eco del período que se pidió, para poder correlacionar la respuesta sin guardarlo tú."
    },
    "estado": {
      "type": "string",
      "enum": [
        "encolado",
        "completado"
      ],
      "description": "'encolado' = la sincronización quedó en cola y va a empezar enseguida; esta respuesta NO trae datos todavía, y el trabajo se sigue por 'jobId'. 'completado' = la sincronización ya corrió y su resumen por alcance viene en 'results'. Un cliente recibe siempre 'encolado': un sync abre una sesión real contra el sistema externo y puede tardar minutos, así que no se te hace esperar por él."
    },
    "jobId": {
      "description": "El identificador de la sincronización encolada. Por la API REST, el avance se consulta en 'GET /v1/syncs/{jobId}'; por MCP, búscalo en 'trabajos' de 'conexiones.estado.consultar' y revisa 'datosListos' ahí mismo. Es el mismo id que viaja en el webhook 'sync.completed' o 'sync.failed' si tu plan los incluye. Es null cuando 'estado' es 'completado': ahí el resultado ya está en la respuesta y no hay nada que seguir.",
      "anyOf": [
        {
          "type": "string"
        },
        {
          "type": "null"
        }
      ]
    },
    "yaEnCurso": {
      "description": "'true' significa que ya había una sincronización viva para esa conexión y ese período, y que 'jobId' es la de ella. No es un error ni un rechazo: pedir dos veces el mismo período es inofensivo y te devuelve el trabajo que ya está andando. Ojo con el otro lado: 'false' NO garantiza que la hayas creado tú: dos llamadas a la vez pueden recibir las dos 'false' y el MISMO 'jobId'. Lo que sí vale siempre es que hay una sola sincronización activa por conexión y período, así que el 'jobId' que recibes es el trabajo que cubre tu pedido, lo hayas encolado tú o no.",
      "type": "boolean"
    },
    "results": {
      "description": "El resumen por alcance, una fila por alcance sincronizado. AUSENTE cuando 'estado' es 'encolado': el trabajo todavía no corrió. Ausente no es lo mismo que vacío: un arreglo vacío significaría que se miró y no había nada.",
      "type": "array",
      "items": {
        "type": "object",
        "properties": {
          "alcance": {
            "type": "string",
            "description": "Cuál de los alcances pedidos describe esta fila. Hay una fila por alcance solicitado, en el orden canónico del conector, no en el orden en que los pediste."
          },
          "marcador": {
            "description": "Detalle técnico, cuando el conector pudo componer uno. En una fila que falló dice en qué paso ocurrió y qué se encontró (conteos, status HTTP, content-type); en una que terminó incompleta, qué no se pudo cubrir. Sirve para diagnosticar sin volver a reproducirlo, y nunca contiene datos del contribuyente.",
            "type": "string"
          },
          "status": {
            "type": "string",
            "enum": [
              "ok",
              "partial",
              "failed"
            ],
            "description": "'ok' = el alcance terminó bien; que 'recordsSynced' sea 0 no lo vuelve un fallo. 'partial' = trajo datos pero alguna casilla quedó incompleta, y 'incompletos' dice cuántas: lo sincronizado sirve, y reintentar el mismo período más tarde puede completarlo. 'failed' = no terminó bien, y la causa va en 'error'; mira igual 'recordsSynced', porque un 'failed' no garantiza que no se haya escrito nada. Y revisa fila por fila: un alcance puede fallar mientras los otros de la misma corrida terminan bien."
          },
          "recordsSynced": {
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991,
            "description": "Cuántos registros de este alcance escribió ESTA corrida. Es el trabajo de esta llamada, no el total acumulado que tienes guardado: para saber cuánto hay, consulta. Un 0 no significa por sí solo «no hay datos»; cuando el cero tiene una explicación, viene en 'detalle'."
          },
          "incompletos": {
            "description": "Cuántas casillas de este alcance quedaron sin traer. Es lo que vuelve 'partial' al status: lo sincronizado sirve, y reintentar el mismo período más tarde puede completarlo. Una casilla legítimamente vacía no cuenta.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "completo": {
            "description": "'true' sólo si ninguna casilla de este alcance falló. No alcanza por sí solo para dar el período por cerrado: revísalo junto con 'reconMismatches' y 'filasDescartadas', porque un documento puede faltar por esas dos vías sin que 'completo' se entere.",
            "type": "boolean"
          },
          "reconMismatches": {
            "description": "Veces que las filas del detalle no coincidieron con el total que el resumen del SII declaraba. Es observabilidad y no detiene el sync, pero un valor distinto de 0 dice que el período puede estar incompleto.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "dedupCollisions": {
            "description": "Cuántas filas llegaron repetidas dentro de esta misma corrida (misma clave natural) y se colapsaron en una. No se cuentan dos veces en 'recordsSynced'.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "filasDescartadas": {
            "description": "Filas que llegaron con una forma inesperada (sin tipo ni folio resoluble) y no se pudieron guardar. Un valor distinto de 0 significa que el alcance corrió entero pero se perdieron filas, aunque 'completo' diga 'true'.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "fueraDeVentana": {
            "description": "Sólo en 'guias': cuántas direcciones cayeron fuera de la ventana de 6 meses que el SII conserva. No es una falla y el status igual sale 'ok', pero es lo único que distingue 'no había guías' de 'no pudimos verlas'. Reintentar no lo arregla.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "diferidos": {
            "description": "Sólo en 'rcv': cuántos grupos (estado y tipo de documento) superaron el límite del detalle en línea del SII, unos 1.000 documentos, y se bajaron completos como archivo. No es una falla: esos documentos están guardados.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "totales": {
            "description": "Sólo en 'rcv': cuántos totales del mes se guardaron (boletas, comprobantes de pago con tarjeta y otros tipos que el SII informa sólo como total, no documento por documento). Se leen con 'sii.rcv_totales.consultar'.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "agregadosEnDetalle": {
            "description": "Sólo en 'rcv': filas del detalle con forma de total del mes (sin fecha ni razón social) en un tipo que el SII declaró como documentos. No debería pasar; si es distinto de 0, avísale a soporte.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "incompletosPorMotivo": {
            "description": "Sólo en 'rcv', y siempre en ese alcance aunque quede vacía: el porqué de las casillas que cuenta 'incompletos'. La suma de 'casillas' es 'incompletos'.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "motivo": {
                  "type": "string",
                  "description": "Por qué no se trajeron. Estable: 'presupuesto' y 'tope' (se acabó el tiempo; el próximo sync lo reintenta), 'recaptcha', 'detalle_vacio', 'resumen_<código>', 'filas_no_calzan', 'csv_<motivo>', 'transporte', 'tipo_solo_resumen_<tipo>' (un tipo que el SII solo informa totalizado, por ejemplo 48), entre otros. La lista es abierta."
                },
                "casillas": {
                  "type": "integer",
                  "minimum": -9007199254740991,
                  "maximum": 9007199254740991,
                  "description": "Cuántas casillas quedaron sin traer por ese motivo."
                }
              },
              "required": [
                "motivo",
                "casillas"
              ],
              "additionalProperties": false
            }
          },
          "perspectivasFallidas": {
            "description": "En 'guias' y 'boletas_honorarios': qué direcciones fallaron, con su código de error. Esos dos alcances la emiten siempre, aunque quede vacía; ningún otro la emite.",
            "type": "array",
            "items": {
              "type": "object",
              "properties": {
                "perspectiva": {
                  "type": "string",
                  "enum": [
                    "emitidas",
                    "recibidas"
                  ],
                  "description": "Qué lado falló: 'emitidas' son las que emitió esta empresa y 'recibidas' las que le emitieron."
                },
                "code": {
                  "type": "string",
                  "description": "El código del catálogo de errores que explica por qué falló ese lado. Decide por el código, nunca por el texto."
                }
              },
              "required": [
                "perspectiva",
                "code"
              ],
              "additionalProperties": false
            }
          },
          "total": {
            "description": "Sólo en 'documentos': cuántos DTE anunció el índice del SII para el período. Es el conteo CRUDO del portal, con sus repetidos, así que restarle 'documentos' NO da el hueco. Para eso está 'faltantes'.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "ventanas": {
            "description": "Sólo en 'documentos': cuántas ventanas de descarga (hasta 20 folios cada una) hicieron falta para bajar el período.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "ventanasRechazadas": {
            "description": "Sólo en 'documentos': cuántas ventanas de descarga rechazó el portal. Lo que sí bajó se guarda igual y el período sale 'partial'; el detalle del rechazo viaja en 'marcador'.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "documentos": {
            "description": "Sólo en 'documentos': cuántos DTE se descargaron de verdad. El hueco es 'faltantes'; la resta contra 'total' NO lo da, porque 'total' viene con los repetidos del portal.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "faltantes": {
            "description": "Sólo en 'documentos': cuántos DTE prometió el índice y la descarga no trajo. Es lo que distingue un hueco del SII de un hueco nuestro; lo que sí bajó se guarda igual.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "sinIndice": {
            "description": "Sólo en 'documentos': cuántos DTE se descargaron sin que su clave apareciera en el índice del listado. Significa que el índice quedó corto, distinto de que la fila no trajera estado (eso llega como 'estado' en null).",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "hashMismatches": {
            "description": "Sólo en 'documentos': cuántos documentos repetidos traían un XML distinto. Un DTE firmado es inmutable, así que un valor distinto de 0 es una anomalía para reportar, nunca un documento que cambió.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "declaraciones": {
            "description": "Sólo en 'f29': cuántas declaraciones vigentes muestra el SII en su grilla, que cubre el año en curso y los seis anteriores. El período pedido no la acota: el F29 se revisa entero.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "nuevas": {
            "description": "Sólo en 'f29': cuántas declaraciones se leyeron completas en esta corrida por primera vez.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "pendientes": {
            "description": "Sólo en 'f29': cuántas declaraciones quedaron sin leer (por tiempo o porque su formulario no se pudo leer). Se retoman solas en la revisión siguiente; un valor distinto de 0 vuelve 'partial' el status.",
            "type": "integer",
            "minimum": -9007199254740991,
            "maximum": 9007199254740991
          },
          "error": {
            "description": "Por qué este alcance no terminó bien. Presente solo cuando 'status' es 'failed'. Normalmente es un código del catálogo de errores; cuando el sistema externo truncó el listado es una etiqueta de resultado ('movimientos_truncated', 'cartolas_truncated') que no está en ese catálogo y que significa «se escribió lo que alcanzó a venir». Decide por el valor, nunca por el texto libre.",
            "type": "string"
          }
        },
        "required": [
          "alcance",
          "status",
          "recordsSynced"
        ],
        "additionalProperties": false
      }
    }
  },
  "required": [
    "periodo",
    "estado"
  ],
  "additionalProperties": false
}

Errores de esta tool

CódigoHTTPReintentableQué hacer
connection_disabled403noReactívala en /connections o usa otra conexión del mismo sistema.
connection_credential_required428noCrea un enlace con conexiones.enlace.crear (modo reconectar si la conexión ya existe) y pide a la persona que entregue la credencial de nuevo. No reintentes con la credencial anterior.
connection_busy409síEspera unos segundos y reintenta. Es una espera transitoria: no necesitas volver a conectar ni ingresar la credencial otra vez.
upstream_error502síReintenta más tarde. Si persiste, el problema está en el sistema externo, no en tu integración.
timeout504síReintenta. Para sincronizaciones largas usa la vía asíncrona y consulta el estado del trabajo.
connection_sync_in_progress409síEspera a que termine y reintenta, o consulta directamente: puede que ya haya datos.
too_many_pending429síDeja terminar los trabajos en curso antes de encolar más.

Toda llamada puede devolver además los códigos transversales (validation_error, unauthorized, scope_not_granted, rate_limited, entre otros): el detalle vive en el catálogo de errores.

Próximos pasos

En esta página