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 (ver Eventos de MercadoPago). - 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.
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.payer_email,back_urls: opcionales.
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
}
marketplace_fee es el monto absoluto en ARS que retiene
la plataforma (round(total * 0.015, 2)).
Errores:
404 tenant_not_found.409 mp_not_connected— el comercio no conectó MP (o token revocado). Mandale elconnect_url.422 invalid_payload— faltaitems, precio negativo, etc.502— Mercado Pago rechazó la creación (vermessage).
Cancelar / reembolsar
POST /v1/mercadopago/refunds
Cancela/revierte un cobro: hace un reembolso total
del pago con el token del comercio. Idempotente por
payment_id (reintentar no genera un segundo
reembolso). El reembolso dispara el webhook
mp.payment.refunded, que es donde invalidás la
entrada/venta del lado tuyo.
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).
Respuesta:
{
"tenant_ref": "bruno-traslados",
"refund_id": "99001",
"payment_id": "123456789",
"amount": 46000,
"status": "approved"
}
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. Procesalo del mismo modo — no
importa quién disparó el refund.
Errores:
404 tenant_not_found.409 mp_not_connected— el comercio no tiene MP conectado.502 refund_failed— Mercado Pago rechazó el reembolso (pago no reembolsable, ya reembolsado, etc.). Vermessage.