# Arguments, output and exit codes

> How to name zones and records, pass key=value settings and JSON, read the output with --json, and what each exit code means.

## Command syntax

```text
openwaf-cloud ctl <family> <command> [arguments] [options]
```

Options can go anywhere among the arguments, with one or two dashes (`--json` or `-json`). After `--`, everything is an argument. `-h` or `--help` after any command prints its usage and options; `openwaf-cloud ctl help` prints the full list.

## Naming things

| Argument | Accepts |
|---|---|
| `<zone>` | The domain (`example.com`) or the zone id. A deleted zone's history needs the id. |
| `<record>` | The record id, or its name: full (`www.example.com`), relative (`www`) or `@` for the apex, optionally with the type (`www/A`) when the name has several records. |
| `<certificate>` | The certificate id or its hostname. |
| `<client>` | The client id or its name (case-insensitive). |

## `key=value` arguments

Commands that send settings or fields (`zones set`, `records add`, `rules add`, …) take `key=value` arguments:

| Form | Sends | Example |
|---|---|---|
| `key=value` | Integers and `true`/`false` as such; anything else as text. | `ttl=300`, `proxied=true`, `content=203.0.113.10` |
| `key.nested=value` | A nested object. | `hsts.max_age=300` → `{"hsts": {"max_age": 300}}` |
| `key:=<json>` | Literal JSON: lists, objects, `null`, or text that would otherwise be typed. | `tags:='["web","prod"]'`, `note:='"42"'` |

Quote values that contain spaces or shell characters. A key given twice, or a nested key that clashes with a plain one, is a usage error.

## Output

Reads print aligned tables in Spanish. Add `--json` to any read (and to `cache purge` and `origin-certs`) to print the API's answer as is, ready for `jq`:

```sh
openwaf-cloud ctl zones list --json | jq -r '.items[] | [.name, .status, .config_version] | @tsv'
```

Errors go to standard error as `error: <message>`. If a message could contain your token, the token is replaced with `[token]`.

## Exit codes

| Code | Meaning |
|---|---|
| `0` | Success, including a change that turned out to change nothing and a simulation with `--dry-run`. |
| `1` | Error: the API refused the request (invalid data, permission denied, not found…), the API could not be reached, a confirmation was declined, or there was no terminal to confirm and no `--yes`. |
| `2` | Usage: unknown command, wrong number of arguments, invalid option or value, missing `--reason`. Nothing was sent. |
| `3` | Version conflict: the zone changed after the simulation (HTTP 412) and nothing was applied; or, during `--wait`, the zone changed again. |
| `4` | The change was applied, but some edge node had not confirmed it when `--wait` ran out of time. |

## Common error messages

| Message | Meaning |
|---|---|
| `falta el token: define OPENWAF_TOKEN o OPENWAF_TOKEN_FILE` | No token configured. |
| `no autorizado (401)` | The token is invalid, expired or revoked. |
| `permiso denegado (403)` | The token's role or scope does not allow this command. |
| `no encontrado (404)` | The object does not exist or is outside your organisation or token scope. |
| `conflicto de versión (412)` | The zone changed after the simulation; nothing was applied. |
| `datos no válidos (422)` | The API rejected a value; the message names the field. |
| `no se puede hablar con la API en …` | The API address is wrong or unreachable; check `OPENWAF_API_URL`. |
| `sin terminal para confirmar` | Add `--yes`, or `--dry-run` to only simulate. |
