Connect

Sincronizar conexión Mercado Pago

Sincroniza los pagos que RECIBIÓ la cuenta de Mercado Pago de esta conexión, con sus reembolsos y comisiones, y los guarda para consultarlos con 'mercadopago.pagos.consultar' y 'mercadopago.reembolsos.consultar'.

Tool IDmercadopago.conexion.sincronizar
Nombre MCPmercadopago__conexion__sincronizar
Conectormercadopago
Planoread
Alcancespagos
Scope (permiso)mercadopago:read
Authconnection_credentials
Versión1
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 y campo connectionId en el execute_write de MCP. 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

Es el ÚNICO camino que trae datos de Mercado Pago. Trae lo actualizado desde la última vez y completa hacia atrás el historial que Mercado Pago permite buscar (12 meses), por tramos: con mucho volumen, varias sincronizaciones seguidas completan el historial y el resultado lo dice en 'detalle'. Sólo lee: nunca cobra, reembolsa ni mueve dinero. No trae saldo, retiros ni liquidaciones. Un 'upstream_error' o un resultado 'partial' por límite de consultas es transitorio y no invalida la autorización.

Entrada

CampoTipoRequeridoDescripción
periodostring `^\d4-(0[1-9]1[0-2])$`no
alcanceslista de stringno · default ["pagos"]Los módulos a sincronizar. Hoy hay uno: 'pagos', que trae pagos, reembolsos y comisiones.
JSON Schema de entrada
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "periodo": {
      "description": "Período de ejecución en AAAA-MM; si se omite, el mes actual en Santiago. No filtra los pagos: el sync avanza por fecha de actualización desde donde quedó, y un período anterior no vuelve a consultar.",
      "type": "string",
      "pattern": "^\\d{4}-(0[1-9]|1[0-2])$"
    },
    "alcances": {
      "default": [
        "pagos"
      ],
      "description": "Los módulos a sincronizar. Hoy hay uno: 'pagos', que trae pagos, reembolsos y comisiones.",
      "minItems": 1,
      "type": "array",
      "items": {
        "type": "string",
        "const": "pagos"
      }
    }
  }
}

Ejemplo

curl
curl -X POST https://connect.emisso.ai/api/v1/tools/mercadopago.conexion.sincronizar/execute \
  -H "Authorization: Bearer connect_sk_…" \
  -H "X-Connect-Connection: conn_9tKfR2mQx4Vb" \
  -H "Content-Type: application/json" \
  -d '{"input":{}}'
MCP · meta-tool execute_write
{
  "tool": "mercadopago.conexion.sincronizar",
  "params": {},
  "connectionId": "conn_9tKfR2mQx4Vb"
}

Salida esperada (200):

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

Con muchos pagos el historial se completa en varias sincronizaciones: cada una guarda tramos completos y lo dice en 'detalle'.

Salida

CampoTipoRequeridoDescripción
periodostringsíPeríodo de ejecución en AAAA-MM.
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, así que no se creó otra. No es un error ni un rechazo. Si esa sincronización sigue en cola, 'jobId' es el suyo; si ya está corriendo, 'jobId' llega null y su avance se ve en 'trabajos' de 'conexiones.estado.consultar'. Cubre el período, no necesariamente los alcances que pediste: si pediste otros, vuelve a pedirlos cuando termine. 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.
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íEl módulo sincronizado.
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' = lo pendiente quedó leído y guardado. 'partial' = se guardó todo lo leído completo, pero quedó historial, reembolsos o tramos por leer (ver 'detalle'); la próxima sincronización sigue sola. 'failed' = no terminó bien; la causa va en 'error'.
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[].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.
results[].detallestringnoExplicación en lenguaje llano, presente solo cuando el resultado necesita una. Existe para que un cero se pueda transmitir tal cual en vez de concluir «no hay datos»: transmítelo a quien pregunte en lugar de resumir el número solo.
JSON Schema de salida
{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "periodo": {
      "type": "string",
      "description": "Período de ejecución en AAAA-MM."
    },
    "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.succeeded' o 'sync.failed' si tu plan los incluye. Es null cuando 'estado' es 'completado', porque ahí el resultado ya está en la respuesta, y cuando 'yaEnCurso' es true y esa sincronización ya está corriendo.",
      "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, así que no se creó otra. No es un error ni un rechazo. Si esa sincronización sigue en cola, 'jobId' es el suyo; si ya está corriendo, 'jobId' llega null y su avance se ve en 'trabajos' de 'conexiones.estado.consultar'. Cubre el período, no necesariamente los alcances que pediste: si pediste otros, vuelve a pedirlos cuando termine. 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.",
      "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",
            "const": "pagos",
            "description": "El módulo sincronizado."
          },
          "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' = lo pendiente quedó leído y guardado. 'partial' = se guardó todo lo leído completo, pero quedó historial, reembolsos o tramos por leer (ver 'detalle'); la próxima sincronización sigue sola. 'failed' = no terminó bien; la causa va en 'error'."
          },
          "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'."
          },
          "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"
          },
          "detalle": {
            "description": "Explicación en lenguaje llano, presente solo cuando el resultado necesita una. Existe para que un cero se pueda transmitir tal cual en vez de concluir «no hay datos»: transmítelo a quien pregunte en lugar de resumir el número solo.",
            "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_not_found404noUsa uno de los connectionId que lista el error, o revisa la conexión en /connections. No hace falta reactivar nada.
alcance_not_enabled403noHabilita el alcance en /connections o quítalo del input de la sincronización.
too_many_pending429síDeja terminar los trabajos en curso antes de encolar más.

La llamada solo encola: las fallas del sistema externo (credencial, sesión, caída del portal) no llegan en esta respuesta, sino en el trabajo: en outcomes y last_error de GET /v1/syncs/{jobId}, o en los webhooks sync.succeeded (un alcance que falló junto a otros que terminaron) y sync.failed.

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