Skip to main content
VertaaUX Docs
API

Error Codes

Complete reference of API error codes and troubleshooting

Error Codes

All API errors return a consistent JSON structure with an error code, message, and optional details.

Error Response Format

errorstring

Machine-readable error code (e.g., 'invalid_url').

messagestring

Human-readable error description.

detailsobject

Additional context about the error (optional).

request_idstring

Unique request identifier for support tickets.

documentation_urlstring

Link to relevant documentation.

Example Error Response

{
  "error": "invalid_url",
  "message": "Invalid URL format. Must be a valid HTTP or HTTPS URL",
  "details": {
    "field": "url",
    "value": "not-a-url",
    "reason": "URL must start with http:// or https://"
  },
  "request_id": "req_abc123def456",
  "documentation_url": "/docs/api/errors#invalid_url"
}

Error Handling Example

interface ApiError {
  error: string;
  message: string;
  details?: {
    field?: string;
    value?: unknown;
    reason?: string;
    [key: string]: unknown;
  };
  request_id?: string;
  documentation_url?: string;
}

async function createAudit(url: string) {
  const response = await fetch('https://vertaaux.ai/api/v1/audit', {
    method: 'POST',
    headers: {
      'X-API-Key': process.env.VERTAAUX_API_KEY!,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({ url }),
  });

  if (!response.ok) {
    const error: ApiError = await response.json();

    // Handle specific error codes
    switch (error.error) {
      case 'quota_exceeded':
        const retryAfter = response.headers.get('Retry-After');
        console.error(`Quota exceeded. Retry after ${retryAfter}s`);
        break;

      case 'rate_limit_exceeded':
        // Implement exponential backoff
        const resetTime = response.headers.get('X-RateLimit-Reset');
        console.error(`Rate limited. Resets at ${resetTime}`);
        break;

      case 'invalid_url':
        console.error(`Invalid URL: ${error.details?.reason}`);
        break;

      case 'api_key_invalid':
        console.error('Check your API key configuration');
        break;

      default:
        console.error(`Error: ${error.message} (${error.request_id})`);
    }

    throw new Error(error.message);
  }

  return response.json();
}
import os
import time
import requests
from typing import TypedDict, Any, Optional

class ApiError(TypedDict):
    error: str
    message: str
    details: Optional[dict[str, Any]]
    request_id: Optional[str]
    documentation_url: Optional[str]

def create_audit(url: str) -> dict:
    response = requests.post(
        'https://vertaaux.ai/api/v1/audit',
        headers={
            'X-API-Key': os.environ['VERTAAUX_API_KEY'],
            'Content-Type': 'application/json',
        },
        json={'url': url}
    )

    if not response.ok:
        error: ApiError = response.json()

        # Handle specific error codes
        if error['error'] == 'quota_exceeded':
            retry_after = response.headers.get('Retry-After', '0')
            print(f"Quota exceeded. Retry after {retry_after}s")

        elif error['error'] == 'rate_limit_exceeded':
            reset_time = response.headers.get('X-RateLimit-Reset')
            print(f"Rate limited. Resets at {reset_time}")

        elif error['error'] == 'invalid_url':
            reason = error.get('details', {}).get('reason', 'unknown')
            print(f"Invalid URL: {reason}")

        elif error['error'] == 'api_key_invalid':
            print('Check your API key configuration')

        else:
            print(f"Error: {error['message']} ({error.get('request_id')})")

        raise Exception(error['message'])

    return response.json()

Authentication Errors (401)

Errors related to API key authentication.

unauthorized

Message: Authentication required

Cause: No API key provided in the request.

Solution: Add the X-API-Key header to your request.

curl https://vertaaux.ai/api/v1/audit \
  -H "X-API-Key: vx_live_your_key"  # Add this header

api_key_invalid

Message: Invalid or missing API key

Cause: The provided API key does not exist or is malformed.

Solution:

  1. Verify the key is copied correctly (no extra spaces)
  2. Check you're using X-API-Key header (not Authorization: Bearer)
  3. Regenerate the key in your dashboard if needed

api_key_revoked

Message: API key has been revoked

Cause: The key was explicitly revoked in the dashboard.

Solution: Create a new API key in Dashboard > Settings > API Keys.


api_key_expired

Message: API key has expired

Cause: The key had an expiration date that has passed.

Solution: Create a new key or extend the expiration in your dashboard.


Authorization Errors (403)

Errors related to permissions and access.

forbidden

Message: You don't have permission to access this resource

Cause: Attempting to access another user's audit or resource.

Solution: Verify you're using the correct API key and accessing your own resources.


tier_restriction

Message: This feature requires a higher tier subscription

Cause: Attempting to use a feature not available on your plan.

Solution: Upgrade your subscription to access this feature.


webhook_limit_reached

Message: Webhook limit reached for your tier

Cause: Attempting to create more webhooks than your tier allows.

TierWebhook Limit
Free0
Pro5
Agency50
Enterprise100

Solution: Delete unused webhooks or upgrade your tier.


schedule_limit_reached

Message: Schedule limit reached for your tier

Cause: Attempting to create more scheduled audits than your tier allows.

Solution: Delete unused schedules or upgrade your tier.


Client Errors (400)

Errors caused by invalid request data.

invalid_request

Message: Invalid request format

Cause: Request body is not valid JSON or missing required fields.

Solution: Verify your request body is valid JSON with all required fields.

# Wrong
curl -X POST https://vertaaux.ai/api/v1/audit \
  -d 'url=https://example.com'  # Form data, not JSON

# Correct
curl -X POST https://vertaaux.ai/api/v1/audit \
  -H "Content-Type: application/json" \
  -d '{"url": "https://example.com"}'

invalid_url

Message: Invalid URL format. Must be a valid HTTP or HTTPS URL

Cause: The provided URL is malformed or uses a blocked protocol.

Valid URLs:

  • https://example.com
  • https://example.com/path?query=value

Invalid URLs:

  • not-a-url
  • ftp://files.example.com
  • http://localhost:3000 (blocked)
  • http://192.168.1.1 (blocked)

Solution: Provide a publicly accessible HTTP or HTTPS URL.


invalid_mode

Message: Invalid mode. Must be 'basic', 'standard', or 'deep'

Cause: The mode parameter has an invalid value.

Solution: Use one of: basic, standard, or deep.


missing_parameter

Message: Required parameter is missing

Cause: A required field is not provided in the request.

Solution: Check the endpoint documentation for required parameters.


page_limit_exceeded

Message: Page limit exceeded. Maximum 20 pages per audit

Cause: The URL leads to more pages than allowed for your tier.

Solution: Audit a more specific URL or contact support for higher limits.


idempotency_key_conflict

Message: Idempotency key conflict. This key was already used with different parameters

HTTP Status: 409 Conflict

Cause: The same idempotency key was used with different request parameters.

Solution: Use a unique idempotency key for each unique request.

{
  "error": "idempotency_key_conflict",
  "message": "Idempotency key conflict",
  "details": {
    "existing_job_id": "clu1a2b3c4d5e6f7g8h9i0j1"
  }
}

validation_error

Message: Request validation failed

Cause: One or more fields failed validation.

Details structure:

{
  "error": "validation_error",
  "message": "Request validation failed",
  "details": {
    "validation_errors": [
      { "field": "url", "message": "Invalid URL format" },
      { "field": "mode", "message": "Must be 'basic', 'standard', or 'deep'" }
    ]
  }
}

Solution: Fix the indicated fields and retry.


Not Found Errors (404)

Errors when a resource doesn't exist.

not_found

Message: Resource not found

Cause: Generic not found error for unspecified resources.


job_not_found

Message: Audit job not found

Cause: The specified job_id does not exist.

Solution:

  1. Verify the job ID is correct
  2. Check the job hasn't been deleted
  3. Ensure you're using the correct API key (jobs are user-scoped)

webhook_not_found

Message: Webhook not found

Cause: The specified webhook ID does not exist.


schedule_not_found

Message: Schedule not found

Cause: The specified schedule ID does not exist.


Rate Limiting Errors (429)

Errors when request limits are exceeded.

quota_exceeded

Message: Daily quota limit reached

Cause: You've used all your daily audit credits.

Response headers:

X-RateLimit-Limit: 1000
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1705363200
Retry-After: 3600

Solution:

  1. Wait until the quota resets (midnight UTC)
  2. Upgrade your tier for higher limits
  3. Use sandbox mode for testing

rate_limit_exceeded

Message: Rate limit exceeded. Please retry after the reset time

Cause: Too many requests in a short period.

Solution:

  1. Implement exponential backoff
  2. Check the Retry-After header
  3. Spread requests over time
async function withRetry<T>(
  fn: () => Promise<T>,
  maxRetries = 3
): Promise<T> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status === 429) {
        const retryAfter = parseInt(error.headers['retry-after'] || '60');
        await new Promise(r => setTimeout(r, retryAfter * 1000));
      } else {
        throw error;
      }
    }
  }
  throw new Error('Max retries exceeded');
}

concurrent_limit_exceeded

Message: Concurrent request limit exceeded

Cause: Too many simultaneous requests.

Solution: Queue requests and limit concurrency.


queue_busy

Message: The audit queue is currently at capacity. Please retry shortly

Cause: The audit processing queue is full.

Response includes queue stats:

{
  "error": "queue_busy",
  "message": "The audit queue is currently at capacity",
  "details": {
    "reason": "Queue at capacity",
    "limits": { "retryAfterSeconds": 60 },
    "queue": { "queued": 1000, "processing": 50 }
  }
}

Solution: Wait and retry with the Retry-After header value.


Server Errors (500)

Errors caused by server-side issues.

internal_error

Message: An internal server error occurred

Cause: Unexpected server error.

Solution:

  1. Retry with exponential backoff
  2. If persistent, contact support with the request_id

timeout

Message: Request timeout. The page took too long to load

Cause: The target URL took too long to respond.

Solution:

  1. Verify the URL is accessible
  2. Try again (may be temporary)
  3. Increase the timeout parameter in your request

engine_failure

Message: Audit engine is temporarily unavailable

Cause: The audit processing engine is having issues.

Solution: Wait a few minutes and retry. Check status.vertaaux.ai for outages.


database_error

Message: Database operation failed

Cause: Database connectivity or query issue.

Solution: Retry after a short delay. This is usually temporary.


webhook_delivery_failed

Message: Webhook delivery failed after all retry attempts

Cause: Your webhook endpoint didn't respond successfully after multiple attempts.

Solution:

  1. Check your webhook endpoint is accessible
  2. Verify it returns 2xx status codes
  3. Check your server logs for errors
  4. Ensure response time is under 5 seconds

Complete Error Code Reference

CodeStatusDescription
unauthorized401Authentication required
api_key_invalid401Invalid or missing API key
api_key_revoked401API key has been revoked
api_key_expired401API key has expired
forbidden403No permission to access resource
tier_restriction403Feature requires higher tier
webhook_limit_reached403Webhook limit for tier reached
schedule_limit_reached403Schedule limit for tier reached
invalid_request400Invalid request format
invalid_url400Invalid URL format
invalid_mode400Invalid audit mode
missing_parameter400Required parameter missing
page_limit_exceeded400Too many pages to audit
idempotency_key_conflict409Idempotency key already used
validation_error400Request validation failed
not_found404Resource not found
job_not_found404Audit job not found
webhook_not_found404Webhook not found
schedule_not_found404Schedule not found
quota_exceeded429Daily quota limit reached
rate_limit_exceeded429Rate limit exceeded
concurrent_limit_exceeded429Too many concurrent requests
queue_busy429Audit queue at capacity
internal_error500Internal server error
timeout500Page load timeout
engine_failure500Audit engine unavailable
database_error500Database operation failed
webhook_delivery_failed500Webhook delivery failed

Was this page helpful?

On this page