Zoho Books can trigger operational email when an invoice changes, but it is not an email-delivery platform. This guide shows how to send email from Zoho Books through Volanea using a Zoho Books workflow rule and a Deluge custom function—without claiming that a native Zoho Books marketplace app exists.
The pattern is deliberately simple: a Zoho Books workflow rule runs when an invoice meets your chosen condition, the workflow calls a custom function, and that function retrieves invoice data and makes a server-to-server request to Volanea. Volanea then handles the actual transactional delivery.
The integration architecture
Zoho Books provides workflow automation for accounting records, including invoices. A workflow rule can be configured to run when a record is created, edited, or meets defined criteria. One of the workflow actions available in this model is a custom function written in Deluge, Zoho's scripting language.
For invoice notifications, the data path looks like this:
- A user, integration, or API creates an invoice in Zoho Books.
- A Zoho Books workflow rule evaluates the invoice event and its criteria.
- The rule invokes a custom function and passes the invoice ID.
- The custom function retrieves the complete invoice record from Zoho Books.
- The function maps selected invoice fields into a Volanea email request.
- Volanea accepts the request and queues the email for delivery.
This is not a native plug-in connection. There is no Volanea app to install from a Zoho Books marketplace, and there should not be any suggestion that a native app is required. The integration uses capabilities available in the Zoho Books automation and developer model.
That distinction matters operationally. A native app can hide field mappings and delivery behavior behind a user interface. A workflow plus custom function makes those decisions explicit: which accounting event deserves an email, which contact receives it, which template is appropriate, and what happens if an event is replayed.
Why use a workflow rule instead of Zoho Books email templates?
Zoho Books has its own invoice-email capabilities, which are appropriate when the job is simply to send an invoice or payment reminder from the accounting product. A Volanea handoff is useful when the email is part of a wider product or operational communication system.
Examples include:
- Sending a branded “invoice created” acknowledgement distinct from the attached invoice email.
- Notifying an internal account owner when an invoice exceeds a risk threshold.
- Sending a customer email after a payment status or approval-related workflow condition is met.
- Keeping transactional email sending, delivery events, and API-based templates in the same infrastructure as your application emails.
- Sending to an address that is not necessarily the invoice's billing contact, such as an accounts-payable mailbox maintained in a custom field.
The workflow is also more precise than reacting to every accounting change. For example, an invoice can be created in draft status and subsequently edited several times. If the business event is “an invoice was sent,” a rule that fires on every edit is the wrong trigger. Start by writing the event in plain language, then translate it into the workflow event and criteria Zoho Books supports.
The concrete Zoho Books trigger
For this implementation, use an Invoices workflow rule whose trigger is When an invoice is created. In the rule's criteria, add a condition that limits the workflow to the invoices that should result in an email.
A practical starting condition is:
- Module: Invoices
- Trigger: invoice created
- Criteria: invoice status is Draft, or another status that matches your process
- Instant action: Custom Function
The exact status condition is a business decision. Many teams create invoices as drafts, review them, and later send them. In that case, “invoice created” means “a billing record now exists,” not “the customer should be notified.” If the customer email must coincide with a sent invoice, configure the workflow around the event and criteria that represent that state in your Zoho Books setup rather than blindly using creation.
Pass only the invoice identifier to the function
In the workflow's custom-function action, create an argument named invoice_id and map it to the invoice ID available from the invoice workflow context. Also provide the Zoho Books organization ID as an argument or keep it as a controlled configuration value in the function.
Passing the record ID, rather than trying to pass every displayed field into the function, has two benefits. First, the function can retrieve the current canonical record from Zoho Books. Second, it avoids an incomplete event context becoming an accidental source of truth for email content.
This matters for line items, customer information, and custom fields. The fields visible in a workflow context are not a substitute for deciding exactly which API response fields your email needs.
What Zoho Books actually sends
A Zoho Books workflow webhook does not provide a universal, fixed invoice-event JSON envelope that every receiver can depend on. Its outgoing request is configured in the webhook action: you choose the target URL, HTTP method, headers, and parameters. Therefore, the body is defined by the webhook configuration rather than by a guaranteed, full invoice object pushed by Zoho Books.
That is why this guide uses a custom function. The function receives the workflow argument and then explicitly fetches the invoice. The important input delivered from the workflow is conceptually this:
invoice_id=460000000053001
The function calls the Zoho Books invoice endpoint through the built-in Books task and receives an invoice response with an invoice object. The fields you will commonly use include values such as invoice_id, invoice_number, customer_name, customer_email, date, due_date, currency_code, total, balance, status, and line_items.
Do not assume customer_email is present just because an invoice exists. A customer can be created without an email address, and an invoice may be addressed to a contact arrangement that does not provide the field your workflow expects. Validate it before calling your email provider.
The outgoing Volanea payload
After retrieving the invoice, the function creates the delivery-provider payload. The payload below is intentionally compact: it contains a sender, one recipient, a subject, HTML content, plain-text content, and a provider-side identifier derived from the invoice ID.
{
"from": "Acme Billing <billing@notify.example.com>",
"to": ["ap@customer.example"],
"subject": "Invoice INV-1042 is ready",
"html": "<p>Hello Northstar Ltd,</p><p>Invoice <strong>INV-1042</strong> for USD 1,250.00 is ready.</p><p>Due date: 2026-10-31.</p>",
"text": "Hello Northstar Ltd,\n\nInvoice INV-1042 for USD 1,250.00 is ready.\nDue date: 2026-10-31.",
"headers": {
"X-Source-System": "zoho-books",
"X-External-Event-ID": "zoho-books-invoice-460000000053001"
}
}
The invoice ID is more reliable than an invoice number as an event key. Invoice numbers may be formatted, changed by numbering rules, or reused in imported data. The underlying Zoho Books record ID is the better deduplication anchor.
Before implementing the request, confirm the current endpoint, authentication header, and available email fields in the email API reference and setup guides. API contracts can evolve, and the account's verified sending domain must match the from address you use.
Build the Zoho Books custom function
Create the function from Zoho Books automation settings and associate it with the invoice workflow rule. The function needs two inputs:
invoice_id: the invoice ID passed by the workflow action.organization_id: your Zoho Books organization ID.
The code below shows the complete mapping logic in Deluge. Replace the values in angle brackets before use, especially the API URL, sender identity, and authorization mechanism required by your Volanea account.
// Workflow function arguments:
// invoice_id = invoice ID mapped from the Invoices workflow rule
// organization_id = your Zoho Books organization ID
invoice_response = zoho.books.getRecordsByID("invoices", organization_id, invoice_id);
invoice = invoice_response.get("invoice");
if(invoice == null)
{
info "Volanea send skipped: invoice was not returned: " + invoice_id;
return;
}
recipient = ifnull(invoice.get("customer_email"), "").trim();
if(recipient == "")
{
info "Volanea send skipped: customer_email is empty for invoice " + invoice_id;
return;
}
invoice_number = ifnull(invoice.get("invoice_number"), invoice_id.toString());
customer_name = ifnull(invoice.get("customer_name"), "there");
currency_code = ifnull(invoice.get("currency_code"), "");
total = ifnull(invoice.get("total"), 0).toString();
due_date = ifnull(invoice.get("due_date"), "not specified");
subject = "Invoice " + invoice_number + " is ready";
text_body = "Hello " + customer_name + ",\n\n"
+ "Invoice " + invoice_number + " for " + currency_code + " " + total + " is ready.\n"
+ "Due date: " + due_date + ".";
html_body = "<p>Hello " + customer_name + ",</p>"
+ "<p>Invoice <strong>" + invoice_number + "</strong> for "
+ currency_code + " " + total + " is ready.</p>"
+ "<p>Due date: " + due_date + ".</p>";
recipients = List();
recipients.add(recipient);
tracking_headers = Map();
tracking_headers.put("X-Source-System", "zoho-books");
tracking_headers.put("X-External-Event-ID", "zoho-books-invoice-" + invoice_id);
payload = Map();
payload.put("from", "Acme Billing <billing@notify.example.com>");
payload.put("to", recipients);
payload.put("subject", subject);
payload.put("html", html_body);
payload.put("text", text_body);
payload.put("headers", tracking_headers);
headers = Map();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer <VOLANEA_API_KEY>");
response = invokeurl
[
url :"https://api.volanea.com/v1/emails"
type :POST
parameters:payload.toString()
headers:headers
];
info response;
This code illustrates the field mapping directly:
| Zoho Books invoice field | Volanea email field | Purpose |
|---|---|---|
customer_email | to[0] | Delivery recipient |
invoice_number | subject, html, text | Human-readable invoice reference |
customer_name | html, text | Greeting |
currency_code and total | html, text | Invoice amount context |
due_date | html, text | Payment deadline context |
invoice_id | X-External-Event-ID | Traceability and duplicate protection |
The HTML example is deliberately plain. Do not concatenate untrusted customer-entered data into HTML without considering escaping and content safety. If customer names can include characters such as <, >, or &, use a well-tested escaping step or switch to an approved Volanea template with variables rather than composing HTML in the function.
Keep the Volanea API key out of visible configuration
The Volanea API key belongs in the server-side automation path only. It must never be placed in a customer portal page, browser JavaScript, invoice PDF, email link, mobile application bundle, or any other client-visible configuration.
A Zoho Books custom function executes on Zoho's server side, which is the correct direction, but hard-coding a production secret directly into function source is still a weak operational practice. Anyone with sufficient access to edit or view the function can potentially read it, and rotating it requires changing code.
Preferred secret pattern
Use a protected server-side credential mechanism available in your Zoho setup—such as a configured connection or a restricted automation credential—when it supports the required authorization header. Configure the authorization there and use the connection in the server-side request rather than embedding the key in the function text.
If your Zoho Books configuration cannot store a static bearer credential in a restricted connection, use a small middleware endpoint under your control. In that design:
- Zoho Books authenticates to the middleware with a separate webhook secret.
- The middleware validates the request and event identity.
- The middleware holds the Volanea API key in its secret manager or environment configuration.
- The middleware calls Volanea.
That route adds a component, but it improves key rotation, structured logging, template management, and idempotency. It also means an accounting-automation editor does not need access to an email-provider production key.
Regardless of the storage method, restrict the Zoho Books roles that can edit workflow rules and custom functions. Rotate the Volanea key when administrators leave, if a secret could have been exposed, or according to your normal credential policy.
Make the email content appropriate for accounting data
Accounting events are sensitive because they can expose amounts, customer names, payment dates, and potentially contractual relationships. “Invoice ready” sounds routine, but the content and recipient selection deserve the same care as payment operations.
Avoid including payment links, bank details, tax identifiers, or full line-item detail in an email unless that is required and approved. It is often safer to tell the recipient that an invoice is available and direct them to the authenticated customer portal or to the official invoice email workflow.
Choose the recipient deliberately
customer_email is convenient, but it may not represent the right accounts-payable contact. Depending on your customer data model, use one of these approaches:
- Maintain a dedicated invoice-recipient email in a custom field.
- Use the primary contact only when it is explicitly designated for billing.
- Send internal notifications to a controlled company address instead of external recipients.
- Require manual review for high-value or unusual invoices.
Run recipients through syntax and deliverability checks before enabling automation. The free email address verification tool can help identify obviously malformed or risky addresses, but it does not replace consent, contact ownership, or a customer-data governance process.
Preserve a clear message identity
Use a verified sender domain that matches your organization. A sender such as billing@notify.example.com should belong to a domain you control and authenticate for sending. Keep the display name recognizable, for example “Acme Billing,” so recipients can distinguish a legitimate invoice notice from a generic system message.
Include a plain-text version alongside HTML. Some recipients use clients that limit HTML, and plain text remains valuable for accessibility, troubleshooting, and predictable rendering.
When this breaks
An integration is not finished because it works for one test invoice. The failure modes are specific to the hop between a Zoho Books workflow, a custom function, and an email API.
Workflow retries can create duplicate sends
A timeout or temporary provider error can make a caller unsure whether the remote service accepted the request. If Zoho Books retries the workflow action, or an administrator reruns an automation after investigating an error, the same invoice can produce another email.
The X-External-Event-ID header in the example is an audit marker, not automatically a guarantee of idempotency. Confirm whether your Volanea sending configuration supports idempotency with a dedicated idempotency key or event identifier. If it does, use the invoice ID plus the specific business event as the key, such as invoice-created-460000000053001.
If duplicate prevention must be absolute, put a middleware service in front of Volanea. Store the event key before sending, use an atomic unique constraint, and return a stable success response for repeated deliveries of the same key. Do not use only an in-memory cache; it will not survive restarts or protect concurrent requests.
Webhook or custom-function timeouts need a defined response
Server-side HTTP calls have execution and network time limits. A slow receiver, DNS failure, TLS problem, or provider outage can make invokeurl fail. Logging the response with info is useful during setup, but it is not enough for production monitoring.
Record the invoice ID, workflow name, recipient, request outcome, and delivery-provider request ID where possible. Set an owner for failed sends and decide whether the correct recovery is an automatic retry, a manual resend, or no resend at all. For an invoice creation acknowledgement, a delayed retry may be fine. For an internal fraud or approval alert, delay may be unacceptable and should generate another alerting path.
Fields can be absent or vary by configuration
Not every invoice has customer_email, a due date, a custom field value, or the same contact structure. Availability can also vary with how a Zoho Books organization is configured and which features are enabled. Custom fields, portal-related data, and automation capabilities should be checked in the specific Zoho Books edition and organization before the workflow is treated as a production dependency.
Guard every optional field. The example explicitly stops when customer_email is empty. For optional presentation fields, provide a safe fallback. Never silently replace a missing customer recipient with a guessed address or an internal mailbox unless that behavior is explicitly approved.
A 2xx acceptance response is not an inbox placement guarantee
A successful API response means the sending service accepted the request. It does not mean the recipient opened the email, that the domain accepted it, or that it reached the primary inbox. Sender authentication, recipient reputation, bounce handling, message content, and the recipient's mailbox rules all affect the eventual result.
Use provider delivery and bounce events to investigate problems after acceptance. Also test with a real controlled mailbox, not only a local string that happens to satisfy email syntax.
Test the workflow before enabling it broadly
Use a separate test customer and a clearly labeled test invoice. Do not start with live customer data or an invoice that triggers an irreversible external business process.
A sound test sequence is:
- Verify the Volanea sending domain and use a real test recipient mailbox.
- Create a Zoho Books invoice with a known invoice number, amount, due date, and customer email.
- Confirm the workflow rule is triggered only once for the intended event.
- Inspect the custom-function execution output and the Volanea API response.
- Check the delivered subject, recipient, amount formatting, HTML rendering, and plain-text fallback.
- Create an invoice with no customer email and confirm that no send is attempted.
- Retry or replay a test event intentionally and verify your duplicate-handling behavior.
Test amount formatting especially carefully. Raw numeric fields may not display in the locale you expect. A US recipient may expect 1,250.00; another process may require currency symbols or locale-specific separators. If exact invoice presentation is a compliance requirement, link to the official invoice PDF or customer portal rather than rebuilding the invoice document in the email body.
Direct custom function, webhook, or middleware?
A custom function is the shortest direct route because it can fetch the invoice record and make an HTTP request in one controlled server-side execution. It is appropriate for a simple, low-volume notification with a small field mapping.
A native workflow webhook is best when the receiving system can consume the parameters Zoho Books lets you configure and when no record enrichment is required. It is less attractive when you need nested JSON, conditional recipient selection, HTML generation, complex security handling, or durable idempotency.
Middleware is the most flexible option. It can be built with a serverless function, an integration platform, or a small application endpoint. Tools such as Zapier or Make can be useful when a non-developer team needs to maintain the routing, but verify their trigger coverage, polling behavior, error handling, and task costs before making an invoice event depend on them.
Choose middleware when you need any of the following:
- A secret manager instead of a key in Zoho automation configuration.
- A database-backed idempotency record.
- Centralized retries and dead-letter handling.
- Template rendering and HTML escaping outside Deluge.
- Multiple downstream actions, such as CRM updates, Slack notifications, and email.
- Detailed audit logs that tie an accounting event to a sending request and delivery status.
The right architecture is the least complicated one that still gives you secure secrets, clear ownership, and safe replay behavior.
Operational checklist
Before placing this automation into production, review these controls with both the finance and engineering owners:
- The workflow trigger matches the real business event, not merely a convenient record update.
- The sender domain is verified and the sender identity is recognizable.
- The recipient source is approved for invoice-related communication.
- Optional Zoho Books fields have fallbacks or explicit skip behavior.
- The Volanea API key is held only in server-side restricted configuration or middleware.
- A unique event ID is generated from the Zoho Books invoice ID and business event.
- Retry behavior cannot silently create multiple customer notices.
- Failed sends are observable and have a named recovery owner.
- Test invoices and recipients are available for regression testing after workflow or template changes.
- Finance can explain what the email says and why each recipient receives it.
Conclusion
To send email from Zoho Books with Volanea, use an Invoices workflow rule to invoke a server-side custom function, retrieve the invoice by ID, map only the fields you need, and call the Volanea REST API. This approach avoids a fictional marketplace installation while giving your team explicit control over trigger timing, content, recipients, and delivery operations.
The most important implementation detail is not the HTTP call itself. It is defining the business event precisely and treating retries, missing data, and secret storage as first-class design concerns. Once those are in place, invoice events can become reliable transactional messages rather than fragile one-off automations.
FAQ
Can Zoho Books send directly to Volanea without a marketplace app?
Yes. Zoho Books workflow automation can invoke a server-side custom function, and the function can make an HTTP request to an email API. Volanea does not need to be installed as a native Zoho Books marketplace app for this pattern.
What Zoho Books event should trigger the email?
Use an Invoices workflow rule and choose the event that represents your real process, such as invoice creation or a status-related update. Add criteria so routine edits do not produce unintended emails.
Where should the Volanea API key be stored?
Keep it only in restricted server-side configuration, such as an appropriate Zoho credential or a middleware secret manager. Never expose it in browser code, invoice links, or customer-facing configuration.
How do I stop duplicate invoice emails?
Use the Zoho Books invoice ID plus the business event as a stable event key. Where available, use provider idempotency support; for strict protection, store that key in middleware with a database-backed unique constraint before sending.
What if an invoice has no customer email?
Do not send. Validate customer_email in the custom function, log the skipped invoice, and route the exception to the finance team or require a dedicated billing-recipient field.