MercadoPago split
Cobros con split de pagos (marketplace): cada comercio
(negocio) conecta su cuenta de Mercado Pago por OAuth y la plataforma
retiene un marketplace_fee del 1,5%
sobre cada cobro. El comercio recibe el resto. La app de Mercado Pago
es de Sabado — el consumer nunca ve client_secret ni los
tokens del comercio.
Orden del reparto (según doc oficial de MP):
primero Mercado Pago descuenta su comisión, después se descuenta el
marketplace_fee del saldo restante. El comercio recibe
lo que queda.
Flujo típico
- El comercio conecta su MP:
GET /v1/mercadopago/connect→ redirigís su navegador alconnect_url. - Verificás estado con
GET /v1/mercadopago/status. - Cobrás:
POST /v1/mercadopago/preferences→ mandás elinit_pointal comprador. - El comprador paga → recibís
mp.payment.approvedpor webhook (por el de por defecto, o por el propio de Mercado Pago si tus ventas las atiende otro sistema) (ver Eventos de MercadoPago). Si necesitás saber el estado sin esperar el webhook:GET /v1/mercadopago/payments. - Para cancelar/revertir un cobro:
POST /v1/mercadopago/refunds→ recibísmp.payment.refunded.
Conectar el comercio
GET /v1/mercadopago/connect
Devuelve la URL de autorización OAuth para que el comercio conecte
su cuenta de Mercado Pago. Redirigí el navegador del dueño del
comercio al connect_url.
Scope: mercadopago.write.
GET /v1/mercadopago/connect?tenant_ref=bruno-traslados
Authorization: Bearer TU_API_KEY
Respuesta:
{
"tenant_ref": "bruno-traslados",
"connect_url": "https://auth.mercadopago.com.ar/authorization?client_id=...&response_type=code&platform_id=mp&redirect_uri=...&state=..."
}
El state es one-time (CSRF + liga el callback con el
comercio). El callback lo maneja Sabado; cuando el comercio
autoriza, queda conectado y status lo refleja.
Errores:
404 tenant_not_found.403 plan_not_included— el plan de tu cuenta no incluye cobros con Mercado Pago. Pasate a un plan que los incluya desde el panel.
Estado de conexión
GET /v1/mercadopago/status
Estado de conexión MercadoPago del comercio. Usalo para mostrar "Conectar" vs "Conectado ✓" en tu UI.
Scope: mercadopago.read.
GET /v1/mercadopago/status?tenant_ref=bruno-traslados
Authorization: Bearer TU_API_KEY
Respuesta:
{
"tenant_ref": "bruno-traslados",
"connected": true,
"mp_user_id": "123456789",
"connected_at": "2026-05-28T19:04:58+00:00"
}
connected: false (con mp_user_id y
connected_at en null) cuando el comercio
no conectó, o cuando su token fue revocado — en ese caso la
plataforma marca la credencial como desconectada automáticamente,
así que el status no miente.
Errores:
404 tenant_not_found.
Crear preferencia (cobrar)
POST /v1/mercadopago/preferences
Crea una preferencia de Checkout Pro con split. La plataforma
calcula el marketplace_fee (1,5% del total) y crea la
preferencia con el token del comercio. Mandá el init_point
al comprador (sandbox_init_point en pruebas).
Scope: mercadopago.write.
POST /v1/mercadopago/preferences
{
"tenant_ref": "bruno-traslados",
"external_reference": "ticket-42",
"items": [
{
"title": "Viaje a Ricky Martin (2 lugares)",
"quantity": 1,
"unit_price": 46000,
"currency_id": "ARS"
}
],
"payer_email": "ana@gmail.com",
"back_urls": {
"success": "https://tudominio.com/pago-ok",
"pending": "https://tudominio.com/pago-pendiente",
"failure": "https://tudominio.com/pago-error"
}
}
items[].currency_id: opcional, defaultARS.external_reference: opcional pero recomendado — te lo devolvemos en el webhook para cruzar el pago con tu venta, y con él podés consultar si se pagó.payer_email,back_urls: opcionales.
Controlar el cobro
Opcionales, por preferencia — cada venta decide. Sirven sobre todo cuando lo que vendés tiene tiempo límite (una reserva, un cupo, un turno):
| Campo | Qué hace |
|---|---|
expiration_date_to | Fecha ISO 8601. Después de esa hora el link deja de aceptar pagos. Ponele el fin de la reserva. |
binary_mode | true: el pago sale aprobado o rechazado en el momento, nunca queda pendiente ni en revisión. Según Mercado Pago baja un poco la tasa de aprobación: lo que iba a revisión se rechaza. |
excluded_payment_types | Tipos de medio de pago a sacar, ej. ["ticket"] para el efectivo (Rapipago, Pago Fácil). El dinero en cuenta de Mercado Pago no se puede excluir. |
date_of_expiration | Fecha ISO 8601: vencimiento de los pagos en efectivo. Mercado Pago acepta entre 1 y 30 días. |
POST /v1/mercadopago/preferences
{
"tenant_ref": "bruno-traslados",
"external_reference": "compra-77",
"items": [{ "title": "2 lugares", "quantity": 1, "unit_price": 46000 }],
"expiration_date_to": "2026-09-21T19:00:00-03:00",
"binary_mode": true,
"excluded_payment_types": ["ticket"]
}
Venta con reserva: prevenir es mejor que devolver. El
efectivo acredita en 1 a 2 días hábiles y no puede vencer
en menos de un día, así que con una reserva de minutos es exactamente el
pago que llega con la reserva ya caída. Para ventas con tiempo límite:
excluí ticket, activá binary_mode y poné
expiration_date_to al fin de la reserva. Al vencer, consultá
por external_reference antes de liberar
el lugar. La devolución queda para la excepción:
no se puede garantizar (ver abajo).
Respuesta:
{
"tenant_ref": "bruno-traslados",
"preference_id": "123456789-abc...",
"init_point": "https://www.mercadopago.com.ar/checkout/v1/redirect?pref_id=...",
"sandbox_init_point": "https://sandbox.mercadopago.com.ar/checkout/v1/redirect?pref_id=...",
"marketplace_fee": 690,
"expires_at": "2026-09-21T19:00:00.000-03:00"
}
marketplace_fee es el monto absoluto en ARS que retiene
la plataforma (round(total * 0.015, 2)).
expires_at es la hora en que el link deja de cobrar
(null si no mandaste expiration_date_to).
Errores:
404 tenant_not_found.403 plan_not_included— el plan de tu cuenta no incluye cobros con Mercado Pago. Pasate a un plan que los incluya desde el panel.409 mp_not_connected— el comercio no conectó MP (o token revocado). Mandale elconnect_url.422(validación) — faltaitems, precio negativo, email mal formado, una fecha de vencimiento ya pasada, etc. Viene con la forma de validación (errorspor campo).502 preference_failed— Mercado Pago rechazó la creación (vermessage).
Consultar pagos
El estado real del pago en Mercado Pago, en el momento, sin depender del webhook. Sirve para decidir qué hacer cuando vence una reserva, o para conciliar. Se consulta con la cuenta del comercio: solo ves sus pagos. No depende del plan (igual que las devoluciones).
Scope: mercadopago.read.
GET /v1/mercadopago/payments?external_reference=…
Los pagos de tu venta, más nuevos primero. Es la forma de preguntar
"¿se pagó la compra 77?" cuando todavía no tenés payment_id
(no te llegó ningún webhook). Puede venir más de uno: un intento rechazado y
después uno aprobado, por ejemplo.
GET /v1/mercadopago/payments?tenant_ref=bruno-traslados&external_reference=compra-77
{
"tenant_ref": "bruno-traslados",
"data": [
{
"payment_id": "123456789",
"external_reference": "compra-77",
"status": "approved",
"status_detail": "accredited",
"payment_type_id": "credit_card",
"transaction_amount": 46000,
"amount_refunded": 0,
"marketplace_fee": 690,
"mp_fee": 1380,
"net_received": 43930,
"currency": "ARS",
"date_created": "2026-09-21T18:00:00.000-03:00",
"date_approved": "2026-09-21T18:00:02.000-03:00",
"refunds": []
}
]
}
GET /v1/mercadopago/payments/{payment_id}
Un pago puntual, con la misma forma (sin el data).
GET /v1/mercadopago/payments/123456789?tenant_ref=bruno-traslados
status:approved,pending,in_process,rejected,cancelled,refunded,charged_back…date_approved: cuándo lo aprobó Mercado Pago — usalo para saber si el pago entró dentro de tu reserva, sin depender de cuánto tardó en llegar el webhook.refunds: las devoluciones hechas (refund_id,amount,status,date_created).- Es la misma forma que el
datade los webhooksmp.payment.*.
Errores:
404 tenant_not_found.404 payment_not_found— el pago no existe o no es de ese comercio.409 mp_not_connected— el comercio no tiene MP conectado.
Cancelar / reembolsar
POST /v1/mercadopago/refunds
Hace un reembolso total del pago con la cuenta del comercio. Antes de pedírselo a Mercado Pago revisamos el estado del pago, así que te contestamos con códigos estables en vez del texto de Mercado Pago. Los reembolsos no dependen del plan: devolver la plata de un pago siempre está disponible.
Scope: mercadopago.write.
POST /v1/mercadopago/refunds
{
"tenant_ref": "bruno-traslados",
"payment_id": "123456789"
}
payment_id: el id del pago de Mercado Pago (el que
recibís en mp.payment.approved o en la
consulta).
Respuesta:
{
"tenant_ref": "bruno-traslados",
"refund_id": "99001",
"payment_id": "123456789",
"amount": 46000,
"status": "approved",
"already_refunded": false
}
Pedirlo dos veces no devuelve dos veces ni falla. Si el pago
ya estaba devuelto (por este endpoint o desde Mercado Pago), respondemos
200 con la devolución que ya existe y
"already_refunded": true, sin tocar nada. Por eso no hace falta
Idempotency-Key: la devolución es una sola por pago.
| Respuesta | Cuándo |
|---|---|
200, already_refunded: false | Se hizo la devolución. |
200, already_refunded: true | Ya estaba devuelto: te damos la devolución existente. |
409 payment_not_refundable, reason: not_approved | El pago no está aprobado (viene payment_status con el estado real). Solo se devuelven pagos aprobados. |
409 payment_not_refundable, reason: refund_window_expired | Pasaron más de 180 días desde la aprobación: Mercado Pago ya no lo permite. |
409 payment_not_refundable, reason: partially_refunded | El pago ya tiene una devolución parcial (hecha desde Mercado Pago). Este endpoint no la completa. |
409 payment_not_refundable, reason: charged_back | El comprador hizo un contracargo con su banco: la plata ya volvió por ese lado. |
404 payment_not_found | El pago no existe o no es de ese comercio. |
409 mp_not_connected | El comercio no tiene Mercado Pago conectado. |
502 refund_failed | Mercado Pago rechazó la devolución — el caso típico es falta de saldo del comercio. El motivo va en message. |
Cuando la devolución sale, te mandamos mp.payment.refunded
en ese mismo momento. Si después llega el aviso de Mercado
Pago por el mismo cambio, no se repite.
La plata y la comisión en una devolución
- Al comprador le vuelve el monto entero.
- Mercado Pago lo descuenta proporcionalmente de la cuenta
del comercio y de la de Sabado: la plataforma devuelve su parte del
marketplace_fee. En una venta devuelta, la plataforma no cobra comisión. - El comercio tiene que tener saldo. Si ya retiró la plata,
Mercado Pago rechaza la devolución total (
502 refund_failed) y hay que resolverlo por otro medio. Por eso una devolución automática nunca está garantizada: para ventas con tiempo límite, mejor controlar el cobro. - El plazo máximo es de 180 días desde la aprobación.
Un solo camino de invalidación. Si el comercio
o el comprador hacen el refund directamente desde Mercado Pago en
lugar de usar este endpoint, igual te llega el webhook
mp.payment.refunded (o mp.payment.partial_refund
si fue parcial). Procesalo del mismo modo — no importa quién lo disparó.