Endpoint: Convert
Method + path
POST /convert
Auth
- Recommended:
X-Fast-Api-Key
Content type
Two input methods are supported:
File upload (multipart/form-data)
Upload a file directly. This is the standard method for most integrations.
URL input (application/json)
Submit a URL pointing to the file instead of uploading it. The server fetches the file and processes it identically to a file upload. Ideal for presigned cloud storage URLs (S3, GCS, Azure Blob) and automation workflows (n8n, Zapier, Make).
URL input is also available as a form field — include inputUrl in a multipart/form-data request instead of a file field.
Form fields (multipart/form-data)
| Field | Required | Description |
|---|---|---|
file | yes* | Single uploaded file |
inputUrl | yes* | HTTPS URL to fetch the file from (alternative to file) |
targetFormat | yes | Desired output format (jpg, png, pdf, etc.) |
sourceFormat | yes* | Source format of the file at the URL (e.g., heic, pdf). Required when using inputUrl |
options | no | JSON string for converter options |
webhookUrl | no | HTTPS URL to receive a webhook POST on job completion |
webhookSecret | no | Shared secret for HMAC-SHA256 signature verification (16–256 characters). Required with webhookUrl |
webhookEvents | no | Comma-separated event filter: succeeded, failed, or both (default: both) |
outputUrl | — | Reserved for future use. Returns 400 if provided |
* Provide exactly one of file or inputUrl — they are mutually exclusive. Sending both returns url_fetch.mutually_exclusive.
Notes:
- Exactly one file per request.
targetFormatcan also be provided via query string as fallback:POST /convert?targetFormat=jpg- Some converters use compound targetFormat values that differ from simple format names — e.g.
bank-statement-excel(notexcel),pdf-ocr(notpdf). UseGET /convert/conversionsto discover the exacttargetFormatvalues.
JSON body fields (application/json)
When using JSON body input, all fields are sent as a JSON object instead of form fields.
| Field | Required | Description |
|---|---|---|
inputUrl | yes | HTTPS URL to fetch the file from |
targetFormat | yes | Desired output format (jpg, png, pdf, etc.) |
sourceFormat | yes* | Source format of the file at the URL (e.g., heic, pdf). Required when using inputUrl |
options | no | Converter options object (not a JSON string — pass the object directly) |
webhookUrl | no | HTTPS URL to receive a webhook POST on job completion |
webhookSecret | no (required with webhookUrl) | Shared secret for HMAC-SHA256 signature verification (16–256 characters) |
webhookEvents | no | Comma-separated event filter: succeeded, failed, or both |
outputUrl | — | Reserved for future use. Returns 400 if provided |
Response
202 Accepted with JobAcceptedResponse
Example response (trimmed)
{
"id": "019c56454f8b755996c45a4874a1f3f6",
"status": "Queued",
"creditCost": 1
}
Examples
File upload
# export API_KEY="your-api-key-here"
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-F "file=@photo.heic" \
-F "targetFormat=jpg"
# with options JSON
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-F "file=@photo.jpg" \
-F "targetFormat=webp" \
-F 'options={"resize":{"enabled":true,"preset":"1080p"}}'# $env:API_KEY = "your-api-key-here"
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-Form @{ file = Get-Item "photo.heic"; targetFormat = "jpg" }
# with options JSON
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-Form @{
file = Get-Item "photo.jpg"
targetFormat = "webp"
options = '{"resize":{"enabled":true,"preset":"1080p"}}'
}Convert from URL (JSON body)
# Convert a file from a presigned S3 URL
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputUrl": "https://my-bucket.s3.amazonaws.com/photo.heic?X-Amz-Expires=3600&...",
"sourceFormat": "heic",
"targetFormat": "jpg"
}'
# URL without a file extension — sourceFormat tells the server what to expect
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputUrl": "https://cdn.example.com/assets/abc123",
"sourceFormat": "heic",
"targetFormat": "png"
}'
# with converter options
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-H "Content-Type: application/json" \
-d '{
"inputUrl": "https://cdn.example.com/photo.jpg",
"targetFormat": "webp",
"options": {"resize": {"enabled": true, "preset": "1080p"}}
}'# Convert a file from a presigned S3 URL
$body = @{
inputUrl = "https://my-bucket.s3.amazonaws.com/photo.heic?X-Amz-Expires=3600&..."
sourceFormat = "heic"
targetFormat = "jpg"
} | ConvertTo-Json
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-ContentType "application/json" -Body $body
# URL without a file extension
$body = @{
inputUrl = "https://cdn.example.com/assets/abc123"
sourceFormat = "heic"
targetFormat = "png"
} | ConvertTo-Json
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-ContentType "application/json" -Body $bodyConvert from URL (multipart form)
You can also pass inputUrl as a form field instead of uploading a file:
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-F "inputUrl=https://cdn.example.com/photo.heic" \
-F "sourceFormat=heic" \
-F "targetFormat=jpg"Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-Form @{
inputUrl = "https://cdn.example.com/photo.heic"
sourceFormat = "heic"
targetFormat = "jpg"
}Audio transcription with options
Transcription converters accept a transcription options object to control mode and output formats. See Options Reference for all settings.
# Transcribe audio to text (quality mode with SRT subtitles)
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-F "file=@meeting.mp3" \
-F "targetFormat=txt" \
-F 'options={"transcription":{"mode":"quality","includeSrt":true}}'# Transcribe audio to text (quality mode with SRT subtitles)
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-Form @{
file = Get-Item "meeting.mp3"
targetFormat = "txt"
options = '{"transcription":{"mode":"quality","includeSrt":true}}'
}With webhook notification
# Convert with webhook — no polling needed
curl -sS -X POST "https://api.tools.fast/convert" \
-H "X-Fast-Api-Key: $API_KEY" \
-F "file=@photo.heic" \
-F "targetFormat=jpg" \
-F "webhookUrl=https://example.com/webhooks/fast" \
-F "webhookSecret=whsec_your_secret_here"# Convert with webhook — no polling needed
Invoke-RestMethod -Method Post "https://api.tools.fast/convert" `
-Headers @{ "X-Fast-Api-Key" = $env:API_KEY } `
-Form @{
file = Get-Item "photo.heic"
targetFormat = "jpg"
webhookUrl = "https://example.com/webhooks/fast"
webhookSecret = "whsec_your_secret_here"
}See Webhooks for payload schema, signature verification, and retry policy.
URL input notes
sourceFormatrequired: URL input requiressourceFormatso the server can validate the conversion pair and enforce per-converter size limits before downloading. Omitting it returnsurl_fetch.missing_source_format.- Pre-download validation: The
sourceFormat→targetFormatpair is validated before fetching. Invalid pairs returnconvert.unsupported_format_pairinstantly (no download occurs). - Per-converter size limits: The download cap uses the converter's configured file size limit for your tier, not a generic cap.
- SSRF protection: Private IPs (127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), bare IPs, and cloud metadata endpoints (169.254.169.254) are blocked.
- HTTPS required: URLs must use HTTPS.
- Redirects: Up to 3 redirects are followed. Each hop is re-validated against SSRF rules.
isRetryable: URL fetch errors include anisRetryableboolean indicating whether the request can be retried (e.g.truefor DNS failures and timeouts,falsefor invalid URLs and private IPs).outputUrlreserved: TheoutputUrlfield is reserved for future server-side upload support and currently returns400if provided.
Errors
See Errors for the full error reference with JSON examples.
| Status | Codes | Cause |
|---|---|---|
400 | request.invalid_content_type, request.no_files, request.empty_file, request.multiple_files, request.invalid_extension, convert.missing_target_format, convert.unsupported_format_pair, convert.unsupported_source_format, convert.invalid_options | Bad request payload |
400 | url_fetch.missing_source_format, url_fetch.invalid_url, url_fetch.invalid_scheme, url_fetch.private_ip, url_fetch.too_large, url_fetch.timeout, url_fetch.http_error, url_fetch.url_expired, url_fetch.redirect_loop, url_fetch.redirect_denied, url_fetch.invalid_content, url_fetch.mutually_exclusive, url_fetch.output_url_reserved, url_fetch.dns_failure, url_fetch.no_filename, url_fetch.domain_circuit_open, url_fetch.disabled | URL fetch error |
401 | api_key.invalid_or_ip_not_allowed | Invalid API key or IP not allowlisted |
402 | entitlements.insufficient_credits | Not enough credits |
403 | url_fetch.guest_not_allowed | URL input requires a signed-in account |
413 | request.file_too_large | File exceeds size limit |
429 | rate_limited, queue.limit_exceeded, url_fetch.rate_limited | Throttled |
Example — unsupported format pair:
{
"error": "convert.unsupported_format_pair",
"detail": "Conversion from 'jpg' to 'mp3' is not supported.",
"sourceFormat": "jpg",
"targetFormat": "mp3",
"supportedTargets": ["avif", "ico", "pdf", "png", "webp"]
}
Example — SSRF blocked (private IP):
{
"error": "url_fetch.private_ip",
"detail": "URL resolves to a private or reserved IP address.",
"isRetryable": false
}