Send email from Quickbase without exposing an API key by using a Quickbase webhook as the trigger and Volanea as the delivery layer. This approach gives your Quickbase app a reliable way to send confirmations, approvals, reminders, status updates, and operational notifications when records change.
Quickbase is an application platform built around tables, records, forms, reports, and automations. Volanea is the email infrastructure layer: it accepts a structured API request and sends the resulting transactional email through your configured sending domain. The important design decision is that Quickbase should trigger the event, while a server-side endpoint should own the Volanea API key and make the final API call.
That distinction matters because Quickbase is not a native Volanea app or marketplace integration. There is no Volanea package to install from a Quickbase marketplace, and there should not be a browser-side field containing a live sending credential. Instead, configure Quickbase to notify a secure webhook endpoint when a record reaches an email-worthy state. Your endpoint validates the request, maps Quickbase field values into an email, calls Volanea, records the outcome, and returns a fast success response to Quickbase.
The recommended Quickbase-to-Volanea architecture
The most dependable setup has three hops:
- A record event occurs in Quickbase.
- A Quickbase webhook sends a server-to-server HTTP request to your endpoint.
- Your endpoint validates the event and sends the email through Volanea's REST API.
In practical terms, the flow looks like this:
Quickbase record is added or modified
↓
Quickbase webhook POST
↓
Your secure webhook endpoint
↓
Validation, deduplication, field mapping
↓
Volanea REST API
↓
Recipient inbox and delivery events
This pattern is preferable to trying to put an email API key in a formula, a form field, front-end JavaScript, or any client-visible configuration. A Quickbase application may be used by many people with different roles, while the Volanea API key can authorize email sends for an entire sending domain. Treat it as a production secret, not as ordinary record data.
It also separates business logic from delivery logic. Quickbase remains the source of truth for records such as requests, orders, cases, projects, or approvals. The webhook relay becomes the place where you decide whether an event should result in a message, which template should be used, which recipient is eligible, and how duplicate events are handled.
What triggers the email in Quickbase
The concrete Quickbase trigger is a webhook notification attached to a table event. A webhook can notify an external endpoint when a record is added, modified, or deleted, subject to the conditions you configure for that webhook.
For an email workflow, avoid firing on every edit unless every edit genuinely deserves an email. A better rule is usually based on a meaningful state transition. Examples include:
- A new record is added to an
Orderstable and its status isPaid. - A request record is modified and its
Approval Statuschanges toApproved. - A support case is modified and its
StagebecomesWaiting for Customer. - A form submission creates a new record with
Send Confirmationchecked. - A project task is modified and its due date enters a reminder window.
The webhook event is still a record event. The business condition determines whether that event should become an email. Put the highest-confidence filtering rule in Quickbase where possible, then enforce the final rule again in your relay. The second check protects you if a user changes a webhook condition later, a field is blank unexpectedly, or Quickbase re-delivers an event.
Example: a record stage change
Assume you have a Quickbase table called Customer Requests with these fields:
| Quickbase field | Purpose | Example value |
|---|---|---|
| Record ID# | Stable record identifier | 4821 |
| Customer Email | Recipient email address | alex@example.com |
| Customer Name | Recipient name | Alex Rivera |
| Request Number | Human-readable request reference | REQ-10482 |
| Stage | Workflow state | Approved |
| Send Email | Workflow control flag | true |
| Email Sent At | Audit timestamp | 2026-09-23T14:20:00Z |
| Email Message ID | Provider message identifier | msg_... |
Configure the webhook around the event where the record is modified and meets your intended send condition, such as Stage = Approved and Send Email = true. In the relay, require both conditions again and decline to send when Email Sent At already has a value for the same notification type.
This creates a predictable operational rule: approval causes one approval email, not an email for every subsequent correction to the record.
Why use a relay instead of calling Volanea directly from Quickbase
A direct outbound HTTP request sounds simpler: point Quickbase at an email API endpoint, add an authorization header, and send JSON. In a real production system, however, a relay is usually the safer choice.
First, it keeps the Volanea API key out of Quickbase-visible settings and out of any workflow artifact that more people may be able to inspect. Second, it lets you validate the incoming event before spending sending capacity or notifying the wrong person. Third, it gives you a durable place to implement idempotency, logging, retries, and template rendering.
The relay can be a small serverless function on your existing stack. Common choices include a route in a Node.js application, an AWS Lambda function behind API Gateway, a Cloudflare Worker, a Vercel function, a Google Cloud Run service, or an internal integration service. The hosting choice matters less than these properties:
- It accepts HTTPS POST requests.
- It can authenticate or verify the Quickbase webhook.
- It has access to server-side environment variables.
- It returns a response quickly.
- It can store an idempotency record or otherwise prevent duplicate sends.
- It logs enough context to diagnose a failed event without logging unnecessary personal data.
A middleware tool can also work for low-code workflows. Zapier or Make can receive or process Quickbase events and then call an HTTP API. But use that route only after confirming that its plan, retention rules, error behavior, and secret storage meet your needs. For critical notifications such as billing receipts, account access messages, regulatory notices, or security alerts, a controlled webhook relay is generally easier to test and audit.
Build the Quickbase webhook payload around stable field IDs
Quickbase records are fundamentally field-based. Names are convenient for people, but IDs are safer for integrations because field labels can be renamed. Your relay should map the incoming record fields explicitly rather than assuming the order of fields or relying on a display form.
A webhook payload should provide enough information to identify the event, the application and table, the record, and the fields needed to build the message. The exact event envelope can vary with the Quickbase webhook configuration and API version, so capture a real test delivery from your own app before finalizing production code.
For this implementation, configure the webhook to include the fields required by the email. The relay should normalize that event into a small internal object like this:
{
"eventType": "record.modified",
"appId": "bqabc1234",
"tableId": "bqdef5678",
"recordId": 4821,
"changedAt": "2026-09-23T14:20:00.000Z",
"fields": {
"customerEmail": "alex@example.com",
"customerName": "Alex Rivera",
"requestNumber": "REQ-10482",
"stage": "Approved",
"sendEmail": true,
"emailSentAt": null
}
}
That object is an internal normalized representation, not a promise that every Quickbase webhook will use those exact property names. In your production code, map the actual Quickbase field IDs from your table to these properties. For example, field ID 6 might be Customer Email, field ID 7 might be Customer Name, and field ID 12 might be Stage.
Capture a real test event before going live
Create a non-production Quickbase application or a test table, configure the webhook to point at a request-inspection endpoint you control, and perform the same record edit that will trigger the production send. Save a redacted sample payload and document the field IDs.
Check all of the following in the real event:
- Whether the webhook includes the fields you expect for both added and modified records.
- How blank fields are represented: omitted,
null, an empty string, or another value. - Whether checkbox, date, user, and multi-select fields require special handling.
- Which identifiers are available for the table and record.
- Whether an update that does not change your email-related fields still triggers the webhook.
This step prevents a common integration error: code works against a hand-written sample but fails when a field is blank, a user edits through a different form, or a field contains a non-string Quickbase value.
Working webhook relay: map Quickbase fields and call Volanea
The example below uses Node.js with Express. It assumes your Quickbase webhook sends a record-oriented JSON body and that your app's real field IDs have been configured as environment variables. The handler extracts values, checks the workflow conditions, creates a deterministic idempotency key, and sends the email through Volanea.
The Volanea credentials are stored only in server-side environment variables. The API call uses a Bearer token and a JSON email payload containing sender, recipient, subject, HTML, and plain-text content.
import express from "express";
import crypto from "node:crypto";
const app = express();
app.use(express.json({ limit: "256kb" }));
const {
VOLANEA_API_KEY,
VOLANEA_FROM_EMAIL,
VOLANEA_FROM_NAME = "Acme Operations",
QUICKBASE_WEBHOOK_SECRET,
QB_FIELD_CUSTOMER_EMAIL,
QB_FIELD_CUSTOMER_NAME,
QB_FIELD_REQUEST_NUMBER,
QB_FIELD_STAGE,
QB_FIELD_SEND_EMAIL,
QB_FIELD_EMAIL_SENT_AT
} = process.env;
function fieldValue(record, fieldId) {
const field = record?.[fieldId];
if (field && typeof field === "object" && "value" in field) {
return field.value;
}
return field ?? null;
}
function safeText(value) {
return String(value ?? "").replace(/[&<>"']/g, (character) => ({
"&": "&",
"<": "<",
">": ">",
"\"": """,
"'": "'"
}[character]));
}
function requestSignatureIsValid(rawBody, signature) {
if (!QUICKBASE_WEBHOOK_SECRET || !signature) return false;
const expected = crypto
.createHmac("sha256", QUICKBASE_WEBHOOK_SECRET)
.update(rawBody)
.digest("hex");
return crypto.timingSafeEqual(
Buffer.from(expected, "utf8"),
Buffer.from(signature, "utf8")
);
}
// Replace this with Redis, Postgres, DynamoDB, or another shared durable store.
const processedEvents = new Set();
app.post("/webhooks/quickbase", express.raw({ type: "application/json" }), async (req, res) => {
const rawBody = req.body.toString("utf8");
// If your Quickbase setup supplies a signed header, validate it here.
// Do not claim a header name until you have verified your webhook configuration.
// const signature = req.get("x-your-quickbase-signature");
// if (!requestSignatureIsValid(rawBody, signature)) return res.sendStatus(401);
let event;
try {
event = JSON.parse(rawBody);
} catch {
return res.status(400).json({ error: "Invalid JSON" });
}
// Adapt this extraction to the actual test payload captured from your Quickbase webhook.
const record = event.record ?? event.data?.record ?? event.data ?? {};
const recordId = event.recordId ?? event.data?.recordId ?? fieldValue(record, "3");
const customerEmail = fieldValue(record, QB_FIELD_CUSTOMER_EMAIL);
const customerName = fieldValue(record, QB_FIELD_CUSTOMER_NAME);
const requestNumber = fieldValue(record, QB_FIELD_REQUEST_NUMBER);
const stage = fieldValue(record, QB_FIELD_STAGE);
const sendEmail = fieldValue(record, QB_FIELD_SEND_EMAIL);
const emailSentAt = fieldValue(record, QB_FIELD_EMAIL_SENT_AT);
const sendIsEnabled = sendEmail === true || sendEmail === "true" || sendEmail === 1;
const eventKey = `quickbase:${recordId}:approval-email:${stage}`;
if (stage !== "Approved" || !sendIsEnabled) {
return res.status(200).json({ skipped: true, reason: "Workflow conditions not met" });
}
if (!customerEmail || !String(customerEmail).includes("@")) {
return res.status(200).json({ skipped: true, reason: "No usable recipient email" });
}
if (emailSentAt || processedEvents.has(eventKey)) {
return res.status(200).json({ skipped: true, reason: "Duplicate notification" });
}
const recipientName = safeText(customerName || "there");
const request = safeText(requestNumber || recordId);
const emailPayload = {
from: {
email: VOLANEA_FROM_EMAIL,
name: VOLANEA_FROM_NAME
},
to: [
{
email: String(customerEmail).trim(),
name: customerName ? String(customerName) : undefined
}
],
subject: `Your request ${request} has been approved`,
html: `<p>Hello ${recipientName},</p><p>Your request <strong>${request}</strong> has been approved.</p><p>You can reply to this email if you need help.</p>`,
text: `Hello ${customerName || "there"},\n\nYour request ${requestNumber || recordId} has been approved.\n\nReply to this email if you need help.`
};
const volaneaResponse = await fetch("https://api.volanea.com/v1/emails", {
method: "POST",
headers: {
"Authorization": `Bearer ${VOLANEA_API_KEY}`,
"Content-Type": "application/json",
"Idempotency-Key": eventKey
},
body: JSON.stringify(emailPayload)
});
const responseText = await volaneaResponse.text();
if (!volaneaResponse.ok) {
console.error("Volanea send failed", {
status: volaneaResponse.status,
recordId,
responseText
});
// Return a non-2xx status only if you want Quickbase to treat this as failed.
// Your retry strategy should be deliberate; see the 'When this breaks' section.
return res.status(502).json({ error: "Email provider request failed" });
}
processedEvents.add(eventKey);
console.info("Volanea email accepted", {
recordId,
recipient: customerEmail,
providerResponse: responseText
});
return res.status(200).json({ sent: true });
});
app.listen(process.env.PORT || 3000, () => {
console.log("Quickbase webhook relay is listening");
});
The field extraction function intentionally supports the common pattern where a Quickbase field is represented as an object with a value property. Do not copy the event.record ?? event.data?.record fallback blindly without testing: adapt it to your captured Quickbase payload. The important part is the explicit mapping from known field IDs to named application values.
The Volanea endpoint, authorization method, and request schema should be checked against the current email API reference and setup guides before deployment. Email APIs can evolve, and your implementation should follow the exact endpoint and payload defined for your Volanea account.
Configure field mapping deliberately
Field mapping is where an integration becomes useful or dangerous. A message saying “your request has been approved” is harmless only if it goes to the correct person, contains the correct request number, and is sent after the correct status change.
Keep the mapping in a configuration layer rather than scattering raw Quickbase field IDs through template code. For example:
QB_FIELD_CUSTOMER_EMAIL=6
QB_FIELD_CUSTOMER_NAME=7
QB_FIELD_REQUEST_NUMBER=10
QB_FIELD_STAGE=12
QB_FIELD_SEND_EMAIL=18
QB_FIELD_EMAIL_SENT_AT=21
Then create a table in your implementation notes that connects each environment variable to the actual Quickbase field label, field ID, data type, and fallback behavior.
| Environment variable | Quickbase field | Required? | Fallback behavior |
|---|---|---|---|
QB_FIELD_CUSTOMER_EMAIL | Customer Email | Yes | Skip send and log reason |
QB_FIELD_CUSTOMER_NAME | Customer Name | No | Use “there” in greeting |
QB_FIELD_REQUEST_NUMBER | Request Number | No | Use Record ID# |
QB_FIELD_STAGE | Stage | Yes | Skip when not Approved |
QB_FIELD_SEND_EMAIL | Send Email | Yes | Skip when unchecked |
QB_FIELD_EMAIL_SENT_AT | Email Sent At | No but recommended | Use idempotency storage too |
For addresses collected in a form, validate before sending. Syntax validation is not proof that a mailbox exists or that it is safe to contact, but it catches obvious errors such as missing domains and malformed addresses. A lightweight pre-send check can reduce preventable bounces; use the email address verification tool for one-off checks and build an appropriate validation process for higher-volume workflows.
Authentication: where the Volanea API key belongs
The Volanea API key belongs in the relay's secret manager or environment configuration, not in a Quickbase record, form, report, formula, client-side script, or user-visible webhook URL.
For a serverless deployment, store it as a protected environment variable such as VOLANEA_API_KEY. For a larger service, store it in a secret manager and grant the running workload permission to read that secret. Rotate it if it is exposed, if a team member with access leaves, or on your normal credential-rotation schedule.
The reason is straightforward: an email API key is an authorization credential. Anyone who obtains it may be able to send mail as your domain, consume your account capacity, damage your domain reputation, or create a security incident. Hiding a key in a hidden Quickbase field does not make it safe. Hidden is a user-interface concept; secret is an access-control concept.
Your Quickbase webhook endpoint should also be protected. Use the authentication or verification mechanism supported by your Quickbase configuration, restrict the endpoint to HTTPS, and reject unexpected requests. If the webhook system cannot supply a suitable signature, use a high-entropy secret in the URL only as a secondary control, rotate it when needed, and add compensating protections such as rate limiting and strict event validation.
Never log the Volanea API key, full authorization header, or raw webhook payloads indefinitely. Payloads may contain names, email addresses, customer identifiers, or other personal information. Log the minimum useful diagnostic context: event ID or record ID, event type, recipient domain where appropriate, response status, provider message ID, and a redacted error reason.
Add idempotency before you trust retries
A record event and an email send are not one atomic transaction. Quickbase can deliver an event more than once, your relay can receive a request and lose its response, or Volanea can accept a send while your process times out before reading the success response. Without idempotency, any of those situations can create duplicate messages.
Use a durable idempotency key built from the record ID and the notification type. For a single approval notification, a suitable logical key is:
quickbase:4821:approval-email
If the record may be approved more than once over its lifetime, include a stable transition version, approval timestamp, or revision number rather than only the current stage. For example:
quickbase:4821:approval-email:2026-09-23T14:20:00.000Z
Store that key in a durable database with a unique constraint before or during the send workflow. An in-memory Set, like the one in the sample code, demonstrates the idea but is not sufficient for a multi-instance or serverless production deployment because it disappears on restart and is not shared across instances.
A robust sequence is:
- Receive and validate the Quickbase event.
- Build a deterministic idempotency key.
- Attempt to create a database row with that key under a uniqueness constraint.
- If the key already exists, return success without another send.
- Send through Volanea.
- Store the provider response and mark the event as sent.
- Update Quickbase with
Email Sent Atand, if useful, the provider message ID.
The Quickbase audit fields are valuable for operators, but do not rely on them as your only deduplication mechanism. A second webhook delivery can arrive before the first process updates the record. The relay's own durable uniqueness check closes that race.
When this breaks: Quickbase webhook failure modes
Every production integration needs a failure plan. The highest-risk problems in this specific hop are duplicate sends caused by retries, webhook timeouts, and missing or differently shaped fields in real Quickbase events.
Quickbase retries can create duplicate emails
If Quickbase does not receive a timely successful response from your endpoint, it may treat delivery as unsuccessful and retry according to its webhook behavior. The first request may still have sent the email successfully, especially when the upstream timeout occurred after Volanea accepted the request.
Do not solve this by assuming retries never happen. Solve it with the idempotency strategy above. Return a success response only after your service has durably accepted responsibility for the event, and ensure a second delivery recognizes the same logical notification.
If sending can take longer than your webhook response window, queue the event. Your endpoint can validate and persist the job quickly, return 200, and let a worker send through Volanea afterward. This changes the system from “webhook request equals send operation” to “webhook request equals accepted send job,” which is usually more reliable.
Webhook timeouts can hide an accepted email
A timeout does not always mean Volanea rejected the request. It can mean DNS resolution stalled, the outbound request remained open too long, your process was cold-starting, your database was slow, or the provider accepted the message just before the connection failed.
Use explicit outbound timeouts, record the idempotency key before retrying, and inspect the provider response or message event when available. Do not immediately retry the same send indefinitely. Retry only transient failures such as a network interruption or a temporary 5xx response, and use bounded exponential backoff.
For permanent failures, such as an invalid recipient address or an unauthorized API key, stop automated retries and create an actionable operational alert. Retrying a bad address does not repair it; retrying an invalid credential only adds noise.
Some fields may be absent, blank, or represented differently
A Quickbase field can be missing from the payload because it was not included in the webhook configuration, because the record has no value, because permissions affect what is available, or because the value type is not what your template code assumed. A checkbox may arrive differently from a string. A user field, multi-select field, date, or related lookup may need normalization.
Treat all incoming values as untrusted input. Check that the recipient is a string before calling .trim(). Check that a status is exactly the expected value before sending. Provide a fallback for optional display fields, but do not invent a fallback recipient address.
A good skip response is often better than a broken email. Log recordId, missing field name, and reason, then send the event to an internal error queue or monitoring channel for review.
Record edits after the trigger can change the message
A webhook payload represents a particular event, but a later user edit can occur before your worker sends the email. Decide whether the message should reflect the event-time values or the latest record values.
For receipts, approvals, and audit-sensitive notices, prefer event-time values captured in the webhook payload. For a “your task is overdue” reminder, fetching the latest record details may be appropriate. Make that policy explicit, because the difference affects customer trust and auditability.
Deliverability considerations for Quickbase notifications
Sending an API request is not the same thing as inbox placement. For customer-facing Quickbase notifications, configure a dedicated, authenticated sending domain and use a recognizable sender identity. Authentication records such as SPF, DKIM, and DMARC should be aligned with your domain strategy before you send production traffic.
Keep transactional messages transactional. An approval notice, account update, service alert, invoice receipt, or workflow notification is expected because it follows an action in Quickbase. Do not quietly turn the same event stream into promotional marketing mail. That creates consent issues, increases complaint risk, and makes the operational messages less trustworthy.
Use a clear subject line that identifies the event and record. For example:
Request REQ-10482 approved
That is more useful than “Update from Acme” because it gives the recipient enough context to recognize the message. Include plain-text content as well as HTML, a support route or reply path, and only the information the recipient needs. Avoid putting sensitive record data in email if the recipient can retrieve it from a secure authenticated portal instead.
Monitor delivery outcomes over time. A spike in bounces may indicate a form-validation problem in Quickbase. A spike in complaints may mean users did not expect the message or the workflow is sending too often. A sudden delivery failure after a domain change may point to broken DNS authentication rather than an application-code problem.
Testing checklist before production
Do not launch this integration from a single happy-path test. Build a compact test matrix that reflects the way people actually use your Quickbase app.
- Create a qualifying record and confirm one email is sent.
- Edit an unrelated field and confirm no additional email is sent.
- Change the stage to the sending state twice and confirm the intended idempotency behavior.
- Submit a record with a blank recipient address and confirm the event is skipped safely.
- Test malformed and role-based email values if your app collects them.
- Confirm that the sender domain is verified and authenticated.
- Temporarily use an invalid Volanea API key and confirm the failure is visible to operators without exposing the key.
- Simulate a Volanea timeout or 5xx response and confirm retry behavior does not create duplicates.
- Confirm that a webhook retry returns the same logical result without sending another email.
- Verify that the
Email Sent Atand provider message ID are written back to the intended Quickbase record if you use audit fields.
Keep a test recipient mailbox under your control and inspect both the rendered HTML and plain-text version. Check mobile layout, reply behavior, sender display name, links, and whether the message contains the correct record number. A technically successful API response is not enough if the wrong customer receives the wrong request details.
Operational patterns that scale
The basic webhook relay can start small, but its design should make future improvements possible. Once you send multiple notification types, move message selection into a structured configuration rather than a growing chain of if statements.
For example, define a notification policy by event and stage:
const notificationPolicies = {
Approved: {
type: "approval-email",
subject: ({ requestNumber }) => `Your request ${requestNumber} has been approved`
},
Rejected: {
type: "rejection-email",
subject: ({ requestNumber }) => `Update on request ${requestNumber}`
}
};
Store templates in version control, test them with realistic Quickbase record fixtures, and make recipient rules explicit. A notification policy can specify whether to send to the record owner, a contact email field, a department mailbox, or an internal escalation address. It can also define whether the event is customer-facing, internal-only, or requires manual approval.
As volume grows, add a queue and observability. Useful metrics include webhook requests received, events skipped, emails accepted by Volanea, provider failures, retry count, duplicate events suppressed, and time from Quickbase event to send acceptance. These measurements show whether a problem belongs in Quickbase configuration, the relay, the email provider request, or the sending domain.
Conclusion
To send email from Quickbase with Volanea, use a Quickbase webhook triggered by a meaningful record event, then route that event through a secure server-side relay. The relay maps real Quickbase field IDs into an email payload, keeps the Volanea API key in protected server-side storage, prevents duplicate sends, and gives you a clear place to handle failures.
The integration is not a marketplace installation and should not depend on exposed credentials. Build it as a small, auditable event pipeline: Quickbase records produce webhook events; your service validates, deduplicates, and renders messages; Volanea handles the API delivery request. That structure is reliable enough for a single approval notification and extensible enough for an entire operational-email program.
FAQ
Can Quickbase send email directly through Volanea?
Quickbase can initiate outbound webhook notifications, but the safer production design is to send those notifications to your own HTTPS relay and have that relay call Volanea. This keeps the Volanea API key out of client-visible or broadly accessible configuration and gives you control over validation, retries, and deduplication.
What Quickbase event should trigger the email?
Use a webhook triggered when a record is added or modified, then constrain it to a business condition such as Stage = Approved or Send Email = true. Avoid sending on every record modification unless that is genuinely the intended behavior.
Where should I store the Volanea API key?
Store it in a server-side environment variable or secret manager used by your webhook relay. Do not store it in a Quickbase field, a form, front-end code, a report, or a shared document.
How do I stop duplicate emails from Quickbase webhook retries?
Create a durable idempotency key using the Quickbase record ID plus the notification type and, when necessary, a transition version or timestamp. Save that key under a unique constraint before sending so repeat webhook deliveries are recognized and skipped.
What should happen if the recipient email field is blank?
Do not send. Return a safe handled response, log the record ID and missing-field reason, and route the issue to an operator or exception report. Never substitute an arbitrary recipient address for a customer-facing notification.