Guías prácticas

Guías paso a paso para tareas comunes. Cada guía incluye ejemplos de código listos para copiar.

Info: Todos los ejemplos usan curl y asumen que YOUR_API_KEY y YOUR_TOKEN están definidos. Reemplazalos con tus credenciales reales. El playground de la API te permite probarlos sin curl.

Gestión de productos

Crear un producto (Admin)

curl -X POST http://localhost:3000/api/admin/products \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Remera de algodón orgánico",
    "description": "Suave, sustentable y con estilo.",
    "price": 2900,
    "comparePrice": 3900,
    "categoryId": "CATEGORY_UUID",
    "images": ["https://example.com/remera.jpg"],
    "isActive": true
  }'
Tip: Slugs automáticos: No necesitás enviar el slug — el backend lo genera automáticamente del nombre. Por ejemplo, "Remera de algodón orgánico" → remera-de-algodon-organico.

Actualizar un producto

Solo enviá los campos que querés cambiar — todos los campos son opcionales en la actualización.

curl -X PUT http://localhost:3000/api/admin/products/PRODUCT_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"price": 1900, "isActive": false}'

Buscar y filtrar productos

# Buscar por nombre
GET /api/admin/products?search=remera

# Filtrar por categoría
GET /api/admin/products?categoryId=CATEGORY_UUID

# Solo productos activos
GET /api/admin/products?active=true

# Combinar filtros
GET /api/admin/products?search=algodon&active=true&limit=10

Eliminar un producto

curl -X DELETE http://localhost:3000/api/admin/products/PRODUCT_ID \
  -H "Authorization: Bearer YOUR_TOKEN"

Carrito de compras

Flujo completo del carrito

# 1. Crear un carrito
POST /api/store/cart
→ { "data": { "token": "cart_abc123..." } }

# 2. Agregar ítems
POST /api/store/cart/cart_abc123.../items
Body: { "productId": "...", "quantity": 2 }

# 3. Ver el carrito (con totales)
GET /api/store/cart/cart_abc123...
→ { "data": { "items": [...], "subtotal": 5000, "itemCount": 2 } }

# 4. Actualizar cantidad
PUT /api/store/cart/cart_abc123.../items
Body: { "productId": "...", "quantity": 5 }

# 5. Eliminar ítem (poner quantity en 0)
PUT /api/store/cart/cart_abc123.../items
Body: { "productId": "...", "quantity": 0 }

# O eliminar por query param:
DELETE /api/store/cart/cart_abc123.../items?productId=...
Info: Precio fijado: Cuando agregás un producto al carrito, el precio actual queda guardado. Si el precio del producto cambia después, el ítem del carrito mantiene el precio original. Esto evita sorpresas en el checkout.

Implementación en el frontend (JavaScript)

// Guardar el token del carrito en una cookie
const CART_COOKIE = 'cart_token';

async function getOrCreateCart(apiKey) {
  let token = getCookie(CART_COOKIE);

  if (!token) {
    const res = await fetch('/api/store/cart', {
      method: 'POST',
      headers: { 'x-api-key': apiKey },
    });
    const data = await res.json();
    token = data.data.token;
    setCookie(CART_COOKIE, token, 30); // 30 días
  }

  return token;
}

async function addToCart(apiKey, productId, quantity = 1) {
  const token = await getOrCreateCart(apiKey);

  const res = await fetch(`/api/store/cart/${token}/items`, {
    method: 'POST',
    headers: {
      'x-api-key': apiKey,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ productId, quantity }),
  });

  return res.json();
}

Checkout y pagos

Flujo de checkout

# Crear una sesión de Stripe Checkout
curl -X POST http://localhost:3000/api/store/checkout \
  -H "x-api-key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "cartToken": "cart_abc123...",
    "email": "cliente@ejemplo.com",
    "shippingAddress": {
      "name": "Juan Pérez",
      "line1": "Av. Corrientes 1234",
      "city": "Buenos Aires",
      "state": "CABA",
      "postalCode": "C1043",
      "country": "AR"
    }
  }'

# Respuesta:
# { "data": { "checkout_url": "https://checkout.stripe.com/..." } }
# → Redirigí al cliente a checkout_url
Atención: Nunca procesés información de pago en tu servidor. Siempre redirigí a Stripe Checkout. El pago lo maneja completamente Stripe — nunca tocás los datos de la tarjeta de crédito.

¿Qué pasa después del pago?

  1. El cliente completa el pago en Stripe
  2. Stripe envía el webhook checkout.session.completed a /api/webhooks/stripe
  3. TiendaAPI crea automáticamente el pedido con estado paid
  4. El cliente es redirigido a /{store}/order/{session_id}
  5. Se envía el email de confirmación (si Resend está configurado)

Pedidos

Listar pedidos (Admin)

GET /api/admin/orders?limit=20
Authorization: Bearer YOUR_TOKEN

Actualizar el estado de un pedido

curl -X PUT http://localhost:3000/api/admin/orders/ORDER_ID \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"status": "shipped"}'

Transiciones de estado válidas

EstadoSignificado
pendingPedido creado, pago aún no confirmado
paidPago confirmado vía webhook de Stripe
shippedEl pedido fue enviado
deliveredEl pedido fue entregado al cliente
cancelledPedido cancelado

Consulta de pedidos del cliente (API de tienda)

# Por ID de pedido
GET /api/store/orders/ORDER_UUID?email=cliente@ejemplo.com

# Por ID de sesión de Stripe (usado en la página de confirmación)
GET /api/store/orders/cs_test_abc123...

Webhooks

Cómo funcionan los webhooks de Stripe

El cliente paga en Stripe
        ↓
Stripe envía POST /api/webhooks/stripe
  con evento: checkout.session.completed
        ↓
TiendaAPI verifica la firma (HMAC)
        ↓
Verifica idempotencia (¿ya se procesó este evento?)
        ↓
Crea el pedido + marca el carrito como completado
        ↓
Envía email de confirmación

Configuración

  1. En el Dashboard de Stripe, agregá un endpoint: https://tudominio.com/api/webhooks/stripe
  2. Seleccioná el evento: checkout.session.completed
  3. Copiá el secreto de firma del webhook y configuralo como STRIPE_WEBHOOK_SECRET
Tip: Para desarrollo local, usá el CLI de Stripe:
stripe listen --forward-to localhost:3000/api/webhooks/stripe

Idempotencia

Stripe puede enviar el mismo webhook varias veces. TiendaAPI registra cada ID de evento procesado en la tabla webhook_logs. Los eventos duplicados se ignoran de forma segura — sin cargos dobles ni pedidos duplicados.

Subida de imágenes

Subir una imagen de producto

curl -X POST http://localhost:3000/api/admin/upload \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -F "file=@/ruta/a/foto-producto.jpg"

Respuesta:

{
  "data": {
    "url": "https://abc.public.blob.vercel-storage.com/stores/xxx/foto-producto-abc123.jpg"
  }
}

Usá la URL al crear o actualizar productos

curl -X POST http://localhost:3000/api/admin/products \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mi Producto",
    "price": 1500,
    "images": ["https://abc.public.blob.vercel-storage.com/stores/xxx/foto-producto-abc123.jpg"]
  }'

Límites

RestricciónValor
Tamaño máximo5 MB
Formatos permitidosJPEG, PNG, WebP, GIF
AlmacenamientoVercel Blob (con CDN)

Próximos pasos