@apigrate/autotask-restapi
v2.0.0
Published
NodeJS library for the Autotask REST API.
Downloads
425
Readme
Autotask REST API NodeJS Connector
v2 Release Notes
Breaking changes:
- Codebase now uses native fetch and requires Node > 18.0.0. (Removed dependency on
isomorphic-fetch
.) - Removed the api() method. All API entity references are now available directly on the AutotaskRestApi instance.
- 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 thequery
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()
, ordelete()
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()
, ordelete()
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()
, ordelete()
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()
, ordelete()
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 yourDEBUG
environment variable - verbose include
autotask:restapi:verbose
or simplyautotask:restapi*
in yourDEBUG
environment variable.