Getting Started with Figma Webhooks
3 min readWebhooks offer a first-class way to react to changes in Figma. In this article, we'll build a small service in Node to listen for these events.
Start by creating a simple server that parses JSON using express:
1const express = require('express')2const bodyParser = require('body-parser')34const PORT = 30005const app = express()67app.use(bodyParser.json())89app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`))
Webhooks require a public endpoint that Figma can ping to let us know when an event has happened. You will most likely use this in a server or CI tool, but today we’ll be testing locally using the wonderful ngrok package. This package allows us to point our local server to a public address easily:
1const express = require('express')2const bodyParser = require('body-parser')3const ngrok = require('ngrok')45const PORT = 30006const app = express()78app.use(bodyParser.json())910app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`))1112ngrok.connect(PORT).then(async (endpoint) => {13 // public endpoint ready to use 🎉14})
Now that we have a public URL, we can create our webhook through Figma’s API and subscribe to any events for a team we’re on. We’ll use axios to make interacting with the API easier and the internal crypto package to create the required passcode:
1const crypto = require('crypto')2const response = await axios({3 url: 'https://api.figma.com/v2/webhooks',4 method: 'post',5 headers: {6 'X-Figma-Token': process.env.FIGMA_TOKEN,7 },8 data: {9 event_type: 'FILE_UPDATE',10 team_id: '68782045876942050',11 passcode: crypto.randomBytes(48).toString('hex'),12 endpoint,13 },14})
Note that when running our script, we expect a figma token to be available as an environment variable. This is required for authentication and can be done using a package like dotenv or set before running the Node script.
Once our webhook is created, we must respond with a 200
status code; otherwise Figma will keep trying to ping our endpoint:
1app.post('/', (request, response) => {2 const { file_name, timestamp } = request.body3 console.log(`${file_name} was updated at ${timestamp}`)4 response.sendStatus(200)5})
We now have a working Figma Webhook service 🎉
Security
Although our code is working, it’s still open to attackers. We’ll use the passcode we created previously and check whether the same passcode has been sent back to us and respond appropriately:
1const express = require('express')2const bodyParser = require('body-parser')3const ngrok = require('ngrok')4const axios = require('axios')5const crypto = require('crypto')67const PORT = 30008const app = express()9const passcode = crypto.randomBytes(48).toString('hex')1011app.use(bodyParser.json())1213app.post('/', (request, response) => {14 if (request.body.passcode === passcode) {15 const { file_name, timestamp } = request.body16 console.log(`${file_name} was updated at ${timestamp}`)17 response.sendStatus(200)18 } else {19 response.sendStatus(403)20 }21})2223app.listen(PORT, () => console.log(`🚀 Server running on port ${PORT}`))2425ngrok.connect(PORT).then(async (endpoint) => {26 const response = await axios({27 url: 'https://api.figma.com/v2/webhooks',28 method: 'post',29 headers: {30 'X-Figma-Token': process.env.FIGMA_TOKEN,31 },32 data: {33 event_type: 'FILE_UPDATE',34 team_id: '687045185276946050',35 passcode,36 endpoint,37 },38 })39 console.log(`🎣 Webhook ${response.data.id} successfully created`)40})
Conclusion
We looked at how to utilize Figma’s new webhooks to respond to changes when events happen within teams. In a future article, we’ll learn how we can use these hooks to source component images whenever a file updates using the Figma Tools library. I encourage you to play around with this new API and see if you can automate any part of your workflow!
- figma
- design
- development
- webhooks