SSL Monitoring API: Cert Expiry, Issuer & Chain (2026)
An SSL monitoring API is the difference between knowing a certificate expires next Tuesday and finding out from a customer ticket at 3 AM. The job is small but unforgiving: every public TLS cert your organization owns needs an expiry date that is somewhere in the future, an issuer that is still trusted, a chain that resolves cleanly on every client, and a key that meets your security baseline.
Doing this with openssl s_client works for one server. Doing it for fifty domains, in five regions, on a daily cron, while also alerting Slack and gating CI deploys, needs structured JSON over HTTP. That is what an SSL monitoring API gives you.
This guide walks through what an SSL monitoring API should return, how the DetectZeStack /certificate/check endpoint is shaped, and three patterns for wiring it into real workflows: daily expiry alerts, CI/CD TLS gates, and bulk monitoring across hundreds of domains.
Why You Need an SSL Monitoring API in 2026
Three things changed about certificate operations in the last few years, and they make API-driven monitoring not optional.
Certificate lifetimes are shrinking. Let's Encrypt has always issued 90-day certs. The CA/Browser Forum has been steadily ratcheting maximum lifetimes downward, and most public CAs now issue 397-day certs as the ceiling. Shorter validity means more renewals, more automation, and more opportunities for a renewal to silently fail. The window between "all green" and "expired in production" can be a single missed cron run.
Multi-SAN deployments are normal. A single certificate often covers app.example.com, api.example.com, www.example.com, and a wildcard for staging. When the SAN list changes, you want to detect it. Manual tracking does not scale; only an API call that returns san_domains as a parsable array does.
Trust stores update without your knowledge. Browsers and OS vendors distrust CAs periodically. A certificate that was valid yesterday can be untrusted on iOS tomorrow if the issuing intermediate gets pulled. An API that returns the full chain lets you check whether every intermediate is still trusted, before users see a connection error.
What an SSL Monitoring API Should Return
The minimum useful response from an SSL monitoring API is structured JSON that answers four questions: when does it expire, who issued it, what does it cover, and is the chain complete. Anything less than that and you are still going to shell out to OpenSSL when something goes wrong.
Expiry, Issuer, Subject, and SAN Coverage
The four fields you will read on every check:
certificate.not_after— the expiry timestamp as ISO 8601. Convert to seconds and you can build any threshold logic you want.certificate.days_remaining— pre-computed integer. Saves you a date-math round trip in shell scripts.certificate.issuer— the CA's organization name and common name. Useful for fleet-wide audits ("are all our certs issued by the same CA").certificate.san_domains— the SAN list as a JSON array. The first time someone removes a SAN entry by accident, an automated diff catches it before customers do.
Chain Validation and Intermediate Certs
The leaf certificate is rarely the whole story. Browsers and clients need the intermediate certificates too, and if your server is misconfigured to omit them, the connection fails in unpredictable ways. A monitoring API should return the chain so you can verify it without a second tool. Look for an array where each entry has at least subject, issuer, not_after, and an is_ca boolean.
Key Algorithm, Bit Length, and Signature Strength
If your security policy says "no RSA below 2048 bits" or "ECDSA preferred for all customer-facing endpoints," you need public_key.algorithm and public_key.bit_length in the response. Same for signature_algorithm: SHA-1 has been deprecated for years, but legacy renewals still happen.
DetectZeStack SSL Monitoring API: Endpoint and Fields
DetectZeStack's GET /certificate/check endpoint performs a live TLS handshake on port 443 and returns the certificate, the chain, and the TLS connection details as a single JSON payload. It is part of the same API surface that handles tech stack detection, DNS intelligence, and security headers, so the same RapidAPI key works for all of them and they share one monthly quota.
Live curl Example Against /demo/certificate
You can try the endpoint without an API key against the demo URL. This is the same handler as the production endpoint, just unauthenticated and rate-limited per IP:
curl -s "https://detectzestack.com/demo/certificate?url=github.com" | python3 -m json.tool
For production use, get a free RapidAPI key (no credit card needed) and call the authenticated endpoint:
curl -s "https://detectzestack.p.rapidapi.com/certificate/check?url=github.com" \
-H "x-rapidapi-key: YOUR_API_KEY" \
-H "x-rapidapi-host: detectzestack.p.rapidapi.com" | python3 -m json.tool
A truncated response looks like this:
{
"domain": "github.com",
"ip": "140.82.121.3",
"port": 443,
"has_tls": true,
"tls": {
"version": "TLS 1.3",
"cipher_suite": "TLS_AES_128_GCM_SHA256",
"negotiated_protocol": "h2"
},
"certificate": {
"subject": {
"common_name": "github.com",
"organization": ["GitHub, Inc."]
},
"issuer": {
"common_name": "Sectigo ECC Domain Validation Secure Server CA",
"organization": ["Sectigo Limited"]
},
"not_before": "2026-02-26T00:00:00Z",
"not_after": "2027-02-26T23:59:59Z",
"days_remaining": 266,
"is_expired": false,
"signature_algorithm": "ECDSA-SHA384",
"public_key": {
"algorithm": "ECDSA",
"bit_length": 256
},
"san_domains": ["github.com", "www.github.com"],
"key_usage": ["Digital Signature"],
"ext_key_usage": ["Server Authentication", "Client Authentication"]
},
"chain": [
{
"subject": "Sectigo ECC Domain Validation Secure Server CA",
"issuer": "USERTrust ECC Certification Authority",
"is_ca": true,
"not_after": "2030-12-31T23:59:59Z",
"signature_algorithm": "ECDSA-SHA384"
}
],
"response_ms": 187
}
Field-by-Field Breakdown of the JSON Response
| Field | Type | Purpose |
|---|---|---|
domain |
string | Domain that was checked |
ip |
string | Resolved IP for the TLS connection |
has_tls |
boolean | Whether the handshake succeeded at all |
tls.version |
string | Negotiated version: TLS 1.0, 1.1, 1.2, or 1.3 |
tls.cipher_suite |
string | Negotiated cipher (e.g. TLS_AES_128_GCM_SHA256) |
certificate.days_remaining |
integer | Days until not_after |
certificate.is_expired |
boolean | True if now > not_after |
certificate.san_domains |
string[] | Subject Alternative Names (DNS) |
certificate.public_key.algorithm |
string | RSA, ECDSA, or Ed25519 |
certificate.public_key.bit_length |
integer | Key size in bits |
chain |
array | Intermediate and root certs in the path |
response_ms |
integer | Handshake time in milliseconds |
One quota, many endpoints. The same API key works for /certificate/check, /analyze (tech detection), /dns (DNS intelligence), and /security (headers). One $9/month plan covers daily SSL checks on roughly 33 domains alongside any other monitoring you want.
Building a Cert Expiry Alerting Workflow
The simplest production use case: run a daily cron, hit /certificate/check for each domain you care about, and post a Slack message when days_remaining drops below a threshold.
Cron + days_remaining Threshold Pattern
The pattern is three nested decisions: hard-fail if the cert is already expired, warn at 30 days, log at 60. You can tune the thresholds to your renewal cadence.
#!/bin/bash
# ssl-monitor.sh — run from cron, e.g. 0 8 * * *
set -euo pipefail
DOMAINS=("app.example.com" "api.example.com" "billing.example.com")
API_KEY="${RAPIDAPI_KEY:?set RAPIDAPI_KEY}"
SLACK_WEBHOOK="${SLACK_WEBHOOK:?set SLACK_WEBHOOK}"
for domain in "${DOMAINS[@]}"; do
RESULT=$(curl -fsS "https://detectzestack.p.rapidapi.com/certificate/check?url=$domain" \
-H "x-rapidapi-key: $API_KEY" \
-H "x-rapidapi-host: detectzestack.p.rapidapi.com")
DAYS=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['certificate']['days_remaining'])")
EXPIRED=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['certificate']['is_expired'])")
ISSUER=$(echo "$RESULT" | python3 -c "import sys,json; print(json.load(sys.stdin)['certificate']['issuer'].get('common_name','?'))")
if [[ "$EXPIRED" == "True" ]]; then
MSG=":rotating_light: CRITICAL: $domain SSL cert is EXPIRED (issuer: $ISSUER)"
elif [[ "$DAYS" -lt 14 ]]; then
MSG=":warning: URGENT: $domain expires in $DAYS days (issuer: $ISSUER)"
elif [[ "$DAYS" -lt 30 ]]; then
MSG=":bell: Reminder: $domain expires in $DAYS days"
else
continue
fi
curl -fsS -X POST "$SLACK_WEBHOOK" \
-H "Content-Type: application/json" \
-d "{\"text\":\"$MSG\"}"
done
Wiring Alerts to Slack or Email
The script above posts to a Slack incoming webhook, but the JSON shape is portable. Pipe the same fields into PagerDuty's Events API, send them through SendGrid for email, or push them into a Datadog metric. The point is that days_remaining as a typed integer means you write the alert logic once and never parse a date string again.
Auditing the Certificate Chain for Trust Issues
Expiry is the headline metric, but chain misconfiguration is the silent killer. A server can serve a leaf certificate that is technically valid, while omitting the intermediate the client needs to build a trust path. Some clients (modern browsers) will compensate by fetching the intermediate themselves; others (older Java, some embedded devices, some mobile clients) will just fail.
The chain array in the response is how you catch this. A correctly configured server returns at least one intermediate; if the array has only the leaf, your server is incomplete. You can audit this in Python:
import requests
API_KEY = "your-rapidapi-key"
DOMAINS = ["app.example.com", "api.example.com", "cdn.example.com"]
headers = {
"x-rapidapi-key": API_KEY,
"x-rapidapi-host": "detectzestack.p.rapidapi.com",
}
for domain in DOMAINS:
r = requests.get(
f"https://detectzestack.p.rapidapi.com/certificate/check?url={domain}",
headers=headers,
timeout=15,
)
data = r.json()
chain = data.get("chain", [])
cert = data.get("certificate", {})
issues = []
if not chain:
issues.append("chain is empty (no intermediates served)")
for link in chain:
if "SHA1" in link.get("signature_algorithm", "").upper():
issues.append(f"intermediate uses SHA-1: {link['subject']}")
if cert.get("public_key", {}).get("algorithm") == "RSA" and cert.get("public_key", {}).get("bit_length", 0) < 2048:
issues.append("RSA key below 2048 bits")
status = "PASS" if not issues else "FAIL"
print(f"{domain:30s} {status}")
for i in issues:
print(f" - {i}")
This catches three of the most common chain problems: missing intermediates, deprecated signature algorithms, and weak keys. Add SAN-coverage checks (every domain you expect should appear in san_domains) and you have a fleet-wide policy audit in 30 lines of code.
Bulk Monitoring with /analyze/batch
For one-off cert sweeps across a list of domains, the authenticated POST /analyze/batch endpoint accepts an array of URLs and runs detection in parallel. It is designed for tech stack scans, but the same batch model works if you want a single round-trip for tech and TLS data together.
If you specifically want certificate-only data at high volume, the cleanest pattern is just a loop of /certificate/check calls with reasonable concurrency:
import concurrent.futures
import requests
API_KEY = "your-rapidapi-key"
DOMAINS = open("domains.txt").read().splitlines()
headers = {
"x-rapidapi-key": API_KEY,
"x-rapidapi-host": "detectzestack.p.rapidapi.com",
}
def check(domain):
r = requests.get(
f"https://detectzestack.p.rapidapi.com/certificate/check?url={domain}",
headers=headers, timeout=15,
)
d = r.json()
cert = d.get("certificate", {})
return {
"domain": domain,
"days": cert.get("days_remaining", -1),
"expired": cert.get("is_expired", True),
"issuer": cert.get("issuer", {}).get("common_name", "?"),
"tls": d.get("tls", {}).get("version", "none"),
}
with concurrent.futures.ThreadPoolExecutor(max_workers=8) as pool:
rows = list(pool.map(check, DOMAINS))
rows.sort(key=lambda r: r["days"])
print(f"{'Domain':35s} {'Days':>5s} {'TLS':>8s} Issuer")
for r in rows:
flag = "EXPIRED" if r["expired"] else str(r["days"])
print(f"{r['domain']:35s} {flag:>5s} {r['tls']:>8s} {r['issuer']}")
Eight workers against a 500-domain list completes in roughly two minutes. At the Ultra tier (10,000 requests for $29/month), you can run that same sweep daily for the entire month and still have headroom for other endpoints.
Pricing and Rate Limits vs Standalone SSL Monitors
| Plan | Requests/mo | Price | Daily SSL Checks On |
|---|---|---|---|
| Basic (Free) | 100 | $0 | ~3 domains |
| Pro | 1,000 | $9 | ~33 domains |
| Ultra | 10,000 | $29 | ~333 domains |
| Mega | 50,000 | $79 | ~1,666 domains |
Standalone SSL monitors (KeyChest, SSLMate Cert Spotter, Updown.io) give you dashboards and built-in alerting out of the box. The DetectZeStack approach trades dashboards for API flexibility: you write the alerting in your own toolchain, and you get tech detection, DNS, security headers, and CPE-based vulnerability data on the same key. For teams that already run their own monitoring (Datadog, Grafana, PagerDuty, n8n, Zapier), API-first is usually less work in the long run.
Get Your API Key and Start Monitoring
The free tier covers daily SSL checks on three domains with no credit card. The Pro tier at $9/month covers 33 domains daily, which is enough for most early-stage SaaS deployments. Sign up on RapidAPI, paste the key into the curl example above, and you have a working SSL monitoring pipeline in under five minutes.
Conclusion
Certificate monitoring is a solved problem; the only question is whether you have wired up the solution. An SSL monitoring API gives you structured data over a single HTTP request, which means you can build the alerting that fits your team rather than adapting to someone else's dashboard. The DetectZeStack /certificate/check endpoint returns expiry, issuer, chain, SANs, key algorithm, and TLS version in one JSON response, and the same API key handles tech stack detection, DNS, and security headers on the same quota. That combination is what makes "monitor every cert across the org" something you actually finish, not something on a quarterly roadmap.
Related Reading
- SSL Certificate Check API for DevOps Teams — The DevOps-focused walkthrough with CI/CD examples
- DNS Intelligence API: SPF, DKIM, DMARC — Pair certificate monitoring with DNS/email-auth checks
- DNS & TLS Detection vs Browser Extensions — Why server-side detection catches what browser extensions miss
- Automate Security Audits with an API — Combine cert, headers, and tech checks into one workflow
- Batch Scan 1000 Websites — Patterns for high-volume scanning across domain lists
Start Monitoring SSL Certificates Today
Free tier: 100 requests/month, no credit card. Structured JSON for expiry, chain, SANs, and TLS version on every check.
Get your free API key