Tutorial

Manage API Keys and JWTs from the Terminal

Generate, store, verify, rotate, and revoke API keys and JWTs with one CLI. AES-256-GCM encrypted keystore, audit trail, smart type detection, and one-command CI/CD export.
May 15, 2026 · 6 min read · Revenue Holdings
Share this article:

If your team is like most teams, your API keys live in a dozen places: .env files shared over Slack, a Google Doc that's six months out of date, hardcoded in test fixtures, and in a CI/CD pipeline that nobody remembers configuring. When a key gets compromised — and it will — you scramble to find everywhere it's used, rotate it manually, and hope nothing breaks.

APIAuth fixes this with a single encrypted local keystore (AES-256-GCM) and a CLI for the full key lifecycle: generate, import, list, verify, rotate, revoke, and export — all from your terminal.

┌─────────────────────────────────────────────────────┐ │ APIAuth Keystore │ │ (~/.apiauth/ — AES-256-GCM) │ │ │ │ generate ──→ keystore ──→ export (CI/CD) │ │ ↓ ↓ ↓ │ │ rotate ──→ verify ──→ revoke │ └─────────────────────────────────────────────────────┘

1. Install APIAuth

$ pip install apiauth

Or from GitHub:

$ pip install git+https://github.com/Coding-Dev-Tools/apiauth.git

Verify:

$ apiauth --help

The first time you run any command, APIAuth creates an encrypted keystore at ~/.apiauth/ with a master key — you're ready to go immediately.

2. Generate an API Key

Create your first key:

$ apiauth generate api-key --name "Gateway Key" --service api-gateway --expiry-days 90

Output:

✓ Key generated
  ID:        ak_8aF3xR7tL9mP2bK5
  Name:      Gateway Key
  Service:   api-gateway
  Created:   2026-05-15
  Expires:   2026-08-13 (90 days)
  Value:     ak_live_v2_x7K9mP2bK5...8aF3xRtL

The generated key is:

💡 Copy the value immediately. APIAuth shows the plaintext key once at creation, then stores only the hash. If you lose it, you'll need to rotate.

Generate a JWT

$ apiauth generate jwt --name "Auth Service JWT" --service auth-service --expiry-days 30 --claim role=admin

3. List and Inspect Keys

See all keys at a glance:

$ apiauth list
╔══════════════════════════════════════════════════════════╗
║                    APIAuth Keystore                      ║
╠══════════════════════════════════════════════════════════╣
║ ID                Name          Service     Expiry      ║
║ ──────────────────────────────────────────────────────── ║
║ ak_8aF3...       Gateway Key   api-gateway 2026-08-13  ║
║ jwt_xR7t...      Auth JWT      auth-svc    2026-06-14  ║
║ ak_L9mP...       Stripe Key    billing     2026-07-22  ║
║ ak_2bK5...       Old Key       api-gateway ⚠ EXPIRED   ║
╚══════════════════════════════════════════════════════════╝

Filter by service:

$ apiauth list --service api-gateway

Inspect a specific key:

$ apiauth show ak_8aF3xR7tL9mP2bK5

4. Verify a Key

When your application receives an API key and needs to check if it's valid, not revoked, and not expired:

$ apiauth verify ak_live_v2_x7K9mP2bK5...8aF3xRtL
✓ Key is valid
  Name:      Gateway Key
  Service:   api-gateway
  Status:    active
  Expires:   2026-08-13 (89 days remaining)

The verify command checks:

5. Rotate a Key

Rotating a key generates a new value and hashes out the old one — one command, no manual coordination:

$ apiauth rotate ak_8aF3xR7tL9mP2bK5
✓ Key rotated
  Old key has been hashed out. New value shown below:
  New value: ak_live_v2_yW4zQ8sT6rN1cV3...hJ2gDfM

  ⚠ Update any services using this key with the new value.

Only the most recent value is retrievable — previous values are cryptographically hashed out, so a compromised old key can't be used even if someone finds it.

6. Revoke a Compromised Key

When a key is compromised, revoke it immediately:

$ apiauth revoke ak_8aF3xR7tL9mP2bK5
✓ Key revoked: Gateway Key (api-gateway)
  This key can no longer be used. All services should be updated.
  Generate a new key with: apiauth generate api-key --service api-gateway

Revoked keys are marked in the keystore and the verify command will reject them. They remain in the audit log for compliance.

7. Export for CI/CD

The most common way keys end up scattered across files is CI/CD configuration. APIAuth exports keys directly to pipeline formats:

$ apiauth export --format github-actions
# Add these to your GitHub Actions secrets
# Service: api-gateway
GATEWAY_API_KEY=ak_live_v2_yW4zQ8sT6rN1cV3...hJ2gDfM
# Service: billing
BILLING_API_KEY=ak_live_v2_pL5kK2jH7gF4dS1...wE9xRtZ

Other export formats:

# Export as dotenv file $ apiauth export --format dotenv --output .env.prod # Export as JSON for deployment tools $ apiauth export --format json # Export as shell exports for Docker $ apiauth export --format shell

For GitHub Actions, add a step to your workflow:

# .github/workflows/deploy.yml
- name: Export API keys
  run: |
    apiauth export --format github-actions --service api-gateway >> $GITHUB_ENV

8. Audit Your Keystore

Run regular audits to find expired, expiring, and revoked keys:

$ apiauth audit
═══ Keystore Audit ═══

Total keys: 12
  Active:     9
  Expired:    2 (rotate or remove)
  Revoked:    1 (verify api-gateway key)
  Expiring:   1 (Stripe Key: 14 days remaining)

Recommendations:
  ⚠ Rotate expired key: ak_2bK5... (api-gateway)
  ⚠ Rotate expiring key: ak_L9mP... (billing)
  🚫 Revoked key present: ak_xR7t... (auth-service) — verify service is updated

Command Reference

CommandDescription
apiauth generate api-keyGenerate a new API key with expiry
apiauth generate jwtGenerate a JWT with custom claims
apiauth listList all keys with expiry status
apiauth show <id>Show key details
apiauth verify <value>Verify a key against stored hashes
apiauth rotate <id>Rotate a key (hashes out old value)
apiauth revoke <id>Revoke a compromised key
apiauth import <value>Import an existing key into keystore
apiauth export --format github-actionsExport keys for CI/CD
apiauth auditFull keystore audit report

Real-World Scenario: Compromised Key Response

A developer accidentally pushed a commit containing a production API key to a public GitHub repo. Within 3 minutes, a bot forked the repo and started using the key. The team lead:

  1. Ran apiauth revoke ak_2bK5... — the compromised key was immediately invalidated
  2. Ran apiauth generate api-key --service api-gateway — a new key was created
  3. Ran apiauth export --format github-actions — the new key was exported to update CI secrets
  4. Verified with apiauth list that the revoked key still appears in the audit trail for compliance

Total time: under 60 seconds. No frantic Slack messages, no searching through .env files, no wondering if the key was rotated everywhere.


Next Steps

APIAuth is the 10th and final tool in the Revenue Holdings suite. Every tool in the suite runs from the terminal and integrates with CI/CD pipelines:

Read the full docs →

Get Notified About New Tutorials

DevOps guides, security tips, and product updates.