error.code (a machine-readable string), an error.message (a human-readable explanation), and an optional error.details object with additional context specific to that error type.
{
"error": {
"code": "invalid_api_key",
"message": "The API key provided is invalid or has been revoked.",
"details": {}
}
}
error.code in your application logic — it is stable across API versions. error.message is intended for logging and debugging and may change over time.
HTTP Status Codes
| Status | Meaning |
|---|---|
200 OK | Request succeeded |
400 Bad Request | Malformed request body or missing required fields |
401 Unauthorized | Missing or invalid API key |
403 Forbidden | Valid key but insufficient permissions |
404 Not Found | Resource does not exist |
422 Unprocessable Entity | Request is valid but contains semantic errors |
429 Too Many Requests | Rate limit exceeded |
500 Internal Server Error | AntifraudAI encountered an unexpected error |
Error Code Reference
| Error Code | HTTP Status | Resolution |
|---|---|---|
invalid_api_key | 401 | The key is malformed, expired, or revoked. Regenerate a key in Settings → API Keys. |
missing_api_key | 401 | No Authorization header was sent. Add Authorization: Bearer <key> to your request. |
insufficient_permissions | 403 | The key is valid but scoped to read-only access. Use a read-write key or adjust the key’s permissions in the dashboard. |
resource_not_found | 404 | The ID in your request path does not match any existing resource. Double-check the event ID, case ID, or rule ID. |
missing_required_field | 400 | One or more required fields were absent from the request body. Consult the API Reference for the required fields list for the endpoint you’re calling. |
invalid_field_value | 400 | A field was present but contained an invalid type or out-of-range value (e.g., a string where a number is required). Check field types and allowed enum values in the API Reference. |
rate_limit_exceeded | 429 | You have exceeded the request rate limit for your environment. Implement retry logic with exponential backoff. See the Rate Limits page for limits and backoff guidance. |
internal_error | 500 | An unexpected error occurred on AntifraudAI’s servers. Retry the request with exponential backoff. If the error persists for more than a few minutes, check the status page and contact support with the request_id from the response. |
Handling Errors in Code
The examples below show a robust error-handling pattern that inspectserror.code and takes action accordingly.
import requests
import time
def screen_event(base_url: str, api_key: str, payload: dict):
for attempt in range(3):
response = requests.post(
f"{base_url}/events/screen",
headers={"Authorization": f"Bearer {api_key}"},
json=payload,
)
if response.ok:
return response.json()
error = response.json().get("error", {})
code = error.get("code")
message = error.get("message")
if code == "invalid_api_key":
raise ValueError(f"Authentication failed: {message}")
elif code == "missing_required_field":
raise ValueError(f"Bad request — check required fields: {message}")
elif code == "rate_limit_exceeded":
wait = 2 ** attempt # exponential backoff: 1s, 2s, 4s
print(f"Rate limited. Retrying in {wait}s...")
time.sleep(wait)
continue
elif code == "internal_error":
if attempt < 2:
time.sleep(2 ** attempt)
continue
raise RuntimeError(f"AntifraudAI internal error after retries: {message}")
else:
raise RuntimeError(f"Unexpected error [{code}]: {message}")
raise RuntimeError("Max retries exceeded.")
async function screenEvent(baseUrl, apiKey, payload, attempt = 0) {
const response = await fetch(`${baseUrl}/events/screen`, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(payload),
});
if (response.ok) {
return response.json();
}
const { error = {} } = await response.json();
const { code, message } = error;
if (code === "invalid_api_key") {
throw new Error(`Authentication failed: ${message}`);
}
if (code === "missing_required_field") {
throw new Error(`Bad request — check required fields: ${message}`);
}
if ((code === "rate_limit_exceeded" || code === "internal_error") && attempt < 3) {
const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
console.warn(`Retrying after ${delay}ms (attempt ${attempt + 1})...`);
await new Promise((resolve) => setTimeout(resolve, delay));
return screenEvent(baseUrl, apiKey, payload, attempt + 1);
}
throw new Error(`AntifraudAI error [${code}]: ${message}`);
}
Always log the full error response body — including
error.code, error.message, and error.details — in your integration. The details field often contains field-level validation information (e.g., which specific field failed and why) that makes debugging significantly faster.
