Certificates API

API endpoints for SSL certificate management.

Manage SSL/TLS certificates for your projects.

Endpoints Overview

MethodEndpointDescription
GET/projects/:id/certificateGet certificate
POST/projects/:id/certificate/obtainObtain Let's Encrypt
POST/projects/:id/certificate/uploadUpload custom cert
POST/projects/:id/certificate/validateValidate certificate
POST/projects/:id/certificate/renewRenew certificate
POST/projects/:id/certificate/revokeRevoke certificate
GET/projects/:id/certificate/statusGet cert status
DELETE/projects/:id/certificateRemove certificate

Get Certificate

GET /api/v1/projects/:id/certificate

Permission: projects:read

Response (certificate exists):

{
  "domain": "api.example.com",
  "type": "letsencrypt",
  "issuedAt": "2026-01-19T00:00:00Z",
  "expiresAt": "2026-04-19T00:00:00Z",
  "issuer": "Let's Encrypt Authority X3",
  "autoRenew": true
}

Response (no certificate):

null

Obtain Let's Encrypt Certificate

POST /api/v1/projects/:id/certificate/obtain

Permission: projects:write

HTTP-01 Challenge

{
  "email": "admin@example.com",
  "challengeType": "http-01",
  "autoRenew": true
}

DNS-01 Challenge (Cloudflare)

{
  "email": "admin@example.com",
  "challengeType": "dns-01",
  "dnsProvider": "cloudflare",
  "dnsCredentials": {
    "apiToken": "your-cloudflare-api-token"
  },
  "autoRenew": true
}

DNS-01 Challenge (AWS Route 53)

{
  "email": "admin@example.com",
  "challengeType": "dns-01",
  "dnsProvider": "aws",
  "dnsCredentials": {
    "accessKeyId": "AKIAXXXXXXXX",
    "secretAccessKey": "your-secret-key",
    "region": "us-east-1"
  }
}

Additional Options

OptionDescriptionDefault
keyTypersa or ecrsa
keySize2048 or 4096 (RSA)2048
stagingUse staging serverfalse
dryRunTest without issuingfalse

Response:

{
  "success": true,
  "certificate": {
    "domain": "api.example.com",
    "issuedAt": "2026-01-19T12:00:00Z",
    "expiresAt": "2026-04-19T12:00:00Z",
    "issuer": "Let's Encrypt",
    "autoRenew": true
  }
}

Upload Custom Certificate

POST /api/v1/projects/:id/certificate/upload

Permission: projects:write

Request:

{
  "certificate": "-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\nMIID...\n-----END CERTIFICATE-----",
  "privateKey": "-----BEGIN PRIVATE KEY-----\nMIIE...\n-----END PRIVATE KEY-----"
}

Response:

{
  "success": true,
  "certificate": {
    "domain": "api.example.com",
    "type": "custom",
    "issuedAt": "2026-01-01T00:00:00Z",
    "expiresAt": "2027-01-01T00:00:00Z",
    "issuer": "DigiCert Inc"
  }
}

Validate Certificate

Test certificate before uploading:

POST /api/v1/projects/:id/certificate/validate

Request:

{
  "certificate": "-----BEGIN CERTIFICATE-----\n...",
  "privateKey": "-----BEGIN PRIVATE KEY-----\n..."
}

Response (valid):

{
  "valid": true,
  "domain": "api.example.com",
  "expiresAt": "2027-01-01T00:00:00Z",
  "issuer": "DigiCert Inc",
  "warnings": []
}

Response (invalid):

{
  "valid": false,
  "error": "Certificate and private key do not match"
}

Renew Certificate

POST /api/v1/projects/:id/certificate/renew

Permission: projects:write

Response:

{
  "success": true,
  "certificate": {
    "domain": "api.example.com",
    "issuedAt": "2026-04-19T12:00:00Z",
    "expiresAt": "2026-07-19T12:00:00Z",
    "renewedFrom": "2026-01-19T12:00:00Z"
  }
}

Revoke Certificate

POST /api/v1/projects/:id/certificate/revoke

Permission: projects:write

Revoked certificates cannot be un-revoked.

Response:

{
  "success": true,
  "message": "Certificate revoked"
}

Get Certificate Status

GET /api/v1/projects/:id/certificate/status

Response:

{
  "status": "valid",
  "domain": "api.example.com",
  "expiresAt": "2026-04-19T12:00:00Z",
  "daysUntilExpiry": 90,
  "autoRenew": true,
  "lastRenewAttempt": null,
  "lastRenewError": null
}

Status values:

  • valid - Certificate active and valid
  • expiring_soon - Expires within 30 days
  • expired - Certificate has expired
  • revoked - Certificate was revoked

Remove Certificate

DELETE /api/v1/projects/:id/certificate

Permission: projects:write

Response:

{
  "success": true,
  "message": "Certificate removed"
}

Error Responses

Domain Not Configured

{
  "success": false,
  "error": "Project has no domain configured"
}

Status: 400

Challenge Failed

{
  "success": false,
  "error": "HTTP-01 challenge failed: Could not verify domain ownership"
}

Status: 400

Invalid Certificate

{
  "success": false,
  "error": "Certificate is not valid for domain api.example.com"
}

Status: 400

DNS Provider Credentials

Cloudflare

{
  "apiToken": "your-cloudflare-api-token"
}

AWS Route 53

{
  "accessKeyId": "AKIAXXXXXXXX",
  "secretAccessKey": "your-secret-key",
  "region": "us-east-1"
}

DigitalOcean

{
  "apiToken": "your-digitalocean-token"
}

GoDaddy

{
  "apiKey": "your-api-key",
  "apiSecret": "your-api-secret"
}

Google Cloud DNS

{
  "projectId": "your-project-id",
  "credentials": { ... }
}