CLI basics
Bookrail is booking infrastructure: availability, holds, bookings, policies and webhooks behind one HTTP API. This CLI describes a project as code and talks to that API.
The loop
Section titled “The loop”bookrail signup # get a sk_test_ key by email, stored mode 600bookrail init --template padel # write bookrail.config.tsbookrail push --dry-run # see what would be createdbookrail push # create itbookrail diff # confirm the project matches the filebookrail doctor # check credentials, project, reachability, version, configThen you operate on it:
bookrail availability --service svc_... --from 2026-09-11T00:00:00Z --to 2026-09-12T00:00:00Zbookrail availability --service svc_... --from ... --to ... --explain # why an instant is not therebookrail holds create --service svc_... --start 2026-09-11T06:00:00Z --ttl 10mbookrail bookings create --service svc_... --start 2026-09-11T06:00:00Z --hold hold_...bookrail bookings cancel bk_... --yesbookrail webhooks create --url https://example.com/hooks/bookrail # the secret, oncebookrail webhooks listen --url https://<your tunnel> --port 4100 # watch deliveries landbookrail events list --follow # watch the logEverything is test until you type --live. A sk_live_ key used without --live is a
hard error, not a warning: no request built by this process can reach the live environment
unless you asked for it.
Where the key comes from
Section titled “Where the key comes from”bookrail signup is the whole answer: it asks for an address, sends a link there, waits for
you to open it, and stores what comes back, which is two keys, a test one and a live one.
No password, and nobody to write to. --no-store prints both once instead of writing them.
Before anything is sent it shows the Terms of Service and the Data Processing Agreement and asks
you to accept them on behalf of your business and, separately, to approve the clauses of their
Section 17; --accept-terms and --approve-clauses answer for a script.
The live key books for real, on the free plan: up to 1,000 confirmed live bookings a
month, then new live bookings are refused with 402 plan_limit_reached until the next month
or a paying plan. It is stored next to the test one and used only when you type --live.
More keys, and revoking one, are in the dashboard at
bookrail.dev/dashboard: you sign in with a link sent to
the same address. A key made there goes in with bookrail login --token sk_test_..., or
bookrail login --live --token sk_live_....
Once there is a key, this is where a command looks for it:
BOOKRAIL_SECRET_KEYin the environment, if set.~/.config/bookrail/credentials.json(or$XDG_CONFIG_HOME/bookrail/credentials.json), written bybookrail signupand bybookrail loginwith mode 600.
The key is never printed. bookrail whoami and bookrail env show it masked; whoami also
names the project the key opens, its scopes and its tenant_id.
Output
Section titled “Output”Every command takes --json and prints
{ "ok": true, "environment": "test", "data": { }, "next_steps": ["..."] }and on failure
{ "ok": false, "environment": "test", "error": { "code": "...", "message": "...", "param": "...", "doc_url": "...", "fix": "..." } }Exit codes: 0 success, 1 user or configuration error, 2 authentication, 3 network or
service, 4 conflict (the state changed under you; retrying may work).
Colour and decoration are off whenever stdout is not a terminal, and always off with --json.