CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-airbyte-source-xero

Airbyte source connector for extracting data from the Xero accounting API with support for 21 data streams and incremental sync capabilities

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

configuration.mddocs/

Configuration & Authentication

Configuration specification and authentication setup for connecting to the Xero API. This includes credential management, tenant identification, and sync boundary configuration with comprehensive validation and security features.

Capabilities

Configuration Schema

Complete specification of required and optional configuration parameters for connecting to Xero's API.

ConfigurationSpec = {
    "type": "object",
    "required": ["access_token", "tenant_id", "start_date"],
    "additionalProperties": True,
    "properties": {
        "access_token": {
            "type": "string",
            "title": "Access Token",
            "description": "Enter your Xero application's access token",
            "airbyte_secret": True,
            "order": 0
        },
        "tenant_id": {
            "type": "string", 
            "title": "Tenant ID",
            "description": "Enter your Xero organization's Tenant ID",
            "airbyte_secret": True,
            "order": 1
        },
        "start_date": {
            "type": "string",
            "title": "Start Date", 
            "pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$",
            "description": "UTC date and time in the format YYYY-MM-DDTHH:mm:ssZ. Any data with created_at before this data will not be synced.",
            "examples": ["2022-03-01T00:00:00Z"],
            "format": "date-time",
            "order": 2
        }
    }
}
"""
Configuration schema for Xero source connector.

All three fields are required for successful connection:
- access_token: OAuth 2.0 bearer token for API authentication
- tenant_id: Xero organization identifier for multi-tenant access
- start_date: Defines the earliest date for incremental sync operations
"""

Authentication Configuration

Details on Xero API authentication using OAuth 2.0 bearer tokens with tenant-specific access control.

# Authentication headers automatically applied to all requests
AuthenticationHeaders = {
    "Authorization": "Bearer {access_token}",
    "Xero-Tenant-Id": "{tenant_id}",
    "Accept": "application/json"
}
"""
HTTP headers used for Xero API authentication.

The connector automatically applies these headers to all API requests:
- Authorization: OAuth 2.0 bearer token authentication
- Xero-Tenant-Id: Required for multi-tenant Xero applications  
- Accept: Specifies JSON response format preference
"""

# Base API configuration
APIConfiguration = {
    "base_url": "https://api.xero.com/api.xro/2.0/",
    "http_method": "GET",
    "authenticator_type": "BearerAuthenticator"
}
"""
Core API configuration for Xero API endpoints.

All API calls use:
- HTTPS with Xero's standard API base URL
- GET method for data extraction (read-only operations)
- Bearer token authentication for security
"""

Error Handling Configuration

Comprehensive error handling rules for different HTTP response scenarios with appropriate retry and failure strategies.

ErrorHandlingRules = {
    "401_unauthorized": {
        "action": "FAIL",
        "error_message": "Failed to authorize request. Please update your access token to continue using the source."
    },
    "403_forbidden": {
        "action": "IGNORE", 
        "description": "Permission denied for specific records - skip and continue"
    },
    "429_rate_limited": {
        "action": "RETRY",
        "backoff_strategy": {
            "type": "ConstantBackoffStrategy", 
            "backoff_time_in_seconds": 30
        }
    }
}
"""
HTTP error handling configuration for robust API interactions.

Response handling strategies:
- 401: Authentication failure - halt sync with clear error message
- 403: Permission denied - skip individual records, continue sync
- 429: Rate limit exceeded - retry after 30 second delay
"""

Usage Examples

Basic Configuration Setup

# Minimum required configuration
config = {
    "access_token": "your_xero_access_token_here",
    "tenant_id": "your_xero_tenant_id_here",
    "start_date": "2023-01-01T00:00:00Z"
}

# Validate configuration format
import re
from datetime import datetime

def validate_config(config):
    """Validate configuration parameters."""
    errors = []
    
    # Check required fields
    required_fields = ["access_token", "tenant_id", "start_date"]
    for field in required_fields:
        if field not in config or not config[field]:
            errors.append(f"Missing required field: {field}")
    
    # Validate start_date format
    if "start_date" in config:
        pattern = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
        if not re.match(pattern, config["start_date"]):
            errors.append("start_date must be in format YYYY-MM-DDTHH:mm:ssZ")
    
    return len(errors) == 0, errors

# Validate the configuration
is_valid, validation_errors = validate_config(config)
if is_valid:
    print("Configuration is valid")
else:
    print("Configuration errors:", validation_errors)

Connection Testing

from source_xero import SourceXero
import logging

def test_connection(config):
    """Test connection with proper error handling."""
    source = SourceXero()
    logger = logging.getLogger(__name__)
    
    try:
        is_connected, error_message = source.check_connection(logger, config)
        
        if is_connected:
            print("✓ Successfully connected to Xero API")
            return True
        else:
            print(f"✗ Connection failed: {error_message}")
            
            # Handle common error scenarios
            if "authorize" in error_message.lower():
                print("  → Check your access_token is valid and not expired")
            elif "tenant" in error_message.lower():
                print("  → Verify your tenant_id is correct")
            
            return False
            
    except Exception as e:
        print(f"✗ Connection test error: {str(e)}")
        return False

# Test with configuration
config = {
    "access_token": "your_token",
    "tenant_id": "your_tenant",
    "start_date": "2023-01-01T00:00:00Z"
}

connection_success = test_connection(config)

Advanced Configuration

# Configuration with additional properties
advanced_config = {
    # Required fields
    "access_token": "your_xero_oauth_token",
    "tenant_id": "12345678-1234-1234-1234-123456789012", 
    "start_date": "2023-01-01T00:00:00Z",
    
    # Additional properties (connector supports extensibility)
    "request_timeout": 30,
    "max_retries": 3,
    "log_level": "INFO"
}

# Start date configuration examples
start_date_examples = {
    "recent_data": "2023-12-01T00:00:00Z",      # Last month
    "current_year": "2024-01-01T00:00:00Z",     # Current year
    "historical": "2020-01-01T00:00:00Z",       # Historical data
    "specific_time": "2023-06-15T14:30:00Z"     # Specific timestamp
}

Security Considerations

Token Management

import os
from pathlib import Path

def load_secure_config():
    """Load configuration from environment variables for security."""
    config = {
        "access_token": os.getenv("XERO_ACCESS_TOKEN"),
        "tenant_id": os.getenv("XERO_TENANT_ID"), 
        "start_date": os.getenv("XERO_START_DATE", "2023-01-01T00:00:00Z")
    }
    
    # Validate all required environment variables are set
    missing_vars = [key for key, value in config.items() if not value]
    if missing_vars:
        raise ValueError(f"Missing environment variables: {missing_vars}")
    
    return config

# Usage with environment variables
# export XERO_ACCESS_TOKEN="your_token_here"
# export XERO_TENANT_ID="your_tenant_id_here" 
# export XERO_START_DATE="2023-01-01T00:00:00Z"

secure_config = load_secure_config()

Access Token Best Practices

  • Token Rotation: Implement regular token refresh for long-running processes
  • Scope Limitation: Use tokens with minimal required permissions
  • Secure Storage: Store tokens in environment variables or secure vaults
  • Monitoring: Log authentication failures for security monitoring
  • Expiry Handling: Implement graceful handling of expired tokens

Tenant ID Security

  • Validation: Verify tenant IDs match expected format (UUID)
  • Access Control: Ensure tokens have permission for specified tenant
  • Multi-tenant Apps: Handle tenant switching in multi-organization scenarios
  • Audit Logging: Track which tenants are accessed for compliance

Troubleshooting

Common configuration issues and solutions:

def diagnose_config_issues(config, error_message):
    """Diagnose common configuration problems."""
    suggestions = []
    
    if "401" in error_message or "unauthorized" in error_message.lower():
        suggestions.extend([
            "Verify access_token is valid and not expired",
            "Check token has required scopes: accounting.transactions.read, accounting.contacts.read",
            "Ensure token was generated for the correct Xero application"
        ])
    
    if "403" in error_message or "forbidden" in error_message.lower():
        suggestions.extend([
            "Verify tenant_id matches the organization you have access to",
            "Check your Xero application has permission to access this tenant",
            "Ensure the organization subscription includes required features"
        ])
    
    if "tenant" in error_message.lower():
        suggestions.extend([
            "Verify tenant_id is in correct UUID format", 
            "Check tenant_id matches an organization you have access to",
            "Try using the organization's short code instead if supported"
        ])
    
    return suggestions

# Example usage
error_msg = "Failed to authorize request"
suggestions = diagnose_config_issues(config, error_msg)
for suggestion in suggestions:
    print(f"  → {suggestion}")

Install with Tessl CLI

npx tessl i tessl/pypi-airbyte-source-xero

docs

configuration.md

core-connector.md

data-processing.md

data-streams.md

index.md

tile.json