Installing the Norbelys CLI and running your first command
Two ways to install the norbelys CLI, how it turns the REST API into commands automatically, and a full walkthrough from install to your first real call.
By Gabriel Lara, Developer Relations, Norbelys
Founder-reviewed ·How we research and correct articles
If you’d rather run a command than click through a dashboard, norbelys is
the official command-line client for the Norbelys API — the
same cold email and deliverability platform,
just driven from a terminal instead of a browser. It isn’t a hand-maintained
wrapper that drifts out of sync with the product — it’s a thin, generated
client. Every resource command is built at startup straight from the same
API contract that powers the OpenAPI spec
and the SDKs, so a command either does
exactly what the API does, or it doesn’t exist yet.
This is a start-to-finish install-and-run guide: get the binary on your machine, authenticate, and make your first real call.
Two ways to install
Pick whichever fits how you already manage tools. Both put the same
norbelys binary on your PATH.
The install script downloads a small self-contained bundle from Norbelys’ own distribution point and doesn’t require Node or npm to be installed first:
The npm package is the better fit if you’re already inside a Node project or CI image that has npm available, and want the CLI managed the same way as your other dependencies:
Either path gives you the same tool. There’s no “npm edition” with fewer commands — it’s the identical bundle, just distributed through a package manager instead of a shell script.
Authenticate before your first command
Every command needs a bearer credential, the same Authorization: Bearer
token the raw API expects. The fastest way to get one is an org-scoped API
key created from the dashboard:
That’s the whole setup for now. There’s also a browser-based OAuth flow built into the CLI for interactive human logins — a separate post covers the tradeoffs between the two and where the credential actually ends up on disk in more depth than makes sense here.
Your first real command
Once you’re logged in, every resource in the API is available as a command.
The shape mirrors the REST endpoint closely enough that if you know the API,
you already know roughly what to type — GET /v1/people becomes something
like norbelys people list, POST /v1/senders becomes norbelys senders create, and so on for every resource the contract defines.
By default the output is a readable table, which is what you want when a
human is reading the terminal. When a script is reading the output instead,
switch to structured output so you can pipe the result into jq or feed it
to another program without parsing a table:
That table/object/JSON split isn’t an afterthought bolted onto one or two commands — it’s a property of the whole CLI, because output rendering is handled by one shared layer that every generated command runs through, not reimplemented per command.
Why every command is generated, not hand-written
This is worth understanding because it changes what you should expect from
the tool. The CLI reads the same contract package that defines the
OpenAPI spec and builds a command
tree from it at startup — each resource’s Zod schema turns into CLI flags,
each operation turns into a subcommand, and a single request builder turns
whatever you typed into the right HTTP call: path parameters go into the
URL, GET/DELETE calls become query parameters, everything else becomes
a JSON body.
The practical upshot: the CLI cannot expose a command that doesn’t correspond to something the real API does, and it cannot silently fall behind when the API changes shape. If a field becomes required in the contract, the flag becomes required in the CLI on the next build. There’s no separate CLI team maintaining a parallel definition of what Norbelys does — there’s one definition, and the CLI is one of several things generated from it, alongside the SDKs and the MCP server’s tool catalog.
There’s also an escape hatch for anything the generated tree doesn’t cover
yet — a raw api command that lets you hit any path directly with your
authenticated session, useful the day after a new endpoint ships and before
you’ve upgraded. It’s the same underlying request builder every generated
command already uses — path parameters, query strings, and JSON bodies
handled the same way — just with the resource and verb spelled out by hand
instead of resolved from a subcommand name. In practice you’ll reach for it
rarely: mostly the window between a new endpoint landing in the contract
and your next norbelys upgrade picking it up.
Staying current
Because the command tree is generated from the contract, an out-of-date CLI binary is the one way it can drift — an old build simply doesn’t know about a resource added after it shipped. The CLI checks for this itself: it pings for a newer version roughly once a day, fails silently if that check can’t complete (a flaky network shouldn’t block you from running a command), and tells you plainly when an upgrade is available.
If you’re pinning a version deliberately — inside a Docker image, say, or a
CI runner where you want reproducible builds — that’s fine; just know the
update check exists and won’t interrupt a script if it fails, only if you
explicitly run upgrade.
Composing the CLI with other tools
Because JSON output is a first-class mode rather than an afterthought, the
CLI slots into whatever shell tooling you already use instead of asking you
to learn a new one. jq for filtering and reshaping, grep for a quick
match, wc -l for a row count, redirecting into a file for something you
want to diff against tomorrow’s run — none of that requires anything
special from the CLI beyond honoring --json consistently across every
generated command, which it does because the flag is handled by the same
shared output layer regardless of which resource you’re calling.
That composability is really the point of a CLI existing at all next to a dashboard: a dashboard shows you one screen at a time; a terminal lets you chain small, well-understood tools together into something specific to the task in front of you, without waiting on a feature request for a view nobody’s built yet.
Where to go next
You’ve got the binary installed and one real call under your belt. From here:
- API key vs. browser OAuth — the two login modes in depth, and where credentials live on disk.
- Automating ops checks in CI
— wiring the CLI into a GitHub Actions pipeline with
$NORBELYS_API_KEY. - Managing multiple orgs from one terminal — the profile system, for agencies running several client workspaces.
- CLI vs. dashboard: when scripting actually wins — an honest take on when not to reach for the terminal.
- The developer portal has the full resource list, the raw OpenAPI spec, and the MCP server if you’re wiring up an AI agent instead.