pdfapi

Ошибки и повторы

Ошибку видно по HTTP-статусу, а причину — по полю error в JSON. На error стоит опираться в коде, message — для журнала и человека, он написан по-русски. У 401 и 429 поля message нет, поэтому строить логику на нём не стоит. Например:

json
{
  "error": "quota_exceeded",
  "message": "Лимит страниц исчерпан"
}

Коды ошибок#

HTTPКодКогда
400invalid_requestнет source или содержимого, лишний или неверный параметр в options — имя поля в message
400url_not_allowedадрес без http(s) или ведёт во внутреннюю сеть
401missing_api_keyнет заголовка Authorization: Bearer … и X-API-Key
401invalid_api_keyключ неверный или отозван
402quota_exceededлимит исчерпан или документ больше остатка; страницы не списываются
403email_not_verifiedпочта аккаунта не подтверждена
403source_not_allowedисточник недоступен на тарифе: на Free — только HTML
409idempotency_in_progressещё выполняется, повторите через Retry-After с тем же ключом
409idempotency_conflictтело запроса отличается от исходного
410result_expiredновый рендер требует нового ключа
413payload_too_largeвынесите картинки по ссылкам или уменьшите файл
429rate_limit_exceededзапросы чаще лимита тарифа; повторите через Retry-After секунд
502render_failedобычно дело в разметке или недоступной странице
503unavailableочередь заполнена или рендер перезапускается; повторите позже
504render_timeoutдокумент слишком тяжёлый или страница грузится долго

Какие запросы повторять#

Передавайте Idempotency-Key — случайный идентификатор одного документа. При таймауте или обрыве повторите то же тело и тот же ключ: готовый PDF хранится приватно 24 часа и выдаётся без нового списания. Без сохранённого ключа повтор считается новым документом.

ОтветДействие
409 idempotency_in_progressзапрос ещё выполняется; повторите тот же ключ через Retry-After
409 idempotency_conflictключ уже связан с другим содержимым; исправьте ошибку в клиенте
410 result_expiredPDF удалён; новый рендер требует нового ключа и расходует страницы
429дождитесь Retry-After, сохраните ключ
таймаут, обрыв или 503повторите с тем же ключом; это не создаст второе списание
сохранённая ошибка с new_key_required: trueэтот рендер завершён без списания; исправьте причину и используйте новый ключ

Страницы списываются один раз, когда PDF сохранён и готов к выдаче. Отключение клиента после этого не отменяет списание: результат доступен для повторной выдачи 24 часа. Факт доставки клиенту сервер подтвердить не может. Подробности — Идемпотентность.

Как это делают библиотеки#

Библиотеки pdfapi повторяют 429, 503 и неустановленное соединение сами — по умолчанию до двух раз — и никогда не повторяют таймауты. Ошибки приходят исключениями отдельных классов:

Python
from pdfapi import PdfApi, PdfApiError, QuotaExceededError, RateLimitError, RenderError

try:
    pdf = PdfApi().html(html)
except QuotaExceededError:
    ...  # страницы кончились — предложите сменить тариф
except RateLimitError as e:
    ...  # повторы кончились; можно снова через e.retry_after с
except RenderError:
    ...  # разметка не отрендерилась
except PdfApiError as e:
    log.error("%s %s: %s", e.code, e.status, e.message)

Ответы не от API#

Между вами и API стоят прокси. Они иногда отвечают сами — кодом 413 или страницей HTML с кодом 502. У таких ответов нет поля error: определяйте ошибку по статусу (библиотеки pdfapi так и делают). 404 чаще всего значит, что в базовом адресе забыли /api: правильно — https://pdfapi.ru/api.