Skip to content

Error Reference

When an API request fails, Comvi returns a consistent error response with a machine-readable error code, a human-readable message, and optional metadata for debugging.

All errors follow this structure:

{
"code": "PROJECT_NOT_FOUND",
"message": "Project not found",
"meta": {
"projectId": 123
}
}

The HTTP status code is on the response itself (e.g., 404). The body carries:

FieldTypeDescription
codestringMachine-readable error code — use this for programmatic handling
messagestringHuman-readable description of what went wrong
metaobjectAdditional context (optional, varies by error)

StatusNameDescription
400Bad RequestThe request body or parameters are invalid
401UnauthorizedMissing or invalid authentication credentials
403ForbiddenValid credentials but insufficient permissions
404Not FoundThe requested resource does not exist
409ConflictThe request conflicts with the current state of a resource
422Unprocessable EntityThe request is well-formed but semantically invalid
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server error

Error CodeStatusDescription
INVALID_CREDENTIALS401Email or password is incorrect
AUTHENTICATION_REQUIRED401No valid session or API key provided
SESSION_EXPIRED401Session has expired, re-authenticate
UNAUTHORIZED401General authentication failure
INVALID_OR_EXPIRED_TOKEN401Token (reset, verification) is invalid or expired
API_KEY_INVALID401API key is malformed or does not exist
API_KEY_DISABLED401API key has been deactivated
API_KEY_EXPIRED401API key has passed its expiration date
Error CodeStatusDescription
FORBIDDEN403Generic access denied
INSUFFICIENT_PERMISSION403User lacks the required permission for this action
NO_PROJECT_ACCESS403User does not have access to this project
NOT_ORGANIZATION_MEMBER403User is not a member of the organization
PERMISSION_DENIED403Permission check failed
GRANULAR_RESTRICTION403Blocked by language or namespace restrictions
ROLE_HIERARCHY_VIOLATION403Cannot assign a role higher than your own
API_KEY_PERMISSIONS_REVOKED403API key’s permissions have been revoked
Error CodeStatusDescription
NOT_FOUND404Generic resource not found
USER_NOT_FOUND404User does not exist
ORGANIZATION_NOT_FOUND404Organization does not exist
PROJECT_NOT_FOUND404Project does not exist
API_KEY_NOT_FOUND404API key does not exist
LOCALE_NOT_FOUND404Locale does not exist
TRANSLATION_KEY_NOT_FOUND404Translation key does not exist
NAMESPACE_NOT_FOUND404Namespace does not exist
WEBHOOK_NOT_FOUND404Webhook does not exist
WEBHOOK_DELIVERY_NOT_FOUND404Webhook delivery does not exist
INVITATION_NOT_FOUND404Invitation does not exist
HISTORY_NOT_FOUND404History entry does not exist
Error CodeStatusDescription
EMAIL_ALREADY_USED409An account with this email already exists
USER_ALREADY_IN_ORGANIZATION409User is already a member of this organization
LOCALE_ALREADY_EXISTS409This locale is already added to the project
TRANSLATION_KEY_ALREADY_EXISTS409A key with this name already exists in the namespace
NAMESPACE_ALREADY_EXISTS409A namespace with this name already exists
UNIQUE_CONSTRAINT409A unique constraint was violated
INVITATION_ALREADY_SENT409An invitation has already been sent to this email
PASSWORD_ALREADY_SET409Password has already been set for this account
Error CodeStatusDescription
VALIDATION_ERROR400General validation failure
INVALID_INPUT400Input data is invalid
FIELD_REQUIRED400A required field is missing
FIELD_TOO_SHORT400Field value is below the minimum length
FIELD_TOO_LONG400Field value exceeds the maximum length
MISSING_PARAMS400Required URL parameters are missing
SYNTAX_ERROR400Request body has a syntax error (invalid JSON)
INVALID_ROLE400The specified role is not valid
Error CodeStatusDescription
FILE_TOO_LARGE400Uploaded file exceeds the size limit
FILE_TYPE_NOT_ALLOWED400File format is not supported
INVALID_FILE_STRUCTURE400File content does not match the expected structure
TOO_MANY_KEYS400Import exceeds the maximum number of translation keys
ZIP_BOMB_DETECTED400Compressed file detected as potentially malicious
JSON_BOMB_DETECTED400JSON file detected as potentially malicious
COMPRESSION_RATIO_EXCEEDED400File compression ratio exceeds the safety threshold
IMPORT_SESSION_EXPIRED400The import session has timed out
IMPORT_SESSION_MISMATCH400Import confirmation does not match the started session
Error CodeStatusDescription
RATE_LIMIT_EXCEEDED429Too many requests, retry after the Retry-After header value
TOO_MANY_REQUESTS429General rate limiting
Error CodeStatusDescription
LIMIT_EXCEEDED403Plan limit reached (e.g., max projects, max keys)
FEATURE_NOT_AVAILABLE403Feature not available on your current plan
READ_ONLY_MODE403Organization is in read-only mode (subscription expired)
SUBSCRIPTION_NOT_FOUND404No active subscription found
PLAN_NOT_FOUND404The referenced billing plan does not exist
INSUFFICIENT_CREDITS402Not enough credits for this operation
ACTIVE_SUBSCRIPTION_REQUIRED403An active subscription is required for this action
CANNOT_CANCEL_FREE_PLAN400Cannot cancel a free plan
Error CodeStatusDescription
CANNOT_REMOVE_LAST_OWNER400Cannot remove or demote the last owner
INVITATION_EXPIRED400The invitation link has expired
INVALID_INVITATION400The invitation is invalid or has already been used
CANNOT_DELETE_LAST_PROVIDER400Cannot remove the only authentication provider
Error CodeStatusDescription
FAILED_TO_CREATE_PROJECT500Internal error during project creation
CANNOT_REMOVE_DEFAULT_LOCALE400Cannot remove the source language from a project
LOCALE_NOT_ENABLED400The locale is not enabled for this project
Error CodeStatusDescription
WEBHOOK_NOT_FOUND404Webhook does not exist
WEBHOOK_DELIVERY_NOT_FOUND404Delivery record does not exist
WEBHOOK_RETRY_NOT_ALLOWED400Can only retry deliveries with failed status
Error CodeStatusDescription
INTERNAL_ERROR500Unexpected internal error
INTERNAL_SERVER_ERROR500General server error
UNKNOWN500An unknown error occurred

try {
const response = await fetch('https://api.comvi.io/api/v1/projects', {
headers: { 'X-API-Key': apiKey },
});
if (!response.ok) {
const error = await response.json();
switch (error.code) {
case 'AUTHENTICATION_REQUIRED':
// Redirect to login or refresh API key
break;
case 'INSUFFICIENT_PERMISSION':
// Show permission denied message
console.error(`Access denied: ${error.message}`);
break;
case 'RATE_LIMIT_EXCEEDED':
// Retry after the specified delay
const retryAfter = response.headers.get('Retry-After');
console.log(`Rate limited. Retry after ${retryAfter} seconds`);
break;
case 'VALIDATION_ERROR':
// Display validation errors to the user
console.error(`Validation failed: ${error.message}`, error.meta);
break;
default:
console.error(`API error: ${error.code} - ${error.message}`);
}
return;
}
const data = await response.json();
// Process successful response
} catch (networkError) {
// Handle network errors (DNS failure, timeout, etc.)
console.error('Network error:', networkError);
}

Check the HTTP status code and parse the JSON error body:

Terminal window
response=$(curl -s -w "\n%{http_code}" \
-H "X-API-Key: comvi_your_api_key" \
https://api.comvi.io/api/v1/projects/999)
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | head -1)
if [ "$http_code" -ne 200 ]; then
echo "Error $http_code: $body"
fi

When your request is rate-limited (429), the response includes headers to help you retry:

HeaderDescription
Retry-AfterSeconds to wait before retrying
X-RateLimit-LimitMaximum requests allowed in the window
X-RateLimit-RemainingRequests remaining in the current window