Overview

Contazen uses conventional HTTP response codes to indicate the success or failure of an API request.
RangeMeaning
2xxSuccess - Request completed successfully
4xxClient Error - Invalid request parameters
5xxServer Error - Something went wrong on our end

Error Response Format

All error responses follow a consistent structure:
{
  "success": false,
  "error": {
    "message": "Human-readable error message",
    "type": "error_type",
    "code": "error_code",
    "status": 400
  },
  "meta": {
    "version": "v1",
    "response_time": "12.5ms"
  }
}

Error Types

Type: authentication_errorThese errors occur when there’s a problem with your API key.
CodeStatusDescription
missing_api_key401No Authorization header provided
invalid_api_key401API key doesn’t exist or is invalid
expired_api_key401API key has expired
ip_restricted401Request from unauthorized IP
insufficient_permissions403API key lacks required permissions
Example:
{
  "success": false,
  "error": {
    "message": "Invalid API key",
    "type": "authentication_error",
    "code": "invalid_api_key",
    "status": 401
  }
}
Type: validation_errorThese errors occur when request parameters fail validation.
CodeStatusDescription
invalid_request400General validation failure
missing_required_field400Required field not provided
invalid_field_value400Field value doesn’t meet requirements
invalid_format400Data format is incorrect
Example with field-specific errors:
{
  "success": false,
  "error": {
    "message": "Validation failed",
    "type": "validation_error",
    "code": "invalid_request",
    "status": 400,
    "errors": {
      "client_data.cui": "Invalid CUI format",
      "items.0.price": "Price must be greater than 0",
      "email": "Invalid email address"
    }
  }
}
Type: rate_limit_errorReturned when you exceed the allowed number of requests.
CodeStatusDescription
rate_limit_exceeded429Too many requests
Example:
{
  "success": false,
  "error": {
    "message": "Rate limit exceeded",
    "type": "rate_limit_error",
    "code": "rate_limit_exceeded",
    "retry_after": 45,
    "status": 429
  }
}
Check the response headers for rate limit information:
  • X-RateLimit-Limit: Maximum requests allowed
  • X-RateLimit-Remaining: Requests remaining
  • X-RateLimit-Reset: Reset time (Unix timestamp)
Type: resource_errorThese errors relate to specific resources.
CodeStatusDescription
resource_not_found404Requested resource doesn’t exist
resource_already_exists409Resource with same identifier exists
resource_locked423Resource is locked for editing
Example:
{
  "success": false,
  "error": {
    "message": "Client not found",
    "type": "resource_error",
    "code": "resource_not_found",
    "status": 404
  }
}
Type: api_errorThese indicate problems on our servers.
CodeStatusDescription
internal_server_error500Unexpected server error
service_unavailable503Service temporarily unavailable
Example:
{
  "success": false,
  "error": {
    "message": "An unexpected error occurred",
    "type": "api_error",
    "code": "internal_server_error",
    "status": 500,
    "request_id": "req_1a2b3c4d5e"
  }
}

Handling Errors

Best Practices

1

Always check the response status

Don’t assume a request succeeded. Check the HTTP status code and success field.
2

Log error details

Store the full error response, especially the request_id for debugging.
3

Handle specific error types

Implement different handling for different error types.
4

Implement retry logic

For 5xx errors and rate limits, implement exponential backoff.

Example Error Handling

async function makeApiRequest(endpoint, options = {}) {
  try {
    const response = await fetch(`${API_BASE}${endpoint}`, {
      ...options,
      headers: {
        'Authorization': `Bearer ${API_KEY}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    const data = await response.json();

    if (!response.ok) {
      // Handle different error types
      switch (data.error?.type) {
        case 'authentication_error':
          throw new AuthError(data.error.message);
        
        case 'validation_error':
          throw new ValidationError(data.error.message, data.error.errors);
        
        case 'rate_limit_error':
          const retryAfter = data.error.retry_after || 60;
          throw new RateLimitError(data.error.message, retryAfter);
        
        default:
          throw new ApiError(data.error.message, data.error.code);
      }
    }

    return data;
  } catch (error) {
    // Handle network errors
    if (error instanceof TypeError) {
      throw new NetworkError('Network request failed');
    }
    throw error;
  }
}

// Usage with retry logic
async function createInvoiceWithRetry(invoiceData, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await makeApiRequest('/invoices', {
        method: 'POST',
        body: JSON.stringify(invoiceData)
      });
    } catch (error) {
      if (error instanceof RateLimitError) {
        // Wait and retry
        await sleep(error.retryAfter * 1000);
        continue;
      }
      
      if (error instanceof ApiError && i < maxRetries - 1) {
        // Exponential backoff for server errors
        await sleep(Math.pow(2, i) * 1000);
        continue;
      }
      
      throw error;
    }
  }
}

Common Error Scenarios

Invalid CUI Format

{
  "error": {
    "message": "Validation failed",
    "errors": {
      "cui": "CUI must be RO followed by 2-10 digits"
    }
  }
}
Solution: Ensure CUI starts with “RO” for Romanian companies

Duplicate Invoice Number

{
  "error": {
    "message": "Invoice number already exists",
    "code": "duplicate_invoice_number"
  }
}
Solution: Let the system auto-generate numbers

Missing Required Fields

{
  "error": {
    "message": "Validation failed",
    "errors": {
      "items": "At least one item is required",
      "client_id": "Client is required"
    }
  }
}
Solution: Check all required fields are provided

Invalid Date Format

{
  "error": {
    "message": "Invalid date format",
    "errors": {
      "date": "Date must be in YYYY-MM-DD format"
    }
  }
}
Solution: Use ISO 8601 date format

e-Factura Not Configured

{
  "error": {
    "message": "e-Factura OAuth not configured",
    "code": "efactura_oauth_not_configured",
    "type": "invalid_request_error"
  }
}
Solution: Complete OAuth setup in settings

Invoice Already Sent to SPV

{
  "error": {
    "message": "Invoice already sent to SPV",
    "code": "already_sent_to_spv",
    "current_status": "submitted"
  }
}
Solution: Check invoice status before sending

Cannot Delete Used Product

{
  "error": {
    "message": "Cannot delete product with associated invoices",
    "code": "product_has_invoices",
    "invoice_count": 5
  }
}
Solution: Products used in invoices cannot be deleted

Getting Help

If you encounter an error you can’t resolve:
  1. Check the error message and code - They provide specific information about what went wrong
  2. Review the API documentation - Ensure you’re using the correct parameters
  3. Include the request ID - Found in error responses for server errors
  4. Contact support - Email contact@contazen.ro with details