# CLI (/developers/cli)

`@fianto/cli` is the `fianto` command for development. It shows which application your keys belong
to, reads your events, forwards them to a route on your machine, sends signed sample events, and
signs a payload by hand. It holds your app secret: run it on your own machine or a trusted CI job.

## Install [#install]

Run it without installing, or add it to your project:

```bash
npx @fianto/cli whoami
```

#### pnpm

```bash
pnpm add -D @fianto/cli
pnpm exec fianto whoami
```

#### npm

```bash
npm install --save-dev @fianto/cli
npx fianto whoami
```

#### yarn

```bash
yarn add --dev @fianto/cli
yarn fianto whoami
```

#### bun

```bash
bun add --dev @fianto/cli
bunx fianto whoami
```

It needs Node.js 20.3 or later.

## Credentials [#credentials]

The CLI reads your shell's environment, not a `.env` file: export the variables, or pass flags.
Flags win over the environment.

| Flag                    | Environment variable    | Needed by                                       |
| ----------------------- | ----------------------- | ----------------------------------------------- |
| `--app-id <id>`         | `FIANTO_APP_ID`         | `whoami`, `events …`, `trigger test.event`      |
| `--app-secret <secret>` | `FIANTO_APP_SECRET`     | the same                                        |
| `--base-url <url>`      | `FIANTO_BASE_URL`       | optional; default `https://api.fianto.xyz`      |
| `--secret <whsec_…>`    | `FIANTO_WEBHOOK_SECRET` | `events tail`, `trigger --forward-to`, `sign`   |
| `--secret-file <path>`  | —                       | the same; the file is read as UTF-8 and trimmed |

The webhook secret comes from `--secret`, then `--secret-file`, then `FIANTO_WEBHOOK_SECRET`.
`trigger --forward-to` and `sign` need only the webhook secret and make no API call. A missing
credential is a usage error (exit 2) that names the flag and the variable to set.

## Commands [#commands]

### `fianto whoami` [#fianto-whoami]

Calls `GET /v1/application` and prints the application's name and app id, the merchant's name, and
the webhook's status and URL, or `not configured`.

```bash
npx @fianto/cli whoami
```

### `fianto events list [--type <type>] [--limit <n>]` [#fianto-events-list---type-type---limit-n]

Prints one page of your events, newest first, one `<id>  <timestamp>  <type>` line each. `--limit`
is 1 to 100, default 20.

```bash
npx @fianto/cli events list --type order.paid --limit 5
```

### `fianto events get <evt_id>` [#fianto-events-get-evt_id]

Prints one event as indented JSON, as `GET /v1/events/{id}` returns it.

### `fianto events tail --forward-to <url>` [#fianto-events-tail---forward-to-url]

Polls your events and posts each new one to `--forward-to`, re-signed with your webhook secret the
way Fianto signs a delivery. The body is the delivery envelope (`id`, `type`, `timestamp`, `data`).
It runs until you press Ctrl-C.

```bash
npx @fianto/cli events tail \
  --forward-to http://localhost:3000/api/webhooks/fianto \
  --since 1h \
  --type order.paid
```

| Flag                        | Default                 | What it does                                                            |
| --------------------------- | ----------------------- | ----------------------------------------------------------------------- |
| `--forward-to <url>`        | required                | Any `http://` or `https://` URL.                                        |
| `--secret`, `--secret-file` | `FIANTO_WEBHOOK_SECRET` | The secret to sign with. Use the one your route verifies with.          |
| `--since <duration>`        | `5m`                    | Forward only events newer than this: a number and `s`, `m`, `h` or `d`. |
| `--type <type>`             | all types               | Forward one event type only.                                            |
| `--interval <ms>`           | `2000`                  | Time between polls, at least `500`.                                     |

Each poll reads up to 100 events per page and follows the cursor until it has caught up. Each event
is forwarded once per run, oldest first, with no retry. It prints `→ <status> <type> <id> <ms>ms` per
forward, `✗ <type> <id> <message>` when your route could not be reached, and `✗ poll failed: …` when
a poll fails, then keeps polling. The first Ctrl-C lets the forward in flight finish and exits 130;
a second one exits at once.

This is a development aid, not delivery: real deliveries go to your verified webhook URL, with
retries.

### `fianto trigger <type>` [#fianto-trigger-type]

With `--forward-to`, signs a realistic local sample of any event type and posts it to that URL. No
API call is made. The sample's ids are clearly fake, such as `sample_order_1001`.

```bash
npx @fianto/cli trigger subscription.created \
  --forward-to http://localhost:3000/api/webhooks/fianto \
  --secret "$FIANTO_WEBHOOK_SECRET"
```

| Flag                        | What it does                                                                                  |
| --------------------------- | --------------------------------------------------------------------------------------------- |
| `--forward-to <url>`        | Where to post the sample. Only `localhost`, `127.0.0.0/8` or `[::1]` unless `--allow-remote`. |
| `--allow-remote`            | Allow a URL that is not local.                                                                |
| `--secret`, `--secret-file` | The secret to sign with. Default `FIANTO_WEBHOOK_SECRET`, with a warning on stderr.           |

It prints `→ <status> <type> (local sample)`. It does not follow redirects, and a status that is not
2xx exits 1. An unknown type exits 2 and lists the known ones.

Without `--forward-to`, only `test.event` works: Fianto sends a real, signed `test.event` to your
application's verified webhook URL, and the CLI prints `Sent test.event <evt_id> to your registered
endpoint`. This needs your app id and secret, and shares the limit of 10 test events per hour per
application with the dashboard's test button. Any other type without `--forward-to` exits 2: Fianto
never sends business events on request.

### `fianto sign --payload <file>` [#fianto-sign---payload-file]

Signs the exact bytes of a JSON file as Fianto would, then prints the body and a ready `curl`
command, with `$URL` left for you to set. Every value in the `curl` line is shell-quoted.

```bash
npx @fianto/cli sign --payload event.json --secret "$FIANTO_WEBHOOK_SECRET"
```

| Flag                        | Default                                      |
| --------------------------- | -------------------------------------------- |
| `--secret`, `--secret-file` | `FIANTO_WEBHOOK_SECRET`                      |
| `--id <id>`                 | the payload's own `id`, else a new `evt_` id |
| `--timestamp <unix>`        | now, in Unix seconds                         |

### `fianto help`, `fianto --version` [#fianto-help-fianto---version]

`help`, `--help`, or no command at all prints the usage and exits 0. `--version` or `-v` prints the
installed version.

## Exit codes [#exit-codes]

| Code  | Meaning                                                                                                       |
| ----- | ------------------------------------------------------------------------------------------------------------- |
| `0`   | Success                                                                                                       |
| `1`   | A handled error. An API error prints `code: message (request req_…)` on stderr.                               |
| `2`   | A usage error: unknown command or flag, or a missing flag or variable. The reason and the usage go to stderr. |
| `130` | `events tail` stopped with Ctrl-C                                                                             |

## See also [#see-also]

- [Testing](/developers/testing): Signed samples, test.event and forwarding real events.

- [Verify webhooks](/developers/webhooks/verify): The route the CLI posts to.

- [SDKs](/developers/sdks/overview): The packages the CLI is built on.