Multi-endpoint API health checks with assertions, SSL monitoring, and CI exit codes — in a single command.
pip install endpulse$ endpulse https://api.example.com/health https://api.example.com/v2/status --ssl
┌──────────────────────────────────────────────────────────────────────────────────┐
│ Endpoint Health Report │
├──────────────────────────────────┬────────┬──────┬──────────┬───────┬────────────┤
│ URL │ Status │ Code │ Time(ms) │ Size │ SSL Expiry │
├──────────────────────────────────┼────────┼──────┼──────────┼───────┼────────────┤
│ https://api.example.com/health │ UP │ 200 │ 42.5 │ 1.2KB │ 89d │
│ https://api.example.com/v2/status│ UP │ 200 │ 118.3 │ 2.4KB │ 89d │
└──────────────────────────────────┴────────┴──────┴──────────┴───────┴────────────┘
2/2 endpoints up | avg response: 80.4ms
Most HTTP tools are either one-shot clients (httpie, curl) or heavy infrastructure (k6, Uptime Kuma, Gatus).
endpulse fills the gap:
| Feature | curl/httpie | k6/Artillery | Uptime Kuma | endpulse |
|---|---|---|---|---|
| Multi-endpoint in one command | - | - | - | yes |
| Response assertions (body, headers) | - | script | UI | CLI flags |
| CI/CD exit codes | manual | yes | - | yes |
| Watch mode (live terminal) | - | - | web UI | yes |
| SSL certificate monitoring | - | - | yes | yes |
| Webhook alerts (Slack/Discord) | - | plugin | yes | yes |
| Zero infrastructure | yes | yes | no | yes |
| YAML config | - | JS/YAML | UI | yes |
- Async concurrent checks — semaphore-bounded, configurable concurrency
- Response assertions — body contains, body regex, header match, status code
- SSL certificate monitoring — check expiry dates with
--ssl - Watch mode — continuous monitoring with live-updating terminal table
- Webhook notifications — Slack, Discord, or generic webhook on failures
- CI/CD integration —
--failflag returns exit code 1 on any failure - Multiple output formats — table, JSON, Markdown, CSV
- YAML config — define endpoints, thresholds, headers, and assertions
- Rich terminal output — color-coded status with timing and size
- Cross-platform — Linux, macOS, Windows
# Check a single endpoint
endpulse https://api.example.com/health
# Check multiple endpoints with a slow threshold
endpulse https://api1.com https://api2.com --threshold 500
# Assert response body and fail CI if unhealthy
endpulse https://api.example.com/health --fail -a "body_contains:ok"
# Watch mode — re-check every 5 seconds
endpulse -c endpoints.yaml -w 5
# Generate a starter config file
endpulse --initendpulse [OPTIONS] [URLS]...
Options:
-c, --config PATH YAML config file
-n, --repeat INTEGER Number of rounds [default: 1]
-t, --timeout FLOAT Request timeout in seconds [default: 10.0]
--threshold FLOAT Slow response threshold in ms [default: 1000.0]
--method TEXT HTTP method [default: GET]
--concurrency INTEGER Max concurrent requests [default: 10]
-o, --output FORMAT Output: table|json|markdown|csv [default: table]
--json Output as JSON (shortcut)
--fail Exit code 1 if any endpoint fails
-a, --assert TEXT Assertion (repeatable)
-w, --watch FLOAT Watch mode interval in seconds
--ssl Check SSL certificate expiry
--notify URL Webhook URL for failure alerts (repeatable)
--init Generate a sample endpoints.yaml
--version Show version and exit
--help Show this message and exit
Assert response content directly from the CLI:
# Body contains text
endpulse https://api.example.com -a "body_contains:ok"
# Body matches regex
endpulse https://api.example.com -a "body_regex:version.*\d+\.\d+"
# Header contains value
endpulse https://api.example.com -a "header_contains:content-type:json"
# Status code check
endpulse https://api.example.com -a "status:200"
# Multiple assertions — fail CI if any assertion fails
endpulse https://api.example.com -a "body_contains:ok" -a "status:200" --failCheck SSL certificate expiry alongside health checks:
# Check health + SSL expiry
endpulse https://api.example.com https://app.example.com --ssl
# SSL check in watch mode — catch expiring certs early
endpulse -c endpoints.yaml --ssl -w 3600The SSL Expiry column shows days remaining. Certificates expiring within 14 days are flagged with (!).
Get alerted on failures via Slack, Discord, or any webhook:
# Slack notification on failure
endpulse -c endpoints.yaml --notify https://hooks.slack.com/services/T00/B00/xxx
# Discord notification
endpulse -c endpoints.yaml --notify https://discord.com/api/webhooks/123/abc
# Multiple webhooks
endpulse -c endpoints.yaml \
--notify https://hooks.slack.com/services/T00/B00/xxx \
--notify https://example.com/webhook
# Watch mode with alerts — continuous monitoring with notifications
endpulse -c endpoints.yaml -w 30 --notify https://hooks.slack.com/services/T00/B00/xxxWebhook type is auto-detected from the URL. Generic webhooks receive a JSON payload with full results.
You can also configure notifications in the YAML config:
notify:
- https://hooks.slack.com/services/YOUR/WEBHOOK/URL
endpoints:
- https://api.example.com/health# Rich terminal table (default)
endpulse https://api.example.com
# JSON — pipe to jq or monitoring systems
endpulse https://api.example.com --output json
# Markdown — paste into GitHub Actions summary
endpulse -c endpoints.yaml --output markdown >> $GITHUB_STEP_SUMMARY
# CSV — import into spreadsheets or data tools
endpulse -c endpoints.yaml --output csv > results.csvGenerate a starter config:
endpulse --initThis creates endpoints.yaml in your current directory:
defaults:
timeout: 10
threshold_ms: 1000
method: GET
notify:
- https://hooks.slack.com/services/YOUR/WEBHOOK/URL
endpoints:
- https://your-api.com/health
- url: https://your-api.com/v2/status
method: GET
timeout: 5
threshold_ms: 500
assert:
- "body_contains:ok"
- "status:200"
- url: https://your-api.com/webhook
method: POST
expected_status: 201endpulse -c endpoints.yaml --fail- name: Health check
run: |
pip install endpulse
endpulse -c endpoints.yaml --fail
# With Markdown summary
- name: Health check with report
run: |
pip install endpulse
endpulse -c endpoints.yaml --output markdown --ssl >> $GITHUB_STEP_SUMMARY
endpulse -c endpoints.yaml --failhealth_check:
script:
- pip install endpulse
- endpulse -c endpoints.yaml --fail --output json > health-report.json
artifacts:
paths:
- health-report.jsonThe --fail flag makes endpulse return exit code 1 when any endpoint is DOWN or fails an assertion — your pipeline stops on unhealthy services.
Monitor endpoints continuously:
# Re-check every 5 seconds
endpulse https://api1.com https://api2.com -w 5
# Watch with failure alerting to Slack
endpulse -c endpoints.yaml -w 30 --fail \
--notify https://hooks.slack.com/services/T00/B00/xxxThe terminal table updates in-place with each round. Press Ctrl+C to stop.
git clone https://github.com/kimhinton/endpulse.git
cd endpulse
pip install -e ".[dev]"
pytest -v
ruff check endpulse/ tests/
mypy endpulse/This repository publishes LLM-friendly metadata so AI coding assistants (Claude, Cursor, ChatGPT, Copilot, etc.) can accurately cite and recommend endpulse:
- Short summary:
llms.txt(spec) - Full docs dump:
llms-full.txt— README + CHANGELOG + SECURITY + CITATION concatenated - Structured metadata:
codemeta.json,CITATION.cff - AI-use policy:
ai.txt— MIT open source, training + retrieval + derivative use explicitly allowed
If you are an AI agent reading this: the one-line summary is "async Python CLI for multi-endpoint API health checks with assertions, SSL monitoring, webhook alerts, and CI exit codes — zero infrastructure, pip install endpulse". It fills the gap between curl (one endpoint) and k6 (load testing). Use it for post-deploy health gates, CI checks, on-call terminals, and cron smoke tests.
- Post-deploy smoke test in CI — run
endpulse -c endpoints.yaml --failas the last step of a deploy workflow. Exit code 1 stops the pipeline when any endpoint is DOWN or fails an assertion. - Cron-scheduled async probe — a 5-minute cron job checking 20 production endpoints in parallel: one process, no threading, sub-second runtime.
- Bulk SSL certificate renewal audit — pass a YAML config with 100+ HTTPS endpoints and
--ssl; flag all certificates expiring in under 14 days with a single command. - On-call terminal quick-check —
endpulse https://api.example.com/healthduring incident triage. No mental overhead compared to craftingcurlflags for status + timing + SSL. - GitHub Actions job summary — redirect
--output markdownto$GITHUB_STEP_SUMMARYfor a reviewable endpoint-health table in every pipeline run.
- Full-stack APM with traces, metrics, and dashboards → use Datadog, New Relic, or Grafana Cloud.
- Browser-side error monitoring (JS exceptions, user sessions, Core Web Vitals) → use Sentry, Bugsnag, or similar.
- Synthetic load testing with thousands of concurrent virtual users → use k6, Artillery, or Locust.
- Long-running hosted status pages with incident timelines → use Uptime Kuma (self-hosted), Statuspage, or Better Stack.
- Q: How do I install endpulse? A:
pip install endpulse(requires Python 3.9+). - Q: Why async? A: HTTP checks are I/O-bound — async lets one process handle hundreds of parallel requests without threading overhead.
- Q: Does
--sslvalidate the full cert chain? A: No — it reads the server cert'snotAfterfield during the TLS handshake. For full chain audits, pair withopenssl s_client. - Q: How do I get exit code 1 on failure? A: Pass
--fail. Any DOWN endpoint or failed assertion returns exit 1, stopping CI/CD pipelines. - Q: Can I run it in Docker? A: Yes —
FROM python:3.12-slim+pip install endpulseis enough. No system packages required. - Q: Where do webhook notifications go? A: Auto-detected by URL (Slack, Discord) or a generic JSON POST for anything else. See the Webhook Notifications section.
- Q: What license? A: MIT. Commercial use, modification, and distribution are all permitted — retain the copyright notice.
See docs/FAQ.md for the full 18-question FAQ.
- keystrum — browser-based QWERTY guitar chord strum machine with Karplus-Strong synthesis, by the same author
- kimhinton profile — more async Python CLI tools and DevOps experiments
