@apigrate/autotask-restapi

2.0.0 • Public • Published

Autotask REST API NodeJS Connector

v2 Release Notes

Breaking changes:

  1. Codebase now uses native fetch and requires Node > 18.0.0. (Removed dependency on isomorphic-fetch.)
  2. Removed the api() method. All API entity references are now available directly on the AutotaskRestApi instance.
  3. API calls automatically invoke the zoneInformation API when needed. No initialization is necessary.

This connector simplifies interaction with the Autotask PSA REST API for developers using NodeJS.

Please insure you are using a LTS version of NodeJS, or at least a version that supports ES6 promises.

npm install @apigrate/autotask-restapi --save

Connecting to Autotask

const {AutotaskRestApi} = require('@apigrate/autotask-restapi');

const autotask = new AutotaskRestApi(
  process.env.AUTOTASK_USER, // make sure it's an API User
  process.env.AUTOTASK_SECRET, 
  process.env.AUTOTASK_INTEGRATION_CODE 
);

The Autotask REST API has endpoints ("zones") distributed around the world. The connector automatically determines the correct endpoint when you make your first API call. There is no need to get the zone information separately.

let company = await autotask.Companies.get(0);//Get the root company

Methods Available on Each Entity

The following sections list the methods on each available entity on the connector.

Not all methods may be applicable for an entity. For example, most entities do not support delete; therefore, expect an error if you attempt to use a method in an inappropriate context.

count

Counts entities. Use Autotask query filter syntax to provide criteria for the count.

// Count companies with a CompanyName beginning with "B"
result = await autotask.Companies.count({
  filter:[
    {
        "op": "beginsWith",
        "field": "CompanyName",
        "value": "B"
    }
  ]
});
// result = {queryCount: 7}

// Count all the contacts in Autotask
result = await autotask.Contacts.count({
  filter:[
    {
        "op": "gte",
        "field": "Id",
        "value": 0
    }
  ]
});
// result = {queryCount: 1209}

related Autotask documentation

get

Get a single entity by id.

let product = await autotask.Products.get(232486923);
// product = { item: { id: 232486923, ...product object properties... } }

When you attempt to get an an entity by id that doesn't exist, this connector automatically swallows the HTTP-404 returned by the Autotask REST API and instead returns {item: null}. This is an intentional decision to facilitate better code readability.

Note, filter expressions using the get method are not supported. Use the query method instead.

related Autotask documentation

Special case: To retrieve attachment base64-encoded data, you must use an attachment-specific parent-child GET request. For: 'ConfigurationItemAttachments', 'ConfigurationItemNoteAttachments', 'OpportunityAttachments', 'TaskAttachments', 'TaskNoteAttachments', 'TicketAttachments', 'TicketNoteAttachments', 'TimeEntryAttachments', you must use the following get syntax:

Get a entity attachment data by id

// TicketID 129873
// AttachmentID 232486923
let ticketAttachment = await autotask.TicketAttachments.get(129873, 232486923);

// ticketAttachment = { items: { id: 232486923, ..., data: "iVBORw0KGgoAAAANSUhEUgAAAV8AAAC (...the rest of the base64 ecoded data)..." } }

query

Query for entities matching a filter expression.

//Find a company by name
let result = await autotask.Companies.query({
  filter:[
    {
        "op": "eq",
        "field": "CompanyName",
        "value": "Sirius Cybernetics Corporation "
    }
  ]
});

Query results take the following form (example shows the Company returned from the above query)

{
  "items": [
    {
      "id": 29683616,
      "additionalAddressInformation": "",
      "address1": null,
      "address2": null,
      "alternatePhone1": "",
      ...
      "surveyCompanyRating": null,
      "taxID": "",
      "taxRegionID": null,
      "territoryID": null,
      "webAddress": null,
      "userDefinedFields": []
    }
  ],
  "pageDetails": {
    "count": 1,
    "requestCount": 500,
    "prevPageUrl": null,
    "nextPageUrl": null
  }
}

Limiting fields returned on a query.

//Find a company by name
let result = await autotask.Companies.query({
  filter:[
    {
        "op": "eq",
        "field": "CompanyName",
        "value": "Sirius Cybernetics Corporation "
    }
  ],
  includeFields:[
    "Id",
    "companyName",
    "city",
    "state"
  ]
});

Running the above query yields a response:

{
  "items": [
    {
      "id": 29683616,
      "city": "",
      "companyName": "Sirius Cybernetics Corporation",
      "state": "",
      "userDefinedFields": []
    }
  ],
  "pageDetails": {
    "count": 1,
    "requestCount": 500,
    "prevPageUrl": null,
    "nextPageUrl": null
  }
}

Note: when using creating filters and specifying field include conditions, field names are not case sensitive.

Querying User Defined Fields

It is possible to query user-defined fields by including a "udf": true to UDF field expressions in filter conditions. In the example below, a Company-level UDF named "Number of Employees" exists. We can query to see which companies have more than 0 employees like this:

result = await autotask.Companies.query({
  filter:[
    {
        "op": "gt",
        "field": "Number of Employees",
        "value": 0,
        "udf": true
    }
  ]
});

related Autotask documentation

create

Creates an entity.

The following creates Company using the Companies api.

 let myCompany = {
      CompanyName: "Sirius Cybernetics Corporation",
      CompanyType: 3,
      Phone: '8005551212',
      OwnerResourceID: 29683995
    };;
result = await autotask.Companies.create(myCompany);

..which yields the result:

{
  "itemId": 29683664
}

Note some entities in the Autotask REST API are child entities of other entities. This does NOT affect how you query or retrieve them, but it does require you to provide the parent entity id when using the create(), update(), replace(), or delete() methods.

To illustrate the child record relationship, the following example will create a ToDo for a Company using the CompanyToDos api.

 let myToDo = {
  ActionType: 3,
  AssignedToResourceID: 29683995,
  CompanyID: 0, 
  ActivityDescription: "Learn more about the Autotask REST API",
  StartDateTime: '2020-06-15',
  EndDateTime: '2020-06-16',
};
result = await autotask.CompanyToDos.create(0, myToDo);

Note the use of the parent id (company id = 0) as the first argument of the create method. The parent id is required as the first parameter of the method. It yields the result:

{
  "itemId": 29684378
}

related Autotask documentation

update

Updates an entity. This updates ONLY the fields you specify, leaving other fields on it unchanged.

The following example updates a Company phone number.

let updateResult = await autotask.Company.update({"id":45701237, phone: "1112223344"});

As mentioned in the create() documentation above, child record relationships require a slight change in syntax when invoking updates on sub-entities. Here is another example of the child record relationship, using the Contacts entity. Since Contacts are children of Companies, we must also provide the CompanyID of the Contact before we can update it.

// Here we are using the autotask.Contacts handle. Queries don't require knowledge of parent-child structure.
let queryResult = await autotask.Contacts.query({filter:[{field:'firstName', op:FilterOperators.eq, value:'Zaphod'}]});

let companyID = queryResult.items[0].companyID;

// However, here we are using the autotask.CompanyContacts handle because of the structure required by the Autotask REST API. The parent entity is provided as the first argument of the update.
let updateResult = await autotask.CompanyContacts.update(companyID, {"id":30684047, middleName: "Hortensius"});

Note some entities in the Autotask REST API are child entities of other entities. This doesn't affect how you query or retrieve them, but it does require you to provide the parent entity id when using the create(), update(), replace(), or delete() methods.

related Autotask documentation

replace

Replaces an entity. This replaces the entire entity, obliterating its prior contents (except for readonly fields) and replacing it with the data you provide.

Note some entities in the Autotask REST API are child entities of other entities. This doesn't affect how you query or retrieve them, but it does require you to provide the parent entity id when using the create(), update(), replace(), or delete() methods.

related Autotask documentation

delete

Deletes an entity by id.

Note some entities in the Autotask REST API are child entities of other entities. This doesn't affect how you query or retrieve them, but it does require you to provide the parent entity id when using the create(), update(), replace(), or delete() methods.

related Autotask documentation

info

related Autotask documentation

fieldInfo

Get metadata about a given entity's fields. This includes information about the data type; whether the field is required, read-only etc; and any valid-values that should be used. related Autotask documentation

result = await autotask.AccountToDo.fieldInfo();

This will yield a result:

{
  "fields": [
    {
      "name": "ActionType",
      "dataType": "integer",
      "length": 0,
      "isRequired": true,
      "isReadOnly": false,
      "isQueryable": true,
      "isReference": false,
      "referenceEntityType": "",
      "isPickList": true,
      "picklistValues": [
        {
          "value": "0",
          "label": "Opportunity Update",
          "isDefaultValue": false,
          "sortOrder": 0,
          "parentValue": "",
          "isActive": true,
          "isSystem": true
        },
        {
          "value": "1",
          "label": "Phone Call",
          "isDefaultValue": false,
          "sortOrder": 0,
          "parentValue": "",
          "isActive": true,
          "isSystem": true
        },
        ...
      ],
      "picklistParentValueField": "",
      "isSupportedWebhookField": false
    },
    {
      "name": "ActivityDescription",
      "dataType": "string",
      "length": 32000,
      "isRequired": false,
      "isReadOnly": false,
      "isQueryable": true,
      "isReference": false,
      "referenceEntityType": "",
      "isPickList": false,
      "picklistValues": null,
      "picklistParentValueField": "",
      "isSupportedWebhookField": false
    },
    ...
    
  ]
}

related Autotask documentation

udfInfo

related Autotask documentation

Special Cases

Modules

The Modules entity allows you to gather information about the active status of modules in Autotask PSA. It can only be queried. Use either empty .get() or .query() methods to obtain the list of modules.

Example:

result = await autotask.Modules.get();

results:

{
  "modules": [
    {
      "key": 24,
      "value": true
    },
    {
      "key": 36,
      "value": true
    },
    {
      "key": 65,
      "value": true
    },
    ...
}

related Autotask documentation

Available Entities

The following is a list of all Autotask entities supported by the connector:

  • ActionTypes
  • AdditionalInvoiceFieldValues
  • Appointments
  • AttachmentInfo
  • ProjectCharges
  • BillingCodes
  • BillingItems
  • BillingItemApprovalLevels
  • ChangeOrderCharges
  • ChangeRequestLinks
  • ChecklistLibraries
  • ClassificationIcons
  • ClientPortalUsers
  • ComanagedAssociations
  • Companies
  • CompanyWebhooks
  • ConfigurationItems
  • ConfigurationItemCategories
  • ConfigurationItemTypes
  • Contacts
  • ContactGroups
  • ContactWebhooks
  • Contracts
  • ContractExclusionSets
  • Countries
  • Currencies
  • Departments
  • Expenses
  • ExpenseReports
  • HolidaySets
  • InternalLocations
  • InternalLocationWithBusinessHours
  • InventoryItems
  • InventoryLocations
  • InventoryTransfers
  • Invoices
  • InvoiceTemplates
  • Modules
  • NotificationHistory
  • Opportunities
  • OrganizationalLevel1
  • OrganizationalLevel2
  • OrganizationalLevelAssociations
  • PaymentTerms
  • PriceListMaterialCodes
  • PriceListProducts
  • PriceListProductTiers
  • PriceListRoles
  • PriceListServices
  • PriceListServiceBundles
  • PriceListWorkTypeModifiers
  • Products
  • Projects
  • PurchaseApprovals
  • PurchaseOrders
  • Quotes
  • QuoteLocations
  • QuoteTemplates
  • Resources
  • ResourceRoles
  • Roles
  • Services
  • ServiceBundles
  • ServiceCalls
  • ShippingTypes
  • Skills
  • Subscriptions
  • Surveys
  • SurveyResults
  • Taxes
  • TaxCategories
  • TaxRegions
  • ThresholdInformation
  • Tickets
  • TicketCategories
  • TicketHistory
  • TimeEntries
  • UserDefinedFieldDefinitions
  • WebhookEventErrorLogs
  • WorkTypeModifiers
  • ZoneInformation

The REST API introduces a parent-child relationship among some Autotask entities. The connector uses a shorthand name to make working with the entities more intuitive. The following child-entities are also supported by the connector:

  • ChecklistLibraryChecklistItems → ChecklistLibraries/ChecklistItems
  • CompanyAlerts → Companies/Alerts
  • CompanyAttachments → Companies/Attachments
  • CompanyContacts → Companies/Contacts
  • CompanyLocations → Companies/Locations
  • CompanyNotes → Companies/Notes
  • CompanySiteConfigurations → Companies/SiteConfigurations
  • CompanyTeams → Companies/Teams
  • CompanyToDos → Companies/ToDos
  • CompanyWebhookExcludedResources → CompanyWebhooks/ExcludedResources
  • CompanyWebhookFields → CompanyWebhooks/Fields
  • CompanyWebhookUdfFields → CompanyWebhoosk/UdfFields
  • ConfigurationItemAttachments → ConfigurationItem/Attachments
  • ConfigurationItemBillingProductAssociations → ConfigurationItems/BillingProductAssociations
  • ConfigurationItemCategoryUdfAssociations → ConfigurationItemCategories/UdfAssociations
  • ConfigurationItemNotes → ConfigurationItems/Notes
  • ConfigurationItemNoteAttachments → ConfigurationItemNotes/Attachments
  • ContactBillingProductAssociations → Contacts/BillingProductAssociationis
  • ContactGroupContacts → ContactGroups/Contacts
  • ContactWebhookExcludedResources → ContactWebhooks/ExcludedResources
  • ContactWebhookFields → ContactWebhooks/Fields
  • ContactWebhookUdfFields → ContactWebhooks/UdfFields
  • ContractBillingRules → Contracts/BillingRules
  • ContractBlocks → Contracts/Blocks
  • ContractBlockHourFactors → Contracts/BlockHourFactors
  • ContractCharges → Contracts/Charges
  • ContractExclusionBillingCodes → Contracts/ExclusionBillingCodes
  • ContractExclusionRoles → Contracts/ExclusionRoles
  • ContractExclusionSetExcludedRoles → ContractExclusionSets/ExcludedRoles
  • ContractExclusionSetExcludedWorkTypes → ContractExclusionSets/ExcludedWorkTypes
  • ContractMilestones → Contracts/Milestones
  • ContractNotes → Contracts/Notes
  • ContractRates → Contracts/Rates
  • ContractRetainers → Contracts/Retainers
  • ContractRoleCosts → Contracts/RoleCosts
  • ContractServices → Contracts/Services
  • ContractServiceAdjustments → Contracts/ServiceAdjustments
  • ContractServiceBundles → Contracts/ServiceBundles
  • ContractServiceBundleAdjustments → Contracts/ServiceBundleAdjustments
  • ContractServiceBundleUnits → Contracts/ServiceBundleUnits
  • ContractServiceUnits → Contracts/ServiceUnits
  • ContractTicketPurchases → Contracts/TicketPurchases
  • ExpenseItems → Expenses/Items
  • Holidays → HolidaySets/Holidays
  • InventoryItemSerialNumbers → InventoryItems/SerialNumbers
  • OpportunityAttachments → Opportunities/Attachments
  • OrganizatonalResources → OrganizationalLevelAssociations/Resources
  • Phases → Projects/Phases
  • ProductNotes → Products/Notes
  • ProductTiers → Products/Tiers
  • ProductVendors → Products/Vendors
  • ProjectAttachments → Projects/Attachments
  • ProjectCharges → Projects/Charges
  • ProjectNotes → Projects/Notes
  • PurchaseOrderItems → PurchaseOrders/Items
  • PurchaseOrderItemReceiving → PurchaseOrderItems/Receiving
  • QuoteItems → Quotes/Items
  • ResourceRoleDepartments → Resources/RoleDepartments
  • ResourceRoleQueues → Resources/RoleQueues
  • ResourceServiceDeskRoles → Resources/ServiceDeskRoles
  • ResourceSkills → Resources/Skills
  • SalesOrders → Opportunities/SalesOrders
  • ServiceBundleServices → ServiceBundles/Services
  • ServiceCallTasks → ServiceCalls/Tasks
  • ServiceCallTaskResource → ServiceCallTasks/Resources
  • ServiceCallTickets → ServiceCalls/Tickets
  • ServiceCallTicketResource → ServiceCallTickets/Resources
  • ServiceLevelAgreementResults → ServiceLevelAgreements/Results
  • SubscriptionPeriods → Subscriptions/Periods
  • Tasks → Projects/Tasks
  • TaskAttachments → Tasks/Attachments
  • TaskNotes → Tasks/Notes
  • TaskNoteAttachments → TaskNotes/Attachments
  • TaskPredecessors → Tasks/Predecessors
  • TaskSecondaryResources → Tasks/SecondaryResources
  • TicketAdditionalConfigurationItems → Tickets/AdditionalConfigurationItems
  • TicketAdditionalContacts → Tickets/AdditionalContacts
  • TicketAttachments → Tickets/Attachments
  • TicketCategoryFieldDefaults → TicketCategories/FieldDefaults
  • TicketChangeRequestApprovals → Tickets/ChangeRequestApprovals
  • TicketCharges → Tickets/Charges
  • TicketChecklistItems → Tickets/ChecklistItems
  • TicketChecklistLibraries → Tickets/ChecklistLibraries
  • TicketNotes → Tickets/Notes
  • TicketNoteAttachments → TicketNotes/Attachments
  • TicketRmaCredits → Tickets/RmaCredits
  • TicketSecondaryResources → Tickets/SecondaryResources
  • TimeEntryAttachments → TimeEntries/Attachments
  • UserDefinedFieldListItems → UserDefinedFields/ListItems

Error Handling

REST API HTTP errors are wrapped in an AutotaskApiError class that can be used to obtain further information about errors returned from Autotask.

For example:

try{
  let myCompany = {
    CompanyName: undefined, //<-- it is required!
    CompanyType: 3,
    Phone: '8005551212',
    OwnerResourceID: 29683995
  };
  let result = await autotask.Companies.create(myCompany);

} catch ( err ){
  if( err instance of AutotaskApiError ){
    // Custom handling is possible for Autotask REST API errors.
    console.error(`Error message: ${ err.message }\nHTTP status: ${ err.status }\nError Details: ${ JSON.stringify(err.details) }`)
  }
}

Please note, in some cases, the Autotask REST API HTTP error handling may not behave in ways you might expect. For example:

An invalid API username will lead to an HTTP 500 error returning:

{"errors":["Zone information could not be determined"]}

, not an HTTP 401 error.

An invalid API Integration key will lead to an HTTP 500 error returning:

{"errors":["IntegrationCode is invalid."]}

, not an HTTP 401 error.

Debugging

Support for debugging is provided via the debug library. Two levels of debugging are supported:

  • debug include autotask:restapi in your DEBUG environment variable
  • verbose include autotask:restapi:verbose or simply autotask:restapi* in your DEBUG environment variable.

Package Sidebar

Install

npm i @apigrate/autotask-restapi

Weekly Downloads

107

Version

2.0.0

License

Apache-2.0

Unpacked Size

66.8 kB

Total Files

8

Last publish

Collaborators

  • apigratedev