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

# Better Auth

> Plugin de Better Auth para cobros y suscripciones usando Commet

[Better Auth](https://better-auth.com) es una librería de autenticación moderna para TypeScript. Este plugin integra Commet directamente en tu configuración de better-auth.

## Features

* Creación automática del cliente al hacer signup
* Portal del cliente para que tus clientes gestionen sus cobros
* Gestión de suscripciones (get, cancel)
* Control de acceso a features (boolean, metered, seats)
* Registro de uso para cobros metered
* Gestión de licencias para precios por usuario
* Manejo opcional de webhooks con verificación de firma

## Instalación

<Tabs>
  <Tab title="pnpm">
    ```bash theme={null}
    pnpm add better-auth @commet/better-auth @commet/node
    ```
  </Tab>

  <Tab title="npm">
    ```bash theme={null}
    npm install better-auth @commet/better-auth @commet/node
    ```
  </Tab>

  <Tab title="yarn">
    ```bash theme={null}
    yarn add better-auth @commet/better-auth @commet/node
    ```
  </Tab>

  <Tab title="bun">
    ```bash theme={null}
    bun add better-auth @commet/better-auth @commet/node
    ```
  </Tab>
</Tabs>

## Preparación

Obtén tu API key desde el dashboard de Commet en **Settings → API Keys**. Usa una key de una organización sandbox mientras integras; cambia a una key de organización live cuando pases a producción.

```bash title=".env" theme={null}
COMMET_API_KEY=ck_...
```

## Configuración del servidor

```typescript title="auth.ts" theme={null}
import { betterAuth } from "better-auth";
import {
  commet,
  portal,
  subscriptions,
  features,
  usage,
  seats,
} from "@commet/better-auth";
import { Commet } from "@commet/node";

const commetClient = new Commet({
  apiKey: process.env.COMMET_API_KEY!,
});

export const auth = betterAuth({
  // ... tu config
  plugins: [
    commet({
      client: commetClient,
      createCustomerOnSignUp: true,
      use: [
        portal(),
        subscriptions(),
        features(),
        usage(),
        seats(),
      ],
    }),
  ],
});
```

## Configuración del cliente

```typescript title="auth-client.ts" theme={null}
import { createAuthClient } from "better-auth/react";
import { commetClient } from "@commet/better-auth";

export const authClient = createAuthClient({
  plugins: [commetClient()],
});
```

## Opciones de configuración

```typescript theme={null}
commet({
  client: commetClient,                    // Requerido: instancia del SDK de Commet
  createCustomerOnSignUp: true,            // Crea automáticamente el cliente al hacer signup
  getCustomerCreateParams: ({ user }) => ({
    fullName: user.name,
    metadata: { source: "web" },
  }),
  use: [/* plugins */],
})
```

<Note>
  Cuando `createCustomerOnSignUp` está habilitado, se crea un cliente en Commet automáticamente usando el ID del usuario como `customerId`. No requiere mapeo de base de datos.
</Note>

## Plugin Portal

Redirige a los usuarios al portal del cliente de Commet para que gestionen sus cobros.

```typescript title="Servidor" theme={null}
import { commet, portal } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [
    portal({ returnUrl: "/dashboard" }),
  ],
})
```

```typescript title="Cliente" theme={null}
// Redirige al portal del cliente de Commet
await authClient.customer.portal();
```

## Plugin Subscriptions

Gestiona las suscripciones de los clientes.

```typescript title="Servidor" theme={null}
import { commet, subscriptions } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [subscriptions()],
})
```

```typescript title="Cliente" theme={null}
// Obtener suscripción actual
const { data: subscription } = await authClient.subscription.get();

// Cancelar suscripción
await authClient.subscription.cancel({
  reason: "Muy caro",
  immediate: false, // Cancela al cierre del período
});
```

## Plugin Features

Verifica el acceso a features para el usuario autenticado.

```typescript title="Servidor" theme={null}
import { commet, features } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [features()],
})
```

```typescript title="Cliente" theme={null}
// Listar todas las features
const { data: featuresList } = await authClient.features.list();

// Obtener una feature específica
const { data: feature } = await authClient.features.get("api_calls");

// Verificar si la feature está habilitada (boolean)
const { data: check } = await authClient.features.check("sso");

// Verificar si el usuario puede consumir una unidad más (metered)
const { data: canUse } = await authClient.features.canUse("api_calls");
// Retorna: { allowed: boolean, willBeCharged: boolean }
```

## Plugin Usage

Registra eventos de uso para cobros metered.

```typescript title="Servidor" theme={null}
import { commet, usage } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [usage()],
})
```

```typescript title="Cliente" theme={null}
await authClient.usage.track({
  feature: "api_calls",
  value: 1,
  idempotencyKey: `evt_${Date.now()}`
});
```

<Note>
  El usuario autenticado se asocia automáticamente con el evento.
</Note>

## Plugin Seats

Gestiona licencias por usuario.

```typescript title="Servidor" theme={null}
import { commet, seats } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [seats()],
})
```

```typescript title="Cliente" theme={null}
// Listar todos los balances de licencias
const { data: seatBalances } = await authClient.seats.list();

// Agregar licencias
await authClient.seats.add({ featureCode: "member", count: 5 });

// Quitar licencias
await authClient.seats.remove({ featureCode: "member", count: 2 });

// Definir cantidad exacta
await authClient.seats.set({ featureCode: "admin", count: 3 });

// Definir todos los tipos de licencia a la vez
await authClient.seats.setAll({ admin: 2, member: 10, viewer: 50 });
```

## Plugin Webhooks

Maneja los webhooks de Commet. Es opcional, ya que siempre puedes consultar el estado directamente.

```typescript title="Servidor" theme={null}
import { commet, webhooks } from "@commet/better-auth";

commet({
  client: commetClient,
  use: [
    webhooks({
      secret: process.env.COMMET_WEBHOOK_SECRET,
      onPayload: (payload) => {
        // Handler genérico
      },
      onSubscriptionCreated: (payload) => {},
      onSubscriptionActivated: (payload) => {},
      onSubscriptionCanceled: (payload) => {},
      onSubscriptionUpdated: (payload) => {},
    }),
  ],
})
```

Configura el endpoint del webhook en tu dashboard de Commet: `/api/auth/commet/webhooks`

## Ejemplo completo

<Steps>
  <Step title="Setup del servidor">
    ```typescript title="auth.ts" theme={null}
    import { betterAuth } from "better-auth";
    import { drizzleAdapter } from "better-auth/adapters/drizzle";
    import {
      commet as commetPlugin,
      portal,
      subscriptions,
      features,
      usage,
      seats,
    } from "@commet/better-auth";
    import { Commet } from "@commet/node";
    import { db } from "./db";
    import * as schema from "./schema";

    const commetClient = new Commet({
      apiKey: process.env.COMMET_API_KEY!,
    });

    export const auth = betterAuth({
      database: drizzleAdapter(db, { provider: "pg", schema }),
      emailAndPassword: { enabled: true },
      plugins: [
        commetPlugin({
          client: commetClient,
          createCustomerOnSignUp: true,
          getCustomerCreateParams: ({ user }) => ({
            fullName: user.name,
          }),
          use: [
            portal({ returnUrl: "/dashboard" }),
            subscriptions(),
            features(),
            usage(),
            seats(),
          ],
        }),
      ],
    });
    ```
  </Step>

  <Step title="Setup del cliente">
    ```typescript title="auth-client.ts" theme={null}
    import { createAuthClient } from "better-auth/react";
    import { commetClient } from "@commet/better-auth";

    export const authClient = createAuthClient({
      baseURL: process.env.NEXT_PUBLIC_BETTER_AUTH_URL,
      plugins: [commetClient()],
    });

    export const { signIn, signUp, signOut, useSession } = authClient;
    ```
  </Step>

  <Step title="Uso en componentes">
    ```tsx title="dashboard.tsx" theme={null}
    "use client";

    import { authClient } from "@/lib/auth-client";

    export function BillingSection() {
      const handlePortal = async () => {
        await authClient.customer.portal();
      };

      const checkFeature = async () => {
        const { data } = await authClient.features.canUse("api_calls");
        if (data?.allowed) {
          // Continúa con la acción
          await authClient.usage.track({ feature: "api_calls" });
        }
      };

      return (
        <div>
          <button onClick={handlePortal}>Gestionar cobros</button>
          <button onClick={checkFeature}>Usar feature</button>
        </div>
      );
    }
    ```
  </Step>
</Steps>

## Relacionado

* [Suscripciones](/docs/es/manage-subscriptions)
* [Eventos de uso](/docs/es/track-usage)
* [Gestión de licencias](/docs/es/seat-management)
* [Portal del cliente](/docs/es/customer-portal)


## Related topics

- [Introducción](/docs/es/index.md)
- [Skills de Commet](/docs/es/commet-skill.md)
- [AI Onboarding](/docs/es/ai-onboarding.md)
- [Servidor MCP](/docs/es/mcp-server.md)
- [CLI](/docs/es/cli.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.