Quickstart
Create a test key, upload a file, and download a conversion result.
1. Create a test key
In your organization's Settings → API Keys tab, create a key with mode Test and copy its secret. It is shown once. Set it as KEY in the examples below.
export BASE=https://api.convertere.io/v1
export KEY=cvio_test_...2. Create a job
This task graph imports an upload, converts PNG to WebP, and exports a download URL. The response contains the job id and, on the import-1 task, a presigned uploadUrl (tasks[0].result.uploadUrl).
curl -s -X POST "$BASE/jobs" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' \
-d '{"tasks":{"import-1":{"operation":"import/upload"},"convert-1":{"operation":"convert","input":"import-1","input_format":"png","output_format":"webp","options":{}},"export-1":{"operation":"export/url","input":"convert-1"}}}' \
| tee job.json
JOB_ID=$(jq -r .id job.json)
UPLOAD_URL=$(jq -r '.tasks[0].result.uploadUrl' job.json)const base = "https://api.convertere.io/v1";
const key = process.env.CONVERTERE_API_KEY; // Node 20+
const response = await fetch(`${base}/jobs`, {
method: "POST",
headers: {
Authorization: `Bearer ${key}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
tasks: {
"import-1": { operation: "import/upload" },
"convert-1": {
operation: "convert",
input: "import-1",
input_format: "png",
output_format: "webp",
options: {},
},
"export-1": { operation: "export/url", input: "convert-1" },
},
}),
});
const job = await response.json();
const uploadUrl = job.tasks[0].result.uploadUrl;import os
import requests
base = "https://api.convertere.io/v1"
key = os.environ["CONVERTERE_API_KEY"]
response = requests.post(f"{base}/jobs", headers={"Authorization": f"Bearer {key}"}, json={"tasks": {
"import-1": {"operation": "import/upload"},
"convert-1": {"operation": "convert", "input": "import-1", "input_format": "png", "output_format": "webp", "options": {}},
"export-1": {"operation": "export/url", "input": "convert-1"}
}})
job = response.json()
upload_url = job["tasks"][0]["result"]["uploadUrl"]The response looks like this (shortened):
{
"id": "11111111-1111-4111-8111-111111111111",
"status": "waiting",
"mode": "single",
"testMode": true,
"test_mode": true,
"credits_estimated": 1,
"tasks": [
{
"name": "import-1",
"operation": "import/upload",
"status": "waiting",
"result": {
"uploadUrl": "https://…",
"uploadExpiresAt": "2026-10-10T13:00:00.000Z"
}
},
{ "name": "convert-1", "operation": "convert", "status": "waiting" },
{ "name": "export-1", "operation": "export/url", "status": "waiting" }
],
"createdAt": "2026-10-10T12:00:00.000Z",
"created_at": "2026-10-10T12:00:00.000Z",
"expires_at": null,
"api_key_id": "22222222-2222-4222-8222-222222222222"
}3. Upload the file
Send the file bytes in a single PUT to the uploadUrl. The URL is presigned: do not add the API key header.
curl -X PUT --upload-file sample.png "$UPLOAD_URL"import { readFile } from "node:fs/promises";
await fetch(uploadUrl, { method: "PUT", body: await readFile("sample.png") });with open("sample.png", "rb") as file:
requests.put(upload_url, data=file).raise_for_status()4. Wait for the job
wait accepts 0–25 seconds. The request returns as soon as the job's status changes, or after the wait with the current state; call it again until the status is finished (or error). Fetching the job also notices your upload and starts the conversion.
curl "$BASE/jobs/$JOB_ID?wait=25" -H "Authorization: Bearer $KEY"let status;
do {
status = await fetch(`${base}/jobs/${job.id}?wait=25`, {
headers: { Authorization: `Bearer ${key}` },
}).then((r) => r.json());
} while (
!["finished", "error", "cancelled", "expired"].includes(status.status)
);while True:
status = requests.get(f"{base}/jobs/{job['id']}", params={"wait": 25},
headers={"Authorization": f"Bearer {key}"}).json()
if status["status"] in ("finished", "error", "cancelled", "expired"):
break5. Download the result
When the job is finished, read the result URL from the export/url task and download it. The link is valid for 24 hours.
curl -L "$(curl -s "$BASE/jobs/$JOB_ID" -H "Authorization: Bearer $KEY" \
| jq -r '.tasks[] | select(.operation=="export/url") | .result.url')" -o output.webpimport { writeFile } from "node:fs/promises";
const resultUrl = status.tasks.find((t) => t.operation === "export/url").result
.url;
const file = await fetch(resultUrl);
await writeFile("output.webp", Buffer.from(await file.arrayBuffer()));result_url = next(t for t in status["tasks"] if t["operation"] == "export/url")["result"]["url"]
with requests.get(result_url, stream=True) as result:
result.raise_for_status()
with open("output.webp", "wb") as output:
for chunk in result.iter_content(8192):
output.write(chunk)A test key never converts anything: the "result" is a copy of the file you uploaded. See Test mode. To use real conversions create a Live key; see Credits.
Next steps
- Skip polling with webhooks.
- Convert a file from a URL, or upload more than 100 MB, in Uploads.
- Make job creation safe to retry with an
Idempotency-Key.