Base URL: http://localhost:5000/api
All responses are JSON unless noted. Errors follow the format:
{ "success": false, "error": "Human readable error message" }Check server status.
Response:
{
"status": "ok",
"service": "Multitool API",
"version": "1.0.0",
"timestamp": "2026-04-11T09:00:00.000Z"
}Merge multiple PDF files into one.
Request: multipart/form-data
| Field | Type | Required | Description |
|---|---|---|---|
pdfs |
File[] | Yes | 2–20 PDF files |
Response: application/pdf binary stream
Errors:
400— Fewer than 2 files uploaded400— Non-PDF file detected
Add a diagonal text watermark to every page of a PDF.
Request: multipart/form-data
| Field | Type | Default | Description |
|---|---|---|---|
pdf |
File | — | PDF file |
text |
string | MULTITOOL |
Watermark text |
fontSize |
number | 60 |
Font size in pt |
opacity |
number | 0.15 |
Opacity (0–1) |
rotation |
number | -45 |
Rotation in degrees |
Response: application/pdf binary stream
Add a text annotation to a specific page.
Request: multipart/form-data
| Field | Type | Default | Description |
|---|---|---|---|
pdf |
File | — | PDF file |
text |
string | — | Annotation text (required) |
pageIndex |
number | 0 |
0-based page index |
x |
number | 50 |
X position in pt |
y |
number | 50 |
Y position in pt |
size |
number | 12 |
Font size |
Response: application/pdf binary stream
Fetch metadata for a media URL.
Request: application/json
{ "url": "https://www.youtube.com/watch?v=dQw4w9WgXcQ" }Response (success):
{
"success": true,
"platform": "youtube",
"title": "Never Gonna Give You Up",
"thumbnail": "https://...",
"duration": 213,
"uploader": "Rick Astley",
"formats": [
{
"formatId": "137",
"ext": "mp4",
"quality": "1080p",
"filesize": 145000000,
"hasVideo": true,
"hasAudio": false
}
]
}Response (requires config):
{
"success": false,
"requiresConfig": true,
"platform": "instagram",
"message": "Instagram downloads require a RapidAPI key..."
}Stream a media file to the client.
Query Parameters:
| Param | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | Source URL |
formatId |
string | No | yt-dlp format ID |
Response: video/mp4 stream with Content-Disposition: attachment
Get the last 50 download history entries.
Response:
{
"success": true,
"history": [
{
"_id": "...",
"url": "https://...",
"platform": "youtube",
"title": "...",
"status": "completed",
"createdAt": "2026-04-11T09:00:00.000Z"
}
]
}Clear all download history.
Response:
{ "success": true, "message": "History cleared." }Scrape a URL and rephrase the content with AI.
Request: application/json
{
"url": "https://example.com/blog-post",
"keywords": ["react", "javascript", "web dev"],
"saveDraft": false
}| Field | Type | Required | Description |
|---|---|---|---|
url |
string | Yes | URL to scrape |
keywords |
string[] | No | Target SEO keywords |
saveDraft |
boolean | No | Save result to MongoDB |
Response:
{
"success": true,
"title": "Original Article Title",
"rephrasedContent": "# Optimized Blog Post\n\n...",
"wordCount": 650,
"estimatedReadTime": 4,
"draftId": "abc123"
}Errors:
400— URL is required422— Could not extract enough content500— AI API error or scraper failure
List saved blog drafts (without full content).
Response:
{
"success": true,
"drafts": [
{
"_id": "...",
"sourceUrl": "https://...",
"originalTitle": "...",
"keywords": ["react"],
"wordCount": 650,
"status": "draft",
"createdAt": "..."
}
]
}Get a single draft with full content.
Response:
{
"success": true,
"draft": {
"_id": "...",
"sourceUrl": "...",
"originalTitle": "...",
"keywords": ["react"],
"rephrasedContent": "# ...",
"wordCount": 650,
"estimatedReadTime": 4
}
}Delete a blog draft.
Response:
{ "success": true, "message": "Draft deleted." }