API Quickstart

Convert your first file with the CleverUtils API in 60 seconds. No signup, no API keys, no setup.

Step 1: Send a file

POST your file as multipart/form-data to /api/v1/convert with a to_format parameter telling us the target format.

cURL
curl -X POST https://cleverutils.com/api/v1/convert \
  -F "[email protected]" \
  -F "to_format=jpg"
Python
import requests

resp = requests.post(
    "https://cleverutils.com/api/v1/convert",
    files={"file": open("photo.heic", "rb")},
    data={"to_format": "jpg"},
)
job = resp.json()["data"]
print(job["job_id"], job["output"]["url"])
Node.js
import fs from "node:fs";

const form = new FormData();
form.append("file", new Blob([fs.readFileSync("photo.heic")]), "photo.heic");
form.append("to_format", "jpg");

const resp = await fetch("https://cleverutils.com/api/v1/convert", {
  method: "POST",
  body: form,
});
const { data: job } = await resp.json();
console.log(job.job_id, job.output.url);
PHP
<?php
$ch = curl_init("https://cleverutils.com/api/v1/convert");
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => [
        "file"      => new CURLFile("photo.heic"),
        "to_format" => "jpg",
    ],
]);
$resp = json_decode(curl_exec($ch), true);
$job = $resp["data"];
echo $job["job_id"], "\n", $job["output"]["url"];
Go
package main

import (
    "bytes"
    "encoding/json"
    "io"
    "mime/multipart"
    "net/http"
    "os"
)

func main() {
    body := &bytes.Buffer{}
    w := multipart.NewWriter(body)
    f, _ := os.Open("photo.heic")
    fw, _ := w.CreateFormFile("file", "photo.heic")
    io.Copy(fw, f)
    w.WriteField("to_format", "jpg")
    w.Close()

    req, _ := http.NewRequest("POST", "https://cleverutils.com/api/v1/convert", body)
    req.Header.Set("Content-Type", w.FormDataContentType())
    resp, _ := http.DefaultClient.Do(req)
    var out struct {
        Data struct{ JobID string `json:"job_id"` } `json:"data"`
    }
    json.NewDecoder(resp.Body).Decode(&out)
    println(out.Data.JobID)
}
Ruby
require 'net/http'
require 'json'

uri = URI('https://cleverutils.com/api/v1/convert')
req = Net::HTTP::Post.new(uri)
req.set_form(
  [
    ['file', File.open('photo.heic')],
    ['to_format', 'jpg']
  ],
  'multipart/form-data'
)
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http| http.request(req) }
job = JSON.parse(res.body)['data']
puts job['job_id'], job['output']['url']
Java
// Java 11+ HttpClient with multipart (using a small helper)
import java.net.URI;
import java.net.http.*;
import java.nio.file.*;

var boundary = "----CleverUtils" + System.currentTimeMillis();
var CRLF = "\r\n";
var file = Path.of("photo.heic");
var fileBytes = Files.readAllBytes(file);

var body = ("--" + boundary + CRLF
    + "Content-Disposition: form-data; name=\"to_format\"" + CRLF + CRLF + "jpg" + CRLF
    + "--" + boundary + CRLF
    + "Content-Disposition: form-data; name=\"file\"; filename=\"photo.heic\"" + CRLF
    + "Content-Type: application/octet-stream" + CRLF + CRLF).getBytes();
var tail = (CRLF + "--" + boundary + "--" + CRLF).getBytes();
var full = new byte[body.length + fileBytes.length + tail.length];
System.arraycopy(body, 0, full, 0, body.length);
System.arraycopy(fileBytes, 0, full, body.length, fileBytes.length);
System.arraycopy(tail, 0, full, body.length + fileBytes.length, tail.length);

var req = HttpRequest.newBuilder(URI.create("https://cleverutils.com/api/v1/convert"))
    .header("Content-Type", "multipart/form-data; boundary=" + boundary)
    .POST(HttpRequest.BodyPublishers.ofByteArray(full))
    .build();

var res = HttpClient.newHttpClient().send(req, HttpResponse.BodyHandlers.ofString());
System.out.println(res.body());
C#
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text.Json;

using var client = new HttpClient();
using var form = new MultipartFormDataContent();

var fileContent = new ByteArrayContent(File.ReadAllBytes("photo.heic"));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/octet-stream");
form.Add(fileContent, "file", "photo.heic");
form.Add(new StringContent("jpg"), "to_format");

var response = await client.PostAsync("https://cleverutils.com/api/v1/convert", form);
var json = await response.Content.ReadAsStringAsync();
var doc = JsonDocument.Parse(json).RootElement.GetProperty("data");
Console.WriteLine(doc.GetProperty("job_id").GetString());

Step 2: Read the response

The API returns a canonical JSON envelope with a job_id and links you can use to poll status and download the result.

JSON
{
  "data": {
    "job_id": "5f8c1a2e9d4b7c0e3f6a8b2d1e4c5f78",
    "status": "done",
    "output": {
      "filename": "photo_cleverutils.com.jpg",
      "size_bytes": 184523,
      "size_human": "180 KB",
      "url": "https://cleverutils.com/api/v1/jobs/5f8c.../output"
    },
    "links": {
      "self": "https://cleverutils.com/api/v1/jobs/5f8c...",
      "output": "https://cleverutils.com/api/v1/jobs/5f8c.../output"
    },
    "expires_at": "2026-04-10T14:32:11Z"
  }
}

For small files, conversion runs synchronously and the response already contains status: "done". For larger files, you'll get status: "processing" and need to poll the job until it's ready.

Step 3: Download the result

Use the URL from data.output.url to download the converted file. The API streams the file as a binary attachment.

cURL
curl -o photo.jpg https://cleverutils.com/api/v1/jobs/5f8c.../output

Polling for async jobs

If your file is large or the response shows status: "processing", poll the job endpoint every few seconds until it's done.

Python
import time, requests

while True:
    s = requests.get(f"https://cleverutils.com/api/v1/jobs/{job_id}").json()["data"]
    if s["status"] == "done":
        break
    if s["status"] == "error":
        raise RuntimeError(s)
    time.sleep(2)

out = requests.get(s["output"]["url"])
open("result.jpg", "wb").write(out.content)

Batch processing

To convert many files at once, use POST /api/v1/batch with up to 20 files in a single request.

cURL
curl -X POST https://cleverutils.com/api/v1/batch \
  -F "files[][email protected]" \
  -F "files[][email protected]" \
  -F "files[][email protected]" \
  -F "to_format=jpg"

Each file in the batch counts against your daily quota individually (max 20 files per request).

What's next?

Request a Feature

0 / 2000