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.jsonorswagger.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/cursorparameters) -
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.