The ostra CLI
ostra is the API from a terminal, for scripts and test suites: list lines, issue proxy credentials, ask for a new carrier IP, follow texts and print the next code. It uses your organization’s API key and can do nothing the key cannot.
What it needs
Node.js 22 or later, and nothing else: it has no other dependency. ostra version prints 1.0.0, and ostra help lists the commands below.
Sign in
ostra login # paste the key at the hidden prompt, or pipe it in
ostra lines # your lines, then LAX-SANDBOX-00ostra loginchecks the key with the API, then keeps it in the macOS keychain (Keychain Access shows it as “Ostra API key”, servicecom.ostranetwork.cli, one entry per API address). It is never written to a file or printed, and never put on a command line.ostra logoutremoves it.OSTRA_API_KEY, when set, is used first. On Linux, in CI, or anywhere but macOS it is the only way.--api-base(orOSTRA_API_BASE_URL) points it at another API address. It must behttps; plainhttponly on this machine, so a key never crosses a network in the clear.
Commands
ostra login- Store an API key in the macOS keychain (paste it at the prompt, or pipe it in)
ostra logout- Remove the stored key for this API from the macOS keychain
ostra lines- Your lines, then the sandbox line LAX-SANDBOX-00
ostra line <line_id>- One line: status, carrier, number, IP, health and proxy ports
ostra proxy <line_id>- The line's proxy endpoints and how many credentials it has
ostra credentials list <line_id>- The line's proxy credentials (never their secrets)
ostra credentials issue <line_id> [--label TEXT] [--expires-in SECONDS]- Issue a proxy credential; its secret is shown once
ostra credentials revoke <line_id> <credential_id>- Revoke one proxy credential
ostra new-ip <line_id> [--wait] [--timeout SECONDS]- Ask the carrier for a new IP on the line (at most one every 5 minutes)
ostra messages <line_id> [--follow] [--content] [--cursor CURSOR] [--limit N]- Texts on the line, oldest first; --content adds bodies and codes (audit-logged)
ostra wait-code <line_id> [--timeout SECONDS] [--cursor CURSOR]- Wait for the next text with a code and print the code (audit-logged)
ostra calls <line_id> [--content] [--cursor CURSOR] [--limit N]- Calls to the line, oldest first; --content adds transcripts and codes (audit-logged)
ostra usage [--from YYYY-MM-DD] [--to YYYY-MM-DD]- Connections and bytes per line per day (the last 30 days by default)
Every command takes --json for the API’s own JSON (with messages --follow, one text a line; an error in the API’s error shape) and --api-base. Every command that changes something sends an Idempotency-Key; new-ip sends the same one again if it has to retry after no answer, so the carrier is asked once. new-ip --wait reads the job every 2 seconds until it finishes (120 seconds by default).
In scripts
ostra wait-code prints the code alone, so a test can capture it. It waits without content and opens only the text with a code, which Ostra writes to its audit log.
#!/bin/sh
# A test step that needs the code your own service just texted to the line.
# ostra wait-code prints the code alone; a non-zero exit says why it did not
# (4: nothing arrived before --timeout).
set -e
ostra lines --json > /dev/null # the key works
CODE=$(ostra wait-code LAX-SANDBOX-00 --timeout 60)
echo "got code $CODE"Exit codes
| Exit | Means |
|---|---|
0 | Done. |
1 | The API refused the request or failed; the error's code and message are on standard error. |
2 | A bad command, option or value. |
3 | No key, a key the API refused (401), or one that lacks a scope (403, which it names). |
4 | Nothing arrived, or the request did not finish, before --timeout. |
5 | The API could not be reached. |
6 | Rate limited, or a new carrier IP refused under the line's limits (with when the next is allowed). |