Errors
Error codes, handling strategies, and debugging tips.
Error Response Format
{
"error": "Unauthorized",
"message": "Invalid API key"
}
| Field | Type | Description |
|---|---|---|
error |
string | Short error code or type |
message |
string | Human-readable description |
HTTP Status Codes
Bad Request
Invalid request parameters or malformed JSON.
Unauthorized
Authentication failed or missing.
Forbidden
Feature requires a higher plan.
Too Many Requests
Rate limit or quota exceeded.
Retry-After: <seconds>
Internal Server Error
Unexpected error during PDF generation.
Service Unavailable
Service temporarily unavailable.
Common Errors
Provide content
Missing 'content' property for /pdf endpoint.
HTML content too large (max 1MB)
Reduce HTML size. Use external stylesheets or optimize embedded images.
Invalid JSON
Use a proper JSON encoder (JSON.stringify, json_encode) instead of manual building.
Internal/private URLs not allowed
Only public URLs are allowed (SSRF protection).
Missing X-API-Key header
Add the X-API-Key header with your API key to all requests.
Monthly quota exceeded
Upgrade your plan or wait for quota reset at next billing cycle.
Password protection requires Business plan or higher
Upgrade to Business+ plan to use PDF password protection.
No dedicated workers available
Password protection requires dedicated workers. Retry after 30 seconds.
Upload failed: 403 Forbidden
Async job upload failed. Your presigned URL may be expired or invalid.
Error Handling Best Practices
Check response status
Verify HTTP status is 2xx before processing.
Implement retry logic
Exponential backoff for 429 and 503 errors.
Log errors
Log status code and message for debugging.
Set timeouts
Recommended: 30 second client timeout.
Retry Implementation
async function generatePdfWithRetry(content, maxRetries = 3) {
let lastError;
for (let attempt = 1; attempt <= maxRetries; attempt++) {
try {
const response = await fetch('https://api.tailpdf.com/pdf', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-API-Key': process.env.TAILPDF_API_KEY,
},
body: JSON.stringify({ content }),
});
if (response.ok) {
return await response.arrayBuffer();
}
const error = await response.json();
// Don't retry client errors (4xx except 429)
if (response.status >= 400 && response.status < 500 && response.status !== 429) {
throw new Error(`PDF generation failed: ${error.message}`);
}
lastError = new Error(error.message);
// Exponential backoff
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
} catch (err) {
lastError = err;
if (attempt === maxRetries) break;
const delay = Math.pow(2, attempt) * 1000;
await new Promise(resolve => setTimeout(resolve, delay));
}
}
throw lastError;
}