CLI
Install the koast command line, sign in with an API key or your browser, and run any API operation as a command.
koast is a command line for the REST API. Every API operation is a command, generated from the API's OpenAPI spec, so a new endpoint becomes a new command without a new release. It needs an Agency plan, like the API.
Install
npm install -g @koast.ai/cli
koast --versionNode 18.17 or newer is required.
Sign in
Pick one. The first that's available wins:
-
KOAST_API_KEY. An organization API key with API access on. Best for CI and servers.export KOAST_API_KEY=koast_sk_... -
A stored key.
koast login --api-keychecks the key with the API, then stores it in the config directory with0600permissions. Read it from stdin to keep it out of your shell history:printf '%s' "$KEY" | koast login --api-key -A key the API refuses is reported with the API's error, and nothing is stored.
-
Your browser.
koast loginopens Koast's sign-in and consent screen, then stores the tokens. The CLI acts as you, with the scopes you tick.publishis off unless you tick it, and needs a spend limit.koast login --no-browserprints the URL instead. The sign-in redirects to a local port on the machine running the CLI, so on a remote box forward that port first, or use an API key.
koast logout removes the stored key and revokes the stored tokens. A removed key stays valid until it's revoked in Koast. KOAST_API_KEY isn't touched.
With no credential at all, every command exits 3:
$ koast list-my-ad-accounts
No Koast credential is available. Run `koast login`, or set KOAST_API_KEY.Commands
A command is the operation id from the API reference. GET /v1/brands/{brandId}/launches is list-koast-batches, POST /v1/webhooks is create-webhook-endpoint.
koast commands # every command, grouped by resource
koast commands --output json # the same, as JSON, with each command's flags
koast help list-koast-batches # one command's flags$ koast help list-koast-batches
Usage: koast list-koast-batches [--flags]
GET /v1/brands/{brandId}/launches
List Koast batches
Lists the brand's Koast launches (batches), drafts and published, with their status and campaign, ad set and ad counts. Filter by `status` or by a title substring with `search`.
Required scope: read
Flags:
--brand <integer> required. The brand the request acts on. Every brand-scoped resource lives under its brand
--account-id <string> optional. Ad account id (act_xxx on Meta).
--status <string> optional. Filter by lifecycle status. one of: "DRAFT", "IMPORTED", "PENDING", "RUNNING", "COMPLETED", "COMPLETED_WITH_ISSUES", "ACTION_REQUIRED", "FAILED", "CANCELLED"
--search <string> optional. Substring match on batch title
--page <integer> optional. default: 1
--limit <integer> optional. Page size. default: 50
--cursor <string> optional. Opaque cursor from the previous page's `nextCursor`. Omit for the first page
Notes:
Paged: --all follows every page and prints one JSON line per item of "batches".Every command is listed in CLI commands.
Flags
Flags are the API's parameter and body field names in kebab case: launchId is --launch-id, datePreset is --date-preset.
- The brand is
--brand. It's required on every brand-scoped command. Get brand ids fromkoast list-my-ad-accounts. - Path parameters are required flags. Query parameters and top-level body fields are typed flags, checked before anything is sent.
- An array is repeatable (
--event-types launch.completed --event-types launch.failed) or takes a JSON array. - An object takes JSON.
- A boolean flag with no value means
true. --json <file|->gives the whole body from a file or stdin. Flags you also pass are applied over it.
koast get-account-overview --brand 1 --account-id act_000000000000001 --date-preset today{"accountId":"act_000000000000001","totalBatches":3,"batchesSampled":0,"batchesUnavailable":0,"totalSpend":0,"totalResults":0,"datePreset":"today","asOf":"2026-10-09T04:47:13.994Z"}Global flags
| Flag | What |
|---|---|
--output json | The response body, pretty on a terminal and compact when piped. The default |
--output table | The response's list as a table, or a single object as field value rows |
--all | On paged commands: follow nextCursor to the end and print one JSON line per item. Page size 100 unless you pass --limit |
--idempotency-key <key> | Send this Idempotency-Key |
--json <file|-> | The request body |
--api-url <url> | Another API base URL. Defaults to https://api.koast.ai |
--refresh | Download the OpenAPI spec again before running |
--help, --version | Help, version |
koast list-koast-batches --brand 1 --all | jq -r '.id'
koast list-my-ad-accounts --output tablePublishing
launch-campaign and edit-live-campaign spend money. They need a credential with the publish scope and a spend ceiling.
koast launch-campaign --brand 1 --launch-id cmv0dbqmv0001vct12clu58vk
koast launch-campaign --brand 1 --launch-id cmv0dbqmv0001vct12clu58vk --confirmThe first validates and previews. The second publishes. Both print the Idempotency-Key they sent to stderr. If a publish times out, run the same command with --idempotency-key <that key> to get its result instead of publishing twice. See Idempotency.
Errors and exit codes
| Exit | Meaning |
|---|---|
0 | Success |
1 | The API refused the request or failed |
2 | Usage error: unknown command, unknown or missing flag, wrong type. Nothing was sent |
3 | No credential, or the API answered 401 |
API errors print the status, the code, the message, field details and the request id:
$ koast list-koast-batches --brand 1 --cursor bogus
Error 400 validation_failed: cursor is invalid or expired
Request id: 958ba589-9682-4090-9a0a-ccad622e9e4aOn a 429 the CLI waits as the API asks, never more than 60 seconds, and retries up to 3 times with the same Idempotency-Key.
Configuration
| Variable | Flag | What |
|---|---|---|
KOAST_API_KEY | An organization API key. Wins over any stored credential | |
KOAST_API_URL | --api-url | API base URL. The flag wins |
KOAST_CONFIG_DIR | Credentials and the spec cache. Defaults to $XDG_CONFIG_HOME/koast, else ~/.config/koast |
The CLI caches the OpenAPI spec for 24 hours, then revalidates it with the API. If the API can't be reached and a cache exists, it uses the cache and warns you. Credentials are stored per API URL.
MCP
Connect Claude, ChatGPT, Cursor or any MCP client to Koast's MCP server. It runs the same operations as the REST API, on every paid plan.
API reference
The Koast REST API. Every brand-scoped resource lives under /v1/brands/{brandId}. Lists are cursor-paginated, errors share one envelope, and every response carries a Koast-Request-Id header.