For anyone having a similar issue, I've figured it out.
To post data to external APIs, Google Apps Script uses
UrlFetchApp.fetch(url, options)
Where the URL is a string and options is an object with several key-value tuples. The apps script syntax is non-standard and apparently doesn't reformat to meet the HTTP 1.1 encoding standard. I found https://httpbin.org/ which responds to requests by sending the request string back for logging. The error, from Apps Script in particular, had to do with the Content Type header being malformed.
Apps Script expects:
{
Authorization: Bearer <TOKEN>,
contentType: 'application/json'
}
and the Canvas API rejects the call. Changing the apps script object to:
{
Authorization: Bearer <TOKEN>,
Content-Type: 'application/json'
}
resulted in a successful request.