Create a job
Creates a job from named tasks and answers with 201 right away. Tasks that need no input start at once, the others when their inputs are done. Under the /sync prefix (POST /sync/v2/jobs) the request waits for the job and answers with 200, or with 302 to the first exported file if redirect is true.
https://api.switchfile.io/v2/jobsExample
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()}`);
console.log(await res.json());<?php
$ch = curl_init('https://api.switchfile.io/v2/jobs');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode([
'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',
],
],
]),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer ' . getenv('SWITCHFILE_API_KEY'),
'Content-Type: application/json',
],
CURLOPT_RETURNTRANSFER => true,
]);
$response = curl_exec($ch);
$status = curl_getinfo($ch, CURLINFO_RESPONSE_CODE);
curl_close($ch);
if ($status >= 400) {
throw new RuntimeException("HTTP $status: $response");
}
print_r(json_decode($response, true));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()
print(res.json())Request body
redirectbooleanSync requests only: redirect to the URL of the first exported file
tagstring | nullat most 255 characters
tasksmap of ImportUrlTask | ImportUploadTask | ImportBase64Task | ConvertTask | ExportUrlTaskrequiredThe tasks of the job. Each key is the task name
1 to 200 entries · keys match ^[A-Za-z0-9_-]{1,100}$
webhook_urlstring | nullat most 4096 characters · matches ^https?://
ImportUrlTask
filenamestring1 to 255 characters
headersmap of stringkeys match ^(.*)$
ignore_errorbooleanIf true, the job does not fail when this task fails
operationstringrequiredone of "import/url"
urlstringrequiredat most 4096 characters · matches ^https?://
ImportUploadTask
filenamestring1 to 255 characters
ignore_errorbooleanIf true, the job does not fail when this task fails
operationstringrequiredone of "import/upload"
ImportBase64Task
filestringrequiredFile content as base64, at most 10 MiB after decoding
1 to 13981272 characters
filenamestringrequired1 to 255 characters
ignore_errorbooleanIf true, the job does not fail when this task fails
operationstringrequiredone of "import/base64"
ConvertTask
enginestringUse only this engine (value as in GET /v2/convert/formats). Internal identifier, may change; usually left out
engine_versionstringThe task fails if the engine ran in another version. Internal identifier, may change; usually left out
filenamestring1 to 255 characters
ignore_errorbooleanIf true, the job does not fail when this task fails
inputstring | string[]requiredName of the task that provides the input, or a list of names
at least 1 characters
input_formatstringFile format, for example pdf or tar.gz
1 to 20 characters
operationstringrequiredone of "convert"
output_formatstringrequiredFile format, for example pdf or tar.gz
1 to 20 characters
timeoutnumberTime limit for this task in seconds
greater than 0
ExportUrlTask
archive_multiple_filesbooleanignore_errorbooleanIf true, the job does not fail when this task fails
inlinebooleaninputstring | string[]requiredName of the task that provides the input, or a list of names
at least 1 characters
operationstringrequiredone of "export/url"
Responses
200Sync requests only: the finished job
dataJobrequireddata.created_atstringrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.ended_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.idstring (uuid)requireddata.linksobjectrequireddata.links.selfstringrequireddata.started_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.statusstringrequiredone of "waiting", "processing", "finished", "error"
data.tagstring | nullrequireddata.tasksTask[]data.tasks[].codestring | nullrequireddata.tasks[].copy_of_task_idstring (uuid) | nullrequireddata.tasks[].created_atstringrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].creditsstring (integer) | integerrequireddata.tasks[].depends_on_task_idsstring (uuid)[]requireddata.tasks[].ended_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].enginestring | nullrequiredInternal identifier, may change. Do not rely on its value
data.tasks[].engine_versionstring | nullrequiredInternal identifier, may change. Do not rely on its value
data.tasks[].host_namestring | nullrequireddata.tasks[].idstring (uuid)requireddata.tasks[].job_idstring (uuid)requireddata.tasks[].linksobjectrequireddata.tasks[].links.selfstringrequireddata.tasks[].messagestring | nullrequireddata.tasks[].namestringrequireddata.tasks[].operationstringrequireddata.tasks[].percentstring (integer) | integerrequiredProgress as in CloudConvert: 100 when finished, otherwise 0
0 to 100
data.tasks[].prioritystring (integer) | integerrequireddata.tasks[].regionstringrequiredRegion the task runs in (eu-central)
data.tasks[].resultTaskResultrequireddata.tasks[].result.filesResultFile[]data.tasks[].result.formUploadFormdata.tasks[].result.uploadDirectUploadimport/upload only: a signed URL for large files, without the 100 MB limit of result.form. The task finishes on its own a few seconds after the PUT. Call POST /v2/tasks/{id}/upload-complete to finish it right away.
data.tasks[].retry_of_task_idstring (uuid) | nullrequireddata.tasks[].started_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].statusstringrequiredone of "waiting", "processing", "finished", "error"
data.tasks[].storagestring | nullrequireddata.tasks[].user_idstring | nullrequiredAccount of the job (opaque ID, the same as data.id in /v2/users/me)
data.tasks[].waiting_forstringWhat a waiting task waits for, one of "upload", "inputs", "queued". Only set while status is waiting
200 application/json{ "data": { "id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "tag": "invoice-4711", "status": "finished", "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:00+00:00", "ended_at": "2026-11-06T18:00:02+00:00", "tasks": [ { "id": "c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "import-1", "operation": "import/url", "status": "finished", "message": null, "code": null, "credits": 0, "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:00+00:00", "ended_at": "2026-11-06T18:00:01+00:00", "depends_on_task_ids": [], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 100, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": { "files": [ { "filename": "report.docx", "size": 48213 } ] }, "links": { "self": "https://api.switchfile.io/v2/tasks/c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31" } }, { "id": "5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "convert-1", "operation": "convert", "status": "finished", "message": null, "code": null, "credits": 2, "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:01+00:00", "ended_at": "2026-11-06T18:00:02+00:00", "depends_on_task_ids": [ "c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31" ], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 100, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": { "files": [ { "filename": "report.pdf", "size": 61544 } ] }, "links": { "self": "https://api.switchfile.io/v2/tasks/5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52" } }, { "id": "e8a4c6b1-2d3f-4a5e-9b7c-1d0f3e5a7c93", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "export-1", "operation": "export/url", "status": "finished", "message": null, "code": null, "credits": 0, "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:02+00:00", "ended_at": "2026-11-06T18:00:02+00:00", "depends_on_task_ids": [ "5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52" ], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 100, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": { "files": [ { "filename": "report.pdf", "size": 61544, "url": "https://api.switchfile.io/files/2a6f8e1c-4b3d-4e7a-9c5f-8d1b0e2a4c67/report.pdf?expires=1762538401&signature=3f9c2a7d41e8b6c05d1f9e2a7b4c8d3e6f0a1b2c3d4e5f60718293a4b5c6d7e8" } ] }, "links": { "self": "https://api.switchfile.io/v2/tasks/e8a4c6b1-2d3f-4a5e-9b7c-1d0f3e5a7c93" } } ], "links": { "self": "https://api.switchfile.io/v2/jobs/6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10" } } }201Created. Tasks run in the background
dataJobrequireddata.created_atstringrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.ended_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.idstring (uuid)requireddata.linksobjectrequireddata.links.selfstringrequireddata.started_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.statusstringrequiredone of "waiting", "processing", "finished", "error"
data.tagstring | nullrequireddata.tasksTask[]data.tasks[].codestring | nullrequireddata.tasks[].copy_of_task_idstring (uuid) | nullrequireddata.tasks[].created_atstringrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].creditsstring (integer) | integerrequireddata.tasks[].depends_on_task_idsstring (uuid)[]requireddata.tasks[].ended_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].enginestring | nullrequiredInternal identifier, may change. Do not rely on its value
data.tasks[].engine_versionstring | nullrequiredInternal identifier, may change. Do not rely on its value
data.tasks[].host_namestring | nullrequireddata.tasks[].idstring (uuid)requireddata.tasks[].job_idstring (uuid)requireddata.tasks[].linksobjectrequireddata.tasks[].links.selfstringrequireddata.tasks[].messagestring | nullrequireddata.tasks[].namestringrequireddata.tasks[].operationstringrequireddata.tasks[].percentstring (integer) | integerrequiredProgress as in CloudConvert: 100 when finished, otherwise 0
0 to 100
data.tasks[].prioritystring (integer) | integerrequireddata.tasks[].regionstringrequiredRegion the task runs in (eu-central)
data.tasks[].resultTaskResultrequireddata.tasks[].result.filesResultFile[]data.tasks[].result.formUploadFormdata.tasks[].result.uploadDirectUploadimport/upload only: a signed URL for large files, without the 100 MB limit of result.form. The task finishes on its own a few seconds after the PUT. Call POST /v2/tasks/{id}/upload-complete to finish it right away.
data.tasks[].retry_of_task_idstring (uuid) | nullrequireddata.tasks[].started_atstring | nullrequiredISO 8601 timestamp, for example 2026-11-06T18:00:00+00:00
data.tasks[].statusstringrequiredone of "waiting", "processing", "finished", "error"
data.tasks[].storagestring | nullrequireddata.tasks[].user_idstring | nullrequiredAccount of the job (opaque ID, the same as data.id in /v2/users/me)
data.tasks[].waiting_forstringWhat a waiting task waits for, one of "upload", "inputs", "queued". Only set while status is waiting
201 application/json{ "data": { "id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "tag": "invoice-4711", "status": "processing", "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:00+00:00", "ended_at": null, "tasks": [ { "id": "c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "import-1", "operation": "import/url", "status": "processing", "message": null, "code": null, "credits": null, "created_at": "2026-11-06T18:00:00+00:00", "started_at": "2026-11-06T18:00:00+00:00", "ended_at": null, "depends_on_task_ids": [], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 0, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": null, "links": { "self": "https://api.switchfile.io/v2/tasks/c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31" } }, { "id": "5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "convert-1", "operation": "convert", "status": "waiting", "message": null, "code": null, "credits": null, "created_at": "2026-11-06T18:00:00+00:00", "started_at": null, "ended_at": null, "depends_on_task_ids": [ "c1f3a9d2-7e44-4b0a-a1b5-2f0e8c9d6a31" ], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 0, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": null, "links": { "self": "https://api.switchfile.io/v2/tasks/5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52" }, "waiting_for": "inputs" }, { "id": "e8a4c6b1-2d3f-4a5e-9b7c-1d0f3e5a7c93", "job_id": "6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10", "name": "export-1", "operation": "export/url", "status": "waiting", "message": null, "code": null, "credits": null, "created_at": "2026-11-06T18:00:00+00:00", "started_at": null, "ended_at": null, "depends_on_task_ids": [ "5b7d2e90-1a3c-4f6e-8d2b-9c0a4e7f1b52" ], "retry_of_task_id": null, "copy_of_task_id": null, "priority": 0, "host_name": null, "storage": null, "engine": null, "engine_version": null, "percent": 0, "region": "eu-central", "user_id": "4f8a2c6e-1b3d-4e5f-8a7c-9d0b2e4f6a18", "result": null, "links": { "self": "https://api.switchfile.io/v2/tasks/e8a4c6b1-2d3f-4a5e-9b7c-1d0f3e5a7c93" }, "waiting_for": "inputs" } ], "links": { "self": "https://api.switchfile.io/v2/jobs/6e2c1b1f-3c1a-4d4e-9a57-0d7b2f6a8e10" } } }- 302Sync requests with redirect: true. Location holds the URL of the first exported file
401The API key is missing or not valid
UNAUTHENTICATED401 application/json{ "message": "Missing or invalid API key.", "code": "UNAUTHENTICATED" }402Today's free quota is used up and there are not enough credits
CREDITS_EXCEEDED402 application/json{ "message": "Not enough credits for this job.", "code": "CREDITS_EXCEEDED" }404Does not exist for this account
NOT_FOUND404 application/json{ "message": "Job not found.", "code": "NOT_FOUND" }411The request has a body but no Content-Length header
LENGTH_REQUIRED411 application/json{ "message": "A Content-Length header is required for this request.", "code": "LENGTH_REQUIRED" }413The request or the file is too large
PAYLOAD_TOO_LARGE413 application/json{ "message": "The request body is larger than the allowed maximum.", "code": "PAYLOAD_TOO_LARGE" }422Invalid data. errors names the fields
INVALID_DATA422 application/json{ "message": "Task convert-1: The output format field is required.", "code": "INVALID_DATA", "errors": { "tasks.convert-1.output_format": [ "The output format field is required." ] } }429Too many requests or a daily quota is used up. See Retry-After
RATE_LIMIT_EXCEEDED429 application/json{ "message": "Too many requests. Try again in 12 seconds.", "code": "RATE_LIMIT_EXCEEDED" }