Connecting N8N to Autotask PSA API: A Comprehensive Guide 

This knowledge base article provides step-by-step instructions on setting up an integration between N8N and Autotask PSA. You’ll learn how to create API credentials in Autotask, test them using PowerShell, and implement common automation workflows in N8N. 

Creating API Credentials in Autotask 

To access the Autotask PSA API, you’ll need to create API credentials: 

  1. Log into Autotask as a user with Administrator permissions 
  1. Navigate to Admin > Resources (Users) 
  1. Click the pulldown on the New button and select New API User
    A screenshot of a computer

AI-generated content may be incorrect. 
  1. Fill in the required fields in the form: 
  • First Name and Last Name: You can use your organization name or “API Integration” 
  • Email Address: Enter a valid email address 
  • Security Level: Select the appropriate security level 
  • Primary Internal Location: Select your organization’s location 
  1. In the Credentials section: 
  • Click Generate Key to create the username (API key) 
  • Click Generate Secret to create the password (secret) 
  1. In the API Tracking Identifier section: 
  • Select Custom (Internal Integration) 
  • Enter an Internal Integration Name (a descriptive name for your integration) 
  • Note the automatically generated Tracking Identifier 
  1. In the Line of Business section: 
  • Select which lines of business this API can interact with (select all if needed)
    A screenshot of a computer

AI-generated content may be incorrect.
  1. Note down the following credentials in a secure location: 
  • Username (Key) 
  • Password (Secret) 
  • API Tracking Identifier 
  1. Click Save & Close 

Testing API Credentials with PowerShell 

Before configuring N8N, it’s a good practice to test your API credentials using PowerShell: 

# Define your Autotask API credentials 

$ApiIntegrationCode = “YOUR_API_INTEGRATION_CODE” 

$UserName = “YOUR_USERNAME” 

$Secret = ‘YOUR_SECRET’  # Use single quotes for secrets with special characters 

# Define the request headers 

$headers = @{ 

    “ApiIntegrationCode” = $ApiIntegrationCode 

    “UserName” = $UserName 

    “Secret” = $Secret 

    “Content-Type” = “application/json” 

} 

# Important: Find your correct Autotask URL 

# Your URL might be webservices15.autotask.net or another subdomain based on your region 

$response = Invoke-RestMethod -Uri “https://webservices15.autotask.net/ATServicesRest/V1.0/Companies/entityInformation” -Method GET -Headers $headers 

# Display the response 

$response | ConvertTo-Json -Depth 5 

Note: If you receive a 401 Unauthorized error, verify you’re using the correct Autotask URL for your instance. Each Autotask customer is assigned to a specific zone (e.g., webservices15.autotask.net). You can discover your correct URL here. Using Swagger UI to explore REST API requests 

Setting Up Credentials in N8N 

Now, let’s set up these credentials in N8N: 

  1. Open your N8N instance and find Add Credential (its in about 4 different spots) 
  1. Select Generic Credential Type 
  1. For Generic Auth Type, select Custom Auth 
  1. For JSON, enter the following structure (replace with your actual values): 

  “headers”: { 

    “ApiIntegrationCode”: “YOUR_API_INTEGRATION_CODE”, 

    “UserName”: “YOUR_USERNAME”, 

    “Secret”: “YOUR_SECRET”, 

    “Content-Type”: “application/json” 

  } 

This custom auth configuration creates the necessary headers that Autotask requires for authentication. 

Implementing Common Workflows 

Checking if a Contact Exists 

To check if a contact already exists in Autotask: 

  1. Create a new workflow in N8N 
  1. Add a Function node to prepare the contact email query: 
  • Name it “Prepare Contact Query” 
  • Use the following code: 

// Extract user data from webhook or previous node 

const firstName = $input.item.json.UserFirstName || “”; 

const lastName = $input.item.json.UserLastName || “”; 

// Create the email (first initial + lastname@domain.com) 

const emailPrefix = firstName.charAt(0).toLowerCase() + lastName.toLowerCase(); 

const contactEmail = `${emailPrefix}@riverbirchrenewables.com`; 

return { 

  json: { 

    contactEmail 

  } 

}; 

  1. Add an HTTP Request node: 
  • Name it “Check Existing Contact” 
  • Method: POST 
  • URL: https://webservices.autotask.net/ATServicesRest/V1.0/Contacts/query 
  • Authentication: Select your Autotask API credentials 
  • Body: 

  “filter”: [ 

    { 

      “op”: “eq”, 

      “field”: “emailAddress”, 

      “value”: “{{$json.contactEmail}}” 

    } 

  ], 

  “includeFields”: [“id”, “firstName”, “lastName”, “emailAddress”] 

  1. Add a Function node to count contacts: 
  • Name it “Count AT Contacts” 
  • Use the following code: 

const items = $input.item.json.items || []; 

return { 

  json: { 

    ATContactsFound: items.length, 

    firstContactId: items.length > 0 ? items[0].id : null 

  } 

}; 

Creating a New Contact 

To create a new contact when one doesn’t exist: 

  1. Add an IF node after the “Count AT Contacts” node: 
  • Condition: {{$json.ATContactsFound}} Equal to 0 
  1. In the “IF” branch (contact doesn’t exist), add an HTTP Request node: 
  • Name it “Create Contact” 
  • Method: POST 
  • URL: https://webservices15.autotask.net/ATServicesRest/V1.0/Companies/283/Contacts (use your specific Autotask zone URL and company ID) 
  • Authentication: Select your Custom Auth credentials 
  • Generic Credential Type: Custom Auth 
  • Custom Auth: Select your Autotask credentials created earlier 
  • Body: 

  “firstName”: “{{$(‘Prepare Contact Query’).item.json.firstName}}”, 

  “lastName”: “{{$(‘Prepare Contact Query’).item.json.lastName}}”, 

  “emailAddress”: “{{$(‘Prepare Contact Query’).item.json.contactEmail}}”, 

  “isActive”: true, 

  “mobilePhone”: “{{$input.item.json.cellPhone}}” 

Updating Contact UDFs 

After creating or finding a contact, you might need to update User Defined Fields (UDFs): 

  1. Add an HTTP Request node after both branches of the IF node: 
  • Name it “Update Contact UDFs” 
  • Method: PATCH 
  • URL for dynamic contact ID: https://webservices15.autotask.net/ATServicesRest/V1.0/Companies/283/Contacts/{{$(‘Count AT Contacts’).item.json.ATContactsFound > 0 ? $(‘Check Existing Contact’).item.json.items[0].id : $json.itemId}} (use your specific Autotask zone URL and company ID) 
  • Authentication: Select your Custom Auth credentials 
  • Generic Credential Type: Custom Auth 
  • Custom Auth: Select your Autotask credentials created earlier 
  • Body: 

  “userDefinedFields”: [ 

    { 

      “name”: “Custom Field Name”, 

      “value”: “Custom Field Value” 

    } 

  ] 

Adding Billing Products to Contacts 

To add billing products to a contact, first create a function to determine which products to add: 

  1. Add a Function node: 
  • Name it “Determine Billing Items” 
  • Use the following code: 

// Get the request type from the webhook data 

const requestType = $(‘Webhook’).first().json.body.Ticket.Questions[0].Value; 

// Initialize array to hold billing product IDs 

let billingProductIDs = []; 

// Determine which billing items to apply based on request type 

if (requestType === “Server Access”) { 

  // Server Access gets these products 

  billingProductIDs = [ 

    29682890,  // bt_Manage 

    29682908,  // Saas Backup for Office 365 

    29682995,  // User Portal 

    29683028   // MS365BusPrem (NCE) 

  ]; 

} else if (requestType === “Email Only”) { 

  // Email Only gets these products 

  billingProductIDs = [ 

    29682908,  // Saas Backup for Office 365 

    29682909,  // ExchOnlineP1 

    29682995   // User Portal 

  ]; 

// Get the contact ID (either existing or newly created) 

const contactID = $(‘Count AT Contacts’).item.json.ATContactsFound > 0  

  ? $(‘Check Existing Contact’).item.json.items[0].id  

  : $json.itemId; 

// Get the current date for effectiveDate 

const effectiveDate = new Date().toISOString(); 

// Create an array of items for N8N to loop through 

if (billingProductIDs.length > 0) { 

  return billingProductIDs.map(productID => { 

    return { 

      json: { 

        billingProductID: productID, 

        contactID: contactID, 

        effectiveDate: effectiveDate 

      } 

    }; 

  }); 

} else { 

  // Return empty array or a single item indicating no products 

  return [{ 

    json: { 

      noProductsToAdd: true, 

      contactID: contactID 

    } 

  }]; 

  1. Add an HTTP Request node: 
  • Name it “Add Billing Product” 
  • Enable “Run for each item” option 
  • Method: POST 
  • URL: https://webservices15.autotask.net/ATServicesRest/V1.0/Contacts/{{$json.contactID}}/BillingProductAssociations (use your specific Autotask zone URL) 
  • Authentication: Select your Custom Auth credentials 
  • Generic Credential Type: Custom Auth 
  • Custom Auth: Select your Autotask credentials created earlier 
  • Body: 

  “billingProductID”: {{$json.billingProductID}}, 

  “contactID”: {{$json.contactID}}, 

  “effectiveDate”: “{{$json.effectiveDate}}” 

  1. Add a Merge node after the HTTP Request: 
  • Name it “Merge Billing Results” 
  • Mode: “Merge By Index” 

Handling API Limitations 

Autotask API has some limitations to be aware of: 

  • Thread Threshold: Maximum of 3 concurrent API requests 
  • Rate Limiting: Excessive requests might be throttled 

To handle these limitations: 

  1. Use the “Run for each item” option with a Merge node instead of sending all requests simultaneously 
  1. Consider adding Wait nodes between requests if you still encounter rate limiting issues 
  1. Implement proper error handling to catch and retry failed requests 

Troubleshooting 

Common issues and solutions: 

  1. Authentication Errors (401) 
  • Verify your API credentials are correct 
  • Check if the API user has the necessary permissions 
  1. Too Many Requests Error 
  • Add delays between requests 
  • Reduce the number of concurrent requests 
  1. Invalid Request Format (400) 
  • Ensure your JSON body matches the expected format 
  • Check field names and data types 
  1. Node Reference Errors 
  • Verify all node names in expressions match actual node names 
  • Check for missing connections between nodes 

For additional assistance, consult the Autotask API Documentation

By following this guide, you should now have a functioning integration between N8N and Autotask PSA, allowing you to automate contact management and billing product associations.