📡

Obtener Docs de API con chub

Recupera documentación actualizada de cualquier API o SDK antes de escribir código — garantiza que el código es correcto contra la referencia real, no contra datos de entrenamiento.

✓ Ejecutado Node.js · TypeScript Stripe API Skill #4db58467
1. Instalar chub
2. Buscar docs
3. Fetch docs
4. Generar código
5. Anotar gotcha
Contexto — CULTIVA IA Tienda de Recursos
Stripe
API target
5 €
precio por recurso
TS
lenguaje objetivo
Paso 1 — Verificar e instalar chub
Terminal
bash — CULTIVA IA workspace
Verificar si chub ya está instalado
chub --help
command not found: chub
No existe → instalamos globalmente
npm install -g @aisuite/chub
added 47 packages in 3.2s
+ @aisuite/chub@0.4.1 installed globally ✓
chub --help
chub — Context Hub CLI v0.4.1
search <keywords> Busca documentación indexada
get <id> Descarga y muestra la doc
annotate <id> <note> Añade una anotación local
feedback <id> Envía feedback a la comunidad
Options: --lang [py|js|ts] --json --verbose
Paso 2 — Buscar documentación de Stripe
Comando ejecutado
chub search "stripe checkout payments" --json
[
{ "id": "stripe/checkout", "score": 0.97 },
{ "id": "stripe/api", "score": 0.91 },
{ "id": "stripe/webhooks", "score": 0.88 },
{ "id": "stripe/sdk-node", "score": 0.84 },
]
Resultados encontrados — selección
stripe/checkout Checkout Sessions — create, expire, retrieve 97%
stripe/webhooks Webhooks — events, signatures, raw body 88%
stripe/api REST API reference — all resources 91%
stripe/sdk-node Node.js SDK — types, configuration 84%
✓ Seleccionados 2 de 4 resultados — scope específico para la tarea
Paso 3 — Fetch de documentación actualizada
stripe/checkout — Checkout Sessions

📦 POST /v1/checkout/sessions

Crea una sesión de Stripe Checkout. Devuelve la URL de pago a la que redirigir al cliente.

line_items array Productos a comprar (price_id + quantity)
mode string 'payment' | 'subscription' | 'setup'
success_url string URL de redirección tras pago exitoso
cancel_url string URL si el usuario cancela
metadata object Datos extra: recurso_id, user_id, etc.

📋 Response: Session object

id string cs_live_xxx — ID de la sesión
url string URL de pago → redirigir usuario aquí
payment_status string 'paid' | 'unpaid' | 'no_payment_required'
stripe/webhooks — Firma y Body Raw

🔐 Verificación de webhook

Stripe firma cada evento con HMAC-SHA256. Verificar la firma es OBLIGATORIO para prevenir ataques.

stripe.webhooks.constructEvent() method Verifica firma y parsea el evento
payload Buffer ⚠️ Body RAW — no parsear antes
sig string Header Stripe-Signature del request
secret string STRIPE_WEBHOOK_SECRET del dashboard

📨 Eventos clave

checkout.session.completed event Pago completado → conceder acceso
payment_intent.payment_failed event Fallo de pago → notificar usuario
Paso 4 — Código generado desde la documentación real
api/checkout.ts — Checkout Session endpoint
api/checkout.ts TypeScript
// CULTIVA IA — Tienda de Recursos — POST /api/checkout
// Generado con documentación chub: stripe/checkout v2024-11-20.acacia
import Stripe from 'stripe';
import { Request, Response } from 'express';
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!, {
  apiVersion: '2024-11-20.acacia', // versión del doc chub
});
export async function createCheckout(req: Request, res: Response) {
  const { recurso_id, user_id, price_id } = req.body;
  const session = await stripe.checkout.sessions.create({
    line_items: [{ price: price_id, quantity: 1 }],
    mode: 'payment',
    success_url: `${process.env.SITE_URL}/descarga?session_id={CHECKOUT_SESSION_ID}`,
    cancel_url: `${process.env.SITE_URL}/recursos`,
    metadata: { recurso_id, user_id },
  });
  // session.url es la URL de Checkout — doc: Session.url (string|null)
  res.json({ checkoutUrl: session.url });
}
webhooks/stripe.ts — Verificación con body raw
webhooks/stripe.ts TypeScript
// ⚠️ Gotcha detectado con chub: raw body obligatorio (ver anotación)
// En app.ts — excluir esta ruta del express.json() global:
app.use('/webhooks/stripe', express.raw({ type: 'application/json' }));
export async function handleStripeWebhook(req, res) {
  const sig = req.headers['stripe-signature'] as string;
  let event: Stripe.Event;
  try {
    // payload debe ser Buffer — NO JSON.parse() previo
    event = stripe.webhooks.constructEvent(
      req.body, // Buffer gracias a express.raw()
      sig,
      process.env.STRIPE_WEBHOOK_SECRET!
    );
  } catch (err) {
    return res.status(400).send(`Webhook inválido: ${err.message}`);
  }
  if (event.type === 'checkout.session.completed') {
    const session = event.data.object as Stripe.Checkout.Session;
    const { recurso_id, user_id } = session.metadata!;
    await grantAccess(user_id, recurso_id);
  }
  res.json({ received: true });
}
Paso 5 — Anotación guardada (persiste entre sesiones)
Terminal — chub annotate
chub annotate stripe/webhooks \
"Body RAW obligatorio — usar express.raw() en la ruta del webhook,
excluirla de express.json() global. Si parseas antes,
constructEvent lanza SignatureVerificationError."
✓ Anotación guardada en ~/.chub/annotations/stripe__webhooks.txt
Aparecerá automáticamente en futuros `chub get stripe/webhooks`
Anotación local — persistente
📌 Anotación — stripe/webhooks
Body RAW obligatorio — usar express.raw() en la ruta del webhook, excluirla de express.json() global. Si parseas antes, constructEvent lanza SignatureVerificationError.
↳ Guardado en ~/.chub/annotations/ · reaparece en próximos chub get stripe/webhooks
Esta anotación evitará el mismo error en futuros proyectos que integren Stripe webhooks.
Impacto — Con vs. Sin esta skill
✗ Sin chub — desde memoria de entrenamiento
Versión de API incorrecta o deprecada
Parámetro stripe.createCheckoutSession() (deprecado)
Webhook sin raw body → 400 SignatureError en prod
Gotcha del express.json() no documentado
⏱️2-4h de debug para encontrar los errores
✓ Con chub — documentación real en tiempo real
API v2024-11-20.acacia — siempre actualizada
stripe.checkout.sessions.create() correcto
express.raw() aplicado correctamente desde el inicio
Anotación guardada → próximos proyectos arrancan más listos
Código correcto en el primer intento