Developer Docs
Convert files programmatically using the SkyConvert REST API. Supports images, audio, video, documents, PDFs, archives, and more.
https://api.skyconvert.net/v1Introduction
The SkyConvert API lets you upload files and convert them to any supported format programmatically. All API calls require a valid API key. Responses are always JSON (except file downloads).
Authentication
Pass your API key using any one of the following methods:
| Method | Example |
|---|---|
| X-API-Key header | X-API-Key: oc_live_abc123... |
| Bearer token | Authorization: Bearer oc_live_abc123... |
| Query parameter | ?api_key=oc_live_abc123... |
You can create and manage API keys from your account dashboard.
Key Restrictions
When creating a key you can choose a restriction type:
| Type | Behaviour |
|---|---|
| all | No restriction – any IP or origin may use the key. |
| ip | Only requests coming from the specified IP addresses are accepted. |
| domain | Only requests with an Origin or Referer matching the allowed domain list are accepted. |
Rate Limits
API access and rate limits are controlled per subscription plan. Only plans that have API access enabled by the admin can use the API. Your admin configures these limits from the plan settings in the admin dashboard.
| Plan | API Access | Calls / Day | Calls / Minute |
|---|---|---|---|
| Free | Disabled | — | — |
| Basic | Enabled | 2,000 | 60 |
| Pro | Enabled | Unlimited | Unlimited |
When a limit is exceeded the API returns HTTP 429 Too Many Requests. If your plan does not have API access, you will receive a 403 Forbidden with a clear message and upgrade instructions. Check GET /v1/keys/me at any time to see your remaining quota.
Errors
All errors follow the same structure:
{
"error": "Human-readable error name",
"message": "Detailed explanation",
"hint": "Optional hint to fix the problem"
}| Status | Meaning |
|---|---|
| 200 | OK |
| 202 | Accepted – conversion job queued |
| 400 | Bad Request – missing or invalid parameters |
| 401 | Unauthorized – missing or invalid API key |
| 403 | Forbidden – IP or domain restriction violation |
| 404 | Not Found – job or file does not exist |
| 409 | Conflict – job not finished yet |
| 429 | Too Many Requests – rate limit reached |
| 500 | Internal Server Error |
API Info
Returns API version info, available endpoints, and docs URL. Useful for health-checks.
curl https://api.skyconvert.net/v1/List Formats
Returns all supported input and output formats grouped by converter type.
curl https://api.skyconvert.net/v1/formats \
-H "X-API-Key: YOUR_API_KEY"Response
{
"ok": true,
"filetypes": {
"image": {
"input_formats": ["jpg", "png", "webp", "gif", "bmp", "tiff"],
"output_formats": ["jpg", "png", "webp", "gif", "bmp", "tiff", "ico"]
},
"audio": { "input_formats": [...], "output_formats": [...] },
...
}
}Upload a File
Upload one or more files. Returns a file_path you can pass directly to /v1/convert.
Request (multipart/form-data)
| Field | Type | Description | |
|---|---|---|---|
| file | File | required | File to upload (repeat for multiple files) |
curl -X POST https://api.skyconvert.net/v1/upload \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@/path/to/image.png"import requests
resp = requests.post(
"https://api.skyconvert.net/v1/upload",
headers={"X-API-Key": "YOUR_API_KEY"},
files={"file": open("image.png", "rb")},
)
data = resp.json()
file_path = data["files"][0]["file_path"]const form = new FormData();
form.append("file", fileInput.files[0]);
const resp = await fetch("https://api.skyconvert.net/v1/upload", {
method: "POST",
headers: { "X-API-Key": "YOUR_API_KEY" },
body: form,
});
const { files } = await resp.json();
const filePath = files[0].file_path;Response
{
"ok": true,
"files": [
{
"file_path": "a3f7bc91d8e2/image.png",
"file_name": "image.png",
"file_size": 204800,
"upload_id": 42,
"extension": "png"
}
]
}Convert a File
Upload a file and start a conversion job in one request. Returns a job_id; poll /v1/status/{job_id} to check progress.
Request (multipart/form-data)
| Field | Type | Description | |
|---|---|---|---|
| file | File | required* | File to convert |
| file_path | string | optional* | Path from a prior /upload call (alternative to sending file) |
| filetype | string | required | Converter category: image, audio, video, document, pdf, hash, archive, ebook |
| output_format | string | required | Target extension, e.g. jpg, mp3, pdf |
| options | JSON string | optional | Converter-specific options (quality, resize, etc.) |
* Either file or file_path is required.
curl -X POST https://api.skyconvert.net/v1/convert \
-H "X-API-Key: YOUR_API_KEY" \
-F "file=@/path/to/input.png" \
-F "filetype=image" \
-F "output_format=webp"import requests, time
API_KEY = "YOUR_API_KEY"
BASE = "https://api.skyconvert.net/v1"
# 1. Start conversion
resp = requests.post(f"{BASE}/convert",
headers={"X-API-Key": API_KEY},
files={"file": open("input.png", "rb")},
data={"filetype": "image", "output_format": "webp"},
)
job = resp.json()
job_id = job["job_id"]
# 2. Poll until done
while True:
status = requests.get(f"{BASE}/status/{job_id}",
headers={"X-API-Key": API_KEY}).json()
if status["status"] == "finished":
break
if status["status"] == "failed":
raise Exception(status.get("error"))
time.sleep(2)
# 3. Download result
out = requests.get(f"{BASE}/download/{job_id}",
headers={"X-API-Key": API_KEY})
with open("output.webp", "wb") as f:
f.write(out.content)const API_KEY = "YOUR_API_KEY";
const BASE = "https://api.skyconvert.net/v1";
// 1. Start conversion
const form = new FormData();
form.append("file", fileInput.files[0]);
form.append("filetype", "image");
form.append("output_format", "webp");
const { job_id } = await fetch(`${BASE}/convert`, {
method: "POST",
headers: { "X-API-Key": API_KEY },
body: form,
}).then(r => r.json());
// 2. Poll until done
let status;
do {
await new Promise(r => setTimeout(r, 2000));
status = await fetch(`${BASE}/status/${job_id}`,
{ headers: { "X-API-Key": API_KEY } }).then(r => r.json());
} while (status.status === "pending" || status.status === "processing");
// 3. Download result
if (status.status === "finished") {
window.location.href = status.download_url;
}Response (202 Accepted)
{
"ok": true,
"job_id": "a1b2c3d4-e5f6-...",
"status": "pending",
"status_url": "https://api.skyconvert.net/v1/status/a1b2c3d4-e5f6-...",
"download_url": "https://api.skyconvert.net/v1/download/a1b2c3d4-e5f6-..."
}Job Status
Poll the status of a conversion job.
curl https://api.skyconvert.net/v1/status/JOB_ID \
-H "X-API-Key: YOUR_API_KEY"Response
// Pending / Processing
{ "ok": true, "job_id": "...", "status": "pending" }
// Finished
{ "ok": true, "job_id": "...", "status": "finished",
"download_url": "https://api.skyconvert.net/v1/download/..." }
// Failed
{ "ok": false, "job_id": "...", "status": "failed",
"error": "Unsupported codec" }| Status | Meaning |
|---|---|
| pending | Job is queued, not yet started |
| processing | Conversion is running |
| finished | Done — download is ready |
| failed | Conversion failed — see error field |
Download Result
Download the converted file. Returns the raw file bytes with Content-Disposition: attachment. Only works once the job status is finished.
curl -O -J https://api.skyconvert.net/v1/download/JOB_ID \
-H "X-API-Key: YOUR_API_KEY"/v1/status first.Key Info & Quota
Inspect the current API key and check your remaining rate-limit quota.
curl https://api.skyconvert.net/v1/keys/me \
-H "X-API-Key: YOUR_API_KEY"Response
{
"ok": true,
"key_id": 3,
"name": "My Production Key",
"restriction_type": "ip",
"allowed_ips": ["203.0.113.5"],
"allowed_domains": [],
"usage_count": 1042,
"last_used_at": "2026-03-27T10:14:55",
"created_at": "2026-01-01T00:00:00",
"rate_limits": {
"calls_per_day": 2000,
"calls_per_minute": 60,
"used_today": 412,
"used_this_minute": 3,
"remaining_today": 1588
}
}Quick Start
Get a file converted in under a minute:
- Log in and go to API Keys in your dashboard.
- Click Create Key. Copy the key — it won't be shown again.
- Call POST /v1/convert with your file and desired output format.
- Poll GET /v1/status/{job_id} until status is finished.
- Download from GET /v1/download/{job_id}.
Polling vs Webhooks
Currently, the API uses a polling model. After submitting a conversion job, poll /v1/status/{job_id} every 2–5 seconds until the status changes to finished or failed.
Recommended polling interval: 2 seconds for short jobs, 5–10 seconds for large video/document jobs.
Key Restrictions
You can lock each API key to specific IPs or domains to prevent misuse if the key is ever exposed.
IP Restriction
Set restriction_type = ip and provide one or more IPv4/IPv6 addresses. Only requests originating from those IPs will be accepted.
Domain Restriction
Set restriction_type = domain and list your domains (e.g. example.com). The API checks the Origin and Referer headers — ideal for browser-based integrations.