title: Why am I getting a 403 response when using the Brightspace API?
body: <p>I'm attempting to use the <a href="https://docs.valence.desire2learn.com/reference.html" rel="nofollow noreferrer">Brightspace API</a>, but I'm getting a 403 (Forbidden) response.</p>
  
  <p>I've registered my application using the Manage Extensability (/d2l/lp/extensibility/home) page, I've generated a user ID and key from the <a href="https://apitesttool.desire2learnvalence.com/" rel="nofollow noreferrer">API Test Tool</a>. </p>
  
  <p>Using all of this, I've installed the <code>D2L.Extensibility.AuthSdk</code> NuGet package in my project. Then, in the relevant class, I've created a property for a UserContext and am initializing it in the constructor like this:</p>
  
  <pre><code>_d2LUserContext = new D2LAppContextFactory()
      .Create(OrionConfiguration.D2LApplicationId, OrionConfiguration.D2LApiKey)
      .CreateUserContext(
          "censored user id",
          "censored user key",
          new HostSpec("https", OrionConfiguration.D2LUrl.Substring(8), 443)
      );
  </code></pre>
  
  <p>Notes:</p>
  
  <ol>
  <li>The <code>.Substring(8)</code> is because D2LUrl includes the URL scheme</li>
  <li>The user id and key were generated this morning, so they have not expired yet</li>
  </ol>
  
  <p>Then, I am trying to call the API. The code for this is split up in a few methods.</p>
  
  <pre><code>private string AuthParam(string path, string method)
  {
      return _d2LUserContext
          .CreateAuthenticatedTokens($"/d2l/api/lp/1.2{path}", method)
          .Select(tuple =&gt; $"{tuple.Item1}={tuple.Item2}")
          .Aggregate((acc, p) =&gt; $"{acc}&amp;{p}");
  }
  
  public Task&lt;UserResponse&gt; CreateUser(UserRequest userRequest)
  {
      const string path = "/users";
      return _httpUtils.Post&lt;UserResponse&gt;($"{path}/?{AuthParam(path, "POST")}", userRequest);
  }
  </code></pre>
  
  <p><code>UserRequest</code> is a POC#O (Plain Old C# Object) version of <a href="https://docs.valence.desire2learn.com/res/user.html?highlight=user#User.CreateUserData" rel="nofollow noreferrer">the model the API expects</a>.</p>
  
  <p>Here is the relevant method in the <code>HttpUtils</code> class - this is a wrapper around the <code>HttpClient</code> I wrote to get rid of some of the boilerplate in other classes.</p>
  
  <pre><code>internal async Task&lt;T&gt; Post&lt;T&gt;(string route, dynamic body)
  {
      var response = await _httpClient.PostAsync(
          _baseUrl + route, 
          new StringContent(JsonConvert.SerializeObject(body), Encoding.UTF8, "application/json")
      );
  
      _logger.LogInformation($"POST request to {route}");
      _logger.LogInformation(await response.Content.ReadAsStringAsync());
      return JsonConvert.DeserializeObject&lt;T&gt;(await response.Content.ReadAsStringAsync());
  }
  </code></pre>
  
  <p>Now, putting it all together, when I try to debug these methods getting called, I set a breakpoint the line after my POST request, and we can see I get a 403
  <a href="https://i.stack.imgur.com/gAByb.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/gAByb.png" alt="403 error in debugger"></a></p>
  
  <p>I'm wondering why this is happening. The user that the key and id were generated from is a super administrator, so this is not a permissions issue.</p>