I have been attempting to send a webhook to IFTTT. Sending it works well enough, but when it gets there it appears that there is no JSON payload. I used https://webhook.site to inspect the payload that Plex was sending and found that the header identifies the payload content-type as multipart/form-data instead of application/json, which inhibits the ability of IFTTT and other platforms to make assumptions about the data that is to follow, and thereby diminishes the richness of the payload. That is, I canât parse the JSON.
Is there a reason that the JSON payload is not identified as application/json? Could it be?
Iâve run into this too. The plex webhook documentation is entirely inadequate. Maybe it just hasnât been updated in two years, I donât know. Iâve found posts all over the place about people trying to figure out why plex webhooks donât work and itâs always because the requests are not actually json, theyâre form-data. No standard webhook receiver in existence expects a multipart/form-data request. Thereâs no mention of this on the docs and Iâve been unable to figure out a way to disable this.
The first part is the JSON payload and it is identified as such. The second part is an image, which is also identified as such.
I agree that the documentation could be better here, but the payloads are what they are. Itâs completely legitimate to encapsulate multiple parts in a payload.
Itâs not even difficult to find reports right here on the plex forums. Plex employees never seem to respond to these though, which I can only assume means they know thereâs a problem and they arenât going to address it.
I didnât say it wasnât actually form-data. Thereâs not technically anything wrong with the webhook request. The problem is that a multipart/form-data request doesnât work with IFTTT, trakt, or basically any other standard webhook receiver because they all expect application/json. They made this change, didnât document it, didnât announce it (not that I could find), didnât add a switch to only send application/json, and thus broke webhooks all over the place and left it to users to individually spend hours debugging what happened and then basically ignore all requests for help/explanation.
As I said, I agree that the documentation could be better. However, the examples they provide here use multer specifically to handle multi-part form data. This article hasnât changed in over three years; the most recent change to the Github repos referenced were over three years ago (with two of the projects not being changed in 5 and 6 years.
Itâs been known for years that multi-part form data needed to be considered when handling Plexâs web hook events, or at least it should have been. A naive implementation on a third-partyâs part doesnât necessarily imply a failure on Plexâs.
examples they provide here use multer specifically to handle multi-part form data
Granted, as long as youâre familiar enough with JS to just know what multer is (I didnât until you mentioned it) and notice the two lines of code referencing it, then yes, itâs completely obvious that theyâre sending multipart/form-data.
Itâs been known for years ⊠or at least it should have been.
How? This is the actual problem. You can call code that expects a webhook request to be JSON naive (and youâre not wrong), basically call people ignorant (paraphrasing - âthe docs could be better, but people should just know thisâ), but that doesnât fix the documentation thatâs been lying to people for âover three yearsâ.
As stated above, the payload is sent in JSON format inside a multipart HTTP POST request. For the media.play and media.rate events, a second part of the POST request contains a JPEG thumbnail for the media.
You canât use application/json when the body also contains an image. It has to be multipart/form-data.
Side note: The support article from 2018 also said it is multipart data.
Good grief. Iâve read that page a number of times now and missed that every time. Thatâs totally on me - @pshanew (and everyone, really) I apologize for my attitude.
So, trying to read more carefully now, is it true that, at least right now, media.play and media.rate are the only events that are multipart? I suppose the wise course of action is to assume any event could be either json or form-data and handle accordingly.
As background, I was trying to hook plex into argo events. Their webhook event source apparently only supports application/json and I was unfortunately testing by just playing media - no other events happened to fire while I had the receiver running. So it looked like nothing was working. Switching on debug logs on the receiver led me to the json parse failure and then my annoyance with plex.
Youâre right - thereâs nothing technically wrong about what theyâre doing. However, that doesnât mean itâs the best way, or the way thatâs right for the customer. Once I figured out what was going on, I spent hours looking for a platform that would accept form-data in the webhook request - Iâve found none. My solution is going to be to implement tautulli, which is fine. It also comes with some other features that would be nice to have that wonât require me to parse the JSON on the receiving end.
All Iâm saying is that a toggle would let Plex play nice with all of the great services available to us, and an update to the documentation to call this out in a more obvious way would be welcome.
Yes, indeed. The webhooks functionality pushed me over the edge to deciding to adopt it. It would be nice if Plex put just a bit of effort into making this more adaptable, but câest la vie.
Ok. I didnât want to set up Tautulli (I might someday, but not right now) and I couldnât find anything simple that already did this so I fixed my own problem. This is a dead-simple proxy that accepts either multipart/form-data or application/json requests from Plex. For the multipart requests, it throws the thumb on the floor and forwards the payload. For JSON requests, it just forwards them. Working like a charm so far.
Nice! I set up tautulli and it was a piece of cake. Especially if using IFTTT, it allows me to use the free tier instead of the paid tiers (needed to parse JSON). Kudos to you though for fixing this problem. This would definitely work for the original and intended use case, so you get the Solution award. Cheers m8!