Cómo migrar de la Instore Orders V2 API a la Orders API
La migración de la Instore Orders V2 API a la Orders API implica la actualización de endpoints y campos de la solicitud, la consolidación del modelo de notificaciones y el aprovechamiento de nuevos recursos nativos, como los endpoints dedicados de cancelación y reembolso. El principal cambio en la creación es que la Orders API retorna 201 Created con el objeto completo de la order, en lugar de 204 No Content sin body. La migración no implica cambios en el flujo de negocio: el cliente continúa escaneando el Código QR con la aplicación de Mercado Pago y confirmando el pago.
Consulta a continuación cómo realizar esta migración de forma completa.
Mapear los cambios de endpoint
Antes de iniciar los pasos de migración, consulta la tabla a continuación para tener una visión general de todos los cambios de endpoint. En la Instore Orders V2 API, cada operación utilizaba una URL con el identificador del usuario, de la tienda y de la caja en el path. La Orders API consolida estas operaciones en endpoints estandarizados identificados por el order_id.
| Operación | Instore Orders V2 API | Orders API |
| Crear order | PUT /instore/qr/seller/collectors/{user_id}/stores/{external_store_id}/pos/{external_pos_id}/ordersAPI | POST /v1/ordersAPI |
| Consultar order | GET /instore/qr/seller/collectors/{user_id}/pos/{external_pos_id}/ordersAPI | GET /v1/orders/{order_id}API |
| Cancelar order | DELETE /instore/qr/seller/collectors/{user_id}/pos/{external_pos_id}/ordersAPI | POST /v1/orders/{order_id}/cancelAPI |
| Reembolsar order | Vía API de Payments (sin endpoint dedicado en la Instore Orders V2 API) | POST /v1/orders/{order_id}/refundAPI |
Actualizar el modelo de status y notificaciones
Uno de los cambios más significativos entre la Instore Orders V2 API y la Orders API es el modelo de status. En la Instore Orders V2 API, el estado de una transacción era determinado por el monitoreo de notificaciones de dos tópicos independientes: payments y merchant_orders con campos y valores distintos para cada uno. La Orders API unifica ese comportamiento en un único campo status en la order. Consulta el mapeo completo a continuación.
Además, la Orders API también introduce el campo status_detail, que permite identificar con mayor detalle el estado de la transacción. Los valores posibles son created, canceled, accredited, refunded y expired.
En la Instore Orders V2 API, la merchant_order es creada en el momento en que el pedido es generado, por lo que las notificaciones de este tópico están disponibles desde el inicio del flujo. El objeto payment, por otro lado, solo es creado cuando existe un intento de pago, aprobado o rechazado. Quien monitoreaba únicamente el tópico payments no recibía ninguna notificación hasta que el usuario iniciaba el proceso de pago. En la Orders API, ese comportamiento es unificado: el campo status de la order refleja el estado completo desde la creación, sin necesidad de monitorear dos tópicos independientes.
Tópico payments (status) | Tópico merchant_orders (status / order_status) | Orders API (status) | Observación |
| — | opened (sin pago o con pago rechazado) | created | En la Instore Orders V2 API, opened indicaba que el pedido aún no tenía un pago aprobado. En la Orders API, ese estado es explícito desde la creación. |
approved | closed + order_status: "paid" | processed | Ambos tópicos convergían en el mismo resultado: pago aprobado. En la Orders API, el estado es autocontenido. |
rejected | opened (la merchant_order no cambia de estado y permanece abierta) | Sin equivalente | En la Instore Orders V2 API, un pago rechazado dejaba la merchant_order en opened esperando un nuevo intento. En la Orders API, los pagos rechazados no son expuestos. El estado permanece en created hasta recibir un pago aprobado. |
refunded | closed + order_status: "reverted" | refunded | Reembolso total. En el tópico merchant_orders, identificable por order_status: "reverted". |
refunded (parcial, status_detail: "partially_refunded") | closed + pago con status_detail: "partially_refunded" | refunded | Reembolso parcial. En la Instore Orders V2 API, era necesario inspeccionar el status_detail del pago dentro de la merchant_order. En la Orders API, el estado es el mismo que el reembolso total, pero el status_detail indica partially_refunded. |
| — | — | canceled | Nuevo status sin equivalencia en la Instore Orders V2 API. |
| — | — | expired | Nuevo status sin equivalencia en la Instore Orders V2 API. |
En cuanto a las notificaciones, en la API Legacy podían configurarse mediante el campo notification_url en el body de la solicitud (modelo IPN) o mediante webhooks con los tópicos payments y merchant_orders. En la Orders API, el campo notification_url no existe y los tópicos payments y merchant_orders no son compatibles. Configura las notificaciones en Tus integraciones, suscribiéndote al tópico "Order (Mercado Pago)" (orders), antes de ir a producción. Para más información, consulta la documentación de notificaciones.
Adaptar los headers
La Orders API introduce un cambio obligatorio de header que afecta a todos los endpoints. El Access Token debe enviarse vía header Authorization. El envío vía query param no está permitido en la Orders API. Aplica el cambio a continuación antes de probar cualquier otro recurso.
El header X-Idempotency-Key es obligatorio en las operaciones de creación, cancelación y reembolso de orders. Garantiza que una solicitud repetida con la misma clave retorne el resultado original sin procesar la operación nuevamente. Envía un UUID v4 o string aleatoria única por solicitud. Las operaciones de tipo GET no requieren este header.
X-Idempotency-Key es reutilizada con un body diferente, la API retornará el error idempotency_key_already_used. Genera una nueva clave para cada operación distinta.Migrar la creación de orders
El endpoint de creación cambia de PUT /instore/qr/seller/collectors/{user_id}/stores/{external_store_id}/pos/{external_pos_id}/ordersAPI a POST /v1/ordersAPI. Además del cambio de método de PUT a POST y de la URL, la respuesta pasa de HTTP 204 No Content sin body a 201 Created con el objeto completo de la order. El {user_id} y los parámetros de path de tienda y caja son eliminados. La identidad proviene del Access Token y la caja es identificada por el campo config.qr.external_pos_id en el body. Sigue los pasos a continuación para adaptar la solicitud, la respuesta y el tratamiento de errores.
204 No Content sin body, lo que hacía imposible obtener el id del pedido para operaciones posteriores. La Orders API retorna 201 Created con el objeto completo de la order. El campo id del response es necesario para consultas, cancelaciones y reembolsos posteriores.En la Orders API, la identidad del usuario es obtenida directamente del Access Token. El {external_store_id} y el {user_id} dejan de ser parámetros de path. La caja pasa a ser identificada por el campo config.qr.external_pos_id en el body. Los campos type, con valor "qr", y external_reference pasan a ser obligatorios. La tabla a continuación presenta los campos que existían en ambas APIs y sufrieron cambios en la migración.
| Instore Orders V2 API | Orders API | Descripción | Cambio |
{user_id} (path param) | No existe | Identificador del usuario de Mercado Pago. En la Orders API, la identidad es obtenida directamente del Access Token. | Deja de ser parámetro de path. |
{external_store_id} (path param) | No existe | Identificador externo de la tienda. | Deja de ser parámetro de path. La tienda es identificada indirectamente por la caja. |
{external_pos_id} (path param) | config.qr.external_pos_id | Identificador externo de la caja. En la Instore Orders V2 API, era enviado en el path. En la Orders API, es enviado en el body dentro de config.qr. | Deja de ser parámetro de path y pasa al body. |
external_reference | external_reference | Referencia que puede sincronizar con el sistema de venta del integrador. En la Orders API, es obligatorio, con un máximo de 64 caracteres, solo letras, números, - y _. No puede contener datos PII. | Pasa a ser obligatorio. |
title | No existe | Título de la compra. En la Orders API, la descripción es suficiente. | Eliminado. |
description | description | Descripción de la compra. En la Instore Orders V2 API, existía tanto en el nivel raíz como dentro de items[]. En la Orders API, existe solo en el nivel raíz. Máx. 150 caracteres. No debe contener datos PII. | Permanece en el nivel raíz. La versión dentro de items[] fue eliminada. |
items[].description | No existe | Descripción del ítem. | Eliminado. La descripción es gestionada solo en el nivel raíz de la order. |
notification_url | No existe | URL para recibir notificaciones de pago o merchant_order. En la Orders API, las notificaciones se configuran como webhook en tu aplicación dentro de Tus integraciones, seleccionando el tópico "Order (Mercado Pago)". Para más información, accede a la documentación de notificaciones. | Eliminado del body. |
expiration_date | expiration_time | Validez del pedido. En la Instore Orders V2 API, era una fecha absoluta (ej.: 2020-08-22T16:34:56.559-04:00). En la Orders API, es una duración relativa en formato ISO 8601 (ej.: PT5M). El valor mínimo es PT30S y el valor máximo es PT3H. En todos los modos (QR Dinámico, QR Estático y QR Híbrido), el valor predeterminado es de 15 minutos y el valor enviado siempre es respetado. | Cambia de fecha absoluta a duración relativa en formato ISO 8601. |
sponsor.id | integration_data.sponsor.id | USER_ID de la cuenta de Mercado Pago del sistema integrador. | Pasa al nodo integration_data.sponsor. |
items[].sku_number | items[].external_code | Código del ítem en el sistema externo. | Renombrado a items[].external_code. |
items[].category | No existe | Categoría del ítem. | Eliminado. No tiene equivalente en la Orders API. |
items[].title | items[].title | Nombre del ítem. En la Orders API, máx. 150 caracteres. | Pasa a ser obligatorio. |
items[].unit_price | items[].unit_price | Precio unitario del ítem. En la Instore Orders V2 API, era number. En la Orders API, es string decimal. Acepta dos decimales (ej.: "15.00") o ninguno. | Cambia de number a string decimal y pasa a ser obligatorio. |
items[].quantity | items[].quantity | Cantidad de ítems. En la Instore Orders V2 API, era number. En la Orders API, es integer. | Cambia de number a integer y pasa a ser obligatorio. |
items[].unit_measure | items[].unit_measure | Unidad de medida del ítem. Máx. 10 caracteres. | Pasa a ser obligatorio. |
items[].total_amount | No existe | Total de ítems (precio unitario × cantidad). | Eliminado. No tiene equivalente en la Orders API. |
items[].external_categories[].id | items[].external_categories[].id | Identificador de categoría del ítem en el sistema externo. Habilita descuentos por categoría. No puede usarse junto con discounts. | Sin cambio. |
marketplace_fee | marketplace_fee | Valor de la tarifa del marketplace. En la Instore Orders V2 API, era number. En la Orders API, es string decimal. Acepta dos decimales (ej.: "15.00") o ninguno. Exclusivo para integraciones con OAuth. | Cambia de number a string decimal. |
total_amount | transactions.payments[].amount | Valor total de la transacción. En la Instore Orders V2 API, era el campo total_amount en el nivel raíz. En la Orders API, el valor del pago es enviado dentro de transactions.payments[]. Acepta dos decimales (ej.: "15.00") o ninguno. | Pasa al nodo transactions.payments. Cambia de number a string decimal. |
La Orders API también introduce los siguientes campos sin equivalencia en la Instore Orders V2 API.
| Campo | Descripción |
type | Tipo de order. Para pagos con Código QR, el único valor posible es "qr". Obligatorio. |
total_amount | Valor total de la order. Representa la suma de todas las transacciones. Acepta dos decimales (ej.: "15.00") o ninguno. |
config.qr.mode | Modo de Código QR. Valores: static (Código QR estático asociado a la caja, equivalente al comportamiento de la Instore Orders V2 API), dynamic (Código QR único por transacción, retornado en type_response.qr_data), hybrid (ambos modos en paralelo). Valor predeterminado: static. |
discounts.payment_methods[].new_total_amount | Nuevo valor total de la order cuando se aplica un descuento. Acepta dos decimales (ej.: "15.00") o ninguno. No puede usarse junto con items[].external_categories. |
discounts.payment_methods[].type | Medio de pago al que se aplica el descuento. Valores: debit_card, credit_card, account_money, prepaid_card. Hasta 4 medios pueden ser definidos. |
integration_data.platform_id | Identificador de la plataforma, asignado por Mercado Pago. |
integration_data.integrator_id | Identificador del integrador, asignado por Mercado Pago. Debe tener el prefijo dev_. |
La Instore Orders V2 API retornaba HTTP 204 No Content sin body en la creación. La Orders API retorna 201 Created con el objeto completo de la order. La tabla a continuación presenta los campos del response de la nueva API.
| Campo | Descripción |
id | Identificador de la order creada (ej.: ORD00001111222233334444555566). En la Instore Orders V2 API, no había body en el response de creación. Es necesario para consultas, cancelaciones y reembolsos. |
user_id | Identificador del usuario de Mercado Pago que creó la order. Renombrado de collector_id (integer) a user_id (string). |
total_amount | Valor total de la order. Cambia de number a string decimal. |
external_reference | Referencia externa de la order. |
description | Descripción del producto o servicio. Permanece en el nivel raíz. La versión dentro de items[] fue eliminada. |
marketplace_fee | Tarifa del marketplace. Cambia de number a string decimal. |
integration_data.sponsor.id | USER_ID del sistema integrador. Movido de sponsor_id (integer) a integration_data.sponsor (string). |
country_code | Identificador del sitio/país (ej.: "AR"). Renombrado de site_id. El formato cambia de minúsculas a mayúsculas. |
type | Tipo de order. Para Código QR: siempre qr. |
expiration_time | Duración de expiración en formato ISO 8601. Sustituye expiration_date (fecha absoluta) por duración relativa. |
processing_mode | Modo de procesamiento. Para Código QR: siempre automatic. Sustituye el array processing_modes. |
status | Estado actual de la order. Al crear: created. En la Instore Orders V2 API, el estado era obtenido solo vía webhooks. |
status_detail | Detalle del estado actual de la order. Los valores posibles son created, canceled, accredited, refunded, expired. |
currency | Identificador de la moneda. Valores: ARS, BRL, CLP, UYU. En la Instore Orders V2 API, la moneda provenía de items[].currency_id. |
created_date | Fecha de creación. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
last_updated_date | Fecha de última actualización. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
config.qr.external_pos_id | Identificador externo de la caja asociada a la order. En la Instore Orders V2 API, era parámetro de path de entrada y no era retornado. |
config.qr.mode | Modo de Código QR configurado. Valores: static, dynamic, hybrid. |
transactions.payments[].id | Identificador de la transacción de pago. En la Instore Orders V2 API, el ID del pago llegaba solo vía webhook del tópico payments. |
transactions.payments[].amount | Valor del pago. En la Instore Orders V2 API, el valor estaba en total_amount en el nivel del pedido. |
transactions.payments[].status | Estado del pago. Al crear: created. |
transactions.payments[].status_detail | Detalle del estado del pago. Al crear: ready_to_process. |
type_response.qr_data | Trama de Código QR para conversión en código QR. Presente solo cuando config.qr.mode es dynamic o hybrid. |
integration_data.application_id | Identificador de la aplicación de Mercado Pago. |
integration_data.platform_id | Identificador de la plataforma, asignado por Mercado Pago. |
integration_data.integrator_id | Identificador del integrador, asignado por Mercado Pago. |
items[].title | Nombre del ítem. |
items[].unit_price | Precio unitario del ítem. |
items[].quantity | Cantidad de ítems. |
items[].unit_measure | Unidad de medida del ítem. |
items[].external_categories[].id | Identificador de categoría del ítem en el sistema externo. |
discounts.payment_methods[].new_total_amount | Nuevo valor total de la order cuando se aplica un descuento. |
discounts.payment_methods[].type | Medio de pago al que se aplica el descuento. |
La Orders API consolida la mayoría de los errores de validación específicos por campo en los códigos genéricos property_value y property_type, con el detalle del campo en el cuerpo de la respuesta. Además, los mensajes de respuesta son más descriptivos, facilitando la identificación y resolución de problemas. Consulta las tablas a continuación para más detalles.
Errores que cambian de comportamiento
Los siguientes errores existen en ambas APIs pero con comportamiento diferente en la Orders API.
| HTTP | Instore Orders V2 API | Orders API | Observación |
400 | Múltiples: invalid_collectorId, invalid_externalStoreId, invalid_externalPosId, invalid_total_amount, invalid_items.* y otros | property_value | property_value consolida los errores de validación por campo. El campo con error está indicado en el detalle de la respuesta. |
400 | error_creating_seller_qr_order (JSON malformado) | property_type | La Orders API distingue JSON malformado con un código propio en lugar del genérico error_creating_seller_qr_order. |
400 | error_creating_seller_qr_order (errores generales) | bad_request | El código genérico error_creating_seller_qr_order abarcaba múltiples errores. La Orders API usa bad_request para casos no cubiertos por otros códigos. |
400 | error_invalid_sponsor_id | sponsor_id_not_valid | El campo migra a integration_data.sponsor.id. |
400 → 401 | autenticación vía middleware | unauthorized | En la Instore Orders V2 API, la autenticación fallida retornaba 400. En la Orders API, es 401 explícito. |
404 | pos_obtainment_error | pos_not_found | El external_pos_id deja de ser parámetro de path y pasa al body. |
Errores que permanecen iguales
El siguiente error tiene el mismo comportamiento en ambas APIs.
| HTTP | Error | Observación |
500 | Genérico | Error interno. Verifica el retorno y repite la solicitud. |
Errores introducidos por la Orders API
Los siguientes errores no tienen equivalencia en la Instore Orders V2 API.
| HTTP | Error | Observación |
400 | marketplace_not_valid | El Access Token no fue obtenido vía OAuth y no es posible identificar un marketplace válido. |
400 | empty_required_header | X-Idempotency-Key ausente. |
400 | unsupported_site | Intento de crear la order en un país no soportado. |
400 | unsupported_properties | Propiedad no soportada en el body. El campo con error está indicado en el detalle de la respuesta. |
404 | marketplace_fee_not_allowed | No está permitido enviar marketplace_fee porque el marketplace no fue encontrado. |
409 | idempotency_key_already_used | El X-Idempotency-Key ya fue utilizado con una solicitud distinta en las últimas 24 horas. |
Actualizar la consulta de orders
El endpoint de consulta cambia de GET /instore/qr/seller/collectors/{user_id}/pos/{external_pos_id}/ordersAPI a GET /v1/orders/{order_id}API. En la Instore Orders V2 API, la consulta era realizada por caja (external_pos_id), retornando la order activa en esa caja sin exponer el estado de la transacción. La Orders API sustituye el endpoint de consulta por caja por un endpoint que opera directamente por el order_id y retorna el estado completo de la transacción: status, pagos, reembolsos y datos del medio de pago. En la Instore Orders V2 API, esa información llegaba solo por notificación.
curlcurl -X GET \ 'https://api.mercadopago.com/v1/orders/{{ORDER_ID}}' \ -H 'Authorization: Bearer {{ACCESS_TOKEN}}'
La tabla a continuación presenta los campos del response de consulta que existían en ambas APIs y sufrieron cambios en la migración.
| Instore Orders V2 API | Orders API | Descripción | Cambio |
| No existe | id | Identificador de la order. En la Instore Orders V2 API, el endpoint de consulta no retornaba el ID del pedido. | Campo nuevo. |
| No existe | user_id | Identificador del usuario que creó la order. En la Instore Orders V2 API, era parámetro de path pero no era retornado en el response. | Campo nuevo. |
| No existe | type | Tipo de order. Para Código QR: siempre qr. | Campo nuevo. |
external_reference | external_reference | Referencia externa de la order. | Sin cambio. |
description | description | Descripción de la compra. | Sin cambio. |
title | No existe | Título de la compra. | Eliminado. |
notification_url | No existe | URL configurada para notificaciones. | Eliminado. Configura las notificaciones webhook en tu aplicación. Para más información, accede a la documentación de notificaciones. |
expiration_date | expiration_time | Validez del pedido. En la Instore Orders V2 API, era fecha absoluta. En la Orders API, es duración relativa en formato ISO 8601. | Cambia de fecha absoluta a duración relativa. |
| No existe | processing_mode | Modo de procesamiento. Para Código QR: siempre automatic. | Campo nuevo. |
total_amount | total_amount | Valor total de la order. En la Instore Orders V2 API, era number. En la Orders API, es string decimal. | Cambia de number a string decimal. |
| No existe | country_code | Identificador del sitio/país. | Campo nuevo. |
marketplace_fee | marketplace_fee | Tarifa del marketplace. En la Instore Orders V2 API, era number. En la Orders API, es string decimal. | Cambia de number a string decimal. |
sponsor.id | integration_data.sponsor.id | USER_ID del sistema integrador. En la Instore Orders V2 API, era integer. En la Orders API, es string. | Pasa a integration_data.sponsor. Cambia de integer a string. |
items[].title | items[].title | Nombre del ítem. | Sin cambio. |
items[].unit_price | items[].unit_price | Precio unitario del ítem. En la Instore Orders V2 API, era number. En la Orders API, es string decimal. | Cambia de number a string decimal. |
items[].quantity | items[].quantity | Cantidad de ítems. | Sin cambio. |
items[].unit_measure | items[].unit_measure | Unidad de medida del ítem. | Sin cambio. |
items[].external_categories[].id | items[].external_categories[].id | Identificador de categoría del ítem en el sistema externo. | Sin cambio. |
En la migración a la Orders API, los siguientes campos de items[] fueron eliminados y no tienen equivalente directo.
| Campo | Observación |
items[].description | Eliminado. La descripción es gestionada solo en el nivel raíz de la order. |
items[].sku_number | items[].external_code |
items[].category | Eliminado. No tiene equivalente en la Orders API. |
items[].currency_id | Eliminado. La moneda es expuesta a nivel de order en el campo currency. |
items[].total_amount | Eliminado. No tiene equivalente en la Orders API. |
items[].discount | Eliminado. La estructura de descuentos migró a discounts.payment_methods[]. |
La Orders API también introduce los siguientes campos en la respuesta de consulta.
| Campo | Descripción |
status | Estado actual de la order. Valores: created, canceled, processed, refunded, expired. En la Instore Orders V2 API, el estado solo era visible vía notificaciones de payments y merchant_orders. |
status_detail | Detalle del estado actual de la order. Los valores posibles son created, canceled, accredited, refunded, expired. |
currency | Identificador de la moneda. Valores: ARS, BRL, CLP, UYU. |
created_date | Fecha de creación. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
last_updated_date | Fecha de última actualización. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
config.qr.external_pos_id | Identificador externo de la caja asociada a la order. |
config.qr.mode | Modo de Código QR configurado. |
integration_data.application_id | Identificador de la aplicación de Mercado Pago. |
integration_data.platform_id | Identificador de la plataforma, asignado por Mercado Pago. |
integration_data.integrator_id | Identificador del integrador, asignado por Mercado Pago. |
transactions.payments[].id | Identificador de la transacción de pago. En la Instore Orders V2 API, el ID del pago llegaba solo vía webhook del tópico payments. |
transactions.payments[].amount | Valor del pago. |
transactions.payments[].refunded_amount | Valor reembolsado. Presente solo cuando hubo un reembolso. |
transactions.payments[].paid_amount | Valor total pagado. |
transactions.payments[].status | Estado actual del pago. |
transactions.payments[].status_detail | Estado detallado del pago. |
transactions.payments[].reference_id | Identificador del pago asociado a la order. |
transactions.payments[].payment_method.type | Medio de pago seleccionado. |
transactions.payments[].payment_method.installments | Cantidad de cuotas. |
transactions.payments[].payment_method.id | Identificador del medio de pago o marca. |
transactions.payments[].discounts.type | Medio de pago con el que se aplicó el descuento. Presente solo si se aplicó un descuento. |
transactions.refunds[].id | Identificador del reembolso. |
transactions.refunds[].transaction_id | Identificador del pago reembolsado. |
transactions.refunds[].reference_id | Identificador que asocia la transacción al reembolso. |
transactions.refunds[].amount | Valor del reembolso. |
transactions.refunds[].status | Estado del reembolso. |
items[].external_code | Código externo del ítem (ej.: EAN). |
En la consulta, los errores fueron agrupados según el tipo de cambio. Consulta las tablas a continuación para más detalles.
Errores que desaparecen
Los siguientes errores existen en la Instore Orders V2 API pero no tienen equivalencia en la Orders API.
| HTTP | Instore Orders V2 API | Observación |
400 | invalid_collectorId | Eliminado en la Orders API. La consulta opera sobre el order_id. |
400 | invalid_externalPosId | Eliminado. La consulta opera sobre order_id, no sobre la caja. |
400 | pos_obtainment_by_external_id_error | Eliminado. El concepto de POS como parámetro de consulta desaparece. |
400 | pos_deleted_error | Eliminado en la Orders API. |
403 | forbidden | Eliminado en la Orders API. |
Errores renombrados
Los siguientes errores fueron renombrados en la Orders API.
| HTTP | Instore Orders V2 API | Orders API | Observación |
404 | point_of_sale_in_store_order_not_found y in_store_order_not_found | order_not_found | Los dos casos de not found son unificados en order_not_found. |
Errores que cambian de comportamiento
Los siguientes errores existen en ambas APIs pero con un comportamiento diferente en la Orders API.
| HTTP | Instore Orders V2 API | Orders API | Observación |
400 → 401 | autenticación vía middleware | unauthorized | En la Instore Orders V2 API, era 400. En la Orders API, es 401 explícito. |
Errores introducidos por la Orders API
Los siguientes errores no tienen equivalencia en la Instore Orders V2 API.
| HTTP | Error | Observación |
400 | invalid_path_param | El order_id tiene formato inválido. Debe comenzar con ORD seguido de 26 caracteres. |
401 | unauthorized | Access Token inválido o expirado. |
404 | order_not_found | El order_id no corresponde a ninguna order creada. |
500 | Genérico | Error interno. Verifica el retorno y repite la solicitud. |
Actualizar la cancelación de orders
El endpoint de cancelación cambia de DELETE /instore/qr/seller/collectors/{user_id}/pos/{external_pos_id}/ordersAPI a POST /v1/orders/{order_id}/cancelAPI. El método HTTP cambia de DELETE a POST, el {user_id} y el {external_id} salen del path, y la cancelación pasa a operar sobre el order_id. El response pasó de vacío (HTTP 204) al objeto completo de la order con status: "canceled" (HTTP 200).
En la Instore Orders V2 API, la cancelación eliminaba la order activa asociada a la caja, una operación sobre la caja y no sobre la transacción individual. En la Orders API, la cancelación opera directamente sobre la order por el order_id, sin depender de la caja en el path.
El response retorna el objeto completo de la order con status: "canceled". El header necesario en esta operación es:
| Header | Obligatoriedad | Descripción |
X-Idempotency-Key | Obligatorio | Clave única por solicitud. |
El response retorna el objeto completo de la order con status: "canceled". En la Instore Orders V2 API, la cancelación retornaba HTTP 204 sin body. La tabla a continuación lista los campos retornados en el response de cancelación.
| Campo | Descripción |
id | Identificador de la order cancelada, generado por Mercado Pago. |
user_id | Identificador del usuario de Mercado Pago que creó la order. |
type | Tipo de order. Para Código QR: siempre qr. |
external_reference | Referencia externa de la order, asignada en el momento de la creación. |
description | Descripción del producto o servicio, motivo de la order. |
expiration_time | Tiempo de expiración de la order en formato ISO 8601. |
processing_mode | Modo de procesamiento. Para Código QR: siempre automatic. |
total_amount | Valor total de la order. |
country_code | Identificador del sitio/país de la aplicación de Mercado Pago. |
marketplace_fee | Tarifa del marketplace. Exclusivo para integraciones con OAuth. |
integration_data.application_id | Identificador de la aplicación de Mercado Pago que creó la order. |
integration_data.platform_id | Identificador de la plataforma, asignado por Mercado Pago. |
integration_data.integrator_id | Identificador del integrador, asignado por Mercado Pago. |
integration_data.sponsor.id | USER_ID del sistema integrador. |
status | Estado actual de la order. Al cancelar: canceled. |
status_detail | Detalle del estado actual de la order. Al cancelar: canceled. |
currency | Identificador de la moneda utilizada. Valores: ARS, BRL, CLP, UYU. |
created_date | Fecha de creación de la order. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
last_updated_date | Fecha de última actualización de la order. Formato yyyy-MM-ddTHH:mm:ss.sssZ. |
config.qr.external_pos_id | Identificador externo de la caja asociada a la order. |
config.qr.mode | Modo de Código QR configurado. Valores: static, dynamic, hybrid. |
transactions.payments[].id | Identificador de la transacción de pago, generado por Mercado Pago. |
transactions.payments[].amount | Valor del pago. |
transactions.payments[].status | Estado del pago. Al cancelar: canceled. |
transactions.payments[].status_detail | Detalle del estado del pago. Al cancelar: canceled_by_api. |
items[].title | Nombre del ítem. |
items[].unit_price | Precio unitario del ítem. |
items[].quantity | Cantidad de ítems. |
items[].unit_measure | Unidad de medida del ítem. |
items[].external_code | Código externo del ítem (ej.: EAN). |
items[].external_categories[].id | Identificador de categoría del ítem en el sistema externo. |
discounts.payment_methods[].new_total_amount | Nuevo valor total de la order cuando se aplica un descuento. |
discounts.payment_methods[].type | Medio de pago al que se aplica el descuento. |
En la cancelación, los errores fueron agrupados según el tipo de cambio. Consulta las tablas a continuación para más detalles.
Errores que desaparecen
Los siguientes errores existen en la Instore Orders V2 API pero no tienen equivalencia en la Orders API.
| HTTP | Instore Orders V2 API | Observación |
400 | invalid_collector_id | Eliminado en la Orders API. |
400 | pos_deleted_error | Eliminado en la Orders API. |
401 | unauthorized (authorization value not present) | Eliminado. Ocurría al enviar {user_id} alfanumérico. La identidad es obtenida directamente del Access Token. |
403 | forbidden | Eliminado. La identidad es validada internamente por el Access Token. |
Errores renombrados
Los siguientes errores fueron renombrados en la Orders API.
| HTTP | Instore Orders V2 API | Orders API | Observación |
400 → 404 | pos_obtainment_by_external_id_error y in_store_order_delete_error | order_not_found | En la Instore Orders V2 API, era 400. En la Orders API, es 404. La cancelación pasa a operar sobre el order_id. |
409 | in_store_order_delete_error (Cannot delete a locked order) | instore_order_locked_error | Mismo concepto. El nombre del código de error cambia. |
Errores que cambian de comportamiento
Los siguientes errores existen en ambas APIs pero con un comportamiento diferente en la Orders API.
| HTTP | Instore Orders V2 API | Orders API | Observación |
400 → 401 | invalid_access_token | unauthorized | En la Instore Orders V2 API, era 400. En la Orders API, es 401. |
Errores que permanecen iguales
El siguiente error tiene el mismo comportamiento en ambas APIs.
| HTTP | Error | Observación |
500 | Genérico | Error interno. Verifica el retorno y repite la solicitud. |
Errores introducidos por la Orders API
Los siguientes errores no tienen equivalencia en la Instore Orders V2 API.
| HTTP | Error | Observación |
400 | empty_required_header | X-Idempotency-Key ausente. |
400 | invalid_path_param | El order_id tiene formato inválido. |
401 | unauthorized | Access Token inválido o expirado. |
404 | order_not_found | El order_id no corresponde a ninguna order creada. |
409 | idempotency_key_already_used | El X-Idempotency-Key ya fue utilizado con una solicitud distinta. |
409 | order_already_canceled | La order ya está cancelada. Las orders solo pueden ser canceladas con status: created. |
Implementar reembolsos con el endpoint dedicado
La Orders API introduce el endpoint dedicado POST /v1/orders/{order_id}/refundAPI para reembolsos, que no existía en la Instore Orders V2 API. Anteriormente, era necesario recibir el webhook del pago, obtener el payment_id y ejecutar el reembolso por la API de Payments por separado. Ahora, el reembolso es realizado directamente sobre la order.
Elige entre reembolso total o parcial según el valor a devolver.
Para reembolsar el valor total de la order, envía la solicitud al endpoint POST /v1/orders/{order_id}/refundAPI sin body.
curlcurl -X POST \ 'https://api.mercadopago.com/v1/orders/{{ORDER_ID}}/refund' \ -H 'Authorization: Bearer {{ACCESS_TOKEN}}' \ -H 'X-Idempotency-Key: {{IDEMPOTENCY_KEY}}'
Los reembolsos son aceptados hasta 360 días a partir de la fecha del pago.
El response del reembolso varía según el tipo de operación realizada.
| Campo | Tipo | Descripción |
id | string | Identificador de la order reembolsada. |
status | string | refunded para reembolso total. processed para reembolso parcial (aún hay saldo disponible). |
status_detail | string | refunded para reembolso total. partially_refunded para reembolso parcial. |
transactions.refunds[].id | string | Identificador del reembolso, generado por Mercado Pago. |
transactions.refunds[].transaction_id | string | Identificador de la transacción de pago que está siendo reembolsada. |
transactions.refunds[].amount | string | Valor del reembolso. Si el pago fue realizado con descuento, refleja ese valor. |
transactions.refunds[].status | string | processing cuando el reembolso total fue solicitado y está en procesamiento. processed cuando el reembolso parcial fue concluido con éxito. |
transactions.refunds[].reference_id | string | Identificador que asocia el pago a su respectivo reembolso. |
Validar la migración
Después de aplicar los cambios, verifica que la integración opere correctamente en todos los flujos antes de ir a producción.
El header X-Idempotency-Key debe estar presente en todas las operaciones de creación, cancelación y reembolso.
Orders creadas con éxito con el nuevo payload en el endpoint POST /v1/ordersAPI y el campo id capturado del response.
Orders consultadas con éxito a través del endpoint GET /v1/orders/{order_id}API.
Status de orders monitoreados vía webhook con el tópico "Order (Mercado Pago)" y los nuevos valores: created, processed, canceled, refunded y expired.
Orders canceladas con éxito a través del endpoint POST /v1/orders/{order_id}/cancelAPI.
Reembolsos ejecutados a través del endpoint dedicado POST /v1/orders/{order_id}/refundAPI.
Accede a la documentación para saber cómo probar la integración.