NodeJS library for the Autotask REST API.
npm install @apigrate/autotask-restapiisomorphic-fetch.)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.
``bash`
npm install @apigrate/autotask-restapi --saveConnecting to Autotask
`javascript
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.
`javascript
let company = await autotask.Companies.get(0);//Get the root company
`
> 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.
Counts entities. Use Autotask query filter syntax to provide criteria for the count.
`javascript
// 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
javascript
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
`javascript
// 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)..." } }
`
$3
Query for entities matching a filter expression.
`javascript
//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)
`json
{
"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.
`javascript
//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:
`json
{
"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:`javascript
result = await autotask.Companies.query({
filter:[
{
"op": "gt",
"field": "Number of Employees",
"value": 0,
"udf": true
}
]
});
`related Autotask documentation
$3
Creates an entity.The following creates Company using the Companies api.
`javascript
let myCompany = {
CompanyName: "Sirius Cybernetics Corporation",
CompanyType: 3,
Phone: '8005551212',
OwnerResourceID: 29683995
};;
result = await autotask.Companies.create(myCompany);
`
..which yields the result:
`json
{
"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.
`javascript
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:`json
{
"itemId": 29684378
}
`related Autotask documentation
$3
Updates an entity. This updates ONLY the fields you specify, leaving other fields on it unchanged.The following example updates a Company phone number.
`javascriptlet 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.
`javascript
// 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$3
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
$3
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
$3
related Autotask documentation$3
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`javascript
result = await autotask.AccountToDo.fieldInfo();
`This will yield a
result:`json
{
"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$3
related Autotask documentation$3
#### 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:
`javascript
result = await autotask.Modules.get();
`results:
`json
{
"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:
`javascript
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:
`json
{"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:
`json
{"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.