- Overview
- Reference Guide
- Setup & Architecture
- Release Notes
- Workflow
- API Reference
- Integration Guide
- Discovery Agent Setup Guide
Certificate Enrollment
The Certificate Enrollment endpoints issue certificates from a CSR or from subject details, generate CSRs, renew and revoke certificates (individually or in bulk), download certificates and PFX files, import third-party certificates and trusted roots, and manage enrollment policies and ownership.
For the corresponding user interface, refer to the Enrollment section.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| GET | /enrollment | List enrollment records. |
| GET | /enrollment/alert_templates | List the templates that raise expiry alerts per CA. |
| POST | /enrollment/alert_templates | Update the templates that raise expiry alerts of the named CAs. |
| PUT | /enrollment/attach-cert | Attach a certificate to a manually entered record. |
| GET | /enrollment/audit_trail | Get the audit trail of a certificate or of a whole CA. |
| POST | /enrollment/bulk/generate | Generate certificates in bulk from an uploaded CSV. |
| POST | /enrollment/bulk/upload | Upload the CSV for a bulk certificate generation. |
| POST | /enrollment/bulk_ownership_transfer | Transfer ownership of several certificates. |
| POST | /enrollment/bulk_renewal | Renew many certificates in bulk. |
| POST | /enrollment/bulk_revoke | Revoke several certificates in one request. |
| GET | /enrollment/ca_cert_count | Count active certificates by certificate authority. |
| GET | /enrollment/cert_status | Look up the revocation status of a certificate by serial number. |
| GET | /enrollment/columns | Get the enrollment table columns. |
| POST | /enrollment/columns | Set the enrollment table columns. |
| POST | /enrollment/csr_details | Decode a certificate signing request. |
| GET | /enrollment/csr_generated_count | Number of CSRs generated per four-week period. |
| DELETE | /enrollment/delete-third-party-cert | Delete a third-party certificate record. |
| POST | /enrollment/delete-trusted-root | Remove a certificate from the trust store. |
| GET | /enrollment/download | Download an issued certificate. |
| GET | /enrollment/download_cert | Download the certificate of an enrollment record as PEM text. |
| POST | /enrollment/download_cert_enroll_pfx | Download a certificate and its private key as a PFX (PKCS#12) file. |
| POST | /enrollment/download_pfx | Download a certificate and its private key as a password-protected PKCS#12 (PFX) file. |
| POST | /enrollment/download_zip_key | Download a certificate, its chain and its password-protected private key as a zip archive. |
| POST | /enrollment/enroll-acme-ca-cert | Register a certificate obtained over ACME from a public CA. |
| POST | /enrollment/enroll_csr | Request a certificate from a CSR. |
| POST | /enrollment/enroll_on_behalf | Request a certificate on behalf of a CMP client (no CSR). |
| GET | /enrollment/enrolled_csr_details | Get the details of an enrollment record. |
| GET | /enrollment/enrollment_inventory_count | Count enrollment records by status. |
| GET | /enrollment/expiry_count | Count certificates by expiry bucket. |
| POST | /enrollment/generate_acme_cert | Request a certificate from an ACME CA. |
| GET | /enrollment/generate_aws_acm_cert | List the options for an AWS ACM certificate request. |
| POST | /enrollment/generate_aws_acm_cert | Request a public certificate from AWS Certificate Manager. |
| POST | /enrollment/generate_cert | Request a certificate with a server-generated key. |
| POST | /enrollment/generate_csr | Generate a key pair and CSR. |
| GET | /enrollment/generate_password | Generate a password that satisfies the policy. |
| POST | /enrollment/hold_cert | Place one certificate on hold. |
| GET | /enrollment/ignore_cert | List ignored certificates. |
| POST | /enrollment/ignore_cert | Ignore a certificate. |
| GET | /enrollment/ignore_templates | List the ignored templates per CA. |
| POST | /enrollment/ignore_templates | Update the ignored templates of the named CAs. |
| POST | /enrollment/import-third-party-cert | Import a third-party certificate from PEM. |
| POST | /enrollment/import-third-party-cert-manual | Record a third-party certificate from typed-in details. |
| POST | /enrollment/import-trusted-root | Add a certificate to the trust store. |
| GET | /enrollment/key_length_count | Count active certificates by key length. |
| GET | /enrollment/organization_details | Get organization details. |
| POST | /enrollment/organization_details | Set organization details. |
| GET | /enrollment/organization_info | Organization information stored for a CA. |
| GET | /enrollment/policy | Get the enrollment policy. |
| POST | /enrollment/policy | Update the enrollment policy. |
| POST | /enrollment/renew_aws_acm_cert | Renew an AWS ACM certificate. |
| POST | /enrollment/renew_cert | Renew a certificate. |
| POST | /enrollment/renew_csr | Renew a certificate with your own CSR. |
| POST | /enrollment/revoke_cert | Revoke one certificate. |
| POST | /enrollment/switch_ca | Re-issue certificates from a different CA. |
| GET | /enrollment/templates | Templates the caller can enroll against, per CA. |
| POST | /enrollment/transfer-third-party-cert | Move a certificate record to another third-party container. |
| GET | /enrollment/transfer_ownership | Transfer ownership of a certificate. |
| POST | /enrollment/trust-certificate-chain | Trust the root of a certificate's chain. |
| GET | /enrollment/trust-history | This certificate's trust chain over time. |
| GET | /enrollment/trusted-roots | List trusted root certificates. |
| POST | /enrollment/unhold_cert | Remove the hold on one certificate. |
| GET | /enrollment/unknown-certs | List third-party certificates as CSV text. |
| POST | /enrollment/update_email | Replace the notification e-mail addresses of an enrollment record. |
| POST | /enrollment/upload-chain | Upload a certificate chain for a certificate. |
| GET | /enrollment/user | Get the status of the caller's user certificate. |
| POST | /enrollment/user | Request a user certificate for the caller. |
| POST | /enrollment/user/download-cert | Download the self-service user certificate. |
| GET | /enrollment/user/manage | Get the self-service enrollment configuration. |
| POST | /enrollment/user/manage | Set the self-service enrollment configuration. |
| GET | /enrollment/view-trust-chain | View the certificate chain of a certificate. |
GET /enrollment
Certificate requests and their state, as distinct from the issued-certificate inventory under /inventory. type chooses the lifecycle state to list (default active); every other query parameter narrows the result. Most filters accept a comma-separated list and match any of the values. The caller only sees records they own or are named on (EmailID), unless view_all_user_certs=true is sent and they hold View all user certificates; for type=requested every record awaiting action is considered. Only CAs the caller's department may use are searched. type=expiring additionally needs day; type=keylength additionally needs a single integer keyLength. Both of those force Status to active. Besides the parameters listed, a cf_<custom field name> query parameter filters on that custom field (comma-separated values, case-insensitive substring match), and the custom fields defined in the product are added to every returned certificate.
Note: Call this endpoint without a trailing slash (/enrollment). The Swagger API lists it as /enrollment/.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
type |
Query | string | No | Lifecycle state of the records to list. Case-insensitive, defaults to active when omitted. It is matched against the record Status, so any status used by enrollment records works, e.g. active, expired, revoked, pending, requested, approved, denied, failed. Two values change behaviour: expiring (needs day) and keylength (needs keyLength). The handler does not reject other values, it simply returns an empty list. |
certCategory |
Query | string | No | Which kind of certificate to list. A value containing thirdparty selects imported third-party certificates, one containing certsecure selects certificates issued through CertSecure; both may be given in one string. Anything else (or empty) selects both. |
day |
Query | string | No | Expiry window in days, matched exactly against the record's expiresIn value. Required (400 otherwise) when type=expiring; ignored otherwise. |
expiration_date_from |
Query | string | No | Only certificates expiring on or after this date, YYYY-MM-DD. Must not be later than expiration_date_to. Empty means no lower bound. |
expiration_date_to |
Query | string | No | Only certificates expiring on or before this date (inclusive of the whole day), YYYY-MM-DD. Empty means no upper bound. |
keyLength |
Query | string | No | Public key size in bits. Comma-separated list of integers (2048,4096) for filtering any listing; with type=keylength it is required and must be a single integer. |
san |
Query | string | No | Substring of the subject alternative names to match, case-insensitive. |
status |
Query | string | No | Accepted for compatibility but has no effect: the Status of the result is always taken from type. A value made up only of commas and spaces is rejected. |
tags |
Query | string | No | Only certificates carrying all of these tags. Comma-separated list (production,external); send the parameter once. |
template |
Query | string | No | Certificate template name. Comma-separated list; matches any of them as a case-insensitive substring. |
view_all_user_certs |
Query | boolean | No | Send true to list every user's records rather than only the caller's. Silently ignored (the list stays limited to the caller) unless the caller holds the View all user certificates permission. false (or leaving it out) keeps the list limited to the caller. The value must be true or false in any letter case; anything else (null, 0, yes, ...) is a 400. (Until 2026-10-26 any value other than an empty one, false included, listed everyone's records for a caller who holds the permission.) |
watchers |
Query | string | No | Only certificates whose watcher list (EmailID) contains all of these e-mail addresses. Comma-separated list; exact, case-insensitive match. |
common_name |
Query | string | No | Common name filter. Comma-separated list; case-insensitive substring match on any value. |
organization |
Query | string | No | Organization (O) filter. Comma-separated list; case-insensitive substring match. |
organization_unit |
Query | string | No | Organizational unit (OU) filter. Comma-separated list; case-insensitive substring match. |
country |
Query | string | No | Country code filter. Comma-separated list; case-insensitive substring match. |
state |
Query | string | No | State or province filter. Comma-separated list; case-insensitive substring match. |
city |
Query | string | No | City or locality filter. Comma-separated list; case-insensitive substring match. |
owner |
Query | string | No | Certificate owner e-mail filter. Comma-separated list; case-insensitive substring match. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Matching enrollment records, with the CA names and template names that occur in them. |
| 400 | A filter failed validation. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the View Enrollment Database permission. |
Example Response
{
"CANames": [
"Issuing CA 1"
],
"TemplateNames": [
"WebServer"
],
"Certificates": [
{
"EnrollmentID": 1042,
"SerialNumber": "4A1B2C3D4E5F",
"CertificateAuthority": "Issuing CA 1",
"Template": "WebServer",
"Status": "active",
"EmailID": [
"[email protected]"
],
"keyLength": 2048,
"commonName": "www.example.com",
"san": "www.example.com, example.com",
"ExpiresOn": "12/31/2026 11:59 PM",
"pfxExport": "False",
"certAvailable": true,
"owner": "[email protected]",
"thirdPartyCert": false,
"tags": [
"production"
]
}
]
}
GET /enrollment/alert_templates
Returns an object keyed by CA name whose values are the alerting template names. When nothing has ever been saved, every registered CA maps to an empty array. Open to any authenticated caller.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/alert_templates" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Alerting template names per CA. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | Any unexpected failure while reading the setting. |
Example Response
{
"Issuing CA 1": [
"WebServer"
],
"Issuing CA 2": []
}
POST /enrollment/alert_templates
Restricted to global administrators and Department PKIAdmins. Responds with the lists of the CAs the request named, as stored, which can be shorter than the ones sent because unknown templates are dropped. A body that is missing, is not a JSON object, or whose alertTemplates is not an object of CA names to arrays of template names is a 400; an unexpected failure is a 500.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
alertTemplates |
object | Yes | Object keyed by CertSecure CA name; each value is the array of template names that should raise expiry alerts for that CA. Each CA named has its list replaced by the one sent, and a CA that is not named keeps its list: to stop alerting on every template of a CA, send an empty array for it. An empty object changes nothing. Template names are trimmed, and a name the CA does not publish is silently skipped. Every CA named must be registered (400 otherwise), and a Department PKIAdmin may only name CAs of their own department (403). |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/alert_templates" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"alertTemplates":{"Issuing CA 1":["WebServer"]}}'
Responses
| Status Code | Description |
|---|---|
| 200 | The alerting templates as stored. |
| 400 | The body is missing or is not a JSON object, it names no alertTemplates, alertTemplates is not an object of CA names to arrays of template names, or a CA is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is neither a global administrator nor a Department PKIAdmin (plain-text body), or a Department PKIAdmin named a CA outside their department (JSON body). |
| 500 | Any unexpected failure while reading or saving the setting. |
Example Response
{
"Templates Configured for Alerts": {
"Issuing CA 1": [
"WebServer"
]
}
}
PUT /enrollment/attach-cert
Completes a record created by POST /enrollment/import-third-party-cert-manual by attaching the real certificate PEM to it. Requires the Import Certificate permission and, in addition, being a global administrator, a Department PKIAdmin for the record's CA, or the record's owner. Only a record that has no certificate yet can be attached to (otherwise 409), and the PEM's serial number must match the serial number that was typed in (otherwise 409). Fields parsed from the certificate then replace the typed-in ones.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
cert_chain |
string | No | PEM-encoded issuing chain for the certificate, root last. |
cert_data |
string | Yes | PEM-encoded certificate body. |
eid |
integer or string | Yes | Enrollment ID of the manually entered record to attach the certificate to. Must be an integer; a numeric string is also accepted. |
watchers |
array of string | No | Email addresses notified about this certificate's expiry and lifecycle events, in addition to the owner. When omitted or empty, the watchers already on the record are kept. |
Example Request
curl -X PUT "https://<certsecure-backend-url>/enrollment/attach-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"cert_chain":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","cert_data":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","eid":1042,"watchers":["[email protected]"]}'
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate was attached. |
| 400 | A key is missing or blank, eid is not an integer, or cert_data could not be parsed as a PEM certificate. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the Import Certificate permission, or is not allowed to modify this record. |
| 404 | No enrollment record has this Enrollment ID. |
| 409 | The record already has a certificate attached, or the certificate's serial number differs from the one recorded. |
| 500 | The attach failed unexpectedly. |
Example Response
{
"Success": "Certificate attached",
"eid": 1042
}
GET /enrollment/audit_trail
Who owns, requested, approved, denied and revoked certificates, in one of two modes. One certificate. Identify it by eid (enrollment ID) or by serialNum together with ca; eid wins when both are sent, and ca is then ignored. A certificate with no recorded events yet answers 200 with empty fields. A caller who is the owner or a listed watcher of the enrollment record may read it; anyone else needs View all user certificates. When no enrollment record is found for the identifier, that permission is required and the identifier must also exist in the audit trail (404 otherwise). A whole CA. Send ca alone. Answers every audit-trail record of that CA, ordered by serial number, as {data, total}; with both count and page it answers that page as {data, total, page, count}. Names and e-mail addresses are returned unredacted, so this mode needs Manage Certification Authorities. Only certificates something has been recorded for appear. To download the same data as CSV use POST /reports/audit_trail.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate. Must be an integer (400 otherwise). Selects the one-certificate mode and takes precedence over serialNum and ca. |
serialNum |
Query | string | No | Certificate serial number, used when eid is absent; ca is then required. |
ca |
Query | string | No | CertSecure name of the Certificate Authority. With serialNum, the CA of that certificate (required, 400 otherwise). Alone, the CA whose whole audit trail to list; it must be a registered CA (400 otherwise). Ignored when eid is sent. |
count |
Query | integer | No | Whole-CA mode only: rows per page, at least 1 and capped at 500. Pagination applies only when page is sent too; sending one without the other, or a non-integer, is a 400. |
page |
Query | integer | No | Whole-CA mode only: 1-based page number. Pagination applies only when count is sent too. |
search |
Query | string | No | Whole-CA mode only: case-insensitive "contains" match on the serial number, common name, owner, requesters, approvers, deniers or revoker. At least 3 characters once trimmed (400 otherwise); blank means no search. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/audit_trail" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | One certificate: the audit trail, with every field present and empty when nothing was recorded. A whole CA: data holds one such record per certificate and total the number of matching records; page and count are echoed when paginating. |
| 400 | No identifier was sent, eid is not an integer, serialNum came without ca, ca is not a registered CA, or count/page/search are invalid. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | One certificate: the caller is not its owner or a watcher and lacks View all user certificates. A whole CA: the caller lacks Manage Certification Authorities. |
| 404 | One certificate: no audit trail exists for the identifier. |
| 500 | The lookup failed. |
Example Response
{
"enrollmentID": 1042,
"serialNumber": "4A1B2C3D4E5F",
"caName": "Issuing CA 1",
"commonName": "www.example.com",
"owner": "[email protected]",
"requesters": [
"[email protected]"
],
"approvers": [
"[email protected]"
],
"deniers": [],
"revoker": ""
}
POST /enrollment/bulk/generate
Second step of a bulk generation (the first is POST /enrollment/bulk/upload). The request does not carry certificate values: it names the previously uploaded file and maps each certificate field to the CSV column header that holds it. One certificate request, with a private key, is queued for every row. Every row must name the same CA, which is read from the column mapped by ca. order_validity and organization_id are only needed (and only checked) when that CA is a DigiCert one. A cell that is empty in a mandatory column is recorded as a failure for that row without stopping the others. The call answers 202 once every row has been processed, whether or not each one succeeded: the parent task taskID carries the totals and the per-row outcome (its status reads Completed, or Failed for N). The uploaded file is consumed when generation starts; a validation refusal (a 400) leaves it in place so the mapping can be corrected and sent again. The caller needs the Generate Certificate with Private Key permission, and file_name must be a file that same user uploaded within the last hour (otherwise 404).
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
file_name |
string | Yes | Name the CSV was uploaded under with POST /enrollment/bulk/upload. Only the caller's own uploads are visible, so another user's file, an expired one and one that never existed all answer 404. |
ca |
string | Yes | Header of the CSV column holding the CertSecure CA name for each row (the Name returned by GET /ca). Every row must hold the same CA. |
template |
string | Yes | Header of the CSV column holding the certificate template for each row. |
key_length |
string | Yes | Header of the CSV column holding the public key size in bits (for example 2048). |
common_name |
string | Yes | Header of the CSV column holding the subject common name (CN). |
organization |
string | Yes | Header of the CSV column holding the subject organisation (O). |
country_code |
string | Yes | Header of the CSV column holding the subject country (C), a two-letter ISO 3166-1 code. |
order_validity |
string | No | Header of the CSV column holding the requested validity, such as 1 year. Mandatory only when the CA is a DigiCert one. |
organization_id |
string | No | Header of the CSV column holding the numeric DigiCert organisation id. Mandatory only when the CA is a DigiCert one. |
organization_unit |
string | No | Header of the CSV column holding the subject organisational unit (OU). Optional. |
city |
string | No | Header of the CSV column holding the subject locality (L). Optional. |
state |
string | No | Header of the CSV column holding the subject state or province (ST). Optional. |
dns_names |
string | No | Header of the CSV column holding comma-separated DNS subject alternative names. Optional. |
ip_addresses |
string | No | Header of the CSV column holding comma-separated IP-address subject alternative names. Optional. |
san_emails |
string | No | Header of the CSV column holding comma-separated email subject alternative names. Optional. |
email |
string | No | Header of the CSV column holding the comma-separated email addresses of the CertSecure users to notify about the certificate (its watchers). Optional. |
group_email |
string | No | Header of the CSV column holding a distribution-list address to put in the subject. Optional; when absent the requesting user's address is used. |
owner |
string | No | Header of the CSV column holding the certificate owner's email address. Optional. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/bulk/generate" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"file_name":"certificates.csv","ca":"ca","template":"template","key_length":"key_length","common_name":"common_name","organization":"organization","country_code":"country_code"}'
Responses
| Status Code | Description |
|---|---|
| 202 | Every row was processed. This does not mean every row succeeded: see the parent task for the outcome. |
| 400 | The mapping or the uploaded file failed validation; nothing was queued. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 404 | No upload by that name belongs to the caller, or it has expired (uploads last one hour). |
| 500 | The stored CSV could not be parsed, or the run failed unexpectedly. |
POST /enrollment/bulk/upload
First step of a bulk generation. Uploads a CSV file in which each row describes one certificate, and answers with the file's columns sorted by data type so the caller can map them onto certificate fields. The second step is POST /enrollment/bulk/generate, which names this file again by file_name. The file is held on the server for one hour, per user and per file name; uploading the same name again replaces the earlier upload. It is never written to disk and nobody else can read it. The size limit is 5 MB. The caller needs the Generate Certificate with Private Key permission. The body is multipart/form-data with a single part called file. The file name must survive sanitising (path separators and similar are stripped) with something left over.
Request Body (multipart/form-data)
| Field | Type | Required | Description |
|---|---|---|---|
file |
string | Yes | The CSV file: a header row followed by one row per certificate. At most 5 MB. The name it is uploaded under is the file_name to give to POST /enrollment/bulk/generate. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/bulk/upload" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"file":"ca,template,key_length,common_name,organization,country_code\nIssuing CA 1,WebServer,2048,www.example.com,Example Corp,US\n"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The CSV was stored. Its columns, grouped by the type pandas inferred. |
| 400 | The upload was refused. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 413 | The file is larger than 5 MB. |
| 500 | The file could not be parsed as CSV, or could not be stored. |
Example Response
{
"date_cols": [
"requested_on"
],
"numeric_cols": [
"key_length"
],
"alphanumeric_cols": [
"ca",
"template",
"common_name",
"organization",
"country_code"
]
}
POST /enrollment/bulk_ownership_transfer
Makes the registered CertSecure user email the owner of each enrollment record in eids. The new owner is checked once up front (400 if not registered); after that each Enrollment ID is processed independently and the answer is 200 even when some of them fail: read successful, failed (with a reason per ID) and already_owned for the outcome. As for the single transfer, only a global administrator or the record's current owner may move a record, so for any other caller every ID lands in failed with reason User Unauthorized. A certificate that has not been issued yet (awaiting approval or the CA, denied or failed) is not transferred either: it lands in failed with reason Ownership can only be transferred after the certificate is issued. Each transfer is recorded in that certificate's audit trail.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eids |
array of integer | Yes | Enrollment IDs of the certificates to transfer. Must be a non-empty array; each element is an integer (a string of digits is also accepted). An element that is neither, for example an object, null, a boolean, a fractional number or a non-numeric string, is not looked up: it is reported in failed and the request still answers 200. |
email |
string | Yes | Email address of the registered CertSecure user who becomes the new owner. Must be a string with an @ between two non-empty parts (400 otherwise), and a registered user (400). |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/bulk_ownership_transfer" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eids":[1042,1043],"email":"[email protected]"}'
Responses
| Status Code | Description |
|---|---|
| 200 | Per-record outcome. Present even when some or all records failed. |
| 400 | The body is missing or is not a JSON object, a key is missing, eids is not a non-empty array, email is not a plausible email address, or the new owner is not a registered user. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The transfer failed unexpectedly. |
Example Response
{
"Response": "Bulk transfer of ownership complete",
"successful": [
1042
],
"failed": [
{
"eid": 1043,
"reason": "Enrollment ID not found"
}
],
"already_owned": []
}
POST /enrollment/bulk_renewal
Starts a background job that renews each listed inventory certificate and answers 202 with the id of a parent task you can follow. The job works through the serial numbers in batches of 10, 30 seconds apart. Serial numbers that another renewal job is already processing are skipped. Template maps the current template name of each certificate to the template to renew it with. Requires the Renew Inventory Certificates permission. The body is validated before anything is started (400 for a missing field, a wrong type, or a CertificateAuthority that is not registered), but the 202 only means the job was queued: a certificate that cannot be renewed, for example one whose current template is not a key of Template, fails inside the job.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
SerialNumber |
array of string | Yes | Serial numbers of the inventory certificates to renew: a non-empty array of non-empty strings. total_certificates in the response is its length. |
Template |
object | Yes | Object mapping a certificate's current template name to the template to renew it with. A certificate whose current template is not a key fails to renew inside the job. |
CertificateAuthority |
string | Yes | CertSecure name of the CA to renew against. Must be a registered CA (400 otherwise). |
additional_notes |
string | No | Free-text note stored with each renewal request. |
additional_info |
object | No | Object of extra order data merged into every renewal request (the job adds the computed order_validity). Free-form; not interpreted here. Anything but an object is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/bulk_renewal" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"SerialNumber":["4A1B2C3D4E5F","4A1B2C3D4E60"],"CertificateAuthority":"Issuing CA 1","Template":{"WebServer":"WebServer"}}'
Responses
| Status Code | Description |
|---|---|
| 202 | The job was accepted. taskID identifies the parent task that tracks the whole batch. |
| 400 | The body is missing or is not a JSON object; SerialNumber, CertificateAuthority or Template is missing or has the wrong type (SerialNumber an empty array or not an array of strings, Template not an object of strings); additional_notes is not a string; additional_info is not an object; or the CA is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Renew Inventory Certificates permission. |
| 500 | The parent task or the worker thread could not be started, or another unexpected failure. |
POST /enrollment/bulk_revoke
Starts a background job that revokes every listed certificate and answers 202 with the id of the parent task. The shape of the body and of every entry is validated before the answer (400 for an entry that is not an object, has no CertificateAuthority string, or has an eid or serialNum of the wrong type); the individual revocations are processed afterwards, one per entry, and their outcomes (queued, skipped because the record is not active, failed, including a certificate that does not exist) are recorded in the parent task and the audit log, not in this response. Each entry is processed like POST /enrollment/revoke_cert: identify the certificate by eid, or by serialNum, and always name its CA in CertificateAuthority. The caller needs the View Enrollment Database permission and, per certificate, the same rights as for a single revocation. The body is read as JSON regardless of the Content-Type header.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
certificates |
array of object | Yes | The certificates to revoke, one object per certificate. Must be a non-empty array of objects. |
revocation_reason |
string | No | Free-text reason, recorded in the job's task and audit entry. The key may be left out, but when it is sent it must be a string: null, a number, an array or an object is a 400. Its content is not validated and it is not sent to the CA. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/bulk_revoke" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"certificates":[{"CertificateAuthority":"Issuing CA 1","eid":1042},{"CertificateAuthority":"Issuing CA 1","serialNum":"4A1B2C3D4E5F"}],"revocation_reason":"cessationOfOperation"}'
Responses
| Status Code | Description |
|---|---|
| 202 | The job was accepted. taskID identifies the parent task to poll. |
| 400 | The body is empty, is not valid JSON or is not a JSON object; certificates is missing, empty, or not an array; revocation_reason is present and not a string (null included); or an entry is not an object, has no CertificateAuthority string, or has an eid that is neither an integer nor a string of digits, or a serialNum that is neither a string nor null. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the View Enrollment Database permission. |
| 500 | The job could not be started, or the request failed unexpectedly. |
GET /enrollment/ca_cert_count
Returns, for every certificate authority (or third-party container) that has active enrollment records, the number of active records filed under it. The keys of the returned object are the CertSecure CA names. An estate with no active certificates answers an empty object. Takes no input.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/ca_cert_count" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Map of CA name to the number of active certificates it issued. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"Issuing CA 1": 12,
"Third Party Container": 3
}
GET /enrollment/cert_status
Read-only status lookup used by the Proton Gateway's OCSP responder. It answers revoked when the matching enrollment record has status revoked; revoked with revocation_reason certificateHold while it is on hold (good again once released); good for any other status (expiry is not a revocation state); and unknown when no record matches. There is no per-user ownership check: the lookup is a machine query made under an API token and revocation status is not user-private. The serial number is matched in the spellings it may be stored in (as given, with :, - and spaces removed, upper and lower case, with and without a leading zero, and the decimal form of a hex value). ca narrows the search to one CA when it names a registered CA; an unknown CA name is ignored rather than rejected. revocation_time is when the revocation or hold was recorded; it is null for a certificate revoked or held before CertSecure recorded those times. revocation_reason is null for a revocation CertSecure performed: the CA revokes those as "unspecified", which an OCSP response expresses by omitting the reason.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
serialNum |
Query | string | Yes | Certificate serial number, usually hex; : and spaces are ignored. Must contain at least one non-blank character. |
ca |
Query | string | No | CertSecure name of the Certificate Authority to restrict the lookup to. Optional; a name that is not a registered CA is ignored. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/cert_status?serialNum=<serialNum>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The disposition of the certificate. revocation_time and revocation_reason accompany revoked and may be null when the record does not hold them. |
| 400 | serialNum is missing, empty or blank. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"status": "good"
}
GET /enrollment/columns
Active is the caller's saved choice (the default set until one has been saved) and Available the default set plus the names of every defined custom field.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/columns" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Columns in use and columns that can be chosen. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"Active": [
"EnrollmentID",
"commonName",
"CertificateAuthority",
"Template",
"ExpiresOn",
"SerialNumber",
"owner",
"san",
"EmailID"
],
"Available": [
"EnrollmentID",
"commonName",
"CertificateAuthority",
"Template",
"ExpiresOn",
"SerialNumber",
"owner",
"san",
"EmailID",
"Cost Center"
]
}
POST /enrollment/columns
Replaces the caller's saved column choice. No permission is needed beyond being signed in.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
columns |
array of string | Yes | Names of the columns to show, in display order. Every item must be a non-empty string (400 otherwise). The names are stored as sent, without checking them against the available columns (Available in the GET response). EnrollmentID is appended when it is missing. An empty array is accepted and stores just EnrollmentID. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/columns" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"columns":["EnrollmentID","commonName","CertificateAuthority","Template","ExpiresOn","SerialNumber","owner","san","EmailID"]}'
Responses
| Status Code | Description |
|---|---|
| 200 | The choice was saved. |
| 400 | columns is missing or is not an array (a request body that is not a JSON object counts as missing), or an item is not a non-empty string. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"Message": "Success"
}
POST /enrollment/csr_details
Parses a PEM-encoded PKCS#10 CSR and returns its public-key type and size, the subject attributes, and the subject alternative names. Nothing is stored; the request is only logged. A value that cannot be parsed as a CSR is answered with 400 Invalid CSR.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
csr |
string | Yes | PEM-encoded PKCS#10 certificate signing request, including the -----BEGIN CERTIFICATE REQUEST----- armour. |
ca |
string | No | Optional. Together with template, selects Sectigo PS key-policy checks: when both name a Sectigo PS CA and one of its templates, the CSR is also checked against the key policy of that template. Ignored for every other CA. |
template |
string | No | Optional. Used with ca for the Sectigo PS key-policy check described there; ignored otherwise. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/csr_details" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC6zCCAdMCAQAwbDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYD\nVQQHDAZEYWxsYXMxFTATBgNVBAoMDEV4YW1wbGUgQ29ycDELMAkGA1UECwwCSVQx\nGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAOChnT6tEg0GgE4vjp/3RUx/psYPGuoK3606TpORcBN98xvqMNLO\nYILpbwjrlkmdJjYTJVT1yHXA9PYTvpD12DcYe08UHSQOQkC0vC7qNDZHXgOlVD8d\nG9ReQAP6KGgD7O1l0oi6wwiK5q1YNLliRVCB+PdXB2coDbyDi7GxaPVcSiWU6pdG\nC5WWRldyRAmYj18iKi72RZQjHRc3C7aGQFaSySjjO1t9ZLpubqGWMHfoOyhUOPL4\npnI/tOJmYROK4aceYjlM+hDH2ndU7ZvItnKS1cQYS71Dfjzv0VwI5rUuyidgM7/R\nWNHkZWoV1h4+F/WWtQlGN5L2APuL89yVTrcCAwEAAaA6MDgGCSqGSIb3DQEJDjEr\nMCkwJwYDVR0RBCAwHoIPd3d3LmV4YW1wbGUuY29tggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAAOCAQEAEApMFMCPeZet/95ukhjHBgbpQDVjhxiRyg7hxcuRmBcJ\nNIHqjVW9F3ryFD+fHXrTMZJGkgaKgw1OZXlsz1j7GvwIKnaDqO2Yix/wQr07btDD\n5RMysRzOnWkcHsinDBY6VWYgMliTkA5VKTkQ+Lq1kL6cTekyaGJv3g8Suj0Hdj+M\npqKo5KjzyRK1L18hZmh7atsd9LobjNIRqm8CnuU3ympGdO/Dz80PjIPfqt3XwMpD\nNrQ6LSh71Ewfe9xNuvNrBYWo06pKoHAsVLxDzjNGVYgdouOptBP8PXsIwx+LYcYL\nzQes0tQtk85fWSwwstIw8RHTCqj+bq22Fb63n1UFpQ==\n-----END CERTIFICATE REQUEST-----\n","ca":"Issuing CA 1","template":"WebServer"}'
Responses
| Status Code | Description |
|---|---|
| 200 | Details decoded from the CSR. |
| 400 | The request body has no csr key, or the value is not a parseable PEM CSR. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | Sectigo PS only: the caller is neither a global administrator nor in a department entitled to the CA named in ca. |
Example Response
{
"key_type": "RSA",
"key_size": 2048,
"attributes": {
"C": "US",
"ST": "Texas",
"L": "Dallas",
"O": "Example Corp",
"OU": "IT",
"CN": "www.example.com"
},
"san_attributes": "DNS:www.example.com, DNS:example.com",
"email": ""
}
GET /enrollment/csr_generated_count
How many CSRs were generated through POST /enrollment/generate_csr in each of the last four four-week periods (0-4 is the most recent four weeks, 12-16 the oldest). Counts all CAs unless ca narrows them to one. Any authenticated caller may read it.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
ca |
Query | string | No | CertSecure name of a Certificate Authority to count for. Optional: omit it to count across all CAs. When sent it must be a registered CA, so an empty value is a 400. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/csr_generated_count" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | One count per period; the keys are the period labels, in weeks ago. |
| 400 | ca was sent but is not a registered CA. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The counts could not be produced. |
Example Response
{
"0-4": 3,
"4-8": 1,
"8-12": 0,
"12-16": 5
}
DELETE /enrollment/delete-third-party-cert
Removes the enrollment record with the given Enrollment ID. Allowed for a global administrator, for a Department PKIAdmin whose department holds the record's CA, and for the record's owner; anyone else is answered with 403. The handler looks the record up by Enrollment ID only and does not check that it is a third-party record.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
EID |
integer or string | Yes | Enrollment ID of the record to delete. Must be an integer; a numeric string is also accepted. |
Example Request
curl -X DELETE "https://<certsecure-backend-url>/enrollment/delete-third-party-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"EID":1044}'
Responses
| Status Code | Description |
|---|---|
| 200 | The record was deleted. |
| 400 | The EID key is missing or is not an integer. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is neither a global administrator, a Department PKIAdmin for the record's CA, nor the record's owner. |
| 404 | No enrollment record has this Enrollment ID. |
Example Response
{
"Success": "Certificate deleted"
}
POST /enrollment/delete-trusted-root
Deletes the trust-store entry whose Subject Key Identifier matches ski, then triggers a background rebuild of stored chains. Unlike the import endpoints, this handler checks no permission beyond authentication.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
ski |
string | Yes | Subject Key Identifier of the trusted root to remove, hexadecimal, as returned by GET /enrollment/trusted-roots. Must be a string: anything else, such as an object, is a 400 (the value is used as a database filter). |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/delete-trusted-root" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ski":"4a1b2c3d4e5f60718293a4b5c6d7e8f901234567"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The trust-store entry was removed. |
| 400 | The body is missing or is not a JSON object, ski is missing or empty, or ski is not a string. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 404 | No trust-store entry has this Subject Key Identifier. |
| 500 | The deletion failed unexpectedly. |
Example Response
{
"Success": "Trusted root certificate with SKI (4a1b2c3d4e5f60718293a4b5c6d7e8f901234567) deleted successfully"
}
GET /enrollment/download
Returns the certificate of an active enrollment record in the requested format. Identify the record with eid, or with taskID of the request that produced it (when taskID is present eid is ignored). type=cer (the default) returns the certificate as PEM text; p7b returns the stored PKCS#7 chain as PEM text; text returns every certificate of the chain, concatenated as PEM text; zip returns an archive holding the certificate, the chain and the full-chain bundle in DER and PEM form. The text formats are served as text/html, the archive as application/zip with a Content-Disposition header naming <commonName>.zip. The caller needs the View Enrollment Database permission and must also hold Download Certificate, be a global administrator, be a Department PKIAdmin whose department owns the CA, or be the owner or a listed watcher of the record. p7b, zip and text need the record to hold a chain, which records that were not issued through CertSecure may not.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate to download. Required unless taskID is sent (400 otherwise); must be an integer. |
taskID |
Query | integer | No | Id of the task that created or renewed the certificate; its enrollment ID is looked up from it. Alternative to eid. An unknown task id is not handled and fails the request. |
type |
Query | string | No | Format to download: cer (certificate, PEM), p7b (PKCS#7 chain, PEM), text (all certificates of the chain, PEM) or zip (archive). Case-insensitive; default cer. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/download" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate in the requested format. cer, p7b and text are PEM text served as text/html; zip is a binary archive. |
| 400 | No identifier was sent, eid is not an integer, the record holds no certificate, or type is not supported. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission (JSON), or may not download this certificate (plain text). |
| 404 | There is no active enrollment record with this id, or type=p7b was asked of a record that holds no chain. |
| 500 | The requested format could not be produced, for example a zip or text of a record that holds no chain. |
GET /enrollment/download_cert
Returns the PEM certificate of an active enrollment record. Identify the record with eid, or with taskID of the request that produced it (when taskID is present eid is ignored). The body is the bare PEM text, served as text/html. The caller needs the View Enrollment Database permission and must also hold Download Certificate, be a global administrator, be a Department PKIAdmin whose department owns the CA, or be the owner or a listed watcher of the record. For other formats (PKCS#7, chain, archive) use GET /enrollment/download.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate to download. Required unless taskID is sent (400 otherwise); must be an integer. |
taskID |
Query | integer | No | Id of the task that created or renewed the certificate; its enrollment ID is looked up from it. Alternative to eid. An unknown task id is not handled and fails the request. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/download_cert" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate in PEM form. |
| 400 | No identifier was sent, eid is not an integer, or the record holds no certificate. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission (JSON), or may not download this certificate (plain text). |
| 404 | There is no active enrollment record with this id. |
| 500 | The certificate could not be read. |
POST /enrollment/download_cert_enroll_pfx
Builds a password-protected PKCS#12 bundle from the stored certificate of an active enrollment record and the private key the caller supplies, and returns it as a file download named Enrollment_<EnrollmentID>.pfx. CertSecure does not keep the key: it must be sent in key (PEM, optionally encrypted, in which case KeyPassphrase is required), and it must belong to the stored certificate. Requires the Download Certificate permission. A key that is wrong, undecryptable or not matching the certificate is answered 400, as is a missing or empty key. The fields are type-checked first: EnrollmentID, ExportPassword, key and algo of the wrong type are a 400 that names the field. The SHA1-3DES profile needs the OpenSSL legacy provider on the server; where it is missing the request is answered 400 with a message saying so (it is not a problem with the key) and OpenSSL's output in details. Algorithm is an older spelling of algo that is still read (it wins when it is non-empty) but is no longer part of the contract; send algo.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
EnrollmentID |
integer or string | Yes | Enrollment ID of the certificate to export: an integer, or a string of digits. Anything else (a sign, a fraction, a boolean, an object) is a 400. The record must exist, be active and hold a certificate. |
ExportPassword |
string | Yes | Password that protects the exported PFX file. Required; must be a string that meets the product's password policy (a weaker one is a 400 naming each rule it breaks). The schema states the policy every install starts with: 9 to 16 characters, at least 2 upper-case, 2 lower-case, 2 digits and 1 special character (ASCII punctuation); an administrator can change it with POST /enrollment/policy, and the server then enforces the changed one. This is the password of the new PFX, so KeyPassphrase (the existing key's own passphrase) is not held to it. |
KeyPassphrase |
string | No | Passphrase of the private key in key. Needed only when that key is encrypted; omit it for an unencrypted key. |
algo |
string or string | No | Encryption profile of the PFX: SHA256-AES (AES-256 with SHA-256 MAC, the default) or SHA1-3DES (legacy, 3DES with SHA-1 MAC, for old consumers). Case-insensitive. The empty string, which the web interface sends for the default, and an omitted key both mean SHA256-AES. A value that is not a string is a 400, and so is an unknown profile name (Unsupported algorithm profile). |
key |
string | Yes | The certificate's private key as PEM (-----BEGIN PRIVATE KEY----- or -----BEGIN RSA PRIVATE KEY-----, or the encrypted forms). It must match the stored certificate. Required and non-empty (400 key should be passed otherwise); must be a string. Sending a CSR or a certificate here is rejected with 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/download_cert_enroll_pfx" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"EnrollmentID":1042,"ExportPassword":"Export-Pa55word!","KeyPassphrase":"Key-Pa55phrase!","algo":"SHA256-AES","key":"-----BEGIN ENCRYPTED PRIVATE KEY-----\nMIIFNTBfBgkqhkiG9w0BBQ0wUjAxBgkqhkiG9w0BBQwwJAQQGVlWzGmPF8bGWiEq\nxtx6CQICCAAwDAYIKoZIhvcNAgkFADAdBglghkgBZQMEASoEEG5D9WtEC7ibVgju\n42VTFoIEggTQeGNYtvCUOtVK4lvobf0i0c6xLOHyGwmBFqiDO7W5pqgmRWqGjrm6\ndFU3XdjmfzH9JKrSrLuZgwLbT7k345crGRivzOf0DQqkda4l8oh/f+Vor19jdPnX\nlxnQ1MrbvLXldGLDn9jgYTYJfHN3gcU69I49tnfYPhJiKhCEeu55u3BBDlHXgFyd\nEC1mDYNgvR1vRggIZDZqdYFTR07ZgqImB5tJpRUMwCvk4WTwOdbt0AAmSQ8oCF8v\ng1tFGYU0K0rMEO3Q3KwzRUKPxiCB68MgytnnyLoy/kmGxJqPVhhdkwDeKJ3UHPN4\nuyvtz6rZv6XRYUiYKdgsrNZ99eTvkNi+G0KaZ549Z6cjTO9SPle8S0xrj3XNlpGm\nHftGNoZunRcoh1ejobvZC505uhhaFZni+FPkPdisG7LyB2o3hFbzoPpVIyDcqEF0\nkuAVFByPs5GPPAsI8sLs5mdom0qd96CW4VNSJ21hZ4KsFt7v835zG0Jr4wgNR62q\n+Ic985ScuUNBpQNlq4T+i4dozOGbf0VwaNVljPTIDuCOMj36cTcuwIuxjbJo5imm\nQff8LfwgevVeQU627WOfIItVH0c9z0EFaDiE3pmYKZnTJvouehUts86JUSieSgHr\nWdqon82XBCGxHtE0JE9kVJYNd4FmJriyv0txtqsH+tm2CJOsFTEpmnTJU+qycUPf\njEssl+00BuDSVuE95+m1NcEqjEeWoliWd3hN8Dscd0vkl2MqQB387D+32NqNUJOY\n3pX8WF0sp8ocoK9ssvvWWA/AGN19pf8UGcSebknRT8daxnDRf6kEjWrY/Q90f+Ht\nojgXbWVr3Ftr+RxbuTtTQ4HWnOaalFDrqNlHpPqcJinViGWXYTMYi7xdmwLtRnlT\nj301x2Ixq9HzgxDo0zrTOP2FyYaplgWJJMQ9qyRzqVIoi9bU3OA2teYO6S/Z6O2J\n7VKpLqnaDD4zmSz0uGUVlenhdSeEQG6dhnkUiGt3B8uobWKUQGxXDzDv/wL4sgrO\niDo+IuAKHOBk59hyJ66dGzgcU81DdSUyPUUOmz7zCPRNldb5zNAdwwGW9Xi8P18k\nqE9Zn9WRm1nghz7hru1E0AfAxK0g+dLZjsTP63eWOiaCBkVonVJdb7ePXI/bM74o\nlCvL5gOCuuvE8OUd2qVE1iUYHj2DQ2130/X/gd8MjbysU8aMmfeAIr4WTgr1UEnJ\nJ8HILhAPHDyL4wN0NXRzH8a4cT9rKUEs/dOBYgUrMJePTmpizi9OlesFDUN1EnJq\nRnedvfaaIa+EsqzQAbBMpF4tYS07nCFzZb6vfuD6n4yBQg1eIR7BqC8L58o8faNC\nNUDc91I9rNKxvvjQ/geR55izOr6haFQHKyufp1yM1RdYkwvP1PORwc7NoXou2IvB\nX3kx1LxZu++8FJPuR7zpgDkP89+kjalaWZr3Ca1I8yNDpaMraC/jcfDOBZPbPG1s\ncqKDnc1wy9q193l3ZPtB/PMKjL3f+nmlKicixALsORENx7i9G7Lh2cB2A/ZpjTHC\nL5e+kYDld5bxj8Xa7KsoJtYsVXZasl/ruta0y4fEGZxjK00RBFcpU3tQgQRo8l+2\n0gwRk+Md260mQ1JBJjj6jY7/I9Q/IRxTeFA5e8Of8etSEyWAQwzFDjY=\n-----END ENCRYPTED PRIVATE KEY-----\n"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The PFX file, sent as an attachment named Enrollment_<EnrollmentID>.pfx. |
| 400 | EnrollmentID, key or ExportPassword is missing or of the wrong type, key is the wrong kind of PEM or does not match the certificate, or OpenSSL could not build the PFX. Further 400 messages, produced once the record has been found: Valid PRIVATE KEY PEM block not found in request.key and Unsupported algorithm profile: <value>. Failures raised by OpenSSL also carry a details key with up to 800 characters of its output. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Download Certificate permission. |
| 404 | No active enrollment record has this Enrollment ID. |
| 500 | The record has no certificate stored, or the export failed unexpectedly. |
POST /enrollment/download_pfx
Exports the certificate and the private key stored with an active enrollment record as a PKCS#12 file protected by password. Identify the record with eid, or with taskID of the request that produced it (eid wins when both are sent). password must satisfy the password policy configured in the product (minimum length and minimum counts of upper-case, lower-case, digit and special characters). The record must hold both a certificate and a private key. The response body is the raw PKCS#12 file; the handler sends it without setting a content type, so it is labelled text/html. The caller needs the View Enrollment Database permission and must also hold Download Certificate, be a global administrator, be a Department PKIAdmin whose department owns the CA, or be the owner or a listed watcher of the record.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
algorithm |
Query | string | No | Encryption used inside the PFX. SHA1-3DES selects PBE-SHA1-3DES with a SHA-1 MAC (legacy), SHA256-AES selects AES-256-CBC with a SHA-256 MAC; case-insensitive. Any other value, or none, leaves the OpenSSL default. |
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
password |
string | Yes | Password protecting the PFX. Must meet the product's password policy; a weaker one is answered with 400 naming each rule it breaks. The schema states the policy every install starts with: 9 to 16 characters, at least 2 upper-case, 2 lower-case, 2 digits and 1 special character (ASCII punctuation). An administrator can change the policy with POST /enrollment/policy, and the server then enforces the changed one. |
eid |
integer or string | No | Enrollment ID of the certificate. An integer or an integer string. Required unless taskID is sent. |
taskID |
string | No | Id of the task that created or renewed the certificate, as a string of digits; its enrollment ID is looked up from it. Alternative to eid, used only when eid is absent. When it is sent it must be a string of digits even if eid is also sent (and wins): anything else, including null, a number or an empty string, is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/download_pfx" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1042,"password":"ExamplePass#42"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The PKCS#12 file (binary), served with a text/html content type. |
| 400 | A field is missing or invalid, the password breaks the policy, or the record lacks a certificate or key. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission (JSON), or may not download this certificate (plain text). |
| 404 | There is no active enrollment record with this id. |
| 500 | The PFX could not be produced. |
POST /enrollment/download_zip_key
Builds a zip archive with the certificate, the chain and the full-chain bundle in DER and PEM form, plus the private key re-encrypted with password (as <commonName>_privkey.key and pem/<commonName>_privkey.pem). Identify the record with eid, or with taskID of the request that produced it (eid wins when both are sent). The private key is the one stored with the record unless privateKey is sent; a key sent in privateKey must be PEM encrypted with the same password, otherwise 400. The body must be a JSON object, password and privateKey must be strings and a taskID that is sent must be a string of digits even when eid is also sent (a 400 names the field otherwise); eid still wins and the two are not compared. password must satisfy the password policy configured in the product (minimum length and minimum counts of upper-case, lower-case, digit and special characters). Success is the archive, application/zip, with a Content-Disposition header naming <commonName>.zip. The caller needs the View Enrollment Database permission and must also hold Download Certificate, be a global administrator, be a Department PKIAdmin whose department owns the CA, or be the owner or a listed watcher of the record. Several validation failures are answered as plain text (text/html) and the rest as JSON; both are listed.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
password |
string | Yes | Password that protects the private key inside the archive. Must meet the product's password policy; a weaker one is answered with 400 naming each rule it breaks. The schema states the policy every install starts with: 9 to 16 characters, at least 2 upper-case, 2 lower-case, 2 digits and 1 special character (ASCII punctuation). An administrator can change the policy with POST /enrollment/policy, and the server then enforces the changed one. |
eid |
integer or string | No | Enrollment ID of the certificate. An integer or an integer string. Required unless taskID is sent. |
taskID |
string | No | Id of the task that created or renewed the certificate, as a string of digits; its enrollment ID is looked up from it. Alternative to eid, used only when eid is absent. When it is sent it must be a string of digits even if eid is also sent: anything else, including null, a number or an empty string, is a 400. |
privateKey |
string | No | PEM private key to put in the archive, either unencrypted or encrypted with password; it is always re-encrypted with password in the archive. Optional: when omitted or the empty string, the key stored with the enrollment record is used (400 when there is none). A key that cannot be read (not PEM, or encrypted with another password) is a 400; a value that is not a string, including null, is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/download_zip_key" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1042,"password":"ExamplePass#42"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The archive. The Content-Disposition header names it <commonName>.zip. |
| 400 | The body is not a JSON object, a field is missing or invalid, the password breaks the policy, a supplied privateKey cannot be read, or the record holds no private key. Identifier and password-presence problems are plain text; the new type messages, the policy and the key messages are JSON. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission (JSON), or may not download this certificate (plain text). |
| 404 | There is no enrollment record with this id. |
| 500 | The archive could not be built, for example because the stored key could not be read or the record holds no chain. |
POST /enrollment/enroll-acme-ca-cert
Records a certificate that was obtained directly over ACME from a public CA as a normal CA-issued enrollment record: CertificateAuthority is the registered name of the ACME CA named by ca (not a third-party container), and the record is created as already issued, with an enrollment task logged against it. The CA must already be registered as an ACME CA under CA Management; the certificate is filed under a template that CA has. Requires the Import Certificate permission. A certificate with the same serial number under the same CA is refused with 404.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Not interpreted. |
ca |
string | Yes | CertSecure name of an ACME Certificate Authority, as registered under CA Management (the Name returned by GET /ca, not the CA's subject DN). A name that is not an ACME CA, a Microsoft or DigiCert CA for example, is refused with 400 No ACME CA named '<name>' is registered. |
cert_chain |
string | No | PEM-encoded issuing chain for the certificate, root last. |
cert_data |
string | Yes | PEM-encoded certificate body. |
domain_id |
string | No | Optional. Identifier of the ACME domain entry used for DNS-01 validation, as listed by GET /acme/get_domains. When given it must exist, otherwise the request is rejected with 400. |
tags |
array of string | No | Free-form labels attached to the certificate for grouping and reporting. |
watchers |
array of string | No | Email addresses notified about this certificate's expiry and lifecycle events, in addition to the owner. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/enroll-acme-ca-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"additional_notes":"Issued for the public web front end.","ca":"API Test ACME","cert_chain":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","cert_data":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","domain_id":"37105","tags":["production","external"],"watchers":["[email protected]"]}'
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate was registered. eid is the new Enrollment ID. |
| 400 | A required key is missing, ca does not name a registered ACME CA, domain_id does not exist, or cert_data could not be parsed. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Import Certificate permission. |
| 404 | A record with this serial number already exists under the same CA; the message names its Enrollment ID. (Reported as 404 by this endpoint, not 409.) |
| 500 | The enrollment failed unexpectedly. |
Example Response
{
"eid": 1042
}
POST /enrollment/enroll_csr
Submits a CSR you generated yourself and queues a certificate request for it; the response is the id of the task that tracks the request. The CSR is parsed (an unreadable one is a 400) and the subject is taken from it. The CA must be registered and the template must be one it publishes. Requires the Submit CSR permission. Whether the request then needs approval depends on the template workflow and on the request policy, which can raise the approvals required for callers other than administrators. SANs are the CSR's own plus san_attributes, unless override_csr_sans is true, when only san_attributes is used. For an ACME CA the CSR's DNS names must all belong to one registered, validated ACME domain; for CAs that build their request from a policy template the CSR is validated against that policy (a violation is a 400). To renew an existing certificate with your own CSR, use POST /enrollment/renew_csr; renews_serial is no longer accepted here. The optional fields are type-checked before anything else is looked at (a wrong type is a 400 naming the field). Several refusals come back as plain text (text/html) rather than JSON, and an unexpected failure is a 400 with a generic Error message; the reason is in the CertSecure log.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
csr |
string | Yes | PEM-encoded PKCS#10 certificate signing request, including the -----BEGIN CERTIFICATE REQUEST----- armour. It must parse (400 Invalid CSR otherwise). |
template |
string | Yes | Certificate template to issue against. Must be one the chosen CA publishes (400 Not a correct template mapping otherwise); GET /enrollment/templates lists them. For a Sectigo CA the numeric certificate type id is accepted in place of the name. |
ca |
string | Yes | CertSecure name of the Certificate Authority to request from. Must be a registered CA (400 otherwise). |
email |
array or string | No | E-mail addresses to notify about the request and the issued certificate (its watchers): an array of strings, or the empty string for none (what the web interface sends when there are no watchers). Any other type, including a non-empty string and null, is a 400. |
san_attributes |
string or array | No | Additional subject alternative names, as comma-separated entries: DNS:, IP:, IPAddress:, Email: or OtherName: followed by the value, or type=value (for example dns=host). Sent as one string, or as an array of such entries. An entry in any other form is a 400, and so is any other type, including null. Empty means none. Merged with the SANs in the CSR unless override_csr_sans is true. |
override_csr_sans |
boolean | No | When true, only the SANs in san_attributes are used and the ones carried inside the CSR are dropped; when false or left out, the two lists are merged. Must be a boolean when sent: anything else, including null, is a 400. |
renews_serial |
object | No | No longer accepted: renew with POST /enrollment/renew_csr. A request that carries this field, with any value, is refused with a 400 so that it is never enrolled as an unlinked new certificate in place of the renewal it asked for. |
tags |
array of string | No | Free-form labels attached to the certificate for grouping and reporting. Must be an array of strings when sent: anything else, including null, is a 400. |
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Must be a string when sent: anything else, including null, is a 400. |
additional_data |
object | No | Caller-supplied data stored on the request task. Free-form. For a policy-template CA it may carry organization_id, term and external_requester, which are passed to the CA; the data the policy produces then replaces it. |
customFields |
array | No | Values for administrator-defined custom fields, as {"name": ..., "value": ...} objects, for example [{"name": "Cost Center", "value": "CC-1042"}]. Every name must be a defined custom field (POST /customFields/create) and every field defined as required must be present, otherwise 400. Optional when no defined field is required; null counts as no values, like leaving the key out. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/enroll_csr" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC6zCCAdMCAQAwbDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYD\nVQQHDAZEYWxsYXMxFTATBgNVBAoMDEV4YW1wbGUgQ29ycDELMAkGA1UECwwCSVQx\nGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAOChnT6tEg0GgE4vjp/3RUx/psYPGuoK3606TpORcBN98xvqMNLO\nYILpbwjrlkmdJjYTJVT1yHXA9PYTvpD12DcYe08UHSQOQkC0vC7qNDZHXgOlVD8d\nG9ReQAP6KGgD7O1l0oi6wwiK5q1YNLliRVCB+PdXB2coDbyDi7GxaPVcSiWU6pdG\nC5WWRldyRAmYj18iKi72RZQjHRc3C7aGQFaSySjjO1t9ZLpubqGWMHfoOyhUOPL4\npnI/tOJmYROK4aceYjlM+hDH2ndU7ZvItnKS1cQYS71Dfjzv0VwI5rUuyidgM7/R\nWNHkZWoV1h4+F/WWtQlGN5L2APuL89yVTrcCAwEAAaA6MDgGCSqGSIb3DQEJDjEr\nMCkwJwYDVR0RBCAwHoIPd3d3LmV4YW1wbGUuY29tggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAAOCAQEAEApMFMCPeZet/95ukhjHBgbpQDVjhxiRyg7hxcuRmBcJ\nNIHqjVW9F3ryFD+fHXrTMZJGkgaKgw1OZXlsz1j7GvwIKnaDqO2Yix/wQr07btDD\n5RMysRzOnWkcHsinDBY6VWYgMliTkA5VKTkQ+Lq1kL6cTekyaGJv3g8Suj0Hdj+M\npqKo5KjzyRK1L18hZmh7atsd9LobjNIRqm8CnuU3ympGdO/Dz80PjIPfqt3XwMpD\nNrQ6LSh71Ewfe9xNuvNrBYWo06pKoHAsVLxDzjNGVYgdouOptBP8PXsIwx+LYcYL\nzQes0tQtk85fWSwwstIw8RHTCqj+bq22Fb63n1UFpQ==\n-----END CERTIFICATE REQUEST-----\n","template":"WebServer","ca":"Issuing CA 1","email":["[email protected]"],"san_attributes":"DNS:www.example.com,DNS:example.com","override_csr_sans":false,"tags":["production"],"additional_notes":"Web server certificate request"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued. TaskID identifies the task that tracks it. |
| 400 | The request was refused: a required field is missing, an optional field has the wrong type, the CSR, CA, template, SANs or custom fields are unusable, or the request failed in a way the handler reports as 400. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Submit CSR permission. |
| 404 | The CA has no template policy, or no details for the template, on record. |
| 500 | The CSR could not be validated against the CA policy, or the CA's inventory has not been refreshed yet. |
Example Response
{
"TaskID": "5821"
}
POST /enrollment/enroll_on_behalf
RA-attested "on-behalf" enrollment, used by the Proton Gateway after it has terminated a CMPv2 ir/kur exchange. Instead of a CSR, the caller submits the end entity's public key (and optionally its subject and requested extensions) as base64-encoded DER. The request is queued as an issue_on_behalf task which the CA connector issues through an Enrollment-Agent CMC request on AD CS. The CSR-based path (POST /enrollment/enroll_csr) is not involved. The caller needs the Submit On-Behalf Request permission. The response only confirms the request was queued: follow TaskID through GET /tasks for the outcome. The CA and template named in the request must exist and be mapped to each other, otherwise the request is refused with a 400. Error bodies are not uniform: the presence checks answer with a bare text string (text/html), the validation checks with {"Error": ...}, and an unexpected failure with {"Error:": ...} (the key really does carry a trailing colon).
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
public_key |
string | Yes | The key to certify, as the base64 encoding of its DER SubjectPublicKeyInfo (not PEM). Must be non-empty, valid base64. |
template |
string | Yes | Certificate template to issue against. Must be one the chosen CA publishes (GET /inventory/templates lists them). |
ca |
string | Yes | CertSecure name of the Certificate Authority to issue from. This is the Name returned by GET /ca, not the CA's subject DN. The CA must be registered, otherwise the answer is a 400. |
subject |
string | No | Requested certificate subject, as the base64 encoding of a DER Name. Optional; an empty string is treated as absent. A non-empty value must be valid base64. |
extensions |
string | No | Requested X.509 extensions, as the base64 encoding of a DER Extensions sequence. Optional; an empty string is treated as absent. A non-empty value must be valid base64. |
crmf |
string | No | The original CMP CRMF certificate-request message (base64 DER CertReqMsg) carrying the end entity's own proof-of-possession. When present the CA connector re-presents it to AD CS; when absent a throw-away proof is used. Optional; a non-empty value must be valid base64. |
pop_verified |
boolean | No | Whether the gateway verified the proof-of-possession for public_key before forwarding it. Asserted by the gateway and recorded on the request; any value is read as a boolean and the default is false. |
old_serial |
string | No | Hex serial number of the certificate being replaced, for a CMP key-update (kur) request, so the connector can revoke it as superseded once the new certificate has issued. Omit it on a first issuance (ir). |
email |
array of string | No | Email addresses of CertSecure users to notify about this request (its watchers). Optional. Each entry must be a string. |
tags |
array of string | No | Free-form labels attached to the certificate for grouping and reporting. Optional; anything other than a list is ignored. |
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Not interpreted. |
additional_data |
object | No | Caller-supplied data carried onto the queued task unchanged. Optional; any JSON value is accepted. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/enroll_on_behalf" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"public_key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+njHpGH32ysr129ASPPGDSg0KPji1bJzMBa91voQBbH+z95QukB1crgPTdK5Ov9t/J4p9xH6ujVgT/J+52Bn/WFnAZ0N89XXW1GuqqCgcOfyR7mKgs/caRRsvow15zoTfimq0XtxMhFKhBEZmmwsjgRwNf76RU+mvpckGqW+ignXC3mubuI6BtElK8EDaPBt1/m5EddgIMR8Du4Dly/GY0Fh/4R6qcPdSzHhXjGI9NJSJg2HQPOdALKYt194HVK+64F7F43kHYVkIJaxVAWuW0Eefztu4MroCe9JcWs7qlDiwUWsb4VwXak/Cvik2BbQBIwvZgRgz2v4nSec+dRGQwIDAQAB","subject":"MBoxGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbQ==","extensions":"MBwwGgYDVR0RBBMwEYIPd3d3LmV4YW1wbGUuY29t","pop_verified":true,"template":"WebServer","ca":"Issuing CA 1","email":["[email protected]"],"tags":["production","external"],"additional_notes":"Issued for the branch-office gateway."}'
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued. Follow the task for the outcome. |
| 400 | The request was refused. Missing keys and an empty public_key answer with a bare text string (text/html); every other refusal is JSON. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Submit On-Behalf Request permission. |
Example Response
{
"TaskID": "2417"
}
GET /enrollment/enrolled_csr_details
Returns the request details of one certificate: subject fields, SANs split by kind, status, owner and watchers. Identify the certificate with exactly one of eid (enrollment ID), taskID (the task that requested it) or serialNum together with ca; when several are sent, eid is used first, then taskID, then serialNum. For eid and taskID the caller must hold View all user certificates or be the record's owner or a listed watcher (403 otherwise). A serialNum lookup falls back to the CA inventory when the certificate has no enrollment record and then needs a global administrator, a Department PKIAdmin of that CA, or the View Inventory permission; in that case the SAN fields are empty and the document has the inventory shape (Serial Number, Watchers, ... instead of EnrollmentID, EmailID). Several failures are answered as plain text (text/html) rather than JSON; both are listed.
Note: Pass eid, taskID, or serialNum together with ca.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate. Takes precedence over taskID and serialNum. Must be an integer (400 otherwise). At least one of eid, taskID, serialNum is needed. |
taskID |
Query | integer | No | Id of the task that requested the certificate; its enrollment ID is looked up. Used when eid is absent. An unknown or non-numeric task id is not handled and fails the request. |
serialNum |
Query | string | No | Certificate serial number, used when neither eid nor taskID is sent. ca must accompany it: without ca the handler fails with 500. |
ca |
Query | string | No | CertSecure name of the Certificate Authority of the certificate. Needed with serialNum (an unregistered name is a 400, a missing one a 500); ignored with eid or taskID. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/enrolled_csr_details" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate details. Fields for an enrollment record are listed; a certificate found only in the CA inventory is returned in the inventory shape instead. |
| 400 | No identifier was sent or eid is not an integer (plain text), or the CA of a serialNum lookup is not registered (JSON). |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller may not see this certificate. JSON for eid/taskID, plain text for serialNum. |
| 404 | No enrollment record or inventory certificate matches. |
| 500 | The lookup failed, for example serialNum was sent without ca. |
Example Response
{
"EnrollmentID": 1042,
"CertificateAuthority": "Issuing CA 1",
"Template": "WebServer",
"Status": "active",
"EmailID": [
"[email protected]"
],
"keyLength": 2048,
"commonName": "www.example.com",
"san": "dns=www.example.com&dns=example.com",
"sanDNSNames": [
"www.example.com",
"example.com"
],
"sanIPAddresses": [],
"sanEmails": [],
"ExpiresOn": "12/31/2026 11:59 PM",
"pfxExport": "False",
"certAvailable": true,
"organization": "Example Corp",
"organizationUnit": "IT",
"state": "Texas",
"country_code": "US",
"city": "Dallas",
"owner": "[email protected]",
"certIgnored": false,
"thirdPartyCert": false
}
GET /enrollment/enrollment_inventory_count
Number of enrollment records in each lifecycle status, across all CAs and users. Any authenticated caller may read it; it is not scoped to the caller's department.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/enrollment_inventory_count" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | One count per status. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"active": 128,
"denied": 4,
"expired": 37,
"pending": 9,
"revoked": 12,
"failed": 2
}
GET /enrollment/expiry_count
Returns how many tracked certificates are currently filed in each of the 7, 30, 60 and 90 day expiry buckets. The counts are read from the pre-computed expiry collection that the background refresh job maintains, so they are only as fresh as the last refresh run. Takes no input; each call also writes an entry to the audit log.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/expiry_count" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Number of certificates in each expiry bucket. The four keys are always present. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"7": 2,
"30": 5,
"60": 9,
"90": 14
}
POST /enrollment/generate_acme_cert
Queues an ACME certificate request. The CA comes from ca (the CertSecure name of an ACME CA registered under CA Management) and the domain from domain_id (a registered domain whose DNS validation has not failed); CertSecure proves control of the domain through the DNS provider stored with that domain and generates the key itself. The certificate's common name is sub_domain and the registered domain joined with a dot, or just the registered domain when sub_domain is empty or absent. The caller needs the Generate Certificate with Private Key permission. The response only confirms the request was queued: follow TaskID through GET /tasks for the outcome. key_length, ca and domain_id must all be present; san_attributes is optional.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
additional_data |
object | No | Caller-supplied data carried onto the queued task unchanged. Optional; any JSON value is accepted. |
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Not interpreted. |
ca |
string | Yes | CertSecure name of an ACME Certificate Authority, as registered under CA Management (the Name returned by GET /ca, not the CA's subject DN). A name that is not an ACME CA, a Microsoft or DigiCert CA for example, is refused with 400 No ACME CA named '<name>' is registered. |
domain_id |
string | Yes | Identifier of the registered domain to request a certificate for: the id of a domain registered through the /acme endpoints (a five-digit string). An unknown id answers 400, and so does a domain whose validation has failed. |
email |
array of string | No | Accepted for compatibility and not used: the notification list comes from watchers. Each entry must be a string if it is sent. |
key_length |
integer or string | Yes | Key size in bits, for example 2048. A numeric string is accepted as well. It is not checked here; a size the ACME client cannot use fails the task. |
san_attributes |
string | Yes | Subject alternative names wanted on the certificate, as a comma-separated string (a JSON array of strings is accepted as well). May be empty. The key itself must be present. |
save_to |
object | No | Where to deliver the issued certificate once it is ready, for example {"azure_key_vault": {"cert_name": "www-example-com.pem", "vault_name": "my-vault"}}. Optional; defaults to none. |
sub_domain |
string | No | Label placed in front of the registered domain, so that www with the domain example.com gives the common name www.example.com. Optional; empty or absent means the registered domain itself. |
tags |
array of string | No | Free-form labels attached to the certificate for grouping and reporting. Optional; anything other than a list is ignored. |
watchers |
array of string | No | Email addresses to notify about this certificate. Only addresses of registered CertSecure users are kept. Optional. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/generate_acme_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ca":"API Test ACME","domain_id":"37105","key_length":2048,"sub_domain":"www","san_attributes":"api.example.com","watchers":["[email protected]"],"tags":["production","external"],"additional_notes":"Public site certificate."}'
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued. Follow the task for the outcome. |
| 400 | The request was refused. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 500 | The request failed unexpectedly. Error carries the failure detail. |
Example Response
{
"TaskID": "2419"
}
GET /enrollment/generate_aws_acm_cert
Returns the values a POST to this path may use for the given CA: the domains the CA can validate, the key algorithms it supports, the validation methods, and the certificate options. The caller needs no permission beyond being authenticated.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
ca |
Query | string | Yes | CertSecure name of the AWS ACM Certificate Authority to describe. This is the Name returned by GET /ca, not the CA's subject DN. Read by GET only; POST takes the CA from the request body. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/generate_aws_acm_cert?ca=<ca>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The request options for this CA. |
| 400 | The ca query parameter is missing or does not name a registered CA. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 404 | The CA is registered but has no stored record. |
| 500 | The request failed unexpectedly. Error carries the failure detail. |
Example Response
{
"aws_acm_payload": {
"domain_validation_options": [
"example.com"
],
"validation_method": [
"DNS",
"EMAIL"
],
"options": {
"CertificateTransparencyLoggingPreference": [
"ENABLED",
"DISABLED"
],
"Export": [
"DISABLED",
"ENABLED"
]
},
"key_algorithm": [
"RSA_2048",
"RSA_3072",
"EC_prime256v1"
]
}
}
POST /enrollment/generate_aws_acm_cert
Queues a public certificate request with AWS ACM. The type of every field is checked here: a field of the wrong type is a 400 that names it. The aws_acm_payload is then handed to the CA connector, which validates the values, so a bad domain name or option shows up as a failed task rather than as a 400. GET on this path lists the values the CA offers. The caller needs the Generate Certificate with Private Key permission. The ca query parameter is not used by POST.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
ca |
string | Yes | CertSecure name of the AWS ACM Certificate Authority to request from (the Name returned by GET /ca). Must be registered, otherwise the answer is a 400. |
aws_acm_payload |
object | No | The certificate request as AWS ACM understands it. Optional here, but the connector rejects a request without domain_name. Use GET on this path to see the values the CA offers. Must be an object, and each field below must have its stated type, otherwise 400. null is not accepted for any field of it. |
email |
array or string or null | No | Email addresses to notify about this certificate (its watchers): an array of strings, or the empty string or null for none. They need not belong to CertSecure users. Any other type is a 400. |
tags |
array | No | Free-form labels attached to the certificate for grouping and reporting. An array of strings, or null for none; anything else is a 400. |
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Not interpreted. Must be a string when sent: anything else, including null, is a 400. |
save_to |
object | No | Where to deliver the issued certificate, for example {"azure_key_vault": {"cert_name": "www-example-com.pem", "vault_name": "my-vault"}}. Optional; defaults to none. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/generate_aws_acm_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ca":"Issuing CA 1","aws_acm_payload":{"domain_name":"www.example.com","san_attributes":["example.com"],"validation_method":"DNS","key_algorithm":"RSA_2048"},"email":["[email protected]"],"tags":["production","external"],"additional_notes":"Public site certificate."}'
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued. Follow the task for the outcome. |
| 400 | The request was refused: ca is missing or not a registered CA, or a field of the POST body has the wrong type. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 500 | The request failed unexpectedly. Error carries the failure detail. |
Example Response
{
"TaskID": "2417"
}
POST /enrollment/generate_cert
Direct enrollment: CertSecure generates the key pair and the CSR itself from the subject fields in the request, then queues the certificate request with the chosen CA. Use POST /enrollment/enroll_csr instead when you hold the key and want to submit your own CSR. The caller needs the Generate Certificate with Private Key permission. The response only confirms the request was queued: follow TaskID through GET /tasks for the outcome. Depending on the approval workflow for the template, the request may wait for approvals before it is issued. ca, template, san_attributes and common_name are mandatory. The other subject fields (organization, organization_unit, city, state, country_code) are optional and are what the rest of the CSR is built from; an empty string means "none", and a CA's policy may still require some of them. The type of every field is checked first: a field of the wrong type is a 400 that names it. country_code must be empty or exactly two letters, and key_length must be a positive integer (an RSA key must be between 1024 and 16384 bits). If administrators have defined required custom fields, customFields must supply them, and every name in it must already exist (POST /customFields/create).
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
ca |
string | Yes | CertSecure name of the Certificate Authority to issue from. This is the Name returned by GET /ca, not the CA's subject DN. The CA must be registered, otherwise the answer is a 400. |
template |
string | Yes | Certificate template to issue against. Must be one the chosen CA publishes (GET /inventory/templates lists them). For a Sectigo CA the numeric certificate-type id is accepted too. |
san_attributes |
string or array | Yes | Subject alternative names, as comma-separated type=value entries: dns=, ipaddress= and email= (and uri= for policy-based CAs). The DNS:value colon form is understood only by policy-based CAs and is silently ignored by the others. May be an empty string; a JSON array of strings with the same entries is accepted as well. Any other type is a 400. The common name is added automatically when it is not listed. |
common_name |
string | Yes | Subject common name (CN) for the certificate, normally the fully-qualified hostname it will protect. Required and non-empty. |
organization |
string | No | Subject organisation (O). The empty string means none; null is a 400. |
organization_unit |
string | No | Subject organisational unit (OU). The empty string means none; null is a 400. |
city |
string | No | Subject locality (L). The empty string means none; null is a 400. |
state |
string | No | Subject state or province (ST). The empty string means none; null is a 400. |
country_code |
string or string | No | Subject country (C) as a two-letter ISO 3166-1 alpha-2 code. Exactly two characters, or the empty string for none: the CSR builder rejects any other length (400). |
group_email |
string | No | Distribution-list address to put in the subject's email attribute. Optional; when empty or absent the requesting user's own address is used. null is a 400. |
key_length |
integer or string | No | Key size in bits: for example 2048, 3072 or 4096 for an RSA key, or 256, 384 or 521 when signing_algorithm selects ECDSA. Defaults to 2048. A positive integer, or a string of digits; anything else is a 400. For an RSA key made by CertSecure (a CA without a policy template) the size must be between 1024 and 16384, otherwise 400. A size the CA does not support makes the request fail later. |
signing_algorithm |
string | No | Signature algorithm. Defaults to SHA256WITHRSA. For a CA without a policy template, ECDSA (or EC) generates an elliptic-curve key, ML-DSA-44, ML-DSA-65 and ML-DSA-87 generate post-quantum keys through OpenSSL 3.5, and any other value generates an RSA key. A policy-based CA interprets the value itself. Must be a string when sent. |
email |
array of string | No | Email addresses of CertSecure users to notify about this certificate (its watchers). Optional. An array of strings; anything else is a 400. |
tags |
array | No | Free-form labels attached to the certificate for grouping and reporting. Optional. An array of strings, or null for none; anything else is a 400. |
customFields |
array | No | Administrator-defined fields to record against the certificate, as {"name": ..., "value": ...} objects. Each name must already be defined; a null value counts as not supplied. Required whenever a defined custom field is marked required. null, like leaving the key out, means no values. |
additional_notes |
string | No | Free-text note stored with the request and shown in the certificate's history. Not interpreted. Must be a string when sent: anything else, including null, is a 400. |
additional_data |
object | No | Extra issuance parameters handed to the CA connector with the request. For a Sectigo CA an object may carry organization_id, external_requester and term (days). A policy-based CA replaces it with the payload it derives from the request. Optional. |
save_to |
object | No | Where to deliver the issued certificate once it is ready, for example {"azure_key_vault": {"cert_name": "www-example-com.pem", "vault_name": "my-vault"}}: the certificate is uploaded to that Azure Key Vault, as PEM when cert_name contains pem and as PFX when it contains pfx. Optional; defaults to none. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/generate_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ca":"Issuing CA 1","template":"WebServer","common_name":"www.example.com","san_attributes":"dns=www.example.com,dns=example.com","organization":"Example Corp","organization_unit":"IT Security","city":"Dallas","state":"Texas","country_code":"US","key_length":2048,"signing_algorithm":"SHA256WITHRSA","email":["[email protected]"],"tags":["production","external"],"additional_notes":"Web front end for the payments service."}'
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued. Follow the task for the outcome. |
| 400 | The request was refused: a required field is missing, a field has the wrong type or an unusable value, or the CA or template is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 404 | The CA has no usable configuration for this request. |
| 500 | The key pair or CSR could not be generated, or the request failed unexpectedly. Error carries the failure detail. |
Example Response
{
"TaskID": "2417"
}
POST /enrollment/generate_csr
Generates a new private key and a PKCS#10 CSR on the server and returns both in a ZIP archive: csr.pem and private_key.key, the key being encrypted with password. The server does not keep the key. A record of the request (subject, key size, CA when given) is kept for the "CSR generated" statistics. Callers other than administrators are held to the request policy (minimum key size, wildcard, duplicate and DNS allow-list rules) and are refused with a 403 when the CSR would break it. The common name is added to the SANs when it is a valid DNS name, IP address or e-mail address and not already listed.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
common_name |
string | Yes | Subject common name (CN) — normally the fully-qualified hostname the certificate will protect. |
organization |
string | Yes | Subject organisation (O). |
organization_unit |
string | Yes | Subject organisational unit (OU). |
city |
string | Yes | Subject locality (L). |
state |
string | Yes | Subject state or province (ST). |
country_code |
string | Yes | Subject country (C) as a two-letter ISO 3166-1 alpha-2 code. Exactly two characters: any other length makes the subject builder raise, which the handler reports as a 500. |
email |
string | Yes | E-mail address placed in the subject of the CSR. |
san_attributes |
string | Yes | Subject alternative names as comma-separated entries in dns=, ipaddress= or email= form. Entries in any other form are ignored, and an empty string means no SANs beyond the common name. An invalid IP address or e-mail address makes the request fail with a 500. |
password |
string | Yes | Password that encrypts the returned private key. Must be a string that meets the product's password policy; a weaker one is answered with 400 naming each rule it breaks, before any key is generated. The schema states the policy every install starts with: 9 to 16 characters, at least 2 upper-case, 2 lower-case, 2 digits and 1 special character (ASCII punctuation). An administrator can change the policy, including the maximum length, with POST /enrollment/policy; the server then enforces the changed one. GET /enrollment/generate_password returns a password that satisfies it. |
key_length |
integer or string | No | Public key size in bits, as a string of digits (an integer is also accepted). Defaults to 2048. For ECDSA it selects the curve: 256, 384 or 521 (anything else gives P-256). |
signing_algorithm |
string | No | Key algorithm: ECDSA (or EC) for an elliptic-curve key, ML-DSA-44, ML-DSA-65 or ML-DSA-87 for a post-quantum key, anything else (default SHA256WITHRSA) for an RSA key. The signature hash is SHA-384 for keys of 4096 bits or more and SHA-256 otherwise. |
ca |
string | No | CertSecure name of the Certificate Authority the CSR is intended for. Only recorded for the "CSR generated" statistics; it is not checked. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/generate_csr" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"common_name":"www.example.com","organization":"Example Corp","organization_unit":"IT Security","city":"Dallas","state":"Texas","country_code":"US","email":"[email protected]","san_attributes":"dns=www.example.com,dns=example.com","password":"Str0ng#Pass12","key_length":"2048","signing_algorithm":"SHA256WITHRSA","ca":"Issuing CA 1"}'
Responses
| Status Code | Description |
|---|---|
| 200 | A ZIP archive containing csr.pem and the encrypted private_key.key. |
| 400 | The body is empty, a required field is missing, or password is not a string or does not meet the password policy. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The CSR breaks the request policy (administrators are exempt). |
| 500 | The key or CSR could not be generated; the message says why when it is a bad SAN entry. |
GET /enrollment/generate_password
Returns a random password that meets the configured password policy (passwordRestriction from GET /enrollment/policy: minimum length and minimum counts of upper-case, lower-case, digit and special characters, within the maximum length if the administrator set one). Use it for the password of a PKCS#12 download or of a generated CSR's private key. Nothing is stored: every call returns a new value.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/generate_password" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | A newly generated password. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The stored password policy could not be read or applied. |
Example Response
{
"generated_password": "xY9$kLm2Qr7!"
}
POST /enrollment/hold_cert
Queues a reversible hold on one certificate (undo with POST /enrollment/unhold_cert) and answers immediately with the id of the task that carries it out, exactly like POST /enrollment/revoke_cert. Microsoft CA (MSCA) certificates only: Active Directory Certificate Services is the one integrated CA that can later reverse this (certutil -revoke <serial> Unrevoke only succeeds when the certificate's current revocation reason is CertificateHold) -- AWS Private CA, GlobalSign, Sectigo, DigiCert and ACME CAs have no such operation, so the request is refused for any CA whose connectorType is not MSCA. Identify the certificate either by eid (enrollment ID) or by serialNum together with ca; at least one of eid or serialNum is needed, and when both are sent eid wins. The certificate must currently be active. Authorization and permissions are identical to revoke_cert: the View Enrollment Database permission, and global administrator, Department PKIAdmin of the owning CA, or (when an enrollment record exists) its owner.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate to hold. Takes precedence over serialNum. Must be an integer (400 otherwise) and name an active record. Required unless serialNum is given. |
serialNum |
Query | string | No | Serial number of the certificate to hold, as shown in the inventory. Used only when eid is absent, in which case ca is required. Required unless eid is given. |
ca |
Query | string | No | CertSecure name of the Certificate Authority that issued the certificate. Must be an MSCA CA (400 otherwise). Required with serialNum; ignored when eid is used. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/hold_cert" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The hold was queued. The body is the task id as plain text. |
| 400 | No identifier was sent, a value is malformed, the CA is not MSCA, the certificate is not active, or the hold could not be queued. The message says which. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission, or may not hold this certificate. |
GET /enrollment/ignore_cert
Returns every certificate that has been marked as ignored, one object per entry. EnrollmentID is null for a certificate that was ignored by serial number and has no enrollment record.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/ignore_cert" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The ignored certificates; an empty array when there are none. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The list could not be read; the message is the underlying error text. |
Example Response
[
{
"EnrollmentID": 1042,
"SerialNumber": "4A1B2C3D4E5F",
"CertificateAuthority": "Issuing CA 1"
},
{
"EnrollmentID": null,
"SerialNumber": "5B2C3D4E5F60",
"CertificateAuthority": "Issuing CA 1"
}
]
POST /enrollment/ignore_cert
Marks one certificate as ignored and removes it from the expiring-certificate listings. Identify it by eid, or by serialNum with ca; eid wins when both are sent. The body must be a JSON object and every field that is sent must have its stated type, even one that is not used (a 400 that names the field). An eid that matches no enrollment record is a 404. Ignoring a certificate that is already ignored answers 200 again and adds no second entry to the list.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | No | Enrollment ID of the certificate to ignore: an integer, or a string of digits (the web interface sends "1042"). Anything else is a 400, and so is an ID that matches no record (404). Takes precedence over serialNum. Either eid or serialNum (with ca) is needed. |
serialNum |
string | No | Serial number of the certificate to ignore, used when eid is absent; ca is then required. The certificate must exist in that CA's inventory. Must be a string even when eid is also sent (400 otherwise). |
ca |
string | No | CertSecure name of the Certificate Authority of the certificate. Required with serialNum (400 otherwise, and it must be a registered CA); not read with eid, but it must be a string when sent (the web interface always sends it). null is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/ignore_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":"1042"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate is now ignored. |
| 400 | The body is not a JSON object, no identifier was sent, a field has the wrong type, or the CA is missing or not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 404 | With eid: no enrollment record has that ID. With serialNum: no such certificate in the CA's inventory. |
| 500 | The operation failed unexpectedly; the message is the underlying error text. |
Example Response
{
"Success": "1042 from Issuing CA 1 has been ignored"
}
GET /enrollment/ignore_templates
Returns an object keyed by CA name whose values are the ignored template names. When nothing has ever been saved, every registered CA maps to an empty array. Open to any authenticated caller.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/ignore_templates" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Ignored template names per CA. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The handler failed unexpectedly; Error carries the exception text. |
Example Response
{
"Issuing CA 1": [
"WebServer",
"Client-Auth"
],
"Issuing CA 2": []
}
POST /enrollment/ignore_templates
Restricted to global administrators and Department PKIAdmins; the permission is checked before the body is read. Responds with the lists of the CAs the request named, as stored, which can be shorter than the ones sent because unknown templates are dropped. A body that is missing or is not a JSON object, or whose ignoreTemplates is not an object of CA names to arrays of template names, is a 400.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
ignoreTemplates |
object | Yes | Object keyed by CertSecure CA name; each value is the array of template names to ignore for that CA. Each CA named has its list replaced by the one sent, and a CA that is not named keeps its list: to stop ignoring every template of a CA, send an empty array for it. An empty object changes nothing. Template names are trimmed, and a name the CA does not publish is silently skipped. Every CA named must be registered (400 otherwise), and a Department PKIAdmin may only name CAs of their own department (403). The value must be an object of CA names to arrays of strings, otherwise 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/ignore_templates" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"ignoreTemplates":{"Issuing CA 1":["WebServer"]}}'
Responses
| Status Code | Description |
|---|---|
| 200 | The ignored templates as stored. |
| 400 | The body is missing or is not a JSON object, it names no ignoreTemplates, ignoreTemplates is not an object of CA names to arrays of template names, or a CA is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is neither a global administrator nor a Department PKIAdmin (plain-text body), or a Department PKIAdmin named a CA outside their department (JSON body). |
| 500 | The handler failed unexpectedly; Error carries the exception text. |
Example Response
{
"Templates Ignored": {
"Issuing CA 1": [
"WebServer"
]
}
}
POST /enrollment/import-third-party-cert
Adds a certificate that was issued outside CertSecure to the enrollment inventory. The PEM in cert_data is parsed and its subject, serial number, validity, key size and chain are recorded; the caller becomes the owner. The certificate is filed under certContainer, which must be a registered third-party container, using the "Third Party Template". Requires the Import Certificate permission. A certificate whose PEM is already stored is refused with 404 and the Enrollment ID that holds it. The body must be a JSON object, and each field must have its stated type (a 400 that names the field otherwise); null is not accepted for any field.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
certContainer |
string | Yes | Name of the registered third-party certificate container to file the certificate under. The request is rejected with 400 unless a container with exactly this name is registered. Must be a string. |
cert_chain |
string | No | PEM-encoded issuing chain for the certificate, root last. Optional; must be a string when sent. |
cert_data |
string | Yes | PEM-encoded certificate body. Must be a string; one that is not a PEM certificate is a 400. |
watchers |
array of string | No | Email addresses notified about this certificate's expiry and lifecycle events, in addition to the owner. Optional. An array of strings; anything else, including null, is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/import-third-party-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"certContainer":"Third Party Container","cert_chain":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","cert_data":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n","watchers":["[email protected]"]}'
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate was imported. eid is the new Enrollment ID. |
| 400 | The body is not a JSON object, a key is missing or has the wrong type, certContainer is not registered, or cert_data could not be read as a PEM certificate. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Import Certificate permission. |
| 404 | The same certificate PEM is already stored; the message names the Enrollment ID that holds it. (Reported as 404 by this endpoint, not 409.) |
| 500 | The import failed unexpectedly. |
Example Response
{
"eid": 1042
}
POST /enrollment/import-third-party-cert-manual
Adds a third-party certificate to the enrollment inventory from metadata the caller types in, without supplying the certificate itself. The resulting record has no certificate body; use PUT /enrollment/attach-cert later to attach the PEM. The record is filed under certContainer, which must be a registered third-party container, and the caller becomes the owner. Requires the Import Certificate permission. A record with the same serial number in the same container is refused with 404. The body must be a JSON object and each field must have its stated type (a 400 that names the field otherwise); null is not accepted for any field, and "" stands for "none" in the optional text fields.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
certContainer |
string | Yes | Name of the registered third-party certificate container to file the certificate under. The request is rejected with 400 unless a container with exactly this name is registered. |
commonName |
string | Yes | Subject common name (CN). |
expiry |
string or string | Yes | Expiry date of the certificate in ISO 8601 form, either a date (2027-01-31) or a date-time (2027-01-31T23:59:59Z). A value without a time zone is read as UTC. A date in the past makes the record expired rather than active. Anything that is not such a date is a 400. |
serialNumber |
string | Yes | Certificate serial number as a hexadecimal string, optionally prefixed with 0x. Colon or space separators are also tolerated and stripped. Stored in lower case. |
template |
string | No | Template name to record against the certificate. Defaults to Third Party Template when omitted or empty. |
watchers |
array of string | No | Email addresses notified about this certificate's expiry and lifecycle events, in addition to the owner. |
san |
string | No | Optional. Subject alternative names as one comma-separated string of TYPE:value entries, for example DNS:www.example.com, IP:192.0.2.10. Recognised types are DNS, IP, Email and othername. The list is checked against the configured SAN policies (wildcard and DNS allow-list); a violation is answered 400. |
keyLength |
integer or string | No | Optional. Public-key size in bits, for example 2048: a positive integer, or a string of digits. Anything else is answered 400. |
tags |
array of string | No | Optional. Names of existing certificate tags to attach, as an array of strings. A name that is not a defined tag is answered 400 with the list of available tags. |
organization |
string | No | Optional. Subject organization (O). |
organizationUnit |
string | No | Optional. Subject organizational unit (OU). |
city |
string | No | Optional. Subject locality (L). |
state |
string | No | Optional. Subject state or province (ST). |
countryCode |
string or string | No | Optional. Subject country (C), a two-letter code, or the empty string for none. Any other length is a 400. |
issuer |
string | No | Optional. Common name of the issuing CA, recorded as typed. |
additional_notes |
string | No | Optional. Free-text note stored with the record and shown in the certificate history. Not interpreted. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/import-third-party-cert-manual" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"certContainer":"Third Party Container","commonName":"www.example.com","expiry":"2027-01-31","serialNumber":"4A1B2C3D4E63","template":"Third Party Template","watchers":["[email protected]"],"san":"DNS:www.example.com, DNS:example.com","keyLength":2048,"tags":[],"organization":"Example Corp","organizationUnit":"IT","city":"Dallas","state":"Texas","countryCode":"US","issuer":"Example Issuing CA","additional_notes":"Registered manually pending receipt of the PEM."}'
Responses
| Status Code | Description |
|---|---|
| 200 | The record was created. eid is the new Enrollment ID. |
| 400 | The body is not a JSON object, a required key (certContainer, commonName, serialNumber, expiry) is missing or empty, a field has the wrong type, certContainer is not registered, or the typed-in details are invalid (serial number not hexadecimal, expiry not ISO 8601, SAN denied by policy, unknown tag). A missing expiry is answered {"Error": "expiry is required"}. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Import Certificate permission. |
| 404 | A record with this serial number already exists in the container; the message names its Enrollment ID. (Reported as 404 by this endpoint, not 409.) |
| 500 | The import failed unexpectedly. |
Example Response
{
"eid": 1042
}
POST /enrollment/import-trusted-root
Parses a PEM certificate and stores it in the CertSecure trust store as a trusted root, keyed by its Subject Key Identifier (re-importing the same certificate updates the stored entry). A background job then rebuilds the stored chains so certificates that chain to it show as trusted. Requires the Manage Certification Authorities administrator permission. Every failure after the permission check, including an unparseable certificate, a request body that is not a JSON object, or a failure while saving, is answered with 400 Invalid root certificate format.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
root_cert |
string | Yes | PEM-encoded root certificate. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/import-trusted-root" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"root_cert":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The certificate was added to the trust store. |
| 400 | root_cert is missing or empty, or the request could not be processed as a PEM certificate. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Manage Certification Authorities permission. |
Example Response
{
"Success": "Trusted root certificate (Example Root CA) imported successfully"
}
GET /enrollment/key_length_count
Returns, for every key length present among the active enrollment records, how many active records use it. The keys of the returned object are the key lengths (for example 2048) and the values are the counts; an estate with no active certificates answers an empty object. Takes no input; each call also writes an entry to the audit log.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/key_length_count" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Map of key length to the number of active certificates using it. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"2048": 14,
"4096": 3
}
GET /enrollment/organization_details
Returns the stored organization details. Any signed-in user may read them. On an installation where none have been saved the lists and the location map are empty and othersEnabled is absent.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/organization_details" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The stored organization details. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"organization": [
"Example Corp"
],
"organizationUnit": [
"IT Security"
],
"Location": {
"Austin": {
"State": "Texas",
"CountryCode": "US"
}
},
"othersEnabled": false
}
POST /enrollment/organization_details
Replaces the stored organization details with the values supplied. Requires the Manage Organization Details administrator permission. The body is not type-checked: the handler stores whatever it is given, but other parts of the product read organization and organizationUnit as lists and location as the city map shown here, so send those shapes. Omitting organization, organizationUnit or location makes the request fail.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
organization |
array of string | Yes | Organization names to offer as the subject O. |
organizationUnit |
array of string | Yes | Organizational unit names to offer as the subject OU. |
location |
object | Yes | Locations keyed by city name, each with its State and two-letter CountryCode. Stored, and returned by GET, as Location. |
othersEnabled |
boolean | No | Whether values other than the listed ones may be entered. Optional; treated as false when omitted. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/organization_details" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"organization":["Example Corp"],"organizationUnit":["IT Security"],"location":{"Austin":{"State":"Texas","CountryCode":"US"}},"othersEnabled":false}'
Responses
| Status Code | Description |
|---|---|
| 200 | The organization details as now stored. Note the location map comes back as Location. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Manage Organization Details permission. |
Example Response
{
"organization": [
"Example Corp"
],
"organizationUnit": [
"IT Security"
],
"Location": {
"Austin": {
"State": "Texas",
"CountryCode": "US"
}
},
"othersEnabled": false
}
GET /enrollment/organization_info
Returns the organization information saved for the CA by its last inventory refresh. A CA whose connector does not report any is answered with 200 and {"Error": "Not found"}, not with a 404; a 404 means the CA itself is unknown.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
caName |
Query | string | Yes | CertSecure name of the Certificate Authority, as returned by GET /ca. Must be a CA known to CertSecure (404 otherwise); an empty value is a 400. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/organization_info?caName=<caName>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The stored organization information, or {"Error": "Not found"} when the CA has none (the status is still 200). |
| 400 | caName is missing or empty. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 404 | No CA with that name. |
Example Response
{
"organizationInfo": {
"O": "Example Corp",
"OU": "IT"
}
}
GET /enrollment/policy
Open to any authenticated caller. number_of_approvers is how many users can currently approve requests.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/policy" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The current policy. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
Example Response
{
"csr": false,
"wildcard": false,
"short_dns_names_allowed": false,
"dnsWhiteList": [],
"passwordRestriction": {
"MinPassLen": 9,
"MaxPassLen": 16,
"uppercase": 2,
"lowercase": 2,
"decimal": 2,
"specialChar": 1
},
"workflow": {
"Issuing CA 1": [
{
"template_name": "WebServer",
"approvals_required": 1
}
]
},
"number_of_approvers": 3
}
POST /enrollment/policy
Requires the Manage Enrollment Policies permission. Every field is optional and only the ones sent are changed. The whole body is checked first: if any field is invalid nothing is changed. The body must be a JSON object, and fields not listed here are ignored. The response is the whole stored policy.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
csr |
string | No | Whether a CSR that is already on record (active, pending, expired or revoked) is refused by policy. Sent as the string true or false (case-insensitive, surrounding spaces ignored); a CSR is not accepted here despite the name. Any other value, including one that is not a string, is a 400. Omit to leave unchanged. |
wildcard |
string | No | Whether wildcard certificates are refused by policy for non-administrators. Sent as the string true or false (case-insensitive). Any other value, including one that is not a string, is a 400. Omit to leave unchanged. |
short_dns_names_allowed |
string | No | Whether unqualified (single-label) DNS names are accepted in SAN lists. Sent as the string true or false (case-insensitive). Any other value, including one that is not a string, is a 400. Omit to leave unchanged. |
dnsWhiteList |
array of string | No | DNS names or *. wildcard suffixes that requests are allowed to name; an empty array allows any name, for example ["example.com", "*.example.org"]. Replaces the stored list. An array of strings; anything else (including null) is a 400. Names are stored as sent. |
passwordRestriction |
object | No | - |
workflow |
object | No | Approval workflow, keyed by CertSecure CA name. Each value is an array of objects {"template_name": ..., "approvals_required": ...} saying how many approvals a request on that template needs; other keys of an object are kept as sent. The value must be an object of CA names to arrays of such objects, and template_name must be a non-empty string, otherwise 400. Every CA named must be registered (400 otherwise). A caller holding Remove Restricted Templates replaces the CA's whole list; a caller holding only Manage Templates can add templates that the CA publishes and that are not already listed; anyone else changes nothing for that CA. Omit to leave unchanged. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/policy" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"csr":"false","wildcard":"false","short_dns_names_allowed":"false","dnsWhiteList":[],"passwordRestriction":{"MinPassLen":9,"MaxPassLen":16,"uppercase":2,"lowercase":2,"decimal":2,"specialChar":1}}'
Responses
| Status Code | Description |
|---|---|
| 200 | The whole stored policy after the update, under Restrict. |
| 400 | The body is not a JSON object, a flag is not true or false, dnsWhiteList, passwordRestriction or workflow has the wrong shape, passwordRestriction is not a valid, satisfiable policy, or a workflow names a CA that is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Manage Enrollment Policies permission. |
Example Response
{
"Restrict": {
"csr": false,
"wildcard": false,
"short_dns_names_allowed": false,
"dnsWhiteList": [],
"passwordRestriction": {
"MinPassLen": 9,
"MaxPassLen": 16,
"uppercase": 2,
"lowercase": 2,
"decimal": 2,
"specialChar": 1
},
"workflow": {
"Issuing CA 1": [
{
"template_name": "WebServer",
"approvals_required": 1
}
]
}
}
}
POST /enrollment/renew_aws_acm_cert
Queues a new AWS ACM certificate request that repeats the original one, identified by the certificate's enrollment id or its serial number. The domain names, watchers, notes, tags and CA are all taken from the stored enrollment record; nothing about the certificate itself is supplied here. Only an active certificate that was requested through CertSecure (so that its request payload was kept) can be renewed; any other certificate is answered 409. The caller needs the Generate Certificate with Private Key permission, which is checked before the body is read. The response only confirms the request was queued: follow TaskID through GET /tasks. At least one of eid, EnrollmentID and serialNum is required. When EnrollmentID is present it takes the place of eid; when an enrollment id is given, serialNum is ignored (but must still be a string). The body must be a JSON object sent with a JSON Content-Type (a body with any other type is treated as missing, 400); a value of the wrong type (including null) is a 400.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | No | Enrollment ID: the number CertSecure assigned to the certificate request, as an integer or a string of digits. Ignored when EnrollmentID is also sent. |
EnrollmentID |
integer or string | No | Alternative spelling of eid; when both are sent this one wins. |
serialNum |
string | No | Serial number of the certificate to renew, in any letter case. Only used when no enrollment id is given, but a blank value (empty or only spaces) is a 400 either way. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/renew_aws_acm_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1046}'
Responses
| Status Code | Description |
|---|---|
| 200 | The renewal was queued. Follow the task for the outcome. |
| 400 | The request was refused. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Generate Certificate with Private Key permission. |
| 404 | No active certificate with that enrollment id or serial number was found. |
| 409 | The certificate is active but was not requested through CertSecure as an AWS ACM request, so there is no request to repeat. |
| 500 | The renewal failed unexpectedly. Error carries the failure detail. |
Example Response
{
"TaskID": "2418"
}
POST /enrollment/renew_cert
Queues the renewal of one existing certificate and answers with the id of the task that tracks it, as a bare string (not JSON). Identify the certificate with eid / EnrollmentID (an enrollment record) or serialNum (an inventory certificate); at least one of the three is needed (400 otherwise), and when both kinds are sent the enrollment id wins. Every other field is an optional override: anything omitted is taken from the certificate being renewed, so {"EnrollmentID": "1042"} alone renews it unchanged. Authorization differs by identifier: with an enrollment id the caller must be a global administrator, a Department PKIAdmin whose department owns the CA, or the record's owner or a listed recipient; with a serial number the caller needs the Renew Inventory Certificates permission. A certificate on an ACME template, or on a HashiCorp Vault CA, is renewed through its own task type and the subject and key fields are ignored. For other CAs a new key pair and CSR are generated and submitted like a fresh request, so the approvals configured for the template apply. The body must be a JSON object sent with a JSON Content-Type (a body with any other type is treated as missing, 400). Every field is type-checked before anything is read, and a wrong type is a 400 that names the field.
Note: Identify the certificate with eid (or EnrollmentID), or with serialNum together with ca.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | No | Enrollment ID of the certificate to renew. An integer or a string of digits (surrounding spaces are trimmed); anything else, a boolean included, is refused with a 400. Overridden by EnrollmentID when that is also sent. |
EnrollmentID |
integer or string or null | No | Alias of eid. When it is not null it replaces eid. Same format. null means not sent. |
serialNum |
string | No | Serial number of an inventory certificate to renew, as shown by the inventory (hex, case insensitive). Must be a string. Used only when neither eid nor EnrollmentID is sent. |
ca |
string | No | CertSecure name of the Certificate Authority to renew against. Defaults to the CA that issued the certificate. Must be a registered CA (404 otherwise). |
template |
string | No | Certificate template to renew against. Defaults to the certificate's current template. Must be a template the CA publishes (400 Not a correct template mapping otherwise); GET /enrollment/templates lists them. |
common_name |
string | No | Subject common name (CN) for the renewed certificate. Defaults to the current one. |
organization |
string | No | Subject organisation (O). Defaults to the current one. |
organization_unit |
string | No | Subject organisational unit (OU). Defaults to the current one. |
city |
string | No | Subject locality (L). Defaults to the current one. |
state |
string | No | Subject state or province (ST). Defaults to the current one. |
country_code |
string | No | Subject country (C) as a two-letter ISO 3166-1 alpha-2 code. Defaults to the current one. |
san |
string | No | Subject alternative names for the renewed certificate: comma-separated entries in dns=, ipaddress= or email= form (an array of the same entries is also accepted). When omitted the enrollment path reuses the current SANs and the serial-number path sends none. |
key_length |
integer or string | No | Public key size in bits, as a positive integer or a string of digits; anything else is a 400. Defaults to the current key size. For an RSA key made by CertSecure (a CA without a policy template) the size must be between 1024 and 16384, otherwise 400; that range is checked once the record, CA and template have been found. |
signing_algorithm |
string | No | Signature algorithm. Defaults to the certificate's current one, else SHA256WITHRSA. |
EmailID |
array of string | No | E-mail addresses to notify about the renewed certificate (its watchers). Defaults to the current ones on the enrollment path and to none on the serial-number path. An array of strings; anything else, a bare string included, is a 400. |
tags |
array | No | Free-form labels attached to the renewed certificate. An array of strings, or null for none; anything else is a 400. |
additional_notes |
string | No | Free-text note stored with the renewal request and shown in the certificate's history. Must be a string. |
additional_data |
object | No | Caller-supplied object stored on the renewal task unchanged. Free-form; not interpreted. For a CA that builds its request from a policy template (for example GlobalSign or AWS Private CA) it is replaced by the data the policy produces. Anything that is not an object is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/renew_cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"EnrollmentID":"1042","common_name":"www.example.com","san":"dns=www.example.com,dns=example.com","key_length":"2048","tags":["production"],"additional_notes":"Scheduled renewal"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The renewal was queued. The body is the numeric id of the task that tracks it, as plain text (served as text/html), for example 5821. |
| 400 | The body is not a JSON object, a field has the wrong type, no certificate was identified, the key size is unusable, or the template is. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller may not renew this certificate (see the operation description). |
| 404 | The enrollment record, certificate, CA, template details or CA policy was not found. |
| 500 | Key or CSR generation failed, or the renewal raised an unexpected error. When it is the latter Reason carries the exception text. |
POST /enrollment/renew_csr
Renews an issued certificate with a CSR you supply, so you keep your own private key; POST /enrollment/renew_cert instead generates a new key pair on the server. The response is the id of the task that tracks the renewal. Name the certificate with eid, or with serialNum and ca. Only an active or expired certificate is renewed (409 otherwise), and CertSecure must hold it (404 otherwise): a certificate it does not hold is never enrolled as a new one. The renewal keeps the old certificate's CA, template, owner, watchers, tags, note and custom fields; anything sent in the body replaces the inherited value, except the owner. When the new certificate is installed, the old one leaves the expiry alerts and renewal notifications are sent. The CSR-reuse policy does not count the CSRs of this certificate and the ones it renewed, so a client may renew repeatedly with the same CSR. Every enrollment rule of POST /enrollment/enroll_csr (CA, template, SANs, approvals) applies. Authorization: the Renew Inventory Certificates permission, or, for a certificate with an enrollment record, being a global administrator, the Department PKIAdmin of the CA the renewal is issued from (the one ca names, else the certificate's own), its owner or a watcher (403 otherwise). The Submit CSR permission is not needed.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
csr |
string | Yes | PEM-encoded PKCS#10 certificate signing request for the renewed certificate. It may be the CSR the certificate was issued from (same key, same subject), a new CSR for the same key, or a CSR for a new key. It must parse (400 otherwise). No private key is generated or stored. |
eid |
integer or string | No | Enrollment ID of the certificate to renew. Send either eid, or serialNum with ca; sending both, or neither, is a 400. An id CertSecure does not hold is a 404. |
serialNum |
string | No | Serial number (hex) of the certificate to renew, on the CA named by ca. Any spelling is accepted (case, leading zero, 0x prefix, :, - or space separators); anything else, including the placeholders None and EMPTY, is a 400. A certificate CertSecure holds only in its inventory (issued outside CertSecure) is renewed too, and then needs template. A serial CertSecure does not hold on that CA is a 404. |
ca |
string | No | CertSecure name of the Certificate Authority. Required with serialNum, where it names the CA the certificate is on. With eid it is optional and moves the renewal to another registered CA; left out, the renewal uses the certificate's own CA. |
template |
string | No | Certificate template to issue against. Optional: left out, the renewal uses the template the certificate was issued from. Required for a certificate CertSecure did not issue, which has none recorded (400 otherwise). |
email |
array or string | No | E-mail addresses to notify about the renewal (the new certificate's watchers): an array of strings, or the empty string for none. Left out, the old certificate's watchers are kept. |
san_attributes |
string or array | No | Additional subject alternative names, exactly as for POST /enrollment/enroll_csr. Merged with the SANs in the CSR unless override_csr_sans is true. |
override_csr_sans |
boolean | No | When true, only the SANs in san_attributes are used; otherwise they are merged with the CSR's. Must be a boolean when sent. |
tags |
array of string | No | Labels for the renewed certificate. Left out, the old certificate's tags are kept. Must be an array of strings when sent. |
additional_notes |
string | No | Note stored with the renewal. Left out, the old certificate's note is kept. Must be a string when sent. |
additional_data |
object | No | Caller-supplied data stored on the request task, exactly as for POST /enrollment/enroll_csr. |
customFields |
array | No | Custom field values as {"name": ..., "value": ...} objects, validated as for POST /enrollment/enroll_csr. Left out (or null), the old certificate's values are kept. |
renews_serial |
object | No | Not accepted on this route either; name the certificate with eid or serialNum. Any value is a 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/renew_csr" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"csr":"-----BEGIN CERTIFICATE REQUEST-----\nMIIC6zCCAdMCAQAwbDELMAkGA1UEBhMCVVMxDjAMBgNVBAgMBVRleGFzMQ8wDQYD\nVQQHDAZEYWxsYXMxFTATBgNVBAoMDEV4YW1wbGUgQ29ycDELMAkGA1UECwwCSVQx\nGDAWBgNVBAMMD3d3dy5leGFtcGxlLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP\nADCCAQoCggEBAOChnT6tEg0GgE4vjp/3RUx/psYPGuoK3606TpORcBN98xvqMNLO\nYILpbwjrlkmdJjYTJVT1yHXA9PYTvpD12DcYe08UHSQOQkC0vC7qNDZHXgOlVD8d\nG9ReQAP6KGgD7O1l0oi6wwiK5q1YNLliRVCB+PdXB2coDbyDi7GxaPVcSiWU6pdG\nC5WWRldyRAmYj18iKi72RZQjHRc3C7aGQFaSySjjO1t9ZLpubqGWMHfoOyhUOPL4\npnI/tOJmYROK4aceYjlM+hDH2ndU7ZvItnKS1cQYS71Dfjzv0VwI5rUuyidgM7/R\nWNHkZWoV1h4+F/WWtQlGN5L2APuL89yVTrcCAwEAAaA6MDgGCSqGSIb3DQEJDjEr\nMCkwJwYDVR0RBCAwHoIPd3d3LmV4YW1wbGUuY29tggtleGFtcGxlLmNvbTANBgkq\nhkiG9w0BAQsFAAOCAQEAEApMFMCPeZet/95ukhjHBgbpQDVjhxiRyg7hxcuRmBcJ\nNIHqjVW9F3ryFD+fHXrTMZJGkgaKgw1OZXlsz1j7GvwIKnaDqO2Yix/wQr07btDD\n5RMysRzOnWkcHsinDBY6VWYgMliTkA5VKTkQ+Lq1kL6cTekyaGJv3g8Suj0Hdj+M\npqKo5KjzyRK1L18hZmh7atsd9LobjNIRqm8CnuU3ympGdO/Dz80PjIPfqt3XwMpD\nNrQ6LSh71Ewfe9xNuvNrBYWo06pKoHAsVLxDzjNGVYgdouOptBP8PXsIwx+LYcYL\nzQes0tQtk85fWSwwstIw8RHTCqj+bq22Fb63n1UFpQ==\n-----END CERTIFICATE REQUEST-----\n","eid":1042}'
Responses
| Status Code | Description |
|---|---|
| 200 | The renewal was queued. TaskID identifies the task that tracks it. |
| 400 | The request was refused: the body names no certificate or both forms, a field has the wrong type, the CSR is unreadable, a template is needed and missing, or the enrollment rules of POST /enrollment/enroll_csr refuse it (CA, template, SANs, custom fields). |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller may not renew this certificate. |
| 404 | CertSecure holds no such certificate, or the CA has no template policy or template details on record. |
| 409 | The certificate is not issued (revoked, pending, requested, denied or failed) and cannot be renewed. |
| 500 | The CSR could not be validated against the CA policy. |
Example Response
{
"TaskID": "5821"
}
POST /enrollment/revoke_cert
Queues the revocation of one certificate and answers immediately with the id of the task that carries it out; the revocation itself happens asynchronously on the CA's agent (or, for ACME CAs, against the ACME service). Identify the certificate either by eid (enrollment ID) or by serialNum together with ca. At least one of eid or serialNum is needed; when both are sent eid wins and serialNum/ca are ignored. With serialNum the CA is mandatory (400 otherwise) and the certificate must be present in that CA's inventory. Only an active enrollment record can be revoked. The caller needs the View Enrollment Database permission and must be a global administrator, a Department PKIAdmin whose department owns the CA, or (for a certificate that has an enrollment record) its owner. The success body is the bare task id, sent as text/html; poll GET /tasks for the outcome.
Note: Identify the certificate with eid, or with serialNum together with ca.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate to revoke. Takes precedence over serialNum. Must be an integer (400 otherwise) and name an active record (404 otherwise). Required unless serialNum is given. |
serialNum |
Query | string | No | Serial number of the certificate to revoke, as shown in the inventory. Used only when eid is absent, in which case ca is required. Required unless eid is given. |
ca |
Query | string | No | CertSecure name of the Certificate Authority that issued the certificate. Required with serialNum (400 otherwise); ignored when eid is used. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/revoke_cert" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The revocation was queued. The body is the task id as plain text. |
| 400 | No identifier was sent, a value is malformed, or the revocation could not be queued. The message says which. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission, or may not revoke this certificate. |
| 404 | With eid: there is no active enrollment record with that id. |
| 500 | Looking up the record or queueing the revocation failed. |
POST /enrollment/switch_ca
Starts a background job that renews each listed inventory certificate against another CA, and answers at once with the plain text Process started. The job works through the serial numbers in batches of 10, 30 seconds apart; nothing about its progress or outcome is returned here. Serial numbers that another renewal job is already processing are skipped. Template maps the current template name of each certificate to the template to use on the new CA. Requires the Renew Inventory Certificates permission, which is checked before anything else. The body must be a JSON object sent with a JSON Content-Type (a body with any other type is treated as missing, 400). Every field is checked before the job starts (400 for a missing field, a wrong type or an unregistered target CA), but the 200 only means the job was started: a template mapping that is wrong for a certificate fails that certificate inside the job.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
SerialNumber |
array of string | Yes | Serial numbers of the inventory certificates to re-issue: a non-empty array of non-blank strings, otherwise 400. |
CertificateAuthority |
string | Yes | CertSecure name of the target Certificate Authority that will issue the new certificates. A non-blank string that must be a registered CA (400 CA not found otherwise). |
Template |
object | Yes | Object mapping a certificate's current template name to the template to use for it on the target CA; every value must be a string, otherwise 400. A certificate whose current template is not a key fails to renew inside the job. |
additional_notes |
string | No | Free-text note stored with each renewal request. A string, otherwise 400. |
additional_info |
object | No | Object of extra order data merged into every renewal request (the job adds the computed order_validity), for example {"organization_id": 7} for DigiCert. Its entries are free-form and not interpreted here, but the value must be an object, otherwise 400. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/switch_ca" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"SerialNumber":["4A1B2C3D4E5F"],"CertificateAuthority":"Issuing CA 2","Template":{"WebServer":"WebServer-2"}}'
Responses
| Status Code | Description |
|---|---|
| 200 | The job was started. |
| 400 | The body is not a JSON object, a required field is missing, a field has the wrong type, or the target CA is not registered. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Renew Inventory Certificates permission. |
| 500 | The request could not be processed because of an unexpected failure. |
GET /enrollment/templates
Returns the certificate templates the caller may request certificates from, grouped by CA. A global administrator sees every CA; anyone else sees the CAs of their department. CAs marked restricted appear only for callers holding Access Restricted CAs. With categories each CA's list is narrowed to the templates filed under those template categories (a CA without categories, or a categories value that is empty, maps to an empty array).
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
categories |
Query | string | No | Comma-separated template category names, for example SSL/TLS,Server. Optional: omit it to list every template. Names are trimmed and empty items ignored. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/templates" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Template names per CA. An empty object when the caller has no CAs. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The templates could not be retrieved. |
Example Response
{
"Issuing CA 1": [
"WebServer",
"Client-Auth"
],
"Issuing CA 2": []
}
POST /enrollment/transfer-third-party-cert
Re-files the enrollment record under a different registered third-party certificate container by changing its CertificateAuthority. Allowed for a global administrator, for a Department PKIAdmin whose department holds the record's CA, and for the record's owner; anyone else is answered with 403. Checks run in this order: EID present and an integer, certContainer present and registered, record exists, caller authorised.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
EID |
integer or string | Yes | Enrollment ID of the record to move. Must be an integer; a numeric string is also accepted. |
certContainer |
string | Yes | Name of the registered third-party certificate container to move the record into. The request is rejected with 400 unless a container with exactly this name is registered. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/transfer-third-party-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"EID":1045,"certContainer":"Third Party Container"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The record was moved. (The word "transfered" is spelled this way in the live response.) |
| 400 | A key is missing, EID is not an integer, or certContainer is not a registered container. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is neither a global administrator, a Department PKIAdmin for the record's CA, nor the record's owner. |
| 404 | No enrollment record has this Enrollment ID. |
Example Response
{
"Success": "Certificate transfered"
}
GET /enrollment/transfer_ownership
Makes the registered CertSecure user email the owner of the enrollment record eid. Allowed only for a global administrator (Admin; the PKIAdmin role is deliberately excluded) or the record's current owner. The new owner must be a registered user and must not already be the owner. Only an issued certificate can be transferred: a request still awaiting approval or the CA, or one that was denied or failed, has no serial number yet and is refused with a 409. To hand such a request to someone else, deny it and request the certificate again. The change of owner is recorded in the certificate's audit trail. With verify=true nothing is changed: the same checks run and the endpoint answers {"Reponse": true} if the transfer would be accepted. Without verify, or with verify=false, the transfer is performed. The response key is spelled Reponse (sic) in both the dry-run and the real answer. Calling it again for the same new owner is a 400 (already the owner).
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | Yes | Enrollment ID of the certificate whose ownership moves. Must be an integer (surrounding spaces and a sign are accepted); anything else is a 400. The example is a record of its own, so a real transfer never changes the certificates the other examples use. |
email |
Query | string | Yes | Email address of the registered CertSecure user who becomes the new owner. |
verify |
Query | boolean | No | Dry run. true (any letter case) checks the transfer but does not perform it. false, or leaving it out, performs it. Any other value is a 400, so a mistyped dry run can never move a certificate. (Until 2026-10-26 any value other than true performed the transfer.) |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/transfer_ownership?eid=<eid>&email=<email>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The transfer was performed, or (with verify=true) would be accepted. |
| 400 | A parameter is missing or unusable, the new owner is already the owner, or the new owner is not a registered user. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is neither a global administrator nor the current owner of the record. |
| 404 | No enrollment record has this Enrollment ID. |
| 409 | The certificate has not been issued yet (awaiting approval or the CA, denied or failed), so its ownership cannot be transferred. The dry run (verify=true) gives the same answer. |
| 500 | The transfer failed unexpectedly. |
Example Response
{
"Reponse": "Transfer of ownership complete"
}
POST /enrollment/trust-certificate-chain
Takes the anchor (last) certificate of the chain stored for the given Enrollment ID and adds it to the CertSecure trust store, then triggers a background rebuild of stored chains. The record must be active, revoked or expired, and must have an uploaded or built chain (see POST /enrollment/upload-chain). The body must be a JSON object. Requires the Manage Certification Authorities administrator permission.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | Yes | Enrollment ID of the certificate whose chain anchor should be trusted. Must be a positive integer; 0 is treated as missing. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/trust-certificate-chain" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1047}'
Responses
| Status Code | Description |
|---|---|
| 200 | The chain anchor was added to the trust store. |
| 400 | The body is missing or is not a JSON object, eid is missing, zero or not an integer, the record is in a state that cannot be trusted, or no usable chain anchor exists. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller does not hold the Manage Certification Authorities permission. |
| 404 | No enrollment record has this Enrollment ID. |
| 500 | The operation failed unexpectedly. |
Example Response
{
"Success": "Certificate chain anchored with trusted root certificate (Example Root CA) successfully"
}
GET /enrollment/trust-history
A merger, a cross-signing or a distrust event changes the path a certificate chains through WITHOUT the certificate changing, so the only visible symptom is a chain that looks different than it did. The timeline is what lets an operator show a customer exactly what moved and when. Entries are recorded per OBSERVED CHANGE, never per refresh, and a regression seen while AIA was unreachable is deliberately absent -- see classes/functions/trust_history.py.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | string | Yes | Enrollment ID — the identifier CertSecure assigns to a certificate request and keeps for the life of the certificate. Distinct from the serial number, which only exists once the CA has issued. |
limit |
Query | integer | No | Maximum number of rows to return. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/trust-history?eid=<eid>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The enrollment id and its trust history, newest change first. An empty history means the chain has never changed. |
| 400 | The request was rejected as malformed or failed validation. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | Unhandled server-side failure. |
Example Response
{
"eid": 1042,
"history": []
}
GET /enrollment/trusted-roots
Returns every certificate in the CertSecure trust store, keyed by Subject Key Identifier. An empty trust store answers an empty object. Takes no input.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/trusted-roots" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | Trusted roots keyed by Subject Key Identifier (hexadecimal). |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The trust store could not be read. |
Example Response
{
"4a1b2c3d4e5f60718293a4b5c6d7e8f901234567": {
"common_name": "Example Root CA",
"certificate": "-----BEGIN CERTIFICATE-----\nMIIB...\n-----END CERTIFICATE-----\n",
"expiry": "2036-01-01T00:00:00+00:00",
"signature_algorithm": "sha256WithRSAEncryption",
"key_size": 4096
}
}
POST /enrollment/unhold_cert
Reverses a hold placed by POST /enrollment/hold_cert and answers immediately with the id of the task that carries it out. Microsoft CA (MSCA) certificates only, for the same reason as hold_cert. Identify the certificate either by eid (enrollment ID) or by serialNum together with ca; at least one of eid or serialNum is needed, and when both are sent eid wins. The certificate must currently be on hold -- an active or revoked certificate is refused, there is nothing to remove. Authorization and permissions are identical to hold_cert/revoke_cert.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | No | Enrollment ID of the certificate to unhold. Takes precedence over serialNum. Must be an integer (400 otherwise) and name an on hold record. Required unless serialNum is given. |
serialNum |
Query | string | No | Serial number of the certificate to unhold, as shown in the inventory. Used only when eid is absent, in which case ca is required. Required unless eid is given. |
ca |
Query | string | No | CertSecure name of the Certificate Authority that issued the certificate. Must be an MSCA CA (400 otherwise). Required with serialNum; ignored when eid is used. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/unhold_cert" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The unhold was queued. The body is the task id as plain text. |
| 400 | No identifier was sent, a value is malformed, the CA is not MSCA, the certificate is not on hold, or the unhold could not be queued. The message says which. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller lacks the View Enrollment Database permission, or may not unhold this certificate. |
GET /enrollment/unknown-certs
Lists the certificates that were imported as third-party records, one per line. The response is not JSON: it is comma-separated text served as text/html, whose first line is a header made of the stored field names of the first record, followed by one line per record. Commas and square brackets inside values are replaced by spaces or removed, and a missing value prints as None. An estate with no third-party certificates answers 200 with an empty body. Because the header comes from the first record only, records with different field sets do not line up column for column.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
ca |
Query | string | No | Optional. Name of the third-party certificate container (the value stored as the record's certificate authority) to list; omit it to list third-party certificates from every container. |
count |
Query | string | No | Accepted but ignored: the response always lists every matching certificate, whatever this value is. |
status |
Query | string | No | Optional. active lists only certificates whose status is active; other lists every certificate that is not active (expired, revoked, pending, ...). Omit it for all of them. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/unknown-certs" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | CSV-style text, header line first. Empty when nothing matches. |
| 400 | status was given and is neither active nor other. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The listing failed unexpectedly. |
POST /enrollment/update_email
Replaces the watcher list (EmailID) of one enrollment record, and of the matching inventory certificate when it exists. Every address is stored (trimmed), registered CertSecure user or not; the response lists what was stored and, separately, which of those addresses do not belong to a registered user. Every address must be well formed, otherwise nothing is stored (400). The body must be a JSON object. Allowed for a global administrator, for a Department PKIAdmin whose department owns the record's CA, and for a user already listed as owner of the record; anyone else gets 403. The record is looked up before the emails type is checked, so an unknown eid answers 404 whatever emails contains, and the address format is checked only for callers who are allowed to make the change.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | Yes | Enrollment ID of the record to update — the identifier CertSecure assigns to a certificate request. Must exist (404 otherwise); a value that is not an integer or integer string is answered 400. |
emails |
array of string | Yes | The complete new list of addresses to notify about this certificate. Replaces the existing list; an empty list clears it. Must be a JSON array of strings, each a well-formed address (surrounding white space is trimmed). |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/update_email" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1042,"emails":["[email protected]","[email protected]"]}'
Responses
| Status Code | Description |
|---|---|
| 200 | The list was replaced. EmailsRegistered is the list that was stored; UnregisteredEmails holds those of the stored addresses that do not belong to a registered CertSecure user (they are kept all the same). |
| 400 | The body is not a JSON object, a required field is missing, eid is not an integer, emails is not an array of strings, or one of the addresses is malformed (InvalidEmails lists them). |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | The caller is not an administrator of this record's CA and not its owner. |
| 404 | No enrollment record has this eid. |
| 500 | The stored record is incomplete, or the update failed. |
Example Response
{
"EmailsRegistered": [
"[email protected]",
"[email protected]"
],
"UnregisteredEmails": []
}
POST /enrollment/upload-chain
Stores a chain for the certificate with the given Enrollment ID, so that GET /enrollment/view-trust-chain and POST /enrollment/trust-certificate-chain can use it. Despite the field name, the handler accepts PEM text: either a -----BEGIN PKCS7----- block or -----BEGIN CERTIFICATE----- blocks. The text must have that armour and hold at least one certificate that parses, otherwise nothing is stored (400). The chain replaces the one already stored for the record, whatever it was, so upload the complete chain. The format is checked before the record is looked up, so a bad value for an unknown eid is answered 400, not 404. The body must be a JSON object sent with a JSON Content-Type (a body with any other type is treated as missing, 400). This handler checks no permission beyond authentication.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
eid |
integer or string | Yes | Enrollment ID of the certificate the chain belongs to: a positive integer, or a string of digits. 0 is treated as missing; any other type (a boolean, a fraction, an object) is a 400. |
p7b |
string | Yes | The chain as PEM text: a -----BEGIN PKCS7----- ... -----END PKCS7----- block, or one or more -----BEGIN CERTIFICATE----- ... -----END CERTIFICATE----- blocks. The text must start with one BEGIN line and end with the matching END line (surrounding whitespace is ignored), and it must contain at least one certificate that can be parsed, otherwise 400. It replaces the stored chain. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/upload-chain" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"eid":1048,"p7b":"-----BEGIN CERTIFICATE-----\nMIIDgzCCAmugAwIBAgIGShssPU5fMA0GCSqGSIb3DQEBCwUAMGwxCzAJBgNVBAYT\nAlVTMQ4wDAYDVQQIDAVUZXhhczEPMA0GA1UEBwwGRGFsbGFzMRUwEwYDVQQKDAxF\neGFtcGxlIENvcnAxCzAJBgNVBAsMAklUMRgwFgYDVQQDDA93d3cuZXhhbXBsZS5j\nb20wHhcNMjYwMTAxMDAwMDAwWhcNNDYwMTAxMDAwMDAwWjBsMQswCQYDVQQGEwJV\nUzEOMAwGA1UECAwFVGV4YXMxDzANBgNVBAcMBkRhbGxhczEVMBMGA1UECgwMRXhh\nbXBsZSBDb3JwMQswCQYDVQQLDAJJVDEYMBYGA1UEAwwPd3d3LmV4YW1wbGUuY29t\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4KGdPq0SDQaATi+On/dF\nTH+mxg8a6grfrTpOk5FwE33zG+ow0s5ggulvCOuWSZ0mNhMlVPXIdcD09hO+kPXY\nNxh7TxQdJA5CQLS8Luo0NkdeA6VUPx0b1F5AA/ooaAPs7WXSiLrDCIrmrVg0uWJF\nUIH491cHZygNvIOLsbFo9VxKJZTql0YLlZZGV3JECZiPXyIqLvZFlCMdFzcLtoZA\nVpLJKOM7W31kum5uoZYwd+g7KFQ48vimcj+04mZhE4rhpx5iOUz6EMfad1Ttm8i2\ncpLVxBhLvUN+PO/RXAjmtS7KJ2Azv9FY0eRlahXWHj4X9Za1CUY3kvYA+4vz3JVO\ntwIDAQABoyswKTAnBgNVHREEIDAegg93d3cuZXhhbXBsZS5jb22CC2V4YW1wbGUu\nY29tMA0GCSqGSIb3DQEBCwUAA4IBAQAs+vreNbnsbORRn4Xlqkx3YgFIVUr9ia+s\nE+KNkFtZ6VqwJ4zBCghYUXAcvGqb/0Ru1jr1hXFW1C4WgeXoGhWm+l6FEgLaHA0Z\nh9JcUZ+zkhLnzHtsz4EBnqmDQ93YjFbQMFkPFxrO98RZsbgcGovF4ohrxRypcYbS\nwcbPRP1NWcF8ljJlbLCTM4pEGz4wfaioZHRed5Po0EcOh5O0JLkqxrhlW6Y9enNE\n5NBywAIeg8Dh50rNtoo9LlvpPboNdr7+Kit+xmzTOoZK2Ky9SjuVm7vOIQ17/02y\n9pPQRD5Uz8jRif2CRgIrm9KuqGsR6C+LM6cvL3CKn4r/zJ9Dk2Uy\n-----END CERTIFICATE-----\n"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The chain was stored. |
| 400 | The body is not a JSON object, eid or p7b is missing or empty, eid has the wrong type, or p7b is not PEM armoured text holding a certificate that parses. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 404 | No enrollment record has this Enrollment ID. |
| 500 | The upload failed unexpectedly. |
Example Response
{
"Success": "Certificate chain uploaded successfully"
}
GET /enrollment/user
Unavailable when the administrator has not configured user certificates; Available for Request when none has been requested yet (or the last one belongs to someone else); Certificate Requested.Pending approval. while the request is requested or pending; Issued otherwise. The last two carry the request's task id and its enrollment details (data, the shape of GET /enrollment/enrolled_csr_details).
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/user" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The state of the caller's user certificate. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The stored request could not be read. |
Example Response
{
"status": "Unavailable",
"cert": null
}
POST /enrollment/user
Generates a key pair and a CSR for the caller (common name = the local part of their e-mail address, e-mail SAN, key size 2048, SHA256WITHRSA) using the organization details and the CA and template that the administrator configured, and queues the request in the background. Answers Unavailable when user certificates are not configured. Needs the organization details (a city, state and country) to have been filled in the Enrollment settings.
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/user" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The request was queued, or user certificates are not configured. |
| 400 | The organization details needed for the CSR have not been configured. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The key pair or request could not be generated. |
Example Response
{
"SUCCESS": true
}
POST /enrollment/user/download-cert
Downloads the certificate record behind the self-service configuration saved with POST /enrollment/user/manage. Two states answer 200 with a small JSON status object and no certificate: Unavailable when no self-service configuration has been saved, and Available for Request when one exists but no certificate has been requested yet. Otherwise the 200 body is the certificate itself, in the format chosen by type (default cer): cer is the PEM certificate, p7b the PKCS#7 bundle text, text the chain as concatenated PEM blocks, zip a ZIP archive with one .cer file per chain certificate (application/zip) and pfx a PKCS#12 file protected by password (binary, but sent with the default text/html media type like cer, p7b and text). type is matched case-insensitively. The caller must be a global administrator, a Department PKIAdmin whose department owns the certificate's CA, or the record's owner or a listed recipient; cer, p7b, text and zip are also open to anyone holding the Download Certificate permission. The request body is only read once a certificate record exists, so the first two states answer identically whatever is sent. Once one does, the body must be a JSON object (400 otherwise). A record that has no certificate yet, for instance a request still pending approval, is answered 409.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | No | Format to download: cer (PEM certificate), p7b, text (PEM chain), zip or pfx. Case-insensitive. Optional: defaults to cer when omitted. Any other value is refused with a 400 once a certificate record exists. |
password |
string | No | Password that protects the PKCS#12 (pfx) file. Required (400 otherwise) when type is pfx and ignored for every other type (when sent it must still be a string, whatever type is: 400 otherwise). For pfx it must satisfy the password policy (passwordRestriction from GET /enrollment/policy: minimum length and minimum counts of upper-case, lower-case, digit and special characters). |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/user/download-cert" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"type":"cer"}'
Responses
| Status Code | Description |
|---|---|
| 200 | Either the JSON status object (nothing to download yet), or the certificate in the requested format: application/zip for zip, otherwise the text or binary body is sent as text/html. |
| 400 | The request cannot produce the requested download: the body is not a JSON object, type or password is not a string, type is not one of the supported formats, or password is missing or breaks the policy for pfx. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 403 | Authenticated, but the caller is neither an administrator for the certificate's CA nor its owner or a listed recipient (and, for pfx, no permission substitutes for that). |
| 404 | The enrollment record the self-service certificate points at no longer exists (or, for pfx, is no longer active). |
| 409 | The record the self-service certificate points at has no certificate yet, for instance because the request is still pending approval. Nothing is wrong with the request itself. |
| 500 | The download failed after the record was found, for example the record carries no PKCS#7 bundle for p7b, zip or text, or the PKCS#12 export failed. |
Example Response
{
"status": "Unavailable",
"cert": null
}
GET /enrollment/user/manage
Returns the saved CA and template. Both are empty strings until a configuration has been saved with POST.
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/user/manage" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The saved configuration, or empty strings when none has been saved. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The configuration could not be read; the cause is in the server log. |
Example Response
{
"caName": "Issuing CA 1",
"template": "User"
}
POST /enrollment/user/manage
Replaces the saved CA and template. The body must be a JSON object and both keys are required, each a non-blank string; anything else is answered 400 and nothing is saved.
Request Body (application/json)
| Field | Type | Required | Description |
|---|---|---|---|
caName |
string | Yes | CertSecure name of the Certificate Authority that issues self-service user certificates. A non-blank string (400 otherwise). Stored as sent: it is not checked against the registered CAs. |
template |
string | Yes | Name of the certificate template to issue self-service certificates from. A non-blank string (400 otherwise). Stored as sent: it is not checked against the CA's templates. Pick one that exists, because POST /enrollment/user issues from it. |
Example Request
curl -X POST "https://<certsecure-backend-url>/enrollment/user/manage" \
-H "Authorization: Bearer <token>" \
-H "Content-Type: application/json" \
-d '{"caName":"Issuing CA 1","template":"User"}'
Responses
| Status Code | Description |
|---|---|
| 200 | The configuration was saved. |
| 400 | The body is not a JSON object, caName or template is missing, is not a string, or is blank. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The configuration could not be saved; the cause is in the server log. |
Example Response
{
"Message": "Configuration Saved"
}
GET /enrollment/view-trust-chain
Returns the chain that CertSecure built for the certificate with the given Enrollment ID, ordered from the leaf up to the root. Each element describes one certificate of the chain and says whether it is a trusted root. A record with no stored chain, and an Enrollment ID that does not exist, both answer 200 with an empty array.
Request Parameters
| Name | Located In | Type | Required | Description |
|---|---|---|---|---|
eid |
Query | integer | Yes | Enrollment ID of the certificate whose chain to return. Must be an integer. |
Example Request
curl -X GET "https://<certsecure-backend-url>/enrollment/view-trust-chain?eid=<eid>" \
-H "Authorization: Bearer <token>"
Responses
| Status Code | Description |
|---|---|
| 200 | The chain, leaf first. Empty when the record has no chain or does not exist. |
| 400 | The eid query parameter is missing or empty, or is not an integer. |
| 401 | Authentication failed. The Authorization header is missing, malformed, expired, revoked, or names a session that no longer exists. |
| 500 | The chain could not be read. |
Example Response
[
{
"level": "leaf",
"status": "active",
"is_trusted_root": false,
"common_name": "www.example.com",
"subject": "CN=www.example.com,OU=IT,O=Example Corp,L=Dallas,ST=Texas,C=US",
"issuer": "Example Root CA (CN=Example Root CA,O=Example Corp,C=US)",
"serial": "4a1b2c3d4e5f",
"signature_algorithm": "sha256WithRSAEncryption",
"public_key": {
"algorithm": "RSA",
"type": "RSA",
"family": "RSA",
"size": 2048,
"exponent": 65537
},
"fingerprints": {
"sha256": "0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0"
},
"valid_from": "Thu, 01 Jan 2026 00:00:00 GMT",
"valid_to": "Fri, 01 Jan 2027 00:00:00 GMT",
"is_ca": false,
"path_length": null,
"self_signed": false,
"ski": "4a1b2c3d4e5f60718293a4b5c6d7e8f901234567",
"aki": "7654321098fedcba0987654321fedcba09876543",
"ocsp": "http://ocsp.example.com",
"issuer_url": "http://pki.example.com/root.crt",
"crl_distribution_points": [
"http://pki.example.com/root.crl"
]
}
]