Send email from Figma without treating a design file like an email client. The reliable approach is to use a Figma webhook as the trigger, receive that webhook at a server endpoint you control, then make a server-side call to Volanea’s REST API.
There is an important limitation up front: Volanea does not provide a native Figma app, marketplace listing, or installable Figma plugin for sending email. That is not a blocker. Figma has an outbound webhook capability in its REST API, and that is the right integration point for an automation that sends release notifications, design-review updates, library-publication alerts, or internal handoff emails.
This guide uses Figma’s FILE_UPDATE webhook event because its payload is compact and predictable. The concrete Figma trigger is a file becoming inactive after edits: Figma documents FILE_UPDATE as firing within 30 minutes of editing inactivity in a file. If your workflow needs a more intentional release signal, Figma also supports FILE_VERSION_UPDATE, which fires when someone creates a named version in a file’s version history. The same server architecture applies to either event.
What the Figma-to-email integration actually does
The integration has three distinct responsibilities:
- Figma detects an event in a file, folder, or team context and sends an HTTP POST to your endpoint.
- Your endpoint verifies and normalizes the event, decides whether it deserves an email, and protects against duplicate processing.
- Your server calls Volanea with a transactional message request using an API key stored only in server-side secrets.
That separation matters. Figma’s webhook is an event notification, not an email composition form. Its FILE_UPDATE payload tells you that a particular file changed; it does not contain a recipient email address, an approved subject line, HTML content, or a Volanea credential. Your server supplies those values from configuration and business rules.
For example, an internal design system team could use this flow:
- A designer finishes edits to the shared component-library file.
- Thirty minutes after editing stops, Figma posts a
FILE_UPDATEevent. - The receiver checks that this is the monitored file and that the request has Figma’s expected passcode.
- The receiver sends a “Design system file updated” email to a configured review group.
- The email includes the Figma file name, file key, update timestamp, and a direct link assembled from the file key.
This is deliberately different from sending an email on every canvas change. A design file can receive many small edits. The webhook event’s inactivity behavior gives you a natural batching window, while the receiver can still add stronger workflow rules before it sends anything.
The real Figma trigger: FILE_UPDATE
To send email from Figma reliably, choose an event whose behavior matches the message you want recipients to receive. For an update digest or review notification, FILE_UPDATE is a useful baseline.
Figma documents this trigger as follows in practical terms: when someone edits a file and editing then remains inactive, Figma sends the event within 30 minutes. This means it is not a real-time “every keystroke” signal and should not be used for urgent approval workflows, incident notifications, or a promise that a message will arrive at an exact minute.
The payload Figma sends
A FILE_UPDATE webhook POST has this documented shape:
{
"event_type": "FILE_UPDATE",
"file_key": "CL06nJNn5eZLQKDoARMND5",
"file_name": "Developer page mockup demo",
"passcode": "secretpasscode",
"timestamp": "2020-02-23T20:27:16Z",
"webhook_id": "22"
}
The field mapping for the email is intentionally straightforward:
| Figma field | How the receiver uses it | Volanea email field |
|---|---|---|
file_name | Human-readable design name | Part of content.subject and content.html |
file_key | Stable identifier for a Figma file | Part of the link and content.html |
timestamp | Time Figma says the event occurred | Part of content.text and content.html |
webhook_id | Identifier of the webhook subscription | Part of the idempotency key |
event_type | Ensures the handler is processing the intended event | Validation only |
passcode | Shared value used to reject untrusted requests | Validation only; never put in email |
Notice what is absent: a recipient address. That is expected. A Figma design event should not decide who receives a production email merely because a field happened to exist in an incoming request. Keep recipients in server-side configuration, a database-backed routing rule, or a controlled release workflow.
When to choose FILE_VERSION_UPDATE instead
A file update is useful when the message means “the design changed.” But a named version is usually better when the message means “this is ready for review,” “this is the approved handoff,” or “this release is ready to announce.”
Use FILE_VERSION_UPDATE when your designers are willing to make creating a named version the explicit operational action that starts the notification. It reduces noise because every ordinary edit does not become a release email. It also makes ownership clear: the person who creates the named version is consciously advancing the workflow.
Do not rely on a file name alone as a routing rule. File names are editable and frequently duplicated. Use the Figma file_key as the stable allowlist value, then render the file name only as reader-friendly context.
Architecture: why the server sits between Figma and Volanea
It may seem tempting to point a Figma webhook at an endpoint that immediately forwards the request to an email API. In practice, that endpoint needs to do meaningful work, so treat it as a small integration service rather than a dumb relay.
Your receiver should perform these actions in order:
- Parse the JSON body.
- Verify the event is a supported event type.
- Compare the incoming Figma
passcodewith a secret stored on the server. - Verify the file key is in an allowlist or belongs to an allowed workflow.
- Create a deterministic idempotency key.
- Send the Volanea request with that idempotency key.
- Log the accepted response and any recipient skip information.
- Return a quick successful HTTP response once processing is safely complete or durably queued.
This architecture gives you two security boundaries. The first is between Figma and your webhook endpoint, where you validate the Figma passcode. The second is between your server and Volanea, where your server authenticates with its Volanea API key.
It also gives you a useful policy boundary. You can decide that only a production design-system file sends email, that a staging file only emails a test inbox, or that updates outside business hours are stored for a daily digest rather than sent immediately.
Create the webhook through Figma’s API
Figma webhooks are not configured through a standard in-product webhook screen. Figma documents webhook creation, modification, listing, and deletion through the Webhooks API. Creating a webhook is a POST request to /v2/webhooks, and the request includes an event type, a context, the context ID, your HTTPS endpoint, and a passcode.
For a file-specific integration, the context is file and the context_id is the Figma file key. For a wider integration, Figma also supports team and folder contexts. Folder context is still represented as project in the webhook API terminology, even though Figma now uses the word “folder” in much of its product documentation.
The webhook setup request needs Figma API authentication with the relevant webhook scope. For organization-level automation, use an appropriately governed Figma OAuth app or plan access token where available, rather than building the integration around a departing employee’s personal token. Keep the Figma credential used to create and administer the webhook in your deployment secret store too.
When Figma creates a webhook, it sends a PING event by default so you can confirm that your endpoint is reachable. Your receiver must recognize this event and return success after verifying the passcode. Do not send an email for a PING request.
Keep webhook setup separate from email sending
Webhook registration is administration. Email sending is runtime processing. They have different credentials, different failure modes, and different access requirements.
A clean deployment normally has:
- a one-time or CI-managed webhook registration task;
- a public HTTPS webhook receiver;
- server-side secret storage for
FIGMA_WEBHOOK_PASSCODE; - server-side secret storage for
VOLANEA_API_KEY; - application configuration for the sender and recipient group.
Avoid putting webhook-registration logic into a browser application or a Figma plugin UI. A browser-visible configuration can expose a Figma token, the Volanea key, or both. It also makes lifecycle management difficult when team members change roles.
Working webhook receiver and Volanea REST API call
The following Node.js example is an Express receiver for the documented FILE_UPDATE payload. It verifies the Figma passcode, rejects unapproved files, creates a stable idempotency key from the webhook event, then sends an email using Volanea’s POST /v1/send endpoint.
The Volanea request maps Figma fields directly into Volanea’s inline content object. The sender and recipient are server configuration, not Figma-supplied values.
import crypto from "node:crypto";
import express from "express";
const app = express();
app.use(express.json({ limit: "100kb" }));
const {
FIGMA_WEBHOOK_PASSCODE,
VOLANEA_API_KEY,
VOLANEA_FROM,
DESIGN_RELEASE_RECIPIENT,
FIGMA_ALLOWED_FILE_KEY
} = process.env;
function sameSecret(received, expected) {
if (typeof received !== "string" || typeof expected !== "string") {
return false;
}
const receivedBuffer = Buffer.from(received);
const expectedBuffer = Buffer.from(expected);
return receivedBuffer.length === expectedBuffer.length &&
crypto.timingSafeEqual(receivedBuffer, expectedBuffer);
}
function escapeHtml(value) {
return String(value)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">")
.replaceAll('"', """)
.replaceAll("'", "'");
}
app.post("/webhooks/figma", async (req, res) => {
const event = req.body;
// Figma sends a PING after webhook creation by default.
if (!sameSecret(event.passcode, FIGMA_WEBHOOK_PASSCODE)) {
return res.status(400).json({ error: "Invalid Figma webhook passcode" });
}
if (event.event_type === "PING") {
return res.status(204).end();
}
// This guide configures the webhook for FILE_UPDATE.
if (event.event_type !== "FILE_UPDATE") {
return res.status(202).json({ ignored: "Unsupported event type" });
}
// Required FILE_UPDATE payload fields.
if (!event.file_key || !event.file_name || !event.timestamp || !event.webhook_id) {
return res.status(400).json({ error: "Incomplete FILE_UPDATE payload" });
}
// Never let an arbitrary Figma file generate email.
if (event.file_key !== FIGMA_ALLOWED_FILE_KEY) {
return res.status(202).json({ ignored: "File is not allowlisted" });
}
const figmaFileUrl = `https://www.figma.com/design/${encodeURIComponent(event.file_key)}`;
// Same webhook + event type + timestamp = same email intent on retries.
const idempotencyKey = [
"figma",
event.webhook_id,
event.event_type,
event.file_key,
event.timestamp
].join(":");
const subject = `Figma file updated: ${event.file_name}`;
const text = [
`The Figma file "${event.file_name}" was updated.`,
`File key: ${event.file_key}`,
`Event time: ${event.timestamp}`,
`Open the file: ${figmaFileUrl}`
].join("\n");
const html = `
<h1>Figma file updated</h1>
<p><strong>${escapeHtml(event.file_name)}</strong> was updated.</p>
<ul>
<li><strong>File key:</strong> ${escapeHtml(event.file_key)}</li>
<li><strong>Event time:</strong> ${escapeHtml(event.timestamp)}</li>
</ul>
<p><a href="${figmaFileUrl}">Open the Figma file</a></p>
`;
const volaneaResponse = await fetch("https://api.volanea.com/v1/send", {
method: "POST",
headers: {
"Authorization": `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": idempotencyKey
},
body: JSON.stringify({
from: VOLANEA_FROM,
to: DESIGN_RELEASE_RECIPIENT,
content: {
subject,
text,
html
}
})
});
const responseBody = await volaneaResponse.json().catch(() => null);
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
responseBody,
webhookId: event.webhook_id,
fileKey: event.file_key
});
return res.status(502).json({ error: "Volanea did not accept the email" });
}
console.info("Figma email accepted by Volanea", {
webhookId: event.webhook_id,
fileKey: event.file_key,
idempotencyKey,
responseBody
});
return res.status(202).json({ accepted: true });
});
app.listen(process.env.PORT || 3000);
The code deliberately uses the Idempotency-Key header. A webhook integration must assume that a sender might not know whether your endpoint finished processing a prior request. A duplicate HTTP delivery, an application restart, or a timeout that occurs after Volanea accepts the message can otherwise create duplicate design-update emails.
The Volanea API key is read from process.env.VOLANEA_API_KEY. The same pattern applies if you deploy to a serverless function, container platform, worker runtime, or dedicated integration service: use the platform’s encrypted server-side secret mechanism, not a checked-in .env file and never a client bundle.
For a fuller list of send fields, templates, response handling, and setup guidance, use the Volanea API reference and setup guides.
Where the Volanea API key belongs
The Volanea API key does not belong in Figma. Figma webhooks send an HTTP callback to your endpoint; they are not a place to configure outbound headers for a second API call to Volanea.
The right location is the secret store attached to the runtime that receives the webhook. Examples include encrypted environment variables in your hosting platform, a cloud secret manager, or a managed function’s secret configuration. The receiver reads the key at runtime and sends it in the server-to-server request to Volanea.
Why client-visible configuration is unsafe
Do not put the Volanea key in any of these locations:
- a Figma file, component description, variable, prototype, or annotation;
- a Figma plugin’s visible UI or browser-side JavaScript bundle;
- a static website’s public environment variable convention;
- a webhook URL query string;
- source code committed to a repository;
- logs, screenshots, email bodies, or support tickets.
An email API key authorizes sending. If exposed, it can be abused to send unauthorized mail from your account, harm domain reputation, consume sending capacity, or expose operational metadata. Rotating the secret after an exposure is necessary, but prevention is better: make it impossible for clients and Figma collaborators to read the credential in the first place.
Keep the Figma webhook passcode separately from the Volanea API key. The passcode validates the incoming Figma event at your receiver. It does not authenticate the Volanea send request and should never be reused as the Volanea credential.
Design the email policy, not just the API call
A technically successful integration can still create a poor workflow if every edit creates an unhelpful message. Before enabling a production route, decide what one email means.
For a FILE_UPDATE event, a good policy is often: “Notify the review list once the designated file has been inactive after edits, provided that the file is allowlisted and the event has not already been processed.” This works for teams that want awareness without requiring a formal release step.
For FILE_VERSION_UPDATE, a better policy might be: “Notify product, engineering, and QA only when a design owner creates a named version in the production file.” That creates an intentional handoff signal.
Useful email content
Keep the message short and action-oriented. Recipients usually need four things:
- the file name;
- what happened;
- when it happened;
- a direct path to inspect the work.
You can also include an internal release owner, sprint reference, or release notes if your server can obtain those values from an approved system of record. Do not assume that Figma’s base FILE_UPDATE payload contains them. Fetch supplementary information only when you need it, and account for the extra latency and API permissions that introduces.
Avoid embedding the entire Figma document structure in email. It produces oversized, hard-to-read messages and can expose design details to a wider recipient group than intended. Link to the file and let Figma remain the collaboration surface.
When this breaks: Figma webhook failure modes
A production integration needs an answer for failure before it has one. The Figma-to-Volanea hop has specific breakpoints that are easy to miss in a first implementation.
A retry or uncertain delivery creates duplicate emails
A webhook sender may retry after a network failure, a non-successful response, or uncertainty about whether the receiver completed its work. The receiver may also crash after Volanea accepted the send but before it returned success to Figma. If the next attempt blindly sends again, people receive duplicate release notifications.
Use a deterministic idempotency key built from fields that identify one event intent. In the example, that is webhook_id, event_type, file_key, and timestamp. Reuse the exact same key if the same event is processed again. Do not generate a random UUID for every attempt; that defeats deduplication.
For stricter guarantees, store processed event keys in a durable database before or alongside the Volanea request. This is especially useful if you need to branch into multiple sends, update an internal release record, or tolerate application redeployments. A database record also gives your support team a human-readable audit trail.
The webhook receiver times out or does too much synchronous work
Webhook endpoints should respond quickly. Slow database queries, Figma API fetches, image rendering, large template builds, or waiting for external systems can cause timeout behavior and uncertain delivery outcomes.
The safest pattern is to validate the event, persist a compact job record keyed by the event identity, return a success response, and have a background worker send the email. If you choose that architecture, the worker must use the same idempotency key. Returning success before work is durable is unsafe because the event can be lost if the process stops immediately afterward.
For low-volume notifications, the direct receiver shown above is reasonable if the Volanea call is fast and your runtime is dependable. For high-value release workflows, queueing is the better default.
Payload fields are absent because you changed event types or assumptions
Do not write one generic handler that assumes every Figma event has every field your favorite event type provides. Webhook payload fields vary by event. FILE_UPDATE has a compact file-oriented payload; other events may contain different objects or event-specific data.
Validate required fields per event type. In the example, file_key, file_name, timestamp, and webhook_id are required before an email is composed. If a field is missing, log the event type and webhook ID, return an intentional error or safe ignore response according to your retry policy, and never substitute undefined into a recipient, subject line, or URL.
Plan and permission differences can also change what your integration can observe or manage. Figma documents webhook limits by context and plan, and team-level webhooks do not notify for files in invite-only folders. Test with the actual plan, team, folder visibility, and file permissions that production uses. A webhook that works against a personally owned test file may not observe a restricted production file.
The PING event accidentally sends a real message
Figma sends a PING event by default when a webhook is created. Treat it as connectivity validation only. If you route every event directly into your email composition function without checking event_type, a setup test turns into a misleading production alert.
Make PING handling explicit and test it first. Return a successful response, write a minimal log entry, and send no email.
Volanea accepts the request, but not every recipient receives a message
A successful API response means the platform accepted and processed the send request; it is not the same as a guarantee that every message reached an inbox. A recipient may be suppressed, unsubscribed, invalid, or skipped under account-level sending conditions.
Log the Volanea response body and inspect per-recipient outcomes when relevant. For recipient lists that change frequently, verify addresses before adding them to operational notifications. Volanea’s email address verification tool can help screen an address before it enters a routing list, but it should complement—not replace—suppression handling and recipient-consent rules.
Testing the integration safely
Test this integration as an event pipeline, not merely as an HTTP request. Your test plan should cover the Figma event, your receiver, Volanea acceptance, and the final observable email outcome.
Start with a test Figma file and a mailbox owned by your team. Create the webhook against the test file, allow the initial PING, then make a harmless edit and wait for the FILE_UPDATE window. Confirm that your logs show the received payload, the idempotency key, the Volanea response, and exactly one email.
Then run these scenarios:
- Send the same captured
FILE_UPDATEpayload twice and confirm only one email is created for the same idempotency key. - Change the
passcodein a captured payload and confirm the endpoint rejects it without calling Volanea. - Send a
PINGpayload and confirm no email is sent. - Use a non-allowlisted
file_keyand confirm the event is safely ignored. - Temporarily make the Volanea request fail and confirm your receiver exposes the failure rather than pretending the notification succeeded.
- Test an event with a missing required field and confirm the error is visible in logs without leaking secret values.
Keep captured payloads out of public issue trackers if they reveal confidential file names or keys. Redact secrets before sharing diagnostic logs, and preserve only the minimum metadata your team needs for debugging.
Operational improvements for larger Figma workflows
Once the basic path works, improve it based on the kind of design operation you are running.
Add a routing table
A single environment variable recipient is enough for one file. It becomes hard to manage when several product areas have separate owners. A small routing table keyed by file_key lets you define different recipients, sender names, subject prefixes, and notification policies per design file.
For example, one file can notify design-system-review@example.com, another can notify a product squad, and a third can be configured as silent. Keep that table in a controlled database or configuration service, not in the Figma file name.
Add quiet hours and digests
A file update after inactivity can happen at inconvenient times. Instead of sending immediately, store event records during quiet hours and send a daily digest with the latest update for each file. Deduplicate at the file level for the digest window, while preserving enough event history for auditability.
This approach reduces inbox noise without losing the signal that work moved forward. It also makes the email more useful for stakeholders who care about a summary rather than every editing session.
Separate notification state from delivery state
Record at least two states: “Figma event received” and “Volanea send accepted.” If the message is operationally important, track a third state from email events such as delivered, bounced, or complained.
This distinction prevents a common reporting mistake: treating a successful webhook response as an inbox delivery confirmation. The webhook confirms an event left Figma. The Volanea send response confirms acceptance for processing. Delivery status is a later email-lifecycle outcome.
Figma webhooks versus a native plugin or automation connector
A Figma webhook is the best direct route when your event is about file activity, versions, comments, or other documented Figma REST API events. It is server-to-server, does not require every designer to install a plugin, and lets you retain control over authorization, routing, and email content.
A native plugin would be a different product model. Plugins can add interactive actions inside Figma, but they require development, distribution, and user interaction. Volanea does not ship a native Figma plugin, so there is no marketplace installation flow to follow here.
An automation platform can still be useful if your team does not operate a server endpoint. However, choose it only after confirming that its Figma trigger supports the specific event you need and that it can store the Volanea credential as a secret. For release-critical notifications, a small owned endpoint is usually easier to audit because the complete field mapping, validation logic, and idempotency policy live in code you control.
Conclusion
The dependable way to send email from Figma with Volanea is not a client-side shortcut. It is a webhook integration: Figma emits a documented file event, your server validates and deduplicates it, and Volanea sends the resulting transactional message through its REST API.
Start with one allowlisted test file and the FILE_UPDATE event. Keep the Volanea API key only in server-side secrets, validate Figma’s passcode before doing work, and use a deterministic idempotency key for every email intent. When your team is ready for a more deliberate handoff signal, move the workflow to FILE_VERSION_UPDATE so a named version—not ordinary editing activity—starts the notification.
FAQ
Can I install a Volanea plugin from the Figma marketplace?
No. Volanea does not provide a native Figma app, marketplace listing, or installable Figma plugin for email sending. Use Figma’s REST API webhooks and a server-side integration endpoint instead.
What starts the email in this setup?
In the main example, Figma’s FILE_UPDATE event starts the flow. It triggers within 30 minutes of editing inactivity in a file. For a more intentional release workflow, use FILE_VERSION_UPDATE, which triggers when a user creates a named version in the file history.
Can I put the Volanea API key in Figma?
No. Store the key only in the secret manager or encrypted environment configuration of the server that receives the Figma webhook. Figma should only notify your endpoint; your endpoint should make the authenticated Volanea request.
Why did two identical Figma update emails arrive?
Treat webhook delivery as potentially repeatable. A retry or uncertain response can cause the same event to reach your endpoint more than once. Send Volanea the same deterministic Idempotency-Key for the same Figma event and, for important workflows, keep a durable processed-event record.
Does a successful Volanea API response prove the email reached the inbox?
No. It confirms that Volanea accepted the send request for processing. Monitor email lifecycle events and recipient-specific outcomes when delivery confirmation matters.