My App
DocExtract API

Errors

Complete error code reference and handling guide

Errors

The DocExtract API uses conventional HTTP response codes and returns detailed error information in JSON format. This guide covers all error codes, their meanings, and how to handle them.

Error Response Format

All errors follow this format:

{
  "error": {
    "code": "document_unreadable",
    "message": "Document quality is too low to extract text",
    "suggestion": "Please provide a higher quality scan or image",
    "status": 400,
    "request_id": "req_abc123...",
    "documentation_url": "https://docs.adteco.com/docextract-api/errors#document_unreadable"
  }
}

Error Object Attributes

AttributeTypeDescription
codestringMachine-readable error code
messagestringHuman-readable error message
suggestionstringHow to fix the error (optional)
statusnumberHTTP status code
request_idstringUnique request identifier for support
documentation_urlstringLink to error documentation

HTTP Status Codes

CodeMeaningDescription
200OKRequest successful
400Bad RequestInvalid request parameters
401UnauthorizedMissing or invalid API key
403ForbiddenAPI key lacks required permissions
404Not FoundResource not found
409ConflictResource already exists
422Unprocessable EntityValid request but cannot be processed
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error
503Service UnavailableTemporary service outage

Authentication Errors

invalid_api_key

Status: 401

The API key provided is invalid, revoked, or expired.

{
  "error": {
    "code": "invalid_api_key",
    "message": "The API key provided is invalid or has been revoked",
    "status": 401
  }
}

Resolution:

  • Verify your API key is correct
  • Check if the key has been revoked in the dashboard
  • Generate a new API key if needed

missing_authorization

Status: 401

No API key was provided in the Authorization header.

{
  "error": {
    "code": "missing_authorization",
    "message": "No API key provided in Authorization header",
    "status": 401
  }
}

Resolution:

  • Include Authorization: Bearer sk_live_your_api_key header

insufficient_permissions

Status: 403

The API key doesn't have permission to perform this action.

{
  "error": {
    "code": "insufficient_permissions",
    "message": "This API key does not have permission to perform this action. Required scope: documents:write",
    "status": 403
  }
}

Resolution:

  • Create a new API key with required scopes
  • Update the existing key's permissions in the dashboard

Document Processing Errors

document_too_large

Status: 422

The document exceeds the maximum file size (10 MB).

{
  "error": {
    "code": "document_too_large",
    "message": "Document size exceeds maximum allowed size of 10 MB",
    "suggestion": "Compress the document or split into multiple smaller files",
    "status": 422
  }
}

Resolution:

  • Compress the PDF using tools like Adobe Acrobat or pdftk
  • Split large documents into smaller files
  • Reduce image resolution for scanned documents

document_unreadable

Status: 422

Cannot extract text from the document due to poor quality.

{
  "error": {
    "code": "document_unreadable",
    "message": "Document quality is too low to extract text",
    "suggestion": "Please provide a higher quality scan or image (minimum 150 DPI recommended)",
    "status": 422
  }
}

Resolution:

  • Re-scan document at higher resolution (300 DPI recommended)
  • Improve lighting and contrast
  • Use a flatbed scanner instead of mobile camera
  • Ensure document is properly oriented

unsupported_format

Status: 422

The document format is not supported.

{
  "error": {
    "code": "unsupported_format",
    "message": "Document format not supported. Supported formats: PDF, PNG, JPG, WEBP, TIFF",
    "status": 422
  }
}

Resolution:

  • Convert document to a supported format
  • Verify the MIME type matches the actual file format

invalid_base64

Status: 400

The document is not properly base64-encoded.

{
  "error": {
    "code": "invalid_base64",
    "message": "Document must be base64-encoded",
    "status": 400
  }
}

Resolution:

  • Ensure document is properly base64-encoded
  • Check for whitespace or line breaks in the encoded string
  • Use standard base64 encoding libraries

Resource Errors

extractor_not_found

Status: 404

The specified extractor does not exist.

{
  "error": {
    "code": "extractor_not_found",
    "message": "Extractor with ID 'ext_abc123' not found",
    "status": 404
  }
}

Resolution:

  • Verify the extractor ID is correct
  • Check if the extractor was deleted
  • Ensure you're using the correct organization

job_not_found

Status: 404

The specified job does not exist.

{
  "error": {
    "code": "job_not_found",
    "message": "Job with ID 'job_xyz789' not found",
    "status": 404
  }
}

Resolution:

  • Verify the job ID is correct
  • Check if the job has been purged (older than 90 days)

resource_already_exists

Status: 409

A resource with this identifier already exists.

{
  "error": {
    "code": "resource_already_exists",
    "message": "An extractor with this name already exists",
    "status": 409
  }
}

Resolution:

  • Use a different name
  • Update the existing resource instead

Credit Errors

insufficient_credits

Status: 402

Not enough credits to process the request.

{
  "error": {
    "code": "insufficient_credits",
    "message": "Insufficient credits to process document. Current balance: 0 credits. Required: 2 credits",
    "suggestion": "Purchase more credits at https://app.adteco.com/docextract/billing",
    "status": 402
  }
}

Resolution:

  • Purchase more credits
  • Check current balance with /v1/credits endpoint
  • Set up low balance alerts

Rate Limiting Errors

rate_limit_exceeded

Status: 429

Too many requests in a short time period.

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Rate limit exceeded. Limit: 100 requests/minute",
    "retry_after": 45,
    "status": 429
  }
}

Response Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1700000000
Retry-After: 45

Resolution:

  • Implement exponential backoff
  • Respect the Retry-After header
  • Upgrade to a higher plan for increased limits
  • Use webhooks instead of polling

Validation Errors

invalid_request

Status: 400

Request parameters are invalid.

{
  "error": {
    "code": "invalid_request",
    "message": "Invalid request parameters",
    "validation_errors": [
      {
        "field": "extractor_id",
        "message": "Required field missing"
      },
      {
        "field": "document",
        "message": "Must be base64-encoded string"
      }
    ],
    "status": 400
  }
}

Resolution:

  • Check the validation errors array
  • Fix each invalid field
  • Refer to API documentation for required parameters

invalid_field_definition

Status: 400

Field definition in extractor is invalid.

{
  "error": {
    "code": "invalid_field_definition",
    "message": "Invalid field definition",
    "validation_errors": [
      {
        "field": "field_definitions[0].type",
        "message": "Invalid type 'string'. Valid types: text, number, currency, date, email, phone, boolean, array, object"
      }
    ],
    "status": 400
  }
}

Resolution:

  • Use valid field types
  • Check field definition structure
  • Ensure all required attributes are present

Server Errors

internal_error

Status: 500

An unexpected error occurred on the server.

{
  "error": {
    "code": "internal_error",
    "message": "An internal error occurred. Please try again later",
    "request_id": "req_abc123...",
    "status": 500
  }
}

Resolution:

  • Retry the request after a short delay
  • Contact support if the issue persists, providing the request_id

service_unavailable

Status: 503

The service is temporarily unavailable.

{
  "error": {
    "code": "service_unavailable",
    "message": "Service temporarily unavailable. Please try again later",
    "retry_after": 60,
    "status": 503
  }
}

Resolution:

  • Retry after the specified time
  • Check status page for service updates

ai_model_error

Status: 500

The AI model encountered an error during processing.

{
  "error": {
    "code": "ai_model_error",
    "message": "AI model temporarily unavailable",
    "suggestion": "Please retry your request",
    "status": 500
  }
}

Resolution:

  • Retry the request
  • Contact support if errors persist

Error Handling Best Practices

Retry Strategy

Implement exponential backoff for transient errors:

async function robustApiCall<T>(
  apiCall: () => Promise<T>,
  maxRetries: number = 3
): Promise<T> {
  let lastError: Error;

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await apiCall();
    } catch (error: any) {
      lastError = error;

      // Don't retry client errors (4xx except 429)
      if (error.status >= 400 && error.status < 500 && error.status !== 429) {
        throw error;
      }

      // Calculate backoff delay
      const delay = Math.min(1000 * Math.pow(2, attempt), 30000);

      // Use Retry-After header if available
      const retryAfter = error.retry_after
        ? error.retry_after * 1000
        : delay;

      console.log(`Attempt ${attempt + 1} failed. Retrying in ${retryAfter}ms...`);
      await sleep(retryAfter);
    }
  }

  throw lastError!;
}

// Usage
const job = await robustApiCall(async () => {
  const response = await fetch('https://api.adteco.com/v1/documents', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer sk_live_your_api_key',
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      extractor_id: 'ext_abc123...',
      document: base64Document,
      mime_type: 'application/pdf',
    }),
  });

  if (!response.ok) {
    const error = await response.json();
    throw Object.assign(new Error(error.error.message), {
      status: response.status,
      code: error.error.code,
      retry_after: response.headers.get('Retry-After'),
    });
  }

  return response.json();
});

Error Classification

Categorize errors for better handling:

interface ApiError {
  code: string;
  message: string;
  status: number;
  retry_after?: number;
}

function classifyError(error: ApiError): ErrorCategory {
  // Authentication errors
  if (error.status === 401 || error.status === 403) {
    return 'authentication';
  }

  // Validation errors
  if (error.status === 400 || error.status === 422) {
    return 'validation';
  }

  // Resource errors
  if (error.status === 404 || error.status === 409) {
    return 'resource';
  }

  // Rate limiting
  if (error.status === 429) {
    return 'rate_limit';
  }

  // Credit errors
  if (error.status === 402) {
    return 'billing';
  }

  // Server errors
  if (error.status >= 500) {
    return 'server';
  }

  return 'unknown';
}

type ErrorCategory =
  | 'authentication'
  | 'validation'
  | 'resource'
  | 'rate_limit'
  | 'billing'
  | 'server'
  | 'unknown';

// Handle based on category
try {
  await processDocument(extractorId, documentPath);
} catch (error: any) {
  const category = classifyError(error);

  switch (category) {
    case 'authentication':
      console.error('Authentication failed. Check your API key.');
      break;

    case 'validation':
      console.error('Invalid request:', error.message);
      break;

    case 'rate_limit':
      console.warn('Rate limited. Retrying after delay...');
      await sleep(error.retry_after * 1000);
      // Retry request
      break;

    case 'billing':
      console.error('Insufficient credits. Purchase more to continue.');
      // Redirect to billing page
      break;

    case 'server':
      console.error('Server error. Retrying...');
      // Retry with backoff
      break;

    default:
      console.error('Unexpected error:', error);
  }
}

User-Friendly Messages

Convert technical errors to user-friendly messages:

const ERROR_MESSAGES: Record<string, string> = {
  document_too_large: 'The document is too large. Please upload a smaller file.',
  document_unreadable: 'We couldn\'t read this document. Please upload a clearer image.',
  unsupported_format: 'This file format is not supported. Please use PDF, PNG, or JPG.',
  insufficient_credits: 'You\'re out of credits. Please purchase more to continue.',
  rate_limit_exceeded: 'You\'re sending requests too quickly. Please slow down.',
  invalid_api_key: 'Your API key is invalid. Please check your settings.',
  extractor_not_found: 'The selected template was not found.',
};

function getUserFriendlyMessage(errorCode: string): string {
  return ERROR_MESSAGES[errorCode] || 'An unexpected error occurred. Please try again.';
}

// Usage in UI
try {
  await uploadDocument(file);
} catch (error: any) {
  const userMessage = getUserFriendlyMessage(error.code);
  showToast('error', userMessage);
}

Logging and Monitoring

Log errors for debugging and monitoring:

import * as Sentry from '@sentry/node';

async function processDocumentWithErrorTracking(
  extractorId: string,
  documentPath: string
) {
  try {
    return await processDocument(extractorId, documentPath);
  } catch (error: any) {
    // Log to error tracking service
    Sentry.captureException(error, {
      tags: {
        api: 'docextract',
        error_code: error.code,
      },
      extra: {
        extractor_id: extractorId,
        document_path: documentPath,
        request_id: error.request_id,
      },
    });

    // Log to console
    console.error('DocExtract API Error:', {
      code: error.code,
      message: error.message,
      request_id: error.request_id,
      timestamp: new Date().toISOString(),
    });

    throw error;
  }
}

Error Testing

Test your error handling during development:

// Simulate different error scenarios
async function testErrorHandling() {
  const testCases = [
    {
      name: 'Invalid API Key',
      apiKey: 'sk_test_invalid',
      expectedError: 'invalid_api_key',
    },
    {
      name: 'Missing Document',
      data: { extractor_id: 'ext_123' }, // Missing document field
      expectedError: 'invalid_request',
    },
    {
      name: 'Invalid Extractor',
      data: {
        extractor_id: 'ext_nonexistent',
        document: 'base64data',
        mime_type: 'application/pdf',
      },
      expectedError: 'extractor_not_found',
    },
  ];

  for (const test of testCases) {
    try {
      await submitDocument(test.data);
      console.error(`❌ ${test.name}: Should have thrown error`);
    } catch (error: any) {
      if (error.code === test.expectedError) {
        console.log(`✅ ${test.name}: Correct error caught`);
      } else {
        console.error(`❌ ${test.name}: Wrong error. Expected ${test.expectedError}, got ${error.code}`);
      }
    }
  }
}

Getting Support

If you encounter persistent errors:

  1. Check the status page: status.adteco.com
  2. Review documentation: Verify you're using the API correctly
  3. Contact support: Email support@adteco.com with:
    • Error code and message
    • Request ID (from error response)
    • Steps to reproduce
    • Timestamp of the error

Next Steps