Developer Docs

Convert files programmatically using the SkyConvert REST API. Supports images, audio, video, documents, PDFs, archives, and more.

Base URLhttps://api.skyconvert.net/v1

Introduction

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).

All requests must be sent over HTTPS. HTTP connections are rejected.

Authentication

Pass your API key using any one of the following methods:

MethodExample
X-API-Key headerX-API-Key: oc_live_abc123...
Bearer tokenAuthorization: Bearer oc_live_abc123...
Query parameter?api_key=oc_live_abc123...

You can create and manage API keys from your account dashboard.

Keep your API key secret. Do not commit it to source control. Rotate it immediately if it is exposed.

Key Restrictions

When creating a key you can choose a restriction type:

TypeBehaviour
allNo restriction – any IP or origin may use the key.
ipOnly requests coming from the specified IP addresses are accepted.
domainOnly 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.

PlanAPI AccessCalls / DayCalls / Minute
FreeDisabled
BasicEnabled2,00060
ProEnabledUnlimitedUnlimited

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.

Rate-limit counters reset every day at midnight UTC (daily) and every rolling 60-second window (per-minute).

Errors

All errors follow the same structure:

{
  "error": "Human-readable error name",
  "message": "Detailed explanation",
  "hint": "Optional hint to fix the problem"
}
StatusMeaning
200OK
202Accepted – conversion job queued
400Bad Request – missing or invalid parameters
401Unauthorized – missing or invalid API key
403Forbidden – IP or domain restriction violation
404Not Found – job or file does not exist
409Conflict – job not finished yet
429Too Many Requests – rate limit reached
500Internal Server Error

API Info

GET/v1/No auth required

Returns API version info, available endpoints, and docs URL. Useful for health-checks.

curl https://api.skyconvert.net/v1/

List Formats

GET/v1/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

POST/v1/upload

Upload one or more files. Returns a file_path you can pass directly to /v1/convert.

Request (multipart/form-data)

FieldTypeDescription
fileFilerequiredFile 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

POST/v1/convert

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)

FieldTypeDescription
fileFilerequired*File to convert
file_pathstringoptional*Path from a prior /upload call (alternative to sending file)
filetypestringrequiredConverter category: image, audio, video, document, pdf, hash, archive, ebook
output_formatstringrequiredTarget extension, e.g. jpg, mp3, pdf
optionsJSON stringoptionalConverter-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

GET/v1/status/{job_id}

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" }
StatusMeaning
pendingJob is queued, not yet started
processingConversion is running
finishedDone — download is ready
failedConversion failed — see error field

Download Result

GET/v1/download/{job_id}

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"
Returns 409 Conflict if the job is not finished yet. Poll /v1/status first.

Key Info & Quota

GET/v1/keys/me

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:

  1. Log in and go to API Keys in your dashboard.
  2. Click Create Key. Copy the key — it won't be shown again.
  3. Call POST /v1/convert with your file and desired output format.
  4. Poll GET /v1/status/{job_id} until status is finished.
  5. Download from GET /v1/download/{job_id}.
That's it! Check the endpoint examples above for code you can copy-paste.

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.

Webhook support is on our roadmap. Watch your dashboard for announcements.

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.

If you are behind a NAT or proxy, use the public egress IP of your server, not a private IP.

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.

Wildcard subdomains are supported: *.example.com allows all subdomains of example.com.