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 }
}
リクエストのトラッキング
すべてのAPIレスポンス(成功またはエラー)には、その呼び出しのUUIDを含むX-FourA-Request-Idヘッダーが含まれます。システム側でログを記録してください。特定のリクエストの状況についてサポートに問い合わせる必要がある場合、その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
リクエストボディに必須フィールドが欠落している、無効な値が含まれている、またはAPIが取得を拒否するターゲットが指定されています。
{
"error": "Invalid request body format"
}
同じ400エラーはSSRF保護にも適用されます。url がプライベート、ループバック、またはその他の予約済みIPレンジ (RFC 5735、RFC 6598、IPv6予約ブロック) に解決された場合、request は FourA のネットワークを出る前に拒否されます:
{
"error": "Target <ip> resolves to a private/reserved IP"
}
ボディ内の不正なJSONは、フィールドが読み取られる前に同様に拒否されます:
{
"error": "Invalid JSON in request body"
}
proxy および ignoreProxies フィールドには独自の 400 エラーがあります。どちらも以前のレスポンスで返された不透明な proxy ID を受け取るため、それ以外のものではデコードに失敗します:
| メッセージ | 発生した問題 |
|---|---|
Invalid proxy format |
proxy の値が FourA の発行した proxy ID ではありません。生のプロキシアドレスがここに指定されています。 |
Invalid ignoreProxies format |
ignoreProxies のエントリのいずれかが proxy ID ではありません。 |
Proxy not found |
ID は正常にデコードされましたが、有効な出口に解決されなくなりました。新しいものを選択してください。 |
修正方法: リクエストにすべての必須フィールドが含まれていること、URL が http:// または https:// を使用していること、ホストがパブリックアドレスに解決されること、および proxy の値が以前のレスポンスからそのままコピーされた ID であることを確認してください。
401: Unauthorized
API キーが欠落しているか、無効です。
キーが欠落しています:
{
"error": "Missing API key. Include X-API-Key header."
}
無効なキー:
{
"error": "Invalid API key"
}
修正: X-API-Key headerに有効なキーが含まれていることを確認してください。必要に応じて、Dashboardから新しいキーを生成してください。
429: Rate Limited
短期間に送信されたrequestが多すぎます。
{
"error": "Rate limit exceeded",
"status": 429,
"service": "single",
"retryAfter": 5,
"current": { "concurrency": 12, "rpm": 3000 },
"limits": { "maxConcurrency": 500, "maxRpm": 3000 }
}
解決策: さらにリクエストを送信する前に、retryAfter に示される秒数待機してください。詳細は Rate Limits を参照してください。
500: Server Error
当社のサーバーで問題が発生しました。
解決策: 少し待ってからリクエストを再試行してください。エラーが解決しない場合は、ステータスページを確認するか、失敗したレスポンスの X-FourA-Request-Id を添えてサポートにお問い合わせください。
502: Upstream Unavailable
FourA は独自のエンジンに到達しましたが、応答を使用できませんでした。
{
"error": "Upstream unavailable",
"details": "..."
}
修正方法: 短いバックオフで再試行してください。これは当社側の問題であるためコストはかかりません。結果はservice_errorとなり、successのみが課金されます。
504: Upstream Timeout
エンジンがこのリクエストの制限時間内に処理を完了しませんでした。
{
"error": "Upstream timeout",
"details": "the backend did not finish inside the time budget for this request"
}
504エラーは処理にかかった時間に関するものであり、キー、パラメータ、またはproxyに関するものではありません。遅いターゲット、コールド状態のチャレンジ解決、サイズの大きいページなどが主な原因です。
修正方法: requestのtimeout_msを増やすか(Singleは最大120000、Browserは最大120000、Autoは最大180000まで受付可能)、再試行してください。FourAは宣言されたバジェットにわずかな余裕を加えた時間を待機するため、時間を多く要求すれば実際の処理時間も増加します。
503: サービス無効またはキャパシティ超過
503は、メンテナンスのためサービスが一時的に利用できないか、同時接続数の制限に達したことを意味します。どちらのresponseにもretryAfterフィールドが含まれます。同時接続制限の場合、currentおよびlimitsも含まれます。
{
"error": "Service disabled",
"status": 503,
"retryAfter": 60
}
対処法: retryAfter秒待機してから再試行してください。ステータスページでアクティブなメンテナンス期間を確認できます。
3つ目の503のパターンにはretryAfterがありません。これは、リクエストの到着時にendpointの背後にあるエンジンが再起動していたことを意味します:
{
"error": "Backend service unavailable",
"backend_status": 503
}
1〜2秒後にリトライしてください。
/api/auto/ からのエラーの読み取り
ラダーが実行された場合、すべてのステップが失敗したとしても、POST /api/auto/ は HTTP 200 で応答します。実際の結果は body に含まれます:
{
"status": 0,
"error": "all attempts failed",
"attempts": 7,
"meta": { "rung": "fail", "solved": false, "attempts": 7, "credits": 47 }
}
したがって、Autoのトランスポートステータスで分岐処理を行わないでください。代わりに、ボディから status と error を読み取ってください。/api/auto/ からの純粋な非200レスポンスは、ラダー開始前にFourAが呼び出しを拒否したことを意味します (401、400、429、503など、すべて上記でドキュメント化されています)。
200 OK内のターゲット側エラー
すべてのエラーが非2xx HTTPステータスとして現れるわけではありません。ターゲットサイトがエラーペイロードを含むHTTP 200を返した場合、FourAはボディを渡しますが、リクエストを application_error として分類します。ターゲットが validate ルールで許容されない非2xxを返した場合、結果は application_fail となり、ボディは変更されずに渡されます。
どちらのケースも、ワイヤーレベルでリクエストが成功したとみなされ課金対象となります。完全な分類については、Outcomes リファレンスを参照してください。
レスポンスエンコーディング
FourAはレスポンスボディを自動的にUTF-8にデコードします。ターゲットが windows-1251、gbk、shift_jis、iso-8859-*、または Content-Type ヘッダーやHTMLの <meta charset> タグで宣言されたその他のcharsetを提供した場合、data (single、proxy) または body (browser) フィールドでクリーンなUTF-8文字列を受け取ります。
バイナリペイロード (画像、protobuf、RAW音声) の場合、リクエストで returnBuffer: true を設定してください。ボディは、charsetの変換が適用されずに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: # 500, 502, 503, 504 are all ours to fix
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")