Error Codes
Complete reference for Vettly API error responses.
HTTP Status Codes
| Status | Name | Description |
|---|---|---|
| 200 | OK | Request successful |
| 201 | Created | Resource created |
| 400 | Bad Request | Malformed request syntax |
| 401 | Unauthorized | Invalid or missing API key |
| 402 | Payment Required | Quota exceeded |
| 403 | Forbidden | Insufficient permissions |
| 404 | Not Found | Resource not found |
| 422 | Unprocessable Entity | Validation error |
| 429 | Too Many Requests | Rate limit exceeded |
| 500 | Internal Server Error | Server error |
| 503 | Service Unavailable | Temporarily unavailable |
Error Response Format
All errors return a consistent JSON structure:
json
{
"error": {
"code": "RATE_LIMIT_EXCEEDED",
"message": "Rate limit exceeded. Try again in 30 seconds.",
"details": {
"limit": 100,
"remaining": 0,
"reset": 1699999999
}
}
}Fields
| Field | Type | Description |
|---|---|---|
error.code | string | Machine-readable error code |
error.message | string | Human-readable description |
error.details | object | Additional context (optional) |
Error Codes by Category
Authentication Errors (401)
| Code | Message | Solution |
|---|---|---|
INVALID_API_KEY | Invalid API key provided | Check your API key is correct |
EXPIRED_API_KEY | API key has expired | Generate a new key in dashboard |
MISSING_API_KEY | No API key provided | Add Authorization: Bearer sk_live_... header |
REVOKED_API_KEY | API key was revoked | Generate a new key in dashboard |
Quota Errors (402)
| Code | Message | Solution |
|---|---|---|
QUOTA_EXCEEDED | Monthly quota exceeded | Upgrade plan or wait for reset |
TRIAL_EXPIRED | Free trial has ended | Add payment method |
Permission Errors (403)
| Code | Message | Solution |
|---|---|---|
INSUFFICIENT_PERMISSIONS | API key lacks required permissions | Use a key with appropriate scopes |
POLICY_NOT_ACCESSIBLE | Cannot access this policy | Check policy ownership |
Not Found Errors (404)
| Code | Message | Solution |
|---|---|---|
POLICY_NOT_FOUND | Policy does not exist | Check policy ID is correct |
DECISION_NOT_FOUND | Decision does not exist | Check decision ID is correct |
WEBHOOK_NOT_FOUND | Webhook does not exist | Check webhook ID is correct |
Validation Errors (422)
| Code | Message | Solution |
|---|---|---|
INVALID_CONTENT | Content is invalid | Check content format |
CONTENT_TOO_LARGE | Content exceeds size limit | Reduce content size |
INVALID_CONTENT_TYPE | Unsupported content type | Use text, image, or video |
INVALID_POLICY_ID | Policy ID format is invalid | Use valid policy ID format |
INVALID_IMAGE_URL | Image URL is not accessible | Check URL is public |
INVALID_BASE64 | Base64 encoding is invalid | Fix base64 encoding |
MISSING_REQUIRED_FIELD | Required field is missing | Add required field |
INVALID_METADATA | Metadata format is invalid | Check metadata is valid JSON |
Rate Limit Errors (429)
| Code | Message | Solution |
|---|---|---|
RATE_LIMIT_EXCEEDED | Too many requests | Wait and retry with backoff |
BURST_LIMIT_EXCEEDED | Burst limit exceeded | Slow down request rate |
Server Errors (5xx)
| Code | Message | Solution |
|---|---|---|
INTERNAL_ERROR | Internal server error | Retry automatically |
SERVICE_UNAVAILABLE | Service temporarily unavailable | Check status page |
PROVIDER_ERROR | AI provider error | Retry automatically |
Rate Limit Headers
Rate limited responses include headers:
http
HTTP/1.1 429 Too Many Requests
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699999999
Retry-After: 30| Header | Description |
|---|---|
X-RateLimit-Limit | Requests allowed per window |
X-RateLimit-Remaining | Requests remaining in window |
X-RateLimit-Reset | Unix timestamp when window resets |
Retry-After | Seconds to wait before retrying |
Endpoint-Specific Errors
POST /v1/check
| Code | Cause |
|---|---|
INVALID_CONTENT | Content format invalid |
CONTENT_TOO_LARGE | Exceeds 32KB (text) or 20MB (image) |
INVALID_CONTENT_TYPE | Not text, image, or video |
POLICY_NOT_FOUND | Policy ID doesn't exist |
POST /v1/batch
| Code | Cause |
|---|---|
TOO_MANY_ITEMS | Exceeds 100 items per batch |
INVALID_BATCH_ITEM | Item in batch is invalid |
POST /v1/policies
| Code | Cause |
|---|---|
INVALID_YAML | Policy YAML is malformed |
INVALID_THRESHOLD | Threshold not between 0 and 1 |
INVALID_ACTION | Action not allow/flag/warn/block |
DUPLICATE_POLICY_ID | Policy ID already exists |
Webhook Endpoints
| Code | Cause |
|---|---|
INVALID_WEBHOOK_URL | URL is not valid HTTPS |
WEBHOOK_URL_UNREACHABLE | Cannot connect to URL |
INVALID_EVENT_TYPE | Event type not recognized |
SDK Exception Mapping
SDKs map error codes to typed exceptions:
| HTTP Status | TypeScript | Python |
|---|---|---|
| 401 | VettlyAuthError | VettlyAuthError |
| 402 | VettlyQuotaError | VettlyQuotaError |
| 422 | VettlyValidationError | VettlyValidationError |
| 429 | VettlyRateLimitError | VettlyRateLimitError |
| 5xx | VettlyError | VettlyServerError |
Best Practices
- Always check error codes, not just HTTP status
- Log error details for debugging
- Implement automatic retry for 429 and 5xx
- Don't retry 401, 402, 403, 422 errors
- Use SDK typed exceptions for cleaner code
typescript
try {
await client.check({ ... })
} catch (error) {
// Log full error for debugging
console.error({
code: error.code,
message: error.message,
details: error.details
})
// Handle by type
if (error instanceof VettlyRateLimitError) {
// Retry after delay
} else if (error instanceof VettlyValidationError) {
// Fix request and retry
}
}See Also
- Error Handling Guide - Best practices
- Troubleshooting - Common issues
- REST API Reference - Full API docs