Cómo migrar de Payments API a Orders API
Orders API unifica el procesamiento de pagos online de , ofreciendo endpoints estandarizados, un modelo de estados consolidado por transacción y nuevos recursos nativos que no existían en Payments API. Entre ellos: múltiples transacciones por order, procesamiento manual o automático, endpoint dedicado de captura, autenticación 3DS 2.0 integrada de forma nativa y lista consolidada de errores de validación.
La migración implica la actualización de los endpoints y campos de la solicitud, la consolidación del modelo de estados y notificaciones y el aprovechamiento de nuevos recursos nativos. La migración no implica cambios en el flujo de negocio percibido por el comprador: el cliente continúa completando el checkout dentro del sitio del vendedor, sin redirecciones.
Consulta a continuación cómo realizar esta migración de forma completa, endpoint por endpoint y campo por campo, incluyendo las particularidades de cada medio de pago.
Antes de implementar, clasifica cada flujo activo de Payments API en una de estas situaciones:
- Tiene equivalente directo: cuando se trata de un recurso obligatorio que tiene una equivalencia directa entre las APIs, migra tu flujo siguiendo los pasos obligatorios de esta guía.
- Requiere una adaptación técnica: cuando se trata de un recurso opcional que ya forma parte de tu integración actual, implementa también los pasos según tu flujo.
- No tiene equivalente documentado: mantén el flujo en Payments API hasta que exista soporte en Orders API.
Payments API continúa funcionando con normalidad después del lanzamiento de Orders API. Mercado Pago no desactivó esta API, solo dejó de agregarle nuevas funcionalidades, mientras mantiene las correcciones de seguridad y estabilidad. Técnicamente, es posible mantener ambas APIs activas al mismo tiempo, cada una procesando una parte de tu volumen.
Recomendamos la siguiente estrategia:
- Migra por medio de pago, no todo de una sola vez. Primero, pasa las tarjetas a Orders API y migra los demás medios de pago uno por uno, después de validar su estabilidad.
- Divide el tráfico en tu propio checkout. Como cada API usa endpoints, credenciales y claves de idempotencia independientes, puedes dirigir de forma segura una parte de las nuevas transacciones a /v1/ordersPOST y el resto a /v1/paymentsPOST.
- Separa el procesamiento de las notificaciones. Configura el Webhook para escuchar los tópicos
ordersypaymenten paralelo durante la transición, y dirige cada payload al flujo correspondiente. Desactivapaymentsolo después de migrar el tráfico nuevo y monitorear las transacciones y notificaciones pendientes de Payments API. - Define cómo interrumpir la migración. Si es necesario volver a usar Payments API, redirige únicamente las nuevas transacciones. Las transacciones ya creadas deben seguir consultándose, capturándose, cancelándose o reembolsándose en la API en la que fueron procesadas, ya que no pueden ni necesitan transferirse de una API a otra.
- Monitorea la tasa de aprobación y la calidad de la integración por separado para cada API durante la coexistencia, como criterio para decidir cuándo desactivar el tráfico de Payments API.
Antes de iniciar la migración, confirma si todos los medios de pago de tu integración ya tienen un equivalente en Orders API.
Además de la disponibilidad por medio de pago, verifica si tu integración utiliza recursos de Marketplace o Split de Pagos 1:1. En Payments API, estas integraciones retienen comisiones mediante application_fee; Orders API todavía no tiene un campo equivalente documentado para esta mecánica. Considera este punto como un bloqueo antes de migrar el flujo.
En Payments API, cada operación usaba un recurso propio sobre /v1/payments/{id}. Orders API consolida la mayoría de estas operaciones en subrecursos del mismo /v1/orders/{order_id} e introduce endpoints dedicados que no existían antes: captura explícita, adición, eliminación y actualización de transacciones, y procesamiento en modo manual.
El header Authorization es obligatorio en ambas APIs y no cambia. La principal modificación está en la obligatoriedad del header de idempotencia en prácticamente todas las operaciones de escritura.
| Header | Payments API | Orders API |
Authorization | Obligatorio en todas las solicitudes | Obligatorio en todas las solicitudes |
X-Idempotency-Key | Obligatorio únicamente en /v1/paymentsPOST y /v1/payments/{id}/refundsPOST | Obligatorio en /v1/ordersPOST, /v1/orders/{order_id}/capturePOST, /v1/orders/{order_id}/transactionsPOST, /v1/orders/{order_id}/processPOST, /v1/orders/{order_id}/cancelPOST y /v1/orders/{order_id}/refundPOST |
X-Idempotency-Key con un body diferente, Orders API devuelve el error 409 (idempotency_key_already_used). Genera siempre una clave nueva por intento de transacción, preferentemente un UUID v4. Para más detalles sobre todos los headers aceptados en Orders API, accede a la Referencia de APIAPI.En Payments API, el status y el status_detail existen en un único nivel. En Orders API, el mismo concepto existe en dos niveles: el estado de la order, como visión consolidada, y el estado de cada transacción en transactions.payments[], lo que se vuelve esencial cuando una order tiene más de una transacción.
La siguiente tabla mapea los valores de status entre el pago en Payments API y los niveles de order y transacción en Orders API.
| Payments API | Orders API (order) | Orders API (transacción) | Observación |
pending | action_required | action_required | Esperando una acción del pagador o del vendedor. |
approved | processed | processed | Pago aprobado y acreditado. |
authorized | action_required (waiting_capture) | action_required (waiting_capture) | Monto reservado, esperando la captura. |
in_process | processing | processing | En análisis o procesamiento. |
in_mediation | charged_back (in_process) | charged_back (in_process) | Contracargo en curso. |
rejected | failed | failed | Rechazado. El status_detail indica el motivo. |
cancelled | canceled | canceled | Cancelado por el vendedor, el comprador o por vencimiento. |
refunded | refunded | refunded | Reembolsado en su totalidad. |
charged_back | charged_back (settled / reimbursed) | charged_back (settled/reimbursed) | Contracargo recibido y resuelto. |
cancelled, con dos letras L, y Orders API usa canceled, con una letra L. Si tu integración compara este valor de estado como una string literal, actualiza la ortografía.El endpoint de creación cambia de /v1/paymentsPOST a /v1/ordersPOST. Además de la URL, se reorganizó la estructura de la solicitud: el monto y el medio de pago pasan al nodo transactions.payments[], un array que permite múltiples transacciones por order. Los campos type, con el valor fijo online, y el nodo config comienzan a existir sin equivalencia directa en el sistema anterior.
La siguiente tabla mapea, campo por campo, la estructura de la solicitud de creación entre las dos APIs.
| Payments API | Orders API | Cambio |
transaction_amount | transactions.payments[].amount / total_amount | Pasa al array de transacciones y se convierte en una string. El total_amount debe corresponder a la suma de las transacciones. |
payment_method_id | transactions.payments[].payment_method.id | Pasa a estar anidado en payment_method. |
token | transactions.payments[].payment_method.token | Pasa a estar anidado en payment_method. |
installments | transactions.payments[].payment_method.installments | Pasa a estar anidado en payment_method. |
statement_descriptor | transactions.payments[].payment_method.statement_descriptor | Pasa a estar anidado en payment_method. |
description | description | Sin cambios. Permanece en el nivel raíz. |
external_reference | external_reference | Sin cambios de nombre. Pasa a ser obligatorio en algunos medios de pago. |
notification_url | No existe. | Eliminado del body. Las notificaciones pasan a configurarse en Tus integraciones. Consulta más información en Notificaciones. |
capture | capture_mode | Cambia de booleano a los valores manual, automatic y automatic_async, en el nivel raíz de la order. |
date_of_expiration | transactions.payments[].expiration_time / date_of_expiration | Pasa a aceptar una duración en formato ISO 8601, además de una fecha absoluta. |
payer.email | payer.email | Sin cambios. |
payer.identification.type / .number | payer.identification.type / .number | Sin cambios. |
payer.first_name / .last_name | payer.first_name / .last_name | Sin cambios. |
payer.address.* | payer.address.* | Sin cambios de estructura. |
three_d_secure_mode | config.online.transaction_security.validation y .liability_shift | Reestructurado. Consulta más información en Integrar 3DS. |
items[].id | items[].external_code | Renombrado. |
items[].title / .unit_price / .quantity / .description / .picture_url / .category_id | Mismos nombres | Sin cambios de nombre. |
| No existe | type | Campo nuevo y obligatorio. Para pagos online, el valor es online. |
| No existe | processing_mode | Campo nuevo. Define si la order se procesa en una etapa o después, mediante /process. |
| No existe | integration_data.{integrator_id, platform_id, sponsor.id} | Campo nuevo. Sustituye parcialmente el sponsor_id del sistema anterior. |
issuer_id | transactions.payments[].payment_method.id (de forma implícita) | No hay un campo issuer_id directo documentado. Valida la necesidad en cada caso. |
binary_mode | No documentado como campo de Orders API | Restringía el resultado a aprobado o rechazado. No se encontró un equivalente directo. |
application_fee | No documentado en Orders API. Valida con el equipo responsable de tu integración antes de migrar integraciones con Split de Pagos 1:1. | |
fee_details[] | Sin equivalente directo documentado | Detalle de comisiones. Valida el cálculo a partir de los reportes de liberación de dinero. |
La siguiente tabla mapea los principales campos de la respuesta de creación entre las dos APIs.
Payments API devuelve un error a la vez, el primero que encuentra. Orders API devuelve una lista con todos los errores de validación de la solicitud en una única respuesta, lo que agiliza la corrección.
La siguiente tabla enumera los errores de Payments API que se renombraron o consolidaron en códigos más genéricos en Orders API.
| HTTP | Payments API | Orders API | Observación |
400 | 3000 a 3032 | property_value / property_type / required_properties | Consolidados en códigos genéricos de validación por campo. |
400 | 4000 a 4051 | required_properties / unsupported_properties / minimum_properties | Consolidados. |
400 | 23 | property_value | Formato no válido de date_of_expiration. |
400 | 2072 | invalid_total_amount | Renombrado. Pasa a validar la suma de transactions.payments[].amount respecto de total_amount. |
400 | 2131 | invalid_order_type / property_value | Consolidado. |
400 | 4292 | empty_required_header | Renombrado. |
401 | Unauthorized use of live credentials | invalid_credentials | Renombrado. |
409 | 2001 | idempotency_key_already_used | Consolidado en el mecanismo de idempotencia. |
403 | 4 (caller not authorized) | No documentado como un error 403 específico en Orders API | Valida el comportamiento en el entorno de prueba. |
El endpoint de consulta cambia de /v1/payments/{id}GET a /v1/orders/{id}GET. La respuesta incluye el objeto completo de la order, con todas las transacciones asociadas, sus reembolsos y posibles contracargos, información que en el sistema anterior exigía consultas por separado.
| Información | Payments API | Orders API |
| Reembolsos | Consulta separada en /v1/payments/{id}/refundsGET. | Incluido en transactions.refunds[] |
| Contracargos | Consulta separada en /v1/chargebacks/{id}GET. | Referenciado en transactions.chargebacks[], con id, transaction_id, case_id, status y references. |
| Datos de 3DS | payment_method.data.threeds | transactions.payments[].payment_method.transaction_security |
| No aplica en este endpoint. | config.payment_method.{default_type, installments_cost, installments.interest_free, installments.available} |
Errores de consulta
| HTTP | Error | Observación |
400 | invalid_path_param | El order_id enviado tiene un formato no válido. |
401 | invalid_credentials | Access Token no válido o vencido. |
404 | order_not_found | El order_id no corresponde a ninguna order creada. |
500 | internal_error | Error genérico. Inténtalo nuevamente y, si persiste, comunícate con soporte e informa el x-request-id. |
El endpoint de búsqueda cambia de /v1/payments/searchGET a /v1/orders/searchGET, con filtros y paginación reestructurados. Los intervalos de fechas pasan a ser obligatorios y la paginación usa page y page_size en lugar de offset y limit.
| Payments API | Orders API | Observación |
sort | sort_by | Renombrado. El valor predeterminado es created_date. |
criteria | sort_order | Renombrado. El valor predeterminado es desc. |
begin_date / end_date | begin_date / end_date | Pasan a ser obligatorios, en formato RFC3339. |
external_reference | external_reference | Sin cambios. |
collector.id / payer.id | No documentado como filtro. | La identidad se obtiene del Access Token. |
offset / limit | page / page_size | Paginación por página. page_size tiene un máximo de 100 y un valor predeterminado de 20. |
| No existe | status / status_detail / payment_method_id / payment_method_type | Nuevos filtros directos. |
La reserva de un monto deja de ser un campo booleano (capture) y pasa a ser un modo de captura configurado al crear la order (capture_mode), combinado con un endpoint dedicado de captura.
La siguiente tabla compara cómo reservar un monto sin captura inmediata en ambas APIs.
| Payments API | Orders API |
/v1/paymentsPOST con "capture": "false". | /v1/ordersPOST con "capture_mode": "manual". |
Resultado: "status": "authorized". | Resultado: "status": "action_required" y "status_detail": "waiting_capture". |
Al igual que en Payments API, es posible cancelar una order antes de que se complete el pago o reembolsarla, total o parcialmente, después de la aprobación. Consulta a continuación cómo cambia cada flujo en Orders API.
Solo es posible cancelar una order con estado action_required o created, es decir, cuando el pago todavía no se ha completado. El endpoint cambia de /v1/payments/{id}PUT al endpoint dedicado /v1/orders/{order_id}/cancelPOST.
Los endpoints de la Customers API son compartidos entre ambas APIs y no sufren cambios de estructura en la migración. Solo cambia la forma de usar la tarjeta guardada en un nuevo cobro, ya que el pago pasa a crearse como una order.
| Recurso | Endpoint sin cambios entre las APIs |
| Crear cliente | /v1/customersPOST |
| Buscar clientes | /v1/customers/searchGET |
| Obtener cliente | /v1/customers/{id}GET |
| Actualizar cliente | /v1/customers/{id}PUT |
| Guardar tarjeta | /v1/customers/{customer_id}/cardsPOST |
| Listar las tarjetas del cliente | /v1/customers/{customer_id}/cardsGET |
| Obtener tarjeta | /v1/customers/{customer_id}/cards/{id}GET |
| Actualizar tarjeta | /v1/customers/{customer_id}/cards/{id}PUT |
| Eliminar tarjeta | /v1/customers/{customer_id}/cards/{id}DELETE |
| Direcciones del cliente | /v1/customers/{id}/addressesPOST, /v1/customers/{id}/addressesGET, /v1/customers/{id}/addresses/{address_id}PUT y /v1/customers/{id}/addresses/{address_id}DELETE |
Cambios al pagar con una tarjeta guardada:
| Payments API | Orders API |
"payer.type": "customer"/ "payer.id": "<customer_id>" / token (generado únicamente con el código de seguridad) | "payer.customer_id": "<customer_id>" / transactions.payments[].payment_method.token |
| /v1/paymentsPOST | /v1/ordersPOST |
En Payments API, las integraciones de marketplace usan OAuth para obtener el Access Token del vendedor conectado y envían el campo application_fee, con el monto retenido por el integrador, en el cuerpo de creación del pago.
application_fee. El nodo integration_data.sponsor.id existe, pero no sustituye la mecánica de retención de comisión. Si tu integración depende del Split de Pagos 1:1 o de un marketplace, valida este punto antes de migrar este flujo específico y no asumas que existe paridad.La autenticación 3D Secure 2.0 deja de ser un campo simple y pasa a ser un nodo de configuración dedicado en config.online.transaction_security, con control explícito de la responsabilidad por contracargos.
| Payments API | Orders API | Descripción |
"three_d_secure_mode": "optional" | "config.online.transaction_security.validation": "on_fraud_risk" | Ejecuta 3DS cuando el motor de riesgo identifica que es necesario. Recomendado. |
"three_d_secure_mode": "not_supported" | config.online.transaction_security.validation: "never" | Desactiva 3DS de forma explícita. Es el valor predeterminado. |
| No existe | config.online.transaction_security.liability_shift: "required" | Transfiere al emisor la responsabilidad por el contracargo. Obligatorio cuando validation es diferente de never. |
Respuesta con desafío: "status": "pending", campos creq y external_resource_url. | Respuesta con desafío: "status = action_required", "status_detail" = "pending_challenge" y URL en transactions.payments[].payment_method.transaction_security.url. | Renombrado y reestructurado. |
| Tiempo límite del desafío no documentado | Tiempo límite del desafío de 40 minutos. | Plazo definido explícitamente. |
Restricción: "capture": "true" y "binary_mode": "false" obligatorios. | Sin restricciones equivalentes documentadas. | Confirma el comportamiento con un capture_mode diferente de automatic en el entorno de prueba. |
Estados posibles después del flujo de 3DS en Orders API:
status | status_detail | Descripción |
processed | accredited | Aprobado, con o sin autenticación. |
failed | failed | Rechazado, sin autenticación o con una falla en ella. |
action_required | pending_challenge | Pendiente de autenticación durante un máximo de 40 minutos. |
canceled | expired | El desafío venció. Es necesario crear una nueva order. |
cardholder_name usados para simular cada escenario difieren entre las dos APIs, por lo que debes utilizar la tabla específica de Orders API. Para más información sobre este flujo, accede a Integrar 3DS.El mecanismo de firma y validación HMAC-SHA256 es idéntico en ambas APIs. Lo que cambia es el tópico de notificación y el origen de la configuración.
| Payments API | Orders API | Observación |
Tópico payment | Tópico orders | Cambio principal. Reconfigura el Webhook para el nuevo tópico. |
Configurable mediante notification_url en el body o en el panel. | Configurable únicamente en el panel, en Tus integraciones | Se elimina la opción de configurar por solicitud. |
| Recurso que se debe consultar: /v1/payments/{id}GET. | Recurso que se debe consultar: /v1/orders/{id}GET. | El endpoint cambia. |
| IPN disponible y sin validación de firma. | No disponible. | Utiliza exclusivamente Webhooks en la nueva integración. |
| Plazo de respuesta de 22 segundos y con reenvío cada 15 minutos. | Plazo de respuesta de 22 segundos y con reenvío cada 15 minutos. | Sin cambios. |
El endpoint de consulta de contracargos /v1/chargebacks/{id}GET es idéntico en ambas APIs. La diferencia está en el evento de notificación y en los nuevos campos expuestos directamente en la order.
| Payments API | Orders API | Observación |
Notificación mediante el tópico topic_chargebacks_wh | Notificación mediante el evento Chargebacks, en el tópico chargebacks, con "action": "order.charged_back". | Configura este evento además de Order (Mercado Pago). |
Estado del pago: charged_back | Estado de la order y de la transacción: charged_back, con "status_detail": "in_process", "settled" o "reimbursed". | Detalle adicional en status_detail. |
| Consulta mediante /v1/chargebacks/{id}GET. | Consulta mediante /v1/chargebacks/{id}GET. | Sin cambios. |
payment_id, /v1/chargebacks/{id}/documentationPOST para enviar la documentación comprobatoria; y /v1/chargebacks/documentation/{type}/{uuid}GET para recuperar un archivo ya enviado.Los campos de resolución son idénticos en ambas APIs.
| Campo | Valor | Descripción |
coverage_applied | true | Decisión a favor del vendedor. El monto se le devuelve. |
coverage_applied | false | Decisión en contra del vendedor. El monto se le descuenta. |
Las buenas prácticas de prevención de fraude permanecen conceptualmente iguales. Lo que cambia es dónde se envían los datos adicionales en el cuerpo de la solicitud.
| Práctica | Payments API | Orders API |
| Device ID | Script de seguridad y header X-meli-session-id en /v1/paymentsPOST | /v1/ordersPOST (mismo mecanismo) |
| Datos adicionales del comprador y del producto | additional_info.{items[], payer, shipments} | Distribuidos entre items[] / payer / shipment (sin el nodo consolidado additional_info) |
| Texto identificable en el resumen | statement_descriptor (en el nivel raíz) | transactions.payments[].payment_method.statement_descriptor |
| Datos de la industria | additional_info.travel.{passengers, routes} | Los datos se envían en la estructura de la order. Consulta Datos de industria; los ejemplos, incluido category_id, no forman una lista cerrada de valores. |
El uso de credenciales, usuarios y tarjetas de prueba funciona del mismo modo. La principal diferencia está en el correo electrónico exigido para el pagador y en la tabla de nombres de titulares usada para simular cada escenario.
cardholder_name de Orders API, accede a Tarjetas de prueba. Para más detalles sobre el flujo, accede a Probar la integración.La evaluación de Orders API considera los siguientes aspectos para medir la calidad de la integración migrada.
| Aspecto evaluado | Payments API | Orders API |
| Uso del SDK oficial en la tokenización | Evaluado | Evaluado |
| Device ID | Evaluado | Evaluado |
Tratamiento del estado y status_detail | Evaluado | Evaluado (incluido el nivel de la transacción) |
Uso de X-Idempotency-Key | Evaluado (únicamente en la creación y el reembolso) | Evaluado (en todas las operaciones de escritura) |
| Conciliación con múltiples transacciones | No aplica | Evaluado |
| Uso de 3DS cuando corresponde | No evaluado | Evaluado |
Antes de salir a producción, confirma los siguientes puntos:
- Activa las credenciales de producción en Tus integraciones.
- Sustituye la Public Key y el Access Token de prueba por los de producción.
- Implementa un certificado SSL/HTTPS, obligatorio en producción.
- Reconfigura el Webhook para el tópico
orders. Desactiva el tópicopaymentsolo después de migrar el tráfico nuevo y de finalizar el monitoreo de las transacciones y notificaciones pendientes de Payments API. - Garantiza el tratamiento de todos los valores de
statusystatus_detailen ambos niveles: order y transacción.
Después de aplicar los cambios, verifica que la integración funcione correctamente en todos los flujos antes de salir a producción. Usa los checkboxes a continuación para confirmar cada punto.