API
The API returns what the Certificates and Sentinels screens show, as JSON, for tools such as Nagios, Icinga, Centreon or Zabbix. It is read-only and included in every plan, Free included.
Create a token
Section titled “Create a token”Owners manage tokens in Settings → API. Select Create token, give it the name of the tool that will use it, and pick an expiration: none, 30 days, 90 days or 1 year.
The token is shown once. Store it in your monitoring tool or secret manager before you close the dialog; if you lose it, revoke it and create another.
A token belongs to the organization, not to the person who created it, so it keeps working after that person leaves. It reads the whole organization, Sentinels included, whatever viewer scopes you set on members. Every owner receives an email when a token is created. An organization holds up to 10 tokens and can create 10 per hour.
Last used in the token list is updated at most every five minutes. Revoking a token, or reaching its expiration date, makes every call with it fail at once.
Authenticate
Section titled “Authenticate”Send the token in the Authorization header. A token placed in the query string is ignored.
curl -H "Authorization: Bearer $NOCERT_TOKEN" https://app.nocert.io/api/v1/summaryThe API is meant for checks that run every few minutes, and the limits are shared by all the tokens of an organization:
- a burst of up to 60 requests, then one request every 10 seconds on average, which is 6 per minute;
- at most 4 requests in progress at once.
A burst covers paging through 6,000 certificates. Above a limit, the API answers 429 Too Many Requests with a Retry-After header giving the seconds to wait.
Requests carry no body, and every query parameter must be one the endpoint documents: an unknown, repeated or badly encoded parameter is refused with 400, so a typo cannot silently fall back to a default.
GET /api/v1/summary
Section titled “GET /api/v1/summary”The numbers a monitoring check alerts on, in one call.
| Parameter | Description |
|---|---|
expiring_within_days |
Horizon of the expiring counter, 1 to 365. Optional, default 30. |
{ "generated_at": "2026-10-18T16:00:00Z", "certificates": { "total": 120, "expired": 1, "expiring": 4, "expiring_within_days": 30, "chain_issues": 2, "next_expiry": { "fingerprint": "3f1c…", "name": "www.example.com", "not_after": "2026-10-30T12:00:00Z", "days_remaining": 12, "url": "https://app.nocert.io/certificates/3f1c…" } }, "sentinels": { "online": 3, "stale": 0, "offline": 1, "never_seen": 0 }}The certificates counted are the leaf certificates of the Active tab of Certificates: excluded certificates never appear, and a certificate replaced or no longer seen on your network leaves the counts. Every counter is computed at generated_at.
totalcounts every one of them, muted ones included. It is not your billed count. The other counters leave out muted certificates, so what you silenced in NoCert does not page you elsewhere. A certificate can be in several counters.expiredcounts certificates whosenot_afteris beforegenerated_at, however long ago.expiringcounts certificates not expired yet whosedays_remainingis between 0 andexpiring_within_days, both included. Certificates valid for seven days or less are left out: they renew automatically and are always about to expire. One of them that does expire still counts inexpired.next_expiryis the soonest of the certificatesexpiringwould count, with no horizon. It isnullwhen there is none. A check can comparedays_remainingwith its own warning and critical thresholds in a single call.chain_issuescounts invalid or incomplete chains and chains ending at a root that browsers have distrusted.days_remainingcounts whole UTC days, as the app does: 0 means the certificate expires today, or already did earlier today. Useexpiredornot_afterto tell the two apart.- A Sentinel is
onlinewhen it reported in the last 7 minutes,staleup to 30 minutes,offlinebeyond that or when it is disabled, andnever_seenwhen it enrolled but never reported. A Sentinel paused by your plan keeps reporting and staysonline.
GET /api/v1/certificates
Section titled “GET /api/v1/certificates”The same certificates, 100 per page, soonest expiry first.
{ "certificates": [ { "fingerprint": "3f1c…", "name": "www.example.com", "subject_alt_names": ["www.example.com", "example.com"], "issuer": "R11", "issuer_organization": "Let's Encrypt", "not_before": "2026-08-01T12:00:00Z", "not_after": "2026-10-30T12:00:00Z", "days_remaining": 12, "key_algorithm": "ECDSA", "key_size": 256, "chain_status": "valid", "root_distrusted": false, "muted": false, "first_seen": "2026-08-01T13:05:00Z", "url": "https://app.nocert.io/certificates/3f1c…" } ], "next_cursor": "WzE3OTM…"}To read the next page, pass next_cursor back as ?cursor=. It is null on the last page. Treat the cursor as opaque: its content can change.
fingerprintis the SHA-256 of the certificate in lowercase hexadecimal.subject_alt_namesholds every Subject Alternative Name as written in the certificate: DNS names, IP addresses, email addresses and URIs, in one list, at most 1000.chain_statusisvalid,incomplete,invalidorunknown(not verified yet).key_sizeis 0 when the algorithm has no key size.urlopens the certificate in NoCert, where you find every place it is deployed.
key_algorithm, chain_status and the Sentinel connection can gain values over time. Handle one you do not know instead of failing on it.
GET /api/v1/sentinels
Section titled “GET /api/v1/sentinels”Every Sentinel of the organization, up to 10,000, in one response.
{ "sentinels": [ { "id": "6d90…", "name": "dc1-sentinel", "hostname": "dc1.internal", "version": "v0.1.13", "last_seen_at": "2026-10-18T15:57:00Z", "connection": "online" } ]}connection follows the rule of the summary. last_seen_at is null for a Sentinel that never reported.
Errors
Section titled “Errors”Errors use the application/problem+json format (RFC 9457), with the HTTP status in status and a short explanation in detail.
| Status | Meaning |
|---|---|
400 |
A parameter or the cursor is invalid. |
401 |
The token is missing, malformed, revoked or expired. |
429 |
Rate limit reached. Wait for Retry-After. |
503 |
Temporary failure on our side, with a Retry-After. Do not treat it as “nothing expires”. |
New fields can appear in responses. Existing fields keep their name and meaning, so ignore what you do not use.
Nagios, Icinga, Centreon
Section titled “Nagios, Icinga, Centreon”A plugin-style check needs curl and jq. It exits 2 on an expired certificate, 1 when one expires within the horizon, and 3 when the API cannot be read.
#!/bin/sh# Usage: check_nocert [days] NOCERT_TOKEN must be set.days="${1:-30}"summary=$(curl -fsS -H "Authorization: Bearer $NOCERT_TOKEN" \ "https://app.nocert.io/api/v1/summary?expiring_within_days=$days") \ || { echo "UNKNOWN - NoCert API unreachable"; exit 3; }expired=$(printf '%s' "$summary" | jq -r '.certificates.expired')expiring=$(printf '%s' "$summary" | jq -r '.certificates.expiring')perf="expired=$expired expiring=$expiring"if [ "$expired" -gt 0 ]; then echo "CRITICAL - $expired expired, $expiring expiring within $days days | $perf" exit 2fiif [ "$expiring" -gt 0 ]; then echo "WARNING - $expiring expiring within $days days | $perf" exit 1fiecho "OK - nothing expires within $days days | $perf"exit 0Zabbix
Section titled “Zabbix”No template is needed: one HTTP agent item reads the summary and dependent items split it.
- Create a secret text macro
{$NOCERT_TOKEN}holding the token. - Add an item of type HTTP agent, key
nocert.summary, URLhttps://app.nocert.io/api/v1/summary, headerAuthorizationwith valueBearer {$NOCERT_TOKEN}, update interval5m, type of information Text. - Add dependent items on
nocert.summary, type of information Numeric (unsigned), each with one JSONPath preprocessing step: keynocert.expiredwith$.certificates.expired, keynocert.expiringwith$.certificates.expiring, keynocert.sentinels.offlinewith$.sentinels.offline. - Add triggers on them. On a host named
NoCert,last(/NoCert/nocert.expired)>0with severity High fires on any expired certificate still deployed.