If you need to send transactional email from monday.com, the reliable pattern is not a native email-provider app installation. Instead, monday.com sends a webhook when a board event occurs, your small server-side endpoint reads the relevant item data, and that endpoint calls Volanea’s REST API to deliver the message.

This matters because Volanea does not currently offer a native “Send Email From Monday” app or monday.com marketplace integration. The integration described here is an honest webhook-to-API workflow: monday.com is the event source, your endpoint is the control layer, and Volanea is the email infrastructure that sends the resulting transactional message.

What you are building

The finished workflow looks like this:

  1. A row changes on a monday.com board, such as an approval status becoming Ready to send.
  2. monday.com’s Webhooks integration sends an HTTP POST request to your public endpoint.
  3. Your endpoint completes monday.com’s required challenge handshake during setup, then processes later event payloads.
  4. The endpoint uses the item ID in the webhook to retrieve the current board fields through monday.com’s GraphQL API.
  5. Your code validates the recipient, chooses whether the event should send an email, renders safe content, and calls POST https://api.volanea.com/v1/send.
  6. Volanea accepts the transactional send and applies its sending pipeline, including suppression checks, contact handling, tracking instrumentation where configured, and dispatch.

The endpoint is important. A standard monday.com webhook does not contain the full contents of every board column. It identifies the board event and the changed item. Treat the webhook as a notification that tells your service which item to fetch, rather than as a complete email payload.

This design also prevents a serious security mistake: placing a Volanea secret key directly in a webhook URL, board field, browser extension, or client-side automation configuration. Your Volanea key stays in server-side environment variables where it belongs.

Why a webhook receiver is the right integration pattern

monday.com supports board-level webhooks through its Webhooks integration in the Automations Center. You can configure a recipe for events such as creating an item or changing a column value, then provide the HTTPS URL that should receive the event.

That webhook is outbound: monday.com sends data to your service. Volanea’s email API is also server-oriented: your service sends a protected authenticated request to Volanea. The receiver sits between those systems and performs the work that neither system should guess about:

  • Decide which board events are eligible to send email.
  • Fetch the current item data rather than relying on a partial event notification.
  • Map stable monday.com column IDs to recipient, name, status, and message fields.
  • Reject malformed or unauthorized input.
  • Escape user-entered values before placing them into HTML.
  • Generate a deterministic idempotency key so webhook retries do not create duplicate messages.
  • Log a minimal audit trail without logging secrets or the entire email body.

You can use a no-code intermediary such as Make or Zapier for simple workflows, but a small endpoint is the better default for transactional email. It gives you control over secret storage, authentication, idempotency, field validation, HTML escaping, error handling, and future changes to your board structure.

For example, a project-management board may have these columns:

Board fieldExample column IDPurpose in the send
Item nameBuilt-in item nameCustomer-facing project or request name
Customer emailemailRecipient address
Customer nametextGreeting personalization
Send statusstatusThe explicit trigger gate
Due datedateTransactional context
Confirmation sentsent_atOptional audit field written back after success

Use column IDs in code, not visible column titles. Board owners can rename Customer email to Primary contact at any time; the column ID is the integration contract.

Choose a transactional event, not a broad board event

The most common early error is sending whenever any column changes. That looks convenient, but it creates accidental notifications when someone corrects a typo, reassigns an owner, or changes a deadline.

Instead, define an explicit send state. A good example is:

When the Send status column changes to Ready to send, send one confirmation email.

That state transition makes the workflow understandable to the operations team and deterministic for your code. It also gives you a clear test procedure: create an internal test item, fill in a mailbox you control, change the status to the send state, and inspect both the endpoint logs and the received email.

A practical event policy can be:

  • Event type: change_column_value or the status-specific webhook recipe.
  • Trigger column: the one column deliberately used to authorize sending.
  • Allowed status label: Ready to send.
  • Recipient source: a dedicated Email column, never the item name or an unvalidated free-text note.
  • Duplicate rule: one message per item and send status transition.
  • Write-back policy: after Volanea accepts the request, update a sent timestamp or sent status on the item.

Do not treat an email address in a long-text column as equivalent to an Email column. Free-text fields regularly contain multiple addresses, pasted notes, invalid punctuation, or private data that was never meant to be used as a recipient.

Before enabling a production workflow, verify addresses with a validation step. For one-off QA checks and support investigations, Volanea’s email address verification tool can help identify malformed or risky addresses before you turn a board change into an outbound message.

Create the monday.com webhook

In the relevant monday.com board, open the Automations Center, go to the Integrations area, search for Webhooks, choose the recipe that matches your event, and enter your endpoint URL. Your endpoint must be publicly reachable over HTTPS.

For this guide, use an endpoint such as:

https://automation.example.com/webhooks/monday/send-email

Do not point monday.com directly at https://api.volanea.com/v1/send. That would fail for several reasons:

  1. monday.com first sends a verification challenge, but the Volanea send endpoint is not a webhook challenge responder.
  2. The monday.com event format is not a Volanea email-send request.
  3. You would have no safe place to hold the Volanea secret key.
  4. You would be unable to fetch current item data, validate recipients, or set a deterministic idempotency key.

Handle the verification challenge

When you create the webhook, monday.com sends a JSON POST body with a challenge field. Your service must return that same value in a JSON body.

The request resembles this:

{
  "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"
}

Your response must be:

{
  "challenge": "3eZbrw1aBm2rZgRNFdxV2595E9CY3gmdALWMmHkvFXO7tYXAYM8P"
}

This handshake verifies that you control the destination URL. It is not a substitute for authorization in your application. If you create webhooks as part of a monday integration app, monday.com can include a JWT in the Authorization header that your endpoint can verify using the app signing secret. For no-code board webhooks and personal-token-created webhooks, do not assume a JWT will be present. In those cases, use a private, unguessable endpoint path, restrict access at your edge where possible, validate the payload carefully, and avoid doing unsafe work based solely on uncontrolled input.

Understand the monday.com webhook payload

Every board webhook event is wrapped in an event object. The exact fields depend on the recipe and event type, but a column-change notification has the following shape:

{
  "event": {
    "app": "monday",
    "type": "change_column_value",
    "triggerTime": "2026-08-23T15:42:18.006Z",
    "subscriptionId": 12345678,
    "userId": 98765432,
    "originalTriggerUuid": null,
    "boardId": 1234567890,
    "groupId": "new_requests",
    "pulseId": 1234567891,
    "pulseName": "Website design request",
    "columnId": "status",
    "columnType": "color",
    "columnTitle": "Send status",
    "value": {
      "label": {
        "text": "Ready to send"
      }
    },
    "previousValue": null,
    "changedAt": 1787499738.006
  }
}

The values above are examples, but the wrapper and event-oriented structure are the important part. For item events, pulseId identifies the monday.com item. Some current API references also use item terminology, so think of pulseId here as the item ID you will use to retrieve the item.

Notice what the event does not promise: a complete set of current item column values. You may receive information about the changed status column, but not the recipient address, customer name, due date, or other values required to compose the email. Fetch the item after receiving the notification.

Why fetch the item after receiving the event

A separate read has two advantages. First, it gives you one predictable mapping layer for every event type. Second, it avoids relying on an older or incomplete value embedded in a notification.

There is one trade-off: a user could change the recipient immediately after the send status changes. For high-consequence messages, store an immutable recipient snapshot before changing the send status, or use an approval workflow where only a controlled automation can mark an item ready. For ordinary confirmations, fetching the current record is usually the appropriate operational choice.

Set up the required secrets and configuration

Your service needs two credentials and a few stable identifiers:

MONDAY_API_TOKEN=your_monday_api_token
VOLANEA_API_KEY=sk_your_volanea_secret_key
VOLANEA_FROM="Operations <updates@yourdomain.example>"
MONDAY_EMAIL_COLUMN_ID=email
MONDAY_NAME_COLUMN_ID=text
MONDAY_STATUS_COLUMN_ID=status
MONDAY_READY_LABEL="Ready to send"

Use a verified sending identity for VOLANEA_FROM. An arbitrary From address is not a deliverability strategy. Authenticate the sending domain and use a sender mailbox or role address that recipients recognize and can reply to when appropriate.

Keep these values in your deployment platform’s secret manager or encrypted environment configuration. Never put them in a monday.com board column, item update, browser JavaScript bundle, public Git repository, or webhook query string.

If you need the exact API fields, request examples, sender setup steps, and endpoint behavior, use the Volanea API reference and setup guides. The rest of this article focuses on the integration boundary between the board webhook and that sending API.

Working Node.js webhook-to-Volanea example

The example below uses Express and Node.js 18 or later. It performs the monday.com challenge response, accepts a column-change event, checks that the intended status changed, fetches the item through monday.com’s GraphQL API, validates the email address, escapes HTML, and sends through Volanea.

Install Express:

npm install express

Create server.mjs:

import express from "express";
import crypto from "node:crypto";

const app = express();
app.use(express.json({ limit: "256kb" }));

const {
  MONDAY_API_TOKEN,
  VOLANEA_API_KEY,
  VOLANEA_FROM,
  MONDAY_EMAIL_COLUMN_ID = "email",
  MONDAY_NAME_COLUMN_ID = "text",
  MONDAY_STATUS_COLUMN_ID = "status",
  MONDAY_READY_LABEL = "Ready to send"
} = process.env;

for (const [name, value] of Object.entries({
  MONDAY_API_TOKEN,
  VOLANEA_API_KEY,
  VOLANEA_FROM
})) {
  if (!value) throw new Error(`Missing required environment variable: ${name}`);
}

function getColumnText(item, columnId) {
  return item.column_values.find((column) => column.id === columnId)?.text?.trim() || "";
}

function escapeHtml(value) {
  return String(value)
    .replaceAll("&", "&amp;")
    .replaceAll("<", "&lt;")
    .replaceAll(">", "&gt;")
    .replaceAll('"', "&quot;")
    .replaceAll("'", "&#039;");
}

function isSingleEmail(value) {
  // Deliberately basic: use a dedicated monday Email column and reject obvious bad input.
  return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}

async function getMondayItem(itemId) {
  const query = `
    query ($itemIds: [ID!]) {
      items(ids: $itemIds) {
        id
        name
        column_values {
          id
          text
          value
        }
      }
    }
  `;

  const response = await fetch("https://api.monday.com/v2", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      "Authorization": MONDAY_API_TOKEN
    },
    body: JSON.stringify({ query, variables: { itemIds: [String(itemId)] } })
  });

  const result = await response.json();
  if (!response.ok || result.errors?.length) {
    throw new Error(`monday.com item lookup failed: ${JSON.stringify(result.errors || result)}`);
  }

  const item = result.data?.items?.[0];
  if (!item) throw new Error(`monday.com item not found: ${itemId}`);
  return item;
}

async function sendWithVolanea({ to, name, item }) {
  const safeName = escapeHtml(name || "there");
  const safeItemName = escapeHtml(item.name);
  const eventId = `monday-item-${item.id}-ready-to-send`;

  const response = await fetch("https://api.volanea.com/v1/send", {
    method: "POST",
    headers: {
      "Authorization": `Bearer ${VOLANEA_API_KEY}`,
      "Content-Type": "application/json",
      "Idempotency-Key": crypto
        .createHash("sha256")
        .update(eventId)
        .digest("hex")
    },
    body: JSON.stringify({
      from: VOLANEA_FROM,
      to: [to],
      subject: `Your request is ready: ${item.name}`,
      text: `Hello ${name || "there"},\n\nYour request “${item.name}” is ready for the next step.\n\nRegards,\nOperations`,
      html: `<p>Hello ${safeName},</p><p>Your request <strong>${safeItemName}</strong> is ready for the next step.</p><p>Regards,<br>Operations</p>`,
      headers: {
        "X-Workflow-Event": eventId
      }
    })
  });

  const result = await response.json();
  if (!response.ok) {
    throw new Error(`Volanea send failed: ${JSON.stringify(result)}`);
  }

  return result;
}

app.post("/webhooks/monday/send-email", async (req, res) => {
  // Required during webhook creation in monday.com.
  if (req.body?.challenge) {
    return res.status(200).json({ challenge: req.body.challenge });
  }

  const event = req.body?.event;
  if (!event) return res.status(400).json({ error: "Missing monday.com event" });

  // Acknowledge irrelevant events without creating an email side effect.
  if (event.type !== "change_column_value") {
    return res.status(200).json({ ignored: "Unexpected event type" });
  }

  if (event.columnId !== MONDAY_STATUS_COLUMN_ID) {
    return res.status(200).json({ ignored: "Unexpected column" });
  }

  try {
    const item = await getMondayItem(event.pulseId);
    const status = getColumnText(item, MONDAY_STATUS_COLUMN_ID);

    if (status !== MONDAY_READY_LABEL) {
      return res.status(200).json({ ignored: "Status is not eligible for sending" });
    }

    const email = getColumnText(item, MONDAY_EMAIL_COLUMN_ID);
    const name = getColumnText(item, MONDAY_NAME_COLUMN_ID);

    if (!isSingleEmail(email)) {
      console.warn("Rejected item with invalid recipient", { itemId: item.id });
      return res.status(200).json({ ignored: "Invalid recipient" });
    }

    const result = await sendWithVolanea({ to: email, name, item });
    console.info("Email accepted by Volanea", { itemId: item.id, recipient: email });

    return res.status(200).json({ ok: true, result });
  } catch (error) {
    console.error("monday.com email workflow failed", {
      message: error instanceof Error ? error.message : String(error),
      itemId: event.pulseId
    });

    // Return a non-2xx response only when you want the upstream delivery to be treated as failed.
    return res.status(500).json({ error: "Unable to process webhook" });
  }
});

app.listen(process.env.PORT || 3000, () => {
  console.log("Webhook receiver is listening");
});

Adapt the code to your board

Replace the default column IDs with your own. You can inspect board columns through monday.com’s API or use the API playground to query the board schema. The important point is to map by IDs, not labels.

The send request uses:

  • from for the verified Volanea sender identity.
  • to as an array containing the recipient address.
  • subject, text, and html for recipient-visible content.
  • headers for an email-level trace identifier.
  • Idempotency-Key for safe retries of one logical send.

Keep a plain-text alternative even if HTML is your primary format. Some recipients, security scanners, and accessibility tools rely on it, and it makes the content legible if HTML rendering is disabled.

Prevent duplicate email when webhooks retry

Transactional messages have real-world side effects. A duplicate “your request is approved” email can confuse a customer; a duplicate invoice or password-related email can create support work or security concern.

A webhook endpoint can fail after the email provider accepted a message but before your service returned success. If monday.com retries the webhook, your code may run the same logical operation again. This is why the example uses an Idempotency-Key derived from the item ID and workflow event:

monday-item-1234567891-ready-to-send

The code hashes that stable string before sending it. Reprocessing that exact event produces the same key, allowing Volanea to recognize the retry as the same send request rather than a new email.

Make the key specific enough

A key that uses only the item ID can be too broad if an item may legitimately send more than one notification over its lifecycle. Include the meaningful business event, such as:

monday:{boardId}:item:{itemId}:event:approval-v1
monday:{boardId}:item:{itemId}:event:invoice-created:{invoiceId}
monday:{boardId}:item:{itemId}:event:appointment-reminder:{date}

Do not use the current timestamp as the idempotency key. A timestamp changes on every retry, defeating the entire purpose. Do not reuse one generic key across unrelated sends either; that would cause legitimate messages to be mistaken for duplicates.

For stronger operational guarantees, persist an outbox record in your own database with the monday item ID, event type, idempotency key, Volanea response, send timestamp, and a limited status value. This creates a durable audit record and makes failures easier to replay deliberately.

Secure the workflow before production

A working demo is not automatically a safe production integration. This workflow handles recipient addresses, board content, and an email API key, so security and privacy controls must be part of the design.

Keep secrets server-side

Your Volanea secret key authorizes sends. Store it only in environment variables or a dedicated secret manager. Rotate it if it appears in a log, screenshot, Git commit, board update, ticket, or no-code automation field.

Your monday.com API token also needs the least privilege possible. Use a service account or integration identity where your organization supports it, scope board access deliberately, and avoid granting unrelated workspace permissions just to power an email workflow.

Verify webhook origin where available

monday.com webhook creation includes the challenge exchange described earlier. If your integration architecture uses an app-created webhook and monday.com sends an authorization JWT, validate that JWT using the appropriate app signing secret before processing the event.

If your board-level webhook does not include a signed authorization header, use compensating controls:

  • Make the endpoint path random and private.
  • Put the endpoint behind a managed edge or API gateway.
  • Set request-size limits.
  • Accept only JSON POST requests.
  • Validate expected event types, board IDs, column IDs, and value shapes.
  • Rate-limit unexpected traffic.
  • Do not expose raw error details to the requester.

Escape board values before building HTML

Board content is user input. A project title can contain angle brackets, quotes, copied markup, or text designed to interfere with rendering. Escape every dynamic HTML value, as the example does with escapeHtml().

Do not place arbitrary board content inside raw HTML attributes, JavaScript blocks, CSS blocks, or redirect URLs. For links, allow only expected protocols and trusted hostnames. Transactional email should communicate a specific event, not become an injection path from a project board to a customer inbox.

Test the complete flow safely

Test in layers rather than activating the workflow for a live customer board immediately.

  1. Test the endpoint challenge. Deploy the receiver, create the webhook, and confirm that monday.com accepts the challenge response.
  2. Inspect a real sample event. Log the event structure with sensitive values redacted. Confirm the trigger column ID and item ID field.
  3. Test the item query. Use an internal item with known values and ensure your service retrieves the correct Email, Name, and Status fields.
  4. Use an internal recipient. Set the recipient to a mailbox your team controls.
  5. Check duplicate behavior. Replay the same event or deliberately retry the endpoint and confirm the idempotency key does not create a second logical send.
  6. Review rendering. Check the subject, From identity, plain-text version, HTML version, link behavior, and personalization.
  7. Test an invalid address. Confirm the workflow logs an ignored event rather than attempting a send.
  8. Test a non-eligible status. Confirm editing unrelated fields and statuses does not send mail.

Avoid testing by changing a real customer item repeatedly. An internal test board with the same column IDs and workflow rules gives you a controlled place to validate changes.

Add a sent status without causing an email loop

Many teams want the board to show whether an email was sent. That is useful, but it can create a loop if the automation listens to every column change and then updates another column after sending.

The safe pattern is simple: listen only to the dedicated trigger column. After Volanea accepts the send, your endpoint may update a separate Email sent status or Sent at date column through monday.com’s API. Because the webhook filters strictly on Send status, the write-back does not qualify as another send event.

A clean state model might look like this:

  • Draft: work is still being prepared.
  • Ready to send: the intentional event that authorizes the endpoint to send.
  • Sent: written by the endpoint after Volanea accepts the request.
  • Send failed: written after a terminal failure or manual review decision.

Do not automatically reset Ready to send to Sent until you have chosen your operational semantics. “Accepted by the sending API” is not identical to “delivered to the recipient mailbox.” If your process requires delivery confirmation, consume provider delivery events separately and update the board based on those events.

When to use Make or Zapier instead

A managed automation platform can be useful when a team does not operate any server-side code. The general pattern remains the same: monday.com triggers the scenario, the scenario retrieves item details if needed, and an HTTP request module calls Volanea’s REST API.

However, use a managed intermediary carefully for transactional sends. Confirm that it can:

  • Store the Volanea secret in encrypted credentials rather than plain scenario text.
  • Send custom headers, including Authorization, Content-Type, and Idempotency-Key.
  • Build a deterministic idempotency key from item data.
  • Fetch the complete monday.com item rather than assuming the trigger carries every field.
  • Expose error history and support controlled retries.
  • Prevent a failed write-back from rerunning the outbound email blindly.

For low-volume internal notifications, those trade-offs may be acceptable. For customer confirmations, receipts, access notices, account events, and other important messages, a small dedicated receiver is usually more transparent and more controllable.

Common problems and how to fix them

The webhook cannot be saved

Your endpoint likely did not return the challenge in the required JSON shape. Confirm that it accepts a POST request, parses JSON, and returns exactly { "challenge": "..." } with a successful HTTP status.

The webhook arrives, but the email address is blank

This normally means the webhook payload was treated as a full record. Fetch the item using event.pulseId, then check your board’s actual Email column ID. Also confirm that the item itself, rather than a linked board or subitem, contains the address.

Every board edit sends an email

Filter on a dedicated trigger column and a specific allowed value. Do not use a broad “any column changes” event as the business rule.

The same recipient gets duplicate messages

Check that retries use the exact same idempotency key. If the key contains a random UUID or a timestamp generated per attempt, each retry becomes a new logical email.

The API key appears in logs

Remove or redact request headers immediately, rotate the exposed key, and review logging middleware. Logging response status, item ID, a hashed recipient identifier, and a provider message reference is generally more useful than logging credentials or email bodies.

The email is accepted but not visible in an inbox

First distinguish acceptance from delivery. Review the Volanea send response, sender-domain authentication, recipient spelling, suppression status, spam or promotions folders, and any delivery-event data configured for the account. Do not solve a deliverability issue by repeatedly resending; repeated sends can make the situation worse.

Conclusion

To send transactional email from monday.com using Volanea, build a webhook-driven workflow rather than looking for a native marketplace app. Configure monday.com’s Webhooks integration, answer its challenge request, use the item ID from each event to fetch trusted board data, validate and map that data in a server-side endpoint, and call Volanea’s POST /v1/send API with a stable idempotency key.

That architecture is honest about the integration boundary and strong enough for production: monday.com controls the work event, your application controls the business logic, and Volanea handles email sending infrastructure. With explicit send states, stable column IDs, strict validation, safe HTML rendering, and duplicate protection, a board update becomes a dependable transactional email trigger rather than a fragile automation shortcut.

FAQ

Is there a native Volanea app for monday.com?

No. Volanea does not currently provide a native “Send Email From Monday” integration or monday.com marketplace app. Use monday.com’s Webhooks integration to call your own endpoint, then have that endpoint call Volanea’s REST API.

Can monday.com send a webhook directly to Volanea’s send endpoint?

No. monday.com first requires a challenge-response verification flow, and its webhook event body is not a Volanea email request. A server-side receiver is needed to complete verification, fetch item data, secure credentials, map fields, and send the correctly shaped API request.

Does a monday.com webhook include every board column value?

Do not rely on it for that. Webhook events are event notifications and generally describe the changed object or column. Use the item ID in the event, such as pulseId, to query the current item through monday.com’s GraphQL API.

How do I stop duplicate emails after a webhook retry?

Create one deterministic Idempotency-Key per logical email event, such as a value derived from the monday.com board ID, item ID, and event name. Reuse that same key when retrying the same event.

Should I send campaign emails from a monday.com status change?

Usually no. This pattern is best for event-driven transactional messages: confirmations, approvals, reminders, receipts, or operational notices. Promotional campaigns require consent, audience management, unsubscribe handling, frequency controls, and different operational safeguards.