- 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