Support · Requirements · Installation · License · Related Integrations
The CERTInext AnyCA Gateway REST plugin extends the certificate lifecycle capabilities of the CERTInext platform (by eMudhra) to Keyfactor Command via the Keyfactor AnyCA Gateway REST. The plugin represents a fully featured AnyCA REST plugin with the following capabilities:
- CA Synchronization:
- Download all certificates issued through the CERTInext CA, either as a full inventory or incrementally since the last sync.
- Expired certificates can optionally be excluded from synchronization using the
IgnoreExpiredconfiguration flag. - A pending or issued order created in the last
SyncRecentOrderGraceSecondsseconds (default120, plus a 5-second clock margin;0turns the hold off) is not imported by that sync pass; the next incremental pass imports it. Without this, a sync that runs while an enrollment is still in flight can list the new order before the enrollment has saved it, and the gateway then rejects the enrollment's own save with a duplicate-key error even though the certificate issued. Revoked and failed orders are never held back. A held-back order reaches the gateway one sync interval later.
- Certificate Enrollment for profiles configured in CERTInext:
- New certificate enrollment (new keys and certificate).
- Certificate renewal — submits a new
GenerateOrderSSLorder when the prior certificate is within the configured renewal window (CERTInext has no dedicated renewal endpoint; the renewal-window check governs how Command tracks old→new, not which API is called). - Certificate reissuance (new keys with the same or updated subject/SANs) when outside the renewal window or no prior certificate is found.
- Synchronous certificate pickup — a fast-issuing order (DV, or already-approved) can return the certificate in the same enrollment call instead of always waiting for the next sync, via
PickupRetries/PickupDelay. Renewals use the same pickup; on a DCV build withDcvEnabled, a renewal still pending DNS-01 validation returns pending at once and the next sync completes it.
- Certificate Revocation:
- Request revocation of a previously issued certificate using any RFC 5280 CRL reason code.
- Supported authentication modes for calls to the CERTInext API:
- AccessKey (HMAC-based request signing) — the primary and recommended mode
- OAuth (bearer token via client credentials flow)
The CERTInext AnyCA Gateway REST plugin is compatible with the Keyfactor AnyCA Gateway REST 25.5.0 and later.
The CERTInext AnyCA Gateway REST plugin is supported by Keyfactor for Keyfactor customers. If you have a support issue, please open a support ticket via the Keyfactor Support Portal at https://support.keyfactor.com.
To report a problem or suggest a new feature, use the Issues tab. If you want to contribute actual bug fixes or proposed enhancements, use the Pull requests tab.
- Keyfactor Command 25.5.x or later
- AnyCA Gateway REST framework version 25.5.0 or later
- A CERTInext account with API access enabled and at least one certificate product configured
- Network connectivity from the AnyCA Gateway host to the CERTInext API endpoint for your region (see table below)
- The AnyCA Gateway host must trust the TLS certificate presented by the CERTInext API endpoint
CERTInext operates three separate environments. Use the sandbox environment for initial integration testing. Switch to a production environment only after all functionality has been verified.
| Environment | Portal Sign-in URL | API Base URL |
|---|---|---|
| Sandbox | https://sandbox-us.certinext.io/ | https://sandbox-us-api.certinext.io/emSignHub-API/ |
| Production — India (Global) | https://in.certinext.io/ | https://api.certinext.io/emSignHub-API/ |
| Production — US | https://us.certinext.io/ | https://us-api.certinext.io/emSignHub-API/ |
Note: Product codes differ between sandbox and production. Always confirm product codes from the GetProductDetails API call against the environment you are targeting before going live.
-
Install the AnyCA Gateway REST per the official Keyfactor documentation.
-
On the server hosting the AnyCA Gateway REST, download and unzip the latest CERTInext AnyCA Gateway REST plugin from GitHub.
-
Copy the unzipped directory (usually called
net8.0ornet10.0) to the Extensions directory:Depending on your AnyCA Gateway REST version, copy the unzipped directory to one of the following locations: Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net8.0\Extensions Program Files\Keyfactor\AnyCA Gateway\AnyGatewayREST\net10.0\Extensions
The directory containing the CERTInext AnyCA Gateway REST plugin DLLs (
net8.0ornet10.0) can be named anything, as long as it is unique within theExtensionsdirectory. -
Restart the AnyCA Gateway REST service.
-
Navigate to the AnyCA Gateway REST portal and verify that the Gateway recognizes the CERTInext plugin by hovering over the ⓘ symbol to the right of the Gateway on the top left of the portal.
-
Follow the official AnyCA Gateway REST documentation to define a new Certificate Authority, and use the notes below to configure the Gateway Registration and CA Connection tabs:
-
Gateway Registration
Before enrolling certificates, the Keyfactor Command server must trust the CERTInext issuing CA chain.
- Log in to the CERTInext portal and download the root CA certificate and any intermediate CA certificates in the chain as PEM or DER files.
- On the Keyfactor Command server, import those certificates into the appropriate Windows certificate store — Trusted Root Certification Authorities for the root CA and Intermediate Certification Authorities for any subordinate CAs.
- In the Keyfactor Command Management Portal, navigate to CA Connectors and add a new CA using the CERTInext AnyCA REST Gateway Plugin.
- Complete the CA connector configuration fields described in the next section, then save and test the connection. The gateway performs a live connectivity test against the CERTInext
ValidateCredentialsendpoint during validation.
-
CA Connection
Populate using the configuration fields collected in the requirements section.
- ApiUrl - CERTInext API base URL. Sandbox (US): https://sandbox-us-api.certinext.io/emSignHub-API/ — Production (US): https://us-api.certinext.io/emSignHub-API/ — Production (Global/India): https://api.certinext.io/emSignHub-API/
- AccountNumber - Your CERTInext account number (numeric string). Available in the CERTInext portal.
- GroupNumber - CERTInext group (delegation) number. When set, it is included in GetProductDetails requests AND in the
orderDetails.groupNumberfield of every SSL order (new and renewal) so the order is routed to the configured account group. When blank, CERTInext uses the account's default group. Available in the CERTInext portal under Delegation → Groups. - OrganizationNumber - Numeric CERTInext organization number for a pre-vetted organization. When set, every SSL order is submitted with
organizationDetails.preVetting="1"and thisorganizationNumber, so CERTInext can reuse that organization's pre-verified domains without fresh DCV. Leave blank to omitorganizationDetails. Available in the CERTInext portal under Organizations → Pre-vetted Organizations. - TechnicalContactName - Technical point of contact name, sent as
technicalPointOfContact.pocFirstName/pocLastNameon every SSL order (new and renewal). The name is split on the first whitespace: the first word is the first name and the rest is the last name; a single-word name is sent in both. Defaults to the configured RequestorName when blank. If no contact name or no email resolves (including from RequestorName/RequestorEmail), the whole technicalPointOfContact block is omitted from the order and a Warning is logged, since CERTInext requires both inside the block. - TechnicalContactEmail - Email sent in the
technicalPointOfContact.pocEmailfield of every SSL order. Defaults to the configured RequestorEmail when blank. If no contact name or no email resolves (including from RequestorName/RequestorEmail), the whole technicalPointOfContact block is omitted from the order and a Warning is logged, since CERTInext requires both inside the block. - TechnicalContactIsdCode - International dialing code for the technical contact phone number, sent as
technicalPointOfContact.pocIsdCode. Defaults to the configured RequestorIsdCode when blank. - TechnicalContactMobileNumber - Mobile number for the technical contact (digits only), sent as
technicalPointOfContact.pocMobileNumber. Defaults to the configured RequestorMobileNumber when blank. - AuthMode - Authentication mode. 'AccessKey' (default) — uses authKey = SHA256(accessKey + ts + txn) in every request body. 'OAuth' — uses an OAuth2 bearer token (requires OAuthTokenUrl, OAuthClientId, OAuthClientSecret).
- ApiKey - The REST API Access Key generated in the CERTInext portal under Integrations → APIs. This value is used to compute authKey = SHA256(accessKey + ts + txn); it is never transmitted directly.
- OAuthTokenUrl - OAuth token endpoint URL. Required when AuthMode is 'OAuth'.
- OAuthClientId - OAuth client ID. Required when AuthMode is 'OAuth'.
- OAuthClientSecret - OAuth client secret. Required when AuthMode is 'OAuth'.
- RequestorName - Default requestor name submitted with all certificate orders. This is the name of the person/service responsible for the certificates.
- RequestorEmail - Default requestor email submitted with all certificate orders. Must be a valid email address registered in your CERTInext account.
- RequestorIsdCode - International dialing code for the requestor phone number (e.g. '1' for US). Default: '1'.
- RequestorMobileNumber - Requestor mobile number (digits only, no country code).
- SignerPlace - City or location of the subscriber agreement signer. Required by CERTInext for all orders. A template SignerPlace overrides it. If neither is set, the placeholder "Gateway" is sent and a Warning is logged; set it so the agreement audit record is accurate.
- SignerIp - IP address of the subscriber agreement signer. Required by CERTInext for all orders. A template SignerIp overrides it. If neither is set, the placeholder 127.0.0.1 is sent and a Warning is logged. A value that is not an IP address is still sent unchanged, with a Warning.
- DefaultProductCode - Connector-level fallback product code. Enroll and renewal do not use it: the template must resolve a product code (ProductCode, ProfileId, or the built-in code for the selected product name), otherwise enrollment is rejected with "Template parameter 'ProfileId' is required." Set ProductCode on the template instead. Product codes are provided by eMudhra. Retrieve available codes from Integrations → APIs → GetProductDetails.
- AccountingModel - CERTInext billing model sent in
orderDetails.accountingModel. "2" = credit-based (most accounts, default). "1" = cash model. - EmailNotifications - Whether CERTInext sends lifecycle-event emails to the requestor. "1" = enabled, "0" = silent (recommended for gateway-driven orders so end users aren't surprised by CA emails). Default: "0".
- SubscriptionValidityYears - Default validity in years for SSL orders. "1", "2", or "3". Used when the template sets neither ValidityYears nor ValidityDays; a template term (the larger of ValidityYears and ValidityDays in years) overrides it. Default: "1".
- SubscriptionAutoRenew - Whether CERTInext should auto-renew certificates issued through this connector. "0" = disabled (recommended — renewal is driven by Keyfactor Command), "1" = enabled. Default: "0".
- SubscriptionRenewCriteriaDays - Days before expiry at which CERTInext auto-renews (only honored when SubscriptionAutoRenew = "1"). Typical values: "30" or "60". Default: "30".
- AutoSecureWww - Sent as
orderDetails.autoSecureWWWon every SSL order (new and renewal). If "1", CERTInext automatically adds thewww.variant of the primary domain as an additional SAN, which must also pass domain validation. "0" = use only the CN/SANs supplied with the CSR. Default: "0". - IgnoreExpired - If true, expired certificates will be skipped during synchronization. Default: false.
- SubmitNonDnsSans - If true (default), SANs that are not DNS names (IP address, email, URI) are submitted to CERTInext in additionalDomains along with the DNS names. CERTInext registers them verbatim as order domains and they cannot pass domain validation, so such an order will not issue until they are removed — but nothing the subscriber requested is dropped silently. Set to false to submit DNS names only, which restores the pre-1.0.1 behaviour: the order issues, but the certificate will not contain the non-DNS names. Default: true.
- PageSize - Number of orders to fetch per page during synchronization. Default: 100, max: 500.
- SyncRecentOrderGraceSeconds - OPTIONAL: during Synchronize (full and incremental), a pending or issued order created less than this many seconds ago (plus a small clock margin) is not emitted to the gateway; the next incremental pass imports it. This stops the sync from inserting a gateway row for an order whose enrollment is still in flight, which would make the enrollment's own save fail with a duplicate key even though the certificate issued. Revoked and failed orders are never held back. 0 disables the hold; a negative value uses the default. Default: 120.
- Enabled - Enables or disables the CA connector. Set to false to create the connector record before credentials are available. Default: true.
- LogSensitiveRequestData - Diagnostic escape hatch. When true, requestor personal data (name, email, phone, and other organization contact details) and full CA request/response payloads are written to the gateway logs: the Trace-level order request/response bodies and the API-failure response bodies are left unredacted (beyond the credential scrubbing that always applies), SAN values and CA error text are logged unmasked, and the Information-level enrollment-attempt log line includes the requestor's name and email in full. A startup Warning is logged whenever it is on. This is meant for temporary use while verifying a new deployment — confirming exactly what was sent to the CA and that the order succeeded — and should be turned back off once verification is complete. When false (default), personal data fields are redacted to 'REDACTED' (email is masked but keeps its domain, e.g. 'j***@example.com'), email SAN values and email addresses in CA error text are masked the same way, mailto:/sip:-style URI SANs are masked and 'user:pw@' userinfo in URI SANs is replaced with '***', and the enrollment log line omits the requester name entirely. DNS and IP SANs are always logged in full. Credentials (the values of the authKey, client_secret, apiKey, accessKey and password fields, and Authorization header lines) are always redacted from logged request/response bodies regardless of this setting. Default: false.
- PickupRetries - Number of times Enroll() will poll CERTInext to download the certificate after a successful order submission. If the certificate has not issued within this window it is picked up during the next synchronization instead. Set to 0 to disable the wait; values are clamped to 0-30. Default: 5. NOTE: CERTInext issues OV/EV certificates asynchronously (organization verification, minutes to hours), so those typically exhaust the wait and are returned pending regardless of this value. On the DCV build, an order that DNS-01 DCV engages for uses the DCV waits (DcvWaitForIssuanceSeconds) instead of this pickup.
- PickupDelay - Number of seconds between certificate-pickup retries. PickupRetries times this delay (plus a short initial delay) is the maximum time an enrollment call occupies a Command worker thread. If the duration is too long the request may time out, so target a total well under ~90s. As a safety backstop the plugin additionally caps the effective total at 180s regardless of how PickupRetries/PickupDelay are set, reducing the retry count to fit. Values are clamped to 1-60; a non-positive value uses the default. Default: 10 (with default retries this yields a ~55s ceiling).
- DcvEnabled - When true, the gateway will perform DNS-based Domain Control Validation (DCV) during enrollment for orders that require it, using the configured DNS provider plugin. Requires a DNS provider plugin (e.g. azure-azuredns-dnsplugin) to be deployed on the gateway. On the default (non-DCV) build there is no DNS validation support, so setting this only logs a startup Warning. Default: false.
- DcvTxtRecordTemplate - Format string for the DNS TXT record hostname used during DCV. {0} is replaced with the domain name being validated. Default: _emsign-validation.{0}
- DcvPropagationDelaySeconds - Seconds to wait after publishing the DNS TXT record before asking CERTInext to verify it. Increase for zones with slow propagation. Default: 30.
- DcvTimeoutMinutes - Maximum minutes to wait for the entire DCV flow (DNS publish + propagation + verify) before timing out the enrollment. Can also be set via the CERTINEXT_DCV_TIMEOUT_MINUTES environment variable; the env var takes precedence when both are set. Default: 10.
- DcvWaitForChallengeSeconds - How long (seconds) the plugin will wait inside Enroll() for CERTInext to expose the DCV challenge (i.e. populate
domainVerificationin TrackOrder). Under concurrent load CERTInext sometimes takes a few seconds after GenerateOrderSSL before the slot appears. Without this wait, the plugin's initial TrackOrder check sees null and skips DCV — the order then has to wait for the next gateway sync cycle to be picked up. Setting to 0 disables the wait (single-check behaviour). Can also be set via the CERTINEXT_DCV_WAIT_FOR_CHALLENGE_SECONDS environment variable; the env var takes precedence when both are set. Default: 60. - DcvWaitForIssuanceSeconds - How long (seconds) the plugin will wait inside Enroll() after DCV verifies for CERTInext to finish generating the certificate. CERTInext issuance is async — DCV may be verified but the cert PEM isn't yet available for download. Without this wait, Enroll() returns a pending result and the issued cert is picked up by the next sync cycle. Setting to 0 disables the wait (single-fetch behaviour). Can also be set via the CERTINEXT_DCV_WAIT_FOR_ISSUANCE_SECONDS environment variable; the env var takes precedence when both are set. Default: 60.
- DcvSyncMaxOrderAgeHours - During synchronization, only pending DV orders younger than this many hours are eligible to be driven through DCV. This keeps a sync pass fast when there is a large backlog of old, never-completing pending orders (e.g. abandoned orders or domains outside the configured DNS provider's zone): they age out and are simply reported as pending rather than retried every pass. Recently-placed orders (the ones that legitimately deferred DCV) are always within the window and complete via the normal scan cadence. Set to 0 to disable the age filter (attempt DCV for all pending). Default: 24.
- DcvSyncMaxPerPass - Maximum number of pending DV orders the plugin will attempt to drive through DCV in a single synchronization pass. Bounds the per-pass cost regardless of backlog size; remaining pending orders are reported as-is and picked up on a later pass (the per-minute incremental scan keeps recent orders moving). Set to 0 to disable the cap. Default: 50.
-
-
Define Certificate Profiles and Certificate Templates for the Certificate Authority as required. One Certificate Profile must be defined per Certificate Template. It's recommended that each Certificate Profile be named after the Product ID. The CERTInext plugin supports the following product IDs:
- DV SSL
- DV SSL Wildcard
- DV SSL Multi-Domain (UCC)
- DV SSL Wildcard Multi-Domain (UCC)
- OV SSL
- OV SSL Wildcard
- OV SSL Multi-Domain (UCC)
- OV SSL Wildcard Multi-Domain (UCC)
- EV SSL
- EV SSL Multi-Domain (UCC)
-
Follow the official Keyfactor documentation to add each defined Certificate Authority to Keyfactor Command and import the newly defined Certificate Templates.
-
In Keyfactor Command (v12.3+), for each imported Certificate Template, follow the official documentation to define enrollment fields for each of the following parameters:
- ProductCode - OPTIONAL: Override the numeric CERTInext product code for this template. When omitted, the default production code for the selected product is used automatically (e.g. DV SSL → 838). Set this explicitly when targeting sandbox or a non-standard code.
- ProfileId - DEPRECATED: Use ProductCode instead. Kept for backward compatibility — mapped to ProductCode if ProductCode is not set.
- ValidityYears - OPTIONAL: Subscription term in years: 1, 2, or 3. The order's term is the larger of ValidityYears and ValidityDays rounded up to whole years (365 days = 1 year); a field left at its default (1 year) never overrides the other. A template value overrides the connector's SubscriptionValidityYears. Because the larger value wins, a stale larger ValidityDays cannot be shortened with ValidityYears alone; set ValidityDays back to 365. Default: 1. Note: CERTInext validates per 390-day certificate within the subscription; the 'validity' field in the order is the subscription term, not certificate lifetime.
- ValidityDays - OPTIONAL: Requested validity in days. CERTInext's order API takes whole subscription years, so days are converted to years, rounded up (365 days = 1 year). The order's term is the larger of this and ValidityYears; a field left at its default (365 days = 1 year) never overrides the other. Kept because certificate lifetimes are shrinking and days is the unit that will matter if CERTInext adds a lifetime field. To shorten a template with a larger value, set this back to 365. Default: 365.
- AutoApprove - Currently has no effect — reserved for future use. The plugin does not call any approval endpoint against CERTInext regardless of this setting.
- RequesterName - OPTIONAL: Per-template override for the requestor name; when blank, the connector's RequestorName is used.
- RequesterEmail - OPTIONAL: Per-template override for the requestor email; when blank, the connector's RequestorEmail is used.
- RenewalWindowDays - OPTIONAL: Number of days before certificate expiration within which a renewal is triggered. Certificates expiring further than this window are reissued instead. Certificates that have already expired also fall back to reissue. Default: 90.
- KeyType - OPTIONAL: Key algorithm to request (e.g. 'RSA2048', 'RSA4096', 'EC256', 'EC384'). If omitted, the profile default is used.
- DomainName - OPTIONAL: Primary domain for SSL/TLS orders. Derived from the CSR CN if omitted.
- SignerName - OPTIONAL: Per-template subscriber agreement signer name. Falls back to the connector-level RequestorName if omitted, then to the placeholder "Keyfactor Gateway" (Warning logged).
- SignerPlace - OPTIONAL: Per-template signer city/location. Falls back to the connector-level SignerPlace if omitted, then to the placeholder "Gateway" (Warning logged).
- SignerIp - OPTIONAL: Per-template signer IP address. Falls back to the connector-level SignerIp if omitted, then to the placeholder 127.0.0.1 (Warning logged). A value that is not an IP address is sent unchanged, with a Warning.
The CERTInext REST API uses HMAC-style request signing. Every API call includes a computed authKey field in the request body. The access key itself is never transmitted — only the derived hash is sent.
The authKey is computed as:
authKey = SHA256(accessKey + requestTs + requestTxnId)
Where requestTs is the ISO 8601 timestamp of the request and requestTxnId is the unique transaction ID generated per request. The gateway performs this computation automatically on every outbound API call.
Steps to generate an Access Key:
- Log in to the CERTInext portal for your environment (e.g. https://in.certinext.io).
- Navigate to Integrations → APIs.
- Click + Create API Credentials at the top right of the page.
- In the dialog, fill in the following fields:
- API Type: Select
REST. - Description: Enter a descriptive label, such as
keyfactor-gateway. - User: Select the CERTInext user account this credential will be associated with.
- Auth Type: Select
Access Key.
- API Type: Select
- Click Generate.
- In the confirmation dialog, copy the displayed Access Key immediately. This is the only time the key is shown in plaintext.
- Confirm that the new credential row appears in the APIs list with status Active before proceeding.
Enter the copied value in the ApiKey field of the CA connector configuration. The field is masked in the Keyfactor Command UI and stored in Command's encrypted gateway configuration.
If your CERTInext account has OAuth enabled, you can use OAuth client credentials as an alternative to AccessKey signing.
- Log in to the CERTInext portal.
- Navigate to Integrations → APIs.
- Click + Create API Credentials.
- Set API Type to
RESTand Auth Type toOAuth. - Complete the form and click Generate.
- Note the Client ID and Client Secret. Enter them in the
OAuthClientIdandOAuthClientSecretfields respectively. - Confirm the OAuth token endpoint URL with eMudhra and enter it in the
OAuthTokenUrlfield. - Set the
AuthModeconnector field toOAuth.
Note: Credentials are stored in Keyfactor Command's encrypted gateway configuration and are never written to disk by the plugin.
CERTInext uses numeric product codes to identify certificate types. Product codes are provisioned per account by eMudhra — the codes available to your account are determined when your account is set up. The codes in the tables below are the values observed on specific sandbox and production accounts; your account may have different codes.
To retrieve the exact codes available to your account, call the GetProductDetails endpoint:
- If you have a
GroupNumberconfigured, include it in the requestproductDetailsblock — some accounts require this to return a non-empty list. - Use the
make get-product-details-groupMakefile target to retrieve products from the sandbox withgroupNumberincluded.
Note: Product codes differ between the sandbox and production environments. Always verify the correct code before switching environments.
Note: Product codes are per-account. If you receive "Invalid Product Code" (EMS-1162) when placing an order, your account does not have that product provisioned. Contact your eMudhra account representative to request provisioning of the product codes you need.
The product codes in this table were observed on:
- the US sandbox environment (
sandbox-us-api.certinext.io) in April–May 2026 - the Production India environment (
api.certinext.io) via the live draft-order coverage matrix in development.md
Your account may still have different codes. Always call GetProductDetails against your target environment before going live.
| Product | Sandbox Code | Production Code | Required fields beyond base (domainName, csr, requestorInformation, subscriptionDetails, agreementDetails) |
|---|---|---|---|
| DV (Domain Validated) | 842 |
838 |
None. domainName is derived from the CSR CN if omitted on the template. |
| DV Wildcard | 843 |
839 |
CSR CN must use wildcard format (e.g. *.example.com). domainName in the order must also use the wildcard format. |
| DV UCC (Multi-domain) | 844 |
840 |
certificateInformation.additionalDomains — array of additional SAN values beyond the primary domainName. |
| DV Wildcard UCC (Multi-domain Wildcard) | 845 |
841 |
Combines wildcard and multi-domain requirements. CSR CN and domainName must use wildcard format; certificateInformation.additionalDomains required. |
| OV (Organization Validated) | 846 |
842 |
organizationDetails.organizationNumber (your CERTInext org ID); certificateInformation.locality, postalCode, and full organization address fields (streetAddress, city, state, country). |
| OV Wildcard | 847 |
843 |
Same as OV. CSR CN and domainName must use wildcard format. |
| OV UCC (Multi-domain) | 848 |
844 |
Same as OV plus certificateInformation.additionalDomains. |
| OV Wildcard UCC (Multi-domain Wildcard) | 849 |
845 |
Combines OV, wildcard, and multi-domain requirements. Same as OV plus wildcard CN/domainName and certificateInformation.additionalDomains. |
| EV (Extended Validation) | 850 |
846 |
All OV fields plus: contractSignerInfo object (name, email, isdCode, mobileNumber, designation, employeeID); certificateApproverInfo object (same fields); certificateInformation.companyRegistrationNumber; streetAddress2 must be non-empty. |
| EV UCC (Multi-domain EV) | 851 |
847 |
Same as EV plus certificateInformation.additionalDomains. |
Note: SSL/TLS codes appear to be offset by 4 between the US sandbox and Production India in the snapshots we've observed — but treat that as a coincidence, not a guarantee. eMudhra controls the per-account mapping and may use different numeric codes for any new account. Always confirm via
GetProductDetails.
Note: The CERTInext portal may display additional short-validity products (e.g. DV SSL Certificate 1 Month, DV SSL Certificate Wildcard 1 Month) that do not appear in the
GetProductDetailsAPI response and have no published product code. These products are not accessible via the API and are therefore not supported by this plugin. Contact eMudhra to determine whether API ordering is available for these products on your account.
| Product | Sandbox Code | Production Code | Availability |
|---|---|---|---|
| emSign Intranet SSL 1 year | 149 |
100 |
Requires special provisioning by eMudhra. Not orderable on standard accounts. |
| IGTF Host 1 year | (not observed) | 104 |
Requires special provisioning by eMudhra. Not orderable on standard accounts. |
Note: Private PKI products are not available for ordering on standard CERTInext accounts. Attempting to place an order will return EMS-1162 (product not provisioned). The sandbox Private PKI code (
149) also returns EMS-1162 on standard sandbox accounts even though it appears in theGetProductDetailslist. Contact eMudhra to have these products enabled on your account.
The same numeric product codes have been observed for S/MIME and document-signing products on both the US sandbox and Production India in the snapshots we have. Treat that as an empirical observation, not a contract — eMudhra is free to assign different codes per account. Always confirm via GetProductDetails.
| Product | Sandbox / Production Code | Availability |
|---|---|---|
| S/MIME | 894 |
Requires a separate S/MIME entitlement on the account. Not available on standard SSL accounts. |
| Natural Person Doc Signer (tier 1) | 825 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Natural Person Doc Signer (tier 2) | 826 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Natural Person Doc Signer (tier 3) | 827 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Person Doc Signer (tier 1) | 822 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Person Doc Signer (tier 2) | 823 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Person Doc Signer (tier 3) | 824 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Entity Doc Signer (tier 1) | 819 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Entity Doc Signer (tier 2) | 820 |
Requires document signing entitlement. Not orderable on standard accounts. |
| Legal Entity Doc Signer (tier 3) | 821 |
Requires document signing entitlement. Not orderable on standard accounts. |
Note: S/MIME (894) and document signing products (819–827) require a separate entitlement that is not included in a standard SSL/TLS account. Contact eMudhra to request access.
To retrieve the full list of product codes available to your account, call the GetProductDetails endpoint against your target environment. The sandbox and production APIs each return their own set of codes.
Note: SSL/TLS products are supported on standard accounts — see the SSL/TLS table above for the exact sandbox/production code pair for each product. Private PKI (Production
100,104/ Sandbox149), S/MIME (894), and document-signing products (819–827) require special provisioning by eMudhra and are not available on standard SSL/TLS accounts — ordering them returns EMS-1162.
This document describes how the CERTInext AnyCA Gateway REST plugin integrates with Keyfactor Command and the CERTInext certificate authority. It covers the three primary certificate lifecycle operations — synchronization, enrollment, and revocation — and how the plugin routes each through the CERTInext API.
┌─────────────────────────────────────────────────────────┐
│ Keyfactor Command │
│ │
│ Certificate Enrollment · Revocation · Sync Jobs │
└────────────────────────────┬────────────────────────────┘
│
AnyCA Gateway REST
(plugin host process)
│
┌────────────────────────────▼────────────────────────────┐
│ CERTInext AnyCA Gateway Plugin │
│ │
│ Translates Keyfactor operations into CERTInext API │
│ calls, maps responses back to Command's data model, │
│ and enforces audit logging on every operation. │
└────────────────────────────┬────────────────────────────┘
│ HTTPS · HMAC-signed requests
│
┌────────────────────────────▼────────────────────────────┐
│ CERTInext REST API (eMudhra) │
│ │
│ ValidateCredentials GenerateOrderSSL TrackOrder │
│ GetCertificate RevokeOrder GetOrderReport │
│ GetProductDetails SubmitCSR │
└─────────────────────────────────────────────────────────┘
Every API call is signed using HMAC-SHA256. The access key itself is never transmitted — only a derived hash is sent:
authKey = SHA256(accessKey + requestTs + requestTxnId)
A unique transaction ID (requestTxnId) is generated for each request. The timestamp (requestTs) and transaction ID travel alongside the authKey so the CERTInext server can reproduce and verify the hash. The plugin handles this automatically; no manual signing is required during normal operation.
An OAuth client-credentials mode is also available as an alternative. When OAuth is configured, the plugin exchanges a client ID and secret for a short-lived bearer token and automatically refreshes it before expiry.
CERTInext assigns two different reference numbers to each order. Understanding the difference matters when tracing certificates across systems:
| Identifier | When it is assigned | What it is used for |
|---|---|---|
| Request Number | Immediately when an order is created | Tracking a draft order before it is formally submitted; attaching a CSR to a pending order |
| Order Number | After the order is formally submitted and accepted | All post-issuance operations: checking status, downloading the certificate, revoking — this is the identifier stored in Keyfactor Command |
When the AnyCA Gateway process starts, it loads each configured CA connector. For CERTInext, this step reads the connector settings, establishes the API client, and confirms that the credentials are structurally valid.
sequenceDiagram
participant GW as AnyCA Gateway
participant Plugin as CERTInext Plugin
participant API as CERTInext API
GW->>Plugin: Load CA connector configuration
Plugin->>Plugin: Validate required fields<br/>(API URL, account number, credentials)
Plugin->>Plugin: Initialize API client<br/>with configured auth mode
Plugin->>Plugin: Record which credential fields are populated<br/>(values are never logged)
GW->>Plugin: Test connection
Plugin->>API: Verify credentials
API-->>Plugin: Credentials accepted
Plugin-->>GW: Connector ready
Keyfactor Command periodically synchronizes its certificate inventory with CERTInext. The plugin retrieves all orders page by page and feeds them into Command's database. Synchronization can be a full refresh or incremental (only orders placed since the last successful sync).
sequenceDiagram
participant CMD as Keyfactor Command
participant Plugin as CERTInext Plugin
participant API as CERTInext API
CMD->>Plugin: Start synchronization<br/>(full refresh or incremental since last sync)
Plugin->>Plugin: Determine date filter<br/>(none for full sync, last sync date for incremental)
loop Retrieve one page at a time
Plugin->>API: Request next page of orders<br/>(filtered by date if incremental)
API-->>Plugin: Page of order records
loop For each order on the page
alt Certificate is expired and ignore-expired is enabled
Plugin->>Plugin: Skip — not imported
else Order failed or was cancelled
Plugin->>Plugin: Skip — no certificate to import
else Valid certificate
Plugin->>CMD: Add certificate record to inventory
end
end
end
Plugin->>Plugin: Log totals: imported / skipped / errors
Plugin-->>CMD: Synchronization complete
Full vs. incremental sync: A full sync imports every order in the account regardless of age. An incremental sync requests only orders placed after the previous sync timestamp, which is faster for accounts with large order histories.
Expired certificates: The IgnoreExpired connector setting controls whether expired certificates are included in synchronization. When enabled, expired certificates are silently skipped and will not appear in the Keyfactor Command inventory.
DCV-during-sync: on a DCV-enabled build, each sync pass also drives DNS-01 validation forward for pending DV orders that are still waiting on it, bounded by DcvSyncMaxOrderAgeHours (skip orders older than this) and DcvSyncMaxPerPass (cap how many are attempted per pass), so a large backlog of stalled pending orders can't slow down every sync.
When a requester submits a certificate request through Keyfactor Command, the plugin translates the request into a CERTInext order and returns the result. The plugin handles three enrollment scenarios: new issuance, renewal (within a configured window before expiry), and reissuance (new keys, same profile).
sequenceDiagram
participant CMD as Keyfactor Command
participant Plugin as CERTInext Plugin
participant API as CERTInext API
CMD->>Plugin: Request new certificate<br/>(CSR, subject, SANs, product code, requester details)
Plugin->>Plugin: Validate product code is present
Plugin->>Plugin: Record enrollment intent in audit log<br/>(subject, SANs, product, requester — before any API call)
Plugin->>API: Place certificate order<br/>(CSR, domain, organization details,<br/>subscriber agreement, requestor info)
API-->>Plugin: Order accepted — order number assigned
Plugin->>API: Check order status
API-->>Plugin: Order status and certificate details
alt DNS-01 DCV engaged (DCV build, DCV enabled, DNS provider available)
opt Order has domains pending DNS-01 validation
Plugin->>Plugin: Publish DNS TXT challenge<br/>via the configured DNS provider plugin
Plugin->>API: Ask CERTInext to verify the record
API-->>Plugin: Domain validated (or skipped / still pending)
end
opt Every pending domain validated
loop DCV issuance wait<br/>(bounded by DcvWaitForIssuanceSeconds, 60s by default)
Plugin->>API: Poll for the certificate
API-->>Plugin: Status and certificate, if ready
end
end
else DCV not engaged and order still pending
loop Certificate-pickup retries<br/>(bounded, ~55s by default — PickupRetries/PickupDelay)
Plugin->>API: Poll for the certificate
API-->>Plugin: Status and certificate, if ready
end
end
alt Certificate available (immediately, or during the DCV or pickup wait)
Plugin-->>CMD: Certificate ready — PEM returned
else Order rejected by CERTInext
Plugin-->>CMD: Enrollment failed — see gateway logs
else Certificate still not available
Plugin-->>CMD: Pending — Command will pick it up<br/>during the next synchronization
end
Plugin->>Plugin: Record enrollment outcome in audit log<br/>(order number, serial number, status)
DCV: on a DCV-enabled build, DNS-01 validation runs inline for DV orders that require it, bounded by DcvTimeoutMinutes. DCV is "engaged" whenever the build supports it, DcvEnabled is set, and a DNS provider is available, whether or not this particular order ends up needing a challenge. An engaged order whose domains are already validated skips TXT staging and goes straight to the DCV issuance wait. When DCV isn't enabled, isn't built into this host, or no DNS provider is available, DCV does not engage and the order follows the synchronous pickup path below like any other asynchronously-issued order.
Waiting for issuance — DCV and pickup are alternatives, not stacked: when DCV engages for an order, DCV owns the in-call wait and the pickup loop does not run. After DCV verifies, Enroll() polls for the certificate for up to DcvWaitForIssuanceSeconds (default 60s), but only if every pending domain was validated. If any domain was skipped or rejected (for example an IP or email SAN with no DNS provider), a DCV step failed, or CERTInext never exposed the challenge within DcvWaitForChallengeSeconds, there is no further in-call wait: Enroll() returns pending carrying the order number and the next sync finishes the order.
Synchronous certificate pickup: when DCV did not engage (the default build, DcvEnabled off, or no DNS provider) and the order is still pending, Enroll() polls CERTInext a bounded number of times (PickupRetries × PickupDelay, each clamped and the total capped at a 180s ceiling) before giving up and returning pending. This lets a fast-issuing certificate (DV, or an already-approved order) come back in the same enrollment call instead of always waiting for the next sync. OV/EV orders validate asynchronously over minutes to hours and typically exhaust this window regardless.
When Command initiates a renewal, the plugin checks whether the existing certificate is within the configured renewal window. If it is, the prior order record is used as context for the new request. If it is outside the window (or the prior certificate cannot be located), the plugin falls back to issuing a new certificate.
Note: CERTInext does not have a dedicated certificate renewal endpoint. Both renewal and reissuance paths submit a new
GenerateOrderSSLorder. The distinction affects how Keyfactor Command tracks the certificate record, not what is sent to CERTInext.
Note: If the prior-order lookup itself throws (rather than cleanly returning "not found" — e.g. a transient database error), the plugin falls back to issuing a new certificate rather than failing the enrollment.
flowchart TD
A([Renewal requested]) --> B{Prior certificate<br/>serial number<br/>provided?}
B -- No --> C[Issue new certificate]
B -- Yes --> D[Look up prior order<br/>in Command database]
D --> E{Prior order<br/>found?}
E -- No --> C
E -- Yes --> F[Check certificate<br/>expiry date]
F --> G{Within renewal<br/>window?}
G -- Yes<br/>within window --> H[Submit new order<br/>linked to prior record]
G -- No<br/>outside window --> C
H --> I([Certificate issued or pending])
C --> I
Pickup on renewal: a renewal order goes through the same synchronous pickup as a new enrollment, so a fast-issuing renewal returns the certificate in the same call. The renew path never runs DCV in the call, so on a DCV build with DcvEnabled a renewal that is still waiting on DNS-01 validation can't issue inside the pickup window: it skips the wait and returns pending at once, and the next sync completes DCV and imports the certificate. Renewals that aren't waiting on DNS-01 validation (validation reused, DCV disabled, or the DCV-state check fails) keep the normal pickup.
When a certificate is revoked in Keyfactor Command, the plugin verifies the certificate's current state before calling the CERTInext revocation endpoint. This prevents unnecessary API calls for certificates that are already revoked or in a non-revocable state.
sequenceDiagram
participant CMD as Keyfactor Command
participant Plugin as CERTInext Plugin
participant API as CERTInext API
CMD->>Plugin: Revoke certificate<br/>(order number, serial number, reason code)
Plugin->>Plugin: Record revocation intent in audit log<br/>(order number, serial, reason — before any API call)
Plugin->>API: Retrieve current certificate status
API-->>Plugin: Current status and details
alt Certificate is already revoked
Plugin->>Plugin: Log warning — already revoked
Plugin-->>CMD: Confirmed revoked (no action needed)
else Certificate is not in an issued state
Plugin->>Plugin: Log error — cannot revoke
Plugin-->>CMD: Error — certificate is not revocable
else Certificate is issued and active
Plugin->>API: Submit revocation request<br/>(order number, reason, remarks)
API-->>Plugin: Revocation confirmed
Plugin->>Plugin: Record revocation outcome in audit log<br/>(order number, serial, subject, reason)
Plugin-->>CMD: Certificate revoked
end
Idempotency: If Command retries a revocation request (for example, after a timeout), the plugin detects that the certificate is already revoked and returns success without submitting a duplicate request to CERTInext.
Audit trail: The revocation intent is written to the gateway log before the API call is made. This ensures that the intent is captured even if the API call subsequently fails, satisfying SOX audit requirements.
When an administrator saves or edits a CERTInext CA connector in the Keyfactor Command Management Portal, the gateway validates the configuration and performs a live connectivity check.
flowchart TD
A([Save connector configuration]) --> B{Connector<br/>marked as disabled?}
B -- Yes --> C([Saved without validation<br/>Connector will not process requests])
B -- No --> D{Required fields<br/>present and valid?<br/>API URL · Account Number · Credentials}
D -- Missing or invalid --> E([Validation error shown to administrator])
D -- Valid --> F[Build temporary API client<br/>from supplied settings]
F --> G[Send test request<br/>to CERTInext]
G --> H{API accepted<br/>the credentials?}
H -- No --> I([Connection test failed<br/>Check credentials and API URL])
H -- Yes --> J([Connector saved and active])
Disabled connectors: Setting Enabled to false allows the connector record to be created and saved before credentials are available. The live connectivity test is skipped, so no credentials are required at save time.
The table below maps each Keyfactor Command operation to the CERTInext API endpoint it calls.
| Operation | CERTInext API endpoint |
|---|---|
| Test connection / verify credentials | POST ValidateCredentials |
| Issue new certificate | POST GenerateOrderSSL then POST TrackOrder |
| Renew certificate | POST GenerateOrderSSL then POST TrackOrder |
| Check certificate status | POST TrackOrder + POST GetCertificate |
| Revoke certificate | POST RevokeOrder |
| Synchronize inventory | POST GetOrderReport (paginated) |
| List available product codes | POST GetProductDetails |
| Attach CSR to draft order | POST SubmitCSR |
Apache License 2.0, see LICENSE.
See all Keyfactor Any CA Gateways (REST).