CLI reference

Complete reference for the Brevo CLI — install, authenticate, and manage OAuth apps

The Brevo CLI (@getbrevo/cli) lets you create and manage OAuth apps, scaffold starter code, and run a local test server — all from the terminal.

Upgrade to v2.1.0. If you are on v2.0.2 or earlier, migrate to 2.1.0. The 2.1.0 release introduces breaking changes, so some CLI commands may not work as expected on older versions.

Upgrade with npm install -g @getbrevo/cli@latest (or yarn global add @getbrevo/cli@latest, or brew upgrade getbrevo/tap/brevo), then confirm with brevo --version. See the latest release on npm.

v2.1.0 replaces brevo app update with brevo app upload and reshapes the app-config.json schema below (auth.redirectUrlsauth.redirectUris, distributiondistribution_type, new version). Nothing breaks immediately — old configs still read correctly and older keys migrate automatically the next time a command writes the file, and brevo app update stays registered just to point you to its replacement.

Installation

$npm install -g @getbrevo/cli

Requirements: Node.js >= 20.15.0 (Homebrew installs Node automatically as a dependency).

Verify:

$brevo --version

Authentication commands

brevo login

Authenticate with your Brevo account via browser.

$brevo login

Opens oauth-cli.brevo.com in your browser. After signing in, credentials are saved to ~/.brevo/credentials.json.

FlagDescription
--browserForce browser login (default)
--jsonOutput result as JSON

Example:

$brevo login

brevo logout

Clear stored credentials.

$brevo logout [--force]
FlagDescription
--forceSkip confirmation prompt (required in non-interactive environments)
--jsonOutput result as JSON

Example:

$brevo logout --force

Logout clears cached app credentials (client ID / client secret). Run brevo app credentials --reveal-secret before logging out if you need to save them.


brevo whoami

Show the currently authenticated user.

$brevo whoami
FlagDescription
--jsonOutput result as JSON

Example:

$brevo whoami
$# Authenticated as you@example.com (Acme Corp)

App commands

brevo app init

Guided setup — authenticate, create an app, and optionally scaffold starter code, in one flow.

$brevo app init

No flags. Prompts for: app name, logo URL, distribution type, app type, OAuth callback URL, output directory, and whether to scaffold the Test OAuth App feature.

Example:

$brevo app init

Use this for first-time setup. For scripted or automated flows, use brevo app create with flags — non-interactive runs stay base-project-only, with no prompts.


brevo app create

Create a new OAuth app.

$brevo app create [--name <name>] [--distribution <type>] [--redirect-uri <url>] [--logo-uri <url>]
FlagDescription
--name <name>App name
--distribution <type>Distribution type — private (default)
--redirect-uri <url>Redirect URI — repeatable to add multiple URIs
--logo-uri <url>App logo URL (http:// or https://). Optional. When omitted in an interactive shell, the command prompts for it; leave blank to skip.
--jsonOutput result as JSON

Behavior:

  • Writes only the base project (app-config.json, .gitignore, AGENTS.md, CLAUDE.md, README.md) first, then — interactively — asks “Scaffold the Test OAuth App?” (default yes) before writing the OAuth test server code. Decline to stay base-only and add it later with brevo app scaffold.
  • Non-interactive runs (--json, or piped stdin) always stay base-only — the feature prompt is skipped, not defaulted to yes.
  • Hard-errors if app-config.json already exists in the current directory. Run brevo app scaffold there instead to add a feature to that project.

Examples:

$# Interactive
$brevo app create
$
$# Non-interactive — base project only; follow up with `brevo app scaffold`
$brevo app create --name "My App" --distribution private --redirect-uri http://localhost:3009/auth/callback
$
$# Multiple redirect URIs
$brevo app create --name "My App" \
> --redirect-uri http://localhost:3009/auth/callback \
> --redirect-uri https://staging.myapp.com/auth/callback
$
$# With a logo
$brevo app create --name "My App" --distribution private --logo-uri https://example.com/logo.png

brevo app list

List all OAuth apps in your account.

$brevo app list
FlagDescription
--jsonOutput result as JSON

Example:

$brevo app list --json

brevo app credentials

Show credentials for an app.

$brevo app credentials [--app-id <id>] [--reveal-secret]
FlagDescription
--app-id <id>Target app ID. Omit to select interactively.
--reveal-secretShow the client secret (hidden by default). Prompts for confirmation.
--jsonOutput result as JSON

Examples:

$# Show credentials (secret hidden)
$brevo app credentials --app-id e22eb778-a2a8-488a-a5e8-466b6dad9385
$
$# Reveal client secret
$brevo app credentials --app-id e22eb778-a2a8-488a-a5e8-466b6dad9385 --reveal-secret

brevo app upload

Renamed from brevo app update in v2.1.0. The command no longer takes --app-id, --name, --redirect-uri, --scope, or --logo-uri flags — edit the field in app-config.json, then run brevo app upload to push the change. Running brevo app update (with or without its old flags) prints this migration message and exits with code 1 — nothing is forwarded or uploaded.

Push app-config.json to Brevo, validated and synced with the server.

$brevo app upload [--yes] [--json]
FlagDescription
--yesSkip confirmation prompt
--jsonOutput result as JSON

Behavior:

  • Always reads app-config.json from the current directory and pushes the whole file — there’s no flag to edit a single field remotely. To change the app’s name, redirect URLs, scopes, or logo, edit the corresponding field in app-config.json first, then run brevo app upload.
  • Always fetches the app’s current state from Brevo and shows a local-vs-server diff before doing anything else — including under --yes (which only skips the confirmation prompt) and --json.
  • No differences: exits 0 with Already up to date at version <version>. and makes no network push — there’s nothing to write back.
  • A difference: prints the diff, asks to confirm (unless --yes or --json), pushes the whole file, and writes the server-confirmed state — including the resolved version — back to app-config.json.
  • distribution_type is immutable after app create. If app-config.json disagrees with the server, upload refuses locally before showing the diff or pushing anything — create a new app with brevo app create to change distribution.
  • If auth.scopes still contains the deprecated all scope, upload refuses and points to brevo app available-scopes — replace it with specific scopes first.
  • Scope values are format-validated locally (^[A-Za-z0-9][A-Za-z0-9:_.-]*$) but not cross-checked against the IdP catalog. Typos surface as invalid_scope errors at authorization time — run brevo app available-scopes first to confirm the spelling.
  • Errors if app-config.json is missing, invalid, or lacks appId.

Examples:

$# Edit app-config.json, then push the change
$brevo app upload
$
$# Skip the confirmation prompt
$brevo app upload --yes
$
$# Machine-readable output
$brevo app upload --json

Lost your project folder? Recover it with brevo app scaffold --app-id <id>, then edit app-config.json and upload.


brevo app available-scopes

List every OAuth scope your app can request, grouped by category. Reads the live catalog from Brevo’s OAuth server.

$brevo app available-scopes [--json] [--web]
FlagDescription
--jsonOutput the catalog as JSON instead of a printed table
--webOpen a local browser page at 127.0.0.1:<port> with search and refresh

Examples:

$# Print the catalog grouped by category
$brevo app available-scopes
$
$# Machine-readable output for scripting
$brevo app available-scopes --json | jq '.scopes[].name'
$
$# Searchable browser view
$brevo app available-scopes --web

brevo app scaffold

Two modes, chosen by whether the current directory already has an app-config.json:

  • With one — adds a feature (the OAuth test server) to the app linked there.
  • Without onebootstraps: sets the directory up for an app you already have. This is the migration path off the removed brevo app update --app-id.
$brevo app scaffold [--app-id <id>] [--overwrite] [--json]
FlagDescription
--app-id <id>Set an empty directory up for an app you already have (bootstrap mode)
--overwriteOverwrite existing feature files instead of merging (skips the conflict prompt)
--jsonOutput result as JSON

Bootstrap mode — recovering a project:

  • With --app-id <id>, fetches that app and writes app-config.json plus the base files (.gitignore, AGENTS.md, CLAUDE.md, README.md), then continues into the feature prompt below.
  • Without --app-id, interactively: asks “Set up a project for an app you already have?” (default yes), then shows a picker of your apps — so recovery doesn’t require the app’s ID in hand. Declining exits 0.
  • Under --json or off a TTY with no --app-id, it raises the same “no app-config.json” error rather than opening a picker — scripts must pass --app-id explicitly.
  • Also asks for an output directory (default: the app name as a slug) and creates it — answer . to stay in the current directory.
  • Refuses, before any network call: bootstrapping into a directory that’s already inside an existing app project; --app-id naming a different app than the one the current directory is already linked to; and an output directory that’s already a different app’s project.

Feature mode — adding to a linked project:

  • Reads the linked app from app-config.json, diffs it against the server, and on drift asks to update the local file to match before writing.
  • If the feature’s files already exist, asks Overwrite / Merge / Cancel (default Merge). --overwrite skips that prompt.

Generates 6 files for the OAuth test server — src/oauth/server.js, handler.js, token-store.js, .env.example, .env.local, package.json — with .env.local pre-populated with your credentials.

Examples:

$# Add the OAuth test server to the app linked in this directory
$brevo app scaffold
$
$# Recover a project for an app you already have
$brevo app scaffold --app-id e22eb778-a2a8-488a-a5e8-466b6dad9385
$
$# Force a full rewrite of feature files
$brevo app scaffold --overwrite
$
$# Machine-readable output
$brevo app scaffold --json

brevo app start

Start a scaffolded feature server locally.

$brevo app start oauth [--port <port>]
ArgumentDescription
oauthStart the OAuth test server
FlagDescription
--port <port>Override the default port (default: read from app-config.json, fallback 3009)

Run from inside your scaffolded project directory (where app-config.json is). Install dependencies first:

$npm --prefix src/oauth install
$# or: yarn --cwd src/oauth install

Examples:

$# Start on default port
$brevo app start oauth
$
$# Start on a custom port
$brevo app start oauth --port 3000

If you change the port, add the matching redirect URL to auth.redirectUris in app-config.json, then run brevo app upload to push the change.

Auto-registration. When the resolved port has no matching http://localhost:<port>/... entry on the app, the CLI prompts to register it automatically — approving pushes the new URL to Brevo and updates app-config.json. In non-TTY/CI mode it hard-fails instead of silently mutating the remote app; add the URL to auth.redirectUris in app-config.json and run brevo app upload to register it first.


brevo app delete

Delete an OAuth app. This action cannot be undone.

$brevo app delete [--app-id <id>] [--force]
FlagDescription
--app-id <id>Target app ID. Omit to select interactively.
--forceSkip confirmation prompt
--jsonOutput result as JSON

Example:

$brevo app delete --app-id e22eb778-a2a8-488a-a5e8-466b6dad9385

Claude Code skill

The CLI ships a Claude Code skill so you can drive brevo commands — creating apps, managing scopes, running the local OAuth test server — straight from Claude Code, with the CLI’s conventions and guardrails loaded as context.

$brevo skill:cli install
CommandDescription
brevo skill:cli install [--json]Install the brevo-cli Claude Code skill
brevo skill:cli uninstall [--json]Remove the brevo-cli skill

Once installed, every brevo invocation auto-refreshes the skill when the CLI ships a newer version, so the guidance stays in sync with your installed CLI.

The skill format is specific to Claude Code. Other AI agents (Cursor, Copilot CLI, Gemini, Codex) shouldn’t run brevo skill:cli install — refer to the agent-context/AGENTS.md file bundled with the package instead.


Exit codes

CodeMeaning
0Success
1General error
2Aborted (Ctrl+C or SIGTERM)
3Authentication failure (401)
4Network error (API unreachable)
5Not found (404)

app-config.json schema

The scaffold writes app-config.json to the project root. brevo app upload pushes this file to Brevo.

1{
2 "appId": "e22eb778-a2a8-488a-a5e8-466b6dad9385",
3 "appName": "my-app",
4 "version": "1",
5 "logoUri": "https://example.com/logo.png",
6 "distribution_type": "private",
7 "auth": {
8 "scopes": ["contacts:read", "contacts:write", "crm:read", "crm:write"],
9 "redirectUris": ["http://localhost:3009/auth/callback"]
10 }
11}
FieldTypeDescription
appIdstringApp ID assigned by Brevo — do not edit
appNamestringDisplay name of your app
versionstringRead-only. Tracks the app-store API’s version for this app; updated automatically after each brevo app upload.
logoUristringOptional http:// or https:// URL to your app’s logo. Empty when not set. Edit this field, then run brevo app upload to push it.
distribution_typestringAlways private. Immutable after app createbrevo app upload refuses a changed value.
auth.scopesstring[]OAuth scopes your app requests. New apps default to ["contacts:read", "contacts:write", "crm:read", "crm:write"]. See Scopes for the full catalog.
auth.redirectUrisstring[]Registered redirect URLs — must match exactly during authorization

Migrated from an older CLI? Before v2.1.0, this file used auth.redirectUrls (now auth.redirectUris) and a top-level distribution, with an interim auth.type (both now distribution_type). Older keys are still read — the new key wins if both are present — and the file is rewritten to the current shape the next time a command writes it (brevo app upload, app start’s redirect-URL registration, app credentials, or app scaffold). cliVersion and minCliVersion are no longer written.

Downgrading to an older CLI? It reads only redirectUrls, so a file already migrated to redirectUris looks to it like it has no redirect URLs. Harmless for most commands, but brevo app start may then offer to register a single local callback URL as the app’s entire redirect_uris, dropping every real one. Upgrade the older CLI, or keep both keys during a transition — if it already happened, restore the list and run brevo app upload.

The scaffolded OAuth test server reads auth.scopes from app-config.json and joins it with spaces for the scope= query parameter. If the file is missing or unreadable, it falls back to an internal default that won’t match your app’s registered scopes — keep app-config.json in your project root and unmodified.


Upgrading

$npm install -g @getbrevo/cli@latest

The CLI checks for new versions after each command and prints a banner when one is available. Pass --no-update-notifier or set BREVO_NO_UPDATE_NOTIFIER=1 to suppress it.