Усе, що вміє сайт, — із вашого коду: конвертація, стиснення, нарізка, розпізнавання мовлення, імпорт за посиланням. JSON через HTTPS, ключ у заголовку, вебхук після готовності.
Базова адреса — https://convr.app/api/v1. Запити й відповіді — JSON в UTF-8, запитам із тілом потрібен заголовок Content-Type: application/json. Час — RFC 3339 в UTC, розміри — в байтах, тривалості — в секундах.
Звичайний сценарій:
створити завдання (POST /jobs) — з назвою й розміром файлу або з посиланням;
завантажити файл напряму в сховище за виданим посиланням і повідомити POST /jobs/{id}/uploaded;
дочекатися state: "done" — вебхуком або опитуванням GET /jobs/{id};
отримати посилання на результат: GET /jobs/{id}/download.
Файли не проходять через API-сервер: завантаження й скачування йдуть напряму в сховище та CDN, тож розмір файлу обмежує лише тариф.
Швидкий старт
export CONVR_KEY=cvk_…
# 1. create a job: what into what, and the file's name and size
curl -s -X POST https://convr.app/api/v1/jobs -H "Authorization: Bearer $CONVR_KEY" -H "Content-Type: application/json" \
-d '{"converter":"mov-mp4","options":{"quality":"medium"},
"file":{"name":"clip.mov","size":52428800}}'
# → {"batch_id":"…","job":{"id":"JOB","state":"awaiting_input",…},
# "upload":{"put_url":"PUT_URL","headers":{"Content-Type":"video/quicktime"}}}
# 2. upload the file straight to storage (no API key here)
curl -X PUT "PUT_URL" -H "Content-Type: video/quicktime" --data-binary @clip.mov
# 3. start it
curl -s -X POST https://convr.app/api/v1/jobs/JOB/uploaded -H "Authorization: Bearer $CONVR_KEY"
# 4. poll until "state":"done", then take the result
curl -s https://convr.app/api/v1/jobs/JOB -H "Authorization: Bearer $CONVR_KEY"
curl -s https://convr.app/api/v1/jobs/JOB/download -H "Authorization: Bearer $CONVR_KEY"
# → {"url":"https://…","expires_at":"…"}
ключ діє від імені акаунта: ті самі ліміти тарифу, та сама історія файлів;
працює лише на тарифах з API; якщо тариф скінчився — 403 plan_required;
ключ показується один раз, у нас зберігається лише його хеш; загубили — відкличте й створіть новий;
до 10 ключів на акаунт, відкликання діє миттєво;
ключем не можна керувати акаунтом: вхід, пароль, оплата, самі ключі — 403 not_for_keys.
Ніколи не вставляйте ключ у код сторінки чи мобільного застосунку: його звідти дістануть. Викликайте API зі свого сервера.
Ліміти
Частота: 120 запитів на хвилину на ключ (із запасом на короткі сплески). Понад — 429 rate_limited і заголовок Retry-After у секундах.
Тариф: розмір файлу, завдання на добу, одночасні завдання, тривалість відео, хвилини розпізнавання мовлення й термін зберігання результатів — як у вашого тарифу. Точні числа віддає GET /limits.
Посилання на завантаження живуть 15 хвилин, посилання на результат — 30 хвилин; нове посилання на результат можна отримати будь-коли, поки файл зберігається (expires_at завдання).
Опитуйте статус не частіше ніж раз на 2–3 секунди або використовуйте вебхуки.
Об’єкт завдання
Завдання — один файл, що перетворюється на один результат. Його повертають майже всі методи.
Етап у роботі: fetching, probing, converting, uploading.
progress
int
Прогрес, 0–100.
converter
string
Конвертер, наприклад mov-mp4.
input_name
string
Назва вихідного файлу.
input_size
int
Розмір вихідного файлу, байт (у посилання — після завантаження).
output_name
string
Назва результату.
output_size
int
Розмір результату, байт (коли готовий).
error
string
Код причини при failed.
expires_at
time
Коли файли буде видалено.
deleted
bool
Файли вже видалено.
result
object
Дані аналізу чи розпізнавання (лише в scan і transcribe).
input_ready
bool
Вихідний файл збережено, з ним можна запускати clips і transcribe.
Код
HTTP
Опис
awaiting_input
Чекає завантаження файлу.
queued
У черзі.
leased
Обробляється.
done
✓
Готово, можна завантажити.
failed
✓
Не вдалося, причина в error.
canceled
✓
Скасовано.
expired
✓
Термін зберігання минув або файл так і не завантажили.
Кінцеві стани позначено ✓ — після них завдання не змінюється.
Конвертери й налаштування
Конвертер називається <з>-<в>: mov-mp4, mp4-mp3, png-webp, docx-pdf, pdf-jpg. Повний список із налаштуваннями кожного — GET /registry (сотні пар форматів відео, аудіо, зображень і документів). Обирайте конвертер за розширенням вихідного файлу.
options — об'єкт «ключ: значення». Усе необов'язкове, пропущене бере значення за замовчуванням; невідомий ключ чи значення поза списком — 400 invalid_options. Типи налаштувань у /registry:
Тип
Опис
enum
string
Одне з values, наприклад "1080".
int
number
Ціле від min до max.
bool
boolean
true або false.
time
number | string
Секунди (12.5) або "хх:сс" / "гг:хх:сс".
text
string
Текст до max символів.
ranges
string
Відрізки "початок-кінець" у секундах через кому: "12-27,40.5-70".
Відео: 9:16, 4:5, 1:1, 16:9; поля blur, обрізка crop або smart (за обличчями).
trim_start / trim_end
time
Відео й аудіо: обрізати початок і кінець.
vcodec / fps
enum
Відео: h264 або h265; частота кадрів.
no_audio / volume
bool / int
Прибрати звук; гучність 0–300 %.
auto_subs / sub_lang / sub_style
bool / enum
Відео: розпізнати мовлення й впекти субтитри; мова; стиль (tiktok, karaoke, beast, lyrics…).
title / wm_text / wm_image
text / asset
Відео: заголовок, текстовий або картинка-водяний знак.
bitrate / sample_rate / channels
enum
Аудіо: 128–320 кбіт/с; 44100/48000; mono/stereo.
resize / image_quality / strip
enum / int / bool
Зображення: ширина; якість 1–100; прибрати EXIF.
pages / dpi
enum
PDF у картинки: all або first; 72/150/300.
gif_width / gif_fps
enum
GIF: ширина й частота кадрів.
Завдання
POST/jobs
Створити завдання
Передайте або file (потім завантажте його за upload), або url — тоді файл завантажимо ми й завдання одразу стане в чергу.
У відповіді upload — одне з двох:
put_url і headers — файл до 64 МБ завантажується одним PUT із цими заголовками;
part_size, part_count, parts — більший файл завантажується частинами по part_size байт (остання коротша); у parts перші 50 посилань, решта — через POST /jobs/{id}/parts.
Для url блок upload порожній.
Тіло запиту (JSON)
Тип
Опис
converterобов'язково
string
Конвертер із /registry, наприклад mov-mp4.
options
object
Налаштування конвертера.
file.name
string
Назва файлу (до 1024 символів). З file.size — замість url.
file.size
int
Точний розмір файлу в байтах.
url
string
Посилання замість файлу: пряме, Google Drive, Dropbox, YouTube, TikTok, Instagram, Vimeo, X.
webhook
string
Куди надіслати POST, коли завдання завершиться.
save_to_drive
bool
Покласти результат у хмару акаунта, коли він буде готовий.
drive_folder
string
Папка хмари для результату (за замовчуванням — верхній рівень).
batch_id
string
Додати завдання в наявний пакет (для ZIP і подій).
unknown_converter400 Немає такого конвертера — дивіться GET /registry.
invalid_options400 Невідоме налаштування або неприпустиме значення.
invalid_file400 Не вказано назву або розмір файлу.
invalid_url400 Посилання не http(s) або разом із ним передано файл.
invalid_webhook400 Адреса вебхука не http(s).
file_too_large413 Файл більший, ніж дозволяє тариф (limit — у байтах).
limit_active429 Забагато завдань виконується одночасно.
limit_daily429 Вичерпано добовий ліміт завдань.
speech_limit429 Вичерпано хвилини розпізнавання мовлення за 30 днів.
links_unavailable503 Завантаження з відеосайтів тимчасово недоступне.
PUT{put_url}
Завантажити файл
Запит іде напряму в сховище — без ключа API, із заголовками з upload.headers. Тіло — сам файл, рівно file.size байт. Посилання діє 15 хвилин.
Під час завантаження частинами: PUT кожної частини за її url, тіло — part_size байт (остання — залишок). Частини можна вантажити паралельно й у будь-якому порядку; збирати їх не треба.
Приклад
curl -X PUT "$PUT_URL" -H "Content-Type: video/mp4" --data-binary @video.mp4
# parts: split -b 16777216 big.mov part_ && upload part_aa to parts[0].url, …
curl -X PUT "$PART_1_URL" --data-binary @part_aa
POST/jobs/{id}/parts
Ще посилання на частини
Підписані посилання для частин від from до to включно, не більше 50 за раз.
Кожне завдання входить у пакет (batch_id у відповіді на створення). Передайте той самий batch_id у наступні POST /jobs, щоб стежити за ними одним потоком подій або запакувати в ZIP.
Server-Sent Events: спершу snapshot з усіма завданнями, потім job за кожної зміни. З’єднання тримається відкритим; після обриву перепідключайтеся — знову прийде snapshot.
Створює завдання-архів з усіх готових результатів пакета (від двох). Повторний виклик для того самого набору поверне той самий архів.
Відповідь
{ "id": "…", "state": "…", … } // the job object
Помилки
nothing_to_zip400 У пакеті менше двох готових результатів.
zip_too_large413 Архів вийшов би завеликим.
Хмара
Файли акаунта без строку зберігання, у папках, у межах місця тарифу. Завантаження — як у завдань: посилання на PUT або частини. Файл із хмари конвертується без повторного завантаження, результат лягає в ту саму папку.
GET/drive
Вміст папки
Папки й файли, шлях до папки, зайняте місце та квота.
file_too_large413 Файл більший, ніж дозволяє тариф (limit — у байтах).
POST/drive/files/{id}/convert
Конвертувати з хмари
Створює завдання, яке читає файл просто з хмари; результат кладеться в папку файлу (save: false — не класти).
Тіло запиту (JSON)
Тип
Опис
converterобов'язково
string
Конвертер для формату файлу.
options
object
Налаштування.
folder
string
Інша папка для результату.
Відповідь
{ "id": "…", "state": "…", … } // the job object
POST/jobs/{id}/drive
Результат — у хмару
Копіює готовий результат завдання в хмару (всередині сховища, без завантаження).
Тіло запиту (JSON)
Тип
Опис
folder
string
Папка.
Помилки
drive_full
not_ready409 Результату ще немає: завдання не в стані done.
GET/drive/files/{id}/url
Посилання на завантаження
Підписане посилання CDN на час.
Відповідь
{ "url": "https://…", "expires_at": "…" }
PATCH/drive/files/{id}
Перейменувати або перемістити
name та/або folder ("" — верхній рівень). Папки — PATCH /drive/folders/{id} з name і parent.
DELETE/drive/files/{id}
Видалити файл
Одразу звільняє місце. Папка видаляється разом із вмістом: DELETE /drive/folders/{id}.
Кліпи й мовлення
Відео завантажується один раз як завдання-аналіз <формат>-scan, після чого з нього можна скільки завгодно разів різати кліпи й розпізнавати мовлення — без повторного завантаження, поки завдання зберігається.
POST/jobs {"converter":"mp4-scan"}
Аналіз відео
Звичайне створення завдання з конвертером mp4-scan (mov-scan, mkv-scan…). Результат аналізу — у полі result готового завдання: гучність, зміни сцен і найкращі моменти для кліпів по 15, 30, 60 і 90 секунд з оцінкою 0–100. Аналіз завантаженого файлу не витрачає добовий ліміт завдань.
{id} — завдання scan. Один відрізок дає MP4, кілька — ZIP із кліпами. Доступні налаштування відео: aspect (за замовчуванням 9:16), fit, quality, заголовок, водяний знак, фільтри, музика.
Тіло запиту (JSON)
Тип
Опис
options.rangesобов'язково
ranges
До 20 відрізків, кожен 1–600 с.
options.*
Інші налаштування конвертера <формат>-clips з /registry.
not_uploaded409 Відео завдання scan ще не завантажено.
source_gone409 Завдання scan скасовано або воно минуло — файлу більше немає.
invalid_options400 Невідоме налаштування або неприпустиме значення.
limit_active429 Забагато завдань виконується одночасно.
limit_daily429 Вичерпано добовий ліміт завдань.
POST/jobs/{id}/transcribe
Розпізнати мовлення
{id} — завдання scan. Слова з таймкодами приходять у result готового завдання. До 20 хвилин мовлення за завдання; витрачає хвилини розпізнавання тарифу.
Тіло запиту (JSON)
Тип
Опис
options.rangesобов'язково
ranges
Які відрізки розпізнати.
options.lang
enum
auto, ru, uk, en, de, es, fr, it, pl, pt, tr, kk, be.
у job.done є download_url — посилання на результат на 30 хвилин; пізніше беріть нове через /download;
дайте будь-яку відповідь 2xx за 10 секунд. Інакше повторимо: через 10 с, 40 с, ~3 хв, ~11 хв і ~43 хв — усього 6 спроб;
адреса має бути публічною: внутрішні мережі й редиректи не підтримуються;
одна подія може прийти двічі (наприклад, через мережевий збій після вашої відповіді) — перевіряйте job.id.
Кожен виклик підписано: X-Convr-Signature: sha256=<hex> — HMAC-SHA256 сирого тіла запиту із секретом whsec_… з кабінету. Перевіряйте підпис до розбору JSON і порівнюйте за сталий час.
import hashlib, hmac, os
from flask import Flask, abort, request
SECRET = os.environ["CONVR_WEBHOOK_SECRET"].encode()
app = Flask(__name__)
@app.post("/hooks/convr")
def convr_hook():
sig = "sha256=" + hmac.new(SECRET, request.get_data(), hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, request.headers.get("X-Convr-Signature", "")):
abort(401)
e = request.get_json()
if e["event"] == "job.done":
print(e["job"]["id"], e["download_url"])
return "", 204
Помилки
Помилка запиту — HTTP-статус 4xx/5xx і тіло {"error": "код"}. Помилки лімітів мають ще limit — число, в яке ви вперлися. Спирайтеся на код, а не на текст: коди не змінюються.
HTTP/1.1 429 Too Many Requests
{"error": "limit_active", "limit": 10}
Код
HTTP
Опис
invalid_key
401
Ключ не знайдено, відкликано або акаунт вимкнено.
plan_required
403
Тариф акаунта без API.
not_for_keys
403
Цей метод доступний лише на сайті.
rate_limited
429
Понад 120 запитів на хвилину. Зачекайте Retry-After секунд.
limit_active
429
Забагато завдань виконується одночасно.
limit_daily
429
Вичерпано добовий ліміт завдань.
speech_limit
429
Вичерпано хвилини розпізнавання мовлення за 30 днів.
file_too_large
413
Файл більший, ніж дозволяє тариф (limit — у байтах).
json_required
415
Немає заголовка Content-Type: application/json.
bad_json
400
Тіло — не JSON або поля не того типу.
unknown_converter
400
Немає такого конвертера — дивіться GET /registry.
invalid_options
400
Невідоме налаштування або неприпустиме значення.
invalid_file
400
Не вказано назву або розмір файлу.
invalid_url
400
Посилання не http(s) або разом із ним передано файл.
invalid_webhook
400
Адреса вебхука не http(s).
not_found
404
Завдання немає або воно не ваше.
already_uploaded
409
Завдання вже запущено.
upload_incomplete
400
Файл (або частина) не завантажений повністю.
upload_size_mismatch
400
Завантажено не стільки байтів, скільки вказано в file.size.
not_ready
409
Результату ще немає: завдання не в стані done.
links_unavailable
503
Завантаження з відеосайтів тимчасово недоступне.
speech_unavailable
503
Розпізнавання мовлення тимчасово недоступне.
internal
500
Збій на нашому боці. Повторіть пізніше.
Якщо завдання завершилося з state: "failed", причина — в полі error завдання:
Код
Опис
input_invalid
Файл пошкоджений або не читається.
input_format_mismatch
Усередині файлу інший формат, ніж у конвертера.
input_no_stream
Немає потрібної доріжки (наприклад, звуку для mp4-mp3).
input_encrypted
Архів захищений паролем.
input_too_long
Відео довше, ніж дозволяє тариф.
input_too_large
Завантажений за посиланням файл більший за ліміт тарифу.
input_resolution
Завелика роздільна здатність.
target_too_small
Відео не вмістити в target_mb навіть із мінімальною якістю.
output_too_large
Результат вийшов більшим за ліміт.
convert_failed
Конвертація не вдалася (після повторів на різних серверах).
timeout
Обробка тривала задовго.
url_unreachable
Посилання не відкривається.
url_blocked
Посилання веде у внутрішню мережу — заборонено.
no_video
За посиланням немає відео (допис із фото).
url_private
Відео приватне, видалене, з віковим чи регіональним обмеженням.
site_blocked
Сайт тимчасово не віддає відео. Повторіть пізніше.
fetch_failed
Не вдалося отримати завантажений файл.
speech_too_long
Понад 20 хвилин мовлення в одному завданні.
worker_lost
Сервер обробки зник; завдання зазвичай перезапускається саме.