Fylvo
FYLVO API

Обработка файлов.
Из вашего приложения.

Конвертируйте файлы, запускайте инструменты и задавайте задачи ИИ через HTTP API сервиса.

Базовый адрес: Текущий адрес сервиса. Пути ниже указаны относительно него. JSON — для параметров и ответов, multipart/form-data — для загрузки файлов.

Сессия и доступ

Сначала выполните GET /api/catalog. Сервер выдаст cookie media_session. Сохраняйте её и передавайте во всех следующих запросах: задания, результаты и диалоги привязаны к этой сессии. API-ключи и Bearer-токены сейчас не используются.

Cookie действует до 30 дней и имеет атрибуты HttpOnly и SameSite=Strict; по HTTPS также Secure. Храните cookie как секрет. В браузере на том же домене она передаётся автоматически. POST-запросы с другого сайта запрещены; для внешней интеграции используйте свой сервер, cURL или Python.

Быстрый старт

Пример: PNG → JPG. Команды рассчитаны на Bash; в PowerShell используйте curl.exe и синтаксис переменных вашей оболочки. Замените базовый адрес адресом сервиса.

bash
BASE="https://media.example.com"
# 1. Получить каталог и сохранить сессию
curl --fail-with-body -c cookies.txt "$BASE/api/catalog"

# 2. Отправить операцию ПЕРВОЙ частью, затем файл
curl --fail-with-body -b cookies.txt "$BASE/api/jobs" \
  -F 'request={"target":"jpg"};type=application/json' \
  -F 'file=@photo.png' 

Сервер вернёт HTTP 202 и идентификаторы заданий. При конвертации нескольких файлов каждый получает своё задание — обработайте все элементы jobs.

JSON · пример
{"job_id":"0123456789abcdef0123456789abcdef","status":"pending","jobs":[{"job_id":"0123456789abcdef0123456789abcdef","name":"photo.png","label":"Конвертация → JPG","status":"pending"}]}
bash
# 3. Подставить job_id из ответа и проверять статус, например раз в 2 секунды
JOB_ID="0123456789abcdef0123456789abcdef"
curl --fail-with-body -b cookies.txt "$BASE/api/jobs/$JOB_ID"

# 4. Только после status=completed скачать результат
curl --fail-with-body -b cookies.txt "$BASE/api/jobs/$JOB_ID/download" -o result.jpg
Полный пример на Python (пакет requests)
Python
import time
import requests

base = "https://media.example.com"
with requests.Session() as client:
    response = client.get(f"{base}/api/catalog", timeout=30)
    response.raise_for_status()
    with open("photo.png", "rb") as source:
        response = client.post(f"{base}/api/jobs", files=[
            ("request", (None, '{"target":"jpg"}', "application/json")),
            ("file", ("photo.png", source, "image/png")),
        ], timeout=300)
    response.raise_for_status()
    for job in response.json()["jobs"]:
        job_id = job["job_id"]
        deadline = time.monotonic() + 600
        while True:
            response = client.get(f"{base}/api/jobs/{job_id}", timeout=30)
            response.raise_for_status()
            result = response.json()
            if result["status"] in {"failed", "cancelled"}:
                raise RuntimeError(result["error"])
            if result["status"] == "completed":
                break
            if time.monotonic() >= deadline:
                raise TimeoutError("Задание ещё выполняется; сохраните job_id")
            time.sleep(2)
        with client.get(base + result["download_url"], stream=True, timeout=300) as download:
            download.raise_for_status()
            with open(f"{job_id}.jpg", "wb") as output:
                for chunk in download.iter_content(65536):
                    output.write(chunk)

Операции и ИИ

Поле request содержит JSON с ровно одним из полей: target, task или prompt. Оно обязательно идёт перед частями file. Для нескольких файлов повторите поле file, максимум 20; конкретный инструмент или ИИ может иметь меньший лимит.

JSON · альтернативные варианты request
{"target":"jpg"}

{"task":{"action":"image.resize","parameters":{"width":800}}}

{"prompt":"Преобразуй изображение в JPG"}

{"prompt":"Теперь уменьши ширину до 800 пикселей","conversation_id":"0123456789abcdef0123456789abcdef"}

Допустимые действия, параметры и расширения проверяйте в каталоге ниже. Для ИИ нужен ai_configured: true; длина prompt — 1–4000 символов. Сохраняйте conversation_id из ответа, чтобы продолжить диалог с ранее загруженными файлами без повторной загрузки.

Ответ ИИ содержит conversation_id, message и jobs. HTTP 202 означает, что созданы задания; HTTP 200 может означать уточнение без задания. Всегда читайте сообщение и список jobs.

Отмена и повтор

POST /api/jobs/{job_id}/cancel с пустым JSON {} отменяет задание текущей сессии. Ответ содержит status и cancel_requested. Выполняющееся задание остаётся активным до остановки процесса, затем получает статус cancelled; ожидающее задание отменяется сразу. Для завершённого задания запрос ничего не меняет. Проверяйте статус через GET до завершения отмены.

В GET /api/jobs/{job_id}/details поле settings содержит сохранённые настройки без паролей. POST /api/jobs/{job_id}/retry создаёт новое задание из сохранённых исходников с теми же параметрами. Сценарии загрузки: website_photos, send_documents, recording_text.

Справочник методов

Все методы, кроме каталога, требуют cookie сессии. Идентификаторы — 32 шестнадцатеричных символа. Параметры POST ниже передаются как JSON, кроме загрузки /api/jobs.

Метод и путьПараметры и результат
GET/api/catalogФорматы, инструменты, лимиты и доступность ИИ. Создаёт сессию при её отсутствии.
POST/api/jobsmultipart: request + file. Конвертация/инструмент: 202, job_id, status, jobs. ИИ: 200 или 202.
GET/api/jobs/{job_id}Статус: job_id, status, error, download_url, output_name, output_size (байты), steps. До готовности download_url равен null.
GET/api/jobs/{job_id}/downloadБинарный файл результата. 409 — ещё не готов; 410 — файл недоступен.
GET/api/jobsСписок: jobs, counts, total, offset, limit. Query: limit (1–100, по умолчанию 30), offset, q, status (all/active/completed/failed), visibility (visible/archived), sort (newest/oldest/name/size), actions (через запятую, уточняет поиск q).
GET/api/jobs/{job_id}/detailsПодробности, available, can_retry, hidden, исходные имена и миниатюры.
GET/api/jobs/{job_id}/thumbnailИзображение миниатюры; query source — индекс исходного файла с нуля. 404, если превью недоступно.
POST/api/jobs/{job_id}/retryПовтор завершённого задания. Ответ 202 с jobs и новым job_id. Проверяйте can_retry; исходные файлы должны быть доступны.
POST/api/jobs/archive{"ids":["job_id"],"hidden":true} — архивировать; false — восстановить. До 100 ID; только завершённые задания. Ответ: updated, hidden.
POST/api/jobs/clearАрхивирует все завершённые видимые задания. Ответ: updated, hidden. Выполняющиеся задания сохраняются.
POST/api/downloads{"ids":["job_id"]} — ZIP из 1–20 готовых результатов.
POST/api/downloads/all{"visibility":"visible"} или {"visibility":"archived"} — ZIP всех доступных готовых результатов выбранной области.
GET/api/ai/{conversation_id}Диалог: conversation_id, history, files. 410 — диалог истёк.
GET/api/requestsИстория ИИ-запросов. Query: q, status (all/queued/error/clarification/processing/saved), limit (1–100, по умолчанию 20), offset.
GET/api/requests/{request_id}Подробности ИИ-запроса и source_thumbnails.
GET/api/requests/{request_id}/thumbnail/{index}Миниатюра исходного файла ИИ-запроса; index с нуля.

Форматы и инструменты

Данные загружаются из GET /api/catalog текущего сервиса. Используйте ключи форматов как target, ключи инструментов как task.action, а поля инструмента — внутри task.parameters.

Загружаем каталог…

Статусы и ошибки

pending → processing → completed — успешная обработка. failed — ошибка задания, её описание находится в error. Принятие запроса с HTTP 202 ещё не означает успешную обработку файла.

Ошибки HTTP возвращаются в JSON: {"error":"Описание ошибки"}.

400
Неверные параметры, формат или набор файлов.
403
Нет сессии или POST отправлен с другого сайта.
404
Объект не найден или принадлежит другой сессии.
408
Истекло время загрузки.
409
Операция несовместима с текущим состоянием задания.
410
Файл или диалог больше недоступен.
413
Превышен суммарный лимит загрузки.
503
Очередь заполнена. Повторите позже с задержкой.

Лимит байтов для всей загрузки — max_input_bytes, лимит файлов ИИ — ai_max_files, ёмкость очереди — max_batch_jobs. Значения зависят от настроек сервиса. При потере ответа на POST сначала проверьте историю заданий: повтор запроса может создать дубликаты.