Most API design tutorials start with a mouse: open a visual editor, drag a schema onto a canvas, and click through dialogs to add fields. That approach works, but it does not match teams that keep API contracts in Git, review them in pull requests, and validate them in CI. For those teams, API design should be text-based, scriptable, and reproducible from the terminal.
Designing APIs from the command line means you can author a contract, lint it against rules, bundle multi-file specifications, and generate server stubs without leaving the shell. Each step is repeatable locally and in CI. Teammates and AI agents can run the same commands instead of trying to reproduce GUI actions.
This guide covers two workflows:
- An open-source CLI stack: author OpenAPI, lint with Spectral, bundle with Redocly CLI, and generate stubs with openapi-generator.
- The Apidog CLI workflow: manage schemas, endpoints, authentication, and exports within one project.
For more API design background, see how to design an API and designing REST APIs.
If you are using Apidog, install the CLI before starting. The Apidog CLI installation guide covers npm install -g apidog-cli and apidog login --with-token. The complete Apidog CLI guide lists all command groups.
The general open-source route: author, lint, bundle, generate
A classic CLI-based API workflow combines focused tools. Store your OpenAPI definition in version control, then run validation, bundling, and generation as explicit pipeline steps. This is a Git-native API design workflow.
1. Author the OpenAPI document
Start with a YAML file. Any editor works because OpenAPI is plain text.
Create openapi.yaml:
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, split schemas and paths into separate files with $ref. For example:
api/
├── openapi.yaml
├── paths/
│ └── orders.yaml
└── schemas/
└── order.yaml
This keeps reviews focused, but downstream tools often need a bundled file. You will handle that in a later step.
2. Lint with Spectral
Hand-written OpenAPI definitions drift over time. Common issues include missing operationId values, undocumented responses, inconsistent naming, and incomplete descriptions.
Install Spectral:
npm install -g @stoplight/spectral-cli
Lint your definition:
spectral lint openapi.yaml
Spectral reports violations with file locations and severity levels. In CI, a lint failure returns a non-zero exit code, which can stop the build.
You can also add a project-level ruleset such as .spectral.yaml:
extends:
- spectral:oas
rules:
operation-operationId:
given: $.paths[*][*]
then:
field: operationId
function: truthy
Alternatives include Redocly CLI and vacuum. The important part is to make OpenAPI linting a dedicated, required pipeline step.
3. Bundle with Redocly CLI
When your API uses multiple files, bundle it before generating code or publishing documentation. Bundling resolves $ref references and produces a self-contained OpenAPI artifact.
Install Redocly CLI:
npm install -g @redocly/cli
Bundle the specification:
mkdir -p dist
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Use the bundled file as the input for generators, documentation builds, and release artifacts.
Redocly can also lint specifications:
redocly lint openapi.yaml
See the Redocly CLI documentation for its full command set.
4. Generate stubs with openapi-generator
Once you have a clean bundled spec, generate server scaffolding or client SDKs from it.
Install the generator:
npm install -g @openapitools/openapi-generator-cli
Generate a Spring server stub:
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g spring \
-o ./server
Swap the generator name for another supported target:
# Python Flask server
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g python-flask \
-o ./server
# Go server
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g go-server \
-o ./server
The result is generated scaffolding aligned with the API contract.
Open-source workflow summary
The end-to-end workflow is four explicit steps:
# 1. Author openapi.yaml
# 2. Lint the source contract
spectral lint openapi.yaml
# 3. Bundle multi-file references
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
# 4. Generate implementation scaffolding
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g spring \
-o ./server
This approach provides maximum control. The trade-off is that you maintain file organization, lint rules, bundling configuration, and generator settings yourself.
The Apidog CLI route: design in one project
The Apidog CLI keeps schemas, endpoints, authentication, mocks, and exports in a single project managed from the terminal.
The apidog-cli binary includes command groups for:
-
schemafor data models -
endpointfor API operations -
folderfor organization -
security-schemefor authentication -
importandexportfor moving between formats -
mockand other project resources
One important distinction: Apidog does not lint OpenAPI or enforce an API style guide. Keep Spectral or vacuum in your pipeline when you need OpenAPI linting. Apidog is also not open source; it is a commercial product with a free tier. Its value is managing API design resources in an integrated project rather than requiring separate tools for every design task.
For a comparison of design and testing options, see Swagger alternatives for API design and testing.
1. Install and authenticate
Install the CLI:
npm install -g apidog-cli
Authenticate with an access token:
apidog login --with-token <YOUR_ACCESS_TOKEN>
See the installation guide for token setup.
Commands return structured JSON. Many responses include agentHints.nextSteps, which makes the CLI useful in scripts and AI-agent workflows. Use --help to inspect available options:
apidog --help
apidog schema --help
apidog endpoint --help
2. Define reusable data models
Start with schemas that represent the reusable domain models in your API.
apidog schema create --project <PROJECT_ID>
A schema serves the same purpose as an OpenAPI components/schemas entry: endpoints can reference it instead of duplicating object definitions.
Because output is JSON, you can extract IDs with jq and use them in subsequent commands:
schema_id=$(
apidog schema create --project <PROJECT_ID> \
| jq -r '.data.id'
)
echo "$schema_id"
If you already have an OpenAPI definition, import it instead of recreating resources manually:
apidog import --project <PROJECT_ID> --file openapi.yaml
apidog import accepts OpenAPI 3.x, Swagger 2.0, Postman, and Apidog formats.
3. Define endpoints
Use the endpoint command group to create, update, and inspect API operations.
apidog endpoint list --project <PROJECT_ID>
Create an endpoint:
apidog endpoint create --project <PROJECT_ID>
Listing endpoints as JSON is useful in automation. For example, you can save the output for a branch comparison:
apidog endpoint list --project <PROJECT_ID> > endpoints.json
git diff -- endpoints.json
Use folder commands to group related endpoints as the project grows:
apidog folder --help
4. Define authentication once
Authentication is part of the contract. Define a project-level security scheme instead of repeating credentials or authentication configuration in every endpoint.
Inspect available security scheme commands:
apidog security-scheme --help
List existing schemes:
apidog security-scheme list --project <PROJECT_ID>
Project-level schemes can represent API keys, bearer tokens, OAuth 2.0, and other authentication patterns. This corresponds to OpenAPI components/securitySchemes.
Centralizing auth configuration reduces contract drift and makes exported OpenAPI definitions more consistent.
5. Validate CLI resource definitions
Before applying resource changes in CI, validate resource definition files with cli-schema validate:
apidog cli-schema validate --file resource.json
Inspect the command options if needed:
apidog cli-schema --help
Use validation as a guard step:
apidog cli-schema validate --file resource.json
# Apply the resource only after validation succeeds.
This validates CLI resource structure. It is not a replacement for OpenAPI style linting. Continue using Spectral or vacuum to validate OpenAPI conventions and style rules.
6. Export to OpenAPI
Export an Apidog project when another tool needs a portable API contract:
mkdir -p dist
apidog export \
--project <PROJECT_ID> \
--format openapi \
-o dist/openapi.yaml
You can then use the exported file with the open-source toolchain:
spectral lint dist/openapi.yaml
redocly bundle \
dist/openapi.yaml \
-o dist/openapi.bundled.yaml
openapi-generator-cli generate \
-i dist/openapi.bundled.yaml \
-g spring \
-o ./server
Apidog and OpenAPI CLI tools can work together: Apidog manages the project resources, while exported OpenAPI remains the portable artifact for linting, code generation, and documentation.
Wiring the workflow into CI
Both workflows fit naturally into CI because every command produces text or JSON output and uses exit codes.
A minimal shell-based API design check might look like this:
#!/usr/bin/env bash
set -euo pipefail
# Fail on OpenAPI style violations.
spectral lint openapi.yaml
# Validate Apidog CLI resource definitions before applying them.
apidog cli-schema validate --file resource.json
# Produce a single artifact for generators and documentation tools.
mkdir -p dist
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
In GitHub Actions, the same checks could be a job step sequence:
name: API contract checks
on:
pull_request:
push:
branches: [main]
jobs:
validate-api:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Install CLI tools
run: |
npm install -g @stoplight/spectral-cli
npm install -g @redocly/cli
npm install -g apidog-cli
- name: Lint OpenAPI
run: spectral lint openapi.yaml
- name: Validate Apidog resource file
run: apidog cli-schema validate --file resource.json
- name: Bundle OpenAPI
run: redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Apidog's structured JSON output and agentHints.nextSteps also work well with coding agents. An agent can read a command result, identify the suggested next action, and execute it without interacting with a GUI.
Common snags
Split files break downstream tools
Multi-file OpenAPI definitions are easier to maintain, but generators and documentation tooling often expect one document.
Bundle before generation:
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Use dist/openapi.bundled.yaml for downstream tools.
Expecting Apidog to lint OpenAPI
Apidog manages project resources but does not enforce an OpenAPI style guide. Keep a dedicated linter in the pipeline:
spectral lint openapi.yaml
Do not treat this as equivalent to:
apidog cli-schema validate --file resource.json
The first validates OpenAPI rules and conventions. The second validates CLI resource structure.
Editing an empty project
If an API already exists as OpenAPI, Swagger, or Postman data, import it before editing:
apidog import --project <PROJECT_ID> --file openapi.yaml
Otherwise, the project will not contain the endpoints and schemas you expect.
Defining auth per endpoint
Avoid duplicating authentication definitions across operations. Create a project-level security-scheme and reference it from endpoints. This keeps authentication behavior consistent and prevents contract drift.
Wrapping up
CLI-based API design turns a click-heavy process into repeatable commands.
The open-source route gives you full control:
spectral lint openapi.yaml
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
openapi-generator-cli generate -i dist/openapi.bundled.yaml -g spring -o ./server
The Apidog CLI route provides an integrated project for schemas, endpoints, authentication, and exports, with structured JSON output for automation. Exported OpenAPI connects that project back to standard linters, generators, and documentation tooling.
Choose the workflow that fits your team. If you already use Git and focused CLI tools, keep that stack and use apidog export when you need a portable artifact. If you want to reduce the glue code between design resources, download Apidog, install the CLI, and design your next API from the terminal.
Top comments (0)