Most API design tutorials start with a mouse. Open a visual editor, drag a schema onto a canvas, click through dialogs to add a field. That works, but it doesn’t fit how a lot of teams actually ship. If your API definition lives in Git, gets reviewed in pull requests, and passes through CI, you want to design it the same way you deploy it: from the terminal, in text, with commands you can script.
Designing APIs from the command line means you author the contract, lint it against a style guide, bundle it into a single file, and generate stubs, all without leaving the shell. Every step is repeatable. Every step can run in a pipeline. And when an AI agent or a teammate needs to reproduce your setup, they run the same commands you did instead of guessing which buttons you clicked.
This guide walks two routes. First, the general open-source path built from single-purpose tools: author an OpenAPI file, lint it with Spectral, bundle it with the Redocly CLI, and generate server stubs with openapi-generator. Then the Apidog CLI path, where design, schemas, endpoints, and auth live in one project you can drive from the terminal. If you want the deeper conceptual background first, read our guide on how to design an API and the walkthrough on designing REST APIs.
If you’re following along with Apidog, grab the binary first. Our Apidog CLI installation guide covers the npm install -g apidog-cli step and the apidog login --with-token handshake, and the complete Apidog CLI guide maps every command group.
The general open-source route: author, lint, bundle, generate
The classic CLI design stack is a set of independent tools you wire together. You keep your API definition in an OpenAPI file under version control and run each tool as a step. This is the Git-native API design workflow, and it’s genuinely good. Here’s the shape of it.
Author the OpenAPI document
You start with a plain YAML file. There’s no special editor required; any text editor works. A minimal openapi.yaml looks like this:
openapi: 3.0.3
info:
title: Orders API
version: 1.0.0
paths:
/orders/{orderId}:
get:
operationId: getOrder
parameters:
- name: orderId
in: path
required: true
schema:
type: string
responses:
'200':
description: An order
content:
application/json:
schema:
$ref: '#/components/schemas/Order'
components:
schemas:
Order:
type: object
required: [id, status]
properties:
id:
type: string
status:
type: string
enum: [pending, shipped, delivered]
As the API grows, you split it across multiple files and reference them with $ref. That keeps each schema readable and reviewable on its own.
Lint with Spectral
Hand-written OpenAPI drifts. Someone forgets an operationId, another person leaves a response undocumented, a third invents their own naming convention. A linter catches all of that before review. Spectral, from Stoplight, is the standard choice. It ships rulesets for OpenAPI and lets you write your own.
npm install -g @stoplight/spectral-cli
spectral lint openapi.yaml
Spectral prints every violation with a line number and severity. You can fail the build on errors by checking the exit code in CI. Redocly’s CLI and vacuum do the same job if you want an alternative; vacuum is fast and drops in as a Spectral-compatible linter. The point stands regardless of which one you pick: linting is a separate, dedicated tool, and you run it as its own step.
Bundle with the Redocly CLI
Once your definition is split across files, most downstream tools want a single self-contained document. The Redocly CLI resolves every $ref and flattens the tree into one file.
npm install -g @redocly/cli
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Redocly also lints (redocly lint) and previews docs, so some teams use it for both style checking and bundling. Its official docs list the full command set.
Generate stubs with openapi-generator
With a clean, bundled spec, you generate code. openapi-generator turns an OpenAPI document into server stubs, client SDKs, and more across dozens of languages.
npm install -g @openapitools/openapi-generator-cli
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g spring \
-o ./server
Swap -g spring for -g python-flask, -g go-server, or any of the supported generators. Now you have scaffolding that matches your contract exactly.
That’s the open route end to end: four tools, four commands, all scriptable. The cost is the wiring. You maintain the file layout, the linter config, the bundle step, and the generator config yourself, and each tool has its own conventions. It works well when you want maximum control and don’t mind the glue.
The Apidog CLI route: design in one project
The other approach keeps design, schemas, endpoints, mocks, and auth inside a single project you drive from the terminal. The apidog-cli binary is a full project-resource CLI, not just a test runner. It has command groups for the whole design surface: schema for data models, endpoint for operations, folder for organization, security-scheme for auth, plus import, export, mock, and more.
One honest note up front: Apidog does not lint your OpenAPI or enforce a style guide. That’s not what it’s for. If you need linting, keep Spectral or vacuum in your pipeline. Apidog isn’t open source either; it’s a commercial product with a free tier. What it gives you is an integrated project so you don’t have to stitch the design pieces together yourself. Our take on Swagger alternatives for API design and testing covers where that trade-off makes sense.
Install and authenticate first (see the installation guide for token setup):
npm install -g apidog-cli
apidog login --with-token <YOUR_ACCESS_TOKEN>
Every command returns structured JSON, and most responses include an agentHints.nextSteps block that tells you (or an agent) what to run next. Add --help to any command to see its exact flags.
Define data models with apidog schema
Design starts with your data. A reusable Order schema becomes the single source of truth that endpoints reference, the same idea as components/schemas in raw OpenAPI, but managed as a project resource.
apidog schema --help
apidog schema create --project <PROJECT_ID>
Because the output is JSON, you can pipe it through jq to grab the new schema’s ID and feed it into the next command. If you already have an OpenAPI file, import it instead of retyping everything:
apidog import --project <PROJECT_ID> --file openapi.yaml
apidog import accepts OpenAPI 3.x, Swagger 2.0, Postman, and Apidog formats, so an existing definition becomes a live project in one step.
Define endpoints with apidog endpoint
With models in place, you add operations. The endpoint group creates and updates endpoints, wiring them to the schemas you defined and to the folders that organize them.
apidog endpoint --help
apidog endpoint list --project <PROJECT_ID>
apidog endpoint create --project <PROJECT_ID>
Listing endpoints as JSON is useful on its own. You can diff the output across branches or feed it to a script that checks every path has the responses you expect. Group related endpoints with the folder command so the project stays navigable as it grows.
Define auth with apidog security-scheme
Auth is part of the contract, not an afterthought. The security-scheme group defines how clients authenticate: API keys, bearer tokens, OAuth 2.0, and so on. This maps to components/securitySchemes in OpenAPI, so importing and exporting round-trips cleanly.
apidog security-scheme --help
apidog security-scheme list --project <PROJECT_ID>
Defining the scheme once at the project level means every endpoint can reference it instead of each operation redeclaring its own auth. That’s exactly the kind of consistency a linter would otherwise nag you about.
Validate your writes with apidog cli-schema validate
Before you commit changes or hand a project to CI, you want to know your resource definitions are well-formed. The CLI ships a cli-schema validate command that checks a definition file against the schema the CLI expects, so a malformed write fails fast instead of landing silently.
apidog cli-schema --help
apidog cli-schema validate --file resource.json
Run this as a guard step in your pipeline: validate first, then apply. A non-zero exit stops the pipeline before a bad resource reaches the project. This is validation of your CLI writes, not OpenAPI style linting; those are two different jobs, and you still want Spectral for the second one.
Export back to OpenAPI
Design in Apidog, then hand a standard artifact to the rest of your toolchain. apidog export writes OpenAPI, HTML, Markdown, or Postman.
apidog export --project <PROJECT_ID> --format openapi -o dist/openapi.yaml
Now you’re back to a portable OpenAPI file. Feed it to Spectral for linting, to openapi-generator for stubs, or into your docs build. The integrated project and the open-tool stack aren’t mutually exclusive; export is the bridge between them.
Wiring it into CI
Both routes shine in a pipeline because every command has an exit code and text output. A minimal design-check job might run the linter, then validate, then bundle:
# fail on style violations
spectral lint openapi.yaml
# validate any CLI resource writes before applying
apidog cli-schema validate --file resource.json
# flatten to a single artifact for downstream steps
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Because Apidog’s output is JSON with agentHints.nextSteps, this flow also drives cleanly from an AI coding agent. The agent reads the structured result, sees the suggested next step, and runs it, no screen-scraping a GUI. That’s the whole reason to design from the CLI in the first place: what a human types, a script or an agent can type too.
Common snags
Split files break downstream tools. A definition spread across many $ref files is great for humans and awkward for generators. Always bundle to a single file before you generate code or publish docs. redocly bundle is the fix.
You expect Apidog to lint. It won’t. Apidog manages resources; it does not enforce a style guide or flag OpenAPI rule violations. Keep Spectral or vacuum in the loop for that. Treating apidog cli-schema validate as a linter is the common mix-up; it validates resource structure, not OpenAPI style.
Forgetting to import before you edit. If you’re editing an existing API through the CLI, import the source definition into the project first. Editing an empty project and expecting your old endpoints to be there is a quick way to get confused.
Auth defined per endpoint instead of once. Define a security-scheme at the project level and reference it. Redeclaring auth on every operation is how contracts drift.
Wrapping up
Designing APIs from the CLI turns a click-heavy task into a set of repeatable commands. The open route, author, lint with Spectral, bundle with Redocly, generate with openapi-generator, gives you full control and no lock-in. The Apidog CLI route gives you an integrated project where schemas, endpoints, and auth live together and every command returns agent-ready JSON. Export bridges the two, so you’re never stuck.
Pick the route that matches your team. If you already live in Git with a pile of single-purpose tools, keep them and add apidog export when you want a portable artifact. If you’d rather not maintain the glue, Download Apidog, install the CLI, and design your next API without touching a mouse.



