Files

3585 lines
214 KiB
HTML

<!DOCTYPE html>
<html lang="en" class="js csstransitions wf-proximanova-n7-active wf-proximanova-n4-active wf-proximanova-n3-active wf-proximanova-i7-active wf-proximanova-n6-active wf-proximanova-i4-active wf-active"><head prefix="og: http://ogp.me/ns# article: http://ogp.me/ns/article#">
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="generator" content="MindTouch">
<meta name="robots" content="index,follow">
<meta property="og:title" content="Developer Guide">
<meta property="og:site_name" content="Developer Network">
<meta property="og:type" content="article">
<meta property="og:locale" content="en_US">
<meta property="og:url" content="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide">
<meta property="og:image" content="https://a.mtstatic.com/@public/production/site_8263/1680273416-logo.png">
<meta property="og:description" content="">
<meta property="article:published_time" content="2016-01-22T19:40:49Z">
<meta property="article:modified_time" content="2025-04-08T15:54:36Z">
<meta name="twitter:card" content="summary">
<meta name="twitter:title" content="Developer Guide">
<meta name="twitter:description" content="">
<meta name="twitter:image" content="https://a.mtstatic.com/@public/production/site_8263/1680273416-logo.png">
<meta name="description" content="">
<link rel="canonical" href="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide">
<link rel="search" type="application/opensearchdescription+xml" title="Developer Network Search" href="https://developer.connectwise.com/@api/deki/site/opensearch/description">
<link rel="apple-touch-icon" href="https://a.mtstatic.com/@public/production/site_8263/1680273491-apple-touch-icon.png">
<link rel="shortcut icon" href="https://a.mtstatic.com/@public/production/site_8263/1680273592-favicon.ico">
<title>Developer Guide - Developer Network</title>
<style type="text/css">/*<![CDATA[*/
h3 {
font-size: 22px !important;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/
#mt-toc-container {
display: block !important;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/
dt {
color: #1468b1;
cursor: pointer;
}
dd {
display: none;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/
table, tr, td, th
{
border: 1px solid black;
border-collapse:collapse;
}
tr.header
{
cursor:pointer;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/#related,
.widget {
display: none;
}
.guide-content.static {
max-width: 98.5%;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/
.cw-footer {
background: #5d5d5d;
width: 100%;
color: #00aeef;
font-size: 11px;
clear: both;
}
.footer-wrapper {
position: relative;
max-width: 1050px!important;
width: 90%;
margin: 0 auto;
padding: 40px 0 75px 0;
overflow: hidden;
}
.cw-footer ul {
position: relative;
overflow: hidden;
list-style-type: none;
margin: 0 0 5px 0;
padding: 0;
}
.cw-footer ul li {
float: left;
border-right: 1px solid #00aeef;
margin: 0 6px 0 0;
padding: 0 6px 0 0;
list-style-type: none;
font-size: 11px;
line-height: 11px;
text-transform: uppercase;
}
.cw-footer ul li:last-child {
border: 0;
}
.cw-footer .social-links {
position: absolute;
top: 40px;
right: 0;
}
@media screen and (max-width:650px) {
.cw-footer .social-links {
position: static;
}
}
.cw-footer .social-links li {
border: 0;
font-size: 28px;
padding: 0;
}
.cw-footer p {
color: #fff;
}
.cw-footer a,
.cw-footer a.link-https,
.cw-footer a.mt-self-link {
color: #fff!important;
}
.cw-footer span.white-text {
color: #fff!important;
}
.elm-footer {
bottom: 0!important;
}
.elm-footer-custom p:last-child {
display: none;
}/*]]>*/</style><style type="text/css">/*<![CDATA[*/
/* Header Styles */
.header-blue {
background: #004b71;
height: 85px;
width: 100%;
position: relative;
}
#Version1_5 {
display:none;
}
.cw-wrapper {
max-width: 1050px;
height: 100%;
position: relative;
margin: 0 auto;
overflow: hidden;
width: 90%;
}
.header-wrapper {
max-width: 1050px;
height: 100%;
position: relative;
margin: 0 auto;
width: 90%;
z-index:500;
}
a#cw-logo {
display: block;
float: left;
width: 200px;
position: relative;
top: 10px;
z-index: 99999999;
}
.mt-logo {
display: none;
}
.action-items {
height: 40px;
position: absolute;
top: 20px;
right: 0;
}
@media screen and (max-width: 1050px) {
.action-items {
display: none;
}
}
.action-items a {
display: inline-block;
color: #fff;
padding: 8px 12px;
margin: 4px;
font-size: 13px;
}
.action-items a:visited {
color: #fff!important;
}
.action-items a:nth-child(2) {
background: #F18021;
}
.action-items a:last-child {
background: #F18021;
}
button#toggleSearch {
background: transparent;
border: 0;
outline: 0;
border-radius: 0;
padding: 0 .8em;
}
button#toggleSearch:focus,
button#toggleSearch:active:focus,
button#toggleSearch:active {
background: transparent!important;
outline: none!important;
outline-color: transparent!important;
outline-style: none!important;
box-shadow: none!important;
border-radius: 0!important;
padding: 0 .8em!important;
}
#toggleSearch i.fa-search {
color: white;
font-size: 17px;
position: relative;
top: 2px;
}
#search-cw {
max-width: 1050px;
margin: 0px auto;
position: relative;
display: block;
z-index:9999;
}
#search-cw form {
position: absolute;
width: 250px;
bottom: -40px;
right: 22px;
z-index: 99;
}
#search-cw input.mt-text {
border-radius: 0;
padding: 10px 10px 11px 10px;
border-color: #e7e7e8;
}
#search-cw button.mt-button {
position: absolute;
top: 0;
right: -21px;
background: #3fa85f;
border-radius: 0;
padding: 12px 10px 11px 11px;
color: #fff;
}
/* Mobile Nav */
.dl-menuwrapper {
width: 100%;
position: relative;
top: 20px;
-webkit-perspective: 1000px;
perspective: 1000px;
-webkit-perspective-origin: 50% 200%;
perspective-origin: 50% 200%;
}
.dl-menuwrapper:first-child {
margin-right: 100px;
}
.dl-menuwrapper button {
background: #1468b1;
border: none;
width: 48px;
height: 45px;
text-indent: -900em;
overflow: hidden;
position: absolute;
cursor: pointer;
outline: none;
top: 0;
right: 0;
visibility: hidden;
}
@media screen and (max-width: 1050px) {
.dl-menuwrapper button {
visibility: visible;
}
}
.dl-menuwrapper button:hover,
.dl-menuwrapper button.dl-active,
.dl-menuwrapper ul {
background: #1468b1;
}
.dl-menuwrapper button:after {
content: '';
position: absolute;
width: 68%;
height: 5px;
background: #fff;
top: 10px;
left: 16%;
box-shadow:
0 10px 0 #fff,
0 20px 0 #fff;
}
.dl-menuwrapper ul {
padding: 0;
list-style: none;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
}
.dl-menuwrapper li {
position: relative;
text-align: center;
border-bottom: 1px solid #007ac6;
}
.dl-menuwrapper li:last-child {
border-bottom: 0;
}
.dl-menuwrapper li a {
display: block;
position: relative;
padding: 15px 20px;
font-size: 16px;
line-height: 20px;
font-weight: 300;
color: #fff;
outline: none;
}
.no-touch .dl-menuwrapper li a:hover {
opacity: 0.8;
}
.dl-menuwrapper li.dl-back > a {
padding-left: 30px;
background: rgba(0,0,0,0.1);
}
.dl-menuwrapper li.dl-back:after,
.dl-menuwrapper li > a:not(:only-child):after {
position: absolute;
top: 0;
line-height: 50px;
font-family: 'icomoon';
speak: none;
-webkit-font-smoothing: antialiased;
content: "\e000";
}
.dl-menuwrapper li.dl-back:after {
left: 10px;
color: rgba(212,204,198,0.3);
-webkit-transform: rotate(180deg);
transform: rotate(180deg);
}
.dl-menuwrapper li > a:after {
right: 10px;
color: rgba(0,0,0,0.15);
}
.dl-menuwrapper .dl-menu {
margin: 5px 0 0 0;
position: absolute;
top: 60px;
width: 100%;
opacity: 0;
pointer-events: none;
-webkit-transform: translateY(10px);
transform: translateY(10px);
-webkit-backface-visibility: hidden;
backface-visibility: hidden;
}
.dl-menuwrapper .dl-menu.dl-menu-toggle {
transition: all 0.3s ease;
}
.dl-menuwrapper .dl-menu.dl-menuopen {
opacity: 1;
pointer-events: auto;
-webkit-transform: translateY(0px);
transform: translateY(0px);
}
/* Hide the inner submenus */
.dl-menuwrapper li .dl-submenu {
display: none;
}
/*
When a submenu is openend, we will hide all li siblings.
For that we give a class to the parent menu called "dl-subview".
We also hide the submenu link.
The opened submenu will get the class "dl-subviewopen".
All this is done for any sub-level being entered.
*/
.dl-menu.dl-subview li,
.dl-menu.dl-subview li.dl-subviewopen > a,
.dl-menu.dl-subview li.dl-subview > a {
display: none;
}
.dl-menu.dl-subview li.dl-subview,
.dl-menu.dl-subview li.dl-subview .dl-submenu,
.dl-menu.dl-subview li.dl-subviewopen,
.dl-menu.dl-subview li.dl-subviewopen > .dl-submenu,
.dl-menu.dl-subview li.dl-subviewopen > .dl-submenu > li {
display: block;
}
/* Dynamically added submenu outside of the menu context */
.dl-menuwrapper > .dl-submenu {
position: absolute;
width: 100%;
top: 50px;
left: 0;
margin: 0;
}
/* Animation classes for moving out and in */
.dl-menu.dl-animate-out-1 {
-webkit-animation: MenuAnimOut1 0.4s;
animation: MenuAnimOut1 0.4s;
}
.dl-menu.dl-animate-out-2 {
-webkit-animation: MenuAnimOut2 0.3s ease-in-out;
animation: MenuAnimOut2 0.3s ease-in-out;
}
.dl-menu.dl-animate-out-3 {
-webkit-animation: MenuAnimOut3 0.4s ease;
animation: MenuAnimOut3 0.4s ease;
}
.dl-menu.dl-animate-out-4 {
-webkit-animation: MenuAnimOut4 0.4s ease;
animation: MenuAnimOut4 0.4s ease;
}
.dl-menu.dl-animate-out-5 {
-webkit-animation: MenuAnimOut5 0.4s ease;
animation: MenuAnimOut5 0.4s ease;
}
@-webkit-keyframes MenuAnimOut1 {
0% { }
50% {
-webkit-transform: translateZ(-250px) rotateY(30deg);
}
75% {
-webkit-transform: translateZ(-372.5px) rotateY(15deg);
opacity: .5;
}
100% {
-webkit-transform: translateZ(-500px) rotateY(0deg);
opacity: 0;
}
}
@-webkit-keyframes MenuAnimOut2 {
0% { }
100% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
}
@-webkit-keyframes MenuAnimOut3 {
0% { }
100% {
-webkit-transform: translateZ(300px);
opacity: 0;
}
}
@-webkit-keyframes MenuAnimOut4 {
0% { }
100% {
-webkit-transform: translateZ(-300px);
opacity: 0;
}
}
@-webkit-keyframes MenuAnimOut5 {
0% { }
100% {
-webkit-transform: translateY(40%);
opacity: 0;
}
}
@keyframes MenuAnimOut1 {
0% { }
50% {
-webkit-transform: translateZ(-250px) rotateY(30deg);
transform: translateZ(-250px) rotateY(30deg);
}
75% {
-webkit-transform: translateZ(-372.5px) rotateY(15deg);
transform: translateZ(-372.5px) rotateY(15deg);
opacity: .5;
}
100% {
-webkit-transform: translateZ(-500px) rotateY(0deg);
transform: translateZ(-500px) rotateY(0deg);
opacity: 0;
}
}
@keyframes MenuAnimOut2 {
0% { }
100% {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
opacity: 0;
}
}
@keyframes MenuAnimOut3 {
0% { }
100% {
-webkit-transform: translateZ(300px);
transform: translateZ(300px);
opacity: 0;
}
}
@keyframes MenuAnimOut4 {
0% { }
100% {
-webkit-transform: translateZ(-300px);
transform: translateZ(-300px);
opacity: 0;
}
}
@keyframes MenuAnimOut5 {
0% { }
100% {
-webkit-transform: translateY(40%);
transform: translateY(40%);
opacity: 0;
}
}
.dl-menu.dl-animate-in-1 {
-webkit-animation: MenuAnimIn1 0.3s;
animation: MenuAnimIn1 0.3s;
}
.dl-menu.dl-animate-in-2 {
-webkit-animation: MenuAnimIn2 0.3s ease-in-out;
animation: MenuAnimIn2 0.3s ease-in-out;
}
.dl-menu.dl-animate-in-3 {
-webkit-animation: MenuAnimIn3 0.4s ease;
animation: MenuAnimIn3 0.4s ease;
}
.dl-menu.dl-animate-in-4 {
-webkit-animation: MenuAnimIn4 0.4s ease;
animation: MenuAnimIn4 0.4s ease;
}
.dl-menu.dl-animate-in-5 {
-webkit-animation: MenuAnimIn5 0.4s ease;
animation: MenuAnimIn5 0.4s ease;
}
@-webkit-keyframes MenuAnimIn1 {
0% {
-webkit-transform: translateZ(-500px) rotateY(0deg);
opacity: 0;
}
20% {
-webkit-transform: translateZ(-250px) rotateY(30deg);
opacity: 0.5;
}
100% {
-webkit-transform: translateZ(0px) rotateY(0deg);
opacity: 1;
}
}
@-webkit-keyframes MenuAnimIn2 {
0% {
-webkit-transform: translateX(-100%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
opacity: 1;
}
}
@-webkit-keyframes MenuAnimIn3 {
0% {
-webkit-transform: translateZ(300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
}
@-webkit-keyframes MenuAnimIn4 {
0% {
-webkit-transform: translateZ(-300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
}
@-webkit-keyframes MenuAnimIn5 {
0% {
-webkit-transform: translateY(40%);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
opacity: 1;
}
}
@keyframes MenuAnimIn1 {
0% {
-webkit-transform: translateZ(-500px) rotateY(0deg);
transform: translateZ(-500px) rotateY(0deg);
opacity: 0;
}
20% {
-webkit-transform: translateZ(-250px) rotateY(30deg);
transform: translateZ(-250px) rotateY(30deg);
opacity: 0.5;
}
100% {
-webkit-transform: translateZ(0px) rotateY(0deg);
transform: translateZ(0px) rotateY(0deg);
opacity: 1;
}
}
@keyframes MenuAnimIn2 {
0% {
-webkit-transform: translateX(-100%);
transform: translateX(-100%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
transform: translateX(0px);
opacity: 1;
}
}
@keyframes MenuAnimIn3 {
0% {
-webkit-transform: translateZ(300px);
transform: translateZ(300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
}
@keyframes MenuAnimIn4 {
0% {
-webkit-transform: translateZ(-300px);
transform: translateZ(-300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
}
@keyframes MenuAnimIn5 {
0% {
-webkit-transform: translateY(40%);
transform: translateY(40%);
opacity: 0;
}
100% {
-webkit-transform: translateY(0);
transform: translateY(0);
opacity: 1;
}
}
.dl-menuwrapper > .dl-submenu.dl-animate-in-1 {
-webkit-animation: SubMenuAnimIn1 0.4s ease;
animation: SubMenuAnimIn1 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-in-2 {
-webkit-animation: SubMenuAnimIn2 0.3s ease-in-out;
animation: SubMenuAnimIn2 0.3s ease-in-out;
}
.dl-menuwrapper > .dl-submenu.dl-animate-in-3 {
-webkit-animation: SubMenuAnimIn3 0.4s ease;
animation: SubMenuAnimIn3 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-in-4 {
-webkit-animation: SubMenuAnimIn4 0.4s ease;
animation: SubMenuAnimIn4 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-in-5 {
-webkit-animation: SubMenuAnimIn5 0.4s ease;
animation: SubMenuAnimIn5 0.4s ease;
}
@-webkit-keyframes SubMenuAnimIn1 {
0% {
-webkit-transform: translateX(50%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
opacity: 1;
}
}
@-webkit-keyframes SubMenuAnimIn2 {
0% {
-webkit-transform: translateX(100%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
opacity: 1;
}
}
@-webkit-keyframes SubMenuAnimIn3 {
0% {
-webkit-transform: translateZ(-300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
}
@-webkit-keyframes SubMenuAnimIn4 {
0% {
-webkit-transform: translateZ(300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
}
@-webkit-keyframes SubMenuAnimIn5 {
0% {
-webkit-transform: translateZ(-200px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0);
opacity: 1;
}
}
@keyframes SubMenuAnimIn1 {
0% {
-webkit-transform: translateX(50%);
transform: translateX(50%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
transform: translateX(0px);
opacity: 1;
}
}
@keyframes SubMenuAnimIn2 {
0% {
-webkit-transform: translateX(100%);
transform: translateX(100%);
opacity: 0;
}
100% {
-webkit-transform: translateX(0px);
transform: translateX(0px);
opacity: 1;
}
}
@keyframes SubMenuAnimIn3 {
0% {
-webkit-transform: translateZ(-300px);
transform: translateZ(-300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
}
@keyframes SubMenuAnimIn4 {
0% {
-webkit-transform: translateZ(300px);
transform: translateZ(300px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
}
@keyframes SubMenuAnimIn5 {
0% {
-webkit-transform: translateZ(-200px);
transform: translateZ(-200px);
opacity: 0;
}
100% {
-webkit-transform: translateZ(0);
transform: translateZ(0);
opacity: 1;
}
}
.dl-menuwrapper > .dl-submenu.dl-animate-out-1 {
-webkit-animation: SubMenuAnimOut1 0.4s ease;
animation: SubMenuAnimOut1 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-out-2 {
-webkit-animation: SubMenuAnimOut2 0.3s ease-in-out;
animation: SubMenuAnimOut2 0.3s ease-in-out;
}
.dl-menuwrapper > .dl-submenu.dl-animate-out-3 {
-webkit-animation: SubMenuAnimOut3 0.4s ease;
animation: SubMenuAnimOut3 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-out-4 {
-webkit-animation: SubMenuAnimOut4 0.4s ease;
animation: SubMenuAnimOut4 0.4s ease;
}
.dl-menuwrapper > .dl-submenu.dl-animate-out-5 {
-webkit-animation: SubMenuAnimOut5 0.4s ease;
animation: SubMenuAnimOut5 0.4s ease;
}
@-webkit-keyframes SubMenuAnimOut1 {
0% {
-webkit-transform: translateX(0%);
opacity: 1;
}
100% {
-webkit-transform: translateX(50%);
opacity: 0;
}
}
@-webkit-keyframes SubMenuAnimOut2 {
0% {
-webkit-transform: translateX(0%);
opacity: 1;
}
100% {
-webkit-transform: translateX(100%);
opacity: 0;
}
}
@-webkit-keyframes SubMenuAnimOut3 {
0% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
100% {
-webkit-transform: translateZ(-300px);
opacity: 0;
}
}
@-webkit-keyframes SubMenuAnimOut4 {
0% {
-webkit-transform: translateZ(0px);
opacity: 1;
}
100% {
-webkit-transform: translateZ(300px);
opacity: 0;
}
}
@-webkit-keyframes SubMenuAnimOut5 {
0% {
-webkit-transform: translateZ(0);
opacity: 1;
}
100% {
-webkit-transform: translateZ(-200px);
opacity: 0;
}
}
@keyframes SubMenuAnimOut1 {
0% {
-webkit-transform: translateX(0%);
transform: translateX(0%);
opacity: 1;
}
100% {
-webkit-transform: translateX(50%);
transform: translateX(50%);
opacity: 0;
}
}
@keyframes SubMenuAnimOut2 {
0% {
-webkit-transform: translateX(0%);
transform: translateX(0%);
opacity: 1;
}
100% {
-webkit-transform: translateX(100%);
transform: translateX(100%);
opacity: 0;
}
}
@keyframes SubMenuAnimOut3 {
0% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
100% {
-webkit-transform: translateZ(-300px);
transform: translateZ(-300px);
opacity: 0;
}
}
@keyframes SubMenuAnimOut4 {
0% {
-webkit-transform: translateZ(0px);
transform: translateZ(0px);
opacity: 1;
}
100% {
-webkit-transform: translateZ(300px);
transform: translateZ(300px);
opacity: 0;
}
}
@keyframes SubMenuAnimOut5 {
0% {
-webkit-transform: translateZ(0);
transform: translateZ(0);
opacity: 1;
}
100% {
-webkit-transform: translateZ(-200px);
transform: translateZ(-200px);
opacity: 0;
}
}
/* No JS Fallback */
.no-js .dl-menuwrapper .dl-menu {
position: relative;
opacity: 1;
-webkit-transform: none;
transform: none;
}
.no-js .dl-menuwrapper li .dl-submenu {
display: block;
}
.no-js .dl-menuwrapper li.dl-back {
display: none;
}
.no-js .dl-menuwrapper li > a:not(:only-child) {
background: rgba(0,0,0,0.1);
}
.no-js .dl-menuwrapper li > a:not(:only-child):after {
content: '';
}
/* Main Nav */
nav#main-nav {
display: block;
position: absolute;
top: 20px;
right: 205px;
}
@media screen and (max-width:1050px) {
nav#main-nav {
display: none;
}
}
nav#main-nav ul {
list-style: none;
}
nav#main-nav ul li {
float: left;
margin: 0 0 0 25px;
}
nav#main-nav ul li a {
color: white;
font-weight: bold;
text-transform: uppercase;
font-size: 13px;
}
body.elm-user-anonymous .show-loggedin {
display: none;
}
body.elm-user-pro-member .show-public {
display: none;
}
nav#elm-header-user-nav {
z-index:1000;
}/*]]>*/</style>
<link media="screen" type="text/css" rel="stylesheet" href="Developer%20Guide%20-%20Developer%20Network_files/viewer.css" id="mt-screen-css">
<link media="print" type="text/css" rel="stylesheet" href="Developer%20Guide%20-%20Developer%20Network_files/print.css" id="mt-print-css">
<script type="text/javascript" async="" src="Developer%20Guide%20-%20Developer%20Network_files/js" nonce=""></script><script type="text/javascript" async="" src="Developer%20Guide%20-%20Developer%20Network_files/js_002" nonce=""></script><script async="" src="Developer%20Guide%20-%20Developer%20Network_files/analytics.js"></script><script type="application/json" nonce="" id="mt-localizations-draft">
{"Draft.JS.alert.cancel.button":"OK","Draft.JS.alert.cancel.message":"You can not cancel a draft when the live page is unpublished.","Draft.JS.alert.cancel.title":"This draft cannot be canceled","Draft.JS.alert.publish.button":"OK","Draft.JS.alert.publish.message":"You can not publish a draft of a page with an unpublished parent","Draft.JS.alert.publish.title":"This draft cannot be published","Draft.JS.alert.unpublish.button":"OK","Draft.JS.alert.unpublish.message":"You can not unpublish a page when published subpages are present.","Draft.JS.alert.unpublish.title":"This page cannot be unpublished","Draft.JS.success.cancel":"The draft was successfully deleted.","Draft.JS.success.schedule.publish":"Publication schedule successfully created.","Draft.JS.success.publish":"The draft was successfully published.","Draft.JS.success.unpublish":"The page was successfully unpublished.","Draft.JS.success.unpublish.inherits-schedule\n Draft.JS.success.unpublish.scheduled-to-publish":"[MISSING: draft.js.success.unpublish.inherits-schedule\n draft.js.success.unpublish.scheduled-to-publish]","Draft.JS.success.update.schedule.publish":"Publication schedule successfully updated.","Draft.JS.success.update.schedule.unpublish":"[MISSING: draft.js.success.update.schedule.unpublish]","Draft.JS.success.delete.schedule\n Draft.JS.success.delete.schedule.with.subpages\n Draft.error.cancel":"[MISSING: draft.js.success.delete.schedule\n draft.js.success.delete.schedule.with.subpages\n draft.error.cancel]","Draft.error.publish":"There was an error publishing the draft.","Draft.error.unpublish":"There was an error unpublishing the page.","Draft.message.at":"at","Dialog.ConfirmSave.StrictIdf.title":"Oops!","Dialog.ConfirmSave.StrictIdf.error.missing-template-reference":"This article type requires a template reference widget. Not having one may negatively impact your site and SEO. Please contact NiCE Knowledge Management support.","Dialog.ConfirmSave.StrictIdf.label.continue":"Proceed anyway","Dialog.ConfirmSave.StrictIdf.label.cancel":"Cancel","Dialog.ConfirmSave.StrictIdf.label.missing-template-reference-help-link":"Learn more about required references","Dialog.ConfirmSave.StrictIdf.error.invalid-idf":"This type of article should not exist at the requested location in the site hierarchy. Proceeding with the requested move may negatively impact site navigation and SEO.","Dialog.ConfirmSave.StrictIdf.label.invalid-idf-help-link":"Learn more about IDF structure","Dialog.EditDraft.page-title":"Create draft","Dialog.Scheduler.Common.label.am":"{0} AM","Dialog.Scheduler.Common.label.pm":"{0} PM","Dialog.Scheduler.Publish.alert-create-draft":"Create","Dialog.Scheduler.Publish.alert-existing-publication-scheduled":"This location has an existing publication schedule applied. The new page will inherit this new schedule.","Dialog.Scheduler.Publish.alert-modify-message":"This draft is scheduled to be published {0} at {1}. A schedule cannot be modified or deleted less than 15 minutes from its start time.","Dialog.Scheduler.Publish.alert-modify-title":"This schedule cannot be modified","Dialog.Scheduler.Publish.button-close":"Close","Dialog.Scheduler.Publish.button-save":"Save publish schedule","Dialog.Scheduler.Publish.button-go-to-parent":"Go to parent","Dialog.Scheduler.Publish.do-not-have-permission-message":"This page will be published {0} with another page scheduled by {1}. You do not have permission to view this page. Please see {1} to resolve scheduling conflicts.","Dialog.Scheduler.Publish.go-to-parent-message":"This draft will be published {0}, scheduled by {1}. A schedule can only be modified where it was created.","Dialog.Scheduler.Publish.label.f1-link":"Learn about scheduled publishing","Dialog.Scheduler.Publish.page-title":"Publish","Dialog.Scheduler.Unpublish.button-save":"Save unpublish schedule","Dialog.Scheduler.Unpublish.alert-modify-message":"This page is scheduled to be unpublished {0} at {1}. A schedule cannot be modified or deleted less than 15 minutes from its start time.","Dialog.Scheduler.Unpublish.do-not-have-permission-message":"This page will be unpublished {0} with another page scheduled by {1}. You do not have permission to view this page. Please see {1} to resolve scheduling conflicts.","Dialog.Scheduler.Unpublish.go-to-parent-message":"This page will be unpublished {0}, scheduled by {1}. A schedule can only be modified where it was created.","Dialog.Scheduler.Unpublish.page-title":"Unpublish","Page.Dashboard.page-title":"Dashboard"} </script> <script type="application/json" nonce="" id="mt-localizations-editor">
{"Article.Attach.file.upload.toobig":"The file \"{1}\" is too large. The maximum allowed file size is {0}.","Article.Attach.file.upload.notAllowed":"The selected file can not be uploaded because you do not have permission to upload files of that type.","Article.Attach.file.upload.fileExtension":"You picked a file with an unsupported extension. Please try again with a valid file.","Article.Common.page-is-restricted-login":"You do not have permission to view this page - please try signing in.","Article.Common.page-save-conflict":"You may have overwritten a concurrent editor's changes. Use this page's <a title=\"Revision History\" target=\"_blank\" href=\"{0}\" >Revision History<\/a> to review.","Article.Error.page-couldnt-be-loaded":"The requested page's contents could not be loaded.","Article.Error.page-save-conflict":"A page already exists at {0}. Navigate to the existing page and edit the page if you wish to modify its contents.","Article.Error.page-save-forbidden":"Your session has expired or you do not have permission to edit this page.","Article.Error.page-title-required":"A page title is required.","Article.edit.summary":"Edit summary","Article.edit.summary-reason":"Why are you making this edit?","Article.edit.enter-reason":"Enter reason (viewable in Site History Report)","Component.YoutubeSearch.error.key-invalid":"Your YouTube API Key was improperly configured. Please review the article at the","Component.YoutubeSearch.error.key-missing":"Your NiCE Knowledge Management deployment needs to update your YouTube API Key. Details on how to update can be found at the","Component.YoutubeSearch.error.search-failed":"Search failed","Component.YoutubeSearch.info.not-found":"No videos found","Component.YoutubeSearch.label.video-url":"Video URL","Component.YoutubeSearch.placeholder.query":"Video URL or YouTube search query","Dialog.ConfirmCancel.button.continue-editing":"Continue editing","Dialog.ConfirmCancel.button.discard-changes":"Discard changes","Dialog.ConfirmCancel.message.changes-not-saved":"Your changes have not been saved to MindTouch.","Dialog.ConfirmCancel.title":"Discard changes?","Dialog.ConfirmDeleteRedirects.label.delete-redirects-help-link":"Learn more about deleting redirects","Dialog.ConfirmSave.error.redirect":"A redirect exists at this location and will be deleted if you continue. This may negatively impact your site and SEO. Please contact NiCE Knowledge Management support.","Dialog.ConfirmSave.label.cancel":"Cancel","Dialog.ConfirmSave.label.continue":"Continue","Dialog.ConfirmSave.title":"Delete redirect?","Dialog.ConfirmSave.StrictIdf.error.invalid-idf":"This type of article should not exist at the requested location in the site hierarchy. Proceeding with the requested move may negatively impact site navigation and SEO.","Dialog.ConfirmSave.StrictIdf.error.missing-template-reference-insert":"You've removed the template reference, which is required for this page. Click Insert to reinsert the template reference.","Dialog.ConfirmSave.StrictIdf.label.cancel":"Cancel","Dialog.ConfirmSave.StrictIdf.label.continue":"Proceed anyway","Dialog.ConfirmSave.StrictIdf.label.insert":"Insert","Dialog.ConfirmSave.StrictIdf.label.missing-template-reference-help-link":"Learn more about required references","Dialog.ConfirmSave.StrictIdf.label.invalid-idf-help-link":"Learn more about IDF structure","Dialog.ConfirmSave.StrictIdf.title":"Oops!","Dialog.JS.wikibits-edit-section":"Edit section","Dialog.SaveRequired.button.cancel":"Cancel","Dialog.SaveRequired.button.save":"Save and continue","Dialog.SaveRequired.label.change-title-start":"This page needs a different title than","Dialog.SaveRequired.label.change-title-end":"Please make the correction and try again.","Dialog.SaveRequired.label.new-page-alert":"This operation can not be performed on a page that has not yet been created. In order to do that, we need to quickly save what you have.","Dialog.SaveRequired.title":"Save required","Draft.error.save-unpublished":"You cannot save an unpublished draft at {0}. A published page already exists at that location.","GUI.Editor.alert-changes-made-without-saving":"You have made changes to the content without saving your changes. Are you sure you want to exit this page?","GUI.Editor.error.copy-hint":"To avoid losing your work, copy the page contents to a new file and retry saving again.","GUI.Editor.error.server-error":"A server error has occurred.","GUI.Editor.error.unable-to-save":"We are unable to save this page","Redist.CKE.mt-save.save-to-file-link":"Save the page content to a file","Redist.CKE.mt-autosave.contents-autosaved":"The page contents were autosaved to the browser's local storage {0}","System.API.Error.invalid-redirect":"Cannot create a redirect on a page with sub-pages.","System.API.Error.invalid-redirect-target":"The redirect does not point at a valid page."} </script> <script type="application/json" nonce="" id="mt-localizations-file-uploader">
{"Dialog.Attach.allowed-types":"Allowed file types:","Dialog.Attach.button.upload":"Upload","Dialog.Attach.choose-files-dad":"Choose files to upload or drag and drop files into this window.","Dialog.Attach.max-size":"Maximum upload file size: {0}"} </script> <script type="application/json" nonce="" id="mt-localizations-grid-widget">
{"Article.Common.page-is-restricted-login":"You do not have permission to view this page - please try signing in.","MindTouch.Help.Page.search-unavailable":"Sorry, search is currently unavailable.","MindTouch.Reports.data.empty-grid-text":"No Data Available.","Page.StructuredTags.error-update":"An unknown error occurred."} </script> <script type="application/json" nonce="" id="mt-localizations-tree-widget">
{"Skin.Common.home":"Home","Dialog.Common.error.path-not-found":"The requested page or section could not be loaded. Please update the link.","Dialog.JS.loading":"Loading...","Dialog.JS.loading.copy":"Copying page(s)...","Dialog.JS.loading.insertImage":"Inserting image...","Dialog.JS.loading.move":"Moving page(s)...","Dialog.JS.loading.moveFile":"Moving file...","Dialog.JS.loading.search":"Searching...","MindTouch.Help.Page.in":"in","MindTouch.Help.Page.no-search-results":"Sorry, we can't find what you are looking for.","MindTouch.Help.Page.no-search-try":"Try searching for something else, selecting a category, or try creating a ticket.","MindTouch.Help.Page.retrysearch":"Click here to search the whole site.","MindTouch.Help.Page.search-error-try":"Please try again later.","MindTouch.Help.Page.search-unavailable":"Sorry, search is currently unavailable."} </script> <script type="application/json" nonce="" id="mt-localizations-dialog">
{"Dialog.Common.button.cancel":"Cancel","Dialog.Common.button.ok":"OK","Dialog.Common.label.home":"Home"} </script>
<script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/globals.jqueryv2.2.4.js"></script><script type="application/json" id="mt-global-settings">{}</script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/deki.legacy.js"></script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/community.js"></script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/skin_elm.js"></script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/pageBootstrap.js"></script>
<link type="text/css" rel="stylesheet" href="Developer%20Guide%20-%20Developer%20Network_files/shCore.min.css"><link type="text/css" rel="stylesheet" href="Developer%20Guide%20-%20Developer%20Network_files/shThemeCedar.min.css"><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/shCore.min.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/shBrushCss.min.js"></script><script type="text/javascript">/*<![CDATA[*/SyntaxHighlighter.all();/*]]>*/</script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/shBrushJScript.min.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/shBrushCSharp.min.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/modernizr.js"></script><link href="Developer%20Guide%20-%20Developer%20Network_files/font-awesome.min.css" rel="stylesheet"><style type="text/css">.tk-proxima-nova{font-family:"proxima-nova",sans-serif;}</style><style type="text/css">@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/7d485b/00000000000000003b9ad1b1/27/l?subset_id=2&fvd=n7&v=3) format("woff2"),url(https://use.typekit.net/af/7d485b/00000000000000003b9ad1b1/27/d?subset_id=2&fvd=n7&v=3) format("woff"),url(https://use.typekit.net/af/7d485b/00000000000000003b9ad1b1/27/a?subset_id=2&fvd=n7&v=3) format("opentype");font-weight:700;font-style:normal;font-stretch:normal;font-display:auto;}@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/347aea/00000000000000003b9ad1b2/27/l?subset_id=2&fvd=i7&v=3) format("woff2"),url(https://use.typekit.net/af/347aea/00000000000000003b9ad1b2/27/d?subset_id=2&fvd=i7&v=3) format("woff"),url(https://use.typekit.net/af/347aea/00000000000000003b9ad1b2/27/a?subset_id=2&fvd=i7&v=3) format("opentype");font-weight:700;font-style:italic;font-stretch:normal;font-display:auto;}@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/04b81b/00000000000000003b9ad1bb/27/l?subset_id=2&fvd=n6&v=3) format("woff2"),url(https://use.typekit.net/af/04b81b/00000000000000003b9ad1bb/27/d?subset_id=2&fvd=n6&v=3) format("woff"),url(https://use.typekit.net/af/04b81b/00000000000000003b9ad1bb/27/a?subset_id=2&fvd=n6&v=3) format("opentype");font-weight:600;font-style:normal;font-stretch:normal;font-display:auto;}@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/c9cde8/00000000000000003b9ad1b9/27/l?subset_id=2&fvd=n4&v=3) format("woff2"),url(https://use.typekit.net/af/c9cde8/00000000000000003b9ad1b9/27/d?subset_id=2&fvd=n4&v=3) format("woff"),url(https://use.typekit.net/af/c9cde8/00000000000000003b9ad1b9/27/a?subset_id=2&fvd=n4&v=3) format("opentype");font-weight:400;font-style:normal;font-stretch:normal;font-display:auto;}@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/4ba64f/00000000000000003b9ad1ba/27/l?subset_id=2&fvd=i4&v=3) format("woff2"),url(https://use.typekit.net/af/4ba64f/00000000000000003b9ad1ba/27/d?subset_id=2&fvd=i4&v=3) format("woff"),url(https://use.typekit.net/af/4ba64f/00000000000000003b9ad1ba/27/a?subset_id=2&fvd=i4&v=3) format("opentype");font-weight:400;font-style:italic;font-stretch:normal;font-display:auto;}@font-face{font-family:proxima-nova;src:url(https://use.typekit.net/af/3333ef/00000000000000003b9ad1b5/27/l?subset_id=2&fvd=n3&v=3) format("woff2"),url(https://use.typekit.net/af/3333ef/00000000000000003b9ad1b5/27/d?subset_id=2&fvd=n3&v=3) format("woff"),url(https://use.typekit.net/af/3333ef/00000000000000003b9ad1b5/27/a?subset_id=2&fvd=n3&v=3) format("opentype");font-weight:300;font-style:normal;font-stretch:normal;font-display:auto;}</style><script src="Developer%20Guide%20-%20Developer%20Network_files/puk4twq.js"></script><script>/*<![CDATA[*/try{Typekit.load();}catch(e){}/*]]>*/</script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/jquery.cookie.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/devnet.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/responsive-tables.js"></script><script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/jquery.dlmenu.js"></script>
<script type="text/javascript" nonce="">(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)})(window,document,'script','//www.google-analytics.com/analytics.js','ga');ga('create','UA-3249818-20','developer.connectwise.com',{allowLinker:true});ga('send','pageview');ga('create','UA-65721316-4','auto',{name:'mtTracker',allowLinker:true});ga('mtTracker.require','linker');ga('mtTracker.set', 'anonymizeIp', true);ga('mtTracker.send','pageview');document.addEventListener('mindtouch-web-widget:f1:loaded',function(e){var t=e.data||{},d=t.widget;d&&''!==t.embedId&&document.addEventListener('mindtouch-web-widget:f1:clicked',function(e){var t=(e.data||{}).href;if(t){var n=document.createElement('a');n.setAttribute('href',t),'expert-help.nice.com'===n.hostname&&(e.preventDefault(),ga('linker:decorate',n),d.open(n.href))}})});</script>
<style id="mt-fixed-header-styles"></style></head>
<body class="elm-user-community columbia-page-main columbia-article-topic-guide columbia-browser-firefox columbia-platform-windows columbia-breadcrumb-home-products-connectwisepsa-developerguide columbia-live no-touch columbia-lang-en-us columbia-skin-elm columbia-group-developer columbia-group-connectwise-developer" style="margin-top: 40px;">
<a class="elm-skip-link" href="#elm-main-content" title="Press enter to skip to the main content">Skip to main content</a><main class="elm-skin-container" data-ga-category="Community | page">
<header class="elm-header">
<div class="elm-header-custom"><div class="header-blue"><div class="header-wrapper"><a id="cw-logo" href="https://developer.connectwise.com/" rel="internal"><img class="internal" alt="CWLogo-R-Reg_Horz-White.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CWLogo-R-Reg_Horz-White.png"></a><div id="dl-menu" class="dl-menuwrapper"><button class="dl-trigger">Open Menu</button><ul class="dl-menu"><li><a href="https://developer.connectwise.com/Best_Practices/Getting_Started" rel="internal">Get Started</a></li><li><a href="https://developer.connectwise.com/Products" rel="internal">Documentation</a></li><li class="show-loggedin"><a href="https://developer.connectwise.com/Special:ClientId" rel="internal">ClientId</a></li><li class="show-public"><a href="https://virtualcommunity.connectwise.com/community-home?CommunityKey=b91ec22c-a6ca-4ae3-bedb-018a5199538b" target="_blank" rel="external noopener nofollow" class="link-https">Developer Community</a></li><li class="show-loggedin"><a href="https://developer.connectwise.com/Special:faq" rel="internal">FAQ</a></li><li><a href="https://marketplace.connectwise.com/" target="_blank" rel="external noopener nofollow" class="link-https">Marketplace</a></li><li class="show-public"><a href="https://developer.connectwise.com/Special:Userlogin" rel="internal">Login</a></li><li class="show-public"><a href="https://register.developer.connectwise.com/" target="_blank" rel="external noopener nofollow" class="link-https">Register</a></li><li class="show-loggedin"><a href="https://developer.connectwise.com/Special:Preferences" rel="internal">Preferences</a></li><li class="show-loggedin"><a href="https://developer.connectwise.com/Special:Userlogout" rel="internal">Logout</a></li></ul></div><nav id="main-nav"><ul><li><a href="https://developer.connectwise.com/Best_Practices/Getting_Started" rel="internal">Get Started</a></li><li><a href="https://developer.connectwise.com/Products" rel="internal">Documentation</a></li><li class="show-loggedin"><a href="https://developer.connectwise.com/ClientID" rel="internal">ClientId</a></li><li><a href="https://virtualcommunity.connectwise.com/community-home?CommunityKey=b91ec22c-a6ca-4ae3-bedb-018a5199538b" target="_blank" rel="external noopener nofollow" class="link-https">Developer Community</a></li><li><a href="https://marketplace.connectwise.com/" target="_blank" rel="external noopener nofollow" class="link-https">Marketplace</a></li></ul></nav><div class="action-items anonymous-user"><button id="toggleSearch"><i class="fa fa-search"></i></button><a href="https://developer.connectwise.com/Special:Userlogin" rel="internal">Login</a><a href="https://register.developer.connectwise.com/" target="_blank" rel="external noopener nofollow" class="link-https">Register</a></div><div class="action-items confirmed-user"><button id="toggleSearch"><i class="fa fa-search"></i></button><a href="https://developer.connectwise.com/Special:Preferences" rel="internal">Preferences</a><a href="https://developer.connectwise.com/Special:Userlogout" rel="internal">Logout</a></div></div></div><div id="search-cw" style="display:none;"><form action="/Special:Search"><input name="qid" id="mt-qid-skin" type="hidden" value=""><input name="fpid" id="mt-search-filter-id" type="hidden" value=""><input name="fpth" id="mt-search-filter-path" type="hidden"><input name="path" id="mt-search-path" type="hidden" value=""><input class="mt-text mt-search search-field" name="search" id="mt-site-search-input" placeholder="Search..." tabindex="1" type="search"><button class="mt-button ui-button-icon mt-icon-site-search-button search-button" tabindex="2" type="submit">Search</button></form></div><div class="style-wrap" style="display: none;"><div id="mt-useremail">user@example.invalid</div></div>
<script type="text/javascript">/*<![CDATA[*/
$(document).ready(function(){
$("button#toggleSearch").click(function(){
$("#search-cw").toggle();
});
$( '#dl-menu' ).dlmenu();
});
$(document).ready(function(){
$('li:contains("API Version 1.5")').remove();
});/*]]>*/</script>
<div class="style-wrap"><input id="mt-manage" type="hidden" value="1"></div>
</div>
<div class="elm-nav mt-translate-module" hidden="true">
<div class="elm-nav-container mt-translate-container"></div>
</div>
<div class="elm-header-logo-container">
<a href="https://developer.connectwise.com/" title="Developer Network" aria-label="Link to home"><img src="Developer%20Guide%20-%20Developer%20Network_files/1680273416-logo.png" alt="Developer Network"></a>
</div>
<nav class="elm-header-user-nav elm-nav" role="navigation">
<div class="elm-nav-container">
<ol>
<li class="elm-global-search" data-ga-action="Header search"><a class="mt-icon-site-search mt-toggle-form" href="#" title="Search site">Search site</a>
<div class="mt-quick-search-container mt-toggle-form-container">
<form action="/Special:Search">
<input name="qid" id="mt-qid-skin" type="hidden" value="">
<input name="fpid" id="mt-search-filter-id" type="hidden" value="230">
<input name="fpth" id="mt-search-filter-path" type="hidden">
<input name="path" id="mt-search-path" type="hidden" value="">
<label class="mt-label" for="mt-site-search-input">
Search
</label>
<input class="mt-text mt-search search-field" name="q" id="mt-site-search-input" placeholder="How can we help you?" type="search">
<button class="mt-button ui-button-icon mt-icon-site-search-button search-button" type="submit">
Search
</button>
</form>
</div>
<div class="elm-search-back"><a class="mt-icon-browser-back" data-ga-label="Browse back" href="#" id="mt-browser-back" title="Go back to previous article">Go back to previous article</a></div>
</li>
<li class="elm-user-menu"><ol class="mt-user-menu">
<li class="mt-user-menu-user">
<a class="mt-icon-user-menu mt-dropdown-link" href="#" title="">redacted-hub-copy</a>
<ol class="mt-user-menu-container mt-dropdown" style="">
<li class="mt-user-menu-preferences">
<a class="mt-icon-user-preferences" href="https://developer.connectwise.com/Special:Preferences" title="Click to change your user preferences">My preferences</a>
</li>
<li class="mt-user-menu-signout">
<a class="mt-icon-user-sign-out" href="https://developer.connectwise.com/Special:UserLogout?returntotitle=Products%2FConnectWise_PSA%2FDeveloper_Guide" title="Click to sign out of this site">Sign out</a>
</li>
</ol>
</li>
</ol></li>
</ol>
</div>
</nav>
<nav class="elm-header-global-nav elm-nav elm-fixed-header" data-ga-action="Elm Navigation" style="top: 0px;">
<div class="elm-nav-container">
<button class="elm-hierarchy-trigger mt-hierarchy-trigger ui-button-icon mt-icon-hierarchy-trigger-closed" title="Expand/collapse global hierarchy" data-ga-label="Hierarchy Toggle - Tree View">
Expand/collapse global hierarchy
</button>
<ol class="mt-breadcrumbs" data-ga-action="Breadcrumbs">
<li>
<a href="https://developer.connectwise.com/" data-ga-label="Breadcrumb category">
<span class="mt-icon-article-category mt-icon-article-home"></span>
Home
</a>
</li>
<li>
<a href="https://developer.connectwise.com/Products" data-ga-label="Breadcrumb category">
<span class="mt-icon-article-category"></span>
Products
</a>
</li>
<li>
<a href="https://developer.connectwise.com/Products/ConnectWise_PSA" data-ga-label="Breadcrumb category">
<span class="mt-icon-article-category"></span>
ConnectWise PSA
</a>
</li>
<li class="mt-breadcrumbs-current-page">
<span class="mt-icon-article-guide"></span>
Developer Guide
</li>
</ol>
<button class="mt-icon-hierarchy-mobile-view-trigger ui-button-icon mt-icon-hierarchy-mobile-trigger-closed" title="Expand/collapse global location" data-ga-label="Hierarchy Toggle - Breadcrumb Expand/Collapse">
Expand/collapse global location
</button>
</div>
</nav>
<nav class="elm-nav elm-header-hierarchy">
<div class="elm-nav-container">
<div class="elm-hierarchy mt-hierarchy"></div>
</div>
</nav> <div class="elm-nav mt-review-banner" hidden="true"></div>
</header>
<article class="elm-content-container" id="elm-main-content" tabindex="-1">
<header>
<div id="flash-messages"><div class="dekiFlash"></div></div>
<h1 id="title" data-title-editor-available="false">
Developer Guide
</h1>
<ol class="elm-meta-data elm-meta-top" data-ga-action="Page actions">
<li class="elm-last-modified"><dl class="mt-last-updated-container">
<dt class="mt-last-updated-label">Last updated</dt>
<dd>
<span class="mt-last-updated" data-timestamp="2025-04-08T15:54:36Z">Apr 8, 2025</span>
</dd>
</dl>
</li>
<li class="elm-pdf-export"><a data-ga-label="PDF" href="https://developer.connectwise.com/@api/deki/pages/901/pdf/Developer%2bGuide.pdf" rel="nofollow" target="_blank" title="Export page as a PDF">
<span class="mt-icon-article-pdf"></span>Save as PDF
</a></li>
<li class="elm-social-share"></li>
</ol>
</header>
<header class="mt-content-header"></header>
<aside class="mt-content-side"></aside>
<aside id="mt-toc-container" data-title="Table of contents" data-collapsed="false" class="mt-toggle-container"><button class="mt-toggle mt-summary-toggle ui-button-icon mt-toggle-collapse" type="button">Table of contents</button>
<nav class="mt-toc-content mt-collapsible-section">
<ol><li><a href="#ClientIds" rel="internal">ClientIds</a><ol><li><a href="#What_is_a_clientId.3F" rel="internal">What is a clientId?</a></li><li><a href="#Asked_for_a_clientId.3F" rel="internal">Asked for a clientId?&nbsp;</a></li><li><a href="#Follow_this_link_to_obtain_a_clientId" rel="internal">Follow this link to obtain a clientId</a></li></ol></li><li><a href="#Versioning" rel="internal">Versioning</a></li><li><a href="#What_is_a_breaking_change.3F" rel="internal">What is a breaking change?</a><ol><li><a href="#Examples_of_breaking_changes:" rel="internal">Examples of breaking changes:</a></li><li><a href="#NOT_a_breaking_change:" rel="internal">NOT a breaking change:</a></li></ol></li><li><a href="#Formatting_Version_Header" rel="internal">Formatting Version Header</a></li><li><a href="#Per_Endpoint" rel="internal">Per Endpoint</a></li><li><a href="#Authentication" rel="internal">Authentication</a><ol><li><a href="#Postman_Example" rel="internal">Postman Example</a></li><li><a href="#Obtaining_your_Keys" rel="internal">Obtaining your Keys</a></li></ol></li><li><a href="#Rate_Limiting" rel="internal">Rate Limiting</a></li><li><a href="#Security" rel="internal">Security</a></li><li><a href="#HTTP_Methods" rel="internal">HTTP Methods</a></li><li><a href="#HTTP_Response_Statuses" rel="internal">HTTP Response Statuses</a></li><li><a href="#Formatting_Each_Method" rel="internal">Formatting Each Method</a><ol><li><a href="#Get" rel="internal">Get</a><ol><li><a href="#URL_Max_Length" rel="internal">URL Max Length</a></li><li><a href="#Query_String_Parameters" rel="internal">Query String Parameters</a></li><li><a href="#Conditions" rel="internal">Conditions</a></li><li><a href="#Using_the_.2FSearch_endpoints" rel="internal">Using the /Search endpoints</a></li></ol></li><li><a href="#Patch" rel="internal">Patch</a></li><li><a href="#Delete" rel="internal">Delete</a></li><li><a href="#Post" rel="internal">Post</a></li><li><a href="#Put" rel="internal">Put</a></li><li><a href="#Escaping_Characters" rel="internal">Escaping&nbsp;Characters</a></li><li><a href="#Partial_Responses" rel="internal">Partial Responses</a></li><li><a href="#Custom_Fields" rel="internal">Custom Fields</a><ol><li><a href="#Field_Options_and_Parameters" rel="internal">Field Options and Parameters</a></li></ol></li><li><a href="#Pagination" rel="internal">Pagination</a><ol><li><a href="#Navigable" rel="internal">Navigable</a></li><li><a href="#Forward-Only" rel="internal">Forward-Only</a></li></ol></li></ol></li><li><a href="#Callbacks_(Webhooks)" rel="internal">Callbacks (Webhooks)</a><ol><li><a href="#Levels_and_Types" rel="internal">Levels and Types</a></li><li><a href="#Configuring_the_Callbacks" rel="internal">Configuring the Callbacks</a></li><li><a href="#Testing_Callbacks" rel="internal">Testing Callbacks</a><ol><li><a href="#Webhook.Site" rel="internal">Webhook.Site</a></li></ol></li><li><a href="#When_Callbacks_Fail_to_POST_to_Target_Host" rel="internal">When Callbacks Fail to POST to Target Host</a></li><li><a href="#Verifying_the_Callback_Source" rel="internal">Verifying the Callback Source</a></li><li><a href="#Callback_Changelog" rel="internal">Callback Changelog&nbsp;</a></li></ol></li><li><a href="#Troubleshooting" rel="internal">Troubleshooting</a><ol><li><a href="#Reading_Logs" rel="internal">Reading Logs</a></li><li><a href="#Telerik's_Fiddler" rel="internal">Telerik's Fiddler</a></li><li><a href="#Error_Handling" rel="internal">Error Handling</a><ol><li><a href="#Retry_Policy" rel="internal">Retry Policy</a></li><li><a href="#500_Server_Errors" rel="internal">500 Server Errors</a></li><li><a href="#400_Client_Errors" rel="internal">400 Client Errors</a></li></ol></li></ol></li><li><a href="#REST_SDK_Downloads" rel="internal">REST SDK Downloads</a></li><li><a href="#Document_API" rel="internal">Document API</a></li><li><a href="#Calling_Company_Info" rel="internal">Calling Company Info</a><ol><li><a href="#Response" rel="internal">Response</a></li></ol></li><li><a href="#API_Request_URL_Format" rel="internal">API Request URL Format</a></li><li><a href="#Cloud_vs_Premise" rel="internal">Cloud vs Premise</a></li><li><a href="#Cloud_URLs" rel="internal">Cloud URLs</a></li></ol>
</nav>
</aside>
<section class="mt-content-container">
<div class="mt-contentreuse-widget" data-page="AddTOC" data-section="" data-show="">
<div class="mt-include" id="s1121">
</div>
</div>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_1"><span id="ClientIds"></span><h3 class="editable">ClientIds</h3>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_2"><span id="What_is_a_clientId.3F"></span><h4 class="editable"><span class="mt-color-000000">What is a clientId?</span></h4>
<p><span class="mt-color-000000">A clientId is a unique GUID or Globally
Unique Identifier assigned to each integration. This clientId is
required for all API calls made by your integration. This will be used
to monitor integration performance and systems' health.</span></p>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_3"><span id="Asked_for_a_clientId.3F"></span><h4 class="editable"><span class="mt-color-000000">Asked for a clientId?&nbsp;</span></h4>
<p><span class="mt-color-000000">You should never share your clientId,
doing so may result in issues relating to integrations in your
environments.&nbsp; A clientId is unique to your company and is used to
say that API traffic is coming from your source.&nbsp; It should be
treated as a sort of password and identifier for your company.&nbsp; We
may disable any clientId&nbsp;that looks to have been compromised if we
suspect any abuse.&nbsp;<strong><strong>If anyone asks you to provide a clientId value, do not do so.</strong></strong>&nbsp;
The only exception to this rule would be integrations where you
yourself are creating it.&nbsp; For instance, if you use Zapier and use
the Zapier Code function and add your own API call, not in the
ConnectWise PSA package.&nbsp; 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.&nbsp; Do not provide
clientId values to integrations that are designed "out-of-the-box" and
apply to all users.&nbsp; An example would be the Automate to
ConnectWise PSA integration.&nbsp; That is an integration that is the
same for every user and the clientId would be set up by the third-party
integration.&nbsp; Automate controls the Ids around that integration
themselves.</span></p>
<blockquote>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section"><span id="Follow_this_link_to_obtain_a_clientId"></span><h4 class="editable"><a title="ClientID" href="https://developer.connectwise.com/ClientID" rel="internal"><span class="mt-color-000000">Follow this link to obtain a clientId</span></a></h4>
</div></blockquote>
</div></div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_4"><span id="Versioning"></span><h3 class="editable">Versioning</h3>
<div class="mt-contentreuse-widget" data-page="Manage/API_Versioning" data-section="" data-show="">
<div class="mt-include" id="s1118"><p><span class="mt-color-000000">Starting
with 2019.1 the API is now tied to the ConnectWise PSA release
cycle.&nbsp; Previously the API was versioned as it's own entity and
followed a format such as 3.0.1.&nbsp; To provide clarity around the API
Versioning and to make it easier for consumers, we have replaced 3.0.0
with the specific ConnectWise PSA version that the API model was
released on.</span></p>
<p><span class="mt-color-000000">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.&nbsp; 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.&nbsp; We do not release new models every
release, however you can still target a version that did not have any
changes.&nbsp; For instance, lets say in 2019.1 we have a specific
ticket model called A.&nbsp; In 2019.4 we update tickets to have model
B.&nbsp; If you pass 2019.1, 2019.2 or 2019.3, you will get model A,
which is 2019.1.</span></p>
<p><span class="mt-color-000000">By default all requests will receive
the latest version of our API endpoint. &nbsp;As breaking changes are
released, each individual API endpoint, may receive an updated version.
&nbsp;In order to prevent your integration from breaking, we encourage
you to request a specific version using an Accept header. &nbsp;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. &nbsp;We will regularly deprecate&nbsp;old
models of the API.</span></p>
<div mt-section-origin="Best_Practices/PSA_Versioning" class="mt-section" id="section_1"><span id="What_is_a_breaking_change.3F"></span><h3 id="What_is_a_breaking_change.3F-1118">What is a breaking change?</h3>
<p><span class="mt-color-000000">Breaking changes are defined as any
change to the APIs that could result in an error being returned by the
SDK.&nbsp; 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.&nbsp; If you hard code every field, you will have issues that we
don't consider breaking.</span></p>
<div mt-section-origin="Best_Practices/PSA_Versioning" class="mt-section" id="section_2"><span id="Examples_of_breaking_changes:"></span><h4 id="Examples_of_breaking_changes:-1118"><span class="mt-color-000000"><strong><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Examples of breaking changes:</span></span></strong></span></h4>
<ul>
<li>
<p><span class="mt-color-000000">Renaming a field (fixing a typo)</span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Changing a field's data type (such as from an int to a decimal, or from editable to read only)</span></span></span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Changing the response type (such as from an object to an array of objects)</span></span></span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Validation changes (fields now required that previously were not)</span></span></span></p>
</li>
</ul>
</div><div mt-section-origin="Best_Practices/PSA_Versioning" class="mt-section" id="section_3"><span id="NOT_a_breaking_change:"></span><h4 id="NOT_a_breaking_change:-1118"><span class="mt-color-000000"><strong><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">NOT a breaking change:</span></span></strong></span></h4>
<ul>
<li>
<p><span class="mt-color-000000">Adding new fields</span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Adding new endpoints</span></span></span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Making a read only field editable</span></span></span></p>
</li>
<li>
<p><span class="mt-color-000000"><span class="mt-font-Helvetica,sans-serif"><span class="mt-font-size-11.5pt">Making a field no longer required if it was previously required</span></span></span></p>
</li>
</ul>
<blockquote>
<p>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.&nbsp; Please note
that some endpoints cannot be versioned.</p>
</blockquote>
</div></div><div mt-section-origin="Best_Practices/PSA_Versioning" class="mt-section" id="section_4"><span id="Formatting_Version_Header"></span><h3 id="Formatting_Version_Header-1118">Formatting Version Header</h3>
<p><span class="mt-color-000000">We try to make it as simple as possible
to format your version header.&nbsp; We use an accept header that lists
our JSON schema as well as the version following.&nbsp; Accept headers
tell the server what type of information you are expecting to get
back.&nbsp; This makes it a perfect fit to add our version to as this
tells the server that you want xyz version back.</span></p>
<div id="highlighter_859561" class="syntaxhighlighter "><div class="bar"><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>1</code></td><td class="content"><code class="plain">Accept: application/vnd.connectwise.com+json; version=</code><code class="value">2019.1</code></td></tr></tbody></table></div></div></div>
</div><div mt-section-origin="Best_Practices/PSA_Versioning" class="mt-section" id="section_5"><span id="Per_Endpoint"></span><h3 id="Per_Endpoint-1118">Per Endpoint</h3>
<p><span class="mt-color-000000">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.&nbsp; We recommend
that you keep a singular version across your integration, but will
support it either way.&nbsp; 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.&nbsp; We may do so without
warning, or give you very little time to make changes.</span></p>
</div></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_5"><span id="Authentication"></span><h3 class="editable">Authentication</h3>
<div class="mt-contentreuse-widget" data-page="Manage/REST/Permissions_(REST)" data-section="" data-show="">
<div class="mt-include" id="s342"><p>REST based integrations have three
methods of authentication. &nbsp;The recommended method, is using an API
Member account to create API Keys specific to the integration.
&nbsp;The second method is to use impersonation. &nbsp;Impersonation
uses either an Integrator Login (Legacy) or another Member to create API
Keys programmatically for other members. &nbsp;The third method which
is only support for internal integrations, uses username and passwords
for individual members. &nbsp;Due to this method requiring a user to
enter their ConnectWise PSA username and password into another
application, we do not support vendors utilizing this method.</p>
<p>ConnectWise PSA <span class="mt-font-Segoe UI,sans-serif"><span class="mt-font-size-10.0pt">utilizes the "Basic Auth" standard with Public and Private keys and the authorization header that are unique to </span></span> ConnectWise PSA <span class="mt-font-Segoe UI,sans-serif"><span class="mt-font-size-10.0pt">members.&nbsp; This means you can use the benefits of </span></span> ConnectWise PSA <span class="mt-font-Segoe UI,sans-serif"><span class="mt-font-size-10.0pt">security roles and give granular access to the APIs.</span></span></p>
<p><span class="mt-font-size-16" style="line-height:1.4;">Your header must be </span>base64<span class="mt-font-size-16" style="line-height:1.4;"> encoded and has to include a username:password. &nbsp;The username will always begin with </span>CompanyId<span class="mt-font-size-16" style="line-height:1.4;">+ and then use either the public key, integrator username or </span>MemberId<span class="mt-font-size-16" style="line-height:1.4;">. &nbsp;The password will be the private key, integrator password or member hash.</span></p>
<pre class="mt-indent-1">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 (<span class="mt-color-ff0000">Not intended for 3rd party products unless using Hosted API</span>)
This method uses 3 cookie headers.
Cookie: companyName=YourLoginCompany
Cookie: memberHash=Generated by POST to login.aspx or via Hosted API
Cookie: memberId=YourUsername
Cookie: memberContext=web
</pre>
<p><strong>Important Note:&nbsp;</strong>SSL is required on production
PSA servers when accessing the API. Any calls received via regular HTTP
will be denied on production systems.</p>
<p>Are you connecting to the Cloud or Staging? &nbsp;If so you must
include API- in front of the ConnectWise PSA site. If you are using a
training environment that normally uses sandbox- in front of the Site,
you will not include sandbox- and should still follow these same
guidelines.&nbsp;</p>
<pre class="mt-indent-1">api-au.myconnectwise.net
api-eu.myconnectwise.net
api-na.myconnectwise.net
api-staging.connectwisedev.com
</pre>
<p>Otherwise you will run into this error:</p>
<pre class="mt-indent-1">{
"code": "Security",
"message": "SSL is required.",
"errors": null
}</pre>
<p>&nbsp;</p>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Authentication" class="mt-section" id="section_1"><span id="Postman_Example"></span><h4 id="Postman_Example-342">Postman Example</h4>
<p><img class="internal" style="width: 1030px; height: 293px;" width="1030px" height="293px" alt="clipboard_e3fce13499f91853cf4c9c60c4c88b774.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_e3fce13499f91853cf4c9c60c4c88b774.png">&nbsp;</p>
<script type="text/javascript">/*<![CDATA[*/
$(function() {
$('dl').find('dt').on('click', function() {
$(this).next().toggle('350');
});
});/*]]>*/</script>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Authentication" class="mt-section" id="section_2"><span id="Obtaining_your_Keys"></span><h4 id="Obtaining_your_Keys-342">Obtaining your Keys</h4>
<p>We only support API Member and My Account based authentication for
Integration Vendors. &nbsp;Impersonation and Cookie Authentication are
for internal only based integrations. &nbsp;In rare cases impersonation
may be the route to go.</p>
<dl>
<dt style="font-size:large">API Member Only *Recommended for 3rd parties</dt>
<dd>
<p>Using the same setup screen as creating a Member an&nbsp;API
Member allows granular control over what type of information an
integration has access to. &nbsp;A global user allows integrations to be
turned on and off easily without requiring the person who initially
setup the integration.</p>
API Members are&nbsp;the recommended route for most integrations.
<blockquote>
<p>The Members screen can by found by going to the System Module and
opening the Members page. &nbsp;After accessing the Members page, click
on the API Members tab. &nbsp;Here you can create a new user and
generate API Keys for them.</p>
<p>API Members do not require a user license.</p>
</blockquote>
<p><img alt="CW_Snag_-_0641.png" class="internal default" style="width: 1089px; height: 836px;" width="1089px" height="836px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0641.png"></p>
<p><img alt="CW_Snag_-_0642.png" class="internal default" style="width: 1089px; height: 836px;" width="1089px" height="836px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0642.png"></p>
<p>&nbsp;</p>
</dd>
</dl>
<dl>
<dt style="font-size:large">Member Impersonation</dt>
<dd>Member impersonation works by using an integrator login with
access to the Member API through the integrator login setup tables. You
can then use the integrator login credentials to make a call to the
Member API under REST in order to generate a temporary (4&nbsp;hours)
API Key for that member. &nbsp;Once you have the generated API Keys, you
will need to use the returned API Keys for that member to make
additional API Calls.
<pre>Post Request:
https://YourConnectWiseSite/v4_6_release/apis/3.0/system/members/{memberIdentifier}/tokens
Headers:
-API Member:
Authentication Basic base64(companyid+publickey:privatekey)
x-cw-usertype: member
-Integrator Login:
Authentication Basic base64(companyid+integratorlogin:integratorpassword)
(example: Y29tcGFueWlkK2ludGVncmF0b3Jsb2dpbjppbnRlZ3JhdG9ycGFzc3dvcmQ=)
x-cw-usertype: integrator
Body:
{
"memberIdentifier":"The member indentifier"
}
Response:
{
"publicKey": "yCdymjwp082t9uqp",
"privateKey": "zhqz7g3ne71jV4Jn",
"expiration": "2015-06-12T22:20:38Z"
}
</pre>
</dd>
</dl>
<dl>
<dt style="font-size:large">My Account</dt>
<dd>
<p><img alt="CW_Snag_-_0560.png" class="internal default" style="width: 1063px; height: 815px;" width="1063px" height="815px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0560.png"></p>
<p><img alt="CW_Snag_-_0561.png" class="internal default" style="width: 1063px; height: 815px;" width="1063px" height="815px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0561.png"></p>
<p><img alt="CW_Snag_-_0562.png" class="internal default" style="width: 1063px; height: 815px;" width="1063px" height="815px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0562.png"></p>
<p><img alt="CW_Snag_-_0563.png" class="internal default" style="width: 1063px; height: 815px;" width="1063px" height="815px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/CW_Snag_-_0563.png"></p>
</dd>
</dl>
<dl>
<dt style="font-size:large">Cookie Authentication</dt>
<dd>
<blockquote>
<p><strong>Warning</strong>:<em> If a partner activates SAML based
authentication, you will not be able to generate a member hash using the
Login.aspx page. &nbsp;The Hosted API will still return a hash that can
be used by the APIs, but all other methods of hash generation will no
longer work.</em></p>
</blockquote>
<p><span class="mt-color-ff0000">Vendor integrations should ignore cookie authentication and instead use API Members.</span></p>
<p>Cookie Authentication uses the ConnectWise PSA member credentials
for making API Requests. &nbsp;This method is subject to change with
the integration of additional two&nbsp;factor
authentications&nbsp;(2fa). &nbsp;By Passing the following
Form&nbsp;Request data, you will impersonate the member using your
integration.</p>
<p><img alt="cookieauth1.png" class="internal default" style="width: 927px; height: 411px;" width="927px" height="411px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/cookieauth1.png"></p>
<p>In order to obtain the MemberHash you have to call to our Login
module. &nbsp;Once you have done that you will recieve a unique hash
that expires every 8 hours. &nbsp;This is the &nbsp;max amount of time a
ConnectWise PSA session can remain active.</p>
<p><img alt="cookieauth2.png" class="internal default" style="width: 943px; height: 721px;" width="943px" height="721px" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/cookieauth2.png"></p>
</dd>
</dl>
</div></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_6"><span id="Rate_Limiting"></span><h3 class="editable">Rate Limiting</h3>
<p>To strengthen the stability, security, and performance of our APIs,
reasonable rate limits are enforced. This measure safeguards our system
against excessive or unintended high-volume requests, ensuring a
consistent and reliable experience for all users. The service monitors
resource usage in real time. If your request volume approaches capacity
limits, you may receive HTTP 429 (Too Many Requests) responses,
indicating temporary throttling. These responses include a Retry-After
header specifying the number of seconds to wait before re-attempting
your request. If your integration currently sends over 1,000 requests
per minute, it will likely experience rate limiting.&nbsp;</p>
<p>To avoid rate limits, we suggest that you optimize your integration
by minimizing unnecessary API calls and using proper filtering, limiting
the number of parallel requests, <a title="Best_Practices/Bundled_Requests" href="https://developer.connectwise.com/Best_Practices/Bundled_Requests" rel="internal">using bundled requests</a>, as well as implementing intelligent retry mechanisms with exponential backoff, respecting the Retry-After header values.</p>
<p>Example response body:</p>
<div class="style-wrap">
<pre> {
"error": "ConnectWiseAPI",
"message": "Too many requests. Please try again in 30 seconds."
}
</pre>
<p>Example code for handling 429 response:</p>
<pre>def make_request_with_backoff(url, headers=None, max_retries=5):
retry_count = 0
wait_time = 30 # Start with default 30 second wait time
while retry_count &lt; max_retries:
response = requests.get(url, headers=headers)
if response.status_code == 429: # Too Many Requests
retry_after = int(response.headers.get("Retry-After", wait_time)) # Use Retry-After if provided
print(f"Rate limit exceeded. Retrying in {retry_after} seconds...")
time.sleep(retry_after) # Wait before retrying
else:
return response # Return successful response or other errors
retry_count += 1
wait_time *= 2 # Exponential backoff (30, 60, 120, ...)
print("Max retries reached. Request failed.")
return None # Return None if all retries fail
</pre>
<p>&nbsp;</p>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_7"><span id="Security"></span><h3 class="editable">Security</h3>
<p>When working with the ConnectWise PSA REST API, security is based on
the Security Roles table within Manage.&nbsp; This table determines each
type of entity and the level of access associated.&nbsp; We do not
recommend requesting Admin access for an integration.&nbsp; Instead,
integrators are highly encouraged to only enable the security roles for
access that they need.</p>
<p><a title="Security_Roles_Matrix_11132017.xlsx" rel="internal" class="iconitext-16 ext-xlsx" href="https://developer.connectwise.com/@api/deki/files/422/Security_Roles_Matrix_11132017.xlsx?revision=1">Click here to view our Security Role Matrix</a></p>
<p>When looking at the REST API documentation, you may notice that some
items are considered a Setup Table value.&nbsp; These are denoted with
the lock icon.&nbsp; These endpoints will return an inquiry level of
access without access to the table.&nbsp; This matches the UI
functionality in that you can create listings of available statuses and
boards without having access to the setup table associated with those
values.</p>
<div class="mt-contentreuse-widget" data-page="Best_Practices/Manage_API_Requests" data-section="" data-show="false">
<div class="mt-include" id="s1291"><div class="mt-contentreuse-widget" data-page="AddTOC" data-section="" data-show="false">
<div class="mt-include" id="s1121">
</div>
</div>
<p>&nbsp;</p>
<div class="mt-contentreuse-widget" data-page="Best_Practices/HTTP_Verbs_and_Error_Codes" data-section="" data-show="false">
<div class="mt-include" id="s873"><div mt-section-origin="Best_Practices/HTTP_Verbs_and_Error_Codes" class="mt-section" id="section_1"><span id="HTTP_Methods"></span><h2 id="HTTP_Methods-873">HTTP Methods</h2>
<ul>
<li>POST
<ul>
<li>Create an entity or any non-CRUD action</li>
</ul>
</li>
<li>GET
<ul>
<li>Return entity or list of entities</li>
</ul>
</li>
<li>PUT
<ul>
<li>Replace all fields on an entity with supplied fields</li>
</ul>
</li>
<li>PATCH
<ul>
<li>Update specific fields on an entity</li>
</ul>
</li>
<li>DELETE
<ul>
<li>Remove entity</li>
</ul>
</li>
</ul>
</div><div mt-section-origin="Best_Practices/HTTP_Verbs_and_Error_Codes" class="mt-section" id="section_2"><span id="HTTP_Response_Statuses"></span><h2 id="HTTP_Response_Statuses-873">HTTP Response Statuses</h2>
<ul>
<li>201 Created
<ul>
<li>The response will be the record that was created as well as the path to it.</li>
</ul>
</li>
<li>204 NoContent
<ul>
<li>Will be returned by successful delete requests</li>
</ul>
</li>
<li>400 Bad Request
<ul>
<li>The request could not be understood by the server due to
malformed syntax. The client SHOULD NOT repeat the request without
modifications</li>
</ul>
</li>
<li>401 Unauthorized
<ul>
<li>The supplied authentication is incorrect</li>
</ul>
</li>
<li>403 Forbidden
<ul>
<li>Improper security role settings&nbsp;for the supplied authentication</li>
</ul>
</li>
<li>404 Not Found
<ul>
<li>Resource URL not found, this could mean the record was deleted or moved</li>
</ul>
</li>
<li>405 Method Not Allowed
<ul>
<li>This will occur if you try to use an HTTP method that is not supported by the URL specified</li>
</ul>
</li>
<li><span class="mt-font-arial" style="line-height:1.5;">409 </span><span class="mt-font-arial" style="line-height:1.5;">Conflict</span>
<ul>
<li>Record possibly in use or another conflict with the record</li>
</ul>
</li>
<li>415 Unsupported Media Type
<ul>
<li>This can occur when using the documents API if you are sending the file as a JSON object</li>
</ul>
</li>
<li>429 Too Many Requests
<ul>
<li>This will occur if request volume exceeds capacity limits
and will include a Retry-After header with a numeric value that
indicates the number of seconds to wait before retrying (see Retry
Policy below)&nbsp;</li>
</ul>
</li>
<li>500 Server Error
<ul>
<li>Server errors can occur oftentimes 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</li>
<li>These errors should follow the retry logic we recommend and if it appears to be an undefined error, should be reported</li>
</ul>
</li>
</ul>
<blockquote>
<p>PSA Specific - Are you getting a 404 error or "Could not get any
response" on cloud? &nbsp;You may have incorrect authentication instead
of the resource not being found. &nbsp;To confirm, change your base URL
from v4_6_release to your ConnectWise PSA version /201x_x/.&nbsp;</p>
</blockquote>
</div></div>
</div>
<div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_1"><span id="Formatting_Each_Method"></span><h2 id="Formatting_Each_Method-1291">Formatting Each Method</h2>
<div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_2"><span id="Get"></span><h3 id="Get-1291">Get</h3>
<p>Get requests are used for finding both individual records or a
listing of records. &nbsp;In order to grab an individual entity you must
specify an id within the request URL.</p>
<pre>https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000
</pre>
<p>When requesting a grouping of records, do not include an id record.
&nbsp;Optionally include parameters at the end of the URL to instead
grab a specific set of records.</p>
<pre>https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets?conditions=board/name="Integration"%20and%20status/name="new"&amp;page=1&amp;pageSize=10</pre>
<p>When looking at an endpoint, the parameters section will tell you
which fields can be used to filter the request. &nbsp;In addition to the
below parameters, you can use the Fields and Columns to manipulate the
response dataset.</p>
<div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_3"><span id="URL_Max_Length"></span><h4 id="URL_Max_Length-1291">URL Max Length</h4>
<p>The HTTP standards document does not impost a max URL length.
&nbsp;However various browsers, as well as applications,&nbsp;have
different limits in place. &nbsp;In addition search engines favor URLs
that are around 2000 characters. &nbsp;As a URL grows in length it no
longer remains user-friendly and becomes unusable or readable by users.
&nbsp;This causes issues with troubleshooting and leads to the overall
confusion. &nbsp;We recommend keeping the URL length of each request to a
maximum of 2000 characters. &nbsp;This will ensure there are no
compatibility issues with various servers and configurations.
&nbsp;Please keep in mind that the max length of a domain name can reach
255 characters. &nbsp;<strong>With that in mind, the safe max length of a URL would be around 1745 characters. &nbsp;</strong></p>
<p>This can vary based on environment configurations. &nbsp;There will
often be times when the URL could be significantly longer. &nbsp;There
may also be one of the server configurations based on premise that
restricts the URL to a lower length. &nbsp;However, it is recommended to
keep the URL length to a max of 2000 characters including the domain
name.</p>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_4"><span id="Query_String_Parameters"></span><h4 id="Query_String_Parameters-1291">Query String Parameters</h4>
<table border="1" cellpadding="1" cellspacing="1" style="width: 100%; table-layout: fixed;">
<tbody>
<tr>
<td style="width:105px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Parameter</strong></span></td>
<td style="width:200px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Description</strong></span></td>
<td style="width:383px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Example</strong></span></td>
<td style="background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>&nbsp;</strong></span></td>
</tr>
<tr>
<td style="width:105px;"><a title="Manage API Requests" href="#Conditions-1291" rel="internal">conditions</a></td>
<td style="width:200px;">Search results based on the fields returned in a GET</td>
<td style="width:383px;">board/name="Integration"<br>
summary="xyz"<br>
board/id in (3, 2, 4)<br>
lastUpdated &gt; [2016-08-20T18:04:26Z]<br>
Only fields returned in a GET request can be used</td>
<td>=, !=, &lt;, &lt;=, &gt;, &gt;=, contains, like, in, not</td>
</tr>
<tr>
<td style="width:105px;">childConditions</td>
<td style="width:200px;">Allows searching arrays on endpoints that list childConditions under parameters</td>
<td style="width:383px;">/company/contacts?childconditions=communicationItems/value like "<a title="mailto:%john@Outlook.com%" href="mailto:%john@Outlook.com%" target="_blank" rel="external noopener nofollow" class="link-mailto">john@Outlook.com</a>" AND communicationItems/communicationType="Email"</td>
<td>=, !=, &lt;, &lt;=, &gt;, &gt;=, contains, like, not</td>
</tr>
<tr>
<td style="width:105px;"><a title="Developer Guide" href="#Custom_Fields" rel="internal">customFieldConditions</a></td>
<td style="width:200px;">Allows searching custom fields when customFieldConditions is listed in the parameters</td>
<td style="width:383px;">/company/contacts?customFieldConditions=caption="TomNumber" AND value !=null</td>
<td>=, !=, &lt;, &lt;=, &gt;, &gt;=, contains, like,&nbsp;not</td>
</tr>
<tr>
<td style="width:105px;">orderBy</td>
<td style="width:200px;">Choose which field to sort the results by</td>
<td style="width:383px;">contact/name asc</td>
<td>asc or desc</td>
</tr>
<tr>
<td style="width:105px;"><a title="Developer Guide" href="#Partial_Responses" rel="internal">fields</a></td>
<td style="width:200px;">Limits which information is returned in the response</td>
<td style="width:383px;">company/companies?fields=id,name,status/id</td>
<td>Not available on the reporting endpoints</td>
</tr>
<tr>
<td style="width:105px;"><a title="Developer Guide" href="#Partial_Responses" rel="internal">columns</a></td>
<td style="width:200px;">Limits which information is returned in the response</td>
<td style="width:383px;">system/reports/service?columns=id,summary,name</td>
<td>Only used for the Reporting Endpoints</td>
</tr>
<tr>
<td style="width:105px;"><a title="Developer Guide" href="#Pagination" rel="internal">page</a></td>
<td colspan="3" rowspan="1" style="width:973px;">Used in pagination to cycle through results</td>
</tr>
<tr>
<td style="width:105px;"><a title="Developer Guide" href="#Pagination" rel="internal">pageSize</a></td>
<td colspan="2" rowspan="1" style="width:585px;">Number of results returned per page (Defaults to 25)</td>
<td rowspan="1" style="width:223px;">Max Size = 1,000*</td>
</tr>
<tr>
<td colspan="4" style="width:79px;">*Max page size was increased to 1,000&nbsp;in 2016.2.</td>
</tr>
</tbody>
</table>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_5"><span id="Conditions"></span><h4 id="Conditions-1291">Conditions</h4>
<table border="1" cellpadding="1" cellspacing="1" class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading">Strings</td>
<td class="mt-noheading">Must be surrounded by quotes</td>
<td class="mt-noheading">Summary = "This is my string" (Accepts *'s for Wild Cards)</td>
</tr>
<tr>
<td class="mt-noheading">Integers</td>
<td class="mt-noheading">No formatting required</td>
<td class="mt-noheading">Board/Id = 123</td>
</tr>
<tr>
<td class="mt-noheading">Boolean</td>
<td class="mt-noheading">No formatting is required but must be True or False</td>
<td class="mt-noheading">ClosedFlag =&nbsp;True</td>
</tr>
<tr>
<td class="mt-noheading">Datetimes</td>
<td class="mt-noheading">Must be surrounded by square brackets</td>
<td class="mt-noheading">LastUpdated =&nbsp;[2016-08-20T18:04:26Z]</td>
</tr>
<tr>
<td class="mt-noheading">Operators</td>
<td class="mt-noheading">&lt;,&nbsp;&lt;=,&nbsp;=,&nbsp;!=,&nbsp;&gt;,&nbsp;&gt;=,&nbsp;contains,&nbsp;like,&nbsp;in,&nbsp;not</td>
<td class="mt-noheading">Summary Not Contains "Low Priority"</td>
</tr>
<tr>
<td class="mt-noheading">Logic Operators</td>
<td class="mt-noheading">Supported operators include:
<ul>
<li>AND</li>
<li>OR</li>
</ul>
</td>
<td class="mt-noheading">
<p>board/name="integration" and summary="xyz"<br>
board/name="integration" or board/name="professional services"</p>
</td>
</tr>
<tr>
<td class="mt-noheading">Reference*</td>
<td class="mt-noheading">Must have a / followed by the field under the reference you would like to use</td>
<td class="mt-noheading">manufacturer/name</td>
</tr>
</tbody>
</table>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_6"><span id="Using_the_.2FSearch_endpoints"></span><h4 id="Using_the_.2FSearch_endpoints-1291">Using the /Search endpoints</h4>
<p>If your request URL is going to be over 10,000 characters long you
can instead use the /Search path for certain endpoints. &nbsp;This
allows you to enter the conditions in the body of the request.</p>
<pre>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'"
}</pre>
<blockquote>
<p>Successful get requests will return a 200 status response and a content body of the record(s).</p>
</blockquote>
</div></div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_7"><span id="Patch"></span><h3 id="Patch-1291">Patch</h3>
<p>Patch requests enable the ability to update individual fields on an
entity. &nbsp;When formatting the request you can specify multiple
fields to be updated. &nbsp;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. &nbsp;If you do not have the square brackets, you
will run into errors.&nbsp; In addition, when you are updating a
reference, you can only update it through the use of unique
values.&nbsp; Many times Name is not considered unique.</p>
<pre>https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000</pre>
<pre>[
{
"op": "string",
"path": "string",
"value": "string"
}
]
<span class="rangySelectionBoundary" id="selectionBoundary_1454443517692_5980667155236006" style="line-height:0;display:none;"></span></pre>
<table border="1" cellpadding="1" cellspacing="1" style="width: 100%; table-layout: fixed;">
<tbody>
<tr>
<td style="width:64px;">op</td>
<td style="width:277px;">The update operation used in the request</td>
<td style="width:293px;">add | replace | remove</td>
</tr>
<tr>
<td style="width:64px;">path</td>
<td style="width:277px;">Pathway for the updated field (Case Sensitive)</td>
<td style="width:293px;">summary<br>
company</td>
</tr>
<tr>
<td style="width:64px;">value</td>
<td style="width:277px;">The new value if doing a replace<br>
Refer to <a title="Developer Guide" href="#Escaping_Characters" rel="internal">escaping characters</a><br>
When working with custom fields, you must pass the entire array of custom fields.</td>
<td style="width:293px;">String: "Here is my Summary"<br>
Object: { "identifier": "connectwise" }</td>
</tr>
</tbody>
</table>
<div id="highlighter_51494" class="syntaxhighlighter "><div class="bar "><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>01</code></td><td class="content"><code class="plain">[</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>02</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>03</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"op"</code><code class="plain">: </code><code class="string">"replace"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>04</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"path"</code><code class="plain">: </code><code class="string">"summary"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>05</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"value"</code><code class="plain">: </code><code class="string">"New Summary"</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>06</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">},</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>07</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>08</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"op"</code><code class="plain">: </code><code class="string">"replace"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>09</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"path"</code><code class="plain">: </code><code class="string">"company"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>10</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"value"</code><code class="plain">: {</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>11</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"identifier"</code><code class="plain">: </code><code class="string">"New Company"</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>12</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">}</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>13</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">},</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>14</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>15</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"op"</code><code class="plain">: </code><code class="string">"replace"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>16</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"path"</code><code class="plain">: </code><code class="string">"customFields"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>17</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"value"</code><code class="plain">: [</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>18</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>19</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"id"</code><code class="plain">: 5,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>20</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"caption"</code><code class="plain">: </code><code class="string">"CloudPlus"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>21</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"type"</code><code class="plain">: </code><code class="string">"Checkbox"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>22</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"entryMethod"</code><code class="plain">: </code><code class="string">"EntryField"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>23</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"numberOfDecimals"</code><code class="plain">: 0,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>24</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"value"</code><code class="plain">: </code><code class="keyword">false</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>25</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">},</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>26</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>27</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"id"</code><code class="plain">: 28,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>28</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"caption"</code><code class="plain">: </code><code class="string">"test"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>29</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"type"</code><code class="plain">: </code><code class="string">"Text"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>30</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"entryMethod"</code><code class="plain">: </code><code class="string">"List"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>31</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"numberOfDecimals"</code><code class="plain">: 0,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>32</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"value"</code><code class="plain">: </code><code class="string">"test"</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>33</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">}</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>34</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">]</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>35</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">}</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>36</code></td><td class="content"><code class="plain">]</code></td></tr></tbody></table></div></div></div>
<blockquote>
<p>When updating an Object such as Company, you cannot specify a
location inside of the object. &nbsp;You have to replace the whole
object like the example above. (Do not
use&nbsp;"path":"company/identifier") &nbsp;If you try to update the
Object incorrectly, you may receive a false 200 message.</p>
<p>Successful patch requests will return a 200 status response for success</p>
</blockquote>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_8"><span id="Delete"></span><h3 id="Delete-1291">Delete</h3>
<p>Delete requests are used for removing records from the ConnectWise
PSA system. &nbsp;Please take care when removing items as they cannot be
recovered. &nbsp;The id for the record to be deleted needs to be
included in the request URL.</p>
<pre>https://api-na.myconnectwise.net/v4_6_release/apis/3.0/service/tickets/5000
</pre>
<blockquote>
<p>Successful delete requests will return a 204 status response for No Content. &nbsp;204 is a success response.</p>
</blockquote>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_9"><span id="Post"></span><h3 id="Post-1291">Post</h3>
<p>Post is used when creating new records. &nbsp;The body of the request
must be sent in JSON format. &nbsp;When sending a Post the response
body will include the newly created record id as well as a Get request
for the record. &nbsp;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.</p>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_10"><span id="Put"></span><h3 id="Put-1291">Put</h3>
<p>Put requests are designed to completely replace an entity. &nbsp;They
work the in the same manner as a Post request with the exception that
you must specify an already created entity in your URL. &nbsp;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.</p>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_11"><span id="Escaping_Characters"></span><h3 id="Escaping_Characters-1291">Escaping&nbsp;Characters</h3>
<p>When working with JSON, you may find that you need to use characters
that require escaping. &nbsp;This comes into play primarily when quotes
are involved as we do not support many of the characters that require
escaping. &nbsp;Refer to the chart below:</p>
<table class="mt-responsive-table">
<tbody>
</tbody>
<tbody>
<tr>
<th>Character</th>
<th class="mt-column-width-15">Escaped</th>
<th class="mt-column-width-50">Displayed in the UI</th>
</tr>
<tr>
<td data-th="Character">Double Quotes</td>
<td class="mt-column-width-15" data-th="Escaped">\"</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">"</td>
</tr>
<tr>
<td data-th="Character">Backslash</td>
<td class="mt-column-width-15" data-th="Escaped">\\</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">\</td>
</tr>
<tr>
<td data-th="Character">Tab</td>
<td class="mt-column-width-15" data-th="Escaped">\t</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">Tabbed space equal to four spaces</td>
</tr>
<tr>
<td data-th="Character">Backspace (Not Supported)</td>
<td class="mt-column-width-15" data-th="Escaped">\b</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">An invisible character that doesn't take up any space</td>
</tr>
<tr>
<td data-th="Character">Carriage Return (Not Supported)</td>
<td class="mt-column-width-15" data-th="Escaped">\r</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">Single space which is returned as a space in the API instead of an escaped character</td>
</tr>
<tr>
<td data-th="Character">Newline (Not Supported)</td>
<td class="mt-column-width-15" data-th="Escaped">\n</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">Single space which is returned as a space in the API instead of an escaped character</td>
</tr>
<tr>
<td data-th="Character">Form Feed (Not Supported)</td>
<td class="mt-column-width-15" data-th="Escaped">\f</td>
<td class="mt-column-width-50" data-th="Displayed in the UI">An invisible character that doesn't take up any space</td>
</tr>
<tr>
<td colspan="3" data-th="Displayed in the UI"><strong>Applies to JSON Bodies Only: </strong>Please
note that Single Quotes ', do not require escaping as they should not
be used as a container for your strings. &nbsp;If you are using single
contains around string values, you must switch to doubles.&nbsp;</td>
</tr>
</tbody>
</table>
<p>&nbsp;URL Encoding is required when using conditions and other URL
parameters that have symbols that would denote new query parameters or
strings.</p>
<table class="mt-responsive-table">
<thead>
<tr>
<th scope="col">Character</th>
<th scope="col">Formatting</th>
</tr>
</thead>
<tbody>
<tr>
<td data-th="Character">&amp;</td>
<td data-th="Formatting">%26</td>
</tr>
<tr>
<td data-th="Character">"</td>
<td data-th="Formatting">%22</td>
</tr>
<tr>
<td data-th="Character">'</td>
<td data-th="Formatting">%27</td>
</tr>
<tr>
<td data-th="Character">*</td>
<td data-th="Formatting">%2A</td>
</tr>
<tr>
<td data-th="Character">%</td>
<td data-th="Formatting">%25</td>
</tr>
<tr>
<td data-th="Character">+</td>
<td data-th="Formatting">%2B</td>
</tr>
<tr>
<td data-th="Character">[string]</td>
<td data-th="Formatting">[[]string]</td>
</tr>
<tr>
<td colspan="2" data-th="Formatting"><strong>This applies to URL Parameters Only</strong></td>
</tr>
</tbody>
</table>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_12"><span id="Partial_Responses"></span><h3 id="Partial_Responses-1291">Partial Responses</h3>
<p>The API allows you to specify which information you want to be
returned. &nbsp;You do this by listing the request fields or columns on
your endpoint URL. &nbsp;Partial responses work for both GET and POST
requests.</p>
<table border="1" cellpadding="1" cellspacing="1" style="width: 100%; table-layout: fixed;">
<tbody>
<tr>
<td style="width:159px;">Fields</td>
<td style="width:486px;">company/companies?fields=company/id,company/name,phoneNumber</td>
</tr>
<tr>
<td style="width:159px;">Columns (Reporting API only)</td>
<td style="width:486px;">system/reports/service?columns=id,summary,company/name</td>
</tr>
</tbody>
</table>
</div><div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_13"><span id="Custom_Fields"></span><h3 id="Custom_Fields-1291">Custom Fields</h3>
<p>Screens that have custom fields in the ConnectWise PSA UI will have
an array of fields on the respective endpoint. &nbsp;This array can be
both queried and updated via the API. &nbsp;When updating custom fields,
you must pass in the entire array object, which means that you cannot
patch a single custom field record. &nbsp;Wondering if an endpoint
supports custom fields? &nbsp;Supported endpoints will
have&nbsp;customFields(CustomFieldValue[]) listed at the end of the
documentation.</p>
<p>There are two methods of adding new custom fields to the ConnectWise
PSA environment. &nbsp;The first method will require access to the
ConnectWise PSA thick client and the second method is available in the
system/userDefinedFields&nbsp;endpoint within the REST API.</p>
<blockquote>
<p>Refer to the <a title="Developer Guide" href="#Get" rel="internal">GET </a>section on how to search custom fields. &nbsp;Searching custom fields uses customFieldConditions instead of conditions.</p>
</blockquote>
<p>In order to access the custom fields via the thick client, navigate to System &gt; Setup Tables &gt; Custom fields,</p>
<div mt-section-origin="Best_Practices/PSA_API_Requests" class="mt-section" id="section_14"><span id="Field_Options_and_Parameters"></span><h4 id="Field_Options_and_Parameters-1291">Field Options and Parameters</h4>
<p><img class="internal" style="width: 844px; height: 269px;" width="844px" height="269px" alt="Custom Fields.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/Custom%20Fields.png"></p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-15"><strong>Field</strong></td>
<td class="mt-noheading mt-column-width-55"><strong>Description</strong></td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Field Caption</td>
<td class="mt-noheading mt-column-width-55">Enter a custom field caption for this required field; you are limited to 12 characters.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Help Text</td>
<td class="mt-noheading mt-column-width-55">
<p>The text entered in this field will be displayed when you
hover over the help button next to the custom field on the screen.
&nbsp;</p>
<p><strong>Note:&nbsp;</strong>This has a limit of 1000 characters, however&nbsp;only 512 characters will display on the opportunity screen.</p>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Field Type</td>
<td class="mt-noheading mt-column-width-55">
<p>Select one of the following options:</p>
<ul>
<li><strong>Button</strong>&nbsp;This field allows you to add a hyperlink in the&nbsp;<strong>Button URL</strong>&nbsp;field. &nbsp;There is a character limit of 1000.</li>
<li><strong>Checkbox</strong>&nbsp;This field is used for simple "Yes/No" or "On/Off" answers. &nbsp;This will display as a checkbox.&nbsp;</li>
<li><strong>Date&nbsp;</strong>This field displays a standard date picker field.</li>
<li><strong>Hyperlink&nbsp;</strong>This field displays a text entry field to enter a URL and will be accompanied by a button to visit the hyperlink.</li>
<li><strong>Number&nbsp;</strong>This field displays
numerical values only. &nbsp;You will be prompted with an error message
that displays 'Option value must be a number' if the text is entered.
&nbsp;</li>
<li><strong>Percent&nbsp;</strong>This field displays
numerical values only. You will be prompted with an error message that
displays 'Option value must be a number' if the text is entered.</li>
<li><strong>Text&nbsp;</strong>This field displays alpha-numeric values. There is a character limit of 100.</li>
<li><strong>Text&nbsp;</strong><strong>Area&nbsp;</strong>This field displays alpha-numeric values. There is a character limit of 1000. The&nbsp;<strong>List&nbsp;</strong>and <strong>Dropdown&nbsp;</strong>method of entry is unavailable for this option.
<p><strong>Note:&nbsp;</strong>If you change a&nbsp;<strong>Date</strong>&nbsp;field to a&nbsp;<strong>Text&nbsp;</strong>or&nbsp;<strong>Text Area</strong>&nbsp;field, the date entered will save as plain text.<br>
<br>
If you change a&nbsp;<strong>Text&nbsp;</strong>or&nbsp;<strong>Text Area</strong>&nbsp;field to a&nbsp;<strong>Date</strong>&nbsp;field,
the system may not automatically save the date. If this occurs, and it
is a required field, the page-level validation will alert the user to
enter a date in the field.</p>
</li>
</ul>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Number of Decimals</td>
<td class="mt-noheading mt-column-width-55">This required field is only available for the Number and Percent Field Type. &nbsp;You can add up to 5 decimal places.&nbsp;</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Method of Entry</td>
<td class="mt-noheading mt-column-width-55">
<p>Select one of the following options:</p>
<ul>
<li><strong>Entry Field</strong>&nbsp;This field is available for all field types.</li>
<li><strong>List (Drop-down)&nbsp;</strong>This field is
available for the following field types: Number, Percent, and Text.
&nbsp;You are able to enter option values once this entry is
selected.&nbsp;</li>
<li><strong>Option (Radio)&nbsp;</strong>This field is
available for the following field types: Number, Percent, and Text.
&nbsp;You are able to enter option values once this entry is
selected.&nbsp;</li>
</ul>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Sequence #</td>
<td class="mt-noheading mt-column-width-55">Enter a sequence number. &nbsp;This value must be between 1 and 50.&nbsp;</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Required Field?&nbsp;</td>
<td class="mt-noheading mt-column-width-55">Select this checkbox if you would like to make this a required custom field. &nbsp;This will display as a blue asterisk.&nbsp;</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Display on Screen?</td>
<td class="mt-noheading mt-column-width-55">Select this checkbox if you would like this to display on the Opportunities screen. &nbsp;This is selected by default.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Read Only?</td>
<td class="mt-noheading mt-column-width-55">This field is used for the API. &nbsp;The&nbsp;<strong>Required Field</strong>&nbsp;checkbox cannot be marked for this field.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Include on List View?</td>
<td class="mt-noheading mt-column-width-55">
<p>Select this checkbox if you would like to include this custom field in the My Opportunities list view screen.</p>
<p><strong>Note:&nbsp;</strong>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.</p>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Button URL</td>
<td class="mt-noheading mt-column-width-55">Enter the URL if you are using the Field Type Button. The field only appends URLs, no other form of entry will generate content.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Select the Locations that will use this Custom Field</td>
<td class="mt-noheading mt-column-width-55">This is a
required field. &nbsp;Opportunities that have the specified location(s)
will display this custom field. &nbsp;Select at least one location where
the custom field will be used. &nbsp;</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Select the Departments that will use this Custom Field</td>
<td class="mt-noheading mt-column-width-55">This is not a required field. Opportunities that have the specified department(s) will display this custom field.</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>
</div></div></div></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_8"><span id="Pagination"></span><h3 class="editable">Pagination</h3>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_9"><span id="Navigable"></span><h4 class="editable">Navigable</h4>
<div class="mt-contentreuse-widget" data-page="Best_Practices/Manage_Pagination" data-section="Navigable Pagination" data-show="false">
<div class="mt-include" id="s1266">
<p>The ConnectWise PSA API provides a vast wealth of information for
developers to consume. &nbsp;Most of the time, you will find that there
is far more information than is needed for integration. &nbsp;In order
to ensure server availability, the API automatically sets the page size
to 25 results. &nbsp;The maximum page size for any request can be up to
1,000 records if properly specified in the request URL.</p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-15">pagesize</td>
<td class="mt-noheading mt-column-width-85">The number of
results returned by each call. &nbsp;Defaulted to 25 and has a maximum
of 1,000. &nbsp;These values cannot be changed.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">page</td>
<td class="mt-noheading mt-column-width-85">Starting with page 1, is the number of pages available based on the current pagesize.</td>
</tr>
</tbody>
</table>
<p>When using paging, the response will include a <a title="https://tools.ietf.org/html/rfc5988" href="https://tools.ietf.org/html/rfc5988" target="_blank" rel="external noopener nofollow" class="link-https">Link header</a> that looks like this:</p>
<div id="highlighter_165522" class="syntaxhighlighter "><div class="bar"><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>1</code></td><td class="content"><code class="plain">/v</code><code class="value">4</code><code class="plain">_</code><code class="value">6</code><code class="plain">_release/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pagesize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">1</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>2</code></td><td class="content"><code class="plain">link &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">2</code><code class="plain">&gt;; rel=</code><code class="string">"next"</code><code class="plain">, &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">4</code><code class="plain">&gt;; rel=</code><code class="string">"last"</code></td></tr></tbody></table></div></div></div>
<p>If you notice, the header contains two separate&nbsp;URLs in this
instance. &nbsp;The first one is "next" and the second one is "last".
&nbsp;These refer to the next set of results and the final set of
results. &nbsp;If we navigate to the next page, we will get some
additional URLs in the response Link header.</p>
<div id="highlighter_609603" class="syntaxhighlighter "><div class="bar"><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>1</code></td><td class="content"><code class="plain">/v</code><code class="value">4</code><code class="plain">_</code><code class="value">6</code><code class="plain">_release/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pagesize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">2</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>2</code></td><td class="content"><code class="plain">link &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">3</code><code class="plain">&gt;; rel=</code><code class="string">"next"</code><code class="plain">, &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">1</code><code class="plain">&gt;; rel=</code><code class="string">"prev"</code><code class="plain">, &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">1</code><code class="plain">&gt;; rel=</code><code class="string">"first"</code><code class="plain">, &lt;<a href="https://staging.connectwisedev.com/v">https://staging.connectwisedev.com/v</a></code><code class="value">2017</code><code class="plain">_</code><code class="value">3</code><code class="plain">/apis/</code><code class="value">3.0</code><code class="plain">/company/companies?pageSize=</code><code class="value">50</code><code class="plain">&amp;page=</code><code class="value">4</code><code class="plain">&gt;; rel=</code><code class="string">"last"</code></td></tr></tbody></table></div></div></div>
<p>Now that we have navigated to the second page, we will find two
additional URLs. &nbsp;These are "prev" and "first" and in total we now
have four including the original "next" and "last".</p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-10">First</td>
<td class="mt-noheading mt-column-width-85">This link will display the first page available based on the current page size</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-10">Prev*</td>
<td class="mt-noheading mt-column-width-85">This link will display the previous page based on the current page position and page size</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-10">Next*</td>
<td class="mt-noheading mt-column-width-85">This link will display the next available page based on the current page position and page size</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-10">Last</td>
<td class="mt-noheading mt-column-width-85">This link will always display the final page available based on the current page size</td>
</tr>
</tbody>
</table>
<p><span class="mt-color-e74c3c">*We will not return the next or prev links if there isn't a next or prev respectively.</span></p>
<p>In the above examples, we have four pages of results and depending on
the page size, that number can change. &nbsp;For instance, let's say we
switch to the default page size of 25. &nbsp;Instead of returning four
pages, we actually get back 7 pages as there are only 160 results.</p>
<p>The goal of pagination is not to pull every possible result, every
single time. &nbsp;Instead, it is designed to be in conjunction with a
UI component to create a set of navigation links.</p>
<p><img class="internal" style="width: 604px; height: 67px;" width="604px" height="67px" alt="clipboard_e29fb7e94d767bfdc2a4db21d834fef74.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_e29fb7e94d767bfdc2a4db21d834fef74.png"></p>
<blockquote>
<p>Navigable Pagination closely follows <a title="https://tools.ietf.org/html/rfc5988" href="https://tools.ietf.org/html/rfc5988" target="_blank" rel="external noopener nofollow" class="link-https">RFC 5988</a>.</p>
</blockquote>
</div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_10"><span id="Forward-Only"></span><h4 class="editable">Forward-Only</h4>
<div class="mt-contentreuse-widget" data-page="Best_Practices/Manage_Pagination" data-section="Forward-Only Pagination" data-show="false">
<div class="mt-include" id="s1266">
<p>Released in 2018.5</p>
<p>Unlike Navigable&nbsp;Pagination, forward-only requires that you pass
in a header to identify the type of pagination you would like to
use.&nbsp; 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.&nbsp; In addition to the new header, there is a new query
parameter called pageId.&nbsp; The pageId is the record in which you
would like to begin with for paging.</p>
<ul>
<li>If you do not include the new header in your request, it will use the default paging method of navigable.&nbsp;</li>
<li>The Page query parameter will be ignored with forward-only paging as all results are technically page 1.</li>
<li>You cannot use an Order By query parameter with forward-only as it must be ordered by the ID.</li>
<li>There will always be a link header in the response for the next pageId.</li>
<li>The pageId query parameter is treated like an additional condition of Id &gt; pageId.</li>
<li>The following pageId in the header will be the last Id you got in the request.</li>
</ul>
<p><img alt="clipboard_ebcad30cfa48ce47932d2c0b47108b933.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_ebcad30cfa48ce47932d2c0b47108b933.png"></p>
<p><img alt="clipboard_ef5cbb3427dc4eaba39453ea2dbcaf2c3.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_ef5cbb3427dc4eaba39453ea2dbcaf2c3.png"></p>
<p>&nbsp;</p>
<blockquote>
<p>Forward-Only pagination does not work with the Audit Trail endpoints at this time.</p>
</blockquote>
</div>
</div>
</div></div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_11"><span id="Callbacks_(Webhooks)"></span><h2 class="editable">Callbacks (Webhooks)</h2>
<div class="mt-contentreuse-widget" data-page="Manage/Developer_Guide/Callbacks" data-section="" data-show="">
<div class="mt-include" id="s859"><p>ConnectWise&nbsp;PSA callbacks are
payloads of information that are similar to webhooks. &nbsp;When a
record is saved within PSA, a summarized payload is sent to a
specified&nbsp;location.&nbsp;</p>
<div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_1"><span id="Levels_and_Types"></span><h3 id="Levels_and_Types-859">Levels and Types</h3>
<p>The REST APIs allow a more granular approach to callbacks.
&nbsp;Levels and types open the ability to report on specific boards or
tickets without getting unnecessary&nbsp;results.</p>
<table border="1" cellpadding="1" cellspacing="1" style="width: 100%; table-layout: fixed;">
<tbody>
<tr>
<td style="width:103px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Type</strong></span></td>
<td style="width:120px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Level</strong></span></td>
<td style="width:503px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Description</strong></span></td>
</tr>
</tbody>
<tbody>
<tr class="header">
<th colspan="3">Activities&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Activity</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;activities&nbsp;are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Activity</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for activities in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Activity</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for activities in the specified type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Activity</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for activities&nbsp;under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Activity</td>
<td style="width:120px;">Activity</td>
<td style="width:503px;">Receive callbacks for specific activity.</td>
</tr>
<tr class="header">
<th colspan="3">Agreements&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Agreement</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;agreements are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Agreement</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for agreements in the specified type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Agreement</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for agreements under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Agreement</td>
<td style="width:120px;">Agreement</td>
<td style="width:503px;">Recieve&nbsp;callbacks for specific agreement.</td>
</tr>
<tr class="header">
<th colspan="3">Companies&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;companies are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for companies in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for companies in the specified type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">Territory</td>
<td style="width:503px;">Receive callbacks for companies in the specified territory.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for specific company regardless of territory.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Company</td>
<td style="width:120px;">IntegratorTag</td>
<td style="width:503px;">Tag companies to only get updates for that company with one callback record</td>
</tr>
<tr class="header">
<th colspan="3">Contacts&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Contact</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;contacts are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Contact</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for contacts&nbsp;in the specified type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Contact</td>
<td style="width:120px;">Territory</td>
<td style="width:503px;">Receive callbacks for contacts in the specified territory.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Contact</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for contacts under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Contact</td>
<td style="width:120px;">Contact</td>
<td style="width:503px;">Receive callbacks for specific contact.</td>
</tr>
<tr class="header">
<th colspan="3">Configurations&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Configuration</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;configurations are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Configuration</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for configurations&nbsp;in the specified type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Configuration</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for contacts in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Configuration</td>
<td style="width:120px;">Configuration</td>
<td style="width:503px;">Receive callbacks for a specific configuration.</td>
</tr>
<tr class="header">
<th colspan="3">Invoice&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Invoice</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;invoices are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Invoice</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for invoices in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Invoice</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for invoices&nbsp;under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Invoice</td>
<td style="width:120px;">Invoice</td>
<td style="width:503px;">Receive callbacks for specific invoice.</td>
</tr>
<tr class="header">
<th colspan="3">Expense&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA expenses are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">ChargeToType</td>
<td style="width:503px;">Receive&nbsp; callbacks for expenses under the specified ChargeToType.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for expenses under the specified Type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">Class</td>
<td style="width:503px;">Receive callbacks for expenses under the specified Class.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for expenses under the specified Company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Expense</td>
<td style="width:120px;">Expense</td>
<td style="width:503px;">Receive calbacks for specific expense.</td>
</tr>
<tr class="header">
<th colspan="3">Member&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Member</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, changes to all ConnectWise PSA member records are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Member</td>
<td style="width:120px;">Location</td>
<td style="width:503px;">Receive callbacks for member records associated with the specified Location.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Member</td>
<td style="width:120px;">SecurityRole</td>
<td style="width:503px;">Receive callbacks for member records associated with the specified Security Role.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Member</td>
<td style="width:120px;">Member</td>
<td style="width:503px;">Receive callbacks for changes made to a specified member record.</td>
</tr>
<tr class="header">
<th colspan="3">Opportunities&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Opportunity</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;opportunities are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Opportunity</td>
<td style="width:120px;">StatusId</td>
<td style="width:503px;">Receive callbacks for opportunities&nbsp;in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Opportunity</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for opportunities&nbsp;under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Opportunity</td>
<td style="width:120px;">Opportunity</td>
<td style="width:503px;">Receive callbacks for specific opportunity.</td>
</tr>
<tr class="header">
<th colspan="3">Product Catalog&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">ProductCatalog</span></td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA product catalog items are returned.</td>
</tr>
<tr class="header">
<th colspan="3">Projects&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Project</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;projects&nbsp;are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Project</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for projects in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Project</td>
<td style="width:120px;">Board</td>
<td style="width:503px;">Receive callbacks for projects&nbsp;on the specified board.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Project</td>
<td style="width:120px;">Project</td>
<td style="width:503px;">Receive callbacks for specific project.</td>
</tr>
<tr class="header">
<th colspan="3">Purchase Orders&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA purchase orders are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for purchase orders in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:120px;">Vendor</td>
<td style="width:503px;">Receive callbacks for purchase orders under the specified Vendor.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for purchase orders&nbsp;under a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:120px;"><span class="mt-font-size-12">PurchaseOrder</span></td>
<td style="width:503px;">Receive callbacks for specific&nbsp;purchase orders.</td>
</tr>
<tr class="header">
<th colspan="3">Schedule Entries&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA schedule entries are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for schedule entries&nbsp;under a specific status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Type</td>
<td style="width:503px;">Receive callbacks for schedule entries&nbsp;under a specific type.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Location</td>
<td style="width:503px;">Receive callbacks for schedule entries&nbsp;under a specific location.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Member</td>
<td style="width:503px;">Receive callbacks for schedule entries&nbsp;under a specific member.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Schedule</td>
<td style="width:120px;">Schedule</td>
<td style="width:503px;">Receive callbacks for specific schedule entries.</td>
</tr>
<tr class="header">
<th colspan="3">Sites&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Site</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA sites are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Site</td>
<td style="width:120px;">Territory</td>
<td style="width:503px;">Receive callbacks for sites&nbsp;in specified territory.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Site</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for sites&nbsp;associated with a specific company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Site</td>
<td style="width:120px;">Site</td>
<td style="width:503px;">Receive callbacks for specific site.</td>
</tr>
<tr class="header">
<th colspan="3">Tickets&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;tickets are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Board</td>
<td style="width:503px;">Receive callbacks for tickets on the specified board.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Project</td>
<td style="width:503px;">Receive callbacks for tickets attached to a specific project.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Phase</td>
<td style="width:503px;">Receive callbacks for tickets attached to a specific project phase.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Status</td>
<td style="width:503px;">Receive callbacks for tickets in the specified status.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">Ticket</td>
<td style="width:503px;">Receive callbacks for specific tickets.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Ticket</td>
<td style="width:120px;">IntegratorTag</td>
<td style="width:503px;">Tag tickets to only get updates for that ticket with one callback record</td>
</tr>
<tr class="header">
<th colspan="3">Time Entries&nbsp;<span>+</span></th>
</tr>
<tr style="display: none;">
<td style="width:103px;">Time</td>
<td style="width:120px;">Owner</td>
<td style="width:503px;">When set to owner, all ConnectWise PSA&nbsp;time entries are returned.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Time</td>
<td style="width:120px;">Company</td>
<td style="width:503px;">Receive callbacks for tickets for the specified company.</td>
</tr>
<tr style="display: none;">
<td style="width:103px;">Time</td>
<td style="width:120px;">Time</td>
<td style="width:503px;">Receive callbacks for specific time entries.</td>
</tr>
</tbody>
</table>
<script type="text/javascript">/*<![CDATA[*/
$('.header').click(function(){
$(this).find('span').text(function(_, value){return value=='-'?'+':'-'});
$(this).nextUntil('tr.header').slideToggle(100, function(){
});
});/*]]>*/</script>
</div><div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_2"><span id="Configuring_the_Callbacks"></span><h3 id="Configuring_the_Callbacks-859">Configuring the Callbacks</h3>
<p>More information can be found within the REST API documentation <a title="https://developer.connectwise.com/Products/Manage/REST#/CallbackEntries" href="https://developer.connectwise.com/Products/ConnectWise_PSA/REST#/CallbackEntries" rel="internal">Here</a>&nbsp;with the endpoint system/callbacks.</p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-15" style="background-color:rgb(0, 102, 204);">
<p><span class="mt-color-ffffff"><strong>Fields</strong></span></p>
</td>
<td class="mt-noheading mt-column-width-85" style="background-color:rgb(0, 102, 204);">
<p><span class="mt-color-ffffff"><strong>Description</strong></span></p>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Id</td>
<td class="mt-noheading mt-column-width-85">The database record id of the callback;&nbsp;is automatically assigned.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Description</td>
<td class="mt-noheading mt-column-width-85">This is used to label the callback's usage.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">URL</td>
<td class="mt-noheading mt-column-width-85">
<p>This is the URL PSA&nbsp;will send the POST&nbsp;payload to.&nbsp;</p>
<p><strong>Note</strong>: PSA&nbsp;appends the record id, and action is taken, to the specified callback URL.</p>
<p>For example,&nbsp;a callback on ticket 7601, turns the callback URL&nbsp;into: <a title="https://mycallbacksite.com/e355a80bc2c107e32" href="https://mycallbacksite.com/e355a80bc2c107e32" target="_blank" rel="external noopener nofollow" class="link-https">https://mycallbacksite.com/e355a80bc2c107e32</a><em>?7601&amp;action=updated</em></p>
<p>Typically, this is not an issue. However, when it is
necessary to add custom&nbsp;parameters to your&nbsp;callback URL, this
can cause a problem. For this reason, it is recommended that partners
append&nbsp;<em>&amp;recordId=</em> to the end of their callback URL, like:&nbsp;<a title="https://mycallbacksite.com/e355a80bc2c107e32" href="https://mycallbacksite.com/e355a80bc2c107e32" target="_blank" rel="external noopener nofollow" class="link-https">https://mycallbacksite.com/e355a80bc2c107e32</a><strong><em>&amp;recordId=</em></strong>. This will ensure that the&nbsp;record id does not interfere with any custom parameters.</p>
<p>Example:<br>
Desired callback URL:&nbsp;<a data-auth="Verified" data-linkindex="0" href="https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapi.mycallbackendpoint.com%2F%3Fparam1%3D5%26param2%3D6&amp;data=05%7C01%7CRBodford%40connectwise.com%7C3deeae87cf1245c0a98008db0301ab7e%7Cf2ddb62f83354cc99886175b834e4bf3%7C0%7C0%7C638107077950837811%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=6dopNZzGSRoM5HMUn%2BzhlV0UV3DeZizIxiwMajv5eXE%3D&amp;reserved=0" originalsrc="https://api.mycallbackendpoint.com/?param1=5&amp;param2=6" rel="noopener noreferrer" shash="XphkNj4he01l3/v29hfbZ8eZIY7Gk5Arvm5LxavTIgYyFi9wOqCQMQNaCxTRCHsP8rB4xhKpF0csWjxclSngJ4SjGIABApacOziMt6jS3uOO84L+8G2hUnk0AVEgciG7annuA3/syZM4r5SGQ7Ely2gdhuLffxMoFaZNBvzre8k=" target="_blank" title="Original URL: https://api.mycallbackendpoint.com/?param1=5&amp;param2=6. Click or tap if you trust this link.">https://api.mycallbackendpoint.com?param1=5&amp;param2=6</a></p>
<p>Currently, a callback on ticket number 2475 turns the callback URL into:</p>
<p><a data-auth="Verified" data-linkindex="1" href="https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapi.mycallbackendpoint.com%2F%3Fparam1%3D5%26param2%3D62475%26action%3Dupdated&amp;data=05%7C01%7CRBodford%40connectwise.com%7C3deeae87cf1245c0a98008db0301ab7e%7Cf2ddb62f83354cc99886175b834e4bf3%7C0%7C0%7C638107077950837811%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=2BxWDta4VObPj81GAHDOWTxyrtYmj3AxTo8MYp3mxv4%3D&amp;reserved=0" originalsrc="https://api.mycallbackendpoint.com/?param1=5&amp;param2=62475&amp;action=updated" rel="noopener noreferrer" shash="TlXW142oUsObxDnCgBTOBwfa+0pl9ziUSh2i4in6gxpSXHmEuiaKVSqotlvhpGUooil0AQzdlAWg3jx26M1r2bk/RW897bYOHzjTFNZ69UYmWfhS80dTtrHRwd6HrFW6A/JN2tY06Da8uIV/yFOKNjzBHt/1Rt1M1Brfy2G3ApQ=" target="_blank" title="Original URL: https://api.mycallbackendpoint.com/?param1=5&amp;param2=62475&amp;action=updated. Click or tap if you trust this link.">https://api.mycallbackendpoint.com?param1=5&amp;param2=62475&amp;action=updated</a></p>
<p>Notice the value of param2 is now changed from 6 to 62475 because the ticket number was appended.</p>
<p aria-hidden="true">To resolve this issue, change the desired callback URL to&nbsp;<a data-auth="Verified" data-linkindex="2" href="https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapi.mycallbackendpoint.com%2F%3Fparam1%3D5%26param2%3D6%26recordId%3D&amp;data=05%7C01%7CRBodford%40connectwise.com%7C3deeae87cf1245c0a98008db0301ab7e%7Cf2ddb62f83354cc99886175b834e4bf3%7C0%7C0%7C638107077950837811%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=6zqQnRHSICdGqSor%2BzxHzG0xp%2F1sA%2FhPWiu7APbwl60%3D&amp;reserved=0" originalsrc="https://api.mycallbackendpoint.com/?param1=5&amp;param2=6&amp;recordId=" rel="noopener noreferrer" shash="meoQPTm90K66Kg5zJdjgiyOdehUJ6XGbBnPp6+b5NphRVS3OAZBYII+cD6RG2p1wZE7BGetcEg+/4qI48Y/vbcmtnlNU2Jej9LzQiJaUu9cj79O8tQot0l5DDpoKmxENMF/nG0kxqaJUqp5uDOjQmLQ+27jjYdrkyxkm5qjHPZQ=" target="_blank" title="Original URL: https://api.mycallbackendpoint.com/?param1=5&amp;param2=6&amp;recordId=. Click or tap if you trust this link.">https://api.mycallbackendpoint.com?param1=5&amp;param2=6&amp;recordId=</a></p>
<p>This results in the following URL:</p>
<p><a data-auth="Verified" data-linkindex="3" href="https://nam02.safelinks.protection.outlook.com/?url=https%3A%2F%2Fapi.mycallbackendpoint.com%2F%3Fparam1%3D5%26param2%3D6%26recordId%3D2475%26action%3Dupdated&amp;data=05%7C01%7CRBodford%40connectwise.com%7C3deeae87cf1245c0a98008db0301ab7e%7Cf2ddb62f83354cc99886175b834e4bf3%7C0%7C0%7C638107077950994009%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C3000%7C%7C%7C&amp;sdata=GwH9Y77%2Be5wgOxXwy%2FD1HXx4XRII%2FgE8eFCu7pyLafw%3D&amp;reserved=0" originalsrc="https://api.mycallbackendpoint.com/?param1=5&amp;param2=6&amp;recordId=2475&amp;action=updated" rel="noopener noreferrer" shash="QlCHGMx45y/eoAsClXEKlmzxS0NiCau08OosJQ9AyBgU+XXeRPiozojW8/1pKs3JuutiG1Ftfyo+HWfJBi8KM6S1LlPtJ4cCrjO9TYRdjqs/gafQKcThyRESlJT4ARsanbCcCbXArFjBeIjtov8msKL5v6+9nmKytE6WCuakcXQ=" target="_blank" title="Original URL: https://api.mycallbackendpoint.com/?param1=5&amp;param2=6&amp;recordId=2475&amp;action=updated. Click or tap if you trust this link.">https://api.mycallbackendpoint.com?param1=5&amp;param2=6&amp;recordId=2475&amp;action=updated</a></p>
</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">ObjectId</td>
<td class="mt-noheading mt-column-width-85">The
ObjectId&nbsp;should be the Id of whatever record you are subscribing
to. This should be set to 1 when using a level of Owner.&nbsp;</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Type</td>
<td class="mt-noheading mt-column-width-85">This is the specific type of record such as Company, Ticket, Contact, etc... See the associated table for all values.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Level</td>
<td class="mt-noheading mt-column-width-85">The level is used to determine how granular the callback subscription will be. &nbsp;See the associated table for all values.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">isSelfSuppressedFlag</td>
<td class="mt-noheading mt-column-width-85">If
isSelfSuppressedFlag = true AND the record (ticket/company/etc.) that is
triggering the callback was updated by the memberId associated with the
callback, then the callback does not fire. The logic being that the
member making&nbsp;the update does not&nbsp;need to be notified an
update was made.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">MemberId</td>
<td class="mt-noheading mt-column-width-85">This is a read-only value that shows who initially created the Callback.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">InactiveFlag</td>
<td class="mt-noheading mt-column-width-85">Used to determine if the callback is active and sending requests.</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">_Info</td>
<td class="mt-noheading mt-column-width-85">This section has additional metadata about the record and is included on all API requests as read-only data.</td>
</tr>
</tbody>
</table>
<div id="highlighter_858562" class="syntaxhighlighter "><div class="bar"><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>01</code></td><td class="content"><code class="plain">POST /v4_6_release/apis/3.0/system/callbacks</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>02</code></td><td class="content"><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>03</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"id"</code><code class="plain">: 0,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>04</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"description"</code><code class="plain">: </code><code class="string">"maxLength = 100"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>05</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"url"</code><code class="plain">: </code><code class="string">"Sample string"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>06</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"objectId"</code><code class="plain">: 0,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>07</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"type"</code><code class="plain">: </code><code class="string">"Sample string"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>08</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"level"</code><code class="plain">: </code><code class="string">"Sample string"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>09</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"memberId"</code><code class="plain">: 0,</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>10</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"inactiveFlag"</code><code class="plain">: </code><code class="string">"false"</code><code class="plain">,</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>11</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="string">"_info "</code><code class="plain">: { </code><code class="string">"lastUpdated"</code><code class="plain">: </code><code class="string">""</code><code class="plain">, </code><code class="string">"updatedBy"</code><code class="plain">: </code><code class="string">""</code> <code class="plain">}</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>12</code></td><td class="content"><code class="plain">}</code></td></tr></tbody></table></div></div></div>
</div><div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_3"><span id="Testing_Callbacks"></span><h3 id="Testing_Callbacks-859">Testing Callbacks</h3>
<div class="mt-contentreuse-widget" data-page="ConnectWise/Troubleshooting/Test_Applications" data-section="JSON Callback Tester:" data-show="">
</div>
<div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_4"><span id="Webhook.Site"></span><h4 id="Webhook.Site-859">Webhook.Site</h4>
<p>When testing the ConnectWise PSA callbacks there are a number of useful browser-based tools. &nbsp;One of note is&nbsp;<a title="https://webhook.site" href="https://webhook.site/" target="_blank" rel="external noopener nofollow" class="link-https">https://webhook.site</a>.</p>
<p>Simply&nbsp;use the New button to create a URL and then the Copy URL
button to save the&nbsp;URL generated to your clipboard&nbsp;and add
this as your ConnectWise PSA callback URL.</p>
<pre>https://webhook.site/xxxxxxx-xxxx-xxxx-af13-855ab85aebae
</pre>
</div></div><div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_5"><span id="When_Callbacks_Fail_to_POST_to_Target_Host"></span><h3 id="When_Callbacks_Fail_to_POST_to_Target_Host-859">When Callbacks Fail to POST to Target Host</h3>
<p>When a callback receives an error when attempting to POST the
callback payload to the host specified in the callback
URL,&nbsp;ConnectWise PSA will&nbsp;retry the POST for any 404, 409,
419, or 429 error responses.&nbsp;ConnectWise PSA retries twice, once
two seconds after the initial POST attempt and again four seconds after
the first retry attempt.&nbsp;Requests will timeout after five seconds.</p>
<p>The system counts how many consecutive days the callback fails, and
after three consecutive&nbsp;days of failed attempts, ConnectWise PSA
will&nbsp;disable the callback</p>
<p>Any 2xx response is considered successful.</p>
<p>For partners with an on-premise instance of&nbsp;ConnectWise PSA,
when troubleshooting why your callback POSTs are receiving error
response from the remote host, logs for the service are found on the
ConnectWise PSA frontend server at C:\Program
Files\ConnectWise\ApiCallbackService\logs\server.log</p>
<p>To enable verbose logging, change the minlevel&nbsp;value to
minlevel=”Info” in the &nbsp;C:\Program
Files\ConnectWise\ApiCallbackService\ApiCallbackService.exe.nlog</p>
</div><div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_6"><span id="Verifying_the_Callback_Source"></span><h3 id="Verifying_the_Callback_Source-859">Verifying the Callback Source</h3>
<p>Callbacks contain&nbsp;a key_url in the metadata section that can be
used to verify the source of the callback. &nbsp;The key_url returns the
signing key which then can be used in conjunction with the below code
sample and the x-content-signature.</p>
<div id="highlighter_904805" class="syntaxhighlighter "><div class="bar "><div class="toolbar"><a href="#viewSource" title="view source" style="width: 16px; height: 16px;" class="item viewSource">view source</a><a href="#printSource" title="print" style="width: 16px; height: 16px;" class="item printSource">print</a><a href="#about" title="?" style="width: 16px; height: 16px;" class="item about">?</a></div></div><div class="lines"><div class="line alt1"><table><tbody><tr><td class="number"><code>1</code></td><td class="content"><code class="keyword">using</code> <code class="plain">(var sha = </code><code class="keyword">new</code> <code class="plain">SHA256Managed())</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>2</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>3</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">var hash = sha.ComputeHash(Encoding.UTF8.GetBytes(sharedSecretKey));</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>4</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="keyword">using</code> <code class="plain">(var hmac = </code><code class="keyword">new</code> <code class="plain">HMACSHA256(hash))</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>5</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">{</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>6</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="keyword">return</code> <code class="plain">Convert.ToBase64String(hmac.ComputeHash(Encoding.UTF8.GetBytes(jsonPayload)));</code></td></tr></tbody></table></div><div class="line alt1"><table><tbody><tr><td class="number"><code>7</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">}</code></td></tr></tbody></table></div><div class="line alt2"><table><tbody><tr><td class="number"><code>8</code></td><td class="content"><code class="spaces">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</code><code class="plain">}</code></td></tr></tbody></table></div></div></div>
</div><div mt-section-origin="Best_Practices/PSA_Callbacks" class="mt-section" id="section_7"><span id="Callback_Changelog"></span><h3 id="Callback_Changelog-859">Callback Changelog&nbsp;</h3>
<table border="1" cellpadding="1" cellspacing="1" style="width: 100%; table-layout: fixed;">
<tbody>
<tr>
<td style="width:136px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Supported Version</strong></span></td>
<td style="width:509px;background-color:rgb(0, 102, 204);"><span class="mt-color-ffffff"><strong>Changes</strong></span></td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2020.2</td>
<td style="width:509px;">Added callbacks for Configurations</td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2016.6</td>
<td style="width:509px;">Added callbacks for Invoice<br>
Added callbacks for Projects<br>
Added callbacks for Activities</td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2016.5</td>
<td style="width:509px;">Company Callbacks: Added Status and Type levels<br>
Contact Callbacks: Added Type level<br>
Ticket Callbacks: Added levels for tracking Project Tickets</td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2016.4</td>
<td style="width:509px;">Added callbacks for Opportunities</td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2016.3</td>
<td style="width:509px;">Added&nbsp;callbacks for Companies and Contacts</td>
</tr>
<tr>
<td style="width:136px;">ConnectWise PSA&nbsp;2015.6</td>
<td style="width:509px;">Added callbacks for Tickets</td>
</tr>
</tbody>
</table>
</div></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_12"><span id="Troubleshooting"></span><h2 class="editable">Troubleshooting</h2>
<div class="mt-contentreuse-widget" data-page="Manage/Developer_Guide/Troubleshooting" data-section="" data-show="">
<div class="mt-include" id="s1176"><p>Troubleshooting with the REST API
requires login access to the ConnectWise PSA UI. &nbsp;Additionally the
account being used to login, must have access to information relating to
the account for integration. &nbsp;In the case of the integration using
API Members, the account accessing logs, must have the security roles
to view members enabled. &nbsp;This requirement has to do with the API
Keys used for integrations, being tied to a specific member.</p>
<p>Logging with the REST API must be specifically turned on and there is
a time limit of 1440 minutes or&nbsp;24 hours that can be recorded in a
single session. &nbsp;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. &nbsp;If you are getting errors from the
API and logs are not appearing, it may be a server side issue.</p>
<p>To get started with logging, you will need to access the API Log tab
found on every ConnectWise PSA member. &nbsp;Open the UI and navigate to
either System &gt; Members or My Account and after you select the
respective account, click on the API Logs tab.</p>
<p><img class="internal default" style="width: 670px; height: 245px;" width="670px" height="245px" alt="clipboard_e89a0f4557369e1913310d5ad38f55b88.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_e89a0f4557369e1913310d5ad38f55b88.png"></p>
<p>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.</p>
<p><img class="internal" style="width: 590px; height: 61px;" width="590px" height="61px" alt="clipboard_ef9f4d7b1792c1769f896add5d50d1b56.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_ef9f4d7b1792c1769f896add5d50d1b56.png"></p>
<p>Debugging will only run for a maximum of 1440 minutes per queue.
&nbsp;You can restart the timer at anytime by hitting "Start Debug Mode"
again.</p>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_1"><span id="Reading_Logs"></span><h3 id="Reading_Logs-1176">Reading Logs</h3>
<p><img class="internal" style="width: 1317px; height: 525px;" width="1317px" height="525px" alt="clipboard_ea2140f5216f5ed663aa1b17823aafb9a.png" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_ea2140f5216f5ed663aa1b17823aafb9a.png"></p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-25">Search</td>
<td class="mt-noheading mt-column-width-75">The search option will refresh the visible logs</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Start Debug Mode</td>
<td class="mt-noheading mt-column-width-75">This will kick off the recording process for the specified amount of time</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Download Logs</td>
<td class="mt-noheading mt-column-width-75">This will
provide a shareable document that contacts all of the requests that were
recorded since the last time the debug mode was started</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">API Key Description</td>
<td class="mt-noheading mt-column-width-75">This is the public key that is associated to the logged API Call</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Start Time</td>
<td class="mt-noheading mt-column-width-75">This is the start time for the request which when clicked, will show you the request body details</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Duration (ms)</td>
<td class="mt-noheading mt-column-width-75">This is how long the request took to be completed in milliseconds</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Response</td>
<td class="mt-noheading mt-column-width-75">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</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">Method</td>
<td class="mt-noheading mt-column-width-75">This is the HTTP Verb being used in the request</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-25">URL</td>
<td class="mt-noheading mt-column-width-75">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</td>
</tr>
</tbody>
</table>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_2"><span id="Telerik's_Fiddler"></span><h3 id="Telerik's_Fiddler-1176">Telerik's Fiddler</h3>
<p>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.&nbsp; What this means, is that if your request is timed out,
malformed&nbsp;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.&nbsp; There are other tools out there, besides our own
built in tools, that will provide information about your requests.&nbsp;
We have found that although there are many similar programs, Fiddler
has provided the easiest user experience and it is extremely accurate.</p>
<table class="mt-responsive-table">
<tbody>
<tr>
<td class="mt-noheading mt-column-width-15">Utility</td>
<td class="mt-noheading mt-column-width-25">Description</td>
<td class="mt-noheading mt-column-width-30">Download</td>
</tr>
<tr>
<td class="mt-noheading mt-column-width-15">Fiddler by Telerik</td>
<td class="mt-noheading mt-column-width-25">Free Web Debugging Proxy</td>
<td class="mt-noheading mt-column-width-30"><a title="https://www.telerik.com/fiddler" href="https://www.telerik.com/fiddler" target="_blank" rel="external noopener nofollow" class="link-https">https://www.telerik.com/fiddler</a></td>
</tr>
</tbody>
</table>
<p>Fiddler must be run from the machine that is making the outbound
requests.&nbsp; It cannot be run locally if the API requests are not
leaving your local machine from your control.&nbsp; Once you have
installed fiddler and have opened it for the first time you will see a
window like the below screenshot.</p>
<p><img alt="fiddler1.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/fiddler1.png"></p>
<p>Once you have managed to open Fiddler, there are a few settings that need to be changed in order for Fiddler to capture SSL.</p>
<p><img alt="fiddler2.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/fiddler2.png"></p>
<p>After you have setup fiddler to be able to capture your requests, you
simply need to send your API calls from your REST Client.&nbsp; 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.&nbsp; 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.</p>
<p><img alt="Image Capture - 0075.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/Image%20Capture%20-%200075.png"></p>
<p>If you do not turn off certificate verification, Postman will return
an error saying it couldn't get a response.&nbsp; Once you have
successfully made your request or successfully had an error occur, the
fiddler screen will display a list of URLs.&nbsp; Any that are marked in
red will be errors that Fiddler bas detected.</p>
<p><img alt="Image Capture - 0076.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/Image%20Capture%20-%200076.png"></p>
<p>If you click on the red entry you can drill into the details about the request and see more information on the error.</p>
<p><img alt="Image Capture - 0077.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/Image%20Capture%20-%200077.png"></p>
<p>In this case we can see that the problem with the request is that
company identifier is already in use.&nbsp; We can now right click on
the red item and unlock it for editing.&nbsp; what this does is we can
actually change the request right from within Fiddler.&nbsp; Once we
have then corrected the request we can right click on it again and this
time we can use replay.&nbsp; Replay will let you re-issue the command
right from within Fiddler, without having to go back to your REST
Client.</p>
<p><img alt="Image Capture - 0078.png" class="internal" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/Image%20Capture%20-%200078.png"></p>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_3"><span id="Error_Handling"></span><h3 id="Error_Handling-1176">Error Handling</h3>
<p>When working with the API, it is important to understand best
practices for handling errors. &nbsp;In the case of ever error, it
should be properly logged so it can be referenced later on. &nbsp;Server
errors are generally considered to be temporary errors and requests
should be repeated. &nbsp;If the request continues to occur, it should
be submitted for review. &nbsp;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.</p>
<div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_4"><span id="Retry_Policy"></span><h4 id="Retry_Policy-1176">Retry Policy</h4>
<p><b>Overview</b></p>
<p>An application that communicates with elements running in the cloud
has to be resilient against transient faults that commonly occur in
distributed environments. These faults include momentary loss of network
connectivity, temporary service unavailability, timeouts when services
are busy, and rate limiting imposed by service providers.</p>
<p>These faults are typically self-correcting, and if the action that
triggered a fault is repeated with an appropriate delay strategy, it's
likely to succeed. For example, a database service processing a large
number of concurrent requests might implement throttling that
temporarily rejects further requests until its workload eases. An
application encountering this throttling will fail to connect initially
but may succeed after a well-designed retry attempt.</p>
<p><b>Design Principles</b></p>
<p>In cloud environments, transient faults are expected, and
applications should be designed to handle them elegantly and
transparently to minimize impacts on business operations. A modern retry
policy should incorporate the following principles:</p>
<ol class="mt-indent-1" start="1">
<li><b>Distinguish between retryable and non-retryable failures</b></li>
<li><b>Implement intelligent delay strategies</b></li>
<li><b>Respect service-provided backoff instructions</b></li>
<li><b>Apply appropriate limits to prevent excessive retries</b></li>
<li><b>Consider the operation context when configuring retry behavior</b></li>
</ol>
<p><b>Failure Handling Strategies</b></p>
<p>When an application detects a failure in communicating with a remote
service, it should handle the failure using one of these strategies:</p>
<p><b>1. Cancel</b></p>
<p>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. Examples include:</p>
<ul class="mt-indent-1" data-lf-anchor-id="8bc42d6fcf39849a2149c94757230663:0">
<li>Authentication failures (HTTP 401)</li>
<li>Authorization failures (HTTP 403)</li>
<li>Resource not found errors (HTTP 404)</li>
<li>Bad request or validation failures (HTTP 400)</li>
<li>Any other client errors (4xx range) except those explicitly identified as retryable</li>
</ul>
<p><b>2. Retry Immediately</b></p>
<p>If the specific fault reported is unusual or rare, it might have been
caused by exceptional circumstances such as a network packet becoming
corrupted during transmission. In these cases, an immediate retry might
be appropriate as the same failure is unlikely to be repeated.</p>
<p><b>3. Retry with Exponential Backoff</b></p>
<p>For common connectivity issues or busy services, implement exponential backoff:</p>
<ul class="mt-indent-1" style="list-style-type:disc;">
<li>Start with a base delay (e.g., 100ms)</li>
<li>For each subsequent retry, multiply the previous delay by a constant factor (typically 2)</li>
<li>Apply a maximum delay cap to prevent extremely long waits</li>
<li>Add jitter (randomization) to the calculated delay to prevent retry storms</li>
</ul>
<p><b>4. Retry with Service-Guided Backoff</b></p>
<p>When services provide explicit guidance on retry timing:</p>
<ul class="mt-indent-1" style="list-style-type:disc;">
<li>For HTTP 429 (Too Many Requests) responses, parse and respect the Retry-After header</li>
<li>Retry-After specifies seconds, so wait that duration before retrying</li>
<li>Fall back to exponential backoff if the service doesn't provide retry guidance</li>
</ul>
<p><b>Implementation Pattern</b></p>
<pre>Initialize retry policy with:
- Maximum retry attempts
- Base delay duration
- Backoff multiplier
- Maximum delay cap
- Jitter factor
For each operation:
retries = 0
DO
Try to execute the operation
IF operation succeeds
Return success
ELSE IF operation fails with HTTP 429 AND Retry-After header exists
delay = Parse Retry-After header value
ELSE IF operation fails with retryable error
delay = baseDelay * (backoffMultiplier^retries) * (1 ± jitterFactor)
delay = min(delay, maxDelay)
ELSE
Return failure (non-retryable error)
END IF
IF retries &gt;= maxRetries
Return failure (retry limit exceeded)
END IF
Wait for calculated delay
retries = retries + 1
WHILE retries &lt; maxRetries
</pre>
<p><b>Configuring Retry Policies</b></p>
<p>The retry policy should be tuned to match the business requirements of the application and the nature of the operation:</p>
<p><b>For Interactive Applications</b></p>
<ul style="list-style-type:disc;">
<li>Use fewer retry attempts (2-3 typically)</li>
<li>Use shorter base delays (50-100ms)</li>
<li>Set lower maximum delay caps (2-5 seconds)</li>
<li>Provide user feedback during retries for longer operations</li>
<li>Consider showing appropriate messages to users when retries are exhausted</li>
</ul>
<p><b>For Background Operations</b></p>
<ul style="list-style-type:disc;">
<li>Use more retry attempts (5-10 or more depending on criticality)</li>
<li>Use longer base delays (200-500ms)</li>
<li>Allow higher maximum delay caps (30-60 seconds)</li>
<li>Implement dead-letter queues or failure logging for operations that exhaust retries</li>
<li>Consider partial success handling for batch operations</li>
</ul>
<p><b>For Critical Operations</b></p>
<ul style="list-style-type:disc;">
<li>Combine retry policies with circuit breakers to prevent cascading failures</li>
<li>Implement fallback mechanisms when retries are exhausted</li>
<li>Consider retry budgets to limit the overall retry rate across your system</li>
</ul>
<blockquote>
<p>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.</p>
</blockquote>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_5"><span id="500_Server_Errors"></span><h4 id="500_Server_Errors-1176">500 Server Errors</h4>
<p>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.</p>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" class="mt-section" id="section_6"><span id="400_Client_Errors"></span><h4 id="400_Client_Errors-1176">400 Client Errors</h4>
<p>A 400 error means that the request isn't valid. &nbsp;In the case of a
400 error you should stop the requests and analyze the results in order
to resolve the issue. &nbsp;Do not attempt to retry the request.</p>
</div></div></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_13"><span id="REST_SDK_Downloads"></span><h2 class="editable">REST SDK Downloads</h2>
<p>For more information please visit our <a title="SDK" href="#s686" rel="internal">SDK Section</a>.</p>
<div class="mt-contentreuse-widget" data-page="Manage/SDK" data-section="REST SDK" data-show="">
<div headingoffset="0" class="mt-include" id="s686"></div>
</div>
</div><div mt-section-origin="Products/ConnectWise_PSA/Developer_Guide" class="mt-section" id="section_14"><span id="Document_API"></span><h2 class="editable">Document API</h2>
<p>When working with the Document API, please use the uploaded sample provided with the following endpoint to proceed with testing.</p>
<p>GET <a title="https://ConnectWiseSite/v4_6_release/apis/3.0/system/documents/uploadsample" href="https://connectwisesite/v4_6_release/apis/3.0/system/documents/uploadsample" target="_blank" rel="external noopener nofollow" class="link-https">https://ConnectWiseSite/v4_6_release...s/uploadsample</a></p>
<p>The response is an HTML template that shows each of the settings that
can be selected. &nbsp;This form should help to design your own code
and mimic functionality.</p>
<p>&nbsp;<img class="internal" style="width: 415px; height: 325px;" width="415px" height="325px" alt="clipboard_e1d56cd4386ffef346995a6f8258a8ced" loading="lazy" src="Developer%20Guide%20-%20Developer%20Network_files/clipboard_e1d56cd4386ffef346995a6f8258a8ced.png"></p>
<div class="mt-contentreuse-widget" data-page="ConnectWise/Company_Info_(Cloud_Requests)" data-section="" data-show="">
<div class="mt-include" id="s959"><p>When making calls to the
ConnectWise PSA&nbsp;API, we have a URL that will give you the exact
codebase to target in place of v4_6_release. &nbsp;This is useful to see
if someone is on a cloud environment programmatically.
&nbsp;Additionally, the request can be routed directly to the correct
PSA&nbsp;version for the partner without it going through another
source.</p>
<div mt-section-origin="Best_Practices/PSA_Cloud_URL_Formatting" class="mt-section" id="section_1"><span id="Calling_Company_Info"></span><h2 id="Calling_Company_Info-959">Calling Company Info</h2>
<pre>"https://" + ConnectWiseSite + "/login/companyinfo/" + LoginCompanyId
https://na.myconnectwise.net/login/companyinfo/connectwise
</pre>
<div mt-section-origin="Best_Practices/PSA_Cloud_URL_Formatting" class="mt-section" id="section_2"><span id="Response"></span><h4 id="Response-959">Response</h4>
<pre>{
"CompanyName":"ConnectWise",
"Codebase":"v2017_3/",
"VersionCode":"v2017.3",
"VersionNumber":"v4.6.38842",
"CompanyID":"CW",
"IsCloud":"True" *<span class="mt-color-0000cd">Added in 2016.5</span>
}
</pre>
</div></div><div mt-section-origin="Best_Practices/PSA_Cloud_URL_Formatting" class="mt-section" id="section_3"><span id="API_Request_URL_Format"></span><h2 id="API_Request_URL_Format-959">API Request URL Format</h2>
<pre>"https://" + ConnectWiseSite + "/" + codebase + "apis/3.0/company/companies"
https://api-my.myconnectwise.net/v2017_3/apis/3.0/company/companies
</pre>
</div><div mt-section-origin="Best_Practices/PSA_Cloud_URL_Formatting" class="mt-section" id="section_4"><span id="Cloud_vs_Premise"></span><h2 id="Cloud_vs_Premise-959">Cloud vs Premise</h2>
<p>A cloud environment will return a codebase&nbsp;with the
PSA&nbsp;version. &nbsp;On-Premise does not use URL redirection and will
return v4_6_release/. &nbsp;If your returned codebase contains anything
other than v4_6_release/, you will need to ensure your request is
prefixed by API-</p>
</div><div mt-section-origin="Best_Practices/PSA_Cloud_URL_Formatting" class="mt-section" id="section_5"><span id="Cloud_URLs"></span><h2 id="Cloud_URLs-959">Cloud URLs</h2>
<p>These are the most commonly used URLs for the cloud.</p>
<pre>https://na.myconnectwise.net
https://eu.myconnectwise.net
https://au.myconnectwise.net
https://aus.myconnectwise.net
https://za.myconnectwise.net
https://staging.connectwisedev.com</pre>
</div></div>
</div>
<div id="mt-guide-tabs" class="noindex" data-ga-action="Guide tabs"></div><script type="application/json" id="mt-guide-tabs-json">/*<![CDATA[*/null/*]]>*/</script><script type="application/json" id="mt-localizations-guide-tabs">/*<![CDATA[*/{"MindTouch.IDF3.label.guide.tabscrollleft":"Scroll tabs left","MindTouch.IDF3.label.guide.tabscrollright":"Scroll tabs right"}/*]]>*/</script><script type="application/json" id="mt-localizations-guide-tabs-settings">/*<![CDATA[*/{"MindTouch.IDF3.label.guide.settings.classifications":"Classification settings","MindTouch.IDF3.label.guide.settings.learningpath":"Path settings","MindTouch.IDF3.label.overview.max.count":"{0} characters remaining.","MindTouch.IDF3.label.overview.max.count.over":"Warning. {0} characters will be truncated.","MindTouch.LearningPath.dialog.remove.cancel":"Cancel","MindTouch.LearningPath.dialog.remove.confirm":"OK","MindTouch.LearningPath.dialog.remove.header":"Remove path","MindTouch.LearningPath.dialog.remove.message":"You are about to remove this path from this guide."}/*]]>*/</script>
</div>
<footer class="mt-content-footer"></footer>
</section>
<footer class="elm-content-footer">
<ol class="elm-meta-data elm-meta-article-navigation">
<li class="elm-back-to-top"><a class="mt-icon-back-to-top" href="#title" id="mt-back-to-top" title="Jump back to top of this article">Back to top</a></li>
<li class="elm-article-pagination"><ul class="mt-article-pagination" data-ga-action="Article pagination bottom">
<li class="mt-pagination-previous">
<a class="mt-icon-previous-article" data-ga-label="Previous page" href="https://developer.connectwise.com/Products/ConnectWise_PSA/REST/CompanyTest" title="CompanyTest"><span>CompanyTest</span></a>
</li>
<li class="mt-pagination-next">
<a class="mt-icon-next-article" data-ga-label="Next page" href="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide/Authentication" title="Authentication"><span>Authentication</span></a>
</li>
</ul>
</li>
</ol>
<div class="elm-article-feedback"><div class="mt-feedback-rating-container" data-ga-action="Page rating" data-page-revision="176" data-use-local-storage="false"><ul class="mt-feedback-rating-controls"><li class="mt-feedback-rating-message mt-feedback-rating-item">Was this article helpful?</li><li class="mt-rating-yes mt-feedback-rating-item"><button class="mt-rating-button-yes mt-feedback-rating-button ui-button-icon mt-icon-rating-yes" data-ga-label="Rate">Yes</button></li><li class="mt-rating-no mt-feedback-rating-item"><button class="mt-rating-button-no mt-feedback-rating-button ui-button-icon mt-icon-rating-no" data-ga-label="Rate">No</button></li><li class="mt-leave-feedback mt-feedback-rating-item"><button class="mt-feedback-button mt-feedback-rating-button ui-button-icon mt-icon-leave-feedback" data-ga-label="Feedback toggle">Leave feedback</button></li><li class="mt-last-rating-date mt-feedback-rating-item"></li></ul><div id="mt-feedback-flash-message"></div><div class="mt-feedback-form" data-path="Products/ConnectWise_PSA/Developer_Guide" data-user-email="user@example.invalid" data-page-title="Developer Guide" data-site-url="https://developer.connectwise.com/"><fieldset class="ui-dform-fieldset"><legend class="ui-dform-legend">Leave feedback</legend><div class="mt-field"><label class="mt-feedback-improve-label ui-dform-label" for="textarea-feedback">How can we improve this article?</label><textarea autocomplete="off" class="mt-feedback-improve-description ui-dform-textarea" id="textarea-feedback" spellcheck="false"></textarea></div><div class="mt-field"><input class="mt-feedback-consent-checkbox ui-dform-checkbox" data-ga-label="Feedback consent" id="mt-feedback-consent" type="checkbox"><label class="mt-feedback-consent-label mt-label-checkbox" data-ga-label="Feedback consent" for="mt-feedback-consent">Yes, you may contact me about this feedback.</label></div><div class="mt-field mt-submit"><button class="mt-feedback-submit mt-disabled ui-button ui-button-primary" data-ga-label="Submit feedback" id="deki-feedback-send">Submit feedback</button></div></fieldset></div></div><script type="application/json" id="mt-localizations-feedback-rating">/*<![CDATA[*/{"Page.FeedbackRating.label.last-rated":"-- You last rated this article on {0}","Page.FeedbackRating.message.contact.no":"No","Page.FeedbackRating.message.contact.yes":"Yes","Page.FeedbackRating.message.submit.error":"An error occurred while attempting to send your feedback. Please try again at a later time.","Page.FeedbackRating.message.submit.success":"Your feedback has been successfully submitted. You can submit more feedback at any time."}/*]]>*/</script></div>
<div class="elm-related-articles-container"><h2 class="mt-related-articles-header">Recommended articles</h2>
<ol class="mt-related-listings-container" data-ga-action="related">
<li class="mt-related-listing mt-related-listing-detailed"><a class="mt-related-listing-link" href="https://developer.connectwise.com/Products/ConnectWise_PSA/REST" title="REST" data-ga-label="related-link-detailed-1"><span class="mt-related-listing-link-icon mt-icon-article-topic-guide"></span><span class="mt-related-listing-link-text">REST</span></a><span class="mt-related-listing-link-overview">This
page will serve as the documentation hub for all Manage REST
docs.&nbsp; If you are having issues please report them to
Platform@ConnectWise.com and u...</span></li><li class="mt-related-listing mt-related-listing-detailed"><a class="mt-related-listing-link" href="https://developer.connectwise.com/Best_Practices/HTTP_Verbs_and_Error_Codes" title="HTTP Verbs and Error Codes" data-ga-label="related-link-detailed-2"><span class="mt-related-listing-link-icon mt-icon-article-topic-guide"></span><span class="mt-related-listing-link-text">HTTP Verbs and Error Codes</span></a></li><li class="mt-related-listing mt-related-listing-detailed"><a class="mt-related-listing-link" href="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide/Batch_Requests" title="Batch Requests" data-ga-label="related-link-detailed-3"><span class="mt-related-listing-link-icon mt-icon-article-topic-category"></span><span class="mt-related-listing-link-text">Batch Requests</span></a></li><li class="mt-related-listing mt-related-listing-detailed"><a class="mt-related-listing-link" href="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide/Troubleshooting" title="Troubleshooting" data-ga-label="related-link-detailed-4"><span class="mt-related-listing-link-icon mt-icon-article-topic-category"></span><span class="mt-related-listing-link-text">Troubleshooting</span></a></li><li class="mt-related-listing mt-related-listing-detailed"><a class="mt-related-listing-link" href="https://developer.connectwise.com/Products/ConnectWise_PSA/Developer_Guide/Markdown" title="Markdown" data-ga-label="related-link-detailed-5"><span class="mt-related-listing-link-icon mt-icon-article-topic-guide"></span><span class="mt-related-listing-link-text">Markdown</span></a></li></ol>
<script type="application/json" nonce="" id="mt-localizations-related-pages">
{"Skin.Columbia.label.no-recommended-articles":"There are no recommended articles."}</script></div>
<ol class="elm-meta-data elm-meta-bottom">
<li class="elm-classifications"> <dl class="mt-classification mt-classification-article-guide" data-ga-action="Tag navigation">
<dt class="mt-classification-label">Article type</dt>
<dd class="mt-classification-value"><a href="https://developer.connectwise.com/Special:Search?tags=article%3Atopic-guide" data-ga-label="Classification">Guide</a></dd>
</dl>
</li>
<li class="elm-tags"><dl class="mt-tags">
<dt class="mt-tag-label">Tags</dt>
<dd class="mt-tag-value">
<ol class="mt-tags-list" data-ga-action="Tag navigation">
<li class="mt-tag-link mt-tag-callbacks" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Callbacks" data-ga-label="Free tag"> Callbacks</a></li>
<li class="mt-tag-link mt-tag-codebase" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Codebase" data-ga-label="Free tag"> Codebase</a></li>
<li class="mt-tag-link mt-tag-conditions" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Conditions" data-ga-label="Free tag"> Conditions</a></li>
<li class="mt-tag-link mt-tag-custom-fields" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Custom+fields" data-ga-label="Free tag"> Custom fields</a></li>
<li class="mt-tag-link mt-tag-endpoints" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Endpoints" data-ga-label="Free tag"> Endpoints</a></li>
<li class="mt-tag-link mt-tag-formatting" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Formatting" data-ga-label="Free tag"> Formatting</a></li>
<li class="mt-tag-link mt-tag-get" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=GET" data-ga-label="Free tag"> GET</a></li>
<li class="mt-tag-link mt-tag-headers" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Headers" data-ga-label="Free tag"> Headers</a></li>
<li class="mt-tag-link mt-tag-http-methods" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=HTTP+Methods" data-ga-label="Free tag"> HTTP Methods</a></li>
<li class="mt-tag-link mt-tag-patch" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=PATCH" data-ga-label="Free tag"> PATCH</a></li>
<li class="mt-tag-link mt-tag-post" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=POST" data-ga-label="Free tag"> POST</a></li>
<li class="mt-tag-link mt-tag-rate-limiting" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Rate+Limiting" data-ga-label="Free tag"> Rate Limiting</a></li>
<li class="mt-tag-link mt-tag-rest" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=rest" data-ga-label="Free tag"> rest</a></li>
<li class="mt-tag-link mt-tag-urls" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=URLs" data-ga-label="Free tag"> URLs</a></li>
<li class="mt-tag-link mt-tag-versioning" rel="nofollow"><a href="https://developer.connectwise.com/Special:Search?tags=Versioning" data-ga-label="Free tag"> Versioning</a></li>
</ol>
</dd>
</dl></li>
</ol>
</footer>
</article>
<footer class="elm-footer">
<nav class="elm-footer-siteinfo-nav elm-nav">
<div class="elm-nav-container">
<ol>
<li class="elm-footer-copyright">© Copyright 2026 Developer Network</li>
<li class="elm-footer-powered-by"><a href="https://mindtouch.com/demo" class="mt-poweredby product " title="MindTouch" target="_blank">
Powered by NiCE Knowledge Management
<span class="mt-registered">®</span>
</a></li>
</ol>
</div>
</nav>
<div class="elm-footer-custom"><script>/*<![CDATA[*/ $('#spanYear').html(new Date().getFullYear());/*]]>*/</script>
<div class="cw-footer"><div class="footer-wrapper"><ul class="show-loggedin"><li><a href="https://developer.connectwise.com/" rel="internal">Home</a></li><li><a href="https://developer.connectwise.com/Products/ConnectWise_PSA" rel="internal">ConnectWise PSA</a></li><li><a href="https://developer.connectwise.com/Products/ConnectWise_Automate" rel="internal">ConnectWise Automate</a></li><li><a href="https://docs.connectwise.com/ConnectWise_Control_Documentation/Developers/Integration_guide" target="_blank" rel="external noopener nofollow" class="link-https">ConnectWise ScreenConnect</a></li><li><a href="https://developer.connectwise.com/Products/ConnectWise_CPQ" rel="internal">ConnectWise CPQ</a></li><li><a href="https://virtualcommunity.connectwise.com/community-home?CommunityKey=b91ec22c-a6ca-4ae3-bedb-018a5199538b" target="_blank" rel="external noopener nofollow" class="link-https">Developer Community</a></li><li><a href="https://developer.connectwise.com/faq" rel="internal">FAQ</a></li><li><a href="https://developer.connectwise.com/ClientID" rel="internal">Client ID</a></li></ul><p>© 2024 ConnectWise. All Rights Reserved.</p><div class="social-links"><ul><li class="facebook"><a href="https://www.facebook.com/ConnectWise?ref=ts" target="_blank" rel="external noopener nofollow" class="link-https"><i class="fa fa-facebook-square"></i></a></li><li class="linkedin"><a href="https://www.linkedin.com/company/connectwise" target="_blank" rel="external noopener nofollow" class="link-https"><i class="fa fa-linkedin-square"></i></a></li><li class="twitter"><a href="https://twitter.com/connectwise" target="_blank" rel="external noopener nofollow" class="link-https"><i class="fa fa-twitter-square"></i></a></li><li class="youtube"><a href="https://www.youtube.com/user/connectwise#grid/uploads" target="_blank" rel="external noopener nofollow" class="link-https"><i class="fa fa-youtube-square"></i></a></li></ul></div></div></div>
<div class="style-wrap">
<script type="text/javascript" src="Developer%20Guide%20-%20Developer%20Network_files/devnetcookie.js"></script>
</div>
</div>
</footer>
</main>
<div id="mt-modal-container"></div>
<script type="text/javascript" async="async" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/f1.js"></script>
<script type="text/javascript" data-mindtouch-module="true" src="Developer%20Guide%20-%20Developer%20Network_files/ui.guideTabsDisplay.js"></script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/serviceworker-unregister.js"></script><script type="text/javascript" data-mindtouch-module="true" nonce="" src="Developer%20Guide%20-%20Developer%20Network_files/pageLoaded.js"></script>
<script type="text/javascript" data-mindtouch-module="true" src="Developer%20Guide%20-%20Developer%20Network_files/f1.widget.js"></script><div id="hudu-eh-root"></div><div id="hudu-ch-root"></div><div id="hudu-pc-root"></div></body></html>