- Implemented complete Addigy API v2 client with authentication via x-api-key - Added device and policy endpoints with automatic org ID resolution - Created field mapping from snake_case to Title Case for UI compatibility - Handles nested 'facts' response structure from Addigy devices API - Added comprehensive API documentation in ADDIGY_API_GUIDE.md - Multi-stage Dockerfile with optimized production build - Custom ports: App on 3100, Redis on 6380 (avoids conflicts) - Docker Compose orchestration with health checks - Standalone Next.js output for smaller container images - Non-root user execution for security - Implemented Redis caching layer for API responses - 5-minute TTL with graceful fallback if Redis unavailable - Cache key structure: service:entity:filter1:filter2 - Applied to Addigy devices endpoint with cache hit/miss logging - Fixed TypeScript strict mode errors for production builds - Added null safety checks with optional chaining throughout API routes - Wrapped useSearchParams in Suspense boundary for Next.js 15+ compatibility - Fixed type assertions for dynamic API responses - Corrected Set<string> type mismatches in device comparison logic - Created DOCKER_README.md with complete deployment guide - Updated ADDIGY_API_GUIDE.md with real-world API patterns - Documented response structures, field mappings, and troubleshooting - Next.js 16.0.0 with Turbopack - Redis 7 with AOF persistence - Podman/Docker compatible - TypeScript strict mode compliant
9.3 KiB
Addigy API Integration Guide
This guide explains how to use the Addigy API integration in the PSA-Utils application.
Setup
1. Get Your Addigy API Token
- Log into your Addigy account
- Navigate to Account > Integrations
- Click on the V2 tab under "Addigy API"
- Click New API Token
- Enter a name for your token (e.g., "PSA-Utils Integration")
- Select the appropriate permissions:
- View Devices - Required to fetch device information
- View Policies - Required to fetch policy information
- View Organizations - Optional, for organization data
- Additional permissions as needed for your use case
- Click Save
- Copy the API token immediately - you won't be able to see it again!
Note: The Addigy v2 API uses the x-api-key header for authentication, not Bearer tokens.
2. Configure Environment Variables
Add your Addigy API token to .env.local:
# Addigy API Configuration
ADDIGY_API_URL=https://api.addigy.com/api/v2
ADDIGY_API_TOKEN=your_actual_token_here
# Optional: Parent Organization ID (if needed)
# ADDIGY_ORG_ID=your_org_id_here
3. Restart Your Development Server
After updating the .env.local file, restart your Next.js development server:
npm run dev
Usage
Import the Addigy Client
import { getAddigyClient } from '@/lib/services/addigy-factory';
const addigyClient = getAddigyClient();
Common Operations
Get All Devices
const devices = await addigyClient.getAllDevices();
console.log(`Found ${devices.length} devices`);
Get Online Devices Only
const onlineDevices = await addigyClient.getOnlineDevices();
Get Devices by Policy
const policyId = '003f01fa-9bb3-421a-be29-409adf7a1xxx';
const devices = await addigyClient.getDevicesByPolicy(policyId);
Get Device Applications
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
const applications = await addigyClient.getDeviceApplications(deviceId);
Get All Policies
const policies = await addigyClient.getAllPolicies();
Get Policy by ID
const policyId = '76yh84t0-ju74-bh45-jd6b-ok87y4gc83gt';
const policy = await addigyClient.getPolicyById(policyId);
Get Active Alerts
const alerts = await addigyClient.getActiveAlerts();
Get Maintenance Items
const maintenanceItems = await addigyClient.getMaintenanceItems();
Get Custom Facts for a Device
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
const facts = await addigyClient.getCustomFacts(deviceId);
Assign Device to Policy
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
const newPolicyId = '76yh84t0-ju74-bh45-jd6b-ok87y4gc83gt';
await addigyClient.assignDeviceToPolicy(deviceId, newPolicyId);
Advanced Queries with Filters
// Get devices with custom filters
const devices = await addigyClient.getAllDevices({
filters: [
{
audit_field: 'Free Disk Percentage',
type: 'number',
operation: 'less_than',
value: 20,
},
{
audit_field: 'Firewall Enabled',
type: 'boolean',
operation: 'equals',
value: false,
},
],
limit: 100,
page: 1,
});
Pagination for Large Datasets
// Get all devices with automatic pagination
const allDevices = await addigyClient.getAllDevicesPaginated(100);
console.log(`Total devices: ${allDevices.length}`);
Test Connection
const isConnected = await addigyClient.testConnection();
if (isConnected) {
console.log('Successfully connected to Addigy API');
} else {
console.error('Failed to connect to Addigy API');
}
API Endpoints
The integration includes the following pre-built API endpoints:
GET /api/addigy-devices
Fetch devices from Addigy. Automatically retrieves the organization ID from policies if not configured.
Query Parameters:
policyId(optional) - Filter devices by policy IDonline(optional) - Set to 'true' to get only online devices
Example:
# Get all devices
curl http://localhost:3000/api/addigy-devices
# Get devices for a specific policy
curl http://localhost:3000/api/addigy-devices?policyId=76yh84t0-ju74-bh45-jd6b-ok87y4gc83gt
# Get only online devices
curl http://localhost:3000/api/addigy-devices?online=true
GET /api/addigy-policies
Fetch all policies from Addigy.
Important API Details
Authentication
- Uses
x-api-keyheader (notAuthorization: Bearer) - Single API token for authentication
Endpoint Structure
- Devices:
POST /o/{orgid}/devices- Requires organization ID - Policies:
POST /oa/policies/query- Returns flat array - All endpoints use POST with JSON body, not GET
Request Body Format
{
"page": 1,
"per_page": 500,
"query": {
"filters": [...]
}
}
Response Structure
Devices Response
Devices are returned with nested facts structure:
{
"items": [
{
"facts": {
"device_name": { "value": "MacBook-Pro", "type": "string" },
"serial_number": { "value": "C02XX...", "type": "string" },
"online": { "value": true, "type": "boolean" }
}
}
]
}
Policies Response
Policies return as a flat array:
[
{
"policyId": "69ae51e4-...",
"orgid": "4200f347-...",
"name": "Policy Name"
}
]
Example:
curl http://localhost:3000/api/addigy-policies
Rate Limiting
The Addigy API has a rate limit of 1,000 requests per 10 seconds. The client includes built-in rate limiting to prevent exceeding this limit. If you exceed the rate limit, further requests will be rejected for 24 hours.
Type Definitions
All Addigy types are defined in /lib/types/addigy.ts. Key types include:
AddigyDevice- Device informationAddigyPolicy- Policy informationAddigyApplication- Installed application detailsAddigyAlert- Alert informationAddigyOrganization- Organization detailsAddigyMaintenanceItem- Maintenance task informationAddigyMonitoringItem- Monitoring rule informationAddigyCustomFact- Custom facts/variablesAddigySoftwareItem- Software catalog items
Error Handling
Always wrap API calls in try-catch blocks:
try {
const devices = await addigyClient.getAllDevices();
// Process devices
} catch (error) {
console.error('Error fetching devices:', error);
// Handle error appropriately
}
Common Device Fields
Addigy returns device fields in snake_case format. The integration automatically maps these to Title Case for UI compatibility:
| Addigy Field | Mapped To | Description |
|---|---|---|
agentid |
agentid |
Unique device identifier |
device_name |
Device Name |
Device hostname |
device_model_name |
Device Model Name |
Device model (e.g., "MacBook Pro") |
mac_os_x_version |
MAC OS X Version |
macOS version |
ios_version |
iOS Version |
iOS version |
online |
online |
Boolean indicating if device is online |
policy_id |
policy_id |
Current policy ID |
current_user |
Current User |
Currently logged in user |
serial_number |
Serial Number |
Device serial number |
free_disk_percentage |
Free Disk Percentage |
Available disk space percentage |
battery_percentage |
Battery Percentage |
Current battery level |
firewall_enabled |
Firewall Enabled |
Boolean |
filevault_enabled |
FileVault Enabled |
Boolean |
agent_version |
Agent Version |
Addigy agent version |
Resources
Troubleshooting
"ADDIGY_API_TOKEN environment variable is required"
Make sure you've added your API token to the .env.local file and restarted your development server.
"API Error: Unauthorized" or 401 Error
Check that your API token is valid and has the necessary permissions. You may need to create a new token with the correct permissions in Addigy.
"404 page not found" Error
This usually means:
- Wrong endpoint path - check you're using
/o/{orgid}/devicesfor devices - Missing organization ID - the integration will auto-fetch from policies if not configured
- Using GET instead of POST - all Addigy v2 endpoints require POST
Empty Device Names
Addigy uses snake_case field names (e.g., device_name). The integration automatically maps these to the UI-expected format (e.g., Device Name).
Rate Limit Exceeded
If you receive a rate limit error, wait 24 hours before making more API requests. Consider implementing caching or reducing the frequency of API calls.
"Invalid JSON response from Addigy API"
This may indicate an issue with the API endpoint or your token permissions. Check the Addigy API documentation for the specific endpoint you're trying to access.
Next Steps
- Explore the Addigy API documentation for additional endpoints
- Create custom API routes for your specific use cases
- Integrate Addigy data with your Autotask or other systems
- Build dashboards to visualize device status, alerts, and compliance