API Documentation for Connectwise Manage APIs
This is documentation created and owned by ConnectWise. Any reference to "We" or "Our" is referring to ConnectWise, not Presh.
ClientId
You should never share your clientId, doing so may result in issues relating to integrations in your environments. A clientId is unique to your company and is used to say that API traffic is coming from your source. It should be treated as a sort of password and identifier for your company. If anyone asks you to provide a clientId value, do not do so. The only exception to this rule would be integrations where you yourself are creating it. For instance, if you use Zapier and use the Zapier Code function and add your own API call, not in the Manage package. If a tool requires that you enter in the API full path, the body and request, map it to different things, or otherwise is a custom tool that the vendor is not actually developing the calls, you may have to enter your clientId. Do not provide clientId values to integrations that are designed "out-of-the-box" and apply to all users. An example would be the Automate to Manage integration. That is an integration that is the same for every user and the clientId would be set up by the third-party integration. Automate controls the Ids around that integration themselves.
Depending on the value that you select, the API Routing may change. You must select the value that represents what you are trying to accomplish. If you select Private, the clientId values cannot be used against environments that you do not own.
- Public - This should be used when an integration is being used by multiple companies. All of the integrations listed on the ConnectWise Marketplace and any other vendor integration would fall into this category.
- Private - These would be in-house integrations that never get hooked up to another instance. Maybe you have an internal efficiency tool that you use or some sort of process automation that you designed.
- Contractor - Only use this if you are creating essentially public or private integrations for someone else. Typically a contractor is hired by either a Solution Provider or Partner to create an integration on their behalf.
Follow this link to view additional documentation and generate a clientId
Versioning
Starting with 2019.1 the API is now tied to the Manage release cycle. Previously the API was versioned as it's own entity and followed a format such as 3.0.1. To provide clarity around the API Versioning and to make it easier for consumers, we have replaced 3.0.0 with the specific Manage version that the API model was released on.
If you develope your API against 2019.1 and pass in the version 2019.1, you will continue to get the models for 2019.1 even if we change them in 2019.2. What this means is that each time we release a breaking change, you have a period of time to switch over to the new version. We do not release new models every release, however you can still target a version that did not have any changes. For instance, lets say in 2019.1 we have a specific ticket model called A. In 2019.4 we update tickets to have model B. If you pass 2019.1, 2019.2 or 2019.3, you will get model A, which is 2019.1.
By default all requests will receive the latest version of our API endpoint. As breaking changes are released, each individual API endpoint, may receive an updated version. In order to prevent your integration from breaking, we encourage you to request a specific version using an Accept header. For all production level integrations we recommend using this Accept header concept and for all development and testing work, we recommend using the latest version of the API. We will regularly deprecate old models of the API.
What is a breaking change?
Breaking changes are defined as any change to the APIs that could result in an error being returned by the SDK. The SDK is a JSON interpreter and as long as you develop your code the way a modern JSON interpreter would, you shouldn't have any issues. If you hard code every field, you will have issues that we don't consider breaking.
Examples of breaking changes:
-
Renaming a field (fixing a typo)
-
Changing a field's data type (such as from an int to a decimal, or from editable to read-only)
-
Changing the response type (such as from an object to an array of objects)
-
Validation changes (fields now required that previously were not)
NOT a breaking change:
-
Adding new fields
-
Adding new endpoints
-
Making a read-only field editable
-
Making a field no longer required if it was previously required
As we release breaking changes the individual endpoint will be versioned when applicable. The previous version will be immediately be considered deprecated but supported for 12 months. Please note that some endpoints cannot be versioned.
Formatting Version Header
We try to make it as simple as possible to format your version header. We use an accept header that lists our JSON schema as well as the version following. Accept headers tell the server what type of information you are expecting to get back. This makes it a perfect fit to add our version to as this tells the server that you want xyz version back.
1 | Accept: application/vnd.connectwise.com+json; version=2019.1 |
Per Endpoint
If you are not ready to update to the latest API Models for your entire integration, you can change your accept header to be on an endpoint by endpoint basis. We recommend that you keep a singular version across your integration, but will support it either way. Anytime you test your integration and validate it against a version, update your version header even if we are not deprecating the version you are on. We may do so without warning, or give you very little time to make changes.
Authentication
REST based integrations have three methods of authentication. The recommended method, is using an API Member account to create API Keys specific to the integration. The second method is to use impersonation. Impersonation uses either an Integrator Login (Legacy) or another Member to create API Keys programmatically for other members. The third method which is only support for internal integrations, uses username and passwords for individual members. Due to this method requiring a user to enter their ConnectWise Manage username and password into another application, we do not support vendors utilizing this method.
ConnectWise Manage utilizes the "Basic Auth" standard with Public and Private keys and the authorization header that are unique to ConnectWise Manage members. This means you can use the benefits of ConnectWise Manage security roles and give granular access to the APIs.
Your header must be base64 encoded and has to include a username:password. The username will always begin with CompanyId+ and then use either the public key, integrator username or MemberId. The password will be the private key, integrator password or member hash.
Method 1 - API Keys - Member Authentication
It is recommended to create API Members versus using API Keys tied to a specific member.
Authorization: Basic base64(companyid+publickey:privatekey)
(Authorization: Basic Y29tcGFueWlkK3B1YmxpY2tleTpwcml2YXRla2V5)
Method 2 - Integrator Login - Impersonation
This method should only be used for legacy integrations in a transition period.
Authorization: Basic base64(companyid+integratorlogin:integratorpassword)
(Authorization: Basic Y29tcGFueWlkK2ludGVncmF0b3Jsb2dpbjppbnRlZ3JhdG9ycGFzc3dvcmQ=)
Method 3 - Member ID and Password - Cookie Authentication (Not intended for 3rd party products unless using Hosted API)
This method uses 3 cookie headers.
Cookie: companyName=YourLoginCompany
Cookie: memberHash=Generated by POST to login.aspx or via Hosted API
Cookie: memberId=YourUsername
Important Note: SSL is required on production PSA servers when accessing the API. Any calls received via regular HTTP will be denied on production systems.
Are you connecting to the Cloud or Staging? If so you must include API- in front of the ConnectWise Manage site:
api-au.myconnectwise.net
api-eu.myconnectwise.net
api-na.myconnectwise.net
api-staging.connectwisedev.com
Otherwise you will run into this error:
{
"code": "Security",
"message": "SSL is required.",
"errors": null
}
Obtaining your Keys
We only support API Member and My Account based authentication for Integration Vendors. Impersonation and Cookie Authentication are for internal only based integrations. In rare cases impersonation may be the route to go.
API Member Only *Recommended for 3rd partiesMember ImpersonationMy AccountCookie AuthenticationSecurity
When working with the Manage REST API, security is based off the Security Roles table within Manage. This table determines each type of entity and the level of access associated. We do not recommend requesting Admin access for an integration. Instead integrators are highly encouraged to only enable the security roles for access that they need.
Click here to view our Security Role Matrix
When looking at the REST API documentation, you may notice that some items are considered a Setup Table value. These are denoted with the lock icon. These endpoints will return an inquire level of access without actually having access to the table. This matches the UI functionality in that you can create listings of available statuses and boards without having access to the setup table associated for those values.
HTTP Methods
- POST
- Create entity or any non CRUD action
- GET
- Return entity or list of entities
- PUT
- Replace all fields on entity with supplied fields
- PATCH
- Update specific fields on an entity
- DELETE
- Remove entity
HTTP Response Statuses
- 201 Created
- Response will the record that was created as well as the path to it.
- 204 NoContent
- Will be returned by successful delete requests
- 400 Bad Request
- The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications
- 401 Unauthorized
- The supplied authentication is incorrect
- 403 Forbidden
- Improper security role settings for the supplied authentication
- 404 Not Found
- Resource URL not found, this could mean the record was deleted or moved
- 405 Method Not Allowed
- This will occur if you try to use an HTTP method that is not supported by the URL specified
- 409 Conflict
- Record possibly in use or other conflict with record
- 415 Unsupported Media Type
- This can occur when using the documents API if you are sending the file as a JSON object
- 500 Server Error
- Server errors can occur often times due to a network fault or other non-application related error, however, In some cases a 500 error may occur when another error message has not been defined for an error
- These errors should follow the retry logic we recommend and if it appears to be an undefined error, should be reported
Manage Specific - Are you getting a 404 error or "Could not get any response" on cloud? You may have incorrect authentication instead of the resource not being found. To confirm, change your base URL from v4_6_release to your ConnectWise Manage version /201x_x/.
Formatting Each Method
Get
Get requests are used for finding both individual records or a listing of records. In order to grab an individual entity you must specify an id within the request URL.
https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000
When requesting a grouping of records, do not include an id record. Optionally include parameters at the end of the URL to instead grab a specific set of records.
https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets?conditions=board/name="Integration"%20and%20status/name="new"&page=1&pageSize=10
When looking at an endpoint, the parameters section will tell you which fields can be used to filter the request. In addition to the below parameters, you can use the Fields and Columns to manipulate the response dataset.
URL Max Length
The HTTP standards document does not impost a max URL length. However various browsers as well as applications have different limits in place. In addition search engines favor URLs that are around 2000 characters. As a URL growths in length it no longer remains user friendly and becomes unusable or readable by users. This causes issues with troubleshooting and leads to overall confusion. We recommend keeping the URL length of each request to a maximum of 2000 characters. This will ensure there are no compatibility issues with various servers and configurations. Please keep in mind that max length of a domain name can reach 255 characters. With that in mind, the safe max length of a URL would be around 1745 characters.
This can vary based on environment configurations. There will often be times where the URL could be significantly longer. There may also be one of server configurations based on premise that restrict the URL to a lower length. However it is recommended to keep the URL length to a max of 2000 characters including the domain name.
Query String Parameters
Parameter | Description | Example | |
conditions | Search results based on the fields returned in a GET | board/name="Integration" summary="xyz" board/id in (3, 2, 4) lastUpdated > [2016-08-20T18:04:26Z] Only fields returned in a GET request can be used |
=, !=, <, <=, >, >=, contains, like, in, not |
childConditions | Allows searching arrays on endpoints that list childConditions under parameters | /company/contacts?childconditions=communicationItems/value like "john@Outlook.com" AND communicationItems/communicationType="Email" | =, !=, <, <=, >, >=, contains, like, not |
customFieldConditions | Allows searching custom fields when customFieldConditions is listed in the parameters | /company/contacts?customFieldConditions=caption="TomNumber" AND value !=null | =, !=, <, <=, >, >=, contains, like, not |
orderBy | Choose which field to sort the results by | contact/name asc | asc or desc |
fields | Limits which information is returned in the response | company/companies?fields=id,name,status/id | Not available on the reporting endpoints |
columns | Limits which information is returned in the response | system/reports/service?columns=id,summary,name | Only used for the Reporting Endpoints |
page | Used in pagination to cycle through results | ||
pageSize | Number of results returned per page (Defaults to 25) | Max Size = 1,000* | |
*Max page size was increased to 1,000 in 2016.2. |
Conditions
Strings | Must be surrounded by quotes | Summary = "This is my string" (Accepts *'s for Wild Cards) |
Integers | No formatting required | Board/Id = 123 |
Boolean | No formatting required but must be True or False | ClosedFlag = True |
Datetimes | Must be surrounded by square brackets | LastUpdated = [2016-08-20T18:04:26Z] |
Operators | <, <=, =, !=, >, >=, contains, like, in, not | Summary Not Contains "Low Priority" |
Logic Operators | Supported operators include:
|
board/name="integration" and summary="xyz" |
Reference* | Must have a / followed by the field under the reference you would like to use | manufacturer/name |
Using the /Search endpoints
If your request URL is going to be over 10,000 characters long you can instead use the /Search path for certain endpoints. This allows you to enter the conditions in the body of the request.
POST /v4_6_release/apis/3.0/service/tickets/search HTTP/1.1
Host: YOURCONNECTWISESITE
Authorization: Basic AUTHKEY=
Content-Type: application/json
Body:
{
"conditions": "summary like 'test'"
}
Successful get requests will return a 200 status response and a content body of the record(s).
Patch
Patch requests enable the ability to update individual fields on an entity. When formatting the request you can specify multiple fields to be updated. When working with a patch, the entire object is part of an array and must be surrounded by square brackets as per the example below. If you do not have the square brackets, you will run into errors. In addition when you are updating a reference, you can only update it through the use of unique values. Many times Name is not considered unique.
https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000
[
{
"op": "string",
"path": "string",
"value": "string"
}
]
op | The update operation used in the request | add | replace | remove |
path | Pathway for the updated field (Case Sensitive) | summary company |
value | The new value if doing a replace Refer to escaping characters When working with custom fields, you must pass the entire array of custom fields. |
String: "Here is my Summary" Object: { "identifier": "connectwise" } |
[
{
"op": "replace",
"path": "summary",
"value": "New Summary"
},
{
"op": "replace",
"path": "company",
"value": {
"identifier": "New Company"
}
},
{
"op": "replace",
"path": "customFields",
"value": [
{
"id": 5,
"caption": "CloudPlus",
"type": "Checkbox",
"entryMethod": "EntryField",
"numberOfDecimals": 0,
"value": false
},
{
"id": 28,
"caption": "test",
"type": "Text",
"entryMethod": "List",
"numberOfDecimals": 0,
"value": "test"
}
]
}
]
When updating an Object such as Company, you cannot specify a location inside of the object. You have to replace the whole object like the example above. (Do not use "path":"company/identifier") If you try to update the Object incorrectly, you may receive a false 200 message.
Successful patch requests will return a 200 status response for success
Delete
Delete requests are used for removing records from the ConnectWise Manage system. Please take care when removing items as they cannot be recovered. The id for the record to be deleted needs to be included in the request URL.
https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000
Successful delete requests will return a 204 status response for No Content. 204 is a success response.
Post
Post is used when creating new records. The body of the request must be send in a JSON format. When sending a Post the response body will include the newly created record id as well as a Get request for the record. If you pass a post request without filling out every possible value, the system will attempt to default all required information and anything that does not require a value, will be set to Null.
Put
Put requests are designed to completely replace an entity. They work the in same manner as a Post request with the exception that you must specify an already created entity in your URL. When you use Put to update a record, any field that has not been specified will be overridden with the system defaults or set to Null.
Escaping Characters
When working with JSON, you may find that you need to use characters that require escaping. This comes into play primarily when quotes are involved as we do not support many of the characters that require escaping. Refer to the chart below:
Character | Escaped | Displayed in the UI |
---|---|---|
Double Quotes | \" | " |
Backslash | \\ | \ |
Tab | \t | Tabbed space equal to four spaces |
Backspace (Not Supported) | \b | Invisible character that doesn't take up any space |
Carriage Return (Not Supported) | \r | Single space which is returned as a space in the API instead of an escaped character |
Newline (Not Supported) | \n | Single space which is returned as a space in the API instead of an escaped character |
Form Feed (Not Supported) | \f | Invisible character that doesn't take up any space |
Applies to JSON Bodies Only: Please note that Single Quotes ', do not require escaping as they should not be used as a container for your strings. If you are using single contains around string values, you must switch to doubles. |
URL Encoding is required for when using conditions and other URL parameters that have symbols that would denote new query parameters or strings.
Character | Formatting |
---|---|
& | %26 |
" | %22 |
' | %27 |
* | %2A |
% | %25 |
+ | %2B |
[string] | [[]string] |
Applies to URL Parameters Only |
Partial Responses
The API allows you to specify which information you want returned. You do this by listing the request fields or columns on your endpoint URL. Partial responses work for both GET and POST requests..
Fields | company/companies?fields=company/id,company/name,phoneNumber |
Columns (Reporting API only) | system/reports/service?columns=id,summary,company/name |
Custom Fields
Screens that have custom fields in the ConnectWise Manage UI will have an array of fields on the respective endpoint. This array can be both queried and updated via the API. When updating custom fields, you must pass in the entire array object, which means that you cannot patch a single custom field record. Wondering if an endpoint supports custom fields? Supported endpoints will have customFields(CustomFieldValue[]) listed at the end of the documentation.
There are two methods of adding new custom fields to the ConnectWise Manage environment. The first method will require access to the ConnectWise Manage thick client and the second method is available in the system/userDefinedFields endpoint within the REST API.
Refer to the GET section on how to search custom fields. Searching custom fields uses customFieldConditions instead of conditions.
In order to access the custom fields via the thick client, navigate to System > Setup Tables > Custom fields,
Field Options and Parameters
Field | Description |
Field Caption | Enter a custom field caption for this required field; you are limited to 12 characters. |
Help Text |
The text entered in this field will be displayed when you hover over the help button next to the custom field on the screen. Note: This has a limit of 1000 characters, however only 512 characters will display on the opportunity screen. |
Field Type |
Select one of the following options:
|
Number of Decimals | This required field is only available for the Number and Percent Field Type. You can add up to 5 decimal places. |
Method of Entry |
Select one of the following options:
|
Sequence # | Enter a sequence number. This value must be between 1 and 50. |
Required Field? | Select this checkbox if you would like to make this a required custom field. This will display as a blue asterisk. |
Display on Screen? | Select this checkbox if you would like this to display on the Opportunities screen. This is selected by default. |
Read Only? | This field is used for the API. The Required Field checkbox cannot be marked for this field. |
Include on List View? |
Select this checkbox if you would like to include this custom field in the My Opportunities list view screen. Note: There is a limit of 10 fields that can be displayed on the list view screen. You can have an unlimited number of custom fields, but the check box will not display if there are already 10 list items. You can unselect this check box at any time. |
Button URL | Enter the URL if you are using the Field Type of Button. The field only appends URLs, no other form of entry will generate content. |
Select the Locations that will use this Custom Field | This is a required field. Opportunities that have the specified location(s) will display this custom field. Select at least one location that the custom field will be used. |
Select the Departments that will use this Custom Field | This is not a required field. Opportunities that have the specified department(s) will display this custom field. |
Pagination
Navigable
The ConnectWise Manage API provides a vast wealth of information for developers to consume. Most of the time, you will find that there is far more information than is needed for an integration. In order to ensure server availability, the API automatically sets page size to 25 results. The maximum page size for any request can be up to 1,000 records if properly specific in the request URL.
pagesize | Number of results returned by each call. Defaulted to 25 and has a maximum of 1,000. These values cannot be changed. |
page | Starting with page 1, this is the number of pages available based on the current pagesize. |
When using paging, the response will include a Link header that looks like this:
1 | /v4_6_release/apis/3.0/company/companies?pagesize=50&page=1 |
2 | link <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=2>; rel="next", <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=4>; rel="last" |
If you notice, the header contains two separate URLs in this instance. The first one is "next" and the second one is "last". These refer to the next set of results and the final set of results. If we navigate to the next page, we will get some additional URLs in the response Link header.
1 | /v4_6_release/apis/3.0/company/companies?pagesize=50&page=2 |
2 | link <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=3>; rel="next", <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=1>; rel="prev", <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=1>; rel="first", <https://staging.connectwisedev.com/v2017_3/apis/3.0/company/companies?pageSize=50&page=4>; rel="last" |
Now that we have navigated to the second page, we will find two additional URLs. These are "prev" and "first" and in total we now have four including the original "next" and "last".
First | This link will display the first page available based on the current page size |
Prev* | This link will display the previous page based on the current page position and page size |
Next* | This link will display the next available page based on the current page position and page size |
Last | This link will always display the final page available based on the current page size |
*We will not return the next or prev links if there isn't a next or prev respectively.
In the above examples, we have four pages of results and depending on the pagesize, that number can change. For instance, lets say we switch to the default page size of 25. Instead of returning four pages, we actually get back 7 pages as there are only 160 results.
The goal of pagination is not to pull every possible result, every single time. Instead it is designed to be in conjunction with a UI component to create a set of navigation links.
Navigable Pagination closely follows RFC 5988.
Forward-Only
Released in 2018.5
Unlike with Navigable Pagination, forward-only requires that you pass in a header to identify the type of pagination you would like to use. For instance, we now accept a header called pagination-type and when you set that to forward-only you will get to utilize the new features. In addition to the new header, there is a new query parameter called pageId. The pageId is record in which you would like to begin with for paging.
- If you do not include the new header in your request, it will use the default paging method of navigable.
- The Page query parameter will be ignored with forward-only paging as all results are technically page 1.
- You cannot use an Order By query parameter with forward-only as it must be ordered by the ID.
- There will always be a link header in the response for the next pageId.
- The pageId query paramter is treated like an additional condition of Id > pageId.
- The following pageId in the header will be the last Id you got in the request.
Forward-Only pagination does not work with the Audit Trail endpoints at this time.
Callbacks (Webhooks)
ConnectWise Manage callbacks are payloads of information that are similar to webhooks. When a record is saved within ConnectWise Manage, a summarized payload is sent to a specified location.
Configuring the Callbacks
More information can be found within the REST API documentation Here with the endpoint system/callbacks.
Fields |
Description |
Id | The database record id of the callback, this is automatically assigned. |
Description | This is used to label the callback's usage. |
URL | This is the URL ConnectWise Manage will send the GET payload to. |
ObjectId | The ObjectId should be the Id of whatever record you are subscribing to. This should be set to 1 when using a level of Owner. |
Type | This is the specific type of record such as Company, Ticket, Contact, etc... See the associated table for all values. |
Level | The level is used to determine how granular the callback subscription will be. See associated table for all values. |
MemberId | This is a read only value that shows who initially created the Callback. |
InactiveFlag | Used to determine if the callback is active and sending requests. |
_Info | This section has additional meta data about the record and is included on all API requests as read only data. |
01 | POST /v4_6_release/apis/3.0/system/callbacks |
02 | { |
03 | "id": 0, |
04 | "description": "maxLength = 100", |
05 | "url": "Sample string", |
06 | "objectId": 0, |
07 | "type": "Sample string", |
08 | "level": "Sample string", |
09 | "memberId": 0, |
10 | "inactiveFlag": "false", |
11 | "_info ": { "lastUpdated": "", "updatedBy": "" } |
12 | } |
Testing Callbacks
Webhook.Site
When testing the ConnectWise Manage callbacks there are a number of useful browser based tools. One of note is Webhook.Site.
Simply use the New button to create a URL and then the Copy URL button to save the URL generated to your clipboard and add this as your ConnectWise Manage callback URL.
https://webhook.site/xxxxxxx-xxxx-xxxx-af13-855ab85aebae
Verifying the Callback Source
Callbacks contain a key_url in the meta data section that can be used to verify the source of the callback. The key_url returns the signing key which then can be used in conjunction with the below code sample and the x-content-signature.
1 | using (var sha = new SHA256Managed()) |
2 | { |
3 | var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(sharedSecretKey)); |
4 | using (var hmac = new HMACSHA256(hash)) |
5 | { |
6 | return Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(jsonPayload))); |
7 | } |
8 | } |
Callback Changelog
Supported Version | Changes |
ConnectWise Manage 2020.2 | Added callbacks for Configurations |
ConnectWise Manage 2016.6 | Added callbacks for Invoice Added callbacks for Projects Added callbacks for Activities |
ConnectWise Manage 2016.5 | Company Callbacks: Added Status and Type levels Contact Callbacks: Added Type level Ticket Callbacks: Added levels for tracking Project Tickets |
ConnectWise Manage 2016.4 | Added callbacks for Opportunities |
ConnectWise Manage 2016.3 | Added callbacks for Companies and Contacts |
ConnectWise Manage 2015.6 | Added callbacks for Tickets |
Troubleshooting
Troubleshooting with the REST API requires login access to the ConnectWise Manage UI. Additionally the account being used to login, must have access to information relating to the account for integration. In the case of the integration using API Members, the account accessing logs, must have the security roles to view members enabled. This requirement has to do with the API Keys used for integrations, being tied to a specific member.
Logging with the REST API must be specifically turned on and there is a time limit of 1440 minutes or 24 hours that can be recorded in a single session. During this time, all requests that are processed by the server and are associated to the member you are running logs from, will appear in the UI. If you are getting errors from the API and logs are not appearing, it may be a server side issue.
To get started with logging, you will need to access the API Log tab found on every ConnectWise Manage member. Open the UI and navigate to either System > Members or My Account and after you select the respective account, click on the API Logs tab.
Once you have found the API Logs tab, the next step will be to press "Start Debug Mode" and from there, select the amount of time you would like to record for.
Debugging will only run for a maximum of 1440 minutes per queue. You can restart the timer at anytime by hitting "Start Debug Mode" again.
Reading Logs
Search | The search option will refresh the visible logs |
Start Debug Mode | This will kick off the recording process for the specified amount of time |
Download Logs | This will provide a shareable document that contacts all of the requests that were recorded since the last time the debug mode was started |
API Key Description | This is the public key that is associated to the logged API Call |
Start Time | This is the start time for the request which when clicked, will show you the request body details |
Duration (ms) | This is how long the request took to be completed in milliseconds |
Response | This will show the HTTP response code returned, please note that any error messages or underlined responses can be clicked in order to see further details |
Method | This is the HTTP Verb being used in the request |
URL | This is the full request endpoint URL that is being used and it can be used to see any conditions or extra fields not found in the request body |
Telerik's Fiddler
The built in logging capabilities of Manage are limited in that if you want your request to show up, it must of first of been processed by the server. What this means, is that if your request is timed out, malformed or one of many other ways in which the server rejects your request, you will not be able to use the built in tools for diagnostics. There are other tools out there, besides our own built in tools, that will provide information about your requests. We have found that although there are many similar programs, Fiddler has provided the easiest user experience and it is extremely accurate.
Utility | Description | Download |
Fiddler by Telerik | Free Web Debugging Proxy | https://www.telerik.com/fiddler |
Fiddler must be run from the machine that is making the outbound requests. It cannot be run locally if the API requests are not leaving your local machine from your control. Once you have installed fiddler and have opened it for the first time you will see a window like the below screenshot.
Once you have managed to open Fiddler, there are a few settings that need to be changed in order for Fiddler to capture SSL.
After you have setup fiddler to be able to capture your requests, you simply need to send your API calls from your REST Client. The calls will begin to show up in the left side of the screen and when you click on them, various options will appear that let you manipulate the records. If you are using Postman to send your requests, you will also need to open Postman and go into the Settings section and turn off SSL Certificate Verification.
If you do not turn off certificate verification, Postman will return an error saying it couldn't get a response. Once you have successfully made your request or successfully had an error occur, the fiddler screen will display a list of URLs. Any that are marked in red will be errors that Fiddler bas detected.
If you click on the red entry you can drill into the details about the request and see more information on the error.
In this case we can see that the problem with the request is that company identifier is already in use. We can now right click on the red item and unlock it for editing. what this does is we can actually change the request right from within Fiddler. Once we have then corrected the request we can right click on it again and this time we can use replay. Replay will let you re-issue the command right from within Fiddler, without having to go back to your REST Client.
Error Handling
When working with the API, it is important to understand best practices for handling errors. In the case of ever error, it should be properly logged so it can be referenced later on. Server errors are generally considered to be temporary errors and requests should be repeated. If the request continues to occur, it should be submitted for review. When it comes to Client errors, the request should be stopped immediately and whoever setup the integration, should be given the error message in order to troubleshoot.
Retry Policy
An application that communicates with elements running in the cloud has to be sensitive to the transient faults that can occur in this environment. Faults include the momentary loss of network connectivity to components and services, the temporary unavailability of a service, or timeouts that occur when a service is busy.
These faults are typically self-correcting, and if the action that triggered a fault is repeated after a suitable delay it's likely to be successful. For example, a database service that's processing a large number of concurrent requests can implement a throttling strategy that temporarily rejects any further requests until its workload has eased. An application trying to access the database might fail to connect, but if it tries again after a delay it might succeed.
In the cloud, transient faults may occur and an application should be designed to handle them elegantly and transparently. This minimizes the effects faults can have on the business tasks the application is performing.
If an application detects a failure when it tries to send a request to a remote service, it can handle the failure using the following strategies:
-
Cancel. If the fault indicates that the failure isn't transient or is unlikely to be successful if repeated, the application should cancel the operation and report an exception. For example, an authentication failure caused by providing invalid credentials or any 400 errors are not likely to succeed no matter how many times it's attempted.
-
Retry. If the specific fault reported is unusual or rare, it might have been caused by unusual circumstances such as a network packet becoming corrupted while it was being transmitted. In this case, the application could retry the failing request again immediately because the same failure is unlikely to be repeated and the request will probably be successful.
-
Retry after delay. If the fault is caused by one of the more commonplace connectivity or busy failures, the network or service might need a short period while the connectivity issues are corrected or the backlog of work is cleared. The application should wait for a suitable time before retrying the request.
Do some asynchronous operation.
retries = 0
DO
wait for (2^retries * 100) milliseconds
status = Get the result of the asynchronous operation.
IF status = SUCCESS
retry = false
ELSE IF status = NOT_READY
retry = true
ELSE IF status = THROTTLED
retry = true
ELSE
Some other error occurred, so stop calling the API.
retry = false
END IF
retries = retries + 1
WHILE (retry AND (retries < MAX_RETRIES))
The retry policy should be tuned to match the business requirements of the application and the nature of the failure. For some noncritical operations, it's better to fail fast rather than retry several times and impact the throughput of the application. For example, in an interactive web application accessing a remote service, it's better to fail after a smaller number of retries with only a short delay between retry attempts, and display a suitable message to the user (for example, “please try again later”). For a batch application, it might be more appropriate to increase the number of retry attempts with an exponentially increasing delay between attempts.
It's important to log all connectivity failures that cause a retry so that underlying problems with the application, services, or resources can be identified.
500 Server Errors
Numerous components on a network, such as DNS servers, switches, load balancers, and others can generate errors anywhere in the life of a given request. The usual technique for dealing with these error responses in a networked environment is to implement retries in the client application. This technique increases the reliability of the application and reduces operational costs for the developer.
400 Client Errors
A 400 error means that the request isn't valid. In the case of a 400 error you should stop the requests and analyze the results in order to resolve the issue. Do not attempt to retry the request.
Document API
When working with the Document API, please use the upload sample provided with the following endpoint to proceed with testing.
GET https://ConnectWiseSite/v4_6_release/apis/3.0/system/documents/uploadsample
The response is an HTML template that shows each of the settings that can be selected. This form should help to design your own code and mimic functionality.
URL Formatting (Company Info)
When making calls to the ConnectWise Manage API, we have a URL that will give you the exact codebase to target in place of v4_6_release. This is useful to see if someone is on a cloud environment programmatically. Additionally the request can be routed directly to the correct ConnectWise Manage version for the partner without it going through another source.
Calling Company Info
"https://" + ConnectWiseSite + "/login/companyinfo/" + LoginCompanyId
https://na.myconnectwise.net/login/companyinfo/connectwise
Response
{
"CompanyName":"ConnectWise",
"Codebase":"v2017_3/",
"VersionCode":"v2017.3",
"VersionNumber":"v4.6.38842",
"CompanyID":"CW",
"IsCloud":"True" *Added in 2016.5
}
API Request URL Format
"https://" + ConnectWiseSite + "/" + codebase + "apis/3.0/company/companies"
https://api-my.myconnectwise.net/v2017_3/apis/3.0/company/companies
Cloud vs Premise
A cloud environment will return a codebase that has the ConnectWise Manage version. On-Premise does not use URL redirection and will return v4_6_release/. If your returned codebase contains anything other than v4_6_release/, you will need to ensure your request is prefixed by API-
Cloud URLs
These are the most commonly used URLs for the cloud.
https://na.myconnectwise.net
https://eu.myconnectwise.net
https://au.myconnectwise.net
https://aus.myconnectwise.net
https://za.myconnectwise.net
https://staging.connectwisedev.com