I had the exact issue but I finally figured out that external tools can't use the canvas REST api to submit grades. You have to follow the LTI protocol. The canvas docs have the details explained here: Grade Passback Tools - Canvas LMS REST API Documentation
If you are using java to implement your provider, you can use this library that makes posting grades easy:
Maven Repository: org.imsglobal » basiclti-util
You use IMSPOXRequest.buildReplaceResult(...);
Here is an example:
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpParams httpParams = httpClient.getParams();
HttpConnectionParams.setConnectionTimeout(httpParams, TIMEOUT_SECONDS*1000);
HttpConnectionParams.setSoTimeout(httpParams, TIMEOUT_SECONDS*1000);
HttpPost httpPost = IMSPOXRequest.buildReplaceResult(canvasUrl, key, secret, sourceId, score, null, true);
HttpResponse httpResponse = httpClient.execute(httpPost);
int statusCode = httpResponse.getStatusLine().getStatusCode();
if(statusCode == 401) {
LOG.error("Unauthorized refresh token request. Wrong client_id or secret?");
HttpEntity errorEntity = httpResponse.getEntity();
if(errorEntity != null) {
String errorBody = EntityUtils.toString(errorEntity);
LOG.error("Response from Canvas: " + errorBody);
}
return ;
}
if(statusCode != 200) {
LOG.error("Non-200 status code ( " + statusCode + " )returned while requesting an access token at URL " + canvasUrl);
HttpEntity errorEntity = httpResponse.getEntity();
if(errorEntity != null) {
String errorBody = EntityUtils.toString(errorEntity);
LOG.error("Response from Canvas: " + errorBody);
}
return ;
}
update: I had a small bug in the code. The above code is now correct with the latest version of basiclti-util .