DelegatedSSL API
A REST API for delegated domain-control validation and automated SSL. The same API powers the console — create domains, hand out delegation records, verify, issue certificates and receive webhooks.
Overview
The API is served from https://api.delegatedssl.com. All authenticated endpoints live under /v1 and speak JSON. Successful responses return the resource directly; errors return a structured envelope (see Errors). Every response carries an x-request-id header for support.
| Base URL | https://api.delegatedssl.com |
| Version prefix | /v1 |
| Content type | application/json |
| Auth | Bearer API key (dssl_…) or Auth0 access token |
Authentication
Programmatic requests authenticate with an organization API key. Create one in the console under Settings → API keys; the secret (prefixed dssl_) is shown once at creation and stored only as a hash. Send it as a bearer token:
Authorization: Bearer dssl_your_api_keyKeys carry least-privilege scopes. Grant only what an integration needs:
Optional headers: x-org-id to disambiguate an organization, and Idempotency-Key to make writes safely retryable (see rate limits & idempotency).
Quickstart
Delegate a domain end to end in four calls.
# 1. Create a domain (returns the delegation record)
curl https://api.delegatedssl.com/v1/domains \
-H "Authorization: Bearer dssl_your_api_key" \
-H "Content-Type: application/json" \
-d '{"apex":"example.com","tags":["care-plan"]}'
# 2. Give the CNAME to the domain owner
# Host: _acme-challenge.example.com
# Value: example.com.a1b9f0e.dcv.delegatedssl.com
# Type: CNAME TTL: 300
# 3. Once the CNAME resolves, verify delegation
curl -X POST https://api.delegatedssl.com/v1/domains/6f9b2a1e-3c4d-4e5f-8a90-1b2c3d4e5f60/verify-delegation \
-H "Authorization: Bearer dssl_your_api_key"
# 4. Request issuance (or let it happen automatically on verify)
curl -X POST https://api.delegatedssl.com/v1/domains/6f9b2a1e-3c4d-4e5f-8a90-1b2c3d4e5f60/certificates/issue \
-H "Authorization: Bearer dssl_your_api_key"The create call responds with the exact record the domain owner must publish:
{
"id": "6f9b2a1e-3c4d-4e5f-8a90-1b2c3d4e5f60",
"apex": "example.com",
"validation": {
"status": "pending",
"delegation": {
"type": "CNAME",
"host": "_acme-challenge.example.com",
"value": "example.com.a1b9f0e.dcv.delegatedssl.com",
"ttl": 300
}
},
"cert": { "status": "pending" },
"opsStatus": "awaiting_dns"
}Delegated DCV
Domain-control validation normally has to be repeated on every renewal. DelegatedSSL delegates it: the domain owner publishes a single stable _acme-challenge CNAME pointing at a per-domain target on dcv.delegatedssl.com. Validation for the initial issuance and every future renewal resolves through that one record — so the owner acts once and never again. Their DNS can live anywhere; only that one record changes.
Domains
A domain represents an apex you manage for a client. It carries a validation block (status pending / verified / error plus the delegation record) and a cert block (status pending / active / error, issuer and validity). Domains can be grouped under a clientId and carry tags and notes.
Certificates
Certificates are issued and rotated through Cloudflare for SaaS as domain-validated (DV) certificates. The API exposes certificate metadata — issuer, status, validity window and trace IDs — and a metadata bundle for handoff. Private keys are never exported; key material stays at Cloudflare's edge.
Domains API
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/domains | Create a domain — provisions a Custom Hostname and returns the delegation record. |
| POST | /v1/domains/bulk | Onboard up to 100 apex domains in one request. |
| POST | /v1/domains/query | List and filter domains by client, validation or certificate status. |
| GET | /v1/domains/:id | Fetch a single domain with its validation and certificate state. |
| GET | /v1/domains/:id/delegation-record | Return the exact CNAME the domain owner must publish. |
| POST | /v1/domains/:id/verify-delegation | Re-check delegation and refresh validation status. |
| POST | /v1/domains/:id/recheck | Re-poll Cloudflare and refresh validation + certificate state. |
| POST | /v1/domains/:id/certificates/issue | Request issuance once a domain is verified. |
| PATCH | /v1/domains/:id | Update a domain's tags and notes. |
| DELETE | /v1/domains/:id | Remove a domain and its Custom Hostname. |
Certificates API
| Method | Endpoint | Description |
|---|---|---|
| POST | /v1/domains/:id/certificates/query | List certificates for a domain. |
| GET | /v1/certificates/:id | Fetch certificate metadata — issuer, status, validity window. |
| GET | /v1/certificates/:id/bundle | Download a certificate metadata bundle (no private keys). |
Webhooks
Register HTTPS endpoints and manage their signing secrets over the API. On creation you receive a signing secret (whsec_…, shown once) which you rotate independently of the endpoint.
| Method | Endpoint | Description |
|---|---|---|
| GET | /v1/webhooks | List configured webhook endpoints. |
| POST | /v1/webhooks | Create an HTTPS endpoint and receive a signing secret (shown once). |
| POST | /v1/webhooks/:id/rotate-secret | Rotate the HMAC signing secret. |
| DELETE | /v1/webhooks/:id | Delete a webhook endpoint. |
Events
{
"event": "certificate.active",
"createdAt": "2026-07-21T10:20:00Z",
"data": {
"domainId": "6f9b2a1e-3c4d-4e5f-8a90-1b2c3d4e5f60",
"apex": "example.com",
"certificate": { "status": "active", "issuer": "Cloudflare" }
}
}// Verify the HMAC-SHA256 signature on every delivery.
// The signing secret (whsec_...) is shown once when you create the endpoint.
import { createHmac, timingSafeEqual } from "node:crypto";
function verify(rawBody, signatureHeader, secret) {
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
const a = Buffer.from(expected);
const b = Buffer.from(signatureHeader || "");
return a.length === b.length && timingSafeEqual(a, b);
}Errors & rate limits
Errors return a consistent envelope with a machine-readable code, a human message and the requestId.
{
"code": "validation_error",
"message": "A valid domain apex is required",
"requestId": "b3d9c1e0-7a42-4f13-9c5e-2a1b0c8d4e6f"
}| Status | Meaning |
|---|---|
400 | Validation error — check message. |
401 | Missing or invalid credentials. |
403 | Key lacks the required scope or role. |
404 | Resource not found in your organization. |
409 | Duplicate — the domain already exists. |
429 | Rate limited — honor the Retry-After header. |
502 | Upstream Cloudflare error during hostname operations. |
Rate limits. Authenticated /v1 traffic is limited to 240 requests/minute; public verification endpoints to 30/minute. Limits are enforced globally by a Cloudflare Durable Object and surfaced via X-RateLimit-Remaining, X-RateLimit-Reset and Retry-After.
Idempotency. Send an Idempotency-Key on writes to make retries safe; a replayed key returns the original result with an Idempotency-Cache-Hit header.
Ready to build?
Create an API key in the console and delegate your first domain.