Overview
All endpoints live under https://mytoolspace.in/api/v1, accept and return JSON (uploads use multipart/form-data) and require an API key.
- Upload each input file and keep the returned
path. - Create a job with a tool slug and the uploaded paths.
- Poll the job, or wait for a webhook, then download from
resultUrl.
Authentication
Create a key in Dashboard → Developer API (up to 5 active keys per account) and send it as a bearer token on every request. Keys can be rotated or revoked at any time.
Authorization: Bearer YOUR_API_KEYKeep keys on your server. A request without a valid key returns 401; a Free-plan key returns 403.
Rate limits
Daily request limits and upload sizes come from your plan and reset at midnight UTC. Uploads are also limited to 20 per minute.
| Plan | API calls / day | Max upload |
|---|---|---|
| Free | Not included | 25 MB |
| Pro | 1,000 | 500 MB |
| Enterprise | 50,000 | 2 GB |
Quickstart
Compress a PDF end to end. Replace the placeholders with values from the previous step’s response.
# 1. Upload a file
curl -X POST https://mytoolspace.in/api/v1/upload \
-H "Authorization: Bearer $MYTOOLSPACE_API_KEY" \
-F "file=@report.pdf"
# 2. Start a job with the returned path
curl -X POST https://mytoolspace.in/api/v1/jobs \
-H "Authorization: Bearer $MYTOOLSPACE_API_KEY" \
-H "Content-Type: application/json" \
-d '{"tool":"compress-pdf","files":["api-uploads/USER_ID/UUID/report.pdf"]}'
# 3. Poll until status is "completed", then download resultUrl
curl https://mytoolspace.in/api/v1/jobs/JOB_ID \
-H "Authorization: Bearer $MYTOOLSPACE_API_KEY"const API = 'https://mytoolspace.in/api/v1'
const headers = { Authorization: `Bearer ${process.env.MYTOOLSPACE_API_KEY}` }
// 1. Upload
const form = new FormData()
form.append('file', new Blob([await fs.promises.readFile('report.pdf')]), 'report.pdf')
const { path } = await fetch(`${API}/upload`, { method: 'POST', headers, body: form }).then((r) => r.json())
// 2. Create the job
const { job } = await fetch(`${API}/jobs`, {
method: 'POST',
headers: { ...headers, 'Content-Type': 'application/json' },
body: JSON.stringify({ tool: 'compress-pdf', files: [path] }),
}).then((r) => r.json())
// 3. Poll for the result
let result
do {
await new Promise((r) => setTimeout(r, 2000))
result = await fetch(`${API}/jobs/${job.id}`, { headers }).then((r) => r.json())
} while (result.status === 'pending' || result.status === 'processing')
console.log(result.status, result.resultUrl)import os, time, requests
API = "https://mytoolspace.in/api/v1"
headers = {"Authorization": f"Bearer {os.environ['MYTOOLSPACE_API_KEY']}"}
# 1. Upload
with open("report.pdf", "rb") as f:
path = requests.post(f"{API}/upload", headers=headers, files={"file": f}).json()["path"]
# 2. Create the job
job = requests.post(f"{API}/jobs", headers=headers,
json={"tool": "compress-pdf", "files": [path]}).json()["job"]
# 3. Poll for the result
while True:
result = requests.get(f"{API}/jobs/{job['id']}", headers=headers).json()
if result["status"] not in ("pending", "processing"):
break
time.sleep(2)
print(result["status"], result["resultUrl"])List tools
GET/api/v1/tools
Returns every active server-side tool you can use in a job. Use the slug as the tool value when creating a job.
| Field | Type | Description |
|---|---|---|
| category | query, optional | Only return tools in this category slug. |
{
"tools": [
{
"slug": "compress-pdf",
"name": "Compress PDF",
"tagline": "Reduce PDF file size",
"is_pro": false,
"input_formats": ["pdf"],
"output_format": "pdf",
"max_file_size_mb": 25,
"max_files": 1,
"category": { "slug": "optimize", "name": "Optimize" }
}
],
"count": 1
}Upload a file
POST/api/v1/upload
Upload one file as multipart/form-data in a field named file. The size limit depends on your plan.
{
"path": "api-uploads/USER_ID/UUID/report.pdf",
"name": "report.pdf",
"size": 482113,
"type": "application/pdf"
}Create a job
POST/api/v1/jobs
Starts processing. Jobs run asynchronously; the response returns immediately with status pending.
| Field | Type | Description |
|---|---|---|
| tool | string, required | Tool slug from List tools, e.g. compress-pdf. |
| files | string[], required | Paths returned by Upload. Must not exceed the tool’s max_files. |
| options | object, optional | Tool-specific settings (for example a quality level). |
{
"job": { "id": "6f1c…", "status": "pending", "tool": "compress-pdf" },
"message": "Job created. Poll GET /api/v1/jobs/6f1c… for status."
}Get a job
GET/api/v1/jobs/{id}
Returns the job’s status and, once completed, signed download links. Status moves from pending → processing → completed or failed. Poll every 2–5 seconds.
{
"success": true,
"status": "completed",
"progress": 100,
"resultUrl": "https://…/report-compressed.pdf?token=…",
"error": null,
"expires_at": "2026-11-14T10:00:00.000Z",
"job": {
"id": "6f1c…",
"tool": "compress-pdf",
"download_urls": ["https://…/report-compressed.pdf?token=…"],
"download_zip": null,
"created_at": "2026-10-15T10:00:00.000Z"
}
}List jobs
GET/api/v1/jobs
Your most recent jobs, newest first.
| Field | Type | Description |
|---|---|---|
| limit | query, optional | Number of jobs, 1–100 (default 20). |
| status | query, optional | Filter: pending, processing, completed or failed. |
Errors
Errors return a JSON body with an error message.
| Field | Type | Description |
|---|---|---|
| 400 | Bad request | Missing tool or files, invalid JSON, or too many files. |
| 401 | Unauthorized | Missing, invalid or revoked API key. |
| 403 | Forbidden | Your plan does not include the API or this tool. |
| 404 | Not found | Unknown tool slug or job ID. |
| 413 | Too large | The file exceeds your plan’s upload limit. |
| 429 | Too many requests | Daily limit reached (resets at midnight UTC) or more than 20 uploads a minute. |
Webhooks
Instead of polling, set an HTTPS endpoint in Dashboard → Webhooks (Pro). We POST to it when a job starts (job.processing), finishes (job.completed) or fails (job.failed). Requests time out after 10 seconds; respond with any 2xx status.
POST /your/endpoint
X-MyToolSpace-Event: job.completed
X-MyToolSpace-Timestamp: 2026-10-15T10:00:05.000Z
X-MyToolSpace-Signature: 5d41402abc4b2a76b9719d911017c592…
{
"event": "job.completed",
"job": {
"id": "6f1c…",
"tool": "compress-pdf",
"status": "completed",
"progress": 100,
"download_urls": ["https://…"],
"created_at": "2026-10-15T10:00:00.000Z",
"expires_at": "2026-11-14T10:00:00.000Z"
},
"timestamp": "2026-10-15T10:00:05.000Z"
}The signature is the hex HMAC-SHA256 of the raw request body, keyed with your webhook signing secret. Verify it before trusting the payload:
import crypto from 'node:crypto'
function isValid(rawBody, signature, secret) {
const expected = crypto.createHmac('sha256', secret).update(rawBody).digest('hex')
return signature?.length === expected.length &&
crypto.timingSafeEqual(Buffer.from(expected), Buffer.from(signature))
}FAQ
Is there a free API plan?
The API is included with Pro (1,000 calls a day) and Enterprise (50,000 calls a day). Every tool remains free to use on the website without an account.
How do I get an API key?
Upgrade to Pro, then open Dashboard → Developer API and click “Create key”. The full key is shown once; store it as a secret on your server.
When does the daily limit reset?
Request counts reset every day at midnight UTC. Every response includes an X-RateLimit-Limit header with your plan’s daily limit.
How long are results available?
Download links are signed and output files are kept for your plan’s retention period: 30 days on Pro and 90 days on Enterprise. Download results you need to keep.
Can I call the API from a browser?
The API sends CORS headers, but never expose your API key in front-end code. Call the API from your server or a serverless function instead.
Last updated