Pedidos
Los pedidos representan las dispensaciones de productos a miembros del club. Esta página documenta los endpoints para gestionar pedidos, incluyendo creación, procesamiento, fulfillment y seguimiento.
Flujo de Pedido
El modelo de Pedido
El modelo de pedido contiene toda la información sobre una dispensación, incluyendo items, pagos, estado de fulfillment y metadata.
Propiedades
- Name
id- Type
- string
- Description
Identificador único del pedido.
- Name
displayId- Type
- string
- Description
Número de pedido legible (ej: #1234).
- Name
status- Type
- OrderStatus
- Description
Estado general del pedido.
- Name
fulfillmentStatus- Type
- FulfillmentStatus
- Description
Estado del proceso de fulfillment.
- Name
paymentStatus- Type
- PaymentStatus
- Description
Estado del pago.
- Name
customer- Type
- object
- Description
Información del cliente que realizó el pedido.
- Name
items- Type
- array
- Description
Lista de items en el pedido.
- Name
id- Type
- string
- Description
ID del item.
- Name
title- Type
- string
- Description
Nombre del producto.
- Name
variantId- Type
- string
- Description
ID de la variante comprada.
- Name
quantity- Type
- number
- Description
Cantidad de unidades.
- Name
unitPrice- Type
- number
- Description
Precio por unidad.
- Name
total- Type
- number
- Description
Total del item.
- Name
payments- Type
- array
- Description
Pagos asociados al pedido.
- Name
subtotal- Type
- number
- Description
Subtotal sin impuestos ni envío.
- Name
shippingTotal- Type
- number
- Description
Costo de envío.
- Name
taxTotal- Type
- number
- Description
Total de impuestos.
- Name
total- Type
- number
- Description
Total del pedido.
- Name
currency- Type
- string
- Description
Código de moneda (ARS, USD).
- Name
shippingAddress- Type
- Address
- Description
Dirección de envío.
- Name
createdAt- Type
- timestamp
- Description
Fecha de creación del pedido.
Ejemplo de pedido completo
{
"id": "order_01HQ8XYZ123",
"displayId": "#1234",
"status": "completed",
"fulfillmentStatus": "shipped",
"paymentStatus": "captured",
"customer": {
"id": "cus_01HQ8ABC456",
"email": "maria@email.com",
"firstName": "María",
"lastName": "González"
},
"items": [
{
"id": "item_01HQ8DEF789",
"title": "Blue Dream 5g",
"variantId": "variant_01HQ_BD_5G",
"quantity": 2,
"unitPrice": 1650000,
"total": 3300000,
"thumbnail": "https://storage.cannahub.tech/..."
}
],
"payments": [
{
"id": "pay_01HQ8GHI012",
"amount": 3300000,
"currency": "ARS",
"status": "captured",
"providerId": "mercadopago",
"createdAt": "2024-03-20T15:30:00Z"
}
],
"subtotal": 3300000,
"shippingTotal": 0,
"taxTotal": 0,
"total": 3300000,
"currency": "ARS",
"shippingAddress": {
"firstName": "María",
"lastName": "González",
"address1": "Av. Corrientes 1234",
"city": "Buenos Aires",
"province": "CABA",
"postalCode": "C1043",
"countryCode": "AR"
},
"createdAt": "2024-03-20T15:00:00Z",
"updatedAt": "2024-03-20T16:00:00Z"
}
Estados del Pedido
OrderStatus
| Estado | Descripción |
|---|---|
pending | Pedido creado, pendiente de procesamiento |
requires_action | Requiere acción del usuario o administrador |
completed | Pedido completado exitosamente |
canceled | Pedido cancelado |
FulfillmentStatus
| Estado | Descripción |
|---|---|
not_fulfilled | No procesado aún |
partially_fulfilled | Parcialmente procesado |
fulfilled | Completamente procesado |
shipped | Enviado/entregado al cliente |
returned | Devuelto |
canceled | Fulfillment cancelado |
PaymentStatus
| Estado | Descripción |
|---|---|
not_paid | Sin pago registrado |
awaiting | Esperando confirmación de pago |
captured | Pago capturado/confirmado |
partially_refunded | Parcialmente reembolsado |
refunded | Completamente reembolsado |
Listar pedidos
Este endpoint permite obtener una lista paginada de pedidos con filtros opcionales.
Parámetros opcionales
- Name
limit- Type
- integer
- Description
Número máximo de pedidos a retornar (default: 10).
- Name
offset- Type
- integer
- Description
Número de pedidos a saltar para paginación.
- Name
status- Type
- string
- Description
Filtrar por estado del pedido.
- Name
fulfillment_status- Type
- string
- Description
Filtrar por estado de fulfillment.
- Name
payment_status- Type
- string
- Description
Filtrar por estado de pago.
- Name
customer_id- Type
- string
- Description
Filtrar por ID de cliente.
Request
curl -G https://yourapp.com/api/orders \
-H "Authorization: Bearer {token}" \
-d limit=10 \
-d status=pending
Response
{
"orders": [
{
"id": "order_01HQ8XYZ123",
"displayId": "#1234",
"status": "pending",
"total": 3300000,
"customer": {
"email": "maria@email.com"
},
"createdAt": "2024-03-20T15:00:00Z"
}
],
"count": 1,
"offset": 0,
"limit": 10
}
Obtener pedido
Este endpoint permite obtener los detalles completos de un pedido específico.
Medusa Reference
Request
curl https://yourapp.com/api/orders/order_01HQ8XYZ123 \
-H "Authorization: Bearer {token}"
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"displayId": "#1234",
"status": "pending",
"fulfillmentStatus": "not_fulfilled",
"paymentStatus": "captured",
"items": [...],
"payments": [...],
"total": 3300000
}
}
Crear pedido (desde carrito)
Los pedidos se crean completando un carrito existente. Este es el flujo estándar para miembros.
Medusa Reference
Flujo completo
- Crear carrito con región
- Agregar items al carrito
- Seleccionar método de envío
- Inicializar sesión de pago
- Completar el carrito (crea el pedido)
Request
// 1. Crear carrito
const { cart } = await medusa.carts.create({
region_id: 'reg_argentina'
})
// 2. Agregar items
await medusa.carts.lineItems.create(cart.id, {
variant_id: 'variant_01HQ_BD_5G',
quantity: 2
})
// 3. Agregar método de envío
await medusa.carts.addShippingMethod(cart.id, {
option_id: 'so_pickup'
})
// 4. Inicializar pago
await medusa.carts.createPaymentSessions(cart.id)
await medusa.carts.setPaymentSession(cart.id, {
provider_id: 'mercadopago'
})
// 5. Completar pedido
const { order } = await medusa.carts.complete(cart.id)
Response
{
"type": "order",
"order": {
"id": "order_01HQ8XYZ123",
"displayId": "#1234",
"status": "pending",
"paymentStatus": "awaiting",
"items": [...],
"total": 3300000
}
}
Capturar pago
Captura el pago de un pedido. Esto confirma que el pago fue recibido.
Medusa Reference
Request
curl -X POST https://yourapp.com/api/orders/order_01HQ8XYZ123/capture \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json"
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"paymentStatus": "captured"
}
}
Crear fulfillment
Crea un fulfillment para marcar items como procesados y listos para entrega.
Medusa Reference
Request
curl -X POST https://yourapp.com/api/orders/order_01HQ8XYZ123/fulfill \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"items": [
{
"id": "item_01HQ8DEF789",
"quantity": 2
}
],
"locationId": "loc_highup_main"
}'
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"fulfillmentStatus": "fulfilled",
"fulfillments": [
{
"id": "ful_01HQ8JKL345",
"items": [...],
"createdAt": "2024-03-20T16:00:00Z"
}
]
},
"fulfillmentId": "ful_01HQ8JKL345"
}
Marcar como enviado
Marca un fulfillment como enviado/entregado al cliente.
Medusa Reference
Request
curl -X POST https://yourapp.com/api/orders/order_01HQ8XYZ123/ship \
-H "Authorization: Bearer {token}" \
-H "Content-Type: application/json" \
-d '{
"fulfillmentId": "ful_01HQ8JKL345"
}'
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"fulfillmentStatus": "shipped"
}
}
Cancelar pedido
Cancela un pedido. Solo se pueden cancelar pedidos que no han sido enviados o entregados.
Medusa Reference
Al cancelar un pedido, el inventario reservado se libera automáticamente y se puede procesar un reembolso si el pago ya fue capturado.
Request
curl -X POST https://yourapp.com/api/orders/order_01HQ8XYZ123/cancel \
-H "Authorization: Bearer {token}"
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"status": "canceled"
}
}
Registro de Actividad
Los pedidos en Cannahub incluyen un registro de actividad para tracking de cambios. Las actividades se almacenan en order.metadata.activityLogs.
- Name
activityLogs- Type
- array
- Description
Historial de actividades del pedido.
- Name
type- Type
- 'system' | 'user'
- Description
Tipo de actividad.
- Name
status- Type
- 'info' | 'success' | 'warning' | 'error'
- Description
Estado/nivel de la actividad.
- Name
description- Type
- string
- Description
Clave de traducción o descripción de la actividad.
- Name
at- Type
- string
- Description
Fecha y hora de la actividad (ISO 8601).
- Name
author- Type
- object
- Description
Usuario que realizó la acción.
- Name
id- Type
- string
- Description
ID del usuario.
- Name
firstName- Type
- string
- Description
Nombre del usuario.
- Name
lastName- Type
- string
- Description
Apellido del usuario.
Tipos de Descripción
| Clave | Significado |
|---|---|
orders:activity.created | Pedido creado |
orders:activity.paymentConfirmed | Pago confirmado |
orders:activity.fulfilled | Pedido preparado |
orders:activity.shipped | Pedido enviado |
orders:activity.completed | Pedido completado |
orders:activity.invoiced | Pedido facturado |
orders:activity.cancelled | Pedido cancelado |
orders:activity.note | Nota agregada |
Ejemplo de actividad
{
"activityLogs": [
{
"type": "system",
"status": "success",
"description": "orders:activity.created",
"at": "2024-03-20T15:00:00Z",
"author": {
"id": "user_01HQ8ABC",
"firstName": "Juan",
"lastName": "Admin"
}
},
{
"type": "system",
"status": "success",
"description": "orders:activity.paymentConfirmed",
"at": "2024-03-20T15:30:00Z",
"author": {
"id": "user_01HQ8ABC",
"firstName": "Juan",
"lastName": "Admin"
}
},
{
"type": "system",
"status": "success",
"description": "orders:activity.fulfilled",
"at": "2024-03-20T16:00:00Z",
"author": {
"id": "user_01HQ8ABC",
"firstName": "Juan",
"lastName": "Admin"
}
},
{
"type": "system",
"status": "success",
"description": "orders:activity.completed",
"at": "2024-03-20T17:00:00Z",
"author": {
"id": "user_01HQ8ABC",
"firstName": "Juan",
"lastName": "Admin"
}
}
]
}
BFF Route: Crear y Procesar Pedido
Esta ruta BFF simplifica el flujo completo de creación de pedido de 15+ llamadas API a una sola llamada. Ideal para dispensaciones rápidas desde el panel de administración.
Este endpoint orquesta todo el flujo de creación de pedido internamente:
- Crear carrito
- Agregar items (en paralelo)
- Configurar método de envío
- Inicializar sesión de pago
- Completar pedido
- Capturar pago
- Crear fulfillment
- Marcar como enviado
- Registrar actividades
Request Body
- Name
customer- Type
- object
- Description
Información del cliente.
- Name
id- Type
- string
- Description
ID del cliente en Medusa.
- Name
email- Type
- string
- Description
Email del cliente.
- Name
firstName- Type
- string
- Description
Nombre del cliente.
- Name
lastName- Type
- string
- Description
Apellido del cliente.
- Name
items- Type
- array
- Description
Items a incluir en el pedido.
- Name
variantId- Type
- string
- Description
ID de la variante del producto.
- Name
quantity- Type
- number
- Description
Cantidad a ordenar.
- Name
shippingMethod- Type
- string
- Description
Método de envío:
pickupodelivery.
- Name
paymentMethod- Type
- string
- Description
Método de pago:
cash,mercadopago,transfer.
- Name
locationId- Type
- string
- Description
ID de la ubicación de stock (para fulfillment).
- Name
notes- Type
- string
- Description
Notas adicionales para el pedido.
Beneficio de Performance
| Flujo | Llamadas API | Latencia Estimada |
|---|---|---|
| Cliente directo | 15+ llamadas | ~3-5 segundos |
| BFF Route | 1 llamada | ~1-2 segundos |
| Reducción | 93% | 60-70% |
Request
curl -X POST https://app.cannahub.tech/api/orders/create-and-process \
-H "Authorization: Bearer {admin_token}" \
-H "Content-Type: application/json" \
-d '{
"customer": {
"id": "cus_01HQ8ABC456",
"email": "maria@email.com",
"firstName": "María",
"lastName": "González"
},
"items": [
{ "variantId": "variant_01HQ_BD_5G", "quantity": 2 },
{ "variantId": "variant_01HQ_GG_1G", "quantity": 1 }
],
"shippingMethod": "pickup",
"paymentMethod": "cash",
"locationId": "sloc_high_up"
}'
Response
{
"order": {
"id": "order_01HQ8XYZ123",
"displayId": "#1234",
"status": "completed",
"fulfillmentStatus": "shipped",
"paymentStatus": "captured",
"customer": {
"id": "cus_01HQ8ABC456",
"email": "maria@email.com",
"firstName": "María",
"lastName": "González"
},
"items": [
{
"id": "item_01HQ8DEF789",
"title": "Blue Dream 5g",
"quantity": 2,
"unitPrice": 1650000,
"total": 3300000
},
{
"id": "item_01HQ8DEF790",
"title": "Gorilla Glue 1g",
"quantity": 1,
"unitPrice": 350000,
"total": 350000
}
],
"total": 3650000,
"currency": "ARS"
},
"timeline": [
{
"action": "ORDER_CREATED",
"timestamp": "2024-03-20T15:00:00Z"
},
{
"action": "PAYMENT_CAPTURED",
"timestamp": "2024-03-20T15:00:01Z"
},
{
"action": "FULFILLMENT_CREATED",
"timestamp": "2024-03-20T15:00:02Z"
},
{
"action": "ORDER_SHIPPED",
"timestamp": "2024-03-20T15:00:03Z"
}
]
}
Diagrama de Flujo Interno
Mapeo Medusa
La API BFF transforma las respuestas de Medusa de snake_case a camelCase:
Campos de Order
| UI (camelCase) | Medusa (snake_case) |
|---|---|
displayId / number | display_id |
createdAt | created_at |
subTotal | subtotal |
discountTotal | discount_total |
taxTotal | tax_total |
shippingTotal | shipping_total |
paymentStatus | payment_status |
fulfillmentStatus | fulfillment_status |
customerId | customer_id |
currency | currency_code |
Campos de Order Item
| UI (camelCase) | Medusa (snake_case) |
|---|---|
unitPrice | unit_price |
variantId | variant_id |
productId | product_id |
Campos de Metadata
| UI (camelCase) | Medusa (snake_case) |
|---|---|
activityLogs | activity_logs |
isInvoiced | isInvoiced |
invoicedAt | invoicedAt |
Las funciones de parser estan en /src/lib/medusa/orders.ts:
import { parseMedusaOrder, parseOrderMetadata, serializeOrderMetadata } from '@/lib/medusa/orders'
// Transforma respuesta Medusa a camelCase
const order = parseMedusaOrder(medusaResponse.order)
// Transforma metadata
const metadata = parseOrderMetadata(order.metadata)
// Serializa metadata para enviar a Medusa
const serialized = serializeOrderMetadata(metadata)