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

# Manage via CLI

> Create, list, test, rotate, and delete webhook subscriptions using the Keebai CLI.

The `keebai` CLI is the fastest way to manage outbound webhooks from your terminal. Under the hood it uses the same `/v1/webhooks` endpoints as the [API](/dev/webhooks/manage), with UX tuned for interactive workflows.

## Installation

<CodeGroup>
  ```bash npm theme={null}
  npm install -g @keebai/cli
  ```

  ```bash one-liner theme={null}
  curl -fsSL https://keebai.ai/install.sh | bash
  ```
</CodeGroup>

After installing:

```bash theme={null}
keebai --version
keebai login           # device-flow authentication against the portal
keebai whoami          # confirms user/company/scopes
```

## Quickstart: 5 minutes to your first event

<Steps>
  <Step title="Log in">
    ```bash theme={null}
    keebai login
    ```

    Opens the browser, prompts you to approve the device in the portal, and returns to the CLI with a PAT stored in `~/.keebai/credentials.json` (chmod 600).
  </Step>

  <Step title="Create a subscription">
    ```bash theme={null}
    keebai webhooks new \
      --url https://hooks.example.com/keebai \
      --event whatsapp.message.received \
      --event whatsapp.channel.connected \
      --name "Production CRM"
    ```

    Output:

    ```text theme={null}
    ✓ Webhook created.
    Created webhook wh_01HXYZ...
    name:   Production CRM
    url:    https://hooks.example.com/keebai
    events: whatsapp.message.received, whatsapp.channel.connected
    active: true

    ⚠ SECRET (shown once — copy it now, you cannot retrieve it later):
      whsec_8f2c5b3a9d4e7c1f...
    ```

    <Warning>
      Copy the `whsec_xxx` now. It can't be retrieved later. If you lose it, you have to rotate it (which invalidates the old one).
    </Warning>
  </Step>

  <Step title="Validate with a synthetic event">
    ```bash theme={null}
    keebai webhooks test wh_01HXYZ... --event whatsapp.message.received
    ```

    We send a synthetic envelope (with `data._test: true`) to your URL. If your endpoint verifies the signature and returns 2xx, you'll see:

    ```bash theme={null}
    keebai webhooks deliveries wh_01HXYZ...
    # status: success, status_code: 200, duration_ms: 142
    ```
  </Step>

  <Step title="Validate with real traffic">
    Send a WhatsApp message to your channel's number. Your endpoint should receive a `whatsapp.message.received` with a shape compatible with the [Meta Cloud API](https://developers.facebook.com/docs/whatsapp/cloud-api/webhooks).
  </Step>
</Steps>

## Available commands

### `keebai webhooks new`

```bash theme={null}
keebai webhooks new \
  --url <https://...> \
  --event <event_type> [--event <event_type>...] \
  --name <label> \
  [--header "Name:Value"] [--header ...] \
  [--inactive]
```

| Flag         | Required        | Description                                                                             |
| ------------ | --------------- | --------------------------------------------------------------------------------------- |
| `--url`      | yes             | HTTPS endpoint on your side.                                                            |
| `--event`    | yes, repeatable | At least one. See the [catalog](/dev/webhooks/events).                                  |
| `--name`     | yes             | Human-readable label to identify the subscription in listings.                          |
| `--header`   | no, repeatable  | Extra headers (`Name:Value` format). Useful for your own routing/auth.                  |
| `--inactive` | no              | Creates the subscription with `is_active: false`. Handy if you want to enable it later. |

**Prints the secret only once. Save it immediately.**

### `keebai webhooks list`

```bash theme={null}
keebai webhooks list
keebai webhooks list --output json | jq
```

### `keebai webhooks test <id>`

Dispatches a synthetic event (`data._test: true`) to the configured endpoint.

```bash theme={null}
keebai webhooks test wh_01HXYZ... --event whatsapp.message.received
```

Useful for validating your pipeline without real traffic. It arrives with the same HMAC signature as a real event.

### `keebai webhooks deliveries <id>`

History of recent delivery attempts.

```bash theme={null}
keebai webhooks deliveries wh_01HXYZ... [--limit 50]
```

For each delivery, output shows: `event_id`, `event_type`, `status` (`pending` / `success` / `failed` / `dead`), `status_code`, `attempts`, `duration_ms`, `last_error`.

### `keebai webhooks rotate <id>`

Generates a new secret. **The old one is invalidated immediately.** Asks for confirmation.

```bash theme={null}
keebai webhooks rotate wh_01HXYZ...
```

The new secret is shown the same way as in `new`. For zero-downtime rotation, see the [strategy in security](/dev/webhooks/security#rotación-de-secret).

### `keebai webhooks delete <id>`

Deletes the subscription. Future events are not sent. Asks for confirmation.

```bash theme={null}
keebai webhooks delete wh_01HXYZ...
```

## Global flags

| Flag                    | Description                                                                                                 |
| ----------------------- | ----------------------------------------------------------------------------------------------------------- |
| `--api-url <url>`       | Override the API base (default `https://api.keebai.com/v1`). Useful for staging.                            |
| `--output pretty\|json` | Output format. Use `json` for piping to `jq`.                                                               |
| `--verbose`             | Logs every HTTP request. **Never prints the full secret, only the first 12 chars.**                         |
| `--no-browser`          | In `keebai login`, doesn't open the browser; prints the URL to copy/paste. Useful over SSH/CI.              |
| `--profile <name>`      | Multi-profile. Default `default`. Each profile stores separate credentials in `~/.keebai/credentials.json`. |

## CI/CD

For pipeline use, override the token via env and skip the credentials file:

```bash theme={null}
export KEEBAI_API_TOKEN=kbai_pk_xxx
keebai webhooks list
```

`KEEBAI_API_TOKEN` takes precedence over `~/.keebai/credentials.json`. The PAT must have the `webhooks:read` and/or `webhooks:manage` scopes depending on the commands you intend to run.

## See also

<CardGroup cols={2}>
  <Card title="Signature verification" icon="shield" href="/dev/webhooks/security">
    How to validate `X-Keebai-Signature` in your endpoint.
  </Card>

  <Card title="Event catalog" icon="list" href="/dev/webhooks/events">
    Full list of types and `data` shapes.
  </Card>

  <Card title="REST endpoints" icon="code" href="/dev/webhooks/manage">
    Same operations over HTTP, no CLI required.
  </Card>

  <Card title="Connect WhatsApp via CLI" icon="plug" href="/dev/endpoints/channels-whatsapp-connect">
    `keebai whatsapp connect` and the equivalent API.
  </Card>

  <Card title="Connect WhatsApp via QR" icon="qrcode" href="/dev/endpoints/channels-whatsapp-connect-qr">
    `keebai whatsapp connect --qr` — QR pairing scanned straight from the terminal.
  </Card>
</CardGroup>

## Connect WhatsApp from the CLI

There are two pairing modes:

```bash theme={null}
# Embedded Signup (Cloud API, opens browser):
keebai whatsapp connect [--coexistence] [--pipeline-id pip_…]

# QR multi-device (scan the QR in the terminal):
keebai whatsapp connect --qr [--name "WhatsApp Support"]
```

The `--qr` mode draws the code in your terminal, refreshes it automatically, and once scanned prints the `channel_id` of the new channel. SSE flow details in [POST /v1/channels/whatsapp/connect (QR mode)](/dev/endpoints/channels-whatsapp-connect-qr).

Once a channel is connected (either Cloud API or QR), send messages with the same command:

```bash theme={null}
keebai whatsapp messages send \
  --from <channel_id-or-number> \
  --to +5491155555555 \
  --text "Hello from the QR channel"
```

Internally the CLI calls `POST /v1/messages` with a `text` message, which detects the channel type (Cloud API vs QR) and routes accordingly. Templates and bulk are not supported against QR channels.
