REST API · X-API-Key · webhook

Photo API для разработчиков

Удаление фона, апскейл до 1440p, восстановление лиц, AI-редактирование промптом, распознавание печатного и рукописного текста (OCR + Markdown) — единый REST с авторизацией X-API-Key, HMAC webhook и пакетной обработкой. От 20 копеек за фото, балансовая модель без подписок.

Что такое Photo API

Photo API — это REST-интерфейс ко всем инструментам нашей нейросети обработки фото. Если в личном кабинете вы загружаете фото мышкой и нажимаете «Обработать», то через API то же самое делает ваш код: один POST-запрос с полем operation — и в ответе JSON со ссылкой outputUrl на готовый файл (плюс callback на ваш URL, если передали webhookUrl). Это позволяет встроить удаление фона, апскейл и реставрацию прямо в интернет-магазин, мобильное приложение, Telegram-бот или конвейер маркетплейса.

Архитектура максимально простая: один заголовок X-API-Key, multipart POST с файлом, HTTP-статус и тело ответа. Никаких OAuth-флоу, JWT-токенов и SDK не требуется — работать можно с любым HTTP-клиентом, от curl в шелл-скрипте до http-нода в no-code-сценарии n8n.

API одинаковый и для маленьких задач (один фото-сниппет в минуту), и для конвейеров с тысячами изображений в день. Внутри — собственная GPU-инфраструктура с приоритетной очередью, балансовая модель в копейках и прозрачные цены: с вас списывается ровно то, что отработало. За неуспешные операции возврат на баланс происходит автоматически.

Photo API оптимизирован под пять сценариев: подготовка карточек товаров для маркетплейсов (Wildberries, Ozon, Яндекс Маркет), автоматизация контента в SMM, фоторедакторы и SaaS-инструменты, ML-пайплайны для генерации обучающих датасетов, оцифровка документов (распознавание сканов, PDF и рукописи в Markdown с сохранением структуры). Для каждого сценария ниже в разделе «Интеграции» — практические примеры.

Что можно сделать через API

Один endpoint обработки POST /v1/photos/process — операция задаётся полем operation — плюс сервисные методы для пакетов, статусов задач и баланса. Все они подчиняются одной авторизации и одной модели биллинга.

Удаление фона

operation=remove_bg. На входе любой JPG, PNG или WebP до 25 МБ — на выходе прозрачный PNG с alpha-каналом. Аккуратно захватывает волосы, мех, стекло и тонкие ткани. Один из самых быстрых методов: обычно от 300 мс до 2 секунд в зависимости от разрешения. Цена 20 копеек за фото — это в 100 раз дешевле зарубежных API за удаление фона ($0.20 за фото).

Апскейл до 1440p

operation=upscale. Три варианта resolution: 720, 1080, 1440 (2K). Внутри диффузионная модель 2025 года, в отличие от классических апскейлеров она не только увеличивает разрешение, но и дорисовывает текстуру и резкость. Дополнительный флаг restoreFace=true запускает восстановление лиц поверх апскейла — нужно, если на фото люди в дальнем плане. Цена от 1 ₽ за 720p до 3 ₽ за 1440p, восстановление лиц добавляет 30 копеек.

Восстановление лиц и реставрация

operation=restore_face. Реставрирует старые сканы и цифровые фото с шумом, царапинами, размытием. Два тарифа tier: normal (12 ₽, GPT Image 2 low quality) — для бытовых сканов и нормально сохранившихся снимков; pro (15 ₽, GPT Image 2 medium) — для сложных задач, заметно повреждённых фото. Опциональный флаг colorize=true раскрашивает чёрно-белые снимки; на цветных он безопасен и обычно даёт лёгкое выравнивание баланса.

Распознавание текста (OCR + Markdown)

Тот же endpoint /process с параметром operation=ocr_markdown или operation=ocr_handwritten. Извлекаем текст из фото, сканов, многостраничных PDF и текстовых документов (DOCX/RTF/ODT/HTML/TXT) — на выходе чистый Markdown со структурой: заголовки, абзацы, списки, таблицы, формулы LaTeX. Рукопись разбираем через multimodal Vision-нейросеть — курсив, нестандартный наклон, прописные буквы. Тарификация постраничная: печатный текст 2 ₽ за страницу, рукописный — 5 ₽. Готовый Markdown можно экспортировать в DOCX или PDF через /photos/recognize/export.

AI-редактирование промптом

operation=prompt_edit. Описываете правку текстом — «убрать прохожих с заднего плана», «сменить фон на пляж», «добавить кружку кофе на стол» — нейросеть применяет её к фото. Движок задаётся полем modelId: nano-banana-lite (12 ₽, бюджет), gpt-image-2-medium (15 ₽, аккуратные правки), nano-banana-2 (24 ₽, премиум-фотореализм), gpt-image-2-high (45 ₽, максимум качества) — цены за 1K, 2K/4K дороже. Можно передать PNG-маску в параметре mask для локального inpaint и до 4 файлов reference как образцы стиля.

Сервисные методы

  • GET /v1/credits/balance — баланс в копейках и рублях. Используйте перед массовой обработкой, чтобы знать сколько ещё влезет.
  • GET /v1/photos/jobs/{id} — статус задачи. Возвращает pending / processing / done / failed + ссылку на результат при done.
  • POST /v1/photos/batch — отправить пачку фото на асинхронную обработку. До 50 файлов за раз, опциональный webhook callback.
  • GET /v1/photos/batches/{id} — прогресс пачки: done/failed счётчики и список jobs.
  • GET /v1/photos/batches/{id}/manifest.json — манифест: имена файлов и outputUrl по каждому job.
  • GET /v1/photos/batches/{id}/download — ZIP со всеми результатами (формат png или webp).

Что в API «из коробки»

X-API-Key auth

Ключи формата pp_<24 символа nanoid> с SHA-256 хэшем в базе. Создаются в ЛК, показываются один раз — храните как пароль.

Webhook callback

Передайте webhookUrl — по завершении пришлём POST с событием job.completed / job.failed / batch.done и подписью X-Webhook-Signature (HMAC-SHA256).

Rate limits

60 запросов в минуту на ключ по умолчанию — лимит задаёте сами при создании ключа (до 10 000 RPM). Плюс общий лимит 100 запросов в минуту с одного IP.

Один endpoint

Вся обработка — через POST /v1/photos/process с полем operation. Один контракт на все операции. OpenAPI-спецификация — по запросу в support@photopanda.ru.

Аутентификация

Все запросы к Photo API авторизуются заголовком X-API-Key с вашим ключом. Других механизмов нет: ни OAuth, ни сессионных кук — это упрощает интеграцию и сокращает сетевые roundtrip-ы. Запрос без ключа или с невалидным ключом сразу отдаёт 401 Unauthorized без раскрытия деталей.

Как получить ключ

Зарегистрируйтесь, зайдите в раздел API-ключи личного кабинета и нажмите «Создать ключ». Полная строка вида pp_3X9k...vQ2 показывается ровно один раз — скопируйте и сохраните в менеджер секретов (1Password, Bitwarden, AWS Secrets Manager, GitHub Actions Secrets и т.п.). В базе у нас хранится только SHA-256 хэш, восстановить ключ потом невозможно.

Ротация и отзыв

Количество ключей на аккаунт не ограничено — удобно разделять по средам (dev, staging, prod) и проектам. Любой ключ можно отозвать в один клик из ЛК — после отзыва он немедленно перестаёт работать, существующие batch-задачи не прерываются. Для регулярной ротации создаёте новый ключ заранее, переключаете окружение, потом отзываете старый.

Параметры ключа

При создании ключа задаются: имя (для учёта по проектам), персональный rate limit rateLimitRpm (по умолчанию 60, до 10 000 запросов в минуту) и опциональный срок действия expiresInDays — по истечении ключ перестаёт работать автоматически. Каждый ключ даёт доступ ко всем методам публичного API и списывает операции с баланса владельца.

Базовый URL и версионирование

Все запросы публичного API идут на https://photopanda.ru/api/v1/v1/. Двойной сегмент /v1/v1 — не опечатка, а особенность роутинга: первый v1 — общий префикс всего API сервиса, второй — версия публичного API для внешних интеграций. Копируйте пути из примеров как есть. Единственное исключение — POST /api/v1/photos/recognize/export (экспорт OCR-результата): он живёт без второго v1.

HTTPS обязателен — HTTP отдаёт 308 Permanent Redirect, не оставляйте боевые интеграции на голом HTTP. Подключайтесь напрямую к продовому домену, никаких дополнительных балансировщиков и регионов настраивать не нужно: GPU-инфраструктура и БД находятся в РФ, географически близко к большинству российских клиентов.

Мы гарантируем стабильный контракт в рамках мажорной версии — поля не удаляются, типы не меняются, новые опциональные параметры добавляются без break-changes. О планируемых изменениях сообщаем в Telegram-канале и через дев-рассылку на привязанный email.

Sync vs Async — какой режим выбрать

Photo API поддерживает два режима работы. В sync режиме (POST /v1/photos/process) вы держите соединение открытым до результата — удобно для одного фото и быстрых операций (удаление фона, апскейл). Под капотом GPU работает через job-queue: даже при пиковой нагрузке запрос встанет в очередь и дождётся GPU. Соединение держится до ~3 минут (с запасом на тяжёлые операции вроде апскейла 1440p + восстановления лиц), обычно ответ приходит за 0.3–2 секунды для лёгких операций и 10–40 секунд для AI-правок. Установите HTTP-клиенту таймаут не менее 3 минут.

В async режиме (POST /v1/photos/batch) вы сразу получаете batchId и jobIds в ответе 202, а результат приходит позже — через webhook на ваш URL (поле webhookUrl) либо при опросе GET /v1/photos/batches/{id}. Это основной режим для пакетной обработки: nano-banana-2 или GPT Image 2 high могут занимать до 40 секунд на фото, а батч на 50 файлов — десятки минут.

Когда использовать sync

  • Один пользователь нажал «обработать» в вашем приложении и ждёт ответ.
  • Telegram-бот: пользователь кинул фото, нужно вернуть результат в том же чате.
  • Удаление фона, апскейл 720p — операции до 2 секунд.
  • Прямой POST из браузера через ваш бэкенд-прокси (но не из самого браузера — ключ нельзя светить).

Когда использовать async

  • Маркетплейсы — выгрузка карточек пачками по 50 за запрос (число запросов не ограничено).
  • Фоновая обработка в SaaS — пользователь загружает, идёт по своим делам, забирает позже.
  • GPT Image 2 high и тяжёлые промпт-правки — до 40 секунд на фото.
  • CI/CD пайплайны и cron — там async проще для retry-логики.

Полный пример batch-сценария с опросом статуса и скачиванием ZIP — ниже в блоке «Примеры кода».

Webhook callback

Передайте поле webhookUrl в /process или /batch — после завершения обработки мы пришлём POST на ваш URL с событием job.completed, job.failed или batch.done и заголовком X-Webhook-Signature вида sha256=… — это HMAC-SHA256 от сырого тела запроса, подписанный персональным webhook-секретом вашего API-ключа (whsec_… из личного кабинета).

Что приходит

JSON вида {event, data, timestamp}. Для job: jobId, status, type, outputUrl, durationMs. Для batch: batchId, счётчики done/failed и готовые downloadUrl / manifestUrl.

Одна доставка

Webhook отправляется один раз с таймаутом 10 секунд, без автоматических повторов. Результат не теряется: статус всегда доступен по GET /v1/photos/jobs/{id} и GET /v1/photos/batches/{id} — стройте на них fallback-опрос.

Проверка достоверности

Тело подписано X-Webhook-Signature (HMAC-SHA256). Каждому API-ключу выдаётся персональный webhook-секрет whsec_… (показывается в личном кабинете при создании ключа и при ротации). Сверьте подпись — и можно доверять событию без лишних запросов.

Ключи, созданные до июня 2026

Персональный webhook-секрет появился в июне 2026 года. У API-ключей, созданных раньше, его нет — такие ключи подписываются устаревшим общим секретом, и проверить подпись их вебхуков по whsec_… нельзя. Сгенерируйте секрет кнопкой ротации в личном кабинете (раздел «API-ключи»): после этого вебхуки ключа начнут подписываться вашим персональным whsec_…, и проверка по нему заработает.

Пример входящего callbackhttp
POST /hooks/panda HTTP/1.1
Host: example.com
Content-Type: application/json
X-Webhook-Signature: sha256=8f3a...e7d1
X-Webhook-Event: job.completed
X-Webhook-Timestamp: 2026-06-10T12:34:57.276Z
User-Agent: PhotoPanda-Webhook/1.0

{
  "event": "job.completed",
  "data": {
    "jobId": "550e8400-e29b-41d4-a716-446655440000",
    "status": "done",
    "type": "remove_bg",
    "outputUrl": "https://photopanda.ru/files/<userId>/<uuid>.png",
    "durationMs": 487
  },
  "timestamp": "2026-06-10T12:34:57.276Z"
}

Защита от replay-атак

Помимо подписи мы передаём X-Webhook-Timestamp с ISO-меткой отправки (она же поле timestamp в теле). Отбрасывайте запросы старше 5 минут и сверяйте jobId со своим списком отправленных задач — неизвестные id игнорируйте.

Rate limits и квоты

По умолчанию 60 запросов в минуту на каждый API-ключ. Лимит персональный: задаётся полем rateLimitRpm при создании ключа в ЛК — до 10 000 RPM. Считается по минутным окнам в Redis; при превышении приходит 429 Too Many Requests с деталями лимита в теле ответа.

Дополнительно действует общий лимит 100 запросов в минуту с одного IP на весь API. Если ваша интеграция шлёт запросы с одного сервера и упирается в него — напишите в support@photopanda.ru с описанием нагрузки.

Справочник endpoint-ов

POST/api/v1/v1/photos/processот 20 коп

Обработка одного фото (sync) — все операции

Единый endpoint: операция задаётся полем operation. Держит соединение до результата и возвращает JSON с outputUrl на готовый файл (для OCR — поле outputText). При ошибке обработки деньги возвращаются на баланс автоматически.

filemultipart/form-data
Файл JPG/PNG/WebP до 25 МБ (для OCR также PDF/DOCX/DOC/RTF/ODT/HTML/TXT)
operationstring
remove_bg | upscale | restore_face | prompt_edit | ocr | ocr_markdown | ocr_handwritten
resolutionstring (optional)
upscale: 720 | 1080 | 1440. prompt_edit: 1K | 2K | 4K (default 1K)
restoreFaceboolean (optional)
Для upscale: доп. восстановление лиц (+30 коп)
tiernormal | pro (optional)
Для restore_face: normal = 12 ₽ (default), pro = 15 ₽
colorizeboolean (optional)
Для restore_face: колоризация ч/б, default true (безопасно для цветных)
colorizeStylevintage | modern (optional)
Стиль колоризации, default vintage
promptstring (optional)
Для prompt_edit: описание правки, до 2000 символов
modelIdstring (optional)
Для prompt_edit: nano-banana-2 | gpt-image-2-low | gpt-image-2-medium | gpt-image-2-high
referencefile (optional, до 4)
Для prompt_edit: референсы стиля/объекта
maskfile (optional)
Для prompt_edit: ч/б PNG-маска inpaint (белое = редактировать)
ocrLangstring (optional)
Для operation=ocr: ru (default) | en | ch | japan | korean | german | french | arabic
webhookUrlstring (optional)
URL для POST-callback о завершении (event job.completed / job.failed)
POST/api/v1/v1/photos/batchпо операциям

Пакетная обработка (async)

До 50 файлов одним запросом (суммарно до 500 МБ), pre-charge сразу за все, обработка в очереди. Ответ 202: batchId + jobIds. Статус — GET /batches/{id}, результаты — ZIP через /batches/{id}/download. Параметры операции те же, что у /process.

filesmultipart/form-data (multiple)
До 50 файлов
operationstring
Одна операция на всю пачку: remove_bg | upscale | restore_face | prompt_edit | ocr_markdown | ocr_handwritten
referencefile (optional, до 4)
Общие референсы для всех jobs (prompt_edit)
webhookUrlstring (optional)
POST-callback c event batch.done по завершении пачки
GET/api/v1/v1/photos/batches/{batchId}

Статус пакета

Прогресс пачки: status, totalJobs / doneJobs / failedJobs, totalCostKop и список jobs с outputUrl у готовых.

batchIdstring (UUID)
ID пакета из ответа POST /batch
GET/api/v1/v1/photos/batches/{batchId}/manifest.json

Манифест пакета

Список файлов пачки: jobId, inputFilename, outputFilename (как будет в ZIP), outputUrl, status, error.

batchIdstring (UUID)
ID пакета
formatpng | webp (optional)
Целевой формат для outputFilename, default png
GET/api/v1/v1/photos/batches/{batchId}/download

Скачать результаты пакета (ZIP)

ZIP со всеми успешными результатами. Имена файлов — из исходных имён. 409, пока пакет ещё обрабатывается.

batchIdstring (UUID)
ID пакета
formatpng | webp (optional)
Формат файлов в архиве, default png
GET/api/v1/v1/photos/jobs/{id}

Статус задачи

Состояние отдельного job: pending / processing / done / failed + outputUrl у готового.

idstring (UUID)
ID задачи (из ответа /process или jobIds батча)
GET/api/v1/v1/credits/balance

Баланс

Текущий баланс: balanceKop, balanceRub, totalSpentKop, totalTopupKop. Используйте для предварительной проверки перед массовой обработкой.

POST/api/v1/photos/recognize/export

Экспорт результата распознавания

Конвертирует Markdown-результат OCR в файл для скачивания: MD / TXT / DOCX / PDF. Без авторизации (используется виджетами сайта). Путь без двойного v1.

textstring (JSON body)
Распознанный текст (Markdown)
formatmd | txt | docx | pdf
Целевой формат
filenamestring (optional)
Имя файла без расширения

Примеры кода

Минимальные, рабочие сниппеты под основные стеки. Замените pp_YOUR_KEY_HERE на свой ключ из ЛК и запускайте.

cURL · sync удаление фонаbash
curl -X POST https://photopanda.ru/api/v1/v1/photos/process \
  -H "X-API-Key: pp_YOUR_KEY_HERE" \
  -F "file=@/path/to/photo.jpg" \
  -F "operation=remove_bg"

# Ответ — JSON:
# {
#   "id": "550e8400-...",
#   "status": "done",
#   "type": "remove_bg",
#   "outputUrl": "https://photopanda.ru/files/<userId>/<uuid>.png",
#   "costKop": 20,
#   "durationMs": 487
# }

# Скачать готовый PNG:
curl -o photo-no-bg.png "https://photopanda.ru/files/<userId>/<uuid>.png"
cURL · batch апскейл + статус + ZIPbash
# 1. Отправить пачку (до 50 файлов) — ответ 202 сразу
curl -X POST https://photopanda.ru/api/v1/v1/photos/batch \
  -H "X-API-Key: pp_YOUR_KEY_HERE" \
  -F "operation=upscale" \
  -F "resolution=1080" \
  -F "webhookUrl=https://example.com/hooks/panda" \
  -F "files=@photo1.jpg" \
  -F "files=@photo2.jpg" \
  -F "files=@photo3.jpg"

# Ответ: { "batchId": "...", "jobIds": [...], "totalJobs": 3,
#          "totalCostKop": 600, "status": "pending", "statusUrl": "..." }

# 2. Проверить статус
curl -H "X-API-Key: pp_YOUR_KEY_HERE" \
  https://photopanda.ru/api/v1/v1/photos/batches/BATCH_ID

# 3. Скачать все результаты одним ZIP (после завершения)
curl -H "X-API-Key: pp_YOUR_KEY_HERE" -o results.zip \
  "https://photopanda.ru/api/v1/v1/photos/batches/BATCH_ID/download?format=png"
cURL · OCR — PDF в Markdown + экспорт в DOCXbash
# Распознать PDF в Markdown (печатный текст, 2 ₽ за страницу)
curl -X POST https://photopanda.ru/api/v1/v1/photos/process \
  -H "X-API-Key: pp_YOUR_KEY_HERE" \
  -F "file=@invoice.pdf" \
  -F "operation=ocr_markdown"

# Ответ:
# {
#   "id": "550e8400-...",
#   "status": "done",
#   "type": "ocr_markdown",
#   "outputText": "# Счёт №42\n\n| Услуга | Цена |\n|---|---|\n| ... |",
#   "costKop": 1200,
#   "durationMs": 9120
# }

# Скачать результат как .docx (endpoint без двойного v1, без auth)
curl -X POST https://photopanda.ru/api/v1/photos/recognize/export \
  -H "Content-Type: application/json" \
  -d '{"text":"# Счёт №42\n\n...","format":"docx","filename":"invoice"}' \
  --output invoice.docx
Python · sync удаление фонаpython
import requests

API_URL = "https://photopanda.ru/api/v1/v1/photos/process"
API_KEY = "pp_YOUR_KEY_HERE"

with open("photo.jpg", "rb") as f:
    r = requests.post(
        API_URL,
        headers={"X-API-Key": API_KEY},
        files={"file": f},
        data={"operation": "remove_bg"},
        timeout=180,
    )
r.raise_for_status()
job = r.json()  # {"id", "status", "outputUrl", "costKop", ...}

png = requests.get(job["outputUrl"], timeout=60)
with open("photo-no-bg.png", "wb") as out:
    out.write(png.content)
print("Saved photo-no-bg.png, cost:", job["costKop"], "kop")
Python · batch + опрос статуса + ZIPpython
import time, requests

API_BASE = "https://photopanda.ru/api/v1/v1/photos"
HEADERS = {"X-API-Key": "pp_YOUR_KEY_HERE"}

# 1. Отправляем пачку на обработку (до 50 файлов)
def submit_batch(paths):
    files = [("files", (p, open(p, "rb"))) for p in paths]
    data = {"operation": "upscale", "resolution": "1080"}
    r = requests.post(f"{API_BASE}/batch", headers=HEADERS,
                      data=data, files=files, timeout=180)
    r.raise_for_status()
    return r.json()  # {"batchId": "...", "jobIds": [...], ...}

# 2. Поллим статус до завершения
def wait_batch(batch_id):
    while True:
        b = requests.get(f"{API_BASE}/batches/{batch_id}",
                         headers=HEADERS, timeout=30).json()
        if b["status"] not in ("pending", "processing"):
            return b
        time.sleep(5)

# 3. Скачиваем ZIP со всеми результатами
def download_zip(batch_id, path="results.zip"):
    r = requests.get(f"{API_BASE}/batches/{batch_id}/download",
                     headers=HEADERS, timeout=300)
    r.raise_for_status()
    open(path, "wb").write(r.content)

batch = submit_batch(["p1.jpg", "p2.jpg", "p3.jpg"])
result = wait_batch(batch["batchId"])
print(result["doneJobs"], "of", result["totalJobs"], "done")
download_zip(batch["batchId"])
Node.js · sync удаление фонаjavascript
import fs from "node:fs";

const API_URL = "https://photopanda.ru/api/v1/v1/photos/process";
const API_KEY = "pp_YOUR_KEY_HERE";

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

const res = await fetch(API_URL, {
  method: "POST",
  headers: { "X-API-Key": API_KEY },
  body: form,
});
if (!res.ok) throw new Error(`Error ${res.status}: ${await res.text()}`);
const job = await res.json(); // {id, status, outputUrl, costKop, ...}

const png = await fetch(job.outputUrl);
fs.writeFileSync("photo-no-bg.png", Buffer.from(await png.arrayBuffer()));
console.log("Saved photo-no-bg.png");
Node.js · webhook-приёмник (Express)javascript
import express from "express";
import crypto from "node:crypto";

// Webhook-приёмник c проверкой подписи.
// Payload: { event, data, timestamp }
// events: job.completed | job.failed | batch.done
// Заголовки: X-Webhook-Signature (sha256=...), X-Webhook-Event,
// X-Webhook-Timestamp (ISO 8601).

// Персональный секрет вашего API-ключа (whsec_...) из личного кабинета.
const WEBHOOK_SECRET = process.env.PHOTOPANDA_WEBHOOK_SECRET;

const app = express();
// ВАЖНО: подпись считается от СЫРОГО тела. Берём raw body, не json-парсер.
app.use("/hooks/panda", express.raw({ type: "*/*" }));

function verify(rawBody, header) {
  // header вида "sha256=<hex>"
  const expected = crypto
    .createHmac("sha256", WEBHOOK_SECRET)
    .update(rawBody)
    .digest("hex");
  const got = String(header || "").replace(/^sha256=/, "");
  // Сравнение в постоянное время — защита от timing-атак.
  const a = Buffer.from(got, "hex");
  const b = Buffer.from(expected, "hex");
  return a.length === b.length && crypto.timingSafeEqual(a, b);
}

app.post("/hooks/panda", async (req, res) => {
  if (!verify(req.body, req.get("X-Webhook-Signature"))) {
    return res.status(401).end(); // подпись не сошлась — игнорируем
  }

  const { event, data, timestamp } = JSON.parse(req.body.toString("utf8"));

  // Защита от replay: отбрасываем события старше 5 минут.
  if (Date.now() - Date.parse(timestamp) > 5 * 60_000) {
    return res.status(202).end();
  }

  if (event === "job.completed") {
    console.log("job", data.jobId, "done:", data.outputUrl);
  } else if (event === "job.failed") {
    console.error("job", data.jobId, "failed:", data.error);
  } else if (event === "batch.done") {
    console.log("batch", data.batchId, "->", data.downloadUrl);
  }

  res.status(204).end();
});
PHP · sync удаление фонаphp
<?php
$ch = curl_init('https://photopanda.ru/api/v1/v1/photos/process');
curl_setopt_array($ch, [
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER     => ['X-API-Key: pp_YOUR_KEY_HERE'],
    CURLOPT_POST           => true,
    CURLOPT_POSTFIELDS     => [
        'file'      => new CURLFile('photo.jpg', 'image/jpeg', 'photo.jpg'),
        'operation' => 'remove_bg',
    ],
]);
$json = curl_exec($ch);
$code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($code === 200) {
    $job = json_decode($json, true);
    // Скачиваем готовый файл по ссылке из ответа
    file_put_contents('photo-no-bg.png', file_get_contents($job['outputUrl']));
}

Интеграции и сценарии

Маркетплейсы — Wildberries, Ozon

Автоматическая подготовка карточек: удаление фона, апскейл до 1500×1500, контроль качества. Один API-ключ закрывает весь конвейер от выгрузки 1С до загрузки на МП.

Telegram-боты

Делайте свои боты-сервисы: фото от пользователя, POST /process с operation=remove_bg, результат обратно в чат. Прямой POST с базы аккуратнее, чем web-скрапинг, и не блокируется.

n8n, Zapier, Make

HTTP Request node с заголовком X-API-Key — и любой no-code сценарий получает обработку фото. Webhook отвечает на ответ, никаких опросов.

SaaS и фоторедакторы

Встраивайте удаление фона и апскейл в свой продукт. Балансовая модель прозрачна — клиент платит вам, вы платите нам по факту.

Интеграция с Wildberries и Ozon

Главный сценарий, ради которого вообще запускают Photo API — автоматизация подготовки карточек товаров для маркетплейсов. Типичный конвейер выглядит так: фотограф снял партию товара, файлы попадают в ваше хранилище (S3, локальный сервер), cron каждые 5 минут забирает новые файлы и шлёт в Photo API, результат складывается в папку «готово к выгрузке», после чего плагин ВБ/Ozon API публикует на маркетплейс с обновлёнными ссылками.

На Wildberries и Ozon одинаковые требования: главное фото 900×1200, белый или прозрачный фон, без водяных знаков, JPG или PNG до 10 МБ. Через наш API за два запроса (operation=remove_bg + при необходимости operation=upscale) получаете полностью готовое к загрузке фото. Стоимость одной карточки — 20 копеек, при объёме 1000 фото в день это 200 рублей.

Для прямой интеграции с MPstats, MPSeller, JVO, Stock-M и другими сервисами автоматизации МП у нас есть упрощённый flow: подключаете webhook нашего API к http-триггеру в их системе, и каждый загруженный файл проходит через обработку без вашего кода.

n8n, Make, Zapier — no-code

Photo API спроектирован под no-code платформы: HTTP Request node с заголовком X-API-Key покрывает любой сценарий. В n8n — нода HTTP Request, в Make — модуль HTTP, в Zapier — Webhooks by Zapier. Async-режим тоже подходит: возвращаемый webhook ловится тем же no-code инструментом через триггер «Webhook receive».

Готовые шаблоны для типовых задач — «удалить фон со всех файлов в Dropbox / Я.Диск», «обработать фото из формы Tilda», «авто-апскейл для постов Telegram», «pipeline маркетплейса» — лежат в соответствующих маркетплейсах n8n и Make. Если шаблона нет под вашу задачу — присылайте описание в support, добавим в библиотеку.

Telegram-боты

Бот-приёмник на aiogram / Telegraf / grammY: пользователь шлёт фото, бот делает file.download(), отправляет POST в наш API и возвращает ответ обратно как изображение. На бесплатном тарифе ВПС справится с десятками одновременных пользователей, потому что GPU-нагрузка — на нашей стороне. Цена для пользователя у вас может быть любой — мы списываем только себестоимость с вашего баланса.

Главное правило: ключ X-API-Key храните в переменных окружения и не светите в коде бота, особенно если репозиторий публичный. Для бизнес-аккаунтов мы можем привязать к ключу IP allowlist — после этого даже утёкший ключ не отработает с чужого сервера.

SaaS и фоторедакторы

Если вы делаете свой продукт — конструктор сайтов, фоторедактор, CRM с фото клиентов — Photo API закрывает «тяжёлую» часть обработки без необходимости арендовать GPU. Балансовая модель прозрачна для ваших пользователей: они платят вам по подписке/за запрос, вы платите нам по факту. Margin контролируете сами в коде — рекомендуем закладывать минимум 3–5× для покрытия маркетинга, поддержки и неуспешных операций.

Оцифровка документов (OCR + Markdown)

Через POST /v1/photos/process с operation=ocr_markdown вы получаете чистый Markdown из отсканированных счетов, договоров, чеков, накладных, технической документации. Структура сохраняется: заголовки, таблицы, абзацы, формулы LaTeX. Принимаем JPG/PNG/WebP, многостраничные PDF до 25 МБ, а также текстовые документы DOC/DOCX/RTF/ODT/HTML/TXT — они идут не через OCR, а через прямую конвертацию в Markdown без потери таблиц. Тарификация постраничная: 2 ₽ за каждую страницу PDF (число страниц считается до отправки на GPU, бюджет предсказуем).

Для рукописного контента (заметки, дневники, исторические документы, рукописные опросники) используйте operation=ocr_handwritten — multimodal Vision-нейросеть разбирает курсив, нестандартный наклон, прописные буквы, авто-определяет язык. Цена 5 ₽ за страницу. На выходе тот же Markdown, готовый к сохранению в базе или экспорту в DOCX/PDF через /photos/recognize/export (без дополнительной оплаты).

Типовые сценарии: автоматизация бухгалтерии (распознавание первички в учётной системе), оцифровка архивов в библиотеках и НИИ, ввод данных в CRM из бумажных опросников, RAG-индексация корпоративной документации, транскрибация рукописных записей в текст для LLM-промптов.

SDK и библиотеки

Официальных SDK пока нет — Photo API устроен так, что отдельный клиент не нужен: всё работает на стандартных HTTP-библиотеках вашего языка. Это сознательный выбор: SDK быстро устаревают, требуют сопровождения и часто скрывают полезные детали запросов. На уровне трёх строк requests.post, fetch или curl код понятнее и не зависит от чужой обёртки.

Если очень хочется лёгкий враппер — запросите OpenAPI-спецификацию в support@photopanda.ru и сгенерируйте клиент через openapi-generator-cli. Поддерживаются 50+ языков: Python, TypeScript, Go, Java, C#, Rust, Kotlin, Swift, Dart и другие. Сгенерированный код будет иметь типизированные модели и методы под все endpoint-ы.

Community-обёртки публикуйте на GitHub — мы добавим ссылку на них в эту страницу с указанием автора. Поддерживаемые сообществом библиотеки часто оказываются удобнее официальных за счёт идиоматики конкретного языка.

Цены на API-вызовы

Цены такие же, как в личном кабинете — отдельного тарифа «для API» не существует. Списание с баланса происходит после успешной обработки; при ошибке (5xx, NSFW-блокировка) деньги возвращаются автоматически.

ОперацияЦенаКомментарий
Удаление фона20 коп / фотоPNG с alpha-каналом, любые JPG/PNG/WebP
Апскейл 720p1 ₽ / фотоДиффузионная модель, до 1280×720
Апскейл 1080p2 ₽ / фотоДо 1920×1080, годится для соцсетей
Апскейл 1440p (2K)3 ₽ / фотоДо 2560×1440, маркетплейсы и печать
Восстановление лица — normal12 ₽ / фотоGPT Image 2 low quality
Восстановление лица — pro15 ₽ / фотоGPT Image 2 medium, тонкая реставрация
Промпт-редактирование — nano-banana-lite12 ₽ / фотоБюджетный режим (1K)
Промпт-редактирование — gpt-image-2 medium15 ₽ / фотоТочные правки (1K; 2K/4K дороже)
Промпт-редактирование — nano-banana-224 ₽ / фотоПремиум-фотореализм (1K; 2K/4K дороже)
Промпт-редактирование — gpt-image-2 high45 ₽ / фотоМаксимальное качество (1K; 2K/4K дороже)
OCR печатного текста2 ₽ / страницаMarkdown со структурой, фото/скан/PDF + DOCX/RTF/ODT/HTML/TXT
OCR рукописного текста5 ₽ / страницаMultimodal Vision-модель, авто-определение языка

Баланс пополняется через ЮKassa: карты МИР, Visa, Mastercard, SberPay, СБП. При пополнении на 500 ₽ и выше начисляется бонус от 5 до 20% — деталь на странице «Цены». Подписок и регулярных списаний нет: вы платите за фактический трафик и сами решаете, когда докинуть на баланс. Закрытие сценариев в стиле «забыл и продолжает списываться» исключено.

Для бизнес-клиентов выставляем счёт на оплату с НДС, ведём учёт расхода по проектам через теги в API-ключах, формируем ежемесячные отчёты. Договор-оферта и реквизиты — в разделе оферты.

Коды ошибок

КодНазваниеОписание
400Bad RequestНевалидные параметры запроса (operation, resolution, modelId), повреждённый файл или заблокировано safety-фильтром
401UnauthorizedОтсутствует X-API-Key, ключ невалиден, отозван или истёк
402Payment RequiredНедостаточно средств на балансе аккаунта
404Not FoundЗадача или пакет не найдены (или принадлежат другому аккаунту)
409ConflictПакет ещё обрабатывается — ZIP пока недоступен, опрашивайте статус
413Payload Too LargeФайл больше 25 МБ — уменьшите или сожмите
429Too Many RequestsПревышен rate limit ключа или общий лимит IP — подождите перед повтором
500Server ErrorВнутренняя ошибка; списанные за неуспешную операцию средства возвращаются автоматически

Частые вопросы по API

Какой формат API — REST или GraphQL?

REST + JSON / multipart. GraphQL не используем — у нас простая модель с предсказуемой стоимостью операций.

Можно ли получить тестовый ключ бесплатно?

При регистрации зачисляем 25 ₽ на баланс. Этого хватит на 125 удалений фона или 12 апскейлов 1080p — достаточно для всех проверок интеграции.

Есть ли SDK для Python, Node.js, Go, PHP?

Официальных пока нет, но Photo API устроен максимально просто: один заголовок X-API-Key и multipart POST. Готовые сниппеты есть выше для cURL, Python, Node.js и PHP — копируйте.

Какие лимиты по размеру и количеству фото?

До 25 МБ на файл и до 50 фото в одном batch-запросе (суммарно до 500 МБ). Sync-режим держит соединение до ~3 минут (хватает на самые тяжёлые операции — апскейл 1440p с восстановлением лиц, AI-редактирование с референсами); ставьте HTTP-клиенту таймаут не меньше. При большем объёме используйте batch — он async, число batch-запросов не ограничено.

Что будет если webhook упадёт или вернёт 500?

Сейчас webhook отправляется один раз (таймаут 10 секунд), автоматических повторов нет. Результат при этом не теряется: статус и outputUrl всегда доступны по GET /v1/photos/jobs/{id} и GET /v1/photos/batches/{id} — стройте на них fallback-опрос.

Как проверить подпись webhook и где взять секрет?

У каждого API-ключа свой webhook-секрет формата whsec_… — он показывается в личном кабинете один раз при создании ключа и при ротации (кнопка обновления секрета у ключа). Подпись в заголовке X-Webhook-Signature: sha256=<hex> — это HMAC-SHA256 от сырого тела запроса на этом секрете. Считайте HMAC на своей стороне и сравнивайте в постоянное время (crypto.timingSafeEqual). Пример приёмника на Node.js есть выше. Секрет потеряли — ротируйте, прежний сразу перестаёт действовать. Важно: ключи, созданные до июня 2026 года, своего webhook-секрета не имеют — нажмите ротацию в ЛК, чтобы сгенерировать его; до этого подпись вебхуков такого ключа проверить нельзя.

Можно ли передавать base64 или ссылку вместо файла?

Нет, сейчас принимается только multipart/form-data с бинарным полем file. Если исходник лежит по URL — скачайте его на своей стороне и отправьте файлом.

В каком формате возвращается распознанный текст?

Markdown — со структурой документа: заголовки (#, ##), списки, таблицы, формулы LaTeX. Поле outputText в JSON-ответе содержит готовый текст. Для скачивания в .docx или .pdf используйте POST /api/v1/photos/recognize/export с body {text, format}.

Как тарифицируются PDF и многостраничные документы?

Постранично. До отправки на GPU считаем число страниц в PDF и списываем 2 ₽ за каждую (печатный) или 5 ₽ за каждую (рукописный). Если страниц 0 или PDF битый — возвращается ошибка 400 без списания.

Какие форматы файлов принимает OCR?

Изображения: JPG/PNG/WebP. PDF до 25 МБ. А ещё текстовые документы DOC/DOCX/RTF/ODT/HTML/TXT — они идут не через OCR, а через прямую конвертацию в Markdown (без потери структуры таблиц и формул).

Как увеличить rate limit выше 60 RPM?

Лимит ключа задаётся при его создании в ЛК — поле rateLimitRpm, до 10 000 запросов в минуту. Дополнительно действует общий лимит 100 запросов в минуту с одного IP; если для вашей нагрузки его не хватает — напишите в support@photopanda.ru.

Безопасно ли хранить ключ на фронтенде?

Нет. X-API-Key даёт доступ к балансу и должен лежать только на сервере. Для браузерных интеграций используйте свой бэкенд как прокси либо короткоживущие токены через серверную выдачу.

Удаляются ли фото после обработки?

Исходники удаляются после обработки. Результаты хранятся и доступны по outputUrl и в истории личного кабинета около 30 дней, затем вычищаются. По запросу в поддержку удалим раньше.

Подходит ли API под 152-ФЗ и работу с персональными данными?

Сервера в РФ, обработка как платёжный сервис под 152-ФЗ, ЮKassa берёт на себя PCI DSS. Для фотобанков с фото людей рекомендуем заключать DPA — пишите в support.

Получите API-ключ за минуту

При регистрации зачисляем 25 ₽ на баланс — 125 удалений фона или 12 апскейлов 1080p для проверки интеграции. Без карты и подписки.

25 ₽ welcome бонус

Создайте фото с ИИ
за 30 секунд

AI-фотосессия по шаблону, генерация изображений нейросетью или обработка вашего фото — удаление фона, апскейл до 1440p, восстановление лиц. 10 ₽/день бесплатно без регистрации, +25 ₽ welcome бонусом — хватит на 125 удалений фона. Без карты, без подписки, без watermark.