346 lines
9.3 KiB
Markdown
346 lines
9.3 KiB
Markdown
|
|
# 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
|
||
|
|
|
||
|
|
1. Log into your Addigy account
|
||
|
|
2. Navigate to **Account > Integrations**
|
||
|
|
3. Click on the **V2** tab under "Addigy API"
|
||
|
|
4. Click **New API Token**
|
||
|
|
5. Enter a name for your token (e.g., "PSA-Utils Integration")
|
||
|
|
6. 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
|
||
|
|
7. Click **Save**
|
||
|
|
8. **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`:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 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:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
npm run dev
|
||
|
|
```
|
||
|
|
|
||
|
|
## Usage
|
||
|
|
|
||
|
|
### Import the Addigy Client
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
import { getAddigyClient } from '@/lib/services/addigy-factory';
|
||
|
|
|
||
|
|
const addigyClient = getAddigyClient();
|
||
|
|
```
|
||
|
|
|
||
|
|
### Common Operations
|
||
|
|
|
||
|
|
#### Get All Devices
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const devices = await addigyClient.getAllDevices();
|
||
|
|
console.log(`Found ${devices.length} devices`);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Online Devices Only
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const onlineDevices = await addigyClient.getOnlineDevices();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Devices by Policy
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const policyId = '003f01fa-9bb3-421a-be29-409adf7a1xxx';
|
||
|
|
const devices = await addigyClient.getDevicesByPolicy(policyId);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Device Applications
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
|
||
|
|
const applications = await addigyClient.getDeviceApplications(deviceId);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get All Policies
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const policies = await addigyClient.getAllPolicies();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Policy by ID
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const policyId = '76yh84t0-ju74-bh45-jd6b-ok87y4gc83gt';
|
||
|
|
const policy = await addigyClient.getPolicyById(policyId);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Active Alerts
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const alerts = await addigyClient.getActiveAlerts();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Maintenance Items
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const maintenanceItems = await addigyClient.getMaintenanceItems();
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Get Custom Facts for a Device
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
|
||
|
|
const facts = await addigyClient.getCustomFacts(deviceId);
|
||
|
|
```
|
||
|
|
|
||
|
|
#### Assign Device to Policy
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
const deviceId = '114x11c3-b5dy-4n38-92fb-34th6ju782se';
|
||
|
|
const newPolicyId = '76yh84t0-ju74-bh45-jd6b-ok87y4gc83gt';
|
||
|
|
await addigyClient.assignDeviceToPolicy(deviceId, newPolicyId);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Advanced Queries with Filters
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// 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
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
// Get all devices with automatic pagination
|
||
|
|
const allDevices = await addigyClient.getAllDevicesPaginated(100);
|
||
|
|
console.log(`Total devices: ${allDevices.length}`);
|
||
|
|
```
|
||
|
|
|
||
|
|
### Test Connection
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
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 ID
|
||
|
|
- `online` (optional) - Set to 'true' to get only online devices
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
# 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-key` header (not `Authorization: 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
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"page": 1,
|
||
|
|
"per_page": 500,
|
||
|
|
"query": {
|
||
|
|
"filters": [...]
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Response Structure
|
||
|
|
|
||
|
|
#### Devices Response
|
||
|
|
Devices are returned with nested `facts` structure:
|
||
|
|
```json
|
||
|
|
{
|
||
|
|
"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:
|
||
|
|
```json
|
||
|
|
[
|
||
|
|
{
|
||
|
|
"policyId": "69ae51e4-...",
|
||
|
|
"orgid": "4200f347-...",
|
||
|
|
"name": "Policy Name"
|
||
|
|
}
|
||
|
|
]
|
||
|
|
```
|
||
|
|
|
||
|
|
**Example:**
|
||
|
|
```bash
|
||
|
|
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 information
|
||
|
|
- `AddigyPolicy` - Policy information
|
||
|
|
- `AddigyApplication` - Installed application details
|
||
|
|
- `AddigyAlert` - Alert information
|
||
|
|
- `AddigyOrganization` - Organization details
|
||
|
|
- `AddigyMaintenanceItem` - Maintenance task information
|
||
|
|
- `AddigyMonitoringItem` - Monitoring rule information
|
||
|
|
- `AddigyCustomFact` - Custom facts/variables
|
||
|
|
- `AddigySoftwareItem` - Software catalog items
|
||
|
|
|
||
|
|
## Error Handling
|
||
|
|
|
||
|
|
Always wrap API calls in try-catch blocks:
|
||
|
|
|
||
|
|
```typescript
|
||
|
|
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
|
||
|
|
|
||
|
|
- [Addigy API v2 Documentation](https://support.addigy.com/hc/en-us/articles/16938210315411-API-Documentation-v2)
|
||
|
|
- [Addigy API v2 Interactive Docs](https://api.addigy.com/api/v2/documentation/)
|
||
|
|
- [Addigy Support Center](https://support.addigy.com/)
|
||
|
|
|
||
|
|
## 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:
|
||
|
|
1. Wrong endpoint path - check you're using `/o/{orgid}/devices` for devices
|
||
|
|
2. Missing organization ID - the integration will auto-fetch from policies if not configured
|
||
|
|
3. 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
|