API
The same tools as on the site, from your own code. Three steps: upload a file, create a job, take the result.
Access key
Create a key in your account and pass it as a header. The key is shown once at creation — save it right away.
Authorization: Bearer sk_ваш_ключIn a minute
1. Upload the file. The request body is the file itself, no multipart. The type is detected from content, not from the extension.
curl -X POST "https://formatika.app/api/v1/uploads?toolId=image.convert&filename=photo.png" \
-H "Authorization: Bearer $FORMATIKA_KEY" \
-H "Content-Type: application/octet-stream" \
--data-binary @photo.png
# {"id":"up_…","filename":"photo.png","mime":"image/png","bytes":820428}2. Create a job. Parameters are validated against the schema of the tool you named.
curl -X POST "https://formatika.app/api/v1/jobs" \
-H "Authorization: Bearer $FORMATIKA_KEY" \
-H "Content-Type: application/json" \
-d '{
"toolId": "image.convert",
"uploadIds": ["up_…"],
"params": { "format": "webp", "quality": 82 }
}'
# {"id":"job_…","status":"QUEUED","toolId":"image.convert","credits":0}3. Poll the status once a second. When it turns DONE, files carries the result links — signed and valid for 15 minutes.
curl "https://formatika.app/api/v1/jobs/job_…" -H "Authorization: Bearer $FORMATIKA_KEY"
# {"status":"DONE","progress":100,
# "files":[{"filename":"photo.webp","bytes":9352,"url":"/api/v1/files/…?exp=…&sig=…"}]}
curl -O -J "https://formatika.app/api/v1/files/…?exp=…&sig=…"Allowances and credits
Free: 10 jobs a day without an account, 50 with one. Beyond that a job costs credits; signing up grants 50. The credits field of the response says what was charged.
Tools
image.convertImage converter- Accepts:
- image/*, .heic, .heif, .avif
- Limit:
- 30 × 50 MB
Parameters
format· enum (jpeg | png | webp | avif | tiff)quality· number · default 82resize· group · optionalstripMetadata· boolean · default true
image.resizeResize image- Accepts:
- image/*, .heic, .heif, .avif
- Limit:
- 30 × 50 MB
Parameters
width· number · optionalheight· number · optionalfit· enum (inside | cover | contain) · default "inside"format· enum (same | jpeg | png | webp) · default "same"quality· number · default 85
image.compressCompress image- Accepts:
- image/*, .heic, .heif, .avif
- Limit:
- 30 × 50 MB
Parameters
targetKb· number · optionalquality· number · default 75format· enum (same | jpeg | webp) · default "same"maxWidth· number · optional
image.cropCrop image- Accepts:
- image/*, .heic, .heif, .avif
- Limit:
- 30 × 50 MB
Parameters
aspect· enum (1:1 | 4:3 | 3:4 | 16:9 | 9:16 | 3:2 | 2:3) · default "1:1"position· enum (center | top | bottom | left | right) · default "center"format· enum (same | jpeg | png | webp) · default "same"quality· number · default 88
image.rotateRotate image- Accepts:
- image/*, .heic, .heif, .avif
- Limit:
- 30 × 50 MB
Parameters
angle· enum (0 | 90 | 180 | 270) · default "90"flipHorizontal· boolean · default falseflipVertical· boolean · default falseformat· enum (same | jpeg | png | webp) · default "same"
Errors
You get a code, not a message: you compose the text yourself, in your own language. The HTTP status matches the code.