API Access

Automate certificate management with the REST API. API keys provide programmatic access with granular per-CA permissions.

Creating API Keys

Navigate to API / MCP Access in the sidebar to create keys. API keys must be scoped to specific CAs — they don't have workspace-wide access. Each key can be granted specific permissions per CA:

  • Read — View CA and certificate details
  • Issue — Create new certificates
  • Revoke — Revoke existing certificates

On the Free plan, API keys get full access (all three permissions) to selected CAs. The Pro plan allows granular control — for example, read-only access to one CA and read+issue for another.

Authentication

Include your API key in the Authorization header:

Authorization: Bearer cm_xxxxxxxxxxxx

Base URL

All API endpoints are available at https://api.certman.app

OpenAPI Specification

The full API specification is available in OpenAPI 3.0 format at https://api.certman.app/v1/openapi. You can use this with tools like Swagger Editor, Postman, or any OpenAPI-compatible client to explore and test the API.

Endpoints

GET/v1/whoami

Returns information about the authenticated API key, including the associated user, workspace, and permissions.

Example Request

curl https://api.certman.app/v1/whoami \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx"

Response

200 OK
{
  "user": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "email": "user@example.com"
  },
  "workspace": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "name": "My Workspace",
    "slug": "my-workspace"
  },
  "apiKey": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "name": "Production Key",
    "prefix": "cm_prod"
  },
  "permissions": {
    "880e8400-e29b-41d4-a716-446655440003": {
      "canRead": true,
      "canIssue": true,
      "canRevoke": false
    }
  }
}
GET/v1/cas

Returns a list of all Certificate Authorities that the API key has read access to. Revoked CAs are automatically excluded.

Query Parameters

ParameterTypeDescription
parentCaIdstringFilter by parent CA ID. Use to list only children of a specific CA.
typestringroot | intermediate | all (default: all)

Example Request

curl https://api.certman.app/v1/cas \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx"

Response

200 OK
{
  "cas": [
    {
      "id": "550e8400-e29b-41d4-a716-446655440000",
      "name": "Production Root CA",
      "common_name": "Production Root CA",
      "organization": "Acme Corp",
      "key_algorithm": "ECDSA-P384",
      "valid_from": "2024-01-01T00:00:00.000Z",
      "valid_to": "2034-01-01T00:00:00.000Z",
      "created_at": "2024-01-01T00:00:00.000Z",
      "parent_ca_id": null,
      "depth": 0,
      "path_length": null
    },
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "name": "Production Intermediate CA",
      "common_name": "Production Intermediate CA",
      "organization": "Acme Corp",
      "key_algorithm": "ECDSA-P256",
      "valid_from": "2024-06-01T00:00:00.000Z",
      "valid_to": "2029-06-01T00:00:00.000Z",
      "created_at": "2024-06-01T00:00:00.000Z",
      "parent_ca_id": "550e8400-e29b-41d4-a716-446655440000",
      "depth": 1,
      "path_length": 0
    }
  ]
}
GET/v1/cas/:id

Returns detailed information about a specific Certificate Authority, including its certificate PEM.

Path Parameters

ParameterTypeDescription
idUUIDCertificate Authority ID

Example Request

curl https://api.certman.app/v1/cas/550e8400-e29b-41d4-a716-446655440000 \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx"

Response

200 OK
{
  "ca": {
    "id": "550e8400-e29b-41d4-a716-446655440000",
    "name": "Production Root CA",
    "common_name": "Production Root CA",
    "organization": "Acme Corp",
    "country": "US",
    "state": "California",
    "locality": "San Francisco",
    "key_algorithm": "ECDSA-P384",
    "certificate_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "serial_number": "01AB23CD45EF",
    "valid_from": "2024-01-01T00:00:00.000Z",
    "valid_to": "2034-01-01T00:00:00.000Z",
    "created_at": "2024-01-01T00:00:00.000Z",
    "has_passphrase": false,
    "parent_ca_id": null,
    "depth": 0,
    "path_length": null,
    "revoked_at": null,
    "revocation_reason": null
  }
}
GET/v1/cas/:id/chain

Returns the full certificate chain for a CA, from the specified CA up to the root. Useful for building trust stores or verifying certificate chains.

Path Parameters

ParameterTypeDescription
idUUIDCertificate Authority ID

Example Request

curl https://api.certman.app/v1/cas/550e8400-e29b-41d4-a716-446655440000/chain \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx"

Response

200 OK
{
  "caId": "660e8400-e29b-41d4-a716-446655440001",
  "chainLength": 2,
  "chain": [
    "-----BEGIN CERTIFICATE-----\n(intermediate CA cert)\n-----END CERTIFICATE-----",
    "-----BEGIN CERTIFICATE-----\n(root CA cert)\n-----END CERTIFICATE-----"
  ]
}
GET/v1/certificates

Returns a paginated list of certificates with optional filtering. Only certificates from CAs that the API key has read access to are returned.

Query Parameters

ParameterTypeDescription
caIdstringFilter by Certificate Authority ID
statusstringactive | revoked | all (default: all)
searchstringSearch by common name (case-insensitive partial match)
createdFromstringFilter certificates created on or after this date (ISO 8601)
createdTostringFilter certificates created on or before this date (ISO 8601)
expiringInDaysintegerFilter certificates expiring within N days
pageintegerPage number (1-indexed) (default: 1)
pageSizeintegerNumber of items per page (default: 20)

Example Request

curl "https://api.certman.app/v1/certificates?status=active&pageSize=10" \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx"

Response

200 OK
{
  "certificates": [
    {
      "id": "660e8400-e29b-41d4-a716-446655440001",
      "ca_id": "550e8400-e29b-41d4-a716-446655440000",
      "common_name": "api.example.com",
      "san_dns": [
        "api.example.com",
        "www.example.com"
      ],
      "san_ip": [
        "192.168.1.1"
      ],
      "key_algorithm": "ECDSA-P256",
      "valid_from": "2024-06-01T00:00:00.000Z",
      "valid_to": "2025-06-01T00:00:00.000Z",
      "serial_number": "AABBCCDD",
      "revoked_at": null,
      "revocation_reason": null,
      "created_at": "2024-06-01T00:00:00.000Z"
    }
  ],
  "total": 42,
  "page": 1,
  "pageSize": 20,
  "totalPages": 3
}
POST/v1/certificates

Issues a new certificate from a Certificate Authority. Supports two modes: 'managed' (Certman generates the key pair) or 'csr' (you provide a Certificate Signing Request).

Idempotency: For CSR mode only, you can provide an Idempotency-Key header to ensure the request is idempotent. If you retry a request with the same key and body, you'll receive the same response. Keys expire after 24 hours. Managed mode does not support idempotency because each request generates a unique private key.

Headers

ParameterTypeDescription
Idempotency-KeystringA unique key to ensure idempotent requests. If you retry a request with the same key and body within 24 hours, you'll receive the cached response. Only supported for CSR-based operations (not managed mode). Recommended format: UUID v4.

Request Body

ParameterTypeDescription
caIdstringID of the Certificate Authority to issue from
modestringmanaged | csr (default: managed)
commonNamestringCommon name for the certificate (required for managed mode)
sanDnsstring[]DNS Subject Alternative Names (supports wildcards like *.example.com)
sanIpstring[]IP address Subject Alternative Names (IPv4 or IPv6)
keyAlgorithmstringRSA-2048 | RSA-4096 | ECDSA-P256 | ECDSA-P384
validityDaysintegerCertificate validity in days (max 397 per CA/Browser Forum)
csrPemstringCertificate Signing Request in PEM format (required for csr mode)
caPassphrasestringCA passphrase (required if the CA is passphrase-protected)

Example Request

curl -X POST https://api.certman.app/v1/certificates \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "caId": "550e8400-e29b-41d4-a716-446655440000",
    "mode": "managed",
    "commonName": "api.example.com",
    "sanDns": [
      "api.example.com",
      "www.example.com"
    ],
    "sanIp": [
      "192.168.1.1"
    ],
    "keyAlgorithm": "ECDSA-P256",
    "validityDays": 365
  }'

Response

200 OK
{
  "certificate": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "common_name": "api.example.com",
    "certificate_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "san_dns": [
      "api.example.com",
      "www.example.com"
    ],
    "san_ip": [
      "192.168.1.1"
    ],
    "valid_from": "2024-06-01T00:00:00.000Z",
    "valid_to": "2025-06-01T00:00:00.000Z",
    "serial_number": "AABBCCDD",
    "created_at": "2024-06-01T00:00:00.000Z"
  },
  "privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
}

Note: privateKey is only returned for managed certificates. Store it securely.

POST/v1/certificates/:id/revoke

Revokes a certificate. Revoked certificates are included in the CA's Certificate Revocation List (CRL) and will be reported as revoked via OCSP.

Path Parameters

ParameterTypeDescription
idUUIDCertificate ID

Request Body (Optional)

ParameterTypeDescription
reasonstringunspecified | keyCompromise | caCompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn (default: unspecified)
caPassphrasestringCA passphrase (required if the CA is passphrase-protected)

Example Request

curl -X POST https://api.certman.app/v1/certificates/550e8400-e29b-41d4-a716-446655440000/revoke \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "reason": "keyCompromise"
  }'

Response

200 OK
{
  "message": "Certificate revoked successfully",
  "certificate": {
    "id": "660e8400-e29b-41d4-a716-446655440001",
    "common_name": "api.example.com",
    "revoked_at": "2024-07-15T12:30:00.000Z",
    "revocation_reason": "keyCompromise"
  }
}
POST/v1/certificates/:id/renew

Creates a new certificate with the same properties as an existing certificate. For managed certificates, a new key pair is generated. For CSR-based certificates, you must provide a new CSR.

Idempotency: When providing a CSR, you can use an Idempotency-Key header to ensure the request is idempotent. If you retry a request with the same key and body, you'll receive the same response. Keys expire after 24 hours. Managed renewals do not support idempotency because each request generates a unique private key.

Path Parameters

ParameterTypeDescription
idUUIDCertificate ID

Headers

ParameterTypeDescription
Idempotency-KeystringA unique key to ensure idempotent requests. If you retry a request with the same key and body within 24 hours, you'll receive the cached response. Only supported for CSR-based operations (not managed mode). Recommended format: UUID v4.

Request Body (Optional)

ParameterTypeDescription
validityDaysintegerCertificate validity in days (max 397 per CA/Browser Forum)
csrPemstringNew CSR in PEM format (required when renewing a CSR-based certificate)
caPassphrasestringCA passphrase (required if the CA is passphrase-protected)

Example Request

curl -X POST https://api.certman.app/v1/certificates/550e8400-e29b-41d4-a716-446655440000/renew \
  -H "Authorization: Bearer cm_xxxxxxxxxxxx" \
  -H "Content-Type: application/json" \
  -d '{
    "validityDays": 365
  }'

Response

200 OK
{
  "message": "Certificate renewed successfully",
  "certificate": {
    "id": "770e8400-e29b-41d4-a716-446655440002",
    "common_name": "api.example.com",
    "certificate_pem": "-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    "san_dns": [
      "api.example.com",
      "www.example.com"
    ],
    "san_ip": [
      "192.168.1.1"
    ],
    "valid_from": "2025-06-01T00:00:00.000Z",
    "valid_to": "2026-06-01T00:00:00.000Z",
    "serial_number": "EEFF0011",
    "created_at": "2025-06-01T00:00:00.000Z"
  },
  "privateKey": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----"
}

Note: privateKey is only returned for managed certificates. Store it securely.

Rate Limits

API requests are rate-limited to ensure fair usage. Certificate issuance and renewal operations have a lower limit due to their computational cost. If you exceed the rate limit, you'll receive a 429 response.

Error Format

All error responses follow a consistent format:

{ "error": "Human-readable error message" }

Common HTTP status codes:

  • 400 — Bad request (invalid parameters)
  • 401 — Unauthorized (missing or invalid API key)
  • 403 — Forbidden (insufficient permissions)
  • 404 — Not found
  • 429 — Too many requests (rate limited)
  • 500 — Internal server error