2

I have been working on subscriptions to notify my application whenever I receive an email. In order to activate the Subscription, I send a POST request to https://graph.microsoft.com/v1.0/subscriptions. Whenever I send a request I received the following error (note that this works fine when tried from Graph Explorer):

response => {
    "error"=> {
        "code"=>"InvalidRequest", 
        "message"=>"Server could not process subscription creation payload.",
        "innerError"=> {
            "request-id"=>"e4a9aef5-89b0-4d9c-ac11-01e0c188ceee", 
            "date"=>"2019-11-07T13:15:50"
        }}}

Code Sample:

GRAPH_HOST = 'https://graph.microsoft.com'.freeze

def mail_noti token

    query = { 
        "changeType": "created,updated",
        "notificationUrl": "https://0d9fdb76.ngrok.io/calendar/notif_sub",
        "resource": "me/mailFolders('Inbox')/messages",
        "clientState": "secretClientValue",
        "expirationDateTime": "2019-11-08T18:23:45.9356913Z",
        "Authorization": "Bearer #{token}",
        "Accept": 'application/json'
    }

    headers = {
        Authorization: "Bearer #{token}",
        Accept: 'application/json'
    }

    endpoint = '/v1.0/subscriptions'

    binding.pry

    a =  HTTParty.post("#{GRAPH_HOST}#{endpoint}", body: query, headers: headers)
end
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63

2 Answers2

1

The body needs to be in application/json format but you're sending it as application/x-www-form-urlencoded. You need to use .to_json:

HTTParty.post("#{GRAPH_HOST}#{endpoint}",
    :body => {
        "changeType": "created,updated",
        "notificationUrl": "https://0d9fdb76.ngrok.io/calendar/notif_sub",
        "resource": "me/mailFolders('Inbox')/messages",
        "clientState": "secretClientValue",
        "expirationDateTime": "2019-11-08T18:23:45.9356913Z",
        "Authorization": "Bearer #{token}",
        "Accept": 'application/json' 
    }.to_json,
    :headers => {
        Authorization: "Bearer #{token}",
        Accept: 'application/json',
        'Content-Type' => 'application/json'
    })
Marc LaFleur
  • 31,987
  • 4
  • 37
  • 63
  • 1
    I did that already. If I do that keys are not being recognized. {"error"=> { "code"=>"InvalidRequest", "message"=>"expirationDateTime is a required property for subscription creation.", "innerError"=> { "request-id"=>"4c7557cb-82f4-46b4-9d2a-449a62422165", "date"=>"2019-11-08T06:09:18" } } } – pranav pranu Nov 08 '19 at 06:11
  • This worked for me. Adding Content-Type to headers. headers: { Authorization: "Bearer #{token}", Accept: 'application/json', 'Content-Type' => 'application/json' } – pranav pranu Nov 08 '19 at 11:30
  • reference: https://github.com/microsoftgraph/microsoft-graph-docs/issues/4092#issuecomment-477435329 I don't know why graph didn't send me the 'Content-type' header missing error in the first place. It could have saved lot of time. – pranav pranu Nov 08 '19 at 11:37
  • I've updated my answer to reflect the `Content-Type`. I expected HTTParty to automatically set the `Content-Type` based on the content but it looks like that isn't the case. – Marc LaFleur Nov 08 '19 at 16:24
-1

Final Payload structure which worked for me:

HTTParty.post("#{GRAPH_HOST}#{endpoint}", 
                    body:  {
                      expirationDateTime: "2019-11-09T18:23:45.9356913Z",
                      changeType: "created,updated",
                      resource: "me/mailFolders('Inbox')/messages",
                      notificationUrl: "https://e44e6608.ngrok.io/calendar/notif_sub",
                      clientState: "secretClientValue"
                    }.to_json, 
                    headers: {
                      Authorization: "Bearer #{token}",
                      Accept: 'application/json',
                      'Content-Type' => 'application/json'
                    }
                )

PS: Whenever there is an issue sending payload make sure you follow following steps

  • Check if your headers are proper especially 'Content-Type' & 'Authorization'(In case you are sending direct http request you must have to add 'Key': 'Authorization' & 'Value': Bearer #{token})
  • Check if you are sending 'body' key
  • Check if you are sending all the necessary keys under 'body' for that API