Грешки в API

Как да се справяте с грешките от FourA API.

Формат на отговорите за грешка

API връща плоски JSON обекти за всички грешки. Няма вложен error обект или кодове за грешки.

{
  "error": "Invalid API key"
}

Някои грешки включват допълнителни полета като status, service, retryAfter, current или limits на най-горно ниво:

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Проследяване на request

Всеки API response (успешен или с грешка) включва X-Foura-Request-Id header с UUID за това повикване. Записвайте го в лог файловете от ваша страна. Ако трябва да попитате поддръжката какво се е случило с конкретен request, този ID ни позволява да го намерим.

curl -i -X POST https://eu.api.foura.ai/api/single/ \
  -H "X-API-Key: YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"method": "GET", "url": "https://example.com"}'
# HTTP/1.1 200 OK
# X-Foura-Request-Id: 9f1c4e6c-7b2a-4d3e-8a1f-2c9d8e4a3b15
# Content-Type: application/json
# ...

Типове грешки

400: Bad Request

В тялото на request липсват задължителни полета, съдържа невалидни стойности или посочва цел, която API отказва да извлече.

{
  "error": "Invalid request body format"
}

Същата грешка 400 покрива и SSRF защитата. Ако вашият url се разрешава до частен, loopback или друг резервиран IP диапазон (RFC 5735, RFC 6598, IPv6 резервирани блокове), request се отхвърля, преди да напусне мрежата на FourA:

{
  "error": "Target <ip> resolves to a private/reserved IP"
}

Решение: Проверете дали вашият request включва всички задължителни полета, дали URL адресите използват http:// или https:// и дали хостът се разрешава до публичен адрес.

401: Unauthorized

Вашият API key липсва или е невалиден.

Липсващ ключ:

{
  "error": "Missing API key. Include X-API-Key header."
}

Невалиден ключ:

{
  "error": "Invalid API key"
}

Решение: Проверете дали вашият X-API-Key header съдържа валиден ключ. Генерирайте нов ключ от Dashboard, ако е необходимо.

429: Rate Limited

Изпратили сте твърде много requests за кратък период от време.

{
  "error": "Rate limit exceeded",
  "status": 429,
  "service": "single",
  "retryAfter": 5,
  "current": { "concurrency": 12, "rpm": 3000 },
  "limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}

Решение: Изчакайте броя секунди в retryAfter, преди да изпратите още requests. Вижте Rate Limits за подробности.

500: Server Error

Нещо се обърка от наша страна.

Решение: Опитайте отново с request след кратко забавяне. Ако грешката продължава, проверете status page или се свържете с поддръжката, като предоставите X-Foura-Request-Id от неуспешния response.

503: Service Disabled or At Capacity

Грешка 503 означава, че услугата е временно недостъпна за поддръжка или че сте достигнали лимита за едновременни заявки (concurrency limit). И двата отговора включват поле retryAfter. Вариантът за concurrency включва също current и limits.

{
  "error": "Service disabled",
  "status": 503,
  "retryAfter": 60
}

Решение: Изчакайте retryAfter секунди, след което опитайте отново. На status page са изброени активните периоди на поддръжка.

Неуспехи от страна на целта в рамките на 200 OK

Не всеки неуспех се показва като различен от 2xx HTTP статус. Когато целевият сайт върне HTTP 200 с данни за грешка, FourA все пак ви предава body, но класифицира request като application_error. Когато целта върне статус, различен от 2xx, който вашите validate правила не приемат, резултатът е application_fail и body се предава непроменено.

И двата случая се таксуват, сякаш request е бил успешен на мрежово ниво. Справочникът за Outcomes обхваща пълната таксономия.

Кодиране на отговора

FourA автоматично декорира response bodies до UTF-8. Ако целта предоставя windows-1251, gbk, shift_jis, iso-8859-* или всяка друга кодировка, декларирана в Content-Type header или в HTML <meta charset> таг, вие получавате чист UTF-8 низ в полето data (single, proxy) или body (browser).

За двоични данни (изображения, protobuf, необработено аудио), задайте returnBuffer: true в request. Тялото се връща като base64 буфер без прилагане на транскодиране на кодировката.

Стратегия за повторен опит

Практична политика за повторен опит:

import time
import requests

def make_request(url, payload, api_key, max_retries=3):
    for attempt in range(max_retries):
        resp = requests.post(
            url,
            headers={"X-API-Key": api_key, "Content-Type": "application/json"},
            json=payload,
        )
        if resp.status_code == 200:
            return resp.json()

        body = resp.json() if resp.headers.get("content-type", "").startswith("application/json") else {}
        retry_after = body.get("retryAfter", 2 ** attempt)
        request_id = resp.headers.get("X-Foura-Request-Id", "?")

        if resp.status_code in (429, 503):
            time.sleep(retry_after)
            continue
        if resp.status_code >= 500:
            time.sleep(2 ** attempt)
            continue

        # 400/401/404 won't fix themselves
        raise RuntimeError(f"{resp.status_code} (request {request_id}): {body.get('error')}")

    raise RuntimeError(f"Exhausted {max_retries} retries")

Свързани теми

  • Rate Limits: Подробности за concurrency и RPM
  • Request Outcomes: Обяснение на седемте стойности за резултат
  • Common Issues: Симптоми, причини, решения
Обновено: 18 юни 2026 г.