Working with OpenAPI Specs

OpenAPI (formerly Swagger) specifications are machine-readable descriptions of an API. They list every endpoint, parameter, request body, response schema, and authentication method. When a spec exists, it is the fastest path to understanding an API.

Fetching the spec

Specs live at predictable paths. Try these in order:

# Common OpenAPI 3.x paths
curl -s https://api.example.com/openapi.json | jq 'keys'
curl -s https://api.example.com/api/openapi.json | jq 'keys'
curl -s https://api.example.com/v3/api-docs | jq 'keys'
curl -s https://api.example.com/api/v1/openapi.json | jq 'keys'

# Common Swagger 2.0 paths
curl -s https://api.example.com/swagger.json | jq 'keys'
curl -s https://api.example.com/api/swagger.json | jq 'keys'
curl -s https://api.example.com/v2/api-docs | jq 'keys'

# YAML variants
curl -s https://api.example.com/openapi.yaml
curl -s https://api.example.com/swagger.yaml

If none of these work, check:

  • The API documentation site (often links to the raw spec)

  • GitHub/GitLab repositories (search for openapi.json or swagger.json)

  • The /.well-known/ path

Some APIs require authentication even for the spec:

curl -s https://api.example.com/openapi.json \
  -H "Authorization: Bearer $TOKEN" \
  | jq 'keys'

Exploring with jq

Identify the spec version and basic info

curl -s "$SPEC_URL" | jq '{
  openapi: .openapi,
  swagger: .swagger,
  title: .info.title,
  version: .info.version,
  description: .info.description
}'

List all endpoints

# Every path and its HTTP methods
curl -s "$SPEC_URL" \
  | jq -r '.paths | to_entries[] | .key as $path | .value | keys[] | "\(.) \($path)"' \
  | sort

This produces output like:

DELETE /api/v1/users/{id}
GET    /api/v1/users
GET    /api/v1/users/{id}
POST   /api/v1/users
PUT    /api/v1/users/{id}

Count endpoints by method

curl -s "$SPEC_URL" \
  | jq -r '[.paths | to_entries[] | .value | keys[]] | group_by(.) | map({method: .[0], count: length}) | .[]' \
  | jq -rs 'map("\(.method)\t\(.count)") | .[]' \
  | column -t -s $'\t'

Find authentication schemes

# OpenAPI 3.x
curl -s "$SPEC_URL" | jq '.components.securitySchemes'

# Swagger 2.0
curl -s "$SPEC_URL" | jq '.securityDefinitions'

This tells you whether the API uses Bearer tokens, API keys, Basic auth, OAuth2, or something else — and where each credential goes (header, query, cookie).

Inspect a specific endpoint

# Full definition of a single endpoint
curl -s "$SPEC_URL" | jq '.paths["/api/v1/users/{id}"].get'

# Just the parameters
curl -s "$SPEC_URL" | jq '.paths["/api/v1/users"].get.parameters'

# Response schema for 200
curl -s "$SPEC_URL" | jq '.paths["/api/v1/users"].get.responses["200"].content["application/json"].schema'

Resolve references

OpenAPI specs use $ref to avoid duplicating schemas. jq cannot resolve these natively, but you can follow them manually:

# If a schema says: "$ref": "#/components/schemas/User"
curl -s "$SPEC_URL" | jq '.components.schemas.User'

Search for endpoints by keyword

# Find all endpoints containing "session" in the path
curl -s "$SPEC_URL" \
  | jq -r '.paths | keys[] | select(test("session"; "i"))'

# Find endpoints that accept a specific parameter
curl -s "$SPEC_URL" \
  | jq -r '
    .paths | to_entries[] |
    .key as $path |
    .value | to_entries[] |
    select(.value.parameters[]?.name == "mac_address") |
    "\(.key | ascii_upcase) \($path)"
  '

Tools for deeper exploration

Swagger UI

If the API hosts Swagger UI (often at /docs, /swagger-ui, or /api-docs), open it in a browser for interactive exploration. You can try requests directly.

Redoc

Redoc renders OpenAPI specs as clean, readable documentation:

# Serve a local spec with redoc (requires npx)
npx @redocly/cli preview-docs openapi.json

openapi-generator

Generate client code, documentation, or server stubs from a spec:

# Generate a bash client from a spec
openapi-generator generate -i openapi.json -g bash -o ./generated-client

# List available generators
openapi-generator list

This is useful for understanding an API’s data model — the generated types show you exactly what fields exist and their types.

Converting specs to netapi vendor definitions

Once you understand an API through its spec, you can encode it as a netapi vendor definition. The spec provides:

  • Base URL and path structure

  • Authentication scheme

  • Pagination strategy (look for limit/offset/cursor parameters)

  • Response envelope structure (where the actual data lives)

  • Available operations per resource

# Extract the information netapi needs from a spec
curl -s "$SPEC_URL" | jq '{
  base_url: .servers[0].url,
  auth: .components.securitySchemes,
  endpoints: [.paths | to_entries[] | {
    path: .key,
    methods: (.value | keys)
  }]
}'

This gives you the skeleton. The vendor definition fills in the specifics: how to authenticate, how to paginate, where to find the data in each response.

Real example: exploring an unfamiliar API

Suppose you encounter a new API at api.newvendor.com. A systematic exploration:

# 1. Check for a spec
for path in /openapi.json /swagger.json /v3/api-docs /api/openapi.json; do
  code=$(curl -so /dev/null -w '%{http_code}' "https://api.newvendor.com${path}")
  echo "${code} ${path}"
done

# 2. If found, get the overview
curl -s "https://api.newvendor.com/openapi.json" \
  | jq '{title: .info.title, version: .info.version, endpoints: (.paths | length)}'

# 3. List all endpoints
curl -s "https://api.newvendor.com/openapi.json" \
  | jq -r '.paths | to_entries[] | .key as $p | .value | keys[] | "\(.) \($p)"' \
  | sort

# 4. Check auth requirements
curl -s "https://api.newvendor.com/openapi.json" \
  | jq '.components.securitySchemes'

# 5. Pick an endpoint and inspect its schema
curl -s "https://api.newvendor.com/openapi.json" \
  | jq '.paths["/api/v1/devices"].get'

Within five commands you know: how many endpoints exist, what authentication is required, and what a representative endpoint looks like. That is enough to start building.