Convert & compress files from your code.
One REST endpoint, one header. Send a file or a URL, poll for a signed download link. The same engines that power filewhirl.com — no JWT, no SDK required. The API is in early access — join the waitlist and we'll get you set up with a key.
x-api-key auth
No JWT, no Authorization header — call it from any backend.
Private by default
Files deleted within an hour; signed URLs only.
Usage-metered
Planned: a $29/mo plan + pay-as-you-go credits. Free during early access.
Authentication
The API is in early access. Request a key and you'll send it on every request like this:
x-api-key: ff_live_your_key_hereKeys start with ff_live_ and are shown only once. Keep them server-side — anyone with a key can spend your quota.
Create a job
POST https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api — upload a file as multipart, or send a public URL as JSON. The to field is the target format; pass the same format as the input to compress it. Returns 202 with an id, token and status_url.
curl -X POST https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api \
-H "x-api-key: ff_live_your_key_here" \
-F "file=@photo.png" \
-F "to=jpg"curl -X POST https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api \
-H "x-api-key: ff_live_your_key_here" \
-H "content-type: application/json" \
-d '{ "to": "mp3", "url": "https://example.com/clip.mp4" }'Poll for the result
GET https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api?id=…&token=… every ~1.5s until status is done or error. On success you get a signed output_url valid for one hour.
curl "https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api?id=JOB_ID&token=JOB_TOKEN" \
-H "x-api-key: ff_live_your_key_here"Full examples
const API = "https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api";
const KEY = process.env.FILEWHIRL_API_KEY;
// 1. Create a job (upload a file)
const form = new FormData();
form.append("file", fileBlob, "photo.png");
form.append("to", "jpg");
const res = await fetch(API, { method: "POST", headers: { "x-api-key": KEY }, body: form });
const { id, token, status_url } = await res.json();
// 2. Poll until done (every ~1.5s; outputs are ready within seconds-minutes)
let job;
do {
await new Promise((r) => setTimeout(r, 1500));
job = await (await fetch(status_url, { headers: { "x-api-key": KEY } })).json();
} while (job.status === "queued" || job.status === "processing");
if (job.status === "done") console.log("Download:", job.output_url);
else throw new Error(job.error);import os, time, requests
API = "https://fkgvpgpdkktikfzspnib.supabase.co/functions/v1/convert-api"
KEY = os.environ["FILEWHIRL_API_KEY"]
H = {"x-api-key": KEY}
# 1. Create a job (or pass JSON {"to": "...", "url": "..."} instead of a file)
with open("photo.png", "rb") as f:
r = requests.post(API, headers=H, files={"file": f}, data={"to": "jpg"})
job = r.json()
sid, token = job["id"], job["token"]
# 2. Poll until done
while True:
time.sleep(1.5)
s = requests.get(API, headers=H, params={"id": sid, "token": token}).json()
if s["status"] in ("done", "error"):
break
print(s.get("output_url") or s["error"])Responses & status codes
| Code | Meaning |
|---|---|
| 202 | Job created — returns { id, token, status, billing, status_url }. |
| 200 | Poll result — { status, output_url?, output_size?, engine?, error? }. |
| 400 | Bad request — missing `to`, or no file/url provided. |
| 401 | Invalid or missing x-api-key. |
| 402 | Quota exceeded — subscribe or buy credits ({ error, reason, hint }). |
| 404 | Unknown job id/token on a poll. |
| 500 | Server error (upload/metering/internal) — safe to retry. |
- Up to 2 GB per file.
- Output URLs are signed and expire after 1 hour.
- One usage unit per job; failed-to-queue jobs are auto-refunded.
- No JWT or Supabase header needed — just x-api-key.
Common questions
How do I get an API key?+
The API is in early access. Email hello@filewhirl.com to request a key — keys look like ff_live_… and are shown once, so store it securely. Self-serve signup and billing go live soon.
Do I need a Supabase or Authorization header?+
No. The endpoint is authenticated solely by the x-api-key header — no JWT, no Authorization, no apikey header. That's why it's safe to call from any backend.
What can I convert or compress?+
Anything the website supports — images, video, audio, documents and archives, plus same-format compression (e.g. to=jpg on a jpg re-encodes it smaller). The full format matrix is the same one powering filewhirl.com.
How is usage billed?+
One unit per job. The API plan includes a monthly allowance; once it's used up, jobs draw from pay-as-you-go credits. If neither has room the API returns 402 with a reason — you're never charged for a job that fails to queue (units are refunded on insert failure). During early access there's no charge.
How big can files be and how long are outputs available?+
Up to 2 GB per file. Output download URLs are signed and valid for 1 hour; both the upload and the result are deleted after that window.
Is there a rate limit?+
There's no hard HTTP rate limit today — throughput is governed by your plan's concurrency and monthly quota. Be a good citizen: poll a job's status every ~1.5s rather than in a tight loop.
Ready? Join the API waitlist · see pricing · browse the tools · OpenAPI spec · Postman collection.