Solution: Getting Patron Email & Discord from Patreon Webhooks (with Node/Express JS Example!)

This is what you need from the JSON for emails and Discord IDs currently. If you’re reading this, you may have been like me bumbling around inaccurate test data, abandoned documentation, and sparse resources on these forums to just give me the Patron’s frickin’ email and Discord ID already!!! So, I made the sacrifice and dinked around with $1 and subbing/unsubbing repeatedly to check the attributes and whatnot of the JSON in webhook payloads, and this is what I can tell you to do for each event emitter type. These should all work for webhook firing options for create, update, and delete.

[Event] pledges: (depreciated)
{json parse}.included[0].attributes.email;
{json parse}.included[0].attributes.social_connections.discord.user_id;

[Event] members:
{json parse}.data.attributes.email;
{json parse}.included[1].attributes.social_connections.discord.user_id;

[Event] members:pledge:
{json parse}.data.attributes.email
{json parse}.included[1].attributes.social_connections.discord.user_id

That’s great Steve, but can you also show me an example of how to actually get this data because I need an example to start my own code? Okydoky. Here’s something in node.js with express.js to get you started.

Before we start, Patreon requires your webhook to be HTTPS. I used Certbot for a Let’s Encrypt certificate and made an A record on my domain pointing to my server’s IP (where my bot runs) using something like “myapp.website.com” in the record, so my webhooks on Patreon look like myapp.website.com/webhook1 and so on. You can learn how to do Certbot on Ubuntu here. Anyway, it came out a little something like this in the end, making sure you’ve installed the proper packages (express, body-parser):

const express = require('express');
const bodyParser = require('body-parser');
const https = require('https');
const fs = require('fs');
const crypto = require('crypto');
const app = express();
const options = {
	key: fs.readFileSync('/etc/letsencrypt/live/**WEBFOLDERFORCERT**/privkey.pem'),
	cert: fs.readFileSync('/etc/letsencrypt/live/**WEBFOLDERFORCERT**/fullchain.pem'),
};
app.use('/webhook1', bodyParser.raw({ type: 'application/json' }));
app.post('/pledges', async (req, res) => {
	const hash = crypto
		.createHmac('md5', '**YOURWEBBOOKSECRETHERE**')
		.update(req.body)
		.digest('hex');
	const success = req.header('x-patreon-signature') === hash;
	if (success) {
		const payload = JSON.parse(req.body);
		const email = **SEE THE SOLUTION POST FOR PROPER PATH**
		const discord = **SEE THE SOLUTION POST FOR PROPER PATH**
		console.log(`Patron Details:\nEmail: ${email}\nDiscord: ${discord}`);
	}
	res.status(200).end();
});

EDIT: Small side note, if the user has no Discord linked it’s going to come over as null and there won’t be the right property. I don’t know if this is optimal but I just changed my constructor to a {condition} ? {true} : {false}; formula that checks the parent, so i.e., payload.included[1].attributes.social_connections.discord ? payload.included[1].attributes.social_connections.discord.user_id : null; to grab their Discord ID if it exists in the payload, otherwise, is just null.

On Patreon make sure your webhook pointing to this has the appropriate things toggled on for what you’re using the above to process.

Anyway, I had trouble finding a simple solution to all this via Google and had to patch lots of things together because I’m an amateur hobbyist that doesn’t really code but happened to find a passion project throwing me in the mix, so, I hope people out there find this helpful. Enjoy!

3 Likes

Thanks for the contrib.

2 Likes