Documentation Index
Fetch the complete documentation index at: https://docs.convertly.sh/llms.txt
Use this file to discover all available pages before exploring further.
The Media Tools API turns common product media tasks into simple authenticated requests. Every tool accepts either a multipart file upload or a remote sourceUrl. Add async=true when the job may be heavy, such as background removal, video watermarking, PDF previews, audio extraction, or large thumbnails.
curl -X POST "https://convertly.sh/api/media/thumbnail" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./video.mp4" \
-F "width=640" \
-F "height=360" \
-F "format=jpg"
curl -X POST "https://convertly.sh/api/media/thumbnail" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/uploads/video.mp4" \
-F "width=640" \
-F "height=360" \
-F "format=jpg"
curl -X POST "https://convertly.sh/api/media/poster-frame" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/uploads/video.mp4" \
-F "timestamp=4" \
-F "async=true"
Async media tools return a jobId. Poll GET /api/jobs/{id} or listen for media.tool.completed webhooks.
{
"jobId": "65f3a673-69d6-42cc-8f6b-fc5a21fb5a8e",
"status": "pending",
"tool": "poster-frame"
}
Endpoints
| Tool | Endpoint | Best for |
|---|
| Thumbnail generation | POST /api/media/thumbnail | Image thumbnails and video preview thumbnails. |
| PDF previews | POST /api/media/pdf-preview | Rendering a PDF page as jpg, png, webp, or avif. |
| Image to PDF | POST /api/media/image-to-pdf | Combining one or more images into a PDF. |
| Metadata stripping | POST /api/media/strip-metadata | Removing EXIF, GPS, tags, and container metadata. |
| Poster frames | POST /api/media/poster-frame | Extracting a video frame for upload previews. |
| Audio extraction | POST /api/media/extract-audio | Pulling audio from video as mp3, m4a, wav, ogg, or flac. |
| Watermarking | POST /api/media/watermark | Applying text watermarks to images and videos. |
| Media inspection | POST /api/media/inspect | Reading dimensions, duration, codecs, file size, streams, and metadata flags. |
| Trim | POST /api/media/trim | Cutting video or audio by start time and duration. |
| Video to GIF | POST /api/media/gif | Creating short animated previews from video. |
| Storyboard | POST /api/media/storyboard | Generating contact sheets from video frames. |
| Image transform | POST /api/media/transform | Resizing, cropping, rotating, flipping, and exporting images. |
| Background removal | POST /api/media/remove-background | Removing image backgrounds while preserving existing transparent cutouts. |
Examples
Thumbnail
curl -X POST "https://convertly.sh/api/media/thumbnail" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./video.mp4" \
-F "width=640" \
-F "height=360" \
-F "format=jpg" \
-F "timestamp=2"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/video.mp4");
body.append("width", "640");
body.append("height", "360");
body.append("format", "jpg");
const res = await fetch("https://convertly.sh/api/media/thumbnail", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
console.log(await res.json());
PDF preview
curl -X POST "https://convertly.sh/api/media/pdf-preview" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./contract.pdf" \
-F "page=1" \
-F "format=webp" \
-F "width=1600"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/contract.pdf");
body.append("page", "1");
body.append("format", "webp");
body.append("async", "true");
const res = await fetch("https://convertly.sh/api/media/pdf-preview", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
Image to PDF
curl -X POST "https://convertly.sh/api/media/image-to-pdf" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "files=@./page-1.jpg" \
-F "files=@./page-2.jpg" \
-F "pageSize=a4"
const body = new FormData();
body.append("files", fileInput.files[0]);
body.append("files", fileInput.files[1]);
body.append("pageSize", "a4");
await fetch("https://convertly.sh/api/media/image-to-pdf", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
curl -X POST "https://convertly.sh/api/media/strip-metadata" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./photo.jpg"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/photo.jpg");
await fetch("https://convertly.sh/api/media/strip-metadata", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
Remove background
curl -X POST "https://convertly.sh/api/media/remove-background" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./product.jpg" \
-F "format=png" \
-F "model=medium" \
-F "async=true"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/product.jpg");
body.append("format", "png");
body.append("model", "medium");
await fetch("https://convertly.sh/api/media/remove-background", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
When the input already has meaningful transparency, Convertly returns a cleaned transparent output without re-segmenting it. Add force=true only when you intentionally want to segment an already-transparent image again.
Poster frame
curl -X POST "https://convertly.sh/api/media/poster-frame" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./clip.mp4" \
-F "timestamp=3.5" \
-F "width=1280" \
-F "format=jpg"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/clip.mp4");
body.append("timestamp", "3.5");
body.append("width", "1280");
body.append("async", "true");
await fetch("https://convertly.sh/api/media/poster-frame", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
curl -X POST "https://convertly.sh/api/media/extract-audio" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./clip.mp4" \
-F "format=mp3" \
-F "bitrateKbps=192" \
-F "async=true"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/clip.mp4");
body.append("format", "mp3");
body.append("bitrateKbps", "192");
body.append("async", "true");
await fetch("https://convertly.sh/api/media/extract-audio", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
Watermark
curl -X POST "https://convertly.sh/api/media/watermark" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./clip.mp4" \
-F "text=Acme Studio" \
-F "position=bottom-right" \
-F "opacity=0.72" \
-F "async=true"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/clip.mp4");
body.append("text", "Acme Studio");
body.append("position", "bottom-right");
body.append("async", "true");
await fetch("https://convertly.sh/api/media/watermark", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
Inspect
curl -X POST "https://convertly.sh/api/media/inspect" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "file=@./upload.mov"
const body = new FormData();
body.append("sourceUrl", "https://cdn.example.com/upload.mov");
const res = await fetch("https://convertly.sh/api/media/inspect", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.CONVERTLY_API_KEY}` },
body,
});
Trim
curl -X POST "https://convertly.sh/api/media/trim" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/video.mp4" \
-F "start=12" \
-F "duration=8" \
-F "format=mp4" \
-F "async=true"
Video to GIF
curl -X POST "https://convertly.sh/api/media/gif" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/video.mp4" \
-F "start=2" \
-F "duration=4" \
-F "width=480" \
-F "async=true"
Storyboard
curl -X POST "https://convertly.sh/api/media/storyboard" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/video.mp4" \
-F "frames=12" \
-F "columns=4" \
-F "format=jpg" \
-F "async=true"
curl -X POST "https://convertly.sh/api/media/transform" \
-H "Authorization: Bearer $CONVERTLY_API_KEY" \
-F "sourceUrl=https://cdn.example.com/photo.jpg" \
-F "width=1200" \
-F "height=900" \
-F "fit=cover" \
-F "format=webp"
Response shapes
Most media tool endpoints return a files array:
{
"files": [
{
"filename": "clip-thumbnail.jpg",
"mimeType": "image/jpeg",
"originalSize": 24819034,
"finalSize": 82419,
"downloadUrl": "data:image/jpeg;base64,..."
}
]
}
Async job results are available through GET /api/jobs/{id}:
{
"jobId": "65f3a673-69d6-42cc-8f6b-fc5a21fb5a8e",
"jobType": "media_tool",
"status": "completed",
"results": {
"files": [
{
"filename": "clip-poster.jpg",
"mimeType": "image/jpeg",
"downloadUrl": "https://..."
}
]
}
}
Media inspection returns:
{
"media": {
"filename": "clip.mp4",
"mimeType": "video/mp4",
"sizeBytes": 24819034,
"kind": "video",
"width": 1920,
"height": 1080,
"duration": 18.4,
"streams": []
}
}