0
# Configuration & Authentication
1
2
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.
3
4
## Capabilities
5
6
### Configuration Schema
7
8
Complete specification of required and optional configuration parameters for connecting to Xero's API.
9
10
```python { .api }
11
ConfigurationSpec = {
12
"type": "object",
13
"required": ["access_token", "tenant_id", "start_date"],
14
"additionalProperties": True,
15
"properties": {
16
"access_token": {
17
"type": "string",
18
"title": "Access Token",
19
"description": "Enter your Xero application's access token",
20
"airbyte_secret": True,
21
"order": 0
22
},
23
"tenant_id": {
24
"type": "string",
25
"title": "Tenant ID",
26
"description": "Enter your Xero organization's Tenant ID",
27
"airbyte_secret": True,
28
"order": 1
29
},
30
"start_date": {
31
"type": "string",
32
"title": "Start Date",
33
"pattern": "^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$",
34
"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.",
35
"examples": ["2022-03-01T00:00:00Z"],
36
"format": "date-time",
37
"order": 2
38
}
39
}
40
}
41
"""
42
Configuration schema for Xero source connector.
43
44
All three fields are required for successful connection:
45
- access_token: OAuth 2.0 bearer token for API authentication
46
- tenant_id: Xero organization identifier for multi-tenant access
47
- start_date: Defines the earliest date for incremental sync operations
48
"""
49
```
50
51
### Authentication Configuration
52
53
Details on Xero API authentication using OAuth 2.0 bearer tokens with tenant-specific access control.
54
55
```python { .api }
56
# Authentication headers automatically applied to all requests
57
AuthenticationHeaders = {
58
"Authorization": "Bearer {access_token}",
59
"Xero-Tenant-Id": "{tenant_id}",
60
"Accept": "application/json"
61
}
62
"""
63
HTTP headers used for Xero API authentication.
64
65
The connector automatically applies these headers to all API requests:
66
- Authorization: OAuth 2.0 bearer token authentication
67
- Xero-Tenant-Id: Required for multi-tenant Xero applications
68
- Accept: Specifies JSON response format preference
69
"""
70
71
# Base API configuration
72
APIConfiguration = {
73
"base_url": "https://api.xero.com/api.xro/2.0/",
74
"http_method": "GET",
75
"authenticator_type": "BearerAuthenticator"
76
}
77
"""
78
Core API configuration for Xero API endpoints.
79
80
All API calls use:
81
- HTTPS with Xero's standard API base URL
82
- GET method for data extraction (read-only operations)
83
- Bearer token authentication for security
84
"""
85
```
86
87
### Error Handling Configuration
88
89
Comprehensive error handling rules for different HTTP response scenarios with appropriate retry and failure strategies.
90
91
```python { .api }
92
ErrorHandlingRules = {
93
"401_unauthorized": {
94
"action": "FAIL",
95
"error_message": "Failed to authorize request. Please update your access token to continue using the source."
96
},
97
"403_forbidden": {
98
"action": "IGNORE",
99
"description": "Permission denied for specific records - skip and continue"
100
},
101
"429_rate_limited": {
102
"action": "RETRY",
103
"backoff_strategy": {
104
"type": "ConstantBackoffStrategy",
105
"backoff_time_in_seconds": 30
106
}
107
}
108
}
109
"""
110
HTTP error handling configuration for robust API interactions.
111
112
Response handling strategies:
113
- 401: Authentication failure - halt sync with clear error message
114
- 403: Permission denied - skip individual records, continue sync
115
- 429: Rate limit exceeded - retry after 30 second delay
116
"""
117
```
118
119
## Usage Examples
120
121
### Basic Configuration Setup
122
123
```python
124
# Minimum required configuration
125
config = {
126
"access_token": "your_xero_access_token_here",
127
"tenant_id": "your_xero_tenant_id_here",
128
"start_date": "2023-01-01T00:00:00Z"
129
}
130
131
# Validate configuration format
132
import re
133
from datetime import datetime
134
135
def validate_config(config):
136
"""Validate configuration parameters."""
137
errors = []
138
139
# Check required fields
140
required_fields = ["access_token", "tenant_id", "start_date"]
141
for field in required_fields:
142
if field not in config or not config[field]:
143
errors.append(f"Missing required field: {field}")
144
145
# Validate start_date format
146
if "start_date" in config:
147
pattern = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$"
148
if not re.match(pattern, config["start_date"]):
149
errors.append("start_date must be in format YYYY-MM-DDTHH:mm:ssZ")
150
151
return len(errors) == 0, errors
152
153
# Validate the configuration
154
is_valid, validation_errors = validate_config(config)
155
if is_valid:
156
print("Configuration is valid")
157
else:
158
print("Configuration errors:", validation_errors)
159
```
160
161
### Connection Testing
162
163
```python
164
from source_xero import SourceXero
165
import logging
166
167
def test_connection(config):
168
"""Test connection with proper error handling."""
169
source = SourceXero()
170
logger = logging.getLogger(__name__)
171
172
try:
173
is_connected, error_message = source.check_connection(logger, config)
174
175
if is_connected:
176
print("✓ Successfully connected to Xero API")
177
return True
178
else:
179
print(f"✗ Connection failed: {error_message}")
180
181
# Handle common error scenarios
182
if "authorize" in error_message.lower():
183
print(" → Check your access_token is valid and not expired")
184
elif "tenant" in error_message.lower():
185
print(" → Verify your tenant_id is correct")
186
187
return False
188
189
except Exception as e:
190
print(f"✗ Connection test error: {str(e)}")
191
return False
192
193
# Test with configuration
194
config = {
195
"access_token": "your_token",
196
"tenant_id": "your_tenant",
197
"start_date": "2023-01-01T00:00:00Z"
198
}
199
200
connection_success = test_connection(config)
201
```
202
203
### Advanced Configuration
204
205
```python
206
# Configuration with additional properties
207
advanced_config = {
208
# Required fields
209
"access_token": "your_xero_oauth_token",
210
"tenant_id": "12345678-1234-1234-1234-123456789012",
211
"start_date": "2023-01-01T00:00:00Z",
212
213
# Additional properties (connector supports extensibility)
214
"request_timeout": 30,
215
"max_retries": 3,
216
"log_level": "INFO"
217
}
218
219
# Start date configuration examples
220
start_date_examples = {
221
"recent_data": "2023-12-01T00:00:00Z", # Last month
222
"current_year": "2024-01-01T00:00:00Z", # Current year
223
"historical": "2020-01-01T00:00:00Z", # Historical data
224
"specific_time": "2023-06-15T14:30:00Z" # Specific timestamp
225
}
226
```
227
228
## Security Considerations
229
230
### Token Management
231
232
```python
233
import os
234
from pathlib import Path
235
236
def load_secure_config():
237
"""Load configuration from environment variables for security."""
238
config = {
239
"access_token": os.getenv("XERO_ACCESS_TOKEN"),
240
"tenant_id": os.getenv("XERO_TENANT_ID"),
241
"start_date": os.getenv("XERO_START_DATE", "2023-01-01T00:00:00Z")
242
}
243
244
# Validate all required environment variables are set
245
missing_vars = [key for key, value in config.items() if not value]
246
if missing_vars:
247
raise ValueError(f"Missing environment variables: {missing_vars}")
248
249
return config
250
251
# Usage with environment variables
252
# export XERO_ACCESS_TOKEN="your_token_here"
253
# export XERO_TENANT_ID="your_tenant_id_here"
254
# export XERO_START_DATE="2023-01-01T00:00:00Z"
255
256
secure_config = load_secure_config()
257
```
258
259
### Access Token Best Practices
260
261
- **Token Rotation**: Implement regular token refresh for long-running processes
262
- **Scope Limitation**: Use tokens with minimal required permissions
263
- **Secure Storage**: Store tokens in environment variables or secure vaults
264
- **Monitoring**: Log authentication failures for security monitoring
265
- **Expiry Handling**: Implement graceful handling of expired tokens
266
267
### Tenant ID Security
268
269
- **Validation**: Verify tenant IDs match expected format (UUID)
270
- **Access Control**: Ensure tokens have permission for specified tenant
271
- **Multi-tenant Apps**: Handle tenant switching in multi-organization scenarios
272
- **Audit Logging**: Track which tenants are accessed for compliance
273
274
## Troubleshooting
275
276
Common configuration issues and solutions:
277
278
```python
279
def diagnose_config_issues(config, error_message):
280
"""Diagnose common configuration problems."""
281
suggestions = []
282
283
if "401" in error_message or "unauthorized" in error_message.lower():
284
suggestions.extend([
285
"Verify access_token is valid and not expired",
286
"Check token has required scopes: accounting.transactions.read, accounting.contacts.read",
287
"Ensure token was generated for the correct Xero application"
288
])
289
290
if "403" in error_message or "forbidden" in error_message.lower():
291
suggestions.extend([
292
"Verify tenant_id matches the organization you have access to",
293
"Check your Xero application has permission to access this tenant",
294
"Ensure the organization subscription includes required features"
295
])
296
297
if "tenant" in error_message.lower():
298
suggestions.extend([
299
"Verify tenant_id is in correct UUID format",
300
"Check tenant_id matches an organization you have access to",
301
"Try using the organization's short code instead if supported"
302
])
303
304
return suggestions
305
306
# Example usage
307
error_msg = "Failed to authorize request"
308
suggestions = diagnose_config_issues(config, error_msg)
309
for suggestion in suggestions:
310
print(f" → {suggestion}")
311
```