# 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
