Documentation menu

command line

The API, from a shell

One command per operation, generated from the same specification the API is built on. 50 of them, and none of them can go stale.

Install#

shell
npm install -g @writavo/cli

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

shell
npx @writavo/cli ping

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.

shell
export WRITAVO_API_KEY=wv_sk_...
writavo ping
  • --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 50 of them without being told.

shell
writavo                        # the groups, and the global flags
writavo articles               # the commands in one group
writavo create-article --help  # what it does, and every flag it takes
writavo commands               # tab separated, for completion scripts and agents

Using it#

shell
# Read
writavo list-articles --status published --limit 10 --json
writavo get-article 0f2a8c31-0000-4000-8000-00000000abcd

# Write. Nothing becomes public by accident: publishing is a separate call.
writavo create-article --title "How autonomous SEO content works" --content "# Draft"
writavo publish-article <id>

# Look before you leap
writavo create-pipeline-run --dry-run

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.

shell
writavo list-articles --json > articles.json

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 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 exposes the same API as tools for an AI assistant.
  • The OpenAPI specification is what both are generated from, so you can generate your own client the same way.
  • llms.txt says when an agent should reach for Writavo and how to call it.