Étape 1 : Envoyer un fichier
Envoyez votre fichier en POST au format multipart/form-data vers /api/v1/convert avec un paramètre to_format indiquant le format cible.
curl -X POST https://cleverutils.com/api/v1/convert \
-F "[email protected]" \
-F "to_format=jpg"
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"])
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
$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"];
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)
}
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 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());
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());
Étape 2 : Lire la réponse
L'API renvoie une enveloppe JSON canonique avec un job_id et des liens utilisables pour interroger le statut et télécharger le résultat.
{
"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"
}
}
Pour les petits fichiers, la conversion s'exécute de manière synchrone et la réponse contient déjà status: "done". Pour les fichiers plus volumineux, vous obtiendrez status: "processing" et devrez interroger le job jusqu'à ce qu'il soit prêt.
Étape 3 : Télécharger le résultat
Utilisez l'URL de data.output.url pour télécharger le fichier converti. L'API diffuse le fichier en pièce jointe binaire.
curl -o photo.jpg https://cleverutils.com/api/v1/jobs/5f8c.../output
Polling pour les jobs asynchrones
Si votre fichier est volumineux ou si la réponse affiche status: "processing", interrogez le endpoint du job toutes les quelques secondes jusqu'à ce qu'il soit terminé.
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)
Traitement par batch
Pour convertir plusieurs fichiers en une fois, utilisez POST /api/v1/batch avec jusqu'à 20 fichiers dans une seule requête.
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"
Chaque fichier dans le batch est comptabilisé individuellement dans votre quota quotidien (20 fichiers maximum par requête).
Et ensuite ?
- Référence complète des endpoints — chaque endpoint, chaque paramètre, chaque champ de réponse.
- Limites de débit — quotas, en-têtes, et comment éviter la limitation.
- Codes d'erreur — chaque erreur possible et comment la résoudre.