File Converts API
A simple REST API for server-side conversions (PDF↔Office, table extraction, and more). Authenticate with an API key, create a job, stream progress, and download the result — or receive a signed webhook when it's done.
Authentication
Create a key in your account dashboard, then send it as an X-API-Key header. Call the API only from a server you control: an API key in browser JavaScript is readable by anyone who opens the page. If your users need to convert files in the browser, use the in-browser tools \u2014 those upload nothing and need no key at all. Keys are shown once — store them securely. The base URL is https://filetransmute-api.fly.dev.
Quickstart
cURL
# 1. Create a job (authenticate with your API key)
curl -X POST https://filetransmute-api.fly.dev/v1/jobs \
-H "X-API-Key: ak_live_…" \
-H "Idempotency-Key: $(uuidgen)" \
-F "tool=pdf-to-excel" \
-F "file=@invoice.pdf"
# → { "id": "job_…", "status": "queued", "events_url": "/v1/jobs/job_…/events" }
# 2. Poll status until "done" (or "failed"), then download.
# Jobs created with a key belong to your org: send the key on every call.
curl https://filetransmute-api.fly.dev/v1/jobs/job_… -H "X-API-Key: ak_live_…"
curl -o out.xlsx https://filetransmute-api.fly.dev/v1/jobs/job_…/download -H "X-API-Key: ak_live_…"JavaScript (Node)
// Node 18+ — run this on your server, never in browser code.
import { readFile, writeFile } from "node:fs/promises";
const auth = { "X-API-Key": process.env.FILE_CONVERTS_API_KEY };
const form = new FormData();
form.append("tool", "pdf-to-excel");
form.append("file", new Blob([await readFile("invoice.pdf")]), "invoice.pdf");
const res = await fetch("https://filetransmute-api.fly.dev/v1/jobs", {
method: "POST",
headers: { ...auth, "Idempotency-Key": crypto.randomUUID() }, // safe to retry
body: form,
});
if (!res.ok) throw new Error(`create failed: ${res.status} ${await res.text()}`);
const { id } = await res.json();
// Poll until the job finishes (or register a webhook instead).
let job;
do {
await new Promise((r) => setTimeout(r, 500));
job = await (await fetch(`https://filetransmute-api.fly.dev/v1/jobs/${id}`, { headers: auth })).json();
} while (job.status === "queued" || job.status === "running");
if (job.status !== "done") throw new Error(job.error ?? "conversion failed");
const out = await fetch(`https://filetransmute-api.fly.dev/v1/jobs/${id}/download`, { headers: auth });
await writeFile(job.output_name, Buffer.from(await out.arrayBuffer()));Python
import os, time, uuid, requests
auth = {"X-API-Key": os.environ["FILE_CONVERTS_API_KEY"]}
with open("invoice.pdf", "rb") as f:
r = requests.post("https://filetransmute-api.fly.dev/v1/jobs",
headers={**auth, "Idempotency-Key": str(uuid.uuid4())},
data={"tool": "pdf-to-excel"}, files={"file": f})
r.raise_for_status()
job_id = r.json()["id"]
# Poll until done. The key goes on every call: the job belongs to your org.
while True:
s = requests.get(f"https://filetransmute-api.fly.dev/v1/jobs/{job_id}", headers=auth).json()
if s["status"] in ("done", "failed"):
break
time.sleep(0.5)
if s["status"] == "failed":
raise RuntimeError(s["error"])
out = requests.get(f"https://filetransmute-api.fly.dev/v1/jobs/{job_id}/download", headers=auth)
out.raise_for_status()
open(s["output_name"], "wb").write(out.content)Endpoints
/v1/jobsCreate a conversion job (multipart: file, tool). Supports Idempotency-Key./v1/jobs/{id}Job status, progress, and output name./v1/jobs/{id}/eventsServer-Sent Events stream of live progress./v1/jobs/{id}/downloadDownload the finished file./v1/formatsSupported server tools and which are available./v1/usageYour org's jobs, bytes processed, and credits spent./v1/api-keysList your API keys./v1/api-keysCreate a key (secret shown once)./v1/webhooksList webhook endpoints./v1/webhooksRegister a webhook (signing secret shown once).Idempotency
Pass an Idempotency-Key header on POST /v1/jobs. A retry with the same key returns the original job (and never charges twice) — safe for network retries.
Webhooks
Register an endpoint at POST /v1/webhooks to receive job.completed and job.failed events. Each delivery is signed with your webhook secret in the X-FileTransmute-Signature header — verify it before trusting the payload:
import hmac, hashlib
# Python. Header: X-FileTransmute-Signature: sha256=<hex HMAC-SHA256 of the raw body>
# Use the raw request bytes — re-serialising parsed JSON changes them.
expected = "sha256=" + hmac.new(secret.encode(), raw_body, hashlib.sha256).hexdigest()
if not hmac.compare_digest(expected, request.headers.get("X-FileTransmute-Signature", "")):
abort(401)Rate limits
Every response includes X-RateLimit-Limit, X-RateLimit-Remaining, and X-RateLimit-Reset. When exceeded you get 429 with a Retry-After header.
Full interactive reference (OpenAPI / Swagger) is served at https://filetransmute-api.fly.dev/docs.