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_xxxxxxxxxxxxBase 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
{
"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
| Parameter | Type | Description |
|---|---|---|
parentCaId | string | Filter by parent CA ID. Use to list only children of a specific CA. |
type | string | root | intermediate | all (default: all) |
Example Request
curl https://api.certman.app/v1/cas \
-H "Authorization: Bearer cm_xxxxxxxxxxxx"Response
{
"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
| Parameter | Type | Description |
|---|---|---|
id | UUID | Certificate Authority ID |
Example Request
curl https://api.certman.app/v1/cas/550e8400-e29b-41d4-a716-446655440000 \
-H "Authorization: Bearer cm_xxxxxxxxxxxx"Response
{
"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
| Parameter | Type | Description |
|---|---|---|
id | UUID | Certificate Authority ID |
Example Request
curl https://api.certman.app/v1/cas/550e8400-e29b-41d4-a716-446655440000/chain \
-H "Authorization: Bearer cm_xxxxxxxxxxxx"Response
{
"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
| Parameter | Type | Description |
|---|---|---|
caId | string | Filter by Certificate Authority ID |
status | string | active | revoked | all (default: all) |
search | string | Search by common name (case-insensitive partial match) |
createdFrom | string | Filter certificates created on or after this date (ISO 8601) |
createdTo | string | Filter certificates created on or before this date (ISO 8601) |
expiringInDays | integer | Filter certificates expiring within N days |
page | integer | Page number (1-indexed) (default: 1) |
pageSize | integer | Number 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
{
"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
| Parameter | Type | Description |
|---|---|---|
Idempotency-Key | string | A 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
| Parameter | Type | Description |
|---|---|---|
caId | string | ID of the Certificate Authority to issue from |
mode | string | managed | csr (default: managed) |
commonName | string | Common name for the certificate (required for managed mode) |
sanDns | string[] | DNS Subject Alternative Names (supports wildcards like *.example.com) |
sanIp | string[] | IP address Subject Alternative Names (IPv4 or IPv6) |
keyAlgorithm | string | RSA-2048 | RSA-4096 | ECDSA-P256 | ECDSA-P384 |
validityDays | integer | Certificate validity in days (max 397 per CA/Browser Forum) |
csrPem | string | Certificate Signing Request in PEM format (required for csr mode) |
caPassphrase | string | CA 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
{
"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
| Parameter | Type | Description |
|---|---|---|
id | UUID | Certificate ID |
Request Body (Optional)
| Parameter | Type | Description |
|---|---|---|
reason | string | unspecified | keyCompromise | caCompromise | affiliationChanged | superseded | cessationOfOperation | certificateHold | privilegeWithdrawn (default: unspecified) |
caPassphrase | string | CA 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
{
"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
| Parameter | Type | Description |
|---|---|---|
id | UUID | Certificate ID |
Headers
| Parameter | Type | Description |
|---|---|---|
Idempotency-Key | string | A 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)
| Parameter | Type | Description |
|---|---|---|
validityDays | integer | Certificate validity in days (max 397 per CA/Browser Forum) |
csrPem | string | New CSR in PEM format (required when renewing a CSR-based certificate) |
caPassphrase | string | CA 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
{
"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