API Documentation

Monitor your SSL certificates programmatically with the StableSSL API

Getting Started
How to authenticate and use the API

1. Get an API Key

API access is available on the Max plan. To create an API key:

  1. Upgrade to the Max plan
  2. Go to Account Settings → API Keys
  3. Click "Create API Key"
  4. Give your key a name and set an expiry period
  5. Save the key immediately - it will only be shown once!

2. Authentication

All API requests require authentication using your API key in the X-API-Key header:

X-API-Key: YOUR_API_KEY_HERE

3. Base URL

https://api.stablessl.com/v1

4. Response Format

All responses are in JSON format with appropriate HTTP status codes.

Domain Status Codes
Understanding the status field in domain responses
CodeStatusDescription
0
Not Checked
Domain added but not yet checked
1
Active
Certificate valid, ≥30 days until expiry
2
Expiring Soon
Certificate expires in <30 days
3
Expired
Certificate has expired
4
Invalid DNS
DNS resolution failed (reserved)
5
Connection Error
Failed to connect and fetch certificate

API Endpoints

GET
/protocols
Get available protocols for SSL/TLS monitoring

Description

Returns a list of supported protocols. Use the protocol ID when creating or updating domains. Common protocols include HTTPS (port 443), FTPS (port 990), SMTPS (port 465).

Authentication

Required - Use API key in X-API-Key header

Response Example

[
  {
    "id": 1,
    "name": "HTTPS"
  },
  {
    "id": 2,
    "name": "FTPS"
  },
  {
    "id": 3,
    "name": "SMTPS"
  }
]
GET
/domains
Get all domains owned by the authenticated user

Description

Returns a list of all domains you're monitoring with their SSL certificate status and expiry information.

Authentication

Required - Use API key in X-API-Key header

Response Example

[
  {
    "id": 1,
    "host": "example.com",
    "port": 443,
    "protocol": 1,
    "status": 1,
    "notes": "Production server",
    "agent": {
      "id": 10,
      "name": "Hoth"
    },
    "expiry_date": "2025-12-31T23:59:59Z",
    "days_left": 350,
    "last_check": "2025-01-15T10:30:00Z"
  }
]

Response Codes

  • 200 - Success
  • 401 - Unauthorized (invalid API key)
POST
/domains
Create a new domain for SSL certificate monitoring

Description

Add a new domain to monitor. Domain limits are enforced based on your plan (Free: 3, Pro: 20, Max: 50).

Authentication

Required - Use API key in X-API-Key header

Request Body

{
  "host": "example.com",
  "port": 443,
  "protocol": 1,
  "notes": "Production server",
  "agent_id": 10
}

Parameters

FieldTypeRequiredDescription
hoststringDomain hostname (e.g., example.com)
portintegerPort number (1-65535)
protocolintegerProtocol ID from /protocols endpoint
notesstringOptional notes or comments
agent_idintegerAgent ID for checking. Null or omitted = auto-assign

Response Example

{
  "id": 42,
  "host": "example.com",
  "port": 443,
  "protocol": 1,
  "status": 0,
  "notes": "Production server",
  "agent": {
    "id": 10,
    "name": "Hoth"
  },
  "expiry_date": null,
  "days_left": 0,
  "last_check": null
}

Response Codes

  • 201 - Domain created successfully
  • 400 - Invalid request (validation failed)
  • 401 - Unauthorized (invalid API key)
  • 403 - Forbidden (domain limit reached)
  • 409 - Conflict (domain already exists)
GET
/domains/{domain_id}
Get detailed information about a specific domain

Description

Retrieve details for a specific domain. Only domain owners can access their domains.

Authentication

Required - Use API key in X-API-Key header

Path Parameters

  • domain_id (integer) - The domain identifier

Response Example

{
  "host": "example.com",
  "port": 443,
  "protocol": 1,
  "status": 1,
  "notes": "Production server",
  "agent_id": 10
}

Response Codes

  • 200 - Success
  • 401 - Unauthorized (invalid API key)
  • 404 - Domain not found
PUT
/domains/{domain_id}
Update an existing domain's configuration

Description

Update a domain's host, port, or protocol. Only the domain owner can update it.

Authentication

Required - Use API key in X-API-Key header

Path Parameters

  • domain_id (integer) - The domain identifier

Request Body

{
  "host": "newdomain.com",
  "port": 8443,
  "protocol": 1,
  "notes": "Staging server",
  "agent_id": 10
}

Response Example

{
  "host": "newdomain.com",
  "port": 8443,
  "protocol": 1,
  "status": 0,
  "notes": "Staging server",
  "agent_id": 10
}

Response Codes

  • 200 - Domain updated successfully
  • 400 - Invalid request (validation failed)
  • 401 - Unauthorized (invalid API key)
  • 404 - Domain not found
DELETE
/domains/{domain_id}
Delete a domain from SSL certificate monitoring

Description

Permanently delete a domain from monitoring. This action cannot be undone. Only the domain owner can delete it.

Authentication

Required - Use API key in X-API-Key header

Path Parameters

  • domain_id (integer) - The domain identifier

Response Codes

  • 200 - Domain deleted successfully
  • 401 - Unauthorized (invalid API key)
  • 404 - Domain not found
GET
/certificates/domain/{domain_id}
Get certificate history for a specific domain

Description

Retrieve historical certificate data for a domain. Returns certificates ordered by collection time (newest first). History depth is limited by your plan: Free (0 days), Pro (90 days), Max (180 days). Only domain owners can access history.

Authentication

Required - Use API key in X-API-Key header

Path Parameters

  • domain_id (integer) - The domain identifier

Response Example

[
  {
    "id": 123,
    "domain_id": 1,
    "fingerprint_sha256": "A1:B2:C3:...",
    "subject": "CN=example.com",
    "issuer": "CN=Let's Encrypt Authority X3",
    "serial_number": "03:AF:...",
    "not_before": "2024-01-01T00:00:00Z",
    "not_after": "2024-04-01T00:00:00Z",
    "signature_algorithm": "sha256WithRSAEncryption",
    "key_type": "RSA",
    "collected_at": "2024-01-15T10:30:00Z"
  }
]

Response Codes

  • 200 - Success
  • 401 - Unauthorized (invalid API key)
  • 403 - Forbidden (plan does not include certificate history)
  • 404 - Domain not found or doesn't belong to user
GET
/certificates/{certificate_id}
Get full certificate details including PEM data

Description

Retrieve complete details of a specific certificate including the full PEM certificate data. Only domain owners can access certificate details. Useful for detailed inspection and verification.

Authentication

Required - Use API key in X-API-Key header

Path Parameters

  • certificate_id (integer) - The certificate identifier

Response Example

{
  "id": 123,
  "domain_id": 1,
  "fingerprint_sha256": "A1:B2:C3:D4:E5:F6:...",
  "subject": "CN=example.com",
  "issuer": "CN=Let's Encrypt Authority X3, O=Let's Encrypt, C=US",
  "serial_number": "03:AF:12:34:56:...",
  "not_before": "2024-01-01T00:00:00Z",
  "not_after": "2024-04-01T00:00:00Z",
  "signature_algorithm": "sha256WithRSAEncryption",
  "key_type": "RSA",
  "key_size": 2048,
  "collected_at": "2024-01-15T10:30:00Z",
  "hostname": "example.com",
  "port": 443,
  "protocol": "HTTPS",
  "pem_certificate": "-----BEGIN CERTIFICATE-----\nMIIFZTCCBE2gAwIBAgISA...\n-----END CERTIFICATE-----"
}

Response Codes

  • 200 - Success
  • 401 - Unauthorized (invalid API key)
  • 404 - Certificate not found or doesn't belong to user's domain
Code Examples
Example requests using cURL and Python

List all domains (cURL)

curl -X GET https://api.stablessl.com/v1/domains \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json"

Create a domain (cURL)

curl -X POST https://api.stablessl.com/v1/domains \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json" \
  -d '{
    "host": "example.com",
    "port": 443,
    "protocol": 1
  }'

List all domains (Python)

import requests

API_KEY = "YOUR_API_KEY_HERE"
BASE_URL = "https://api.stablessl.com/v1"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

response = requests.get(f"{BASE_URL}/domains", headers=headers)
domains = response.json()

for domain in domains:
    print(f"{domain['host']}:{domain['port']} - Status: {domain['status']}")

Create a domain (Python)

import requests

API_KEY = "YOUR_API_KEY_HERE"
BASE_URL = "https://api.stablessl.com/v1"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

data = {
    "host": "example.com",
    "port": 443,
    "protocol": 1
}

response = requests.post(f"{BASE_URL}/domains", headers=headers, json=data)

if response.status_code == 201:
    domain = response.json()
    print(f"Domain created: {domain['id']}")
else:
    print(f"Error: {response.status_code} - {response.text}")

Get certificate history (cURL)

curl -X GET https://api.stablessl.com/v1/certificates/domain/123 \
  -H "X-API-Key: YOUR_API_KEY_HERE" \
  -H "Content-Type: application/json"

Get certificate details (Python)

import requests

API_KEY = "YOUR_API_KEY_HERE"
BASE_URL = "https://api.stablessl.com/v1"

headers = {
    "X-API-Key": API_KEY,
    "Content-Type": "application/json"
}

# Get certificate details including PEM data
cert_id = 456
response = requests.get(f"{BASE_URL}/certificates/{cert_id}", headers=headers)

if response.status_code == 200:
    cert = response.json()
    print(f"Certificate for: {cert['subject']}")
    print(f"Expires: {cert['not_after']}")
    print(f"Fingerprint: {cert['fingerprint_sha256']}")
    # Access PEM certificate data
    pem_data = cert['pem_certificate']
else:
    print(f"Error: {response.status_code} - {response.text}")
Best Practices

Security

  • Never commit API keys to version control
  • Use environment variables to store API keys
  • Rotate keys regularly (create new key, update apps, delete old key)
  • Use separate keys for different environments (dev, staging, production)
  • Deactivate or delete compromised keys immediately

Error Handling

  • Always check HTTP status codes
  • Implement exponential backoff for failed requests
  • Handle 401 errors by checking if your API key is valid and not expired
  • Handle 403 errors by verifying your plan includes the requested feature
  • Handle 429 errors by reducing request frequency

Domain Limits

Respect your plan's domain limits:

  • Free plan: 3 domains
  • Pro plan: 20 domains
  • Max plan: 50 domains