Saltar al contenido
Tienda online

Seguimiento y reseñas

Muestra el pedido, sigue el envío y recoge reseñas con Storefront API.

Andrea compra en Arequipa una casaca y unas botas de dos vendedores. Desde su cuenta ve los dos pedidos, sigue al courier y, al recibirlos, deja una reseña.

Requisitos

  • Un pedido creado con el checkout. Ver Checkout y pago.
  • Para ver una compra dividida, la sesión del cliente en X-Customer-Session. Ver Cuentas de clientes.
  • La ruta /review/{reviewToken} en el dominio principal de la tienda.
  • Para la ficha, el id del producto. Ver Tienda headless.

Muestra la compra

Sin sesión, el comprador entra con el enlace de estado de cada pedido: GET /v1/orders/status/{statusToken}, explicado en Checkout y pago. Con sesión, GET /v1/customer/orders/group/{orderGroup} junta los pedidos de una compra. Si el carrito tenía productos de varios vendedores, hay un pedido por vendedor.

curl https://storefront.ecomiq.pe/v1/customer/orders/group/7204558912004325350 \
  -H "x-Store-Domain: mi-tienda" \
  -H "X-Customer-Session: $SESSION_ID"
Respuesta (extracto)
{
  "orderId": "7204558912004325350",
  "orderNumber": "ORD-2026-0001",
  "orderGroup": "7204558912004325350",
  "orderIds": ["7204558912004325350", "7204558912004325351"],
  "status": "inTransit",
  "total": 449.8,
  "currencyCode": "PEN",
  "orders": [
    { "orderNumber": "ORD-2026-0001", "status": "inTransit", "total": 289.9 },
    { "orderNumber": "ORD-2026-0002", "status": "confirmed", "total": 159.9 }
  ]
}
  • orderGroup llega en la respuesta del checkout y en cada fila de GET /v1/customer/orders.
  • orderNumber y status son los del primer pedido. total suma todos.
  • Cada elemento de orders contiene el mismo detalle de comprador que GET /v1/customer/orders/{orderId}: artículos, importes, direcciones, pagos, statusTimeline y shipments. totalPaid suma los pagos registrados.

Sigue el envío

shipments trae carrierName, trackingNumber y trackingLink. Llega en GET /v1/orders/status/{statusToken}, en GET /v1/customer/orders/{orderId} y en cada elemento de orders del grupo de compra. Con el número, GET /v1/tracking/{trackingNumber} devuelve el estado del envío. No necesita sesión.

curl https://storefront.ecomiq.pe/v1/tracking/UR1029384756 \
  -H "x-Store-Domain: mi-tienda"
Respuesta (extracto)
{
  "trackingNumber": "UR1029384756",
  "carrierName": "Urbano",
  "trackingLink": "https://…/UR1029384756",
  "status": "shipped",
  "delivered": false,
  "events": [
    { "name": "Pedido creado", "date": "06/10/2026 09:12" },
    { "name": "Pedido en ruta", "date": "08/10/2026 08:40" }
  ],
  "message": null
}
  • status es el de la preparación: pendingAssignment, pending, inProgress, readyToPickUp, shipped, delivered o cancelled. Pasa a delivered cuando el transportista confirma la entrega.
  • events llega como lo informa el transportista. name y date son texto: muéstralos tal cual.
  • Sin transportista conectado, events llega vacío y message dice por qué. Enlaza a trackingLink si viene.

Abre el enlace de reseña

Al entregar el pedido, los correos de Ecomiq llevan al comprador a https://<dominio-principal>/review/{reviewToken}. En esa ruta, lee el pedido con GET /v1/orders/review-context/{reviewToken}. El token basta: no hace falta sesión.

curl https://storefront.ecomiq.pe/v1/orders/review-context/<review-token> \
  -H "x-Store-Domain: mi-tienda"
Respuesta
{
  "orderId": "7204558912004325350",
  "orderNumber": "ORD-2026-0001",
  "customerName": "Andrea",
  "email": "andrea.ramos@example.com",
  "deliveredAt": "2026-10-09T16:20:00Z",
  "items": [
    {
      "productId": "7204558912004320011",
      "title": "Casaca de alpaca",
      "variantTitle": "M / Gris",
      "thumbnail": "https://…/casaca.webp"
    }
  ]
}
  • items trae cada producto del pedido una vez. Muestra un formulario por producto.
  • Responde 404 Orders.ReviewContextNotFound si el token no existe, o si el pedido no se entregó o se canceló.

Publica la reseña

POST /v1/products/{productId}/reviews guarda la reseña de un producto. Envía el reviewToken y, en reviewerEmail, el email del contexto. Los ejemplos llaman context a la respuesta del paso anterior.

curl -X POST https://storefront.ecomiq.pe/v1/products/7204558912004320011/reviews \
  -H "x-Store-Domain: mi-tienda" \
  -H "Content-Type: application/json" \
  -d '{
    "rating": 5,
    "title": "Abriga mucho",
    "content": "Llegó en tres días. La talla M me queda perfecta.",
    "reviewerName": "Andrea R.",
    "reviewerEmail": "andrea.ramos@example.com",
    "orderId": "7204558912004325350",
    "reviewToken": "<review-token>"
  }'
Respuesta
{
  "id": "7204558912004330101",
  "productId": "7204558912004320011",
  "isVerifiedPurchase": true,
  "rating": 5,
  "title": "Abriga mucho",
  "content": "Llegó en tres días. La talla M me queda perfecta.",
  "reviewerName": "Andrea R.",
  "createdOn": "2026-10-16T14:05:00Z"
}
  • rating va de 1 a 5. content es obligatorio, hasta 4000 caracteres; title y reviewerName, hasta 200.
  • La reseña espera moderación. El comercio la aprueba en el admin o con PATCH /v1/catalog/product-reviews/{reviewId}/status.
  • Una reseña por producto y pedido. orderId es opcional; si lo envías, debe ser el del enlace.

Muestra las reseñas

GET /v1/products/{productId}/reviews lista las reseñas aprobadas, de la más reciente a la más antigua. No necesita sesión.

curl "https://storefront.ecomiq.pe/v1/products/7204558912004320011/reviews?limit=10" \
  -H "x-Store-Domain: mi-tienda"
Respuesta (extracto)
{
  "data": [
    {
      "id": "7204558912004330101",
      "isVerifiedPurchase": true,
      "rating": 5,
      "title": "Abriga mucho",
      "content": "Llegó en tres días. La talla M me queda perfecta.",
      "reviewerName": "Andrea R.",
      "createdOn": "2026-10-16T14:05:00Z"
    }
  ],
  "hasNextPage": true,
  "nextCursor": "MjAyNi0xMC0xNlQxNDowNTowMFo",
  "totalCount": 24
}
  • limit vale 20 si no lo envías. Mientras hasNextPage sea true, envía nextCursor en cursor. totalCount solo llega en la primera página.
  • rating filtra por estrellas y search busca en título, texto y nombre. sortBy=rating&sortDirection=desc pone primero las mejores.
  • Si el producto no existe, la lista llega vacía.

Sugiere productos relacionados

GET /v1/products/{productId}/related llena el bloque de recomendaciones de la ficha. Primero trae productos parecidos y completa con la misma categoría, la misma marca y el resto del catálogo.

curl "https://storefront.ecomiq.pe/v1/products/7204558912004320011/related?limit=4" \
  -H "x-Store-Domain: mi-tienda"
Respuesta (extracto)
[
  {
    "id": "7204558912004320012",
    "name": "Chompa de alpaca",
    "url": "/products/chompa-de-alpaca",
    "imageUrl": "https://…/chompa.webp",
    "price": 189.9,
    "compareAtPrice": 229.9,
    "isAvailable": true
  }
]
  • limit vale 8 si no lo envías. El máximo es 12.
  • Solo trae productos disponibles y visibles, nunca el de la ficha.
  • Si el producto no existe, responde [].

Errores

codeEstadoQué hacer
Orders.NotFound404Revisa orderGroup: no existe o es de otro cliente.
Customer.RegistrationRequired403Completa el registro antes de mostrar los pedidos.
Common.NotFound404El número de seguimiento no es de esta tienda.
Common.Conflict409El número coincide con más de un envío. Usa trackingLink.
Orders.ReviewContextNotFound404El enlace no sirve. Muestra un aviso y enlaza a la tienda.
ProductReview.ReviewLinkNotFound404El token no existe. Usa el del correo.
Product.NotFound404El producto ya no existe. Quita su formulario.
ProductReview.OrderInvalid400El pedido no está entregado o tiene una devolución.
ProductReview.OrderOwnerMismatch400Envía en reviewerEmail el email del contexto.
ProductReview.ProductNotPurchased400Usa un productId de items.
ProductReview.OrderMismatch400Envía el orderId del contexto u omítelo.
ProductReview.AlreadyExists409Ya hay una reseña. Marca el producto como reseñado.
Common.Validation400errors dice qué campo falló.

El seguimiento tiene límite de peticiones. Con 429, espera lo que indique Retry-After. Ver Límites de uso.

Siguientes pasos

Última actualización:

En esta página