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

> ## Agent Instructions
> Money is always a decimal string at the currency's precision (for example "29.00"), paired with an ISO 4217 currency field. Never use minor units.
> Build against the sandbox first: base URL https://sandbox-api.bachs.io with sk_sandbox_ keys. Production is https://api.bachs.io with sk_live_ keys; going live is a key swap.
> Treat webhooks (for example collection.succeeded) as the source of truth for fulfilment, never client-side events or redirects.
> Subscriptions are created by completing a checkout for a recurring product. There is no direct create-subscription endpoint.
> IDs carry resource prefixes (cust_, prod_, sub_, chk_, inv_, ref_) and timestamps are ISO 8601 UTC.

# Command Reference

> Every Bachs CLI command, flag, and argument.

Run `bachs` with no arguments to see the command list, or `bachs <command> --help` for the flags on any one of them.

Every command accepts `--api-key` to override your stored credentials for that invocation. It is left out of the tables below to keep them readable.

***

## login

Pairs this machine with your account through the browser. See [Log in](/cli/overview#log-in) for the full flow.

```bash Connect this machine theme={"dark"}
bachs login
```

| Flag                   | What it does                                                   |
| ---------------------- | -------------------------------------------------------------- |
| `--sandbox`            | Pair against the sandbox rather than production.               |
| `--device-name <name>` | Label shown on the approval screen. Defaults to your hostname. |
| `--api-key <key>`      | Log in with a key instead of the browser.                      |

<Warning>
  `--api-key` puts a credential in your shell history, and on Linux it is readable by other local users through the process list. Prefer the browser flow, or `BACHS_API_KEY` where no browser is available.
</Warning>

***

## whoami

Shows which environment your stored credentials target. Useful before running anything that changes data.

```bash Check the active environment theme={"dark"}
bachs whoami
```

```text Response theme={"dark"}
Environment: sandbox
API base:    https://sandbox-api.bachs.io
Key:         sk_sandbox_a1b2c3d4…
```

***

## listen

Forwards live events to a port on your machine. The connection is opened outbound, so there is no public URL and no tunnel. See [Test webhooks locally](/developer-portal/local-testing) for the full guide.

```bash Forward every event theme={"dark"}
bachs listen --forward-to localhost:3000/webhooks
```

| Flag                   | What it does                                                      |
| ---------------------- | ----------------------------------------------------------------- |
| `--forward-to`, `-f`   | Local target, for example `localhost:3000/webhooks`. Required.    |
| `--events`, `-e`       | Comma-separated event types to forward.                           |
| `--all`                | Forward every event type. The default when `--events` is omitted. |
| `--device-name <name>` | Label for this session in the dashboard.                          |

The target accepts the shapes people actually type. `localhost:3000/webhooks`, `:3000/webhooks`, and a full URL all work.

```bash Forward two event types theme={"dark"}
bachs listen --forward-to localhost:3000/webhooks --events collection.succeeded,refund.paid
```

Pass either `--events` or `--all`, not both. The CLI refuses rather than silently preferring one, so a filter you passed never does nothing without telling you.

***

## trigger

Emits a sample event so you can exercise a handler without making a real payment. The event goes through the ordinary delivery path, so it fans out to whatever is subscribed, records delivery attempts, and is signed like any other event.

```bash Emit a sample event theme={"dark"}
bachs trigger collection.succeeded
```

<Warning>
  Sandbox only. A fake `collection.succeeded` in production could have you fulfil an order nobody paid for, so the CLI refuses rather than warning. In production, use [`bachs events replay`](#events) to redeliver a real past event.
</Warning>

The event type is a positional argument. These are supported:

| Group       | Event types                                      |
| ----------- | ------------------------------------------------ |
| Collections | `collection.succeeded`, `collection.failed`      |
| Payouts     | `payout.created`, `payout.paid`, `payout.failed` |
| Refunds     | `refund.created`, `refund.paid`, `refund.failed` |
| Checkout    | `checkout.completed`, `checkout.expired`         |
| Customers   | `customer.created`, `customer.updated`           |

***

## events

Lists past events and redelivers them. Replay is a plain API call, so it needs no forwarding session and works against your registered destinations in production too.

### events list

```bash Recent events and how they went theme={"dark"}
bachs events list
```

| Flag                  | What it does                                              |
| --------------------- | --------------------------------------------------------- |
| `--limit <n>`         | How many events to show. Max 100, default 20.             |
| `--type <event_type>` | Only this event type, for example `collection.succeeded`. |
| `--failed`            | Only events whose last delivery failed.                   |
| `--undelivered`       | Only events nothing was listening for.                    |

`--undelivered` is the one to reach for when an event seems to have vanished. It shows events that matched no destination at all, which usually means the endpoint filter does not include that type.

### events replay

```bash Redeliver one event theme={"dark"}
bachs events replay evt_3ab4e0d5d27445cf8a52ab3d8cb8f0b1
```

### events replay-failed

Redelivers events whose delivery failed, which saves replaying them one at a time after an outage on your side.

```bash See what would be replayed theme={"dark"}
bachs events replay-failed --dry-run
```

| Flag                  | What it does                          |
| --------------------- | ------------------------------------- |
| `--dry-run`           | List what would be replayed and stop. |
| `--limit <n>`         | Most events to replay. Default 20.    |
| `--type <event_type>` | Only this event type.                 |

<Tip>
  Run `--dry-run` first. It costs nothing and tells you exactly what the real run will touch.
</Tip>

***

## endpoints

Manages the webhook destinations Bachs delivers to. These are the same destinations shown in the Developer Portal.

```bash Your webhook destinations theme={"dark"}
bachs endpoints list
```

```bash Register a destination theme={"dark"}
bachs endpoints create --url https://example.com/webhooks --events collection.succeeded,refund.paid
```

| Flag             | What it does                           |
| ---------------- | -------------------------------------- |
| `--url <url>`    | HTTPS URL to deliver to. Required.     |
| `--events <a,b>` | Comma-separated event types. Required. |
| `--name <name>`  | Label for this destination.            |

```bash Remove a destination theme={"dark"}
bachs endpoints delete whe_8f2e40f6bdf84c1980e1e1f6407f3f8a
```

***

## Resource commands

Every API operation is also a command, grouped by resource. Run a resource name on its own to see its operations:

```bash See what you can do with customers theme={"dark"}
bachs customers
```

```text Operations theme={"dark"}
Usage: bachs customers <operation> [flags]

Operations:
  create                Create a customer
  get    <customer_id>  Retrieve a customer
  list                  List customers
  update <customer_id>  Update a customer
```

The available resources:

<Columns cols={2}>
  <div>
    `accounts`<br />
    `balances`<br />
    `checkout-sessions`<br />
    `connected-accounts`<br />
    `conversions`<br />
    `customer-sessions`<br />
    `customers`<br />
    `disputes`<br />
    `media`<br />
    `misc`
  </div>

  <div>
    `payments`<br />
    `payouts`<br />
    `persons`<br />
    `platform-fees`<br />
    `product-groups`<br />
    `products`<br />
    `reference`<br />
    `refunds`<br />
    `subscriptions`<br />
    `transfers`<br />
    `webhooks`
  </div>
</Columns>

Operations follow the API. Anything the operation takes in its path is a positional argument, and everything else is a flag:

```bash Retrieve one customer theme={"dark"}
bachs customers get cust_8f2e40f6bdf84c1980e1e1f6407f3f8a
```

```bash List with a filter theme={"dark"}
bachs payments list --limit 10
```

You do not have to know whether a value belongs in the query string or the request body. A flag the operation lists as a query parameter is sent as one, and anything else becomes a body field:

```bash Create a customer theme={"dark"}
bachs customers create --email ada@example.com --name "Ada Lovelace"
```

Values are converted to the JSON type the API expects. `true` and `false` become booleans, whole numbers become integers, and anything containing a decimal point is left as a string, so an amount like `29.00` stays exact rather than being rounded through a float.

Responses print as formatted JSON, which pipes cleanly into `jq`:

```bash Pull one field out of the response theme={"dark"}
bachs customers list --limit 5 | jq '.data[].email'
```

<Tip>
  Resource commands read and write real data in whichever environment you are paired with. Run `bachs whoami` first if you are not sure, and prefer `bachs login --sandbox` while you are exploring.
</Tip>

***

## Exit codes

| Code | Meaning                                                                    |
| ---- | -------------------------------------------------------------------------- |
| `0`  | The command succeeded.                                                     |
| `1`  | The command ran and failed, for example the API returned an error.         |
| `2`  | The command was used incorrectly, for example a required flag was missing. |

Scripts should check for a non-zero exit rather than parsing output, which is formatted for people and may change.
