Cómo migrar de la API de Intención de Pago a la API de Orders
La API de Orders unifica el procesamiento de pagos presenciales en Mercado Pago Point, ofreciendo endpoints estandarizados, un modelo de status más completo y nuevos recursos nativos que no existían en la API de Intención de Pago. Además, todas las nuevas funcionalidades de Mercado Pago se desarrollarán sobre la API de Orders.
La migración de la integración de Mercado Pago Point de la API de Intención de Pago a la API de Orders implica la actualización de endpoints y campos de la solicitud, la adaptación del modelo de status y el aprovechamiento de nuevos recursos nativos, como el endpoint dedicado de reembolso. La migración no implica cambios en el flujo de negocio: la terminal sigue recibiendo las orders creadas por el backend y procesando los pagos de forma autónoma.
A continuación, te explicamos 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 API de Intención de Pago, cada operación utilizaba una estructura de URL propia con el identificador del dispositivo en el path. La API de Orders consolida estas operaciones en endpoints estandarizados y elimina el {deviceid} del path en todas las operaciones.
La API de Orders introduce dos cambios obligatorios de headers que afectan a todos los endpoints: el mecanismo de sandbox fue eliminado y un nuevo control de idempotencia fue introducido. Aplica los cambios a continuación antes de probar cualquier otro recurso.
El headerx-test-scope: sandbox era utilizado en la API de Intención de Pago para identificar solicitudes de prueba. En la API de Orders, el mecanismo de sandbox fue reestructurado y ese header ya no existe. Elimínalo de todas las solicitudes de la integración. Para operar en ambiente de prueba en la API de Orders, utiliza usuarios de prueba. Consulta la documentación de pruebas para más información.
El headerX-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 devuelva el resultado original sin procesar la operación nuevamente. Envía un UUID v4 o string aleatorio único por solicitud. Las operaciones de tipo GET no requieren este header.
Si se reutiliza la misma X-Idempotency-Key con un body diferente, la API devolverá el error idempotency_key_already_used. Genera una clave distinta para cada nueva operación.
Actualizar el listado y configuración de terminales
Los endpoints de terminales cambiaron de URL: el listado pasa de GET /point/integration-api/devices a GET /terminals/v1/list y la actualización de modo pasa de PATCH /point/integration-api/devices/{device_id} a PATCH /terminals/v1/setup. En la actualización de modo, el identificador de la terminal también deja el path y pasa al body, lo que permite actualizar múltiples terminales en una única llamada.
En la API de Intención de Pago, los dispositivos eran devueltos en el arraydevices. En la API de Orders, pasan a data.terminals. Los query params store_id, pos_id, limit y offset se mantienen iguales. La tabla a continuación describe los cambios en la respuesta.
API de Intención de Pago
API de Orders
Descripción
Cambio
devices[]
data.terminals[]
Lista de terminales asociadas a la cuenta. En la API de Intención de Pago, era devuelto como array directo en devices. En la API de Orders, es movido dentro del objeto data y renombrado a terminals.
Renombrado y movido dentro del objeto data.
devices[].id
data.terminals[].id
Identificador único de la terminal. Los últimos caracteres coinciden con el serial en la etiqueta trasera de la terminal.
Mismo concepto. El formato del ID puede variar según el modelo de la terminal.
devices[].pos_id
data.terminals[].pos_id
Identificador de la caja asociada a la terminal.
Sin cambios.
devices[].store_id (integer)
data.terminals[].store_id (string)
Identificador de la sucursal asociada a la terminal. En la API de Intención de Pago, era devuelto como entero. En la API de Orders, es devuelto como string.
Cambia de integer a string.
devices[].external_pos_id
data.terminals[].external_pos_id
Identificador externo de caja, definido por el integrador.
Sin cambios.
devices[].operating_mode
data.terminals[].operating_mode
Modo de operación de la terminal. En la API de Intención de Pago, los valores posibles son PDV y STANDALONE. En la API de Orders, el valor UNDEFINED es añadido para configuraciones no reconocidas.
Incorpora el valor UNDEFINED para configuración no reconocida.
paging.total / paging.offset / paging.limit
paging.total / paging.offset / paging.limit
Datos de paginación del listado: total de registros, punto de inicio y límite.
Sin cambios.
En el listado de terminales, los errores fueron agrupados según el tipo de cambio. Consulta las tablas a continuación para más detalles.
Errores no documentados en la API de Orders
Los siguientes errores existen en la API de Intención de Pago pero no están documentados en la API de Orders.
HTTP
API de Intención de Pago
Observación
400
bad_request
Parámetro obligatorio ausente o con formato incorrecto.
400
bad_request
Formato de solicitud inválido.
403
forbidden
Presente en la API de Intención de Pago.
Errores que permanecen igual
Los siguientes errores tienen el mismo comportamiento en ambas APIs.
HTTP
Error
Observación
401
unauthorized
Token inválido o expirado.
500
internal_error
Error interno. Verificar el retorno y reintentar.
En la API de Intención de Pago, solo era posible actualizar una terminal por llamada y su identificador se enviaba en el path. En la API de Orders, el identificador migra al body dentro del arrayterminals[], lo que permite actualizar múltiples terminales en una única llamada.
A continuación, un ejemplo comparativo de actualización de modo de operación.
Actualización del modo de operación vía API de Intención de Pago. El identificador de la terminal se envía como path param.
En la API de Intención de Pago, la respuesta devuelve solo el campo operating_mode. En la API de Orders, la respuesta devuelve el arrayterminals[] con id y operating_mode, identificando cada terminal actualizada. Consulta la tabla a continuación para el mapeo completo.
API de Intención de Pago
API de Orders
Descripción
Cambio
operating_mode
terminals[].operating_mode
Modo de operación definido para la terminal. En la API de Intención de Pago, era devuelto como campo único. En la API de Orders, es devuelto dentro del arrayterminals[]. Los valores posibles son PDV y STANDALONE.
Pasa al interior del arrayterminals[].
La API de Orders también introduce el siguiente campo sin equivalente en la API de Intención de Pago.
Campo
Descripción
terminals[].id
Identificador único de la terminal actualizada. Es devuelto solo en la API de Orders.
En la actualización del modo de operación, los errores fueron agrupados según el tipo de cambio. Consulta las tablas a continuación para más detalles.
Errores que desaparecen
El siguiente error existe en la API de Intención de Pago pero fue eliminado en la API de Orders.
HTTP
API de Intención de Pago
Observación
424
failed_dependency
Código eliminado en la API de Orders.
Errores renombrados
El siguiente error fue renombrado en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
403
forbidden
store_pos_not_found
Terminal sin sucursal o caja asociada.
Errores que cambian de comportamiento
El siguiente error existe en ambas APIs pero con un significado diferente en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
400
bad_request
property_value
device_id u operating_mode con valor inválido.
Errores que permanecen igual
Los siguientes errores tienen el mismo comportamiento en ambas APIs.
HTTP
Error
Observación
401
unauthorized
Token inválido o expirado.
500
internal_error
Error interno. Reintentar la solicitud.
Errores introducidos por la API de Orders
Los siguientes errores no tienen equivalente en la API de Intención de Pago.
HTTP
Error
Observación
400
unsupported_site
Site inválido.
400
required_properties
Propiedad obligatoria ausente.
400
unsupported_properties
Campo no soportado enviado.
400
invalid_payload
Payload inválido. Verificar los campos enviados.
403
terminal_not_allowed_action
Acción no permitida para este modelo de terminal.
404
not_found
Recurso no encontrado o ID inválido.
412
(sin código string)
Operación no permitida: ya existe una terminal asociada a la caja en modo PDV. Solo se permite una terminal por caja en modo PDV.
Migrar la creación de intenciones de pago a la creación de orders
El endpoint de creación cambia de POST /point/integration-api/devices/{deviceid}/payment-intents a POST /v1/orders. Además del cambio de URL, la estructura de la solicitud fue significativamente reorganizada: el identificador de la terminal deja el path y pasa al body, se introdujeron nuevos campos obligatorios y la API de Orders posee una estructura distinta. Sigue los pasos a continuación para adaptar la solicitud, la respuesta y el tratamiento de errores.
La API de Orders posee una estructura distinta a la de Intención de Pago: el identificador de la terminal debe enviarse en el body, los campos de configuración de pago e impresión se ubican en nuevos nodos, y los headers de identificación forman parte del body. Los nuevos campos obligatorios son type (con valor "point") y external_reference. Consulta la tabla a continuación para el mapeo completo de campos.
A continuación, un ejemplo comparativo entre la creación de una intención de pago y la creación de una order, seguido de la tabla de mapeo completo de campos.
Solicitud para crear una intención de pago. El identificador de la terminal se envía como path param y el amount es un valor entero.
Identifica la terminal que recibirá la order. En la API de Intención de Pago, se envía en el path. En la API de Orders, se envía en el body con el formato {tipo_terminal}__{serial_terminal}.
Pasa de path param a campo en el body.
amount (integer)
transactions.payments[].amount (string)
Monto a cobrar. En la API de Intención de Pago, se representa como entero con dos decimales implícitos (ej.: 1500 para $15,00). En la API de Orders, se representa como string dentro del arraytransactions.payments. Acepta dos decimales (ej.: "15.00") o ninguno. Solo se permite 1 transacción por order cuando type es point.
Cambia de entero a string y pasa al arraytransactions.payments.
additional_info.external_reference
external_reference
Identificador alfanumérico de la transacción en el sistema del integrador, devuelto en las notificaciones de webhook. En la API de Orders, es obligatorio, con un máximo de 64 caracteres, solo letras, números, - y _. Debe ser único por order y no puede contener datos PII.
Sube al nivel raíz y pasa a ser obligatorio.
additional_info.print_on_terminal (boolean)
config.point.print_on_terminal (string)
Controla la impresión del ticket en la terminal. En la API de Intención de Pago, acepta los valores booleanos true y false. En la API de Orders, acepta los valores seller_ticket (imprime) y no_ticket (no imprime). Valor por defecto: seller_ticket.
Cambia de booleano a enumstring.
payment.type
config.payment_method.default_type
Define el medio de pago aceptado por la terminal. En la API de Intención de Pago, los valores posibles son credit_card, debit_card. En la API de Orders, los valores posibles son credit_card, debit_card y qr. Si no se envía, la terminal acepta todos los medios de pago.
Cambia de nodo y pasa a aceptar también qr.
description
description
Describe el producto, servicio o motivo del pago. En la API de Orders, acepta hasta 150 caracteres.
Sin cambios.
X-platform-id (header)
integration_data.platform_id
Identifica la plataforma de la integración, asignado por Mercado Pago. En la API de Intención de Pago, se enviaba como header. En la API de Orders, se envía en el body dentro de integration_data.
Deja de ser header y pasa al body.
X-integrator-id (header)
integration_data.integrator_id
Identifica al integrador de la integración, asignado por Mercado Pago. En la API de Intención de Pago, se enviaba como header. En la API de Orders, se envía en el body dentro de integration_data.
Deja de ser header y pasa al body.
La API de Orders también introduce los siguientes campos sin equivalente en la API de Intención de Pago.
Campo
Descripción
integration_data.sponsor.id
USER_ID de la cuenta de Mercado Pago del sistema integrador.
type
Tipo de order. Para Point, el único valor aceptado es "point". Obligatorio.
expiration_time
Define el tiempo de validez de la order desde su creación, en formato ISO 8601. El valor mínimo es PT30S (30 segundos), el valor máximo es PT3H (3 horas) y el valor por defecto es PT15M (15 minutos). Ejemplos: PT30S para 30 segundos, PT10M para 10 minutos, PT1H15M para 1 hora y 15 minutos. Si la order expira sin ser procesada, se cancela automáticamente. Opcional.
El formato del ID de la order cambia de UUID (ej.: 7f25f9aa-eea6-...) a alfanumérico (ej.: ORD00001111222233334444555566). Actualiza cualquier lógica de almacenamiento o consulta que dependa del formato del ID antes de continuar.
La tabla a continuación presenta los campos de la respuesta de creación que existían en ambas APIs y sufrieron cambios en la migración.
API de Intención de Pago
API de Orders
Descripción
Cambio
id (UUID)
id (alfanumérico)
Identificador de la order creada, generado por Mercado Pago. En la API de Intención de Pago, se devuelve en formato UUID. En la API de Orders, se devuelve en formato alfanumérico con prefijo ORD.
El formato del ID cambia a ORD....
device_id
config.point.terminal_id
Identificador de la terminal que recibió la order.
Pasa a config.point.
amount (integer)
transactions.payments[].amount (string)
Valor del pago. En la API de Intención de Pago, se devuelve como entero. En la API de Orders, se devuelve como string decimal dentro del array de pagos.
Pasa al array de pagos.
additional_info.external_reference
external_reference
Referencia externa de la order en el sistema del integrador.
Sube al nivel raíz.
additional_info.print_on_terminal (boolean)
config.point.print_on_terminal (string)
Indica si la terminal imprimió el ticket. En la API de Intención de Pago, se devuelve como booleano. En la API de Orders, se devuelve como enumstring: seller_ticket o no_ticket.
Cambia de booleano a enumstring.
additional_info.ticket_number
config.point.ticket_number
Valor alfanumérico para identificar el número de factura o ticket, impreso en la terminal cuando la impresión está habilitada.
Pasa a config.point.
La API de Orders también introduce los siguientes campos sin equivalente en la API de Intención de Pago.
Campo
Descripción
status
Estado actual de la order. Al crear: created.
status_detail
Detalle del estado de la order. Al crear: created.
type
Tipo de order. Para Point: siempre point.
expiration_time
Tiempo de validez de la order en formato ISO 8601. Si la order expira sin ser procesada, se cancela automáticamente.
created_date / last_updated_date
Registra las fechas de creación y última actualización de la order en formato yyyy-MM-ddTHH:mm:ss.sssZ.
transactions.payments[].id
Identificador de la transacción de pago, generado por Mercado Pago. Necesario para reembolsos parciales.
transactions.payments[].status
Estado de la transacción de pago. Al crear: created.
user_id
Identificador del usuario de Mercado Pago que creó la order.
processing_mode
Modo de procesamiento de la order. Para Point: siempre automatic.
country_code
Identificador del site/país de la aplicación.
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.
integration_data.sponsor.id
USER_ID del sistema integrador.
En la creación, los errores fueron agrupados según el tipo de cambio. Consulta las tablas a continuación para más detalles.
Errores que cambian de comportamiento
En la API de Intención de Pago, los siguientes errores devolvían el código genérico bad_request. En la API de Orders, son reemplazados por códigos específicos.
HTTP
API de Intención de Pago
API de Orders
Observación
400
bad_request
required_properties
Propiedad obligatoria ausente.
400
bad_request
property_value
Valor inválido en una propiedad.
400
bad_request
property_type
Tipo incorrecto. Por ejemplo: integer en vez de string.
400
bad_request
json_syntax_error
JSON inválido.
400
bad_request
unsupported_properties
Propiedad no soportada enviada.
Errores renombrados
Los siguientes errores fueron renombrados en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
403
forbidden
forbidden_checking_terminal_owner
Terminal no vinculada a la cuenta.
409
conflict_error
already_queued_order_for_terminal
Ya existe una order en espera para este terminal.
Errores que desaparecen
El siguiente error existe en la API de Intención de Pago pero fue eliminado en la API de Orders.
HTTP
API de Intención de Pago
Observación
424
failed_dependency
Código eliminado en la API de Orders.
Errores que permanecen igual
El siguiente error tiene el mismo comportamiento en ambas APIs.
HTTP
Error
Observación
401
unauthorized
Token inválido o expirado.
500
internal_error
Error interno. Verifica el retorno y repite la solicitud.
Errores introducidos por la API de Orders
Los siguientes errores no tienen equivalente en la API de Intención de Pago.
HTTP
Error
Observación
400
empty_required_header
X-Idempotency-Key ausente.
400
minimum_properties
Número mínimo de propiedades obligatorias no enviado.
400
minimum_items / maximum_items
Número inválido de ítems en el arraytransactions.payments.
409
idempotency_key_already_used
Clave de idempotencia reutilizada con body diferente.
500
idempotency_validation_failed
Falla en la validación de idempotencia. Reintenta la solicitud.
Actualizar el mecanismo de consulta de Intención de Pago a Orders
Además de los campos documentados en la respuesta de creación, la respuesta del GET incluye campos adicionales relevantes para la migración. Consulta la tabla a continuación para el detalle.
API de Intención de Pago
API de Orders
Descripción
Cambio
state
status
Estado de la order. En la API de Intención de Pago, campo state con valores en mayúsculas. En la API de Orders, campo status con valores en minúsculas y conjunto de estados expandido.
Identificador del pago procesado, disponible cuando el flujo se completa con éxito. En la API de Intención de Pago, era devuelto como entero en payment.id. En la API de Orders, es devuelto como string en transactions.payments[].reference_id.
Identificador del pago procesado. Cambia de integer a string.
La API de Orders también introduce los siguientes campos sin equivalente en la API de Intención de Pago.
Campo
Descripción
status_detail
Detalle del estado de la order. Valores posibles: accredited, canceled_by_api, bad_filled_card_data, insufficient_amount, entre otros. Consulta la Referencia de API para la lista completa.
transactions.payments[].paid_amount
Valor efectivamente pagado en la transacción.
transactions.payments[].refunded_amount
Valor reembolsado en la transacción.
transactions.payments[].status
Estado de la transacción de pago.
transactions.payments[].status_detail
Detalle del estado de la transacción. Mismos valores posibles de status_detail de la order.
transactions.payments[].payment_method.type
Medio de pago utilizado en la transacción (ej.: credit_card, debit_card).
Primeros y últimos dígitos de la tarjeta utilizada en la transacción, disponibles cuando el pago se realizó con tarjeta.
transactions.refunds[]
Array con los datos de los reembolsos realizados en la order (id, transaction_id, reference_id, amount, status).
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 API de Intención de Pago pero no tienen equivalente en la API de Orders.
HTTP
API de Intención de Pago
Observación
401
unauthorized (Unauthorized use of live credentials)
El headerx-test-scope fue eliminado en la API de Orders.
403
forbidden
La validación de propiedad de la terminal ocurre solo en la creación.
429
too_many_requests
Presente en la API de Intención de Pago. No documentado en la API de Orders.
Errores renombrados
El siguiente error fue renombrado en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
404
not_found
order_not_found
Order no encontrada. Verificar si el ID enviado es correcto.
Errores que cambian de comportamiento
El siguiente error existe en ambas APIs pero con un significado diferente en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
400
bad_request
bad_request
Formato del order_id inválido. El ID cambia de UUID a alfanumérico.
Errores que permanecen igual
Los siguientes errores tienen el mismo comportamiento en ambas APIs.
HTTP
Error
Observación
401
unauthorized
Token inválido o expirado.
500
internal_error
Error interno. Reintentar la solicitud.
Actualizar el tratamiento de status
Uno de los cambios más significativos entre la API de Intención de Pago y la API de Orders es el del campo state, que pasa a llamarse status en la nueva API y recibe nuevos valores. En la API de Intención de Pago, el estado FINISHED requería llamadas adicionales para determinar el resultado real del pago. En la API de Orders, los status processed y failed son autocontenidos y eliminan esa necesidad. Actualiza todas las verificaciones de status de la integración conforme a la tabla a continuación.
API de Intención de Pago (state)
API de Orders (status)
Observación
OPEN
created
Renombrado
ON_TERMINAL
at_terminal
Renombrado
PROCESSING
Absorbido
No hay estado intermedio en la API de Orders
PROCESSED
Absorbido
No hay estado intermedio en la API de Orders
FINISHED (pago aprobado)
processed
El resultado del pago aprobado está contenido en la propia order, sin necesidad de consultas adicionales.
FINISHED (pago rechazado)
failed
El resultado del pago rechazado está contenido en la propia order, sin necesidad de consultas adicionales.
CONFIRMATION_REQUIRED
action_required
Renombrado
ERROR
failed
Renombrado
ABANDONED
expired
Renombrado (basado en timeout)
CANCELED
canceled
Mismo significado. Ahora en minúsculas
No existe
refunded
Nuevo status. Debe tratarse explícitamente en todos los flujos
En la API de Intención de Pago, para confirmar el resultado de un pago con state: FINISHED, era necesario inspeccionar payment.state en el webhook, llamar a GET /v1/payments/{id} o buscar por external_reference. En la API de Orders, los status processed y failed son autocontenidos: el resultado del pago está disponible directamente en la order, sin consultas adicionales.
Actualizar la cancelación de orders
El nuevo endpoint para cancelar una order es POST /v1/orders/{orderid}/cancel, reemplazando el DELETE de la API de Intención de Pago. El {deviceid} desaparece del path y la cancelación pasa a identificarse únicamente por el {orderid}.
Con la API de Intención de Pago, solo era posible cancelar intenciones de pago que aún no habían llegado a la terminal. En la API de Orders, es posible cancelar una order incluso después de que haya llegado a la terminal, mediante un nuevo header específico.
La respuesta pasa a devolver el objeto completo de la order con status: "canceled", en lugar de solo el id. Los headers necesarios en esta operación son:
Header
Obligatoriedad
Descripción
X-Idempotency-Key
Obligatorio
Clave única por solicitud
x-allow-cancelable-status
Condicional
Obligatorio para cancelar orders en at_terminal. Valor: "at_terminal"
Para cancelar orders en status at_terminal, envía el headerx-allow-cancelable-status: at_terminal. Sin este header, solo se cancelarán orders con status: created.
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 API de Intención de Pago pero no tienen equivalente en la API de Orders.
HTTP
API de Intención de Pago
Observación
400
bad_request (deviceID format)
deviceid fue eliminado del path en la API de Orders.
429
too_many_requests
Presente en la API de Intención de Pago. No documentado en la API de Orders.
Errores renombrados
El siguiente error fue renombrado en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
409
conflict_error
cannot_cancel_order
El estado de la order no permite la cancelación. Para at_terminal, enviar x-allow-cancelable-status: at_terminal.
Errores que cambian de comportamiento
Los siguientes errores existen en ambas APIs pero con comportamiento diferente en la API de Orders.
HTTP
API de Intención de Pago
API de Orders
Observación
400
bad_request
bad_request
Formato del order_id inválido. El ID cambia de UUID a alfanumérico.
404
101
order_not_found
Order no encontrada. En la API de Intención de Pago, el campo error usa el código numérico "101".
409
101
order_already_canceled
En la API de Intención de Pago, order inexistente y order ya cancelada devolvían el mismo error "101". En la API de Orders se diferencian en dos errores distintos: 404 para order no encontrada y 409 para order ya cancelada.
500
internal_error
idempotency_validation_failed
Falla en la validación de idempotencia. Reintentar la solicitud.
Errores que permanecen igual
El siguiente error tiene el mismo comportamiento en ambas APIs.
HTTP
Error
Observación
401
unauthorized
Token inválido o expirado.
Errores introducidos por la API de Orders
Los siguientes errores no tienen equivalente en la API de Intención de Pago.
HTTP
Error
Observación
400
empty_required_header
X-Idempotency-Key ausente.
409
idempotency_key_already_used
Clave de idempotencia reutilizada.
Implementar reembolsos con el endpoint dedicado
La API de Orders introduce el endpoint dedicado POST /v1/orders/{orderid}/refund para reembolsos, que no existía en la API de Intención de Pago. Antes, era necesario recibir el webhook del pago, obtener el payment_id y ejecutar el reembolso a través de la API de Payments por separado. Ahora, el reembolso se realiza directamente sobre la order.
Elige entre reembolso total o parcial de acuerdo con el valor a devolver.