- DigiCert developer portal
- Get started
- Error handling & rate limits
Error handling & rate limits
DigiCert® ONE APIs return JSON errors and enforces per-API key rate limits. Understanding returned errors and rate limits helps you:
Parse error payloads and map them to actionable logic.
Respect rate limits to avoid throttling.
Implement production-grade retry and logging strategies.
Error response structure and example
Error response structure
{
"error": {
"code": "<error_code>",
"message": "<error_message>"
}
}
code: Returned error code.message: Description of the error that occurred and potential solutions.
Error response example
{
"errors": [
{
"code": "duplicate_error",
"message": "Nickname api_service_user_3 already exists. Enter a different nickname."
}
]
}API troubleshooting basics
Symptom | Likely cause | Quick fix |
|---|---|---|
401 Unauthorized | Missing/invalid | Verify the |
403 Forbidden | Authenticated but lacks required role | Add the needed role in Account Manager or use a different key. |
429 Too Many Requests | Burst traffic | Implement backoff; spread calls across service users. |
503 Service Unavailable | Maintenance window | Retry after header; escalate if >10 min. |
SSL handshake failure when using mTLS | Wrong certificate, key mismatch, or incorrect URL | Check cert/key pair and ensure URL prefix is correct. |
Everything stopped at midnight | Key or service user reached end date | Create/rotate the key before expiry; update all integrations. |
Works in demo, fails in prod | Using demo key against prod hostname | Generate a new key in production; update |
HTTP status and machine codes
HTTP | Machine code | Meaning | Retry? |
|---|---|---|---|
200 OK | — | Success | — |
201 Created | — | Resource created | — |
204 No Content | — | Success, no body | — |
400 Bad Request |
| Payload failed validation | No |
401 Unauthorized |
| Bad or missing API key | No |
403 Forbidden |
| Authenticated but not authorised | No |
404 Not Found |
| Resource ID or path is wrong | No |
409 Conflict |
| Resource already exists or version clash | No |
429 Too Many Requests |
| Rate limit hit | After |
500 Internal Server Error |
| Unexpected server fault | With backoff |
503 Service Unavailable |
| Maintenance or downstream outage | After |
Tip
Always check for the Retry-After header on 429 and 503 responses. The value is either seconds or an HTTP date.
Sample retry logic
import time
import requests
from typing import Dict, Any
def api_request(url: str, headers: Dict[str, str], max_retries: int = 3) -> Any:
"""Simple retry with exponential backoff for API requests."""
for i in range(max_retries):
try:
response = requests.get(url, headers=headers)
response.raise_for_status()
return response.json()
except requests.exceptions.RequestException as error:
# Check if error is retryable
status_code = getattr(error.response, 'status_code', 0)
is_retryable = status_code in [429, 500, 503]
is_last_attempt = i == max_retries - 1
if not is_retryable or is_last_attempt:
raise
# Wait before retrying: 1s, 2s, 4s...
delay = 2 ** i
time.sleep(delay)
# Example: Get certificates from DigiCert
certificates = api_request(
'https://api.digicert.com/v1/certificates',
headers={'X-API-Key': os.environ['DIGICERT_API_KEY']}
)import java.io.IOException;
import java.net.http.*;
import java.time.Duration;
public class ApiClient {
private static final HttpClient client = HttpClient.newHttpClient();
public static String apiRequest(String url, String apiKey, int maxRetries)
throws IOException, InterruptedException {
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("X-API-Key", apiKey)
.header("Content-Type", "application/json")
.GET()
.build();
for (int i = 0; i < maxRetries; i++) {
try {
HttpResponse<String> response = client.send(request,
HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 200 && response.statusCode() < 300) {
return response.body();
}
// Check if error is retryable
int status = response.statusCode();
boolean isRetryable = status == 429 || status == 500 || status == 503;
boolean isLastAttempt = i == maxRetries - 1;
if (!isRetryable || isLastAttempt) {
throw new IOException("API request failed: " + status);
}
} catch (IOException | InterruptedException e) {
if (i == maxRetries - 1) throw e;
}
// Wait before retrying: 1s, 2s, 4s...
Thread.sleep((long) Math.pow(2, i) * 1000);
}
throw new IOException("Max retries exceeded");
}
// Example: Get certificates from DigiCert
public static void main(String[] args) throws Exception {
String response = apiRequest(
"https://api.digicert.com/v1/certificates",
System.getenv("DIGICERT_API_KEY"),
3
);
System.out.println(response);
}
}package main
import (
"fmt"
"io"
"net/http"
"os"
"time"
)
// apiRequest makes an HTTP GET request with exponential backoff retry
func apiRequest(url string, headers map[string]string, maxRetries int) ([]byte, error) {
client := &http.Client{Timeout: 30 * time.Second}
for i := 0; i < maxRetries; i++ {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
// Add headers
for key, value := range headers {
req.Header.Set(key, value)
}
resp, err := client.Do(req)
if err != nil {
if i == maxRetries-1 {
return nil, err
}
time.Sleep(time.Duration(1<<i) * time.Second)
continue
}
defer resp.Body.Close()
// Check if error is retryable
isRetryable := resp.StatusCode == 429 ||
resp.StatusCode == 500 ||
resp.StatusCode == 503
isLastAttempt := i == maxRetries-1
if resp.StatusCode >= 200 && resp.StatusCode < 300 {
return io.ReadAll(resp.Body)
}
if !isRetryable || isLastAttempt {
return nil, fmt.Errorf("API request failed: %d", resp.StatusCode)
}
// Wait before retrying: 1s, 2s, 4s...
time.Sleep(time.Duration(1<<i) * time.Second)
}
return nil, fmt.Errorf("max retries exceeded")
}
// Example: Get certificates from DigiCert
func main() {
headers := map[string]string{
"X-API-Key": os.Getenv("DIGICERT_API_KEY"),
"Content-Type": "application/json",
}
data, err := apiRequest(
"https://api.digicert.com/v1/certificates",
headers,
3,
)
if err != nil {
panic(err)
}
fmt.Println(string(data))
}using System;
using System.Net.Http;
using System.Threading.Tasks;
public class ApiClient
{
private static readonly HttpClient client = new HttpClient();
private static readonly int[] retryableStatusCodes = { 429, 500, 503 };
public static async Task<string> ApiRequest(string url, string apiKey, int maxRetries = 3)
{
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("X-API-Key", apiKey);
for (int i = 0; i < maxRetries; i++)
{
try
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
return await response.Content.ReadAsStringAsync();
}
// Check if error is retryable
var statusCode = (int)response.StatusCode;
var isRetryable = Array.Exists(retryableStatusCodes,
code => code == statusCode);
var isLastAttempt = i == maxRetries - 1;
if (!isRetryable || isLastAttempt)
{
response.EnsureSuccessStatusCode();
}
}
catch (HttpRequestException ex)
{
if (i == maxRetries - 1) throw;
}
// Wait before retrying: 1s, 2s, 4s...
await Task.Delay((int)Math.Pow(2, i) * 1000);
}
throw new Exception("Max retries exceeded");
}
// Example: Get certificates from DigiCert
static async Task Main()
{
var apiKey = Environment.GetEnvironmentVariable("DIGICERT_API_KEY");
var result = await ApiRequest(
"https://api.digicert.com/v1/certificates",
apiKey
);
Console.WriteLine(result);
}
}function Invoke-ApiRequest {
param(
[string]$Url,
[hashtable]$Headers,
[int]$MaxRetries = 3
)
$retryableStatusCodes = @(429, 500, 503)
for ($i = 0; $i -lt $MaxRetries; $i++) {
try {
$response = Invoke-RestMethod -Uri $Url -Headers $Headers -Method Get
return $response
}
catch {
$statusCode = $_.Exception.Response.StatusCode.value__
$isRetryable = $statusCode -in $retryableStatusCodes
$isLastAttempt = $i -eq ($MaxRetries - 1)
if (-not $isRetryable -or $isLastAttempt) {
throw $_
}
# Wait before retrying: 1s, 2s, 4s...
$delay = [math]::Pow(2, $i)
Write-Host "Retrying in $delay seconds..."
Start-Sleep -Seconds $delay
}
}
}
# Example: Get certificates from DigiCert
$headers = @{
'X-API-Key' = $env:DIGICERT_API_KEY
'Content-Type' = 'application/json'
}
$certificates = Invoke-ApiRequest `
-Url 'https://api.digicert.com/v1/certificates' `
-Headers $headers `
-MaxRetries 3
$certificates | ConvertTo-Json