# The API, from a shell

Drive the whole API from a shell or a script.

## Install

Or run it without installing anything, which is usually the right answer in CI and in a one-off script:

Node 20 or newer.

## Authenticate

Create a key in the dashboard under Settings, then API keys, and put it in the environment. Keys are not created through this API: making the first one needs a signed in person rather than a credential you do not have yet.

- `--key` overrides the environment variable for one invocation.
- The key is sent as `Authorization: Bearer` to the published base URL and nowhere else. `WRITAVO_API_BASE_URL` is honoured only for a loopback address, so nothing that can write a shell profile can redirect your key to another host.
- `--dry-run` prints the request the command would send, with the key redacted, and sends nothing.

## Finding a command

Every command is named after its operation id in the specification. That makes the name unambiguous, and it means anything that has read the specification already knows all of them without being told.

## Using it

The response body goes to standard output and everything else goes to standard error, so a redirect produces clean JSON rather than JSON with a rate limit line stuck to the end of it.

## Exit codes

- `0` succeeded.
- `1` the API returned an error, or the request could not be sent.
- `2` usage error: unknown command, missing flag, bad value, or no key. Nothing was sent.

The distinction between 1 and 2 is the one a script needs: a 2 will never succeed on retry, and a 1 might.

> On an API error the CLI prints the code, the message, the per field messages where there are any, what to do about it, and the request id to quote to support. That remedy text comes from the same source as the [errors page](/docs/errors) and the MCP server, so the three can never give different advice.

## What it will not let you do by accident

- `Idempotency-Key` is generated per invocation and never asked of you. A key reused with a different body is a `409`, which is the opposite of the retry safety the header exists to provide.
- A required flag that is missing is refused before anything is sent, so a billable command cannot cost you a request to be told what the flag table already knew.
- Commands that spend credits, publish to your live site, or delete permanently say so in `--help`, in those words.
- A key is never printed. `--dry-run` shows that one would be sent, and shows `Bearer <redacted>` where it would go.

## See also

- [The MCP server](/docs/mcp) exposes the same API as tools for an AI assistant.
- [The OpenAPI specification](https://writavo.com/openapi.json) is what both are generated from, so you can generate your own client the same way.
- [llms.txt](https://writavo.com/llms.txt) says when an agent should reach for Writavo and how to call it.
