Posts tagged with webhooks

I would like to call for suggestions regarding a challenge I've been trying to solve recently involving Meta API & Webhooks. I assume this particular setting has not been addressed here before.

As one may know, to configure receiving requests from WhatsApp, Facebook, and Instagram for a Meta app you need setting up a webhook for each in the respective parts of Meta dev dashboard. This involves allowing webhooks required app-level subscriptions/permissions and providing an endpoint that you confirm by returning a verify token on a GET request to ensure it's ok to send you requests there.

In my case, I would like other people to use the app as well, so I added oath2 to get necessary permissions for user business pages on Wa, Fb or Instagram, which works well.

After that, with necessary access, you can add your or someone's page to a pre-configured webhook, so it starts accepting requests. This action can be done through a dashboard in the menu that looks similar to this depending on the platform.

On the other hand, this can be done with sending a request, specifying webhook subscription fields yourself (such as messages on the picture above).

POST /v20.0/{app-id}/subscriptions HTTP/1.1

However, this feature is only available for Facebook pages and in the request-dedicated article we can see it mentioned. Any other webhook-related requests actually allowed for WhatsApp and Instagram are only for adding a webhook to an app (the very first step described here).

Limitations:

Webhooks for Instagram is not supported. Instagram webhooks must be configured using the App Dashboard. Webhooks for WhatsApp is not supported. WhatsApp webhooks must be configured using the App Dashboard. https://developers.facebook.com/docs/graph-api/reference/v20.0/app/subscriptions

And given that, one needs to do it through dev dashboard UI which is not an acceptable solution in my case.

Therefore, I can really use some insights on how can this be solved directly or through some witty alternative to receive messages from all three platforms and being able to programmatically allow webhook page requests.

Additionally, I have been considering raising the issue with Meta directly, so it can be adjusted and would love to hear thoughts on potentially doing this.

P.S.

For those deeply interested in the issue, I found some sort of similar issue on the meta dev forum https://developers.facebook.com/community/threads/799110895741478/

Description
I've been working on processing leads through our system and encountered an issue. I've enabled webhooks on my app, subscribed to leadgen, and provided my callback redirect URL. However, whenever I create a lead, it should be sent to my server, but when I track the status, it shows "failed" with the message "webhook.delivery.rejected." I've looked in the logs of my application but the request is not entering my server at all. I'm trying to understand why this is happening and how to ensure my configuration is correct for receiving leads.

Previously, I completed the process manually by subscribing to each webhook with a seperate app, and it worked fine. Now, I want to programmatically do this using Facebook’s API and one app. Here's the request I'm using to subscribe to the webhook for leads: curl -X POST "https://graph.facebook.com/{page_id}/subscribed_apps?subscribed_fields=leadgen&access_token={page_token}" -H "Content-Type: application/json" -d '{ "override_callback_uri": "https://api-development.recrubo.app/facebook/webhooks/{organization_id}", "verify_token": "{verify_token}" }'

Debugging
Here are my debugging steps so far: I've used the Facebook sharing debugger tool with my callback URL, which returns a 200 status. You can check the results here: Debugging Results..

I've used the Lead Ads RTU Debug Tool to send a test lead to our server but it isn't arriving at my server.

Question
Is there any place to see more error logging in the developer app?

Code
The perform method calls all subsequent calls . It first fetches the user_id which is used to check what pages the user has given us access to. It then fetches the page_access_tokens for all the accessible pages. It then loops through the pages and subscribes to the webhooks.

 def perform   @user_id = get_user_id   @pages = get_page_access_tokens   @pages.each do |page|     @facebook.subscribe_to_webhook(page[:id], page[:token])     token = @facebook.get_long_lived_access_token(page[:token])     options = {       ad_account_id: @ad_account_id     }     @access_token ||= @organization.access_tokens.create!(token: token, options: options, name: 'Meta', user_id: @user_id)   end   @access_token end def get_page_access_tokens(user_id, access_token)   response = Faraday.get("#{ENV.fetch('FACEBOOK_GRAPH_API')}/#{user_id}/accounts") do |req|     req.headers['Content-Type'] = 'application/json'     req.params['access_token'] = access_token   end   raise "Unable to get page access token server responded with #{response.body} and status #{response.status}" unless response.success?   data = JSON.parse(response.body)   page_data = data['data']   page_data.map { |page| { id: page['id'], name: page['name'], token: page['access_token'] } } end def subscribe_to_webhook(page_id, page_token)   response = Faraday.post("#{ENV.fetch('FACEBOOK_GRAPH_API')}/#{page_id}/subscribed_apps?subscribed_fields=leadgen") do |req|     req.headers['Content-Type'] = 'application/json'     req.params['access_token'] = page_token     req.body = {       override_callback_uri: "#{ENV.fetch('API_URL')}/facebook/webhooks/#{@organization['id']}",       verify_token: {local_token}     }.to_json   end   raise "Unable to subscribe to leadgen webhook server responded with #{response.body} and status #{response.status}" unless response.success?   response end def get_user_id(access_token)   response = Faraday.get("#{ENV.fetch('FACEBOOK_GRAPH_API')}/me") do |req|     req.headers['Content-Type'] = 'application/json'     req.params['fields'] = 'id'     req.params['access_token'] = access_token   end   raise "Unable to get user id server responded with #{response.body} and status #{response.status}" unless response.success?   JSON.parse(response.body)['id'] end 

Edit 1

After the comment of CBroe we have looked further in to the subscription and have added validation for these subscriptions. We see the following data:

  • graph.facebook.com/v20.0{page_id}/subscribed_apps

  • graph.facebook.com/v20.0{app_id}/subscriptions

I'm implementing the WhatsApp Cloud API, one of the steps to do it it's subscribe to webhooks and verify them using three parameters: hub.mode, hub.challenge and hub.verify_token.

We have tried sending webhook tests from several sources and tools to send petitions to the API and we have also sent messages to the WhatsApp account that is being handled by the API, and in none of these tests the Hub parameters are appearing. As it's shown in the image, we are expecting the parameters are shown in a Get array.

This is how the log is looking in my Callback URL

array ( )POST GETarray ( 

This is how the log should look

array ( )POST GETarray (   'hub_mode' => 'subscribe',   'hub_challenge' => '<challenge number>',   'hub_verify_token' => '<token>', ) 

The query string and the request URI should show the hub parameters too, but it doesn't.

What are we missing?

I'm working on an api that receives notifications from the meta weebhook every time my page have changes. Currently its in test mode, I just want to test the webhook first. In the process I'm able to verify my callback link but once I want to test one of the fields nothing its send to my server. Feed field that I want to test I have a POST controller in my backend that should take care of the request and its working; How do I know that ? Because one of the only fields that sends a request it send_cart field. Send cart field There is one or two more fields that actually send a request, but 98% of them don't work. Im not sure if there an error on the Meta Graph API or I did something wrong. If anyone had this problem, or has an idea how I could solve it, it would be very helpful; because this should have been a simple project but it's taking me a week, and I'm already embarrassed. If more information its needed I'm gonna be responding all the requests. Thanks ! Below its the server code that I'm working with:

  • This is the controller:
exports.facebookWebhook = (req, res) => {   if(req.query["hub.verify_token"] === "my_token"){     res.status(200).send(req.query["hub.challenge"])   }else{     res.status(400).send({ message: "bad request" })   } } exports.facebookWebhookChanges = (req, res) => {   if (!req.body || Object.keys(req.body).length === 0) {     console.log('Received an empty request body');     res.status(400).send('Bad Request: Request body is empty');     return;   }   console.log(req.body)   res.status(200).send({ message: "Ok" }) } 
  • This is the route:
  app.get("/api/facebook/webhook/", controller.facebookWebhook);   app.post("/api/facebook/webhook/", controller.facebookWebhookChanges); 

I already read all the documentation to make sure Im doing everything good, I have read other people posts that doesnt match with my problem. I asked on facebook developer forum to.

Hello fellow developers,

I hope you're all doing well. I am currently setting up a bot (LLM agent) using WhatsApp API and a Flask application hosted on Azure.

As recommended in Azure's tutorial, I have a startup.txt with the following command

gunicorn --bind=0.0.0.0 --timeout 600 --chdir src/whatsapp_agent/whatsapp_agent run:app

which runs locally without an issue.

Once it is deployed on Azure, however, the webhook setting from WhatsApp API (Edit Whatsapp Business Account subscription) returns the following error:

The URL couldn't be validated. Callback verification failed with the following errors: curl_errno = 28; curl_error = Operation timed out after 6000 milliseconds with 0 bytes received; HTTP Status Code = 200; HTTP Message = Connection established

Did anyone run into a similar issue and managed to solve it?

Many thanks!