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

Loading diagram...

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

EstadoDescripción
pendingPedido creado, pendiente de procesamiento
requires_actionRequiere acción del usuario o administrador
completedPedido completado exitosamente
canceledPedido cancelado

FulfillmentStatus

EstadoDescripción
not_fulfilledNo procesado aún
partially_fulfilledParcialmente procesado
fulfilledCompletamente procesado
shippedEnviado/entregado al cliente
returnedDevuelto
canceledFulfillment cancelado

PaymentStatus

EstadoDescripción
not_paidSin pago registrado
awaitingEsperando confirmación de pago
capturedPago capturado/confirmado
partially_refundedParcialmente reembolsado
refundedCompletamente reembolsado

GET/api/orders

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

GET
/api/orders
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
}

GET/api/orders/:id

Obtener pedido

Este endpoint permite obtener los detalles completos de un pedido específico.

Request

GET
/api/orders/:id
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
  }
}

POST/store/carts/:id/complete

Crear pedido (desde carrito)

Los pedidos se crean completando un carrito existente. Este es el flujo estándar para miembros.

Flujo completo

  1. Crear carrito con región
  2. Agregar items al carrito
  3. Seleccionar método de envío
  4. Inicializar sesión de pago
  5. Completar el carrito (crea el pedido)

Request

POST
/store/carts/:id/complete
// 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
  }
}

POST/api/orders/:id/capture

Capturar pago

Captura el pago de un pedido. Esto confirma que el pago fue recibido.

Request

POST
/api/orders/:id/capture
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"
  }
}

POST/api/orders/:id/fulfill

Crear fulfillment

Crea un fulfillment para marcar items como procesados y listos para entrega.

Request

POST
/api/orders/:id/fulfill
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"
}

POST/api/orders/:id/ship

Marcar como enviado

Marca un fulfillment como enviado/entregado al cliente.

Request

POST
/api/orders/:id/ship
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"
  }
}

POST/api/orders/:id/cancel

Cancelar pedido

Cancela un pedido. Solo se pueden cancelar pedidos que no han sido enviados o entregados.

Request

POST
/api/orders/:id/cancel
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

ClaveSignificado
orders:activity.createdPedido creado
orders:activity.paymentConfirmedPago confirmado
orders:activity.fulfilledPedido preparado
orders:activity.shippedPedido enviado
orders:activity.completedPedido completado
orders:activity.invoicedPedido facturado
orders:activity.cancelledPedido cancelado
orders:activity.noteNota 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"
      }
    }
  ]
}

POST/api/orders/create-and-process

BFF Route: Crear y Procesar Pedido

Este endpoint orquesta todo el flujo de creación de pedido internamente:

  1. Crear carrito
  2. Agregar items (en paralelo)
  3. Configurar método de envío
  4. Inicializar sesión de pago
  5. Completar pedido
  6. Capturar pago
  7. Crear fulfillment
  8. Marcar como enviado
  9. 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: pickup o delivery.

  • 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

FlujoLlamadas APILatencia Estimada
Cliente directo15+ llamadas~3-5 segundos
BFF Route1 llamada~1-2 segundos
Reducción93%60-70%

Request

POST
/api/orders/create-and-process
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

Loading diagram...

Mapeo Medusa

La API BFF transforma las respuestas de Medusa de snake_case a camelCase:

Campos de Order

UI (camelCase)Medusa (snake_case)
displayId / numberdisplay_id
createdAtcreated_at
subTotalsubtotal
discountTotaldiscount_total
taxTotaltax_total
shippingTotalshipping_total
paymentStatuspayment_status
fulfillmentStatusfulfillment_status
customerIdcustomer_id
currencycurrency_code

Campos de Order Item

UI (camelCase)Medusa (snake_case)
unitPriceunit_price
variantIdvariant_id
productIdproduct_id

Campos de Metadata

UI (camelCase)Medusa (snake_case)
activityLogsactivity_logs
isInvoicedisInvoiced
invoicedAtinvoicedAt

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)

POST/api/orders/:id/invoice

Crear factura

Marca un pedido como facturado mediante una actualización de metadata. No requiere body.

La operación actualiza order.metadata con isInvoiced: true e invoicedAt con la fecha actual, y agrega un evento de actividad orders:activity.invoiced.

Request

POST
/api/orders/:id/invoice
curl -X POST https://yourapp.com/api/orders/order_01HQ8XYZ123/invoice \
  -H "Authorization: Bearer {token}"

Response

{
  "order": {
    "id": "order_01HQ8XYZ123",
    "displayId": "#1234",
    "status": "completed",
    "metadata": {
      "isInvoiced": true,
      "invoicedAt": "2024-03-20T18:00:00Z",
      "activityLogs": [
        {
          "type": "system",
          "status": "success",
          "description": "orders:activity.invoiced",
          "at": "2024-03-20T18:00:00Z",
          "author": {
            "id": "user_01HQ8ABC",
            "firstName": "Juan",
            "lastName": "Admin"
          }
        }
      ]
    }
  }
}

GET/api/orders/:id/activities

Obtener actividades

Retorna el registro de actividades de un pedido almacenado en su metadata. Útil para mostrar la línea de tiempo de eventos del pedido.

Respuesta

  • Name
    activities
    Type
    OrderActivityEvent[]
    Description

    Lista de eventos de actividad del pedido. Cada evento contiene type, status, description, at y author.

Request

GET
/api/orders/:id/activities
curl https://yourapp.com/api/orders/order_01HQ8XYZ123/activities \
  -H "Authorization: Bearer {token}"

Response

{
  "activities": [
    {
      "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"
      }
    }
  ]
}

POST/api/orders/create-and-process-stream

BFF Route: Crear y Procesar Pedido (Streaming)

Este endpoint acepta el mismo body que /api/orders/create-and-process pero responde con un stream de eventos SSE en lugar de una respuesta JSON única. Cada evento indica el paso actual, un mensaje descriptivo y el porcentaje de progreso.

Request Body

Idéntico a /api/orders/create-and-process. Ver ese endpoint para detalles del body.

Formato de Eventos SSE

  • Name
    step
    Type
    string
    Description

    Identificador del paso actual (ej: creating_cart, adding_items, capturing_payment).

  • Name
    message
    Type
    string
    Description

    Mensaje descriptivo del paso en curso.

  • Name
    progress
    Type
    number
    Description

    Porcentaje de progreso (0-100).

  • Name
    success
    Type
    boolean
    Description

    Presente en el evento final. Indica si el flujo se completó exitosamente.

  • Name
    error
    Type
    string
    Description

    Presente solo si el flujo falla. Mensaje de error descriptivo.

  • Name
    order
    Type
    Order
    Description

    Presente en el evento final exitoso. Pedido creado y procesado.

Content-Type

La respuesta usa Content-Type: text/event-stream siguiendo el estándar SSE.

Request

POST
/api/orders/create-and-process-stream
curl -N -X POST https://app.cannahub.tech/api/orders/create-and-process-stream \
  -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 }
    ],
    "shippingMethod": "pickup",
    "paymentMethod": "cash",
    "locationId": "sloc_high_up"
  }'

Eventos SSE (stream)

data: {"step":"creating_cart","message":"Creando carrito...","progress":10}

data: {"step":"adding_items","message":"Agregando productos...","progress":25}

data: {"step":"configuring_shipping","message":"Configurando envío...","progress":40}

data: {"step":"initializing_payment","message":"Inicializando pago...","progress":55}

data: {"step":"completing_cart","message":"Completando pedido...","progress":65}

data: {"step":"capturing_payment","message":"Capturando pago...","progress":75}

data: {"step":"creating_fulfillment","message":"Creando fulfillment...","progress":85}

data: {"step":"shipping_order","message":"Marcando como enviado...","progress":95}

data: {"step":"completed","message":"Pedido creado exitosamente","progress":100,"success":true,"order":{"id":"order_01HQ8XYZ123","displayId":"#1234","status":"completed"}}

Próximos Pasos

API de ProductosAPI de MiembrosAPI de InventarioWebhooks