Trying to validate token for webhook subscription keeps returning Bad Request error

Efraim Paley 0 Reputation points
2025-11-30T13:30:00.44+00:00

I am trying to create a subscription for webhooks for my application. I created an endpoint for accepting the validationToken which I specified in the notificationUrl as can be seen below. When I run my changes locally on our server everything seems to work correctly. The validationToken is returned in Plain text with a 200 response. But when I recieve the call from Microsoft I keep getting a 415 bad Response Code and it looks like it is not even hitting our server. Can anyone help guide me on what the issue is? Attached below are screenshots showing it working when I call my server locally from postman along with my code and the request body I am passing through for the subscriptions call. Any help would be very greatly appreciated!

Call for subscriptions in PostmanUser's image

Response in our logsUser's image

Example of it working when I call my endpoint locallyUser's image

Developer technologies | ASP.NET | Other
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Raymond Huynh (WICLOUD CORPORATION) 3,645 Reputation points Microsoft External Staff Moderator
    2025-12-01T11:00:07.19+00:00

    Hello Efraim Paley,

    Thanks for sharing the contexts. The 415 error happens because Microsoft Graph expects the validation token as plain text, but your endpoint is returning JSON.

    When Microsoft Graph creates a subscription, it first validates your endpoint by sending a POST request with a validationToken query parameter. Your endpoint must return that exact token as plain text, not wrapped in JSON.

    Most ASP.NET Core implementations use Ok() which returns JSON by default:

    return Ok(validationToken);  // Returns: {"validationToken":"abc123..."}
    
    

    Microsoft Graph sees the JSON and rejects it with a 415 error.

    My recommendations:

    Return plain text instead:

    return Content(validationToken, "text/plain");  // Returns: abc123...
    

    Verify before creating your subscription:

    Test your endpoint manually:

    curl "https://your-endpoint/api/webhook?validationToken=test123"
    

    Correct response: test123 (plain text)  

    Wrong response: {"validationToken":"test123"} (JSON)

     

    Here's my complete controller handling both validation and notifications:

    [HttpPost]
    public async Task<IActionResult> HandleWebhook([FromQuery] string? validationToken)
    {
        // Validation phase
        if (!string.IsNullOrEmpty(validationToken))
        {
            return Content(validationToken, "text/plain");
        }
        // Notification phase
        using var reader = new StreamReader(Request.Body);
        var requestBody = await reader.ReadToEndAsync();
        var notifications = JsonSerializer.Deserialize<ChangeNotificationCollection>(
            requestBody, 
            new JsonSerializerOptions { PropertyNameCaseInsensitive = true });
        // Process notifications...
        return Accepted();
    }
    

    Here is my screenshot showing successful subscription creation.

    User's image

    Hope this helps!

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.