If your product works with a one-year commercial term while the CA only issues certificates with a shorter maximum validity, you can now automate that lifecycle much more cleanly with the current regfish API.
The important change is that the model is now split cleanly: follow-up issuances on the same order use POST /tls/certificate/{certificate_id}/reissue, while the transition into the next contract period uses POST /tls/certificate with renewal_of_certificate_id.
The API now exposes the provider-side contract window through contract_valid_from and contract_valid_until. If your own commerce or billing logic has an additional lifecycle on top, you can still enrich the workflow with your own business dates.
Prerequisites
- an API key with access to TLS and DNS endpoints
- the current certificate response, including
contract_valid_until - optionally, an internally stored commercial end date if it differs from the provider-side contract window
- an active certificate
idthat is currently deployed - a job or scheduler that can evaluate the workflow daily or multiple times per day
- a fresh CSR for every follow-up issuance
- a zone managed through Regfish DNS
Step 1: Place the initial issuance at the CA maximum validity
Create the first issuance directly with the maximum publicly documented validity_days. In the current OpenAPI contract that maximum is 199.
curl --request POST \
--url 'https://api.regfish.com/tls/certificate' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '
{
"sku": "RapidSSL",
"common_name": "www.example.com",
"dns_names": ["api.example.com"],
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC...\n-----END CERTIFICATE REQUEST-----",
"dcv_method": "dns-cname-token",
"validity_days": 199
}
'Store your internal control record right away alongside the API response. The provider-side contract window can come from the API, while any extra commercial context can still come from your own system if needed.
{
"contract_valid_from": "2026-03-16T00:00:00Z",
"contract_valid_until": "2027-03-16T23:59:59Z",
"active_certificate_id": "7K9QW3M2ZT8HJ",
"sku": "RapidSSL",
"common_name": "www.example.com",
"dns_names": ["api.example.com"],
"dcv_method": "dns-cname-token"
}Step 2: Finish the first issuance and store the actual validity
Take the records returned in validation.dns_records and create them in DNS. After that, poll the order until valid_until and certificate_pem_available are present.
curl --request POST \
--url 'https://api.regfish.com/dns/rr' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '
{
"type": "CNAME",
"name": "_dnsauth.example.com",
"data": "0123456789abcdef.dcv.digicert.com.",
"ttl": 300
}
'curl --request GET \
--url 'https://api.regfish.com/tls/certificate/7K9QW3M2ZT8HJ' \
--header 'x-api-key: YOUR_API_KEY'From the issued response, store at least:
contract_valid_fromcontract_valid_untilvalid_fromvalid_untilstatuscertificate_pem_available
Step 3: Calculate the re-issue window
The efficient lifecycle minimizes overlap, so it waits until shortly before the current certificate expires. At the same time, a re-issue should no longer be triggered once the remaining provider-side contract term is effectively used up.
A simple decision model looks like this:
reissue_lead_days = 7
safety_days = 2
days_until_expiry = floor((valid_until - now) / 86400)
days_until_contract_end = floor((contract_valid_until - now) / 86400)
if days_until_contract_end <= reissue_lead_days + safety_days:
action = "renew-next-term"
elif days_until_expiry > reissue_lead_days:
action = "wait"
else:
action = "reissue-now"The important parts are:
- only re-issue shortly before
valid_untilso you do not waste coverage - once the commercial remaining term is effectively used up, do not trigger one more re-issue; start the next renewal as a new order
- the main optimization still comes from the trigger timing; use
validity_dayson re-issue only when you intentionally want to request a shorter replacement lifetime for eligible multi-year orders - use
contract_valid_untilfrom the API as the baseline contract boundary; add your own commercial cutoff only if your business model needs it
Step 4: Trigger the re-issue on the same order
When the decision model returns reissue-now, trigger the re-issue directly on the existing certificate id. This is exactly where the new endpoint is a better fit than the older model of creating a separate certificate order.
curl --request POST \
--url 'https://api.regfish.com/tls/certificate/7K9QW3M2ZT8HJ/reissue' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '
{
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC...\n-----END CERTIFICATE REQUEST-----",
"dcv_method": "dns-cname-token",
"comments": "Scheduled reissue near certificate expiry",
"validity_days": 90
}
'For this re-issue, prefer a new key and therefore a new CSR. Only send validity_days when you intentionally want a shorter replacement certificate and the underlying multi-year order supports it.
Step 5: Update the DCV token efficiently
Do not assume that the old DCV token remains valid. Read the new record from response.reissue.validation.dns_records and update the existing _dnsauth record preferably through PATCH /dns/rr.
curl --request PATCH \
--url 'https://api.regfish.com/dns/rr' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '
{
"type": "CNAME",
"name": "_dnsauth.example.com",
"data": "fedcba9876543210.dcv.digicert.com.",
"ttl": 300
}
'If the record does not exist yet, the workflow falls back to POST /dns/rr for that step.
Step 6: Promote the new certificate and advance internal state
Once the re-issue has been issued, download the new certificate through the same certificate id and advance your internal control state.
curl --request GET \
--url 'https://api.regfish.com/tls/certificate/7K9QW3M2ZT8HJ' \
--header 'x-api-key: YOUR_API_KEY'curl --request GET \
--url 'https://api.regfish.com/tls/certificate/7K9QW3M2ZT8HJ/download/pem' \
--header 'x-api-key: YOUR_API_KEY' \
--output 'certificate-7K9QW3M2ZT8HJ.pem'After that, persist at least:
active_certificate_id = 7K9QW3M2ZT8HJ- the new
valid_until reissue.requested_ator your own timestamp of the last follow-up issuance
In a normal re-issue flow, you usually do not need to revoke the old certificate. After the new deployment is complete, the old certificate can simply expire naturally.
Step 7: Start the next contract period as an explicit renewal
When the decision model returns renew-next-term, do not place another follow-up issuance on the same order. Instead, create a new order and explicitly mark it as a renewal of the current certificate.
curl --request POST \
--url 'https://api.regfish.com/tls/certificate' \
--header 'content-type: application/json' \
--header 'x-api-key: YOUR_API_KEY' \
--data '
{
"sku": "RapidSSL",
"common_name": "www.example.com",
"dns_names": ["api.example.com"],
"csr": "-----BEGIN CERTIFICATE REQUEST-----\nMIIC...NEXT...\n-----END CERTIFICATE REQUEST-----",
"dcv_method": "dns-cname-token",
"renewal_of_certificate_id": "7K9QW3M2ZT8HJ",
"validity_days": 199
}
'This request creates a new order with a new certificate id. That is exactly why it is not a re-issue, but the start of the next contract or billing cycle. After that, treat the response like any other new order: apply the returned DCV record, poll the new order, download the certificate through the new certificate id, and persist the mapping renewed_from_certificate_id -> new_certificate_id.
For renewals, remember that validity_days is still only the purchased base order validity. Once the order has been issued, use valid_until as the authoritative lifetime and persist renewal_bonus_days when the provider confirms extra carried-over validity.
Practical notes for production workflows
- make re-issue jobs idempotent, for example per contract and target generation
- generate the next CSR before the re-issue window so key creation never blocks issuance
- keep DNS TTLs short so updated DCV tokens take effect quickly
- keep a small buffer between ordering and the expected deployment time
- use
renewal_of_certificate_idexplicitly when moving into the next contract period instead of creating a completely unrelated new order
Result
With the current regfish API, this lifecycle can now be automated much more cleanly: the initial issuance runs through create-certificate, later follow-up issuances on the same order run through reissue-certificate, and the next contract period starts again through create-certificate with renewal_of_certificate_id. The API now also exposes the provider-side contract window directly, while any additional commercial logic can still live in your own system if needed.