Devoluciones y reembolsos
Registra devoluciones, reembolsa pagos y repón stock con Admin API.
Andrea Ramos devuelve uno de los dos polos de su pedido. Registras la devolución, repones el stock y reembolsas su pago con Admin API.
Requisitos
- Un token de Admin con el scope
api_admin. Ver Integración con ERP. - Los permisos
order:updatey, para reembolsar,payment:create. - Un pedido con su pago capturado.
- Node.js o Python, para los ejemplos.
Lee el pedido
Consulta el pedido antes de devolver o reembolsar. Guarda el id de cada item
y el paymentTransactionId de cada pago.
curl https://api.ecomiq.pe/api/v1/orders/7204558912004325301 \
-H "Authorization: Bearer $ECOMIQ_TOKEN"{
"id": "7204558912004325301",
"orderNumber": "ORD-2026-0001",
"status": "delivered",
"returnStatus": "none",
"currencyCode": "PEN",
"total": 178,
"items": [
{
"id": "7204558912004325302",
"title": "Polo de algodón",
"quantity": 2,
"quantityReturned": 0
}
],
"payments": [
{
"paymentTransactionId": "7204558912004325320",
"paymentMethod": "card",
"amount": 178,
"paymentStatus": "Captured",
"refundedAmount": 0,
"refundableAmount": 178
}
],
"financialSummary": {
"paidAmount": 178,
"refundedAmount": 0,
"refundableAmount": 178,
"shippingRefundableAmount": 0
},
"pendingRefund": null
}payments[].refundableAmount es lo que aún puedes reembolsar de ese pago. Vale
0 si el pago no se capturó. financialSummary.refundableAmount es el tope de
todo el pedido.
Los pasos siguientes reusan API, headers y orderId.
Marca el estado de la devolución
returnStatus sigue la devolución antes de que lleguen las unidades. Cuando
Andrea Ramos pide devolver, marca requested. Para aprobar, pasa a
inProgress con la dirección de envío.
curl -X PUT https://api.ecomiq.pe/api/v1/orders/7204558912004325301/return-status \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"status": "inProgress",
"comment": "Aprobamos tu devolución. Envía el polo con su etiqueta.",
"returnAddress": "Av. Larco 345, Miraflores, Lima"
}'La respuesta 200 devuelve el pedido con returnStatus: "inProgress".
| Estado | Significado | Por esta ruta |
|---|---|---|
none | Sin devolución. | No, responde 409 |
requested | Solicitada. | Sí |
inProgress | En proceso. | Sí |
inspected | Revisada. | Sí |
rejected | Rechazada. | Sí |
returned | Hay unidades devueltas registradas. | No, responde 409 |
Al pasar de requested a inProgress, el cliente recibe la aprobación con
comment y returnAddress. Al pasar a rejected, recibe el rechazo con
comment.
none y returned responden 409 con Orders.InvalidReturnTransition:
returned se asigna al registrar la devolución.
Registra la devolución al final
Una devolución registrada, aunque sea parcial, deja returnStatus en
returned. Desde ahí, esta ruta responde 409 con Orders.ReturnCompleted.
Registra la devolución
Registra las unidades que recibiste. Para un item, usa
POST /. Para todo el pedido, usa
POST / con el mismo cuerpo, sin quantity.
Este ejemplo devuelve un polo, lo repone en stock y reembolsa 89.
curl -X POST https://api.ecomiq.pe/api/v1/orders/7204558912004325301/items/7204558912004325302/return \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"idempotencyKey": "devolucion-ORD-2026-0001-1",
"quantity": 1,
"comment": "Talla incorrecta.",
"restock": true,
"restockLocationId": "7204558912004325378",
"refundAmount": 89,
"paymentTransactionId": "7204558912004325320"
}'{
"id": "7204558912004325301",
"status": "partialReturned",
"returnStatus": "returned",
"items": [
{
"id": "7204558912004325302",
"quantity": 2,
"quantityReturned": 1
}
],
"payments": [
{
"paymentTransactionId": "7204558912004325320",
"refundedAmount": 89,
"refundableAmount": 89
}
],
"financialSummary": {
"paidAmount": 178,
"refundedAmount": 89,
"refundableAmount": 89
}
}| Campo | Uso |
|---|---|
idempotencyKey | Obligatorio, hasta 100 caracteres. Repetirlo no registra otra devolución. |
quantity | Unidades a devolver. Sin valor, devuelve todas las pendientes. |
restock | true suma las unidades al stock de restockLocationId. |
restockLocationId | Ubicación que recibe las unidades. Obligatoria con restock. |
refundAmount | Monto a reembolsar en la misma llamada. |
paymentTransactionId | Pago a reembolsar. Obligatorio con refundAmount. |
comment | Nota de hasta 500 caracteres. |
Los IDs de ubicación están en
Listar ubicaciones logísticas.
status pasa a partialReturned, o a returned si se devolvieron todas las
unidades.
refundAmount no se limita al valor del item. Su tope es lo que queda del pago:
payments[].refundableAmount. Este reembolso no cubre envío; para eso, usa Reembolsa un pago.
Si el reembolso falla, la devolución no se registra. Reintenta con la misma
idempotencyKey. Un pedido cerrado o cancelado responde 409.
La devolución del pedido completo envía el webhook order.returned. La
devolución de un item no lo envía.
Reembolsa un pago
Usa POST / para reembolsar sin devolución o para
reembolsar envío. Para un reembolso completo, envía en amount el
refundableAmount del pago. Para uno parcial, envía menos.
curl -X POST https://api.ecomiq.pe/api/v1/orders/7204558912004325301/refunds \
-H "Authorization: Bearer $ECOMIQ_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"paymentTransactionId": "7204558912004325320",
"idempotencyKey": "reembolso-ORD-2026-0001-1",
"amount": 20,
"reason": "Compensación por demora en la entrega.",
"notifyCustomer": true
}'{
"id": "7204558912004325301",
"hasRefund": true,
"financialSummary": {
"paidAmount": 178,
"refundedAmount": 109,
"refundableAmount": 69,
"shippingRefundableAmount": 0
},
"pendingRefund": null
}| Campo | Uso |
|---|---|
paymentTransactionId | Pago a reembolsar, tomado de payments[]. |
idempotencyKey | Obligatorio, hasta 100 caracteres. |
amount | Total a reembolsar, con hasta dos decimales. Incluye shippingAmount. |
shippingAmount | Parte de amount que reembolsa envío. Por defecto 0. |
reason | Motivo, hasta 500 caracteres. |
notifyCustomer | Avisa al cliente. Por defecto true. |
lines | Items y unidades reembolsados. Obligatorio con restock. |
restock | Con restockLocationId, devuelve las unidades de lines al stock. |
amount no puede superar payments[].refundableAmount ni
financialSummary.refundableAmount. Si los supera, la API responde 400 con
Orders.RefundExceedsBalance. shippingAmount tiene como tope
financialSummary.shippingRefundableAmount.
Repetir la misma idempotencyKey con el mismo cuerpo no reembolsa dos veces.
Con otro cuerpo, la API responde 409 con Orders.RefundKeyConflict.
El stock cambia según la llamada:
| Llamada | Stock |
|---|---|
Devolución sin restock | No cambia. |
Devolución con restock | Suma las unidades devueltas en restockLocationId. |
Reembolso sin lines | No cambia. |
Reembolso con lines, sin restock | Las unidades aún sin despachar salen de la preparación y liberan su reserva. |
Reembolso con lines y restock | Registra las unidades como devueltas y las suma en restockLocationId. |
restock en un reembolso exige un pedido inTransit, delivered,
partialDelivered o partialReturned. Solo acepta unidades despachadas que no
se devolvieron. Solo vuelven al stock items vinculados a una variante, en
unidades enteras.
Reintenta un reembolso pendiente
El reembolso se guarda antes de pedirlo al proveedor de pagos. Si el proveedor
falla o no confirma, la API responde con error y el pedido muestra
pendingRefund.
{
"id": "7204558912004325301",
"pendingRefund": {
"id": "7204558912004325340",
"idempotencyKey": "reembolso-ORD-2026-0001-1",
"payments": [
{ "paymentTransactionId": "7204558912004325320", "amount": 20 }
],
"amount": 20,
"shippingAmount": 0,
"reason": "Compensación por demora en la entrega.",
"restockLocationId": null,
"notifyCustomer": true,
"lines": [],
"createdOn": "2026-10-04T15:30:00Z"
}
}Mientras exista, otros reembolsos y devoluciones responden 409 con
Orders.RefundPending. Reintenta con pendingRefund.id: la API repite la
solicitud con su misma idempotencyKey.
curl -X POST https://api.ecomiq.pe/api/v1/orders/7204558912004325301/refunds/7204558912004325340/retry \
-H "Authorization: Bearer $ECOMIQ_TOKEN"Si el reembolso ya se completó, la API devuelve el pedido sin reembolsar otra vez. Si el proveedor confirma más tarde, el reembolso pendiente se completa solo.
Revisa los movimientos
GET / lista el dinero que entró y salió del
pedido. Cada reembolso es un movimiento out con amount negativo.
curl https://api.ecomiq.pe/api/v1/orders/7204558912004325301/transactions \
-H "Authorization: Bearer $ECOMIQ_TOKEN"[
{
"id": "7204558912004325350",
"type": "in",
"amount": 178,
"paymentMethod": "card",
"referenceId": "7204558912004325320",
"referenceType": "paymentTransaction",
"createdOn": "2026-10-01T10:12:00Z"
},
{
"id": "7204558912004325351",
"type": "out",
"amount": -89,
"paymentMethod": "card",
"referenceId": "7204558912004325320",
"referenceType": "paymentTransaction",
"content": "Talla incorrecta.",
"createdOn": "2026-10-04T15:10:00Z"
},
{
"id": "7204558912004325352",
"type": "out",
"amount": -20,
"paymentMethod": "card",
"referenceId": "7204558912004325320",
"referenceType": "paymentTransaction",
"content": "Compensación por demora en la entrega.",
"createdOn": "2026-10-04T15:30:00Z"
}
]referenceId es el pago de cada movimiento. content guarda el motivo del
reembolso o el comentario de la devolución.
Siguientes pasos
Última actualización: