Overview
The KONVERTER API is a REST API served from https://api.konverterapp.com/v1. It accepts multipart/form-data (to upload files) and JSON, and always answers with JSON. Every operation you can do on konverterapp.com — and every workflow you build — is available to your code.
| Concept | What it is |
|---|---|
| Job | Run one operation (e.g. pdf.compress) on one or more files. POST /v1/jobs |
| Workflow | A saved graph of nodes built in the visual editor or via the API. POST /v1/workflows/:id/runs |
| Run | One execution of a job or workflow. Poll it, wait for it, or get a callback. Results are downloadable for 2 hours. |
The API and Workflows are part of the Pro plan. Local tools are free and unlimited (within rate limits); AI tools spend credits from your monthly allowance and top-ups — the same prices as on the website.
Quickstart
1. Create a key on the API keys page and store it as KONVERTER_API_KEY. 2. Convert a file and wait for the result in the same request:
3. Browse the operation reference for all 40+ operations and their parameters.
Authentication
Send your key as a bearer token on every request (or as X-API-Key):
Authorization: Bearer kv_live_…Keys start with kv_live_, are shown once when created and are stored only as a SHA-256 hash — if you lose one, revoke it and create another. You can have up to 10 active keys; revoking takes effect immediately. Keys can’t manage other keys: creating and revoking keys only works from your signed-in account.
Keep keys on your server. Never ship them in browser or mobile code — anyone holding a key can spend your credits.
Errors
Errors use standard HTTP status codes and one JSON shape:
{ "error": { "code": "INVALID_PARAMS", "message": "\"Quality\" must be between 1 and 100" } }| Status | Codes | Meaning |
|---|---|---|
| 400 | NO_INPUT MISSING_OPERATION INVALID_URL INVALID_UPLOAD INVALID_GRAPH TOO_MANY_FILES | The request is malformed. |
| 401 | AUTH_REQUIRED INVALID_API_KEY AUTH_INVALID | Missing, invalid or revoked credentials. |
| 403 | PLAN_REQUIRED SESSION_REQUIRED | Not on Pro, or key management attempted with an API key. |
| 404 | UNKNOWN_OPERATION RUN_NOT_FOUND WORKFLOW_NOT_FOUND OUTPUT_NOT_FOUND | No such resource (or it expired). |
| 409 | TOO_MANY_KEYS TOO_MANY_WORKFLOWS | An account limit was reached. |
| 413 | FILE_TOO_LARGE | A file is over the size limit. |
| 422 | INVALID_PARAMS INVALID_WORKFLOW SCHEDULE_NEEDS_URL_INPUT | Valid JSON, but the values don’t make sense. |
| 429 | RATE_LIMIT_EXCEEDED RUN_RATE_LIMIT TOO_MANY_ACTIVE_RUNS | Slow down — see Limits. |
| 5xx | QUEUE_FULL STORAGE_UNAVAILABLE | Temporary — retry with backoff. |
A run that starts but fails reports its error inside the run object (status: "failed", error.code), e.g. INSUFFICIENT_CREDITS, SCANNED_PDF, UNSUPPORTED_FILE, NOT_ENOUGH_FILES, CONVERSION_FAILED, NODE_TIMEOUT, INPUT_DOWNLOAD_FAILED, WEBHOOK_FAILED.
Limits
| Limit | Value |
|---|---|
| Requests per minute (per account) | 300 |
| New jobs / runs per minute | 60 |
| Runs in progress at once | 3 (more → 429 TOO_MANY_ACTIVE_RUNS) |
| Files per run | 20 (uploads + file_url combined) |
| File size | 100 MB per file (some AI tools have lower provider limits, e.g. transcription 25 MB) |
| Results kept | 2 hours after the run finishes |
| wait=true | holds the request up to 60 s by default (wait_timeout, max 120 s) |
Rate-limited responses include RateLimit-* headers. Back off and retry on 429 and 5xx.
Credits
Local operations (image, PDF, audio, video and Office tools that run on KONVERTER’s own servers) cost 0 credits. AI operations — background removal, AI enhance / background / expand, advanced OCR, translation, transcription — cost a fixed number of credits per file, shown as credits in GET /v1/operations. Credits come from your monthly allowance first, then your top-up balance.
The balance is checked before each paid step; if it runs out, that step fails with INSUFFICIENT_CREDITS and you are never charged for a step that failed. credits_used on every run shows what it cost.
Jobs
/v1/jobsRun one operation| Field | Description |
|---|---|
operation | Required. An operation id, e.g. pdf.compress — see the reference. |
params | Operation parameters as a JSON object (or a JSON string in multipart). In multipart you can also send each parameter as its own field: -F format=webp. |
file / files | The input file(s), multipart. Many-to-one operations (merge, images → PDF) take several files. |
file_url / file_urls | Instead of (or as well as) uploads: public http(s) URLs KONVERTER downloads for you. |
callback_url | Optional. We POST the finished run here — see callbacks. |
wait | Query or field. true holds the request until the run finishes (or wait_timeout seconds, default 60, max 120). |
Without wait the API answers 202 immediately with a queued run; with wait=true you get 200 and the finished run (or 202 if it’s still going when the wait times out — then poll it).
Runs
/v1/runs/:idGet a run (job or workflow) — also at /v1/jobs/:id/v1/runsRecent runs · ?kind=job|workflow ?workflow_id= ?limit= (max 100)/v1/runs/:id/cancelCancel a queued or running run{
"id": "6f1c2e8a-4b7d-4a52-9d2e-1f0c3b5a7e91",
"object": "run",
"kind": "job", // "job" (one operation) or "workflow"
"trigger": "api", // api | manual | webhook | schedule
"workflow_id": null,
"status": "succeeded", // queued | running | succeeded | failed | cancelled
"progress": 100,
"created_at": "2026-10-05T09:12:03.120Z",
"started_at": "2026-10-05T09:12:03.141Z",
"finished_at": "2026-10-05T09:12:04.007Z",
"credits_used": 0,
"nodes": [
{ "id": "step", "type": "image.convert", "label": "Convert image", "status": "succeeded",
"items_in": 1, "items_out": 1, "item_errors": [], "error": null, "duration_ms": 812, "credits_used": 0 }
],
"outputs": [
{ "id": "9b2f4c1d0e3a", "node_id": "output", "name": "photo.webp", "size": 48211,
"content_type": "image/webp",
"url": "https://api.konverterapp.com/v1/runs/6f1c…/outputs/9b2f4c1d0e3a?exp=1791195124&sig=…" }
],
"error": null, // { code, message, node_id? } when failed
"expires_at": "2026-10-05T11:12:04.007Z"
}Poll every 1–2 seconds until status is succeeded, failed or cancelled — or skip polling with wait=true or a callback_url. Each node reports how many files went in and out; files skipped by a node set to continue on failure are listed in item_errors.
Downloading results
/v1/runs/:id/outputs/:outputIdEvery output has a ready-to-use url: a signed link that works without your key (handy for passing to another service or a browser) and expires with the run’s results, 2 hours after it finished. The same path also accepts your API key without the signature. After expiry, downloads return 404 — run the job again.
Workflows
Build workflows visually in the editor — they’re instantly callable from the API — or manage them entirely in code:
/v1/workflowsList your workflows/v1/workflowsCreate · { name, description?, graph, schedule?, webhook? }/v1/workflows/:idGet one, with its graph and validation result/v1/workflows/:idUpdate any of name description graph schedule webhook/v1/workflows/:idDelete/v1/workflows/validateCheck a graph without saving · { graph } → { ok, errors[] }Saving accepts work-in-progress graphs; the response’s validation lists anything that would stop a run (missing settings, unconnected nodes, loops).
Graph format
A graph is a list of nodes and the edges between them. Files flow along edges as a list: a trigger emits the run’s input files, an operation node processes each file on its own (many-to-one operations like pdf.merge or util.zip combine them), logic nodes route or reshape the list, and output nodes publish the results.
{
"name": "Web-ready photos",
"graph": {
"nodes": [
{ "id": "in", "type": "input.files" },
{ "id": "resize", "type": "image.resize", "params": { "width": 1600, "format": "webp" } },
{ "id": "compress", "type": "image.compress", "params": { "quality": 72 }, "continueOnFail": true },
{ "id": "zip", "type": "util.zip", "params": { "filename": "photos-{date}" } },
{ "id": "out", "type": "output.files" }
],
"edges": [
{ "source": "in", "target": "resize" },
{ "source": "resize", "target": "compress" },
{ "source": "compress", "target": "zip" },
{ "source": "zip", "target": "out" }
]
}
}| Node type | What it does |
|---|---|
input.files | Trigger. The files sent with the run (uploads, file_url, webhook). |
input.url | Trigger. Downloads params.urls (one per line, max 10) at run time — required for schedules. |
image.* pdf.* audio.* video.* office.* ai.* | Every operation, with the same params as jobs. |
logic.filter | Routes each file to output port true or false by extension, size_mb or name. Set sourceHandle on the edge. |
logic.rename | Renames with a pattern: {name} {ext} {index} {date} {time}. |
util.zip / util.unzip | Bundle every file into one ZIP / expand ZIPs back into files. |
output.files | Publishes files as run outputs (downloadable). |
output.webhook | POSTs results to params.url as JSON links or multipart files (signed). |
output.email | Emails the results to your account address (attached when small, links otherwise). |
Set "continueOnFail": true on a node to skip files it can’t process instead of failing the run. A workflow without any output node returns the files produced by its last steps.
Running workflows
/v1/workflows/:id/runsSame input fields as jobs: files / file_url / callback_url / waitWebhook trigger
Turn on the webhook in the editor (or PATCH { "webhook": true }) to get a secret URL like https://api.konverterapp.com/hooks/w/…. Anyone with the URL can POST files to it to start a run — no API key — which makes it easy to connect Zapier, Make, n8n, forms or other servers. It accepts the same files, file_url and callback_url fields and answers 202 with the run id. Rotate it with { "webhook": "rotate" }, disable it with false. Limit: 30 runs per minute per webhook.
Schedules
Workflows that start with a input.url node can run on a schedule (times in UTC):
PATCH /v1/workflows/:id
{ "schedule": { "enabled": true, "every": "day", "hour": 6, "minute": 30 } }
// every: "hour" (uses minute) | "day" (hour, minute) | "week" (weekday 0=Sun…6, hour, minute)
// "schedule": null removes itCallbacks & signatures
When a run started with callback_url finishes, we POST { "type": "run.completed", "data": <run> } to it (up to 3 attempts on network errors / 5xx). The output.webhook node sends { "type": "workflow.output", "run_id", "files": [ { name, size, url } ] } — or, in files mode, a multipart body with a payload JSON field plus the files.
Every request carries Konverter-Signature: t=<unix>,v1=<hex> where v1 = HMAC-SHA256(secret, t + "." + body) (for multipart: the payload field). Find your signing secret on the API keys page. Verify it and reject old timestamps:
Callback and webhook URLs must be public http(s) addresses — private, loopback and internal networks are refused.
Account
/v1/mePlan, live credit balance and your limits/v1/operationsPublic, no key needed — every operation with params and credit prices/v1/nodesPublic — every workflow node typeOperation reference
Live from GET /v1/operations. Use the id as operation in a job, or as a node type in a workflow graph.