API Request Parameters Reference#
This reference covers the request headers, processing modes, and configuration parameters available across all EnConvert API endpoints — including async_mode, direct_download, callback_url, output_filename, and pdf_options. It explains sync mode (200 OK with the result) versus async mode (202 Accepted with a batch_id), presigned URL responses, and the file size, monthly conversion, and storage limits enforced per plan.
Request Headers#
| Header | Type | Description |
|---|---|---|
X-API-Key |
string |
Your API key (sk_live_... for private, pk_live_... for public). Use this OR the Authorization header. |
Authorization |
string |
Bearer token from /v1/auth/token. Use this OR the X-API-Key header. |
Content-Type |
string |
application/json for URL-based converters, multipart/form-data for file uploads. |
X-Parent-Origin |
string |
Required for public key JWT token exchange. The parent domain embedding the widget. |
Endpoint Types#
Enconvert has two types of conversion endpoints, each with a different request format:
URL-Based Endpoints#
Accept a JSON body (application/json) with a url parameter. Support async mode, batch processing, and browser rendering options.
Endpoints: url-to-pdf, url-to-screenshot, website-to-pdf, website-to-screenshot
File Upload Endpoints#
Accept a file via multipart/form-data. Synchronous only. No batch or async support.
Endpoints: All data format, document to PDF, and image conversion endpoints.
Sync vs Async Mode#
| Sync Mode | Async Mode | |
|---|---|---|
| Trigger | Default for single URL / file upload | Multiple URLs, or async_mode: true |
| Response | 200 OK with result |
202 Accepted with batch_id |
| Result delivery | File bytes or presigned URL in response | Poll, webhook, or email |
| Key types | Private and public keys | Private keys only |
| Plan requirement | All plans | Requires async access (Starter+) |
- Sync mode is the default. The server processes the conversion and returns the result in the response.
- Async mode is triggered automatically when you submit multiple URLs, or explicitly via
async_mode: true. Requires thehas_async_modefeature on your subscription plan. - File upload endpoints are always synchronous. The
async_modeparameter does not apply. - Public keys are restricted to sync mode with a single URL.
async_mode: true or submit multiple URLs on a free plan returns 403 Forbidden.
Direct Download#
Controls whether the API returns raw file bytes or a JSON response with a presigned download URL.
Default Behavior#
| Endpoint Type | Key Type | Default |
|---|---|---|
| File upload endpoints | All keys | true (raw bytes) |
| URL endpoints | Private key | false (JSON with presigned URL) |
| URL endpoints | Public / dashboard key | true (forced, returns JSON with presigned URL) |
direct_download is forced to true, but the response is a JSON object with a presigned_url (not raw bytes). This avoids reverse-proxy timeout issues with large files that can take 60-120 seconds to convert.
Private Key with direct_download=true#
Returns raw file bytes:
curl -X POST https://api.enconvert.com/v1/convert/url-to-pdf \
-H "X-API-Key: sk_live_your_private_key" \
-H "Content-Type: application/json" \
-d '{"url": "https://example.com", "direct_download": true}' \
--output output.pdf
Response Headers#
All conversion responses include these metadata headers:
| Header | Description |
|---|---|
Content-Disposition |
inline; filename="{filename}" |
X-Object-Key |
Storage path of the converted file |
X-File-Size |
Size of the converted file in bytes |
X-Conversion-Time |
Time taken for conversion in seconds |
X-Filename |
Generated filename |
Restrictions#
direct_downloadcannot be used withasync_mode: true(returns400)direct_downloadcannot be used with multiple URLs (returns400)
Output Filename#
Customize the output filename using the output_filename parameter. A UTC timestamp is always appended to ensure uniqueness:
{output_filename}_{YYYYMMDD_HHMMSSmmm}.{ext}
Default naming:
- File uploads: Derived from the input filename (e.g., report.docx becomes report_20260405_123456789.pdf)
- URL conversions: Derived from the domain name (e.g., example_20260405_123456789.pdf)
- Fallback: output_20260405_123456789.{ext}
If you include the target extension in your custom name, it is stripped before the timestamp is appended to avoid duplication.
{
"url": "https://example.com",
"output_filename": "my-report"
}
Produces: my-report_20260405_123456789.pdf
PDF Options#
Endpoints that produce PDF output support an optional pdf_options parameter for controlling page layout, headers, footers, and color mode.
Supported Endpoints#
| Endpoint | pdf_options Support |
|---|---|
| url-to-pdf | Full support (page size, margins, orientation, scale, header/footer, grayscale) |
| website-to-pdf | Full support (applied to each page) |
| html-to-pdf | Full support (translated to CSS @page rules) |
| markdown-to-pdf | Full support (translated to CSS @page rules) |
| doc-to-pdf, excel-to-pdf, and other LibreOffice endpoints | Grayscale only. Page layout comes from the document itself. |
Fields#
| Field | Type | Default | Description |
|---|---|---|---|
page_size |
string |
"A4" |
Named page size. Ignored when both page_width and page_height are set. |
page_width |
float |
null |
Custom page width in millimeters. Must be positive. Both width and height must be set together. |
page_height |
float |
null |
Custom page height in millimeters. Must be positive. |
orientation |
string |
"portrait" |
"portrait" or "landscape". Swaps width and height when set to landscape. |
margins |
object |
{"top": 10, "bottom": 10, "left": 10, "right": 10} |
Page margins in millimeters. All values must be non-negative. |
scale |
float |
1.0 |
Content rendering scale. Range: 0.1 to 2.0. Applied in paginated mode only (url-to-pdf with single_page: false). |
grayscale |
boolean |
false |
Post-process the output to grayscale via Ghostscript. Works on all PDF endpoints. |
header |
object |
null |
Page header. Format: {"content": "<html>", "height": 15}. Content max 2000 characters. Height in mm, must be positive. Default height: 15mm. |
footer |
object |
null |
Page footer. Same format as header. Default height: 15mm. |
Supported page sizes: A0, A1, A2, A3, A4, A5, A6, B0, B1, B2, B3, B4, B5, Letter, Legal, Tabloid, Ledger
Header/footer template variables: {{page}}, {{total_pages}}, {{date}}, {{title}}, {{url}}
Passing pdf_options#
URL-based endpoints -- JSON object in the request body:
{
"url": "https://example.com",
"pdf_options": {
"page_size": "Letter",
"orientation": "landscape",
"margins": {"top": 20, "bottom": 20, "left": 15, "right": 15},
"footer": {
"content": "Page {{page}} of {{total_pages}}",
"height": 10
}
}
}
File upload endpoints -- JSON string in a form field:
curl -X POST https://api.enconvert.com/v1/convert/html-to-pdf \
-H "X-API-Key: sk_live_your_private_key" \
-F "[email protected]" \
-F 'pdf_options={"page_size": "Letter", "grayscale": true}'
Image Options (Image Endpoints Only)#
The SVG rasterization endpoints (svg-to-png, svg-to-jpeg, svg-to-webp) accept optional output dimensions:
| Parameter | Type | Default | Description |
|---|---|---|---|
width |
integer |
SVG's own size | Output width in pixels (1-10000). When height is omitted, the height is derived from the SVG's aspect ratio. |
height |
integer |
SVG's own size | Output height in pixels (1-10000). When width is omitted, the width is derived from the SVG's aspect ratio. |
Passing both dimensions sets the exact canvas size, which may change the aspect ratio. Requests above 25,000,000 total output pixels return 400.
The compress-image endpoint accepts a size budget:
| Parameter | Type | Default | Description |
|---|---|---|---|
target_size_kb |
integer |
-- | Target file size in kilobytes. Omitted: lossless optimization only. Set: the image is additionally downscaled (aspect ratio locked) until it fits. Best effort — unreachable targets return the smallest achievable file. |
Browser & Rendering Options (URL Endpoints Only)#
These parameters control how the browser renders the page before conversion. They apply to url-to-pdf, url-to-screenshot, website-to-pdf, and website-to-screenshot.
| Parameter | Type | Default | Description |
|---|---|---|---|
viewport_width |
integer |
1920 |
Browser viewport width in pixels. |
viewport_height |
integer |
1080 |
Browser viewport height in pixels. |
single_page |
boolean |
true |
Render entire page as one continuous PDF (url-to-pdf only). Set to false for paginated output. |
load_media |
boolean |
true |
Wait for all images and videos to load. Set to false for faster conversion with media placeholders. |
enable_scroll |
boolean |
true |
Scroll the page to trigger lazy-loading content. |
handle_sticky_header |
boolean |
true |
Detect and handle sticky/fixed headers before capture. |
handle_cookies |
boolean |
true |
Auto-dismiss cookie consent banners. |
wait_for_images |
boolean |
true |
Wait for all <img> elements to finish loading (5-second timeout per image). |
wait_for_selector |
string |
null |
CSS selector to wait for before capture. Returns 422 if it never appears within wait_for_selector_timeout. Useful for SPAs that hydrate content after load. |
wait_for_selector_timeout |
integer |
10000 |
Milliseconds to wait for wait_for_selector (maximum 60000). |
block_ads |
boolean |
false |
Abort requests to known ad/tracker domains so they never load, render, or slow the capture. |
block_media |
boolean |
false |
Abort image and audio/video requests entirely for a faster, lighter render. Unlike load_media (which only controls waiting), this prevents media from downloading at all. |
Authentication & Custom Requests (URL Endpoints Only)#
These parameters allow converting pages behind authentication or requiring specific cookies/headers. They require a plan with basic auth access (Starter+).
| Parameter | Type | Default | Description |
|---|---|---|---|
auth |
object |
null |
HTTP Basic Auth credentials: {"username": "...", "password": "..."}. |
cookies |
array |
null |
Array of cookie objects injected before navigation. Max 50 per request. Each requires name, value, and either domain or url. |
headers |
object |
null |
Custom HTTP headers sent with requests. Max 20 per request. Cannot include blocked headers: host, content-length, transfer-encoding, connection, upgrade, te, trailer. |
Authorization header (for example a Bearer token) passed via headers — or credentials from the auth object — is sent only to the target origin, never to third-party subresources the page requests. This prevents credential leakage to ad, analytics, or CDN hosts.
URL Validation (SSRF Protection)#
The url on every URL-based endpoint must be a public http:// or https:// address. Before the browser fetches anything, the URL is screened and rejected with 400 Bad Request when it:
- uses a scheme other than
http/https; - embeds credentials (
https://user:pass@host/— use theauthfield instead); - targets
localhost, a cloud metadata hostname, or an IP that resolves into a private, loopback, link-local, reserved, or otherwise non-public range; - uses a non-standard IP notation (octal, hexadecimal, or packed-integer) that could resolve ambiguously.
This applies to the seed URL, to every URL in a batch, and to the pages discovered by the website-to-* crawl endpoints.
Non-HTML URLs#
When a URL returns non-HTML content, the response depends on the endpoint:
url-to-markdownreturns the raw body inside a fenced code block (with ajsonortextlanguage hint) forapplication/jsonandtext/plainresponses, instead of running article extraction over the browser's viewer.url-to-pdfandurl-to-screenshotreturn415 Unsupported Media Typeforapplication/jsonresponses (a browser JSON viewer makes a poor PDF/image). Useurl-to-markdownto capture JSON. Plain text renders normally.
Presigned URLs#
When direct_download is false (or for public key responses), the API returns a presigned URL for downloading the converted file directly from storage.
- Expiry: Presigned URLs expire after 15 minutes. Download the file promptly after receiving the URL.
- Reusable: URLs can be used multiple times before they expire.
- Fresh on poll: The batch status endpoint generates fresh presigned URLs on each request.
File Size Limits#
Maximum upload file size depends on your subscription plan:
| Plan | Max File Size |
|---|---|
| Free | 5 MB |
| Paid plans | Plan-dependent |
If a file exceeds your plan's limit, the API returns 413 Payload Too Large:
{
"error": "File too large",
"file_size": 10485760,
"max_size": 5242880,
"tier": "free",
"key_type": "private"
}
File size is validated via the Content-Length request header before the file body is read.
Monthly Conversion Limits#
Each plan has a monthly cap on total conversions:
| Plan | Monthly Limit |
|---|---|
| Free | 100 conversions |
| Paid plans | Plan-dependent |
When the limit is exceeded, the API returns 402 Payment Required:
{
"detail": "Monthly conversion limit reached (100/100). Upgrade your plan to continue."
}
For batch requests, the entire batch count is pre-checked against the remaining quota before any processing begins. If 10 URLs are submitted but only 3 conversions remain, the entire batch is rejected upfront.
Storage Limits#
Projects on plans with storage allocations are subject to storage usage limits. When the project's accumulated file storage reaches the plan's limit, conversions are blocked:
{
"detail": "Storage limit reached. Delete files or upgrade your storage plan to continue."
}
Feature Gating Summary#
Certain features are restricted to specific subscription tiers:
| Feature | Parameter | Free | Starter | Pro | Enterprise |
|---|---|---|---|---|---|
| Async mode | async_mode |
No | Yes | Yes | Yes |
| Batch processing | url (array) |
No | Yes | Yes | Yes |
| ZIP output | output_format |
No | No | Yes | Yes |
| Webhook callbacks | callback_url |
No | No | Yes | Yes |
| HTTP Basic Auth | auth |
No | Yes | Yes | Yes |
| Cookie injection | cookies |
No | Yes | Yes | Yes |
| Custom headers | headers |
No | Yes | Yes | Yes |
When a gated feature is used on an unsupported plan, the API returns 403 Forbidden with a message indicating which feature requires a plan upgrade.
Frequently asked questions#
What is the difference between sync and async mode in the EnConvert API?#
Sync mode is the default: the server processes the conversion and returns 200 OK with the result. Async mode returns 202 Accepted with a batch_id and is triggered automatically by multiple URLs or explicitly via async_mode: true. Async requires a private key and the has_async_mode plan feature (Starter and above).
What does the direct_download parameter do?#
It controls whether the API returns raw file bytes (true) or a JSON response with a presigned download URL (false). It cannot be combined with async_mode: true or multiple URLs — both return 400. For public and dashboard keys it is forced to true, but the response is still JSON with a presigned_url.
How long do presigned download URLs stay valid?#
Presigned URLs expire after 15 minutes and can be used multiple times before expiry. The batch status endpoint generates fresh presigned URLs on each request, so re-polling always returns working links.
How do I set a custom output filename for a conversion?#
Pass the output_filename parameter. A UTC timestamp is always appended for uniqueness, producing {output_filename}_{YYYYMMDD_HHMMSSmmm}.{ext}, and a target extension included in your custom name is stripped to avoid duplication.
Why does the API return 403 Forbidden when I set async_mode to true?#
Async mode is not available on the free plan. Setting async_mode: true or submitting multiple URLs on a plan without async access returns 403 Forbidden with a message indicating which feature requires a plan upgrade.