Jobs and tasks
The CloudConvert-compatible switchfile API (v2). Jobs made of tasks, task status, results, retries and moving over from CloudConvert.
The /v2 API takes jobs in the format of the CloudConvert API v2. A job is a set of named tasks: import the file, convert it, export the result. Tasks name their input, so one job can convert one file into several formats or several files at once.
Coming from CloudConvert#
Change the base URL and the API key, keep your request bodies and your webhook handling:
- https://api.cloudconvert.com/v2/jobs
+ https://api.switchfile.io/v2/jobsTask names, statuses, results, pagination and the webhook signature header (CloudConvert-Signature) follow the same format. Options for convert go on the task, like at CloudConvert; the names are listed in Formats and options.
Create a job#
curl https://api.switchfile.io/v2/jobs \
-H "Authorization: Bearer $SWITCHFILE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"tag": "invoice-4711",
"tasks": {
"import-1": {"operation": "import/url", "url": "https://example.com/report.docx"},
"convert-1": {"operation": "convert", "input": "import-1", "output_format": "pdf"},
"export-1": {"operation": "export/url", "input": "convert-1"}
}
}'const res = await fetch("https://api.switchfile.io/v2/jobs", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SWITCHFILE_API_KEY}`, "Content-Type": "application/json" },
body: JSON.stringify({
tag: "invoice-4711",
tasks: {
"import-1": { operation: "import/url", url: "https://example.com/report.docx" },
"convert-1": { operation: "convert", input: "import-1", output_format: "pdf" },
"export-1": { operation: "export/url", input: "convert-1" },
},
}),
});
if (!res.ok) throw new Error(`HTTP ${res.status}: ${await res.text()}`);
const { data: job } = await res.json();
console.log(job.id, job.status);<?php
$job = [
'tag' => 'invoice-4711',
'tasks' => [
'import-1' => ['operation' => 'import/url', 'url' => 'https://example.com/report.docx'],
'convert-1' => ['operation' => 'convert', 'input' => 'import-1', 'output_format' => 'pdf'],
'export-1' => ['operation' => 'export/url', 'input' => 'convert-1'],
],
];
$ch = curl_init('https://api.switchfile.io/v2/jobs');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($job),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('SWITCHFILE_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
$data = json_decode(curl_exec($ch), true)['data'];
echo $data['id'], ' ', $data['status'], PHP_EOL;import os
import requests
res = requests.post(
"https://api.switchfile.io/v2/jobs",
headers={"Authorization": f"Bearer {os.environ['SWITCHFILE_API_KEY']}"},
json={
"tag": "invoice-4711",
"tasks": {
"import-1": {"operation": "import/url", "url": "https://example.com/report.docx"},
"convert-1": {"operation": "convert", "input": "import-1", "output_format": "pdf"},
"export-1": {"operation": "export/url", "input": "convert-1"},
},
},
)
res.raise_for_status()
job = res.json()["data"]
print(job["id"], job["status"])The answer is 201 with the job and its tasks. Task names may use letters, digits, - and _, up to 100 characters. A job has at most 200 tasks.
Operations#
| Operation | What it does | Main fields |
|---|---|---|
import/url | Downloads a file from a public http or https URL | url, filename, headers |
import/upload | Waits for a file that you upload, see Uploads | filename |
import/base64 | Takes the file inline, up to 10 MB | file, filename |
convert | Converts its input | input, output_format, input_format, options |
export/url | Creates signed download URLs for its input | input, inline |
input is the name of another task, or a list of names. All tasks take ignore_error: when it is true, the job does not fail if this task fails. convert takes timeout in seconds to lower the time limit, and every option of the target format directly on the task:
"convert-1": { "operation": "convert", "input": "import-1", "output_format": "mp4", "crf": 23, "width": 1280 }Status and results#
Jobs and tasks have the status waiting, processing, finished or error. A waiting task says what it waits for in waiting_for: upload, inputs or queued. A failed task has code and message, see Errors.
engine and engine_version on a task are internal identifiers and may change. Do not rely on their values; the examples in these docs show them as null.
Get the job with GET /v2/jobs/{id}, wait for it with GET /v2/jobs/{id}/wait (up to 5 minutes), or let a webhook call you. The export/url task lists the files:
{
"name": "export-1",
"operation": "export/url",
"status": "finished",
"result": {
"files": [
{ "filename": "report.pdf", "size": 61544, "url": "https://api.switchfile.io/files/2a6f8e1c-.../report.pdf?expires=...&signature=..." }
]
}
}The URLs are signed and work without an API key for 24 hours. With "inline": true on the export task, the browser shows the file instead of downloading it.
curl "https://api.switchfile.io/v2/jobs/$JOB_ID/wait" \
-H "Authorization: Bearer $SWITCHFILE_API_KEY"const res = await fetch(`https://api.switchfile.io/v2/jobs/${process.env.JOB_ID}/wait`, {
headers: { Authorization: `Bearer ${process.env.SWITCHFILE_API_KEY}` },
});
if (!res.ok) throw new Error(`HTTP ${res.status}`);
const { data: job } = await res.json();
const exported = job.tasks.find((t) => t.operation === "export/url" && t.status === "finished");
console.log(job.status, exported?.result.files.map((f) => f.url));Lists and retries#
- GET /v2/jobs and GET /v2/tasks list your jobs and tasks, newest first, with
filter[status],filter[tag],filter[job_id],filter[operation]and pages of up to 1000 entries (per_page,page). - POST /v2/tasks/{id}/retry runs a finished or failed task again as a new task. Retry the tasks that use its output afterwards.
- POST /v2/tasks/{id}/cancel stops a waiting or running task.
- DELETE /v2/jobs/{id} deletes a job with its files right away. Otherwise jobs are deleted 24 hours after they end.
Formats#
GET /v2/convert/formats lists every pair of input and output format with its minimum credits. Filter it with filter[input_format] and filter[output_format]. No API key needed. The engine of each pair is an internal identifier and may change.