> ## Documentation Index
> Fetch the complete documentation index at: https://docs.onflay.com/llms.txt
> Use this file to discover all available pages before exploring further.

# CLI

> Gestiona tu catálogo desde código, escucha webhooks localmente y dispara eventos de prueba con la CLI de Onflay.

La CLI de Onflay (`onflay`) es la forma más rápida de arrancar un proyecto de integración sin tocar el dashboard. Define tu catálogo en un archivo TypeScript, aplícalo al entorno y genera tipos listos para usar en tu backend, todo desde la terminal.

## Instalación y autenticación

No necesitas instalar nada de forma global. Usa `npx` directamente o agrégala como devDependency:

```bash theme={"dark"}
# Sin instalación
npx onflay --help

# Como devDependency (recomendado para proyectos)
pnpm add -D onflay
```

Autentica exportando tu API key de sandbox:

```bash theme={"dark"}
export ONFLAY_API_KEY=sk_test_...
```

<Tip>
  Agrega `ONFLAY_API_KEY` a tu archivo `.env` y cárgalo con `dotenv-cli` o el mecanismo de tu framework. La CLI lo detecta automáticamente. También puedes usar `onflay whoami` para validar entorno y base URL resuelta.
</Tip>

***

## Flujo CLI-first para un proyecto nuevo

Puedes configurar toda tu integración sin abrir el dashboard:

<Steps>
  <Step title="Scaffold inicial (opcional)">
    Ejecuta `npx onflay init` para crear `pricing.onflay.ts`, webhook route y `.env.example` automáticamente.
  </Step>

  <Step title="Crea el archivo de catálogo">
    Define tus productos, precios o listings en `pricing.onflay.ts`.
  </Step>

  <Step title="Revisa el plan">
    Ejecuta `catalog plan` para ver qué se creará o modificará sin aplicar nada.
  </Step>

  <Step title="Aplica el catálogo">
    Ejecuta `catalog apply` para sincronizar el archivo con tu entorno sandbox.
  </Step>

  <Step title="Genera los tipos">
    Ejecuta `catalog sync` para aplicar + generar tipos en un solo comando (o `catalog codegen` si ya aplicaste antes).
  </Step>

  <Step title="Levanta el túnel de webhooks">
    Ejecuta `onflay listen` para recibir eventos en tu servidor local.
  </Step>

  <Step title="Dispara un evento de prueba">
    Ejecuta `onflay trigger` para simular un pago completado y probar tu handler.
  </Step>
</Steps>

***

## Catálogo declarativo

El catálogo es un archivo `.ts` que exporta la definición de lo que vendes. La CLI lo lee, calcula la diferencia con el entorno y aplica solo los cambios necesarios — similar a Terraform para tu catálogo de Onflay.

### Estructura del archivo

```ts theme={"dark"}
// pricing.onflay.ts
import { defineCatalog } from 'onflay/catalog';

export default defineCatalog({
  products: [
    {
      nickname: 'pro_plan',
      name: 'Plan Pro',
      description: 'Acceso completo a todas las funciones.',
      prices: [
        {
          nickname: 'pro_monthly',
          amount: 2900,
          currency: 'usd',
          interval: 'month',
        },
        {
          nickname: 'pro_annual',
          amount: 29000,
          currency: 'usd',
          interval: 'year',
        },
      ],
    },
    {
      nickname: 'starter_plan',
      name: 'Plan Starter',
      description: 'Para proyectos personales y pruebas.',
      prices: [
        {
          nickname: 'starter_monthly',
          amount: 900,
          currency: 'usd',
          interval: 'month',
        },
      ],
    },
  ],
});
```

<Note>
  El campo `nickname` es tu identificador local estable. No lo cambies sin usar antes `onflay catalog mv`, o la CLI lo tratará como un objeto nuevo.
</Note>

### Pagos únicos

Para productos sin recurrencia, omite `interval`:

```ts theme={"dark"}
prices: [
  {
    nickname: 'ebook_usd',
    amount: 1500,
    currency: 'usd',
  },
],
```

***

## Comandos del catálogo

### `catalog plan` — previsualizar cambios

Muestra qué se creará, actualizará o archivará sin modificar nada en el entorno.

```bash theme={"dark"}
npx onflay catalog plan pricing.onflay.ts
```

Salida de ejemplo:

```
~ Plan Pro               (actualizar descripción)
+ Plan Starter           (crear)
+ Starter mensual        (crear price)
  Pro mensual            (sin cambios)
  Pro anual              (sin cambios)
```

Úsalo en CI para detectar drift entre el archivo y el entorno.

Con `--exit-code`, la CLI termina con código `2` cuando detecta drift:

```bash theme={"dark"}
npx onflay catalog plan pricing.onflay.ts --exit-code
```

### `catalog apply` — aplicar cambios

Sincroniza el archivo con el entorno activo según la API key configurada.

```bash theme={"dark"}
npx onflay catalog apply pricing.onflay.ts
```

<Warning>
  `apply` modifica objetos en el entorno apuntado por `ONFLAY_API_KEY`. Con `sk_test_` toca sandbox; con `sk_live_` toca producción. Revisa siempre el `plan` antes.
</Warning>

### `catalog codegen` — generar tipos TypeScript

Genera un archivo con los IDs reales de Onflay mapeados a tus keys, listo para importar en tu backend:

```bash theme={"dark"}
npx onflay catalog codegen pricing.onflay.ts --out src/onflay-catalog.ts
```

Archivo generado (`src/onflay-catalog.ts`):

```ts theme={"dark"}
// Archivo generado automáticamente — no editar manualmente
export const catalog = {
  products: {
    pro_plan: 'cmpulbdci00004moh85qpsd6k',
    starter_plan: 'cmpuql04c000p4mn3iumpcaxf',
  },
  prices: {
    pro_monthly: 'cmpulbdci00004moh85qpsd6k:cmpulbdcm00014mohsjolsvoq',
    pro_annual: 'cmpulbdci00004moh85qpsd6k:cmpulbdcn00024mohsjolsvoq',
    starter_monthly: 'cmpuql04c000p4mn3iumpcaxf:cmpuql04f000q4mn3w0iz64m1',
  },
} as const;
```

Úsalo directamente al crear sesiones de checkout (modo compatibilidad `lineItems`):

```ts theme={"dark"}
import { catalog } from '@/onflay-catalog';
import { Onflay } from '@onflay/node';

const onflay = new Onflay(process.env.ONFLAY_API_KEY!);

const session = await onflay.checkoutSessions.create({
  lineItems: [{ priceId: catalog.prices['pro-monthly'].id, quantity: 1 }],
  successUrl: 'https://tu-app.com/gracias',
  cancelUrl: 'https://tu-app.com/precios',
});
```

### `catalog sync` — apply + codegen en un solo paso

```bash theme={"dark"}
npx onflay catalog sync pricing.onflay.ts --out src/onflay-catalog.ts --yes
```

### `catalog mv` — renombrar claves sin recrear objetos

Si quieres renombrar un `nickname` sin que el siguiente apply lo trate como “borrado + creado”, usa:

```bash theme={"dark"}
npx onflay catalog mv pricing.onflay.ts pro_plan pro_plus_plan
```

***

## Webhooks locales

Levanta un túnel para recibir eventos de Onflay en tu servidor local durante el desarrollo:

```bash theme={"dark"}
npx onflay listen --forward-to http://localhost:3000/api/webhooks/onflay
```

La CLI imprime un secret temporal que expira al cerrar el proceso:

```
  connected to https://sandbox-api.onflay.com (sandbox)

  ready
    Webhook secret: whsec_dev_...
    Forwarding events ▸ http://localhost:3000/api/webhooks/onflay
    Press Ctrl+C to stop.
```

La CLI también intenta guardarlo automáticamente en `.env.local` en el directorio actual.

Si prefieres configurarlo manualmente, expórtalo para que tu handler lo use:

```bash theme={"dark"}
export ONFLAY_WEBHOOK_SECRET=whsec_dev_...
```

O agrégalo a tu `.env.local` si tu framework lo carga automáticamente.

<Note>
  En producción usa el secret permanente del dashboard, no el `whsec_dev_...` que genera `listen`.
</Note>

***

## Disparar eventos de prueba

Simula un evento sin necesitar un pago real:

```bash theme={"dark"}
npx onflay trigger payment.completed
```

Eventos disponibles para `trigger`:

| Evento                  | Descripción                             |
| ----------------------- | --------------------------------------- |
| `payment.completed`     | Pago exitoso procesado                  |
| `payment.refunded`      | Reembolso emitido                       |
| `payout.scheduled`      | Payout en cola                          |
| `payout.completed`      | Payout completado                       |
| `payout.failed`         | Payout fallido                          |
| `dispute.opened`        | Disputa abierta                         |
| `dispute.resolved`      | Disputa resuelta                        |
| `subscription.created`  | Nueva suscripción (primer pago exitoso) |
| `subscription.renewed`  | Renovación de suscripción               |
| `subscription.canceled` | Suscripción cancelada                   |
| `subscription.expired`  | Suscripción expirada                    |
| `subscription.dunning`  | Reintento de cobro                      |
| `invoice.created`       | Invoice creada                          |
| `invoice.finalized`     | Invoice finalizada                      |
| `invoice.paid`          | Invoice pagada                          |

<Warning>
  `trigger` solo funciona en sandbox. No lo uses con `sk_live_`.
</Warning>

***

## Gestión de eventos

Consulta y reenvía eventos pasados del entorno:

```bash theme={"dark"}
# Listar eventos recientes
npx onflay events list

# Ver detalle de un evento
npx onflay events show evt_...

# Reenviar un evento al webhook configurado
npx onflay events resend evt_...
```

`events resend` es útil para reprobar un handler sin crear una transacción nueva.

***

## Scripts recomendados en `package.json`

```json theme={"dark"}
{
  "scripts": {
    "catalog:plan": "onflay catalog plan pricing.onflay.ts",
    "catalog:apply": "onflay catalog apply pricing.onflay.ts",
    "catalog:sync": "onflay catalog sync pricing.onflay.ts --out src/onflay-catalog.ts --yes",
    "webhooks:dev": "onflay listen --forward-to http://localhost:3000/api/webhooks/onflay"
  }
}
```

Con esto puedes correr `pnpm catalog:plan` antes de cada deploy para verificar que el catálogo esté sincronizado.
