Airbyte source connector for extracting financial and accounting data from Xero's cloud-based accounting platform.
npx @tessl/cli install tessl/pypi-source-xero@0.2.00
# Airbyte Source Xero
1
2
An Airbyte source connector for extracting financial and accounting data from Xero's cloud-based accounting platform. This connector implements the Airbyte CDK framework to enable data synchronization from Xero's API endpoints including accounts, contacts, invoices, and other financial data with OAuth 2.0 authentication support.
3
4
## Package Information
5
6
- **Package Name**: source-xero
7
- **Package Type**: Python (Airbyte Connector)
8
- **Language**: Python 3.8+
9
- **Installation**: Integrated with Airbyte platform
10
- **Dependencies**: `airbyte-cdk~=0.40`
11
12
## Core Imports
13
14
```python
15
from source_xero import SourceXero
16
```
17
18
For individual stream classes:
19
20
```python
21
from source_xero.source import SourceXero
22
from source_xero.streams import Accounts, BankTransactions, Contacts, Invoices
23
from source_xero.oauth import XeroSingleUseRefreshTokenOauth2Authenticator
24
```
25
26
## Basic Usage
27
28
```python
29
from source_xero import SourceXero
30
import logging
31
32
# Configure logger
33
logger = logging.getLogger("airbyte")
34
35
# Configuration with OAuth2 credentials
36
config = {
37
"authentication": {
38
"client_id": "your-xero-client-id",
39
"client_secret": "your-xero-client-secret",
40
"refresh_token": "your-refresh-token",
41
"access_token": "your-access-token",
42
"token_expiry_date": "2024-12-31T23:59:59Z"
43
},
44
"tenant_id": "your-xero-tenant-id",
45
"start_date": "2023-01-01T00:00:00Z"
46
}
47
48
# Initialize the source
49
source = SourceXero()
50
51
# Test connection
52
is_connected, error = source.check_connection(logger, config)
53
if is_connected:
54
# Get available streams
55
streams = source.streams(config)
56
print(f"Available streams: {len(streams)}")
57
else:
58
print(f"Connection failed: {error}")
59
```
60
61
## Architecture
62
63
The connector follows Airbyte's architecture pattern with distinct layers:
64
65
- **Source Class**: Main `SourceXero` class implementing `AbstractSource` interface
66
- **Authentication Layer**: OAuth2 implementation with automatic token refresh
67
- **Stream Classes**: 21 data streams (14 incremental, 7 full-refresh) each extending base classes
68
- **Schema Definitions**: JSON schemas for all Xero data types and validation
69
70
The connector supports both incremental and full-refresh synchronization modes, with incremental streams using `UpdatedDateUTC` (or `CreatedDateUTC` for bank transfers) as cursor fields.
71
72
## Capabilities
73
74
### Source Configuration
75
76
Core source configuration and connection validation functionality. Handles OAuth2 authentication setup, connection testing, and stream discovery for the Xero API.
77
78
```python { .api }
79
class SourceXero(AbstractSource):
80
def check_connection(self, logger, config) -> Tuple[bool, any]: ...
81
def streams(self, config: Mapping[str, Any]) -> List[Stream]: ...
82
@staticmethod
83
def get_authenticator(config: Mapping[str, Any]) -> XeroSingleUseRefreshTokenOauth2Authenticator: ...
84
```
85
86
[Source Configuration](./source-configuration.md)
87
88
### OAuth2 Authentication
89
90
OAuth2 authentication implementation with automatic token refresh, rate limiting handling, and secure credential management for Xero API access.
91
92
```python { .api }
93
class XeroSingleUseRefreshTokenOauth2Authenticator(SingleUseRefreshTokenOauth2Authenticator):
94
def build_refresh_request_body(self) -> Mapping[str, Any]: ...
95
def build_refresh_request_headers(self) -> Mapping[str, Any]: ...
96
```
97
98
[OAuth2 Authentication](./oauth-authentication.md)
99
100
### Incremental Data Streams
101
102
Fourteen incremental sync streams that synchronize only new or updated records since the last sync. These streams handle financial transactions, customer data, and accounting records with efficient incremental updates.
103
104
```python { .api }
105
class IncrementalXeroStream(XeroStream, ABC):
106
cursor_field: str = "UpdatedDateUTC"
107
state_checkpoint_interval: int = 100
108
def get_updated_state(self, current_stream_state, latest_record) -> Mapping[str, Any]: ...
109
```
110
111
[Incremental Streams](./incremental-streams.md)
112
113
### Full Refresh Data Streams
114
115
Seven full-refresh streams that synchronize complete datasets on each sync. These streams handle reference data like currencies, tax rates, and organizational settings that require complete snapshots.
116
117
```python { .api }
118
class XeroStream(HttpStream, ABC):
119
url_base: str = "https://api.xero.com/api.xro/2.0/"
120
page_size: int = 100
121
def parse_response(self, response: requests.Response, **kwargs) -> Iterable[Mapping]: ...
122
```
123
124
[Full Refresh Streams](./full-refresh-streams.md)
125
126
### Data Type Utilities
127
128
Utility functions for parsing Xero's custom date formats and JSON data structures, ensuring proper data type conversion and RFC3339 compliance.
129
130
```python { .api }
131
def parse_date(value: str) -> Optional[datetime]: ...
132
def _json_load_object_hook(_dict: dict) -> dict: ...
133
```
134
135
[Data Utilities](./data-utilities.md)
136
137
## Configuration Schema
138
139
The connector requires specific configuration for OAuth2 authentication and tenant identification:
140
141
```python { .api }
142
ConfigSpec = {
143
"authentication": {
144
"client_id": str, # Required: Xero application Client ID
145
"client_secret": str, # Required: Xero application Client Secret (secret)
146
"refresh_token": str, # Required: OAuth refresh token (secret)
147
"access_token": str, # Required: OAuth access token (secret)
148
"token_expiry_date": str # Required: Token expiry date-time
149
},
150
"tenant_id": str, # Required: Xero organization Tenant ID (secret)
151
"start_date": str # Required: UTC date in YYYY-MM-DDTHH-mm-ssZ format
152
}
153
```
154
155
## Types
156
157
```python { .api }
158
from typing import Any, List, Mapping, Tuple, Optional, Iterable, MutableMapping
159
from datetime import datetime
160
from airbyte_cdk.sources import AbstractSource
161
from airbyte_cdk.sources.streams import Stream
162
from airbyte_cdk.sources.streams.http import HttpStream
163
from airbyte_cdk.sources.streams.http.requests_native_auth import SingleUseRefreshTokenOauth2Authenticator
164
import requests
165
166
# Core type aliases
167
ConfigMapping = Mapping[str, Any]
168
StreamState = MutableMapping[str, Any]
169
RecordMapping = Mapping[str, Any]
170
171
# Authentication types
172
class XeroSingleUseRefreshTokenOauth2Authenticator(SingleUseRefreshTokenOauth2Authenticator):
173
"""OAuth2 authenticator with Xero-specific token refresh handling."""
174
pass
175
176
# Stream base classes
177
class XeroStream(HttpStream):
178
"""Base class for all Xero API streams."""
179
url_base: str
180
page_size: int
181
current_page: int
182
pagination: bool
183
primary_key: str
184
tenant_id: str
185
186
class IncrementalXeroStream(XeroStream):
187
"""Base class for incremental sync streams."""
188
cursor_field: str
189
state_checkpoint_interval: int
190
start_date: datetime
191
```
192
193
## Error Handling
194
195
The connector implements comprehensive error handling for common Xero API scenarios:
196
197
- **Rate Limiting**: Automatic backoff and retry for 429 responses
198
- **Server Errors**: Retry logic for 500+ status codes
199
- **Authentication Errors**: Automatic token refresh on 401 responses
200
- **Validation Errors**: Detailed error reporting for configuration issues
201
- **Network Errors**: Connection timeout and retry handling
202
203
## Limitations and Requirements
204
205
- **Custom Connections**: Requires Xero Custom Connections subscription for production use
206
- **Tenant Scope**: Each configuration is limited to a single Xero tenant
207
- **Rate Limits**: Subject to Xero API rate limits (handled automatically)
208
- **OAuth2 Flow**: Requires valid OAuth2 credentials with appropriate scopes
209
- **Date Ranges**: Incremental streams limited by Xero's data retention policies