SSL Clock REST API
Manage monitors and read certificate status from your own scripts. JSON over HTTPS.
Authentication
Create a key in Settings. It is shown once; we store only a hash. Send it as a bearer token:
curl -H "Authorization: Bearer sslc_..." https://www.sslclock.com/api/v1/monitors
Revoke a key in Settings at any time. Keys act on the account they were created in.
Rate limits
Keep to 60 requests per minute per key. Every response carries X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset. Over the limit you may get 429 with Retry-After; back off and retry.
Endpoints
| Method | Path | What it does |
|---|---|---|
| GET | /api/v1/monitors | List monitors with current certificate status. |
| POST | /api/v1/monitors | Add a monitor. Body {"hostname": "example.com", "port": 443}. Port is optional; host:port and URLs work too. Returns 201, 402 over the plan limit, or 409 if it already exists. |
| GET | /api/v1/monitors/{id} | One monitor. |
| GET | /api/v1/monitors/{id}/checks | The last 50 checks. |
| POST | /api/v1/monitors/{id}/check | Run a check now and return the result. |
| DELETE | /api/v1/monitors/{id} | Remove a monitor. Returns 204. |
Monitor object
{
"id": "…", "hostname": "example.com", "port": 443, "paused": false,
"status": "ok" | "problem" | "pending", "error_code": null,
"days_remaining": 41, "valid_from": "…", "valid_to": "…",
"issuer": "R11", "subject": "example.com",
"chain_valid": true, "hostname_match": true,
"last_checked_at": "…", "domain": "example.com", "domain_expires_at": "…",
"created_at": "…"
}
Errors
Errors return {"error": "code", "message": "…"} with codes unauthorized, invalid_json, invalid_hostname, plan_limit, duplicate, not_found and rate_limited.
Signed webhooks
Add a webhook URL in Settings to receive alerts as JSON. Each POST has X-SSLClock-Event and X-SSLClock-Signature: t=<unix seconds>,v1=<hex>, where v1 is HMAC-SHA256 of t + "." + raw body with your signing secret. Reject requests older than five minutes. Events: certificate.expiring, certificate.error, certificate.changed, domain.expiring, ct.new_certificate and test.
// Node.js
const [t, v1] = sig.split(",").map((p) => p.split("=")[1]);
const ok = crypto.timingSafeEqual(
Buffer.from(v1, "hex"),
crypto.createHmac("sha256", secret).update(t + "." + rawBody).digest());