Contents

Upload Documents to Connectwise via ReST API

I struggled for a while with uploading documents to Connectwise via the API. This post has waited to be born for about a year, it was information I didn’t want to loose so I kept it in a dusty folder on my desktop.

The information presented is aimed at the Connectwise ReST API but who knows, it may be handy for someone else struggling with a similar problem. I needed to be able to upload files to a Connectwise Service Ticket. Looking at the API documentation resulted in more questions than answers.

Just use the SDK provided by Connectwise

I have used the SDK before, my problem with the SDK is that it seemed to break quite often and need updated while my manual code using HttpClient survived without issues. I wanted to stick with my code and not rely on a third party dll.

The Client

I’m assuming that you are already using System.Net.Http.HttpClient and not the SDK and that you know how to configure the client. If not then this is how I configure my HttpClient. I pull the information for Codebase from the official endpoint https://na.myconnectwise.net/login/companyinfo/YOUR_COMPANY_NAME

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
// Get Company Info
CWCompanyInfo companyInfo = await GetCompanyInfo();

// Create Client
HttpClient httpClient = new HttpClient()
{
    BaseAddress = new Uri($"https://{companyInfo.SiteUrl}/{companyInfo.Codebase}apis/3.0")
};

httpClient.DefaultRequestHeaders.Add("Authorization", string.Format("Basic {0}",
    Base64Encode(string.Format("COMPANY+{0}:{1}", Registry.GetValue(CWCLIENT_REGISTRY_ROOT, "pub", ""),
    Registry.GetValue(CWCLIENT_REGISTRY_ROOT, "priv", "")))));
httpClient.DefaultRequestHeaders.Add("Accept",
    $"application/vnd.connectwise.com+json; version={companyInfo.VersionCode}");
httpClient.DefaultRequestHeaders.Add("clientId", "CONNECTWISE-CLIENTID-HERE");
httpClient.DefaultRequestHeaders.Add("cache-control", "no-cache");

The Endpoint

The endpoint we will end up using is under ‘Documents’ in the API specs, [POST] /system/documents.

/images/cwapi-upload-documents-r1.png
Connectwise Endpoint

The endpoint lists the following schema which led me to question if this was even the right endpoint.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
{
  "id": 0,
  "title": "string",
  "fileName": "string",
  "serverFileName": "string",
  "owner": "string",
  "linkFlag": true,
  "imageFlag": true,
  "publicFlag": true,
  "htmlTemplateFlag": true,
  "readOnlyFlag": true,
  "size": 0,
  "urlFlag": true,
  "_info": {
    "additionalProp1": "string",
    "additionalProp2": "string",
    "additionalProp3": "string"
  }
}

Thanks to Raymond over at http://solutionsbyraymond.com/ I found his article How to Upload Documents using ConnectWise API which let me know this was the right endpoint and gave me some tips on how to achieve it. Raymond wasn’t using HttpClient so I had to do some investigation.

The Solution

Using HttpClient was actually easier than I had hoped. I found a few other random articles that demonstrated file uploads to other APIs and finally pieced it together.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
string file_path = @"C:\Folder\test.jpg";
string file_name = "test.jpg";
int ticket_id = 45268;

MultipartFormDataContent form = new MultipartFormDataContent();
form.Add((HttpContent)new ByteArrayContent(new StreamContent((Stream)File
    .OpenRead(file_path)).ReadAsByteArrayAsync().Result), "file", file_name);
form.Add((HttpContent)new StringContent(file_name), "title");
form.Add((HttpContent)new StringContent(ticket_id), "recordId");
form.Add((HttpContent)new StringContent("Ticket"), "recordType");

HttpResponseMessage file_response = await client
    .PostAsync($"{client.BaseAddress.OriginalString}/system/documents", (HttpContent)form);

if (file_response.IsSuccessStatusCode)
{
    return true;
}

return false;