Carrito

Cómo se identifica el carrito de cada visitante y de quién es, cómo añadir, ver y quitar productos, calcular el envío y el descuento de un cupón, y pagar para crear el pedido.

13 min de lecturaActualizado el 30 de setiembre de 2026

Cómo se identifica el carrito

Cada visitante tiene su carrito, aunque no haya iniciado sesión. Se identifica con la cabecera user-ip-address:

  1. Genera un identificador propio para cada visitante, difícil de adivinar, de al menos 16 caracteres. Un UUID sirve.
  2. Guárdalo en el navegador o en la app, en una cookie o en el almacenamiento local.
  3. Envíalo en todas las llamadas del carrito.
curl https://<dominio-de-la-empresa>/api/v1/ecommerce/carts/shipments/calculate?type=DOMICILIO \
  -H "user-ip-address: 3f2b8c1e-9d4a-4e7b-8a1c-2b5d6e7f8a90" \
  -H "Accept: application/json"

Si el visitante inicia sesión o se registra enviando esta cabecera, su carrito pasa a ser de su cuenta.

De quién es el carrito:

  • Mientras nadie inicia sesión, el carrito es de visitante y solo lo protege el identificador. Por eso tiene que ser difícil de adivinar.
  • Cuando el visitante inicia sesión o se registra, el carrito pasa a su cuenta. Desde ese momento solo esa cuenta lo ve, lo cambia o lo paga, aunque otro conozca el identificador.
  • Con el identificador del carrito de otra cuenta, todas las rutas responden como si no existiera: sin carrito o 404 CART_NOT_FOUND. Iniciar sesión con ese identificador tampoco se lleva el carrito.

Todas las rutas del carrito, y también pagar, exigen que la tienda esté publicada. Con la tienda en privado responden igual que el catálogo: 404 STORE_NOT_FOUND si nunca se publicó, o 503 STORE_PAUSED si estuvo publicada y está cerrada un tiempo.

Añadir un producto

POST /api/v1/ecommerce/carts

Si el visitante aún no tiene carrito, se crea con este primer producto. No pide token; si se envía el del cliente, el carrito queda en su cuenta.

Campo Tipo Obligatorio Reglas
item_id número Sí Un producto a la venta en la tienda. Los servicios no se venden por aquí
quantity número Sí Entre 1 y 100000
variants lista No Solo si el producto tiene variantes (talla, color…). Hasta 100
variants[].id número Con variants Una variante de ese mismo producto
variants[].quantity número Con variants Entre 1 y 100000
{ "item_id": 45, "quantity": 2, "variants": [ { "id": 7, "quantity": 2 } ] }

La cantidad reemplaza, no suma. Si el producto ya estaba en el carrito, su línea pasa a tener la cantidad enviada. Para quitarlo, usa «Quitar un producto», más abajo.

El precio lo calcula el ERP: precio de oferta si lo hay, y precios por cantidad si el producto los tiene.

Respuesta

El carrito completo, con los totales ya recalculados. Tiene la misma forma que al verlo (ver «Ver el carrito»).

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
400 CART_IDENTIFIER_REQUIRED Falta la cabecera user-ip-address o tiene menos de 16 caracteres Envía el identificador del carrito
422 VALIDATION_ERROR El producto no existe o no está a la venta, la cantidad no es válida, o una variante no es de ese producto Corrige el campo que indica errors
503 STORE_NOT_CONFIGURED La tienda no tiene almacén Avisa a la tienda

Ver el carrito

GET /api/v1/ecommerce/carts

Devuelve el carrito activo del visitante, con sus líneas y el envío elegido. Si no tiene, data llega en null: no es un error.

{ "success": true, "message": "Carrito de compras obtenido de forma correcta.", "data": null }

Cuando hay carrito, data tiene la misma forma que la respuesta de «Quitar un producto», más shipment con el envío elegido o null.

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
400 CART_IDENTIFIER_REQUIRED Falta la cabecera user-ip-address o tiene menos de 16 caracteres Envía el identificador del carrito

Quitar un producto

DELETE /api/v1/ecommerce/carts/{code}/items/{id}

Parámetro Dónde Qué es
code Ruta Código del carrito, con formato UUID
id Ruta Identificador de la línea del carrito (items[].id), no del producto
user-ip-address Cabecera El identificador del carrito. Obligatorio si no se envía el token del cliente

El carrito tiene que ser de quien llama: por el token del cliente, si el carrito es de su cuenta, o por el identificador de la cabecera. Un carrito ajeno responde igual que uno inexistente.

Respuesta

Devuelve el carrito actualizado, con los totales ya recalculados.

{
  "success": true,
  "message": "Producto eliminado del carrito correctamente.",
  "data": {
    "code": "3f2b8c1e-9d4a-4e7b-8a1c-2b5d6e7f8a90",
    "order": "000123",
    "status": "PROCESANDO PEDIDO",
    "phase": null,
    "can_cancel": true,
    "payment_method": "",
    "quantity": 2,
    "subtotal": 84.75,
    "total_taxes": 15.25,
    "total_shipments": 0,
    "discounts": 0,
    "total": 100,
    "items": [
      {
        "id": 88,
        "quantity": 2,
        "subtotal": 84.75,
        "total_taxes": 15.25,
        "discounts": 0,
        "total": 100,
        "item": { "id": 45, "description": "Polo algodón", "price": 50.0, "stock": 10.0 }
      }
    ],
    "cash_order_id": "0000"
  }
}
Campo Qué es
items[].id Identificador de la línea. Es el que se usa para quitarla
items[].item Copia del producto en el momento de añadirlo
total Envío + suma de las líneas − descuentos

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
400 CART_IDENTIFIER_REQUIRED Sin token y sin la cabecera user-ip-address, o con menos de 16 caracteres Envía el identificador del carrito
404 CART_NOT_FOUND El carrito no existe o no es de quien llama Revisa el código y el identificador
404 CART_ITEM_NOT_FOUND Esa línea no está en el carrito Vuelve a consultar el carrito
409 CART_ALREADY_PAID El carrito ya se pagó Nada: un pedido pagado no se modifica
409 CART_NOT_EDITABLE El carrito ya no está activo, por ejemplo porque se anuló Empieza un carrito nuevo

Calcular el envío del carrito

GET /api/v1/ecommerce/carts/shipments/calculate

Calcula cuánto cuesta enviar el carrito del visitante. Solo calcula: no guarda nada en el carrito.

Parámetro Dónde Obligatorio Reglas
user-ip-address Cabecera Sí El identificador del carrito
type Query Sí Uno de los tipos de envío que la tienda tiene activos, en mayúsculas. Si no activó ninguno, vale DOMICILIO, AGENCIA o TIENDA
ubigeo Query No Distrito de destino, 6 cifras. Si no se envía y el cliente tiene sesión, se usa su dirección por defecto
agency_code Query No Solo con AGENCIA: devuelve solo esa agencia
establishment_id Query No Solo con TIENDA: devuelve solo ese establecimiento. Tiene que estar visible en la tienda

El peso es la suma del peso de cada producto por su cantidad. Hasta 1 kg se cobra el precio por kilo; a partir de ahí se suma el precio por kilo adicional. Si la tienda lo tiene configurado, al total se le suma el IGV (18 %), sin redondear.

Respuesta a domicilio

{
  "success": true,
  "message": "Información procesada de forma correcta.",
  "data": { "type": { "price": 12, "lead_time": 1 }, "weight": 1.2, "subtotal": 12, "total": 14.16 }
}

Respuesta a agencia

Una lista con cada agencia que llega al destino, con su propio subtotal y total. Si ninguna llega, la lista viene vacía.

{
  "success": true,
  "message": "Información procesada de forma correcta.",
  "data": {
    "type": [ { "code": "OLVA", "name": "Olva Courier", "logo": "…", "price": 15.5, "lead_time": 3, "subtotal": 15.5, "total": 18.29 } ],
    "weight": 2.5
  }
}

Respuesta con recojo en tienda

Los establecimientos del mismo distrito, provincia o departamento. El subtotal y el total son 0.

{
  "success": true,
  "message": "Información procesada de forma correcta.",
  "data": {
    "type": [ { "id": 1, "description": "Tienda Centro", "address": "Av. Lima 123", "lead_time": 1, "logo": null, "latitude": "-12.04", "longitude": "-77.03", "department": "LIMA", "province": "LIMA", "district": "LIMA" } ],
    "weight": 1.2,
    "subtotal": 0,
    "total": 0
  }
}

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
422 VALIDATION_ERROR Falta el tipo o no está activo en la tienda, el ubigeo no tiene 6 cifras o el establecimiento no existe Corrige el parámetro que indica errors
400 CART_IDENTIFIER_REQUIRED Falta la cabecera user-ip-address Envía el identificador del carrito
404 CART_NOT_FOUND No hay un carrito activo con ese identificador Añade un producto primero
422 UBIGEO_REQUIRED No se envió ubigeo y no hay sesión Envía el ubigeo
422 DEFAULT_ADDRESS_MISSING No se envió ubigeo y el cliente no tiene dirección por defecto Envía el ubigeo o pide al cliente una dirección
422 DESTINATION_NOT_FOUND La dirección por defecto no tiene ubigeo Envía el ubigeo
422 SHIPPING_AREA_NOT_COVERED A domicilio: no hay tarifa para ese distrito Ofrece otro tipo de envío

Calcular el descuento de un cupón

GET /api/v1/ecommerce/carts/coupons/calculate

Comprueba un cupón y devuelve cuánto descontaría. No aplica el cupón al carrito.

Parámetro Dónde Obligatorio Reglas
code Query Sí Código del cupón. Máximo 50 caracteres
user-ip-address Cabecera No El identificador del carrito. Sin él se comprueba el cupón, pero no se puede calcular el importe
Authorization Cabecera No El token del cliente. Hace falta para los cupones de un solo uso o reservados a ciertos clientes

Esta ruta admite 10 peticiones por minuto, para que no se puedan probar códigos. Ver límites.

Respuesta

data es el importe del descuento.

{ "success": true, "message": "Información procesada de forma correcta.", "data": 15.0 }
  • Si el cupón es de porcentaje, se aplica sobre el importe de los productos o sobre el envío, según cómo lo configuró la tienda.
  • Si es de importe fijo, se devuelve ese importe, con un tope: nunca más que el importe sobre el que se aplica.

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
422 VALIDATION_ERROR Falta el código o es demasiado largo Corrige el código
422 COUPON_NOT_FOUND El cupón no existe o no está activo Pide al cliente que revise el código
422 COUPON_EXPIRED El cupón aún no empieza o ya venció —
401 COUPON_LOGIN_REQUIRED El cupón exige sesión Pide al cliente que inicie sesión
422 COUPON_ALREADY_USED El cliente ya usó este cupón —
422 COUPON_USER_NOT_ELIGIBLE El cupón no es para este cliente —
422 COUPON_REQUIRES_CART El cupón es válido, pero hace falta un carrito para calcular el descuento Envía el identificador del carrito, o añade productos
422 COUPON_PRODUCTS_NOT_IN_CART El carrito no tiene ningún producto de la promoción Añade uno
422 COUPON_MIN_AMOUNT_NOT_REACHED El carrito no llega al importe mínimo Añade productos
422 COUPON_MAX_AMOUNT_EXCEEDED El carrito supera el importe máximo Quita productos
429 RATE_LIMITED Más de 10 peticiones por minuto Espera lo que indica Retry-After

COUPON_LOGIN_REQUIRED es un 401 distinto del de sesión: no trae error_code y no significa que el token haya caducado.

Pagar y crear el pedido

POST /api/v1/ecommerce/carts/pay

Convierte el carrito en un pedido del ERP. Es una solicitud de pedido: el cobro y el envío los gestiona después la tienda desde el ERP.

Pide el token del cliente y la cabecera user-ip-address con el identificador del carrito. El carrito tiene que ser de visitante (sin cuenta) o de la cuenta del cliente que paga: el de otra cuenta responde como si no existiera. Lo normal es registrarse o iniciar sesión enviando la cabecera, y pagar justo después.

Cuerpo

Campo Tipo Obligatorio Reglas
contact.first_name texto Sí Nombre de quien recibe el aviso. Máximo 50 caracteres
contact.last_name texto No Máximo 50 caracteres
contact.country_code texto Sí Prefijo del país, por ejemplo +51. Máximo 5 caracteres
contact.phone texto Sí WhatsApp de contacto. Exactamente 9 cifras
origin texto Sí WEB o APP
payment_method texto No Uno de los métodos de pago de la tienda. Sin él se usa EFECTIVO
billing.document_type_id texto No 01 (factura) o 03 (boleta)
billing.document_number texto No DNI de 8 cifras o RUC de 11. Una factura exige RUC
billing.name texto No Nombre o razón social. Máximo 250 caracteres
data objeto No Lo que devolvió la consulta de DNI o RUC de ese mismo documento: ruc o dni, nombre_o_razon_social o nombre_completo, direccion, condicion, estado, ubigeo
{
  "contact": { "first_name": "Ana", "last_name": "Pérez", "country_code": "+51", "phone": "987654321" },
  "origin": "WEB",
  "payment_method": "TRANSFERENCIA",
  "billing": { "document_type_id": "03", "document_number": "45678912", "name": "Ana Pérez" }
}

El teléfono y el prefijo solo se guardan como dato de contacto del pedido: no se envía ningún código ni se comprueba el país.

Si se indica un documento de facturación que la empresa aún no tiene, se da de alta como cliente con los datos de data. Sin nombre, ni en data ni en billing.name, responde BILLING_NAME_REQUIRED.

Respuesta

{
  "success": true,
  "message": "Información procesada de forma correcta.",
  "data": { "number": "PED P001-15", "order_id": 57 }
}
Campo Qué es
number Número del pedido en el ERP, para mostrárselo al cliente
order_id Identificador interno del pedido en el ERP

Al pagar se reserva el stock de los productos y se descuenta el de sus variantes (talla, color…). Si el pedido se anula, ambos vuelven.

Si algo sale mal

HTTP code Cuándo Qué hacer
404 STORE_NOT_FOUND La tienda no está publicada Publícala en el ERP
503 STORE_PAUSED La tienda está pausada Vuelve a intentarlo más tarde (Retry-After)
401 SESSION_EXPIRED o TOKEN_INVALID Falta el token o no es válido Pide al cliente que inicie sesión
403 NOT_A_STORE_USER El token no es de un cliente de la tienda Usa el token de un cliente
422 VALIDATION_ERROR Falta el contacto u origin, el teléfono no tiene 9 cifras, el método de pago no está disponible o el documento no es válido Corrige el campo que indica errors
400 CART_IDENTIFIER_REQUIRED Falta la cabecera user-ip-address Envía el identificador del carrito
404 CART_NOT_FOUND No hay carrito activo con ese identificador, o es de otra cuenta Añade un producto primero
409 CART_ALREADY_PAID El carrito ya se pagó Consulta el pedido en el historial
422 CART_EMPTY El carrito no tiene productos Añade uno
422 BILLING_NAME_REQUIRED Falta el nombre del documento de facturación Envía billing.name o data
409 OUT_OF_STOCK No hay stock suficiente de algún producto Quita o reduce ese producto
503 STORE_NOT_CONFIGURED Falta el almacén o la serie de pedidos en el ERP Avisa a la tienda