Vendor Definition Format

Purpose

A vendor definition is a YAML file that tells netapi how to talk to an API: where it lives, how to authenticate, how pagination works, and what resources are available. You write the YAML; netapi handles the HTTP, auth, pagination, rate limiting, and output formatting.

No Python code required.

File Location

Vendor definitions live in:

~/.config/netapi/vendors/<name>.yml

Built-in vendors ship inside the netapi package and cannot be edited directly. To override a built-in, create a user definition with the same name — the user definition takes precedence.

Full Schema

This annotated example defines the GitHub API:

# ~/.config/netapi/vendors/github.yml

# Unique identifier — becomes the CLI vendor segment: netapi github ...
name: github

# Base URL — all resource paths are relative to this
base_url: https://api.github.com

# Authentication configuration
auth:
  # Auth type: basic | bearer | api-key | oauth2 | mtls
  type: bearer
  # Environment variable holding the token
  token_env: GITHUB_TOKEN

# Default headers sent with every request
headers:
  Accept: application/vnd.github+json
  X-GitHub-Api-Version: "2022-11-28"

# Pagination strategy
pagination:
  # Type: link-header | offset | cursor | page-param | none
  type: link-header

# Rate limit handling
rate_limit:
  # Response header containing remaining request count
  header: X-RateLimit-Remaining
  # Strategy: backoff | fixed-delay | none
  strategy: backoff

# Resource definitions — each becomes a CLI noun
resources:
  repos:
    list: GET /orgs/{org}/repos
    get: GET /repos/{owner}/{repo}
    create: POST /user/repos
  issues:
    list: GET /repos/{owner}/{repo}/issues
    get: GET /repos/{owner}/{repo}/issues/{number}
    create: POST /repos/{owner}/{repo}/issues
    update: PATCH /repos/{owner}/{repo}/issues/{number}
  pulls:
    list: GET /repos/{owner}/{repo}/pulls
    get: GET /repos/{owner}/{repo}/pulls/{number}
    create: POST /repos/{owner}/{repo}/pulls

Each key under resources becomes a resource noun in the CLI. Each key under a resource (list, get, create, etc.) maps to a standard verb. Path parameters in braces ({org}, {repo}) become required CLI arguments.

Schema Reference

Top-Level Fields

Field Type Required Description

name

string

Yes

Unique vendor identifier. Used as the CLI segment.

base_url

string

Yes

Root URL for all API requests.

auth

object

Yes

Authentication configuration. See Authentication Types.

headers

map

No

Default headers for every request. Merged with per-request headers.

pagination

object

No

How the API paginates collections. See Pagination Types. Defaults to none.

rate_limit

object

No

Rate limit detection and handling. See Rate Limit Strategies. Defaults to none.

resources

map

Yes

Resource definitions. At least one resource with at least one verb.

Authentication Types

Type Configuration Example

basic

username_env + password_env — environment variables holding credentials

auth:
  type: basic
  username_env: ISE_USER
  password_env: ISE_PASS

bearer

token_env — environment variable holding a bearer token

auth:
  type: bearer
  token_env: GITHUB_TOKEN

api-key

key_env + header — the env var and which header to send it in

auth:
  type: api-key
  key_env: CF_API_KEY
  header: X-Auth-Key

oauth2

client_id_env, client_secret_env, token_url — OAuth2 client credentials flow

auth:
  type: oauth2
  client_id_env: OAUTH_CLIENT_ID
  client_secret_env: OAUTH_SECRET
  token_url: https://auth.example.com/token

mtls

cert_path, key_path, ca_path — mutual TLS with client certificate

auth:
  type: mtls
  cert_path: ~/.secrets/certs/client.crt
  key_path: ~/.secrets/certs/client.key
  ca_path: ~/.secrets/certs/ca.crt

Pagination Types

Type Behavior Used By

link-header

Follows RFC 8288 Link header with rel="next".

GitHub, GitLab

offset

Increments an offset query parameter by limit each page.

params: { offset: offset, limit: limit }

cursor

Sends a cursor from the previous response as a query parameter.

cursor_param: after
cursor_path: meta.next_cursor

page-param

Increments a page query parameter.

page_param: page
per_page_param: per_page

none

No pagination. The API returns everything in one response.

Small APIs, count endpoints

Rate Limit Strategies

Strategy Behavior

backoff

When header value reaches 0, sleep with exponential backoff until the reset time (read from reset_header, default X-RateLimit-Reset).

fixed-delay

Insert a fixed delay (delay_ms, default 100) between every request. Useful for APIs without explicit rate limit headers.

none

No rate limit handling. Requests fire as fast as possible.

Validating a Definition

Before using a vendor definition, validate it:

# Syntax check — validates YAML structure and required fields
netapi vendor validate github

# Dry-run test — resolves auth, sends a single GET to base_url
netapi vendor validate github --live

# Show the fully resolved definition (built-in + user overrides merged)
netapi vendor show github --format yaml

Validation checks:

  • YAML parses without errors

  • Required fields (name, base_url, auth, resources) are present

  • Auth type is recognized and referenced env vars exist

  • Pagination type is recognized

  • Every resource has at least one valid verb

  • Path parameters in resource URLs are syntactically correct

Vendor Resolution Order

When you run netapi github repo list, netapi resolves the github vendor through this chain:

  1. --vendor-file flag — If provided, load this file and skip all other sources.

  2. User config — ~/.config/netapi/vendors/github.yml

  3. Built-in — Shipped with the netapi package.

The first match wins. This means a user definition silently overrides the built-in, allowing customization without forking.

To see where a vendor resolved from:

netapi vendor show github --verbose
# Source: ~/.config/netapi/vendors/github.yml (user override)
# Overrides: built-in github vendor

More Examples

Cloudflare DNS

name: cloudflare
base_url: https://api.cloudflare.com/client/v4

auth:
  type: bearer
  token_env: CF_API_TOKEN

pagination:
  type: page-param
  page_param: page
  per_page_param: per_page

rate_limit:
  header: X-RateLimit-Remaining
  strategy: backoff

resources:
  dns:
    list: GET /zones/{zone_id}/dns_records
    get: GET /zones/{zone_id}/dns_records/{id}
    create: POST /zones/{zone_id}/dns_records
    update: PATCH /zones/{zone_id}/dns_records/{id}
    delete: DELETE /zones/{zone_id}/dns_records/{id}
  zones:
    list: GET /zones
    get: GET /zones/{id}

Cisco ISE ERS

name: ise
base_url: https://ise-01.inside.domusdigitalis.dev:9060/ers/config

auth:
  type: basic
  username_env: ISE_ERS_USER
  password_env: ISE_ERS_PASS

headers:
  Accept: application/json
  Content-Type: application/json

pagination:
  type: page-param
  page_param: page
  per_page_param: size

resources:
  endpoint:
    list: GET /endpoint
    get: GET /endpoint/{id}
    create: POST /endpoint
    update: PUT /endpoint/{id}
    delete: DELETE /endpoint/{id}
  identity-group:
    list: GET /identitygroup
    get: GET /identitygroup/{id}
  network-device:
    list: GET /networkdevice
    get: GET /networkdevice/{id}
    create: POST /networkdevice
    update: PUT /networkdevice/{id}
    delete: DELETE /networkdevice/{id}