DEV Community

Cover image for How to Design APIs From the CLI
Hassann
Hassann

Posted on • Originally published at apidog.com

How to Design APIs From the CLI

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.

Try Apidog today

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:

  1. An open-source CLI stack: author OpenAPI, lint with Spectral, bundle with Redocly CLI, and generate stubs with openapi-generator.
  2. 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]
Enter fullscreen mode Exit fullscreen mode

As the API grows, split schemas and paths into separate files with $ref. For example:

api/
├── openapi.yaml
├── paths/
│   └── orders.yaml
└── schemas/
    └── order.yaml
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Lint your definition:

spectral lint openapi.yaml
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Bundle the specification:

mkdir -p dist
redocly bundle openapi.yaml -o dist/openapi.bundled.yaml
Enter fullscreen mode Exit fullscreen mode

Use the bundled file as the input for generators, documentation builds, and release artifacts.

Redocly can also lint specifications:

redocly lint openapi.yaml
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Generate a Spring server stub:

openapi-generator-cli generate \
  -i dist/openapi.bundled.yaml \
  -g spring \
  -o ./server
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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:

  • schema for data models
  • endpoint for API operations
  • folder for organization
  • security-scheme for authentication
  • import and export for moving between formats
  • mock and 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
Enter fullscreen mode Exit fullscreen mode

Authenticate with an access token:

apidog login --with-token <YOUR_ACCESS_TOKEN>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

2. Define reusable data models

Start with schemas that represent the reusable domain models in your API.

apidog schema create --project <PROJECT_ID>
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

If you already have an OpenAPI definition, import it instead of recreating resources manually:

apidog import --project <PROJECT_ID> --file openapi.yaml
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

Create an endpoint:

apidog endpoint create --project <PROJECT_ID>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Use folder commands to group related endpoints as the project grows:

apidog folder --help
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

List existing schemes:

apidog security-scheme list --project <PROJECT_ID>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Inspect the command options if needed:

apidog cli-schema --help
Enter fullscreen mode Exit fullscreen mode

Use validation as a guard step:

apidog cli-schema validate --file resource.json

# Apply the resource only after validation succeeds.
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Do not treat this as equivalent to:

apidog cli-schema validate --file resource.json
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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)