# Certificates API

> List the outbound hosts whose TLS certificates are monitored, read a host's chain analysis and history, add, pause or re-check hosts, and set reminders.

Source: https://www.apitraffic.io/docs/api-reference/certificates

Certificate monitoring checks the TLS certificate and chain of every outbound HTTPS host your API calls, about once a day. See [Monitor the certificates of hosts you call](https://www.apitraffic.io/docs/certificates) for how it works in the app.

**Plan:** needs a plan that includes **Certificate monitoring**. Reading hosts and settings keeps working if the plan changes. Adding hosts counts toward the plan's monitored host limit. **Permissions:** any member, or a `user` or `administrator` API token, can read hosts and re-check one. Adding, changing and removing hosts, and the reminders, need an owner or admin, or an `administrator` API token. A token with access scopes needs `alerts:read` to read and `alerts:write` for everything else, re-checks included.

Hosts are account-wide: one host's certificate serves every bucket that calls it. Each host is a `host:port` pair.

## The host object

- **sid (string, required)**:
  The monitored host's identifier (`tlsw_` followed by 27 letters and digits).

- **host (string, required)**:
  The hostname.

- **port (integer, required)**:
  The port, usually `443`.

- **source (string, required)**:
  How the host was added: `auto` (found in outbound calls) or `manual` (added by hand).

- **status (string, required)**:
  `active`, `paused`, `ignored`, `stale` (no request in the last 30 days and not Always monitor) or `limited` (over the plan's limit).

- **alwaysMonitor (boolean, required)**:
  Checked even without requests.

- **monitored (boolean, required)**:
  Whether the host is checked now: `active` with a request in the last 30 days, or Always monitor.

- **bucketSids (string[], required)**:
  The buckets whose traffic called the host.

- **environmentSids (string[], required)**:
  The environments whose traffic called it.

- **firstSeenAt (string | null)**:
  When the host was first seen (ISO 8601).

- **lastSeenAt (string | null)**:
  When it was last called. A host added by hand counts as called on the day it was added.

- **vendor (object, required)**:
  `name`, `contact` (an email address, URL or phone number) and `statusUrl`, each a string or `null`. Included in alerts about the host.

- **notes (string | null)**:
  Free text.

- **certificate (object, required)**:
  The result of the last check.

**properties**

- **checkStatus (string)**: `pending` (not checked yet), `ok`, `expiring`, `expired`, `invalid` or `unreachable`

- **lastCheckedAt (string | null)**: When the host was last checked

- **lastSuccessAt (string | null)**: When a check last read a certificate

- **nextCheckAt (string | null)**: When the next check is due, while the host is monitored

- **notBefore (string | null)**: The start of the certificate's validity

- **notAfter (string | null)**: When it expires

- **daysRemaining (integer | null)**: Days until it expires

- **subjectCn (string | null)**: The common name

- **san (string[])**: The other names it is valid for

- **issuer (string | null)**: The issuer, with `issuerCn` and `issuerOrg`

- **serial (string | null)**: The serial number

- **fingerprintSha256 (string | null)**: The SHA-256 fingerprint. Hosts with the same fingerprint share a certificate

- **keyType (string | null)**: The key type, with `keyBits`

- **signatureAlgorithm (string | null)**: The signature algorithm

- **tlsVersion (string | null)**: The TLS version negotiated

- **chainValid (boolean | null)**: Whether a standard client trusts the chain

- **hostnameMatch (boolean | null)**: Whether the certificate covers the hostname

- **validationError (string | null)**: Why a client rejects the certificate, when it does

- **chainCapture (string | null)**: `handshake` when the chain was read exactly as the server sent it, or `reconstructed` when the server only speaks TLS 1.3 and the chain was rebuilt

- **chainStatus (string | null)**: `complete`, `misordered`, `incomplete`, `wrong_intermediate`, `untrusted`, `expired_intermediate`, `expiring_intermediate`, `invalid_leaf` or `weak`

- **chainIssues (object[])**: Each problem found: `code` (for example `INCOMPLETE_CHAIN`, `WRONG_INTERMEDIATE`, `UNTRUSTED_ROOT`, `CHAIN_CERT_EXPIRING`, `WEAK_SIGNATURE`, `MISORDERED_CHAIN`, `ISSUER_CHANGED`), `severity` and `message`

- **chainNotAfter (string | null)**: When the first certificate in the chain expires, with `chainDaysRemaining`

- **resolvedIp (string | null)**: The address that was checked

- **consecutiveFailures (integer)**: Checks in a row that could not complete

- **lastErrorCode (string | null)**: Why the last check failed, with `lastError`

- **createdAt (string | null)**:
  When the host was added.

- **updatedAt (string | null)**:
  When it last changed.

## List hosts

`GET https://api.apitraffic.io/v1/accounts/{accountSid}/certificates`

Lists monitored hosts, soonest expiry first, up to 1,000. By default only monitored hosts are listed: those with a request in the last 30 days, or with Always monitor on.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

### Query parameters

- **status (query, string)**:
  One status, or several separated by commas: `active`, `paused`, `ignored`, `stale`, `limited`.

- **checkStatus (query, string)**:
  `pending`, `ok`, `expiring`, `expired`, `invalid` or `unreachable`.

- **chainStatus (query, string)**:
  One chain status, such as `incomplete`.

- **chainIssues (query, boolean)**:
  Only hosts whose chain has a problem (anything but complete or merely out of order).

- **expiresWithinDays (query, integer)**:
  Only certificates that expire within this many days (0 to 3650).

- **alwaysMonitor (query, boolean)**:
  Only hosts with Always monitor on, or off.

- **fingerprint (query, string)**:
  Only hosts serving the certificate with this SHA-256 fingerprint (64 hex characters).

- **bucketSid (query, string)**:
  Only hosts this bucket called.

- **q (query, string)**:
  Part of the hostname.

- **includeUnmonitored (query, boolean, default false)**:
  Also list hosts without a request in 30 days that don't have Always monitor on.

- **groupBy (query, string)**:
  `certificate`: one record per certificate, each with `fingerprintSha256`, `certificate` and `hosts` (the host objects that serve it). Hosts not checked yet stand alone.

### Response

`records`, a list of [host objects](#the-host-object) (or groups, with `groupBy`), and `hasMore`, which is `true` when more than 1,000 hosts match.

```bash cURL
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates?expiresWithinDays=7" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN"
```

```json 200
{
  "hasMore": false,
  "records": [
    {
      "sid": "tlsw_2kM4nP6qR8sT1uV3wX5yZ7aB9cE",
      "host": "api.acme-pay.example",
      "port": 443,
      "source": "auto",
      "status": "active",
      "alwaysMonitor": false,
      "monitored": true,
      "bucketSids": ["k3m9p2x"],
      "environmentSids": ["env_2pQ7rS9tU1vW3xY5zA7bC9dE1fG"],
      "firstSeenAt": "2026-09-14T08:12:40.000Z",
      "lastSeenAt": "2026-11-03T17:41:09.000Z",
      "vendor": { "name": "Acme Pay", "contact": "support@acme-pay.example", "statusUrl": null },
      "notes": null,
      "certificate": {
        "checkStatus": "expiring",
        "lastCheckedAt": "2026-11-04T06:02:13.000Z",
        "lastSuccessAt": "2026-11-04T06:02:13.000Z",
        "nextCheckAt": "2026-11-05T06:19:51.000Z",
        "notBefore": "2026-08-10T00:00:00.000Z",
        "notAfter": "2026-11-09T23:59:59.000Z",
        "daysRemaining": 5,
        "subjectCn": "api.acme-pay.example",
        "issuer": "CN=R11,O=Let's Encrypt,C=US",
        "issuerCn": "R11",
        "issuerOrg": "Let's Encrypt",
        "san": ["api.acme-pay.example"],
        "serial": "04a1c3f2e98b7d6c5b4a3f2e1d0c9b8a7f6e",
        "fingerprintSha256": "9f2c4e6a8b0d1f3e5a7c9b1d3f5e7a9c0b2d4f6e8a0c2e4f6a8b0d2c4e6f8a0b",
        "keyType": "EC",
        "keyBits": 256,
        "signatureAlgorithm": "sha256WithRSAEncryption",
        "tlsVersion": "TLSv1.3",
        "chainValid": true,
        "hostnameMatch": true,
        "validationError": null,
        "chainCapture": "handshake",
        "chainStatus": "complete",
        "chainIssues": [],
        "chainNotAfter": "2027-03-12T23:59:59.000Z",
        "chainDaysRemaining": 128,
        "resolvedIp": "203.0.113.24",
        "consecutiveFailures": 0,
        "lastErrorCode": null,
        "lastError": null
      },
      "createdAt": "2026-09-14T08:12:41.000Z",
      "updatedAt": "2026-11-04T06:02:13.000Z"
    }
  ]
}
```

## Get host

`GET https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/{watchSid}`

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

- **watchSid (path, string, required)**:
  The host's identifier.

### Response

The [host object](#the-host-object), with:

- `chain`: each certificate in the chain, from the server's certificate up, with its `subject`, `issuer`, `notAfter`, `keyType`, `keyBits`, `signatureAlgorithm`, `fingerprintSha256` and `source`: `sent` (by the server), `downloaded` or `known_intermediate` (not sent, so a client has to fetch it) or `trust_store`.
- `chainPaths`: the certification paths a client can build, when there is more than one (for example through a cross-signed root).
- `history`: a row each time the certificate, its chain or its status changed, newest first, up to 100: `observedAt`, `fingerprintSha256`, `notBefore`, `notAfter`, `issuerCn`, `checkStatus`, `validationError`, `chainStatus` and `chainIssues`.
- `sharedWith`: the account's other hosts on the same certificate (`sid`, `host`, `port`), up to 100.

```bash cURL
curl "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates/tlsw_2kM4nP6qR8sT1uV3wX5yZ7aB9cE" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN"
```

## Add host

`POST https://api.apitraffic.io/v1/accounts/{accountSid}/certificates`

Adds a host by hand, to watch it before any traffic reaches it or to keep a rarely called vendor monitored. The host counts as called on the day it is added: it is monitored for 30 days, then only while it gets traffic, unless `alwaysMonitor` is on. Its first check runs within 15 minutes.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

### Body parameters

- **host (body, string, required)**:
  A public hostname, such as `api.vendor.com`, optionally with a port (`api.vendor.com:8443`). IP addresses and internal names are refused.

- **port (body, integer, default 443)**:
  `443`, `8443`, `4443`, `9443` or `10443`. Other ports are added from your traffic on their own.

- **alwaysMonitor (body, boolean, default false)**:
  Keep checking the host without requests.

- **vendor (body, object)**:
  `name`, `contact` and `statusUrl`.

- **notes (body, string)**:
  Up to 2,000 characters.

### Response

The new [host object](#the-host-object).

```bash cURL
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "host": "api.acme-freight.example", "alwaysMonitor": true, "vendor": { "name": "Acme Freight", "contact": "ops@acme-freight.example" } }'
```

## Update host

`PATCH https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/{watchSid}`

Pauses, ignores or resumes a host, turns Always monitor on or off, or edits the vendor contact and notes. Send at least one field.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

- **watchSid (path, string, required)**:
  The host's identifier.

### Body parameters

- **status (body, string)**:
  `paused` stops checks and alerts. `ignored` does the same and keeps traffic from adding the host again. `active` resumes it. A host without a request in the last 30 days can only be resumed with `alwaysMonitor` on.

- **alwaysMonitor (body, boolean)**:
  Keep checking the host without requests.

- **vendor (body, object)**:
  `name`, `contact` and `statusUrl`.

- **notes (body, string)**:
  Up to 2,000 characters.

### Response

The updated [host object](#the-host-object).

```bash cURL
curl -X PATCH "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates/tlsw_2kM4nP6qR8sT1uV3wX5yZ7aB9cE" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "status": "paused" }'
```

## Remove host

`DELETE https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/{watchSid}`

Stops tracking a host. A host found in traffic is added again by its traffic within the hour; to keep it out, set its status to `ignored` instead.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

- **watchSid (path, string, required)**:
  The host's identifier.

### Response

`{ "sid": "tlsw_...", "deleted": true }`

```bash cURL
curl -X DELETE "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates/tlsw_2kM4nP6qR8sT1uV3wX5yZ7aB9cE" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN"
```

## Re-check host

`POST https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/{watchSid}/check`

Checks the certificate now and waits up to 20 seconds for the result. Within 5 minutes of the host's last check, the last result is returned instead. Only a monitored host can be re-checked.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

- **watchSid (path, string, required)**:
  The host's identifier.

### Response

The [host object](#the-host-object), with the detail fields of [Get host](#get-host), and:

- `rechecked`: `true` when this call ran a fresh check.
- `checkFailed`: `true` when the check ran but the host could not be checked. The reason is in `certificate.lastError`.
- `failed`: `true` when the check could not run just now. The last result is returned.
- `inProgress`: `true` when a check is still running. The last result is returned.

```bash cURL
curl -X POST "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates/tlsw_2kM4nP6qR8sT1uV3wX5yZ7aB9cE/check" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN"
```

## Get reminder settings

`GET https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/settings`

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

### Response

- **reminderDays (integer[], required)**:
  The early reminders turned on: any of `30` and `14`.

- **reminderOptions (integer[], required)**:
  The reminders you can choose: `[30, 14]`.

- **warningDays (integer, required)**:
  When the always-on warning fires: `7` days before expiry.

- **criticalDays (integer, required)**:
  When the always-on critical alert fires: `1` day before expiry.

```json 200
{ "reminderDays": [30, 14], "warningDays": 7, "criticalDays": 1, "reminderOptions": [30, 14] }
```

## Update reminder settings

`PUT https://api.apitraffic.io/v1/accounts/{accountSid}/certificates/settings`

Turns the 30-day and 14-day early reminders on or off. Reminders are info alerts, sent in the alert digest. The 7-day warning and the 1-day critical alert are always on.

### Path parameters

- **accountSid (path, string, required)**:
  The account identifier.

### Body parameters

- **reminderDays (body, integer[], required)**:
  Any of `30` and `14`. An empty list turns both off.

### Response

The reminder settings, as [Get reminder settings](#get-reminder-settings) returns them.

```bash cURL
curl -X PUT "https://api.apitraffic.io/v1/accounts/acc_2mXq7RbT4kPz9WvN3cHd8LsYfQa/certificates/settings" \
  -H "Authorization: Bearer $APITRAFFIC_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "reminderDays": [14] }'
```

## Errors

| Status | Code | Meaning |
| --- | --- | --- |
| `400` | `1000` | A parameter is invalid, for example an IP address as the host, or a port that can't be added by hand. |
| `403` | `2221` | The plan does not include certificate monitoring. |
| `404` | `4000` | No host with that sid in this account. |
| `409` | `2213` | The plan's monitored host limit is reached. |
| `409` | `2800` | The host is already in the list. |
| `409` | `2801` | The host has had no requests in the last 30 days, so it isn't monitored. Turn on `alwaysMonitor` to check or resume it. |
| `409` | `2802` | The host changed while you were editing it. Read it again and retry. |
| `503` | `2803` | Certificate checks are switched off for now. Try again later. |

## Events

Adding, removing or changing a host, and changing the reminders, are recorded in the account's activity and sent to webhooks as `alerting.certificate_watch_changed` and `alerting.certificate_settings_changed`. See the [webhook event reference](https://www.apitraffic.io/docs/webhooks/reference#event-alerting-certificate-watch-changed).
