Lightweight API endpoint smoke-test CLI — no OpenAPI spec required.
Point api-probe at any HTTP endpoint and assert status codes, JSON keys, response times, and content-types — from the command line or a simple JSON config file. Zero boilerplate. Works anywhere Node.js runs.
- Zero config required — pass a URL and go
- Status code assertions — confirm your endpoints return exactly what you expect
- JSON key assertions — verify response body fields using dot-notation (e.g.
address.city) - Response time thresholds — fail if a probe exceeds your latency budget
- Content-Type verification — ensure endpoints return the correct media type
- Custom request headers — pass auth tokens, API keys, or any header
- POST/PUT/PATCH support — send request bodies for non-GET endpoints
- Config file support — define multi-endpoint suites in
.probe.json - Fail-fast mode — stop immediately after the first failure in CI
- Verbose mode — print response body excerpts for debugging
- CI/CD ready — exits with code
1on any failure,0on all-pass - No dependencies beyond chalk + commander — fast to install, lightweight in CI
Run without installing (npx):
npx api-probe https://api.example.com/healthInstall globally:
npm install -g api-probe
api-probe https://api.example.com/healthInstall as a local dev dependency (recommended for CI/CD):
npm install --save-dev api-probe
npx api-probe --config .probe.json1. Smoke-test a single endpoint:
api-probe https://jsonplaceholder.typicode.com/todos/12. Assert JSON keys are present in the response:
api-probe -k id -k title -k completed https://jsonplaceholder.typicode.com/todos/13. Full assertion suite — status, keys, content-type, timeout, and auth header:
api-probe \
--status 200 \
--key id \
--key address.city \
--content-type application/json \
--timeout 2000 \
--header "Authorization: Bearer $API_TOKEN" \
https://api.example.com/users/1Usage: api-probe [options] [urls...]
Arguments:
urls API endpoint URLs to probe
Options:
-V, --version output the version number
-c, --config <file> path to .probe.json config file (default: ".probe.json")
-s, --status <code> expected HTTP status code (default: "200")
-k, --key <key> assert JSON response contains this key (dot-notation, repeatable)
-t, --timeout <ms> max response time threshold in milliseconds (default: "5000")
-H, --header <header> add request header "Key: Value" (repeatable)
--content-type <type> assert that Content-Type header contains this string
--method <method> HTTP method to use (default: "GET")
--body <body> request body (use with --method POST/PUT)
--fail-fast exit immediately after first failing probe
--verbose print response body excerpt on each probe
-h, --help display help for command
| Flag | Description | Example |
|---|---|---|
-s, --status |
Expected HTTP status code | --status 201 |
-k, --key |
Assert JSON key exists (repeatable, dot-notation) | -k id -k user.email |
-t, --timeout |
Response time limit in ms (also used as abort timeout) | --timeout 3000 |
-H, --header |
Custom request header (repeatable) | -H "Authorization: Bearer token" |
--content-type |
Assert Content-Type header contains string | --content-type application/json |
--method |
HTTP method | --method POST |
--body |
Raw request body string | --body '{"name":"test"}' |
--fail-fast |
Stop after first failed probe | --fail-fast |
--verbose |
Show response body excerpt (first 300 chars) | --verbose |
-c, --config |
Path to config file | --config ./probes/.probe.json |
For multi-endpoint test suites, define probes in a .probe.json file and run api-probe with no URL arguments (it auto-discovers .probe.json in the current directory, or use --config <path>).
{
"probes": [
{
"name": "Health Check",
"url": "https://api.example.com/health",
"status": 200,
"timeout": 3000,
"keys": ["status", "version"]
},
{
"name": "Auth - Get User",
"url": "https://api.example.com/users/me",
"status": 200,
"timeout": 5000,
"keys": ["id", "email", "roles"],
"contentType": "application/json",
"headers": {
"Authorization": "Bearer YOUR_TOKEN_HERE"
}
},
{
"name": "Create Resource",
"url": "https://api.example.com/items",
"method": "POST",
"status": 201,
"timeout": 5000,
"headers": {
"Content-Type": "application/json",
"Authorization": "Bearer YOUR_TOKEN_HERE"
},
"body": "{\"name\": \"Test Item\", \"active\": true}",
"keys": ["id", "name"]
},
{
"name": "Expect 404 on Missing Resource",
"url": "https://api.example.com/items/does-not-exist",
"status": 404,
"timeout": 3000
}
]
}| Field | Type | Required | Description |
|---|---|---|---|
name |
string | No | Human-readable label for this probe |
url |
string | Yes | Full URL to probe |
method |
string | No | HTTP method (default: "GET") |
status |
number | No | Expected status code (default: 200) |
timeout |
number | No | Max response time in ms (default: 5000) |
keys |
string[] | No | JSON body keys to assert exist (dot-notation) |
contentType |
string | No | Assert Content-Type header contains this string |
headers |
object | No | Key-value map of request headers |
body |
string | No | Raw request body string |
name: API Smoke Tests
on:
push:
branches: [main]
pull_request:
branches: [main]
schedule:
# Run every 15 minutes as a production health monitor
- cron: '*/15 * * * *'
jobs:
smoke-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install api-probe
run: npm install -g api-probe
- name: Run API smoke tests
run: api-probe --config .probe.json --fail-fast
env:
# If your probes use environment variables in headers,
# inject secrets here and reference them in your probe config
API_TOKEN: ${{ secrets.API_TOKEN }}Add to your package.json:
{
"scripts": {
"smoke": "api-probe --config .probe.json",
"smoke:fast": "api-probe --config .probe.json --fail-fast"
}
}Then run:
npm run smokeAdd to .git/hooks/pre-push or your deployment pipeline:
#!/bin/bash
echo "Running API smoke tests before deploy..."
npx api-probe --config .probe.json --fail-fast
if [ $? -ne 0 ]; then
echo "Smoke tests failed. Aborting deploy."
exit 1
fi| Code | Meaning |
|---|---|
0 |
All probes passed |
1 |
One or more probes failed |
1 |
Config file not found or unparseable |
1 |
No URLs provided and no config file found |
This makes api-probe a first-class CI/CD citizen — any standard pipeline runner treats exit code 1 as a build failure.
| Tool | What it needs | What api-probe needs |
|---|---|---|
| Postman / Newman | Full collection files, Postman install | Just a URL |
| Dredd | Full OpenAPI/Swagger spec | Just a URL |
| k6 | JavaScript test scripts | Just a URL |
| curl + bash | Shell scripting, manual parsing | Just a URL |
| api-probe | Nothing — or a simple .probe.json |
Just a URL |
api-probe is designed for the gap between "I want to check this endpoint works" and "I want to write a full test suite." It's the 80/20 tool: covers most smoke-testing needs with almost zero setup, and gets out of the way when you need something more sophisticated.
When to use api-probe:
- Health checks in CI/CD after deploy
- Verifying staging environments match expected contracts
- Quickly testing third-party API endpoints during development
- Sanity-checking that breaking changes haven't silently broken production routes
- Running on a schedule as a lightweight uptime monitor
When to use something else:
- You need load testing (use k6, artillery)
- You need full contract testing against an OpenAPI spec (use Dredd, Schemathesis)
- You need a visual test runner (use Postman)
Contributions are welcome. Please open an issue first to discuss proposed changes.
- Fork the repository
- Create a feature branch:
git checkout -b feat/your-feature - Make your changes and add tests to
test/basic.test.js - Run tests:
node test/basic.test.js - Submit a pull request
Repository: https://github.com/yonderzenith/api-probe
MIT — see LICENSE for details.
If api-probe saves you time, consider sponsoring continued development: