ServiceNow can do far more than display notifications inside a workspace: you can send email from ServiceNow through Volanea when an operational record reaches the point where a customer, requester, or internal team needs a tailored message. The dependable route is a server-side Business Rule that reacts to an inserted or updated record and makes an outbound REST request to Volanea.
Volanea does not provide a native ServiceNow application, Store listing, or Marketplace plugin. That is not a blocker, but it changes the implementation model: your ServiceNow instance owns the trigger and field mapping, while Volanea owns email submission and delivery infrastructure. This guide uses ServiceNow's documented sn_ws.RESTMessageV2 server-side API rather than pretending there is an app to install.
What this integration does
The example in this guide sends an email after a new Incident record is inserted into ServiceNow's incident table. In ServiceNow terminology, the concrete trigger is an after Business Rule configured to run asynchronously when an Incident is inserted. The script reads fields from current, builds JSON, and submits it to Volanea's email REST endpoint.
That is a useful baseline because an Incident has a caller, a short description, a number, state information, and a record URL. The same pattern works for other tables, including Requests (sc_request), Requested Items (sc_req_item), Change Requests (change_request), Case records, or a custom table. What changes is the Business Rule table, its When-to-run condition, and the fields you map.
The path is straightforward:
- A user, integration, or ServiceNow process inserts an Incident record.
- The asynchronous Business Rule checks whether the record is eligible for an email.
- ServiceNow reads recipient and message data from the server-side record.
- ServiceNow calls Volanea over HTTPS with a JSON request body and a bearer API key.
- The script records the Volanea response identifier on the Incident when the send succeeds.
- If the request fails, ServiceNow logs enough context for an administrator to investigate or retry safely.
Use this for messages that are actually transactional or operational: an incident acknowledgement, a request confirmation, a change notice, or a service restoration update. Do not use a record-triggered script as an unbounded campaign engine. A bulk campaign needs deliberate recipient consent, segmentation, suppression handling, pacing, and a retry strategy that is different from a single-record transactional notification.
Why use a server-side Business Rule and RESTMessageV2
ServiceNow supports outbound HTTP from server-side scripts through sn_ws.RESTMessageV2. A Business Rule is therefore a direct option when your requirement is tied to a record database operation. It does not require a native email-provider plugin.
A Business Rule has an important advantage over a browser-side UI script: the API key never needs to be sent to a user's browser. The server can read the record, construct the request, call the external endpoint, and limit sensitive logging in one controlled environment.
The selected ServiceNow trigger
Create the rule on the Incident table with these characteristics:
- When:
after - Insert: selected
- Update: not selected for the first version
- Advanced: selected, because the action is script-based
- Asynchronous: selected
- Condition: only records that should generate an acknowledgement, such as records with a non-empty caller email and an eligible contact type
An after rule is appropriate because the Incident has already been written and has its final record number. Marking it asynchronous keeps an external network call out of the user's record-save path. A user should not have to wait for an email API call before ServiceNow finishes saving an Incident.
Do not start with “every update.” Incident records are often updated repeatedly by assignment, work notes, state transitions, SLA activity, and automation. An update-triggered message needs a precise condition, such as a transition to Resolved, and a persistent marker showing that the particular notification has already been sent.
Why not put the request in client-side code
Client scripts and UI actions run in a user context and can expose implementation details to the browser. A Volanea API key in a client-visible script, hidden form field, browser storage value, or public Script Include is not a secret. Anyone who can inspect the page or network requests may be able to reuse it to send mail from your domain.
Server-side scripting also lets you make decisions using authoritative record values. For example, you can use the caller's email from the user reference record, avoid sending to inactive contacts, and persist a send status on the Incident. Those checks are harder to make reliable when the browser is the integration point.
Prepare the Volanea sender and ServiceNow fields
Before writing the rule, make sure the address in the from field is a sender that your Volanea account is permitted to use. In practical terms, that means completing the sender or domain verification steps in Volanea and publishing the DNS records Volanea supplies for your domain. A request may be syntactically correct yet fail or be rejected if the From domain is not authorized.
For this example, create these properties and fields in ServiceNow. Names are examples; follow your instance's naming convention, especially if you are developing in a scoped application.
Store configuration separately from code
Use system properties for non-secret configuration:
x_volanea.from_email— for example,support@example.comx_volanea.from_name— for example,Example Supportx_volanea.instance_url— the base URL of your instance, such ashttps://example.service-now.com
For x_volanea.api_key, create a system property with the Password2 type rather than a plain text property. Password2 values are encrypted at rest in ServiceNow. Limit who can administer that property, and do not print its value in scripts, system logs, flow execution details, or error messages.
A larger implementation can use ServiceNow's credential and connection-alias facilities where the available products and governance model support that approach. The key rule remains the same: keep the Volanea key in a server-side secret store, give only the integration the ability to read it, and rotate it without editing application code.
Add operational tracking fields
Add fields on incident or, preferably for a reusable design, on a custom outbound-message table related to the Incident:
u_volanea_message_id— string; stores the provider message identifier returned after a successful request.u_volanea_send_status— choice or string; for examplepending,sent, orfailed.u_volanea_last_error— string; stores a deliberately sanitized error summary.u_volanea_delivery_key— string; an internal deterministic key such asincident:<sys_id>:ack-v1.
The message identifier is useful when an administrator needs to correlate a ServiceNow record with Volanea activity. The delivery key is useful before the provider responds: it gives your code a stable way to recognize that this exact Incident and notification type have already entered the send process.
Do not put full API response bodies, email HTML, or recipient addresses into broadly visible work notes merely for debugging. Those fields can contain personal or operationally sensitive data. Use the system log and restricted integration records thoughtfully, with a retention policy.
Field mapping for an Incident acknowledgement
A successful integration starts with a field map, not with a generic “send email” block. Here is the mapping used by the script below.
| ServiceNow source | Volanea request field | Purpose |
|---|---|---|
gs.getProperty('x_volanea.from_email') | from.email | Verified sender address |
gs.getProperty('x_volanea.from_name') | from.name | Human-readable sender name |
current.caller_id.email | to[0].email | Incident caller's recipient address |
current.caller_id.getDisplayValue() | to[0].name | Recipient display name |
current.number | subject and message body | Incident reference |
current.short_description | subject and message body | Concise incident description |
current.getDisplayValue('state') | message body | Current Incident state label |
current.sys_id plus instance URL | message body | Link back to the record |
The email address comes from the Incident's caller_id reference. That reference can be empty, can point to a user without an email address, or can contain an address that should not receive a particular class of message. The script must validate it before attempting an API call.
The body escapes text copied from record fields before embedding it into HTML. This is not merely cosmetic. A short description may contain angle brackets, ampersands, or text that would otherwise be interpreted as markup. Escape user-controlled values for the context in which they are used.
For higher confidence before triggering a send, teams can run proposed recipient addresses through a free address verification tool. Verification is not a replacement for consent or a valid business purpose, but it can help identify malformed or undeliverable addresses in data imported into ServiceNow.
Working ServiceNow script and Volanea REST request
The following is an Advanced Business Rule script for an asynchronous, after-insert rule on incident. It constructs the JSON ServiceNow sends and makes the Volanea REST call. The Volanea email request uses POST https://api.volanea.com/v1/emails, a bearer token, and from, to, subject, html, and text fields.
(function executeRule(current, previous /* null when async */) {
// Prevent an acknowledgement from being sent twice for the same Incident.
if (!gs.nil(current.u_volanea_message_id)) {
return;
}
var recipientEmail = String(current.caller_id.email || '').trim();
var recipientName = String(current.caller_id.getDisplayValue() || '').trim();
if (gs.nil(recipientEmail)) {
gs.warn('[Volanea] Incident ' + current.number +
' has no caller email; acknowledgement was not sent.');
return;
}
var fromEmail = gs.getProperty('x_volanea.from_email');
var fromName = gs.getProperty('x_volanea.from_name', 'Support');
// This property must be Password2 and readable only by trusted server-side code.
var apiKey = gs.getProperty('x_volanea.api_key');
var instanceUrl = gs.getProperty('x_volanea.instance_url');
if (gs.nil(fromEmail) || gs.nil(apiKey) || gs.nil(instanceUrl)) {
gs.error('[Volanea] Required Volanea properties are missing for Incident ' +
current.number + '.');
return;
}
function escapeHtml(value) {
return String(value || '')
.replace(/&/g, '&')
.replace(/</g, '<')
.replace(/>/g, '>')
.replace(/"/g, '"')
.replace(/'/g, ''');
}
var incidentNumber = String(current.number);
var description = String(current.short_description || 'No short description provided');
var state = String(current.getDisplayValue('state') || 'New');
var incidentUrl = instanceUrl.replace(/\/$/, '') +
'/nav_to.do?uri=incident.do?sys_id=' + current.sys_id;
// This is the actual JSON request body submitted from ServiceNow to Volanea.
var payload = {
from: {
email: fromEmail,
name: fromName
},
to: [{
email: recipientEmail,
name: recipientName
}],
subject: 'We received incident ' + incidentNumber,
html: '<p>Hello ' + escapeHtml(recipientName || 'there') + ',</p>' +
'<p>We received your incident <strong>' + escapeHtml(incidentNumber) +
'</strong>.</p>' +
'<p><strong>Description:</strong> ' + escapeHtml(description) + '</p>' +
'<p><strong>Current state:</strong> ' + escapeHtml(state) + '</p>' +
'<p><a href="' + escapeHtml(incidentUrl) + '">View the incident in ServiceNow</a></p>',
text: 'Hello ' + (recipientName || 'there') + ',\n\n' +
'We received your incident ' + incidentNumber + '.\n' +
'Description: ' + description + '\n' +
'Current state: ' + state + '\n\n' +
'View it: ' + incidentUrl
};
try {
var request = new sn_ws.RESTMessageV2();
request.setEndpoint('https://api.volanea.com/v1/emails');
request.setHttpMethod('post');
request.setRequestHeader('Authorization', 'Bearer ' + apiKey);
request.setRequestHeader('Content-Type', 'application/json');
request.setRequestHeader('Accept', 'application/json');
request.setRequestBody(JSON.stringify(payload));
var response = request.execute();
var status = response.getStatusCode();
var responseBody = response.getBody();
if (status >= 200 && status < 300) {
var result = JSON.parse(responseBody);
// Volanea returns the accepted email identifier as id.
current.u_volanea_message_id = String(result.id || 'accepted');
current.u_volanea_send_status = 'sent';
current.u_volanea_last_error = '';
current.update();
} else {
current.u_volanea_send_status = 'failed';
current.u_volanea_last_error = 'Volanea HTTP status ' + status;
current.update();
gs.error('[Volanea] Send failed for Incident ' + current.number +
' with HTTP status ' + status + '.');
}
} catch (ex) {
current.u_volanea_send_status = 'failed';
current.u_volanea_last_error = 'Outbound request exception';
current.update();
gs.error('[Volanea] Request exception for Incident ' + current.number +
': ' + ex.getMessage());
}
})(current, previous);
The code deliberately does not log payload, apiKey, or the full response body. Logging a full response might expose recipient addresses or provider details to a wider audience than the integration team.
Review the current REST endpoint, request schema, available response fields, and send options in the email API reference and setup guides before deploying. In particular, if your account uses a template, tags, metadata, reply-to address, or a different sender representation, adjust the JSON to match the documented Volanea schema rather than adding guessed fields.
Test safely before enabling the rule for production records
Build this in a non-production instance first. Use a verified test sender and a test mailbox that your team controls. Create one test Incident with a caller that has that mailbox as its email address, then confirm both the ServiceNow result and Volanea's send activity.
A practical test sequence is:
- Create the Password2 property and non-secret sender properties in the target instance.
- Verify the From domain and sender in Volanea before running the Business Rule.
- Add the tracking fields and the Business Rule, initially with a condition that limits execution to a test category or test caller.
- Insert a single Incident and inspect
u_volanea_send_statusandu_volanea_message_id. - Confirm the recipient sees a usable plain-text and HTML version, correct incident number, correct state, and a valid ServiceNow link.
- Test missing caller email, a non-2xx API response, and a timeout or blocked egress path.
- Remove the test-only condition only after the failure paths are understood.
A Business Rule may run under a system context that differs from the interactive user who created the Incident. Test with the same application scope, roles, and outbound network controls that production will use. If your instance restricts outbound HTTP access, allow the Volanea API hostname through the appropriate network or security controls rather than weakening outbound restrictions globally.
When this breaks: diagnose the ServiceNow-to-Volanea hop
External sends are distributed operations. ServiceNow and Volanea cannot make a single database transaction that guarantees both “the Incident was saved” and “exactly one email was accepted.” Design for ambiguity rather than assuming a successful-looking script means exactly one recipient message.
A timeout can produce an unknown outcome
If request.execute() times out, ServiceNow may not know whether Volanea received and accepted the request before the connection was interrupted. Retrying immediately can create a duplicate email. Treat a timeout as unknown, not automatically as “not sent.”
Use the stored message ID to avoid obvious repeats after a confirmed success. For timeout cases, queue the record for controlled investigation or build a durable outbound-message table with a status such as unknown. A worker can retry only after checking the provider-side activity or after applying an explicit, documented idempotency strategy supported by your sending endpoint.
Retries and reprocessing can create duplicate sends
ServiceNow does not magically make every custom REST script exactly-once. A scheduled retry job, a Flow retry policy, an administrator re-running a record action, an import replay, or an upstream process that re-inserts data can execute the send path again. The same is true if a later update rule accidentally shares the insert notification script.
Use at least two defenses:
- Persist a notification-specific sent marker or provider message ID and exit when it is present.
- Give each message type an internal key, such as
incident:<sys_id>:ack-v1, rather than treating all messages on an Incident as equivalent. - Avoid a condition based only on
current.state; compare a relevant previous and current value for update notifications. - Build retries from a dedicated queue or outbound-message record, not by asking users to edit the Incident again.
The sample's u_volanea_message_id check is a basic safeguard, not a complete concurrency solution. If multiple workers can process the same record at once, use a separate queue record with a unique key and an atomic claim process.
Missing payload fields are a data-model problem, not an API mystery
ServiceNow does not automatically serialize every form field into an outbound payload. The JSON is exactly what your script constructs. A value can be absent because the Incident has no caller, the caller has no email, a reference field is empty, a custom field is not present in a lower environment, or a no-code connector exposes a narrower field set than your table does.
This also matters if you choose an automation product rather than server-side scripting. Available actions, connection features, and data pills can depend on your ServiceNow release, subscriptions, installed capabilities, table permissions, and the connector's version. Test the actual input object with representative Incident records; do not assume a field seen on a form is automatically available to a workflow action.
In the direct script, add explicit validation for every required field. In the example, recipient email is required. For a change notice, you might also require a planned start date and a specific contact field. Fail safely with a traceable status instead of sending a message with an empty recipient or misleading content.
Authentication failures and sender failures have different fixes
An HTTP 401 or 403 generally points to the API key, authorization header, account permissions, or a rotated secret. Check that the property is populated in the correct instance and that the script is reading it server-side. Do not “debug” an authorization issue by writing the key to a log.
A validation or sender-related 4xx response can instead indicate an invalid recipient, an unverified From address, or an invalid request shape. Keep the status code and a limited diagnostic reference in ServiceNow, then inspect Volanea's API response and sender configuration through authorized administrative tools.
Alternatives: Flow Designer, IntegrationHub, Zapier, and Make
A scripted Business Rule is not the only way to send email from ServiceNow. It is often the clearest direct method when a developer can maintain a small server-side integration and needs exact payload control.
ServiceNow Flow Designer and IntegrationHub can be appropriate when your team prefers a visual workflow and the necessary REST capability is available in your ServiceNow entitlement. A flow can be triggered by a record condition and make a REST-oriented action, with values mapped from the trigger record. Treat connector and action availability as instance-specific: verify the feature in your own release and subscription before committing to a design.
Zapier or Make can be useful middleware when the integration team does not have ServiceNow server-side development capacity, when a broader cross-app workflow is required, or when a business process needs visual approvals between ServiceNow and email sending. The trade-offs are another credential store, additional execution latency, possible task or operation charges, and a second retry system that can duplicate sends if it is not coordinated with ServiceNow.
For a record-triggered transactional message, choose based on ownership:
- Choose a Business Rule plus RESTMessageV2 when you need direct server-side control, low extra latency, and explicit code review.
- Choose Flow Designer or IntegrationHub when visual orchestration, managed connections, and non-developer maintenance outweigh the limits of available actions and licensing.
- Choose Zapier or Make when ServiceNow is only one part of a multi-application process and middleware ownership is already established.
Regardless of the route, the email request should come from a secure server-side context, have a deterministic trigger, record an outcome, and guard against duplicate execution.
Production design: delivery, privacy, and observability
A sending API accepting a message is not identical to inbox placement. Transactional email performance depends on a verified sending domain, aligned authentication, recipient data quality, content relevance, and a sending pattern that recipients expect.
Keep transactional notices distinct from promotional mail. If an Incident acknowledgement contains product marketing, a recipient may regard an operational message as an unsolicited campaign. Separate streams and sender identities where appropriate, and make sure the data source and notification purpose satisfy your organization's privacy, security, and retention obligations.
For observability, track four layers:
- ServiceNow trigger evidence: which record, notification type, and execution timestamp started the send.
- Request outcome: HTTP status and a sanitized error category, never the API secret.
- Provider correlation: Volanea message ID stored against the record or outbound-message row.
- Recipient outcome: provider events and support evidence when an intended recipient says they did not receive a message.
This structure makes support conversations faster. Instead of asking whether “the integration worked,” an administrator can determine whether the Business Rule ran, whether Volanea accepted the request, which provider message is relevant, and whether a delivery event needs separate investigation.
For teams estimating the economics of operational sends at scale, review transactional email pricing and sending costs alongside ServiceNow and middleware costs. A workflow that sends on every update can multiply both email volume and automation executions quickly, which is another reason to define transition conditions narrowly.
A practical rollout checklist
Before enabling this for real Incident records, verify the following:
- The From address is authorized in Volanea and its domain authentication setup is complete.
- The Volanea key is in a Password2 property or an approved server-side credential store, not code or a client script.
- The Business Rule is asynchronous and runs only on the intended insert or state-transition event.
- The recipient mapping handles empty references and missing email addresses.
- The HTML content escapes record values, and the text version remains readable.
- The outbound hostname is permitted by ServiceNow and organizational network controls.
- A successful send writes a provider correlation ID and a failure writes a safe, actionable status.
- A retry or re-run strategy cannot silently send duplicate incident acknowledgements.
- Test records have been checked in a non-production instance and with a real recipient mailbox.
- Ownership is clear: someone is responsible for sender verification, key rotation, failed-send review, and changes to the Incident schema.
The most maintainable version is usually not the shortest script. It is the version with clear eligibility conditions, secret handling, durable status records, and enough correlation data to explain what happened days later.
FAQ
Does Volanea have a native ServiceNow plugin?
No. This integration does not rely on a native ServiceNow app or Marketplace listing. It uses ServiceNow's server-side outbound REST capability and Volanea's email API.
What ServiceNow event starts the email in this example?
An asynchronous, after Business Rule on the incident table starts the send when an Incident record is inserted. You can adapt the same pattern to a state transition, but use a precise condition and a sent marker.
Where should the Volanea API key be stored in ServiceNow?
Store it in a server-side secret mechanism, such as a Password2 system property or an approved credential configuration. Never place it in a client script, UI policy, browser-visible property, or form field.
Why did one Incident generate two emails?
The send path was likely executed more than once, or a timeout made the first outcome unknown and a retry created a second request. Persist a message ID or notification key, use a durable queue for retries, and do not retry ambiguous timeout outcomes blindly.
Can I use Flow Designer instead of a Business Rule?
Potentially, if the REST or IntegrationHub capabilities you need are available in your ServiceNow instance and subscription. Validate the exact action, field availability, credential handling, and retry behavior in your release before using it for production sends.