Layerbeat

Scripting

JSON output, exit codes, waiting and safe retries for scripts, CI and agents.

Output

When stdout is not a terminal — in a pipe, a script or an agent — the CLI prints JSON: the API's own response shapes. In a terminal it prints tables; add --json to get JSON there too.

layerbeat ls --json | jq -r '.data[] | select(.status == "running") | .name'
layerbeat ls -q          # names only, one per line

Errors go to stderr, as JSON when stdout is not a terminal, and leave stdout empty.

Never prompt

--no-input makes any command fail instead of asking a question. Without a terminal the CLI never prompts anyway: layerbeat new with a missing flag is an error, not a question.

Saying yes to purchases

Buying or renewing a server or a disk spends credit, so it needs a yes. In a terminal the CLI shows the order and asks. In a script or agent, pass --yes (-y). Without it, the command exits 2 with confirmation_required and nothing is bought.

Exit codes

CodeMeaning
0Success
2Usage error (a missing or wrong flag), or a purchase without --yes and without a terminal (confirmation_required)
3Not signed in, or the key lacks the permission
4Not found
5Invalid state: the server is busy, already in that state, or the change conflicts
6Not enough credit, or the total is above your --max-price
7Rate limited: wait and try again
8--wait timed out (the operation may still finish; check it with layerbeat operation)
9Layerbeat or the network is unavailable
10Out of stock, or a quota is reached

Don't retry 2, 3, 4, 6 or 10 without changing something; back off before retrying 7 and 9.

Waiting

Changes run as operations. By default a command returns as soon as the change is accepted, with an op_... ID. Then:

layerbeat start agent-01 --wait               # wait inside the command
layerbeat wait op_... --timeout 900           # or wait later
layerbeat operation op_...                    # check without waiting

See Asynchronous operations.

Safe retries

Buying (new, renew, volume new, volume renew, topup) takes an --idempotency-key. The same key never charges twice, so a script that times out or crashes can simply run the same command again with the same key:

KEY=deploy-$(date +%Y%m%d)-agent-01
layerbeat new agent-01 --region sgp --plan SG-B224 --image "Ubuntu 24.04" \
  --ssh-key ci --max-price 5 --idempotency-key "$KEY" --no-input --yes --wait

Always pass --max-price in automation: the command refuses a total above it, whatever the price is when it runs. See Safe retries.

Any API call

layerbeat api calls any endpoint with your sign-in or key, for anything without its own command:

layerbeat api GET /v1/billing/wallet
layerbeat api POST /v1/vms/vm_.../firewall-rules -d '{"protocol":"tcp","port":"8080"}'
layerbeat api POST /v1/vms -d @order.json -H "Idempotency-Key: $KEY"

-d takes JSON, @file or - for stdin. The API reference lists every endpoint.

In CI

# GitHub Actions
- run: curl -fsSL https://layerbeat.com/install.sh | sh
- run: echo "$HOME/.local/bin" >> "$GITHUB_PATH"
- run: layerbeat template update https-proxy --server web-1 --wait
  env:
    LAYERBEAT_API_KEY: ${{ secrets.LAYERBEAT_API_KEY }}

layerbeat ssh, exec and cp also need an SSH private key that the server accepts, available to the job.