wulf-pulse/ADDIGY_API_GUIDE.md
Lorentz Hinrichsen f429f3af54 Add Addigy API integration and Docker deployment with Redis caching
- 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
2025-10-28 22:49:08 -04:00

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

  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:

# 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 ID
  • online (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-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

{
  "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 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:

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:

  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