Document that Companies and Resources entities do not support incremental sync in the Autotask API and automatically fall back to full sync when incremental sync is requested. This clarifies expected behavior and prevents confusion about why these entities always perform full syncs even during incremental sync operations.
759 lines
20 KiB
Markdown
759 lines
20 KiB
Markdown
# Sync Behavior Documentation
|
|
|
|
## Overview
|
|
|
|
This document provides comprehensive details about how the Autotask sync system works, including the differences between sync types, date range filtering, database operations, and entity-specific behaviors.
|
|
|
|
---
|
|
|
|
## Table of Contents
|
|
|
|
- [Sync Types](#sync-types)
|
|
- [Date Range Filtering](#date-range-filtering)
|
|
- [Database Operations](#database-operations)
|
|
- [Entity-Specific Behaviors](#entity-specific-behaviors)
|
|
- [Foreign Key Validation](#foreign-key-validation)
|
|
- [Soft Deletes](#soft-deletes)
|
|
- [Performance Considerations](#performance-considerations)
|
|
|
|
---
|
|
|
|
## Sync Types
|
|
|
|
### Full Sync
|
|
|
|
**What it does:**
|
|
- Fetches **ALL** records from Autotask that match the configured filters
|
|
- Performs an **UPSERT** operation on every fetched record
|
|
- Optionally performs **soft deletes** for missing records (entity-dependent)
|
|
|
|
**When to use:**
|
|
- Initial setup or first-time sync
|
|
- After major data changes in Autotask
|
|
- To ensure complete data consistency
|
|
- When you suspect data drift between systems
|
|
|
|
**Characteristics:**
|
|
- Processes all records within filter criteria (date range, status, etc.)
|
|
- Does NOT check if records have changed - upserts everything
|
|
- Slower than incremental sync
|
|
- More thorough and ensures data consistency
|
|
|
|
**Example:**
|
|
```
|
|
Full Sync of Tickets (last 2 years):
|
|
1. Fetch all tickets created in last 2 years from Autotask
|
|
2. Upsert all fetched tickets to PostgreSQL
|
|
3. Skip soft deletes (has date filter)
|
|
```
|
|
|
|
### Incremental Sync
|
|
|
|
**What it does:**
|
|
- Fetches only records **modified since the last successful sync**
|
|
- Uses `lastModifiedDate` or similar timestamp fields
|
|
- Performs UPSERT on changed records only
|
|
- Does NOT perform soft deletes
|
|
|
|
**When to use:**
|
|
- Regular scheduled syncs (hourly, daily)
|
|
- To keep data up-to-date with minimal overhead
|
|
- When you only need recent changes
|
|
|
|
**Characteristics:**
|
|
- Only processes records that changed since last sync
|
|
- Much faster than full sync
|
|
- Requires a previous successful sync to establish baseline
|
|
- Falls back to full sync if no previous sync found
|
|
|
|
**Important Limitations:**
|
|
- **Companies and Resources** do NOT support incremental sync
|
|
- These entities automatically fall back to full sync
|
|
- Autotask API does not support date-based filtering for these entities
|
|
- This is by design and prevents sync failures
|
|
|
|
**Example:**
|
|
```
|
|
Incremental Sync of Tickets:
|
|
1. Get last sync time: 2026-01-24 08:00:00
|
|
2. Fetch tickets where lastActivityDate >= 2026-01-24 08:00:00
|
|
3. Upsert only the changed tickets
|
|
4. No soft deletes
|
|
|
|
Incremental Sync of Companies (automatic fallback):
|
|
1. Request incremental sync
|
|
2. System detects Companies doesn't support incremental
|
|
3. Automatically performs full sync instead
|
|
4. Logs: "companies does not support incremental sync, performing full sync instead"
|
|
```
|
|
|
|
### Sync Selected (Entity-Specific)
|
|
|
|
**What it does:**
|
|
- Syncs only the selected entities
|
|
- Uses full sync behavior for each selected entity
|
|
- Respects all entity-specific filters and behaviors
|
|
|
|
**When to use:**
|
|
- To sync specific entities without syncing everything
|
|
- After fixing entity-specific issues
|
|
- For testing or troubleshooting
|
|
|
|
---
|
|
|
|
## Date Range Filtering
|
|
|
|
### Entities with Required Filters
|
|
|
|
These entities **REQUIRE** filters - the Autotask API will return an error without them:
|
|
|
|
| Entity | Filter Field | Default Range | Reason |
|
|
|--------|-------------|---------------|---------|
|
|
| **Time Entries** | `dateWorked` | Last 2 years | API requirement |
|
|
| **Billing Items** | `itemDate` | Last 2 years | API requirement |
|
|
| **Contracts** | `status` | Active only (status=1) | API requirement |
|
|
| **Projects** | `status` | Non-completed (status≠5) | API requirement |
|
|
|
|
### Entities with Optional Date Filters
|
|
|
|
These entities have date filters applied for **performance** and **data management**:
|
|
|
|
| Entity | Filter Field | Default Range | Configurable |
|
|
|--------|-------------|---------------|--------------|
|
|
| **Tickets** | `createDate` | Last 2 years | Yes (via yearsBack) |
|
|
| **Tasks** | `createDateTime` | Last 2 years | Yes (via yearsBack) |
|
|
|
|
### Entities Without Date Filters
|
|
|
|
These entities sync **ALL** records (no date filtering):
|
|
|
|
- **Companies** - All active companies
|
|
- **Resources** - All active resources
|
|
- **Contacts** - All active contacts
|
|
- **Configuration Items** - All active items
|
|
- **Picklists** (Statuses, Issue Types, Sub-Issue Types, Work Types) - All values
|
|
|
|
### Configuring Date Range
|
|
|
|
The `yearsBack` parameter controls the date range:
|
|
|
|
```typescript
|
|
// Default: 2 years
|
|
syncService.fullSync(2);
|
|
|
|
// Custom: 5 years
|
|
syncService.fullSync(5);
|
|
|
|
// Via API
|
|
POST /api/sync/full
|
|
{
|
|
"yearsBack": 3,
|
|
"triggeredBy": "user@example.com"
|
|
}
|
|
```
|
|
|
|
**Important Notes:**
|
|
|
|
1. **Date filters apply to BOTH full and incremental sync**
|
|
- Full sync: Fetches all records within date range
|
|
- Incremental sync: Fetches changed records within date range
|
|
|
|
2. **Soft deletes are skipped for date-filtered entities**
|
|
- Prevents deleting old records outside the sync window
|
|
- See [Soft Deletes](#soft-deletes) section
|
|
|
|
---
|
|
|
|
## Database Operations
|
|
|
|
### UPSERT Behavior
|
|
|
|
All syncs use PostgreSQL's `ON CONFLICT DO UPDATE` (UPSERT):
|
|
|
|
```sql
|
|
INSERT INTO table_name (id, field1, field2, ...)
|
|
VALUES ($1, $2, $3, ...)
|
|
ON CONFLICT (id)
|
|
DO UPDATE SET
|
|
field1 = EXCLUDED.field1,
|
|
field2 = EXCLUDED.field2,
|
|
...
|
|
synced_at = NOW()
|
|
```
|
|
|
|
**What this means:**
|
|
|
|
- **If record exists**: All fields are updated with new values from Autotask
|
|
- **If record doesn't exist**: Record is inserted as new
|
|
- **Every fetched record is processed**, regardless of whether data actually changed
|
|
- The `synced_at` timestamp is always updated
|
|
|
|
### Record Counts
|
|
|
|
Sync history tracks three metrics:
|
|
|
|
| Metric | Description | How It's Calculated |
|
|
|--------|-------------|---------------------|
|
|
| `records_added` | New records inserted | **Estimated** (~10% of upserted) |
|
|
| `records_updated` | Existing records updated | **Estimated** (~90% of upserted) |
|
|
| `records_deleted` | Records soft-deleted | **Actual count** from soft delete operation |
|
|
|
|
**Important:** `records_added` and `records_updated` are **estimates** based on the total upserted count. PostgreSQL doesn't easily distinguish between inserts and updates in bulk UPSERT operations.
|
|
|
|
### Bulk Processing
|
|
|
|
Records are processed in batches for performance:
|
|
|
|
- **Fetch batch size**: 500 records per API call
|
|
- **Upsert batch size**: 100 records per database transaction
|
|
- **Pagination**: Automatic for large datasets
|
|
|
|
---
|
|
|
|
## Entity-Specific Behaviors
|
|
|
|
### Picklist Entities
|
|
|
|
**Entities:** Statuses, Issue Types, Sub-Issue Types, Work Types
|
|
|
|
**Special Handling:**
|
|
- Fetched from `/entity/entityInformation/fields` endpoint (not `/query`)
|
|
- No date filtering
|
|
- No soft deletes
|
|
- Synced as key-value pairs
|
|
|
|
**Example:**
|
|
```typescript
|
|
// Statuses from Tickets.status field
|
|
GET /Tickets/entityInformation/fields
|
|
|
|
// Maps to:
|
|
{ value: 1, label: "New", is_active: true }
|
|
{ value: 5, label: "Complete", is_active: true }
|
|
```
|
|
|
|
### Tickets
|
|
|
|
**Filters:**
|
|
- Date: `createDate >= (now - 2 years)`
|
|
- Active: `isActive = true` (if applicable)
|
|
|
|
**Foreign Key Validation:**
|
|
- `assigned_resource_id` → Resources
|
|
- `first_response_assigned_resource_id` → Resources
|
|
- `first_response_initiating_resource_id` → Resources
|
|
- Invalid references are set to `null`
|
|
|
|
**Soft Deletes:** ❌ Skipped (has date filter)
|
|
|
|
### Tasks
|
|
|
|
**Filters:**
|
|
- Date: `createDateTime >= (now - 2 years)`
|
|
|
|
**Foreign Key Validation:**
|
|
- `project_id` → Projects
|
|
- `assigned_resource_id` → Resources
|
|
- `creator_resource_id` → Resources
|
|
- `completed_by_resource_id` → Resources
|
|
- `last_activity_resource_id` → Resources
|
|
- Invalid references are set to `null`
|
|
|
|
**Soft Deletes:** ❌ Skipped (has date filter)
|
|
|
|
### Time Entries
|
|
|
|
**Filters:**
|
|
- **Required**: `dateWorked >= (now - 2 years)`
|
|
|
|
**Special Notes:**
|
|
- `company_id` is nullable (time entries can exist without a company)
|
|
- No foreign key validation needed
|
|
|
|
**Soft Deletes:** ❌ Skipped (has date filter)
|
|
|
|
### Billing Items
|
|
|
|
**Filters:**
|
|
- **Required**: `itemDate >= (now - 2 years)`
|
|
|
|
**Special Notes:**
|
|
- API requires a filter parameter
|
|
- Returns 500 error without filter
|
|
|
|
**Soft Deletes:** ❌ Skipped (has date filter)
|
|
|
|
### Companies
|
|
|
|
**Filters:**
|
|
- Active: `isActive = true`
|
|
|
|
**Special Notes:**
|
|
- No date filtering - syncs all active companies
|
|
- Foundation entity for many foreign keys
|
|
|
|
**Soft Deletes:** ✅ Yes (no date filter)
|
|
|
|
### Resources
|
|
|
|
**Filters:**
|
|
- Active: `isActive = true`
|
|
|
|
**Special Notes:**
|
|
- No date filtering - syncs all active resources
|
|
- Referenced by Tickets, Tasks, Time Entries
|
|
|
|
**Soft Deletes:** ✅ Yes (no date filter)
|
|
|
|
### Contacts
|
|
|
|
**Filters:**
|
|
- Active: `isActive = true`
|
|
|
|
**Special Notes:**
|
|
- No date filtering - syncs all active contacts
|
|
- Referenced by Configuration Items
|
|
|
|
**Soft Deletes:** ✅ Yes (no date filter)
|
|
|
|
### Configuration Items
|
|
|
|
**Filters:**
|
|
- Active: `isActive = true`
|
|
|
|
**Foreign Key Validation:**
|
|
- `contact_id` → Contacts
|
|
- Invalid references are set to `null`
|
|
|
|
**Soft Deletes:** ✅ Yes (no date filter)
|
|
|
|
### Contracts
|
|
|
|
**Filters:**
|
|
- **Required**: `status = 1` (Active)
|
|
|
|
**Special Notes:**
|
|
- API requires status filter
|
|
- Only syncs active contracts
|
|
|
|
**Soft Deletes:** ❌ Skipped (has status filter)
|
|
|
|
### Projects
|
|
|
|
**Filters:**
|
|
- **Required**: `status != 5` (Not Complete)
|
|
|
|
**Special Notes:**
|
|
- API requires status filter
|
|
- Excludes completed projects
|
|
|
|
**Soft Deletes:** ❌ Skipped (has status filter)
|
|
|
|
---
|
|
|
|
## Foreign Key Validation
|
|
|
|
### Why It's Needed
|
|
|
|
Autotask data may reference entities that:
|
|
- Haven't been synced yet
|
|
- Are outside the sync date range
|
|
- Have been deleted in Autotask
|
|
- Don't exist due to data inconsistencies
|
|
|
|
Without validation, these references cause PostgreSQL foreign key constraint violations.
|
|
|
|
### How It Works
|
|
|
|
Before upserting records, the sync validates foreign key references:
|
|
|
|
1. **Fetch valid IDs** from the database
|
|
```typescript
|
|
const validResourceIds = await getValidResourceIds();
|
|
// Returns Set of all resource IDs where is_deleted = false
|
|
```
|
|
|
|
2. **Validate each record**
|
|
```typescript
|
|
if (task.assigned_resource_id && !validResourceIds.has(task.assigned_resource_id)) {
|
|
task.assigned_resource_id = null; // Nullify invalid reference
|
|
}
|
|
```
|
|
|
|
3. **Log warnings** for nullified references
|
|
```
|
|
[WARN] Nullified invalid resource references: 15 records
|
|
```
|
|
|
|
### Validated Relationships
|
|
|
|
| Entity | Foreign Key Field | References | Action on Invalid |
|
|
|--------|------------------|------------|-------------------|
|
|
| **Tickets** | `assigned_resource_id` | Resources | Set to null |
|
|
| **Tickets** | `first_response_assigned_resource_id` | Resources | Set to null |
|
|
| **Tickets** | `first_response_initiating_resource_id` | Resources | Set to null |
|
|
| **Tasks** | `project_id` | Projects | Set to null |
|
|
| **Tasks** | `assigned_resource_id` | Resources | Set to null |
|
|
| **Tasks** | `creator_resource_id` | Resources | Set to null |
|
|
| **Tasks** | `completed_by_resource_id` | Resources | Set to null |
|
|
| **Tasks** | `last_activity_resource_id` | Resources | Set to null |
|
|
| **Configuration Items** | `contact_id` | Contacts | Set to null |
|
|
|
|
### Performance Impact
|
|
|
|
Foreign key validation queries are:
|
|
- Executed once per sync (cached)
|
|
- Indexed queries (fast)
|
|
- Minimal overhead compared to API fetching
|
|
|
|
---
|
|
|
|
## Soft Deletes
|
|
|
|
### What Are Soft Deletes?
|
|
|
|
Instead of permanently deleting records, the system marks them as deleted:
|
|
|
|
```sql
|
|
UPDATE table_name
|
|
SET is_deleted = true, deleted_at = NOW()
|
|
WHERE id NOT IN (fetched_ids)
|
|
AND is_deleted = false
|
|
```
|
|
|
|
### When Soft Deletes Occur
|
|
|
|
**Only during Full Sync** for entities **without date filters**:
|
|
|
|
| Entity | Soft Deletes? | Reason |
|
|
|--------|--------------|---------|
|
|
| Companies | ✅ Yes | No date filter - safe to delete |
|
|
| Resources | ✅ Yes | No date filter - safe to delete |
|
|
| Contacts | ✅ Yes | No date filter - safe to delete |
|
|
| Configuration Items | ✅ Yes | No date filter - safe to delete |
|
|
| Tickets | ❌ No | Has date filter - would delete old records |
|
|
| Tasks | ❌ No | Has date filter - would delete old records |
|
|
| Time Entries | ❌ No | Has date filter - would delete old records |
|
|
| Billing Items | ❌ No | Has date filter - would delete old records |
|
|
| Projects | ❌ No | Has status filter - would delete completed |
|
|
| Contracts | ❌ No | Has status filter - would delete inactive |
|
|
| Picklists | ❌ No | Picklist values don't get deleted |
|
|
|
|
### Why Skip Soft Deletes for Date-Filtered Entities?
|
|
|
|
**Problem:**
|
|
If we soft-deleted records not in the fetched set for date-filtered entities, we would incorrectly delete old records outside the sync window.
|
|
|
|
**Example:**
|
|
```
|
|
Full Sync of Tickets (last 2 years):
|
|
1. Fetch tickets created >= 2024-01-24
|
|
2. Ticket #12345 created in 2020 exists in DB
|
|
3. Ticket #12345 NOT in fetched set (outside date range)
|
|
4. ❌ Would incorrectly soft-delete Ticket #12345
|
|
|
|
Solution: Skip soft deletes for date-filtered entities
|
|
```
|
|
|
|
### Restoring Soft-Deleted Records
|
|
|
|
If a record is soft-deleted but appears in a later sync:
|
|
|
|
```sql
|
|
-- Record is automatically restored
|
|
UPDATE table_name
|
|
SET is_deleted = false, deleted_at = NULL, ...
|
|
WHERE id = $1
|
|
```
|
|
|
|
---
|
|
|
|
## Performance Considerations
|
|
|
|
### Sync Duration Factors
|
|
|
|
| Factor | Impact | Mitigation |
|
|
|--------|--------|------------|
|
|
| **Number of records** | High | Use date range filters |
|
|
| **API rate limits** | Medium | Built-in rate limiting (10 req/sec) |
|
|
| **Network latency** | Medium | Pagination, batch processing |
|
|
| **Database operations** | Low | Bulk upserts, indexed queries |
|
|
| **Foreign key validation** | Low | Cached, indexed queries |
|
|
|
|
### Estimated Sync Times
|
|
|
|
Based on typical data volumes:
|
|
|
|
| Entity | Record Count | Full Sync Time | Incremental Sync Time |
|
|
|--------|-------------|----------------|----------------------|
|
|
| Companies | 500 | ~30 seconds | ~5 seconds |
|
|
| Resources | 100 | ~10 seconds | ~2 seconds |
|
|
| Tickets (2 years) | 10,000 | ~10 minutes | ~1 minute |
|
|
| Tasks (2 years) | 5,000 | ~5 minutes | ~30 seconds |
|
|
| Time Entries (2 years) | 50,000 | ~45 minutes | ~5 minutes |
|
|
| Billing Items (2 years) | 50,000+ | ~45-60 minutes | ~5 minutes |
|
|
|
|
**Note:** Times vary based on data volume, network speed, and system load.
|
|
|
|
### Optimization Tips
|
|
|
|
1. **Use Incremental Sync for regular updates**
|
|
- Schedule incremental syncs hourly or daily
|
|
- Reserve full syncs for weekly/monthly maintenance
|
|
|
|
2. **Adjust date range based on needs**
|
|
- Default 2 years is usually sufficient
|
|
- Reduce to 1 year for faster syncs if older data isn't needed
|
|
- Increase to 5+ years only if historical data is required
|
|
|
|
3. **Sync entities in dependency order**
|
|
- Companies → Resources → Tickets → Tasks
|
|
- Reduces foreign key validation overhead
|
|
|
|
4. **Monitor sync history**
|
|
- Check for failures and patterns
|
|
- Identify slow entities for optimization
|
|
|
|
5. **Use Sync Selected for troubleshooting**
|
|
- Test individual entities
|
|
- Isolate and fix issues without full sync
|
|
|
|
---
|
|
|
|
## Sync Workflow Examples
|
|
|
|
### Example 1: Initial Setup
|
|
|
|
```
|
|
1. Full Sync - All Entities (2 years)
|
|
├─ Companies (all active)
|
|
├─ Resources (all active)
|
|
├─ Contacts (all active)
|
|
├─ Configuration Items (all active)
|
|
├─ Contracts (active only)
|
|
├─ Projects (non-completed)
|
|
├─ Tickets (last 2 years)
|
|
├─ Tasks (last 2 years)
|
|
├─ Time Entries (last 2 years)
|
|
├─ Billing Items (last 2 years)
|
|
└─ Picklists (all values)
|
|
|
|
Result: Complete database populated with all relevant data
|
|
```
|
|
|
|
### Example 2: Daily Maintenance
|
|
|
|
```
|
|
1. Incremental Sync - All Entities
|
|
├─ Fetch only records modified since last sync
|
|
├─ Upsert changed records
|
|
└─ No soft deletes
|
|
|
|
Result: Database updated with latest changes (fast)
|
|
```
|
|
|
|
### Example 3: Fixing Specific Entity
|
|
|
|
```
|
|
1. Identify failed entity: Billing Items
|
|
2. Sync Selected - Billing Items only
|
|
├─ Full sync with date filter (last 2 years)
|
|
├─ Upsert all billing items
|
|
└─ No soft deletes
|
|
|
|
Result: Billing Items data refreshed and consistent
|
|
```
|
|
|
|
### Example 4: Historical Data Sync
|
|
|
|
```
|
|
1. Full Sync - Tickets (5 years)
|
|
├─ Adjust yearsBack parameter to 5
|
|
├─ Fetch tickets created >= 2021-01-24
|
|
├─ Upsert all fetched tickets
|
|
└─ Skip soft deletes
|
|
|
|
Result: 5 years of ticket history in database
|
|
```
|
|
|
|
---
|
|
|
|
## Troubleshooting
|
|
|
|
### Common Issues
|
|
|
|
#### Issue: Foreign Key Constraint Violations
|
|
|
|
**Symptoms:**
|
|
```
|
|
[DATABASE_CONSTRAINT_ERROR] violates foreign key constraint "tasks_project_id_fkey"
|
|
```
|
|
|
|
**Cause:** Referenced entity hasn't been synced or is outside date range
|
|
|
|
**Solution:**
|
|
1. Sync dependency entities first (Companies → Resources → Projects)
|
|
2. Foreign key validation will nullify invalid references
|
|
3. Check logs for nullified reference warnings
|
|
|
|
#### Issue: API Filter Required Error
|
|
|
|
**Symptoms:**
|
|
```
|
|
[API_ERROR] Value cannot be null. Parameter name: filters
|
|
```
|
|
|
|
**Cause:** Entity requires a filter (Time Entries, Billing Items, Contracts, Projects)
|
|
|
|
**Solution:** Filters are automatically applied - this shouldn't occur. If it does, check entity-sync.ts for proper filter configuration.
|
|
|
|
#### Issue: Slow Sync Performance
|
|
|
|
**Symptoms:** Sync takes longer than expected
|
|
|
|
**Solutions:**
|
|
1. Reduce `yearsBack` parameter (e.g., from 2 to 1 year)
|
|
2. Use incremental sync instead of full sync
|
|
3. Sync entities individually instead of all at once
|
|
4. Check network connectivity and API response times
|
|
|
|
#### Issue: Records Not Appearing
|
|
|
|
**Symptoms:** Records exist in Autotask but not in database
|
|
|
|
**Possible Causes:**
|
|
1. Outside date range filter
|
|
2. Not active (filtered out by `isActive`)
|
|
3. Foreign key validation nullified references
|
|
4. Sync failed (check sync history)
|
|
|
|
**Solutions:**
|
|
1. Check sync history for errors
|
|
2. Verify record meets filter criteria
|
|
3. Check logs for validation warnings
|
|
4. Run full sync for the entity
|
|
|
|
---
|
|
|
|
## Best Practices
|
|
|
|
### 1. Sync Strategy
|
|
|
|
- **Initial Setup:** Full sync all entities (2 years)
|
|
- **Daily Maintenance:** Incremental sync all entities
|
|
- **Weekly/Monthly:** Full sync for data consistency
|
|
- **Troubleshooting:** Sync selected entities as needed
|
|
|
|
### 2. Date Range Configuration
|
|
|
|
- **Default (2 years):** Good for most use cases
|
|
- **1 year:** Faster syncs, less historical data
|
|
- **3-5 years:** More historical data, slower syncs
|
|
- **Adjust based on:** Business needs, performance requirements
|
|
|
|
### 3. Monitoring
|
|
|
|
- Review sync history regularly
|
|
- Set up alerts for failed syncs
|
|
- Monitor sync duration trends
|
|
- Check for foreign key validation warnings
|
|
|
|
### 4. Dependency Management
|
|
|
|
Sync entities in this order for best results:
|
|
1. Companies
|
|
2. Resources
|
|
3. Contacts
|
|
4. Configuration Items
|
|
5. Contracts
|
|
6. Projects
|
|
7. Tickets
|
|
8. Tasks
|
|
9. Time Entries
|
|
10. Billing Items
|
|
11. Picklists
|
|
|
|
### 5. Error Handling
|
|
|
|
- Failed syncs are logged in `sync_history` table
|
|
- Check error messages for specific issues
|
|
- Re-run failed entity syncs individually
|
|
- Contact support if errors persist
|
|
|
|
---
|
|
|
|
## API Reference
|
|
|
|
### Full Sync
|
|
|
|
```typescript
|
|
POST /api/sync/full
|
|
{
|
|
"yearsBack": 2,
|
|
"triggeredBy": "user@example.com"
|
|
}
|
|
```
|
|
|
|
### Incremental Sync
|
|
|
|
```typescript
|
|
POST /api/sync/incremental
|
|
{
|
|
"triggeredBy": "user@example.com"
|
|
}
|
|
```
|
|
|
|
### Sync Selected Entities
|
|
|
|
```typescript
|
|
POST /api/sync/entity
|
|
{
|
|
"entities": ["tickets", "tasks"],
|
|
"yearsBack": 2,
|
|
"triggeredBy": "user@example.com"
|
|
}
|
|
```
|
|
|
|
### Get Sync History
|
|
|
|
```typescript
|
|
GET /api/sync/history?limit=50&offset=0
|
|
```
|
|
|
|
### Get Sync Status
|
|
|
|
```typescript
|
|
GET /api/sync/status
|
|
```
|
|
|
|
---
|
|
|
|
## Related Documentation
|
|
|
|
- [Sync Interface Guide](./SYNC_INTERFACE_GUIDE.md) - User guide for the sync UI
|
|
- [Sync Logging Improvements](./SYNC_LOGGING_IMPROVEMENTS.md) - Structured logging details
|
|
- [Database Schema](../migrations/001_initial_schema.sql) - PostgreSQL table definitions
|
|
|
|
---
|
|
|
|
## Changelog
|
|
|
|
### 2026-01-24
|
|
- Added billing items filter requirement
|
|
- Added task foreign key validation
|
|
- Documented sync behavior comprehensively
|
|
|
|
### 2026-01-23
|
|
- Fixed statuses and work types sync (picklist API)
|
|
- Added structured logging
|
|
- Created sync interface documentation
|
|
|
|
---
|
|
|
|
## Support
|
|
|
|
For issues or questions:
|
|
1. Check sync history in the admin interface
|
|
2. Review error messages and logs
|
|
3. Consult this documentation
|
|
4. Contact system administrator
|