A Nuvemshop email integration can send timely order emails without exposing an email API key in your storefront. The reliable pattern is Nuvemshop webhook → server-side middleware → Volanea REST API: Nuvemshop notifies your endpoint about an order event, your service retrieves the order details, and Volanea delivers the message.

This distinction matters because Volanea does not provide a native Nuvemshop marketplace app or plugin. The integration is built with Nuvemshop’s developer webhook and API capabilities, not by adding JavaScript to a storefront theme or installing an app from a marketplace.

What this integration can and cannot do

Nuvemshop, also known as Tiendanube in several markets, exposes an API for registered applications and integrations. Its webhooks notify an external URL when a supported resource changes. For transactional sending, a useful event is order/created: Nuvemshop creates an order, posts a compact notification to your server, and your server decides whether and how to email the buyer.

That makes this a server-to-server integration. It is appropriate for messages such as order acknowledgements, payment instructions, fulfillment updates, cancellations, and internal operational alerts. It is not a replacement for a customer’s browser sending email directly.

A Nuvemshop webhook notification is deliberately small. It identifies the event, store, and resource; it is not a complete email-ready order document. Your middleware should use the order ID in the webhook to retrieve the current order from the Nuvemshop API, then map the relevant fields to a Volanea message.

The basic flow is:

  1. A buyer completes checkout and Nuvemshop creates an order.
  2. Nuvemshop sends an order/created webhook to an HTTPS endpoint you operate.
  3. Your endpoint verifies that the notification is associated with an authorized store and records an idempotency key.
  4. The endpoint requests GET /v1/{store_id}/orders/{order_id} from Nuvemshop’s API.
  5. It maps contact_email, order details, and product lines into an email payload.
  6. It sends that payload to Volanea over HTTPS using a server-held API key.
  7. It stores the resulting message ID and returns a successful webhook response.

For developers evaluating providers, review the email API reference and setup guides before committing the sending portion of the workflow. The webhook architecture remains useful even if templates, sender domains, or event names evolve.

The concrete Nuvemshop trigger: order/created

The trigger used in this guide is the Nuvemshop webhook event named order/created. It represents the creation of an order. It does not necessarily mean that payment has settled, the order is approved, or goods have shipped. Those are separate business states and should lead to separate notifications when your store’s workflow requires them.

That distinction prevents a common transactional-email mistake: treating every new order as paid. Stores that accept card payments, transfers, bank slips, cash-on-delivery, or manual review may have orders in different payment states immediately after creation. An order/created email should therefore be framed as an order-received confirmation unless the order data confirms a state that justifies stronger wording.

Nuvemshop’s webhook configuration is part of an app or integration’s API workflow. It is not a general-purpose “send arbitrary HTTP from the storefront” feature that should be configured in browser code. A registered integration obtains authorization for a store, then creates a webhook subscription for that store with the Nuvemshop API.

A conceptual webhook registration request looks like this:

curl --request POST "https://api.tiendanube.com/v1/$STORE_ID/webhooks" \
  --header "Authentication: bearer $NUVEMSHOP_ACCESS_TOKEN" \
  --header "User-Agent: YourIntegrationName (ops@example.com)" \
  --header "Content-Type: application/json" \
  --data '{
    "event": "order/created",
    "url": "https://email.example.com/webhooks/nuvemshop/orders"
  }'

Use the correct API host and authorization details for the country and app type documented for your Nuvemshop integration. Do not put the store access token in a theme, a checkout script, a public Git repository, or a URL query parameter. A webhook subscription belongs to the backend service that owns the integration.

Why order/created is a good first event

An order-created event gives the buyer fast confirmation that the store received the request. It also gives your team a durable event from which to create internal notifications. The payload has an order ID, making it possible to fetch the authoritative order record rather than trusting a stale browser-side cart.

For post-purchase email, define the business rule first. For example:

  • Send an “order received” email for every order that has a usable contact email address.
  • Send payment instructions only when the order’s payment status and payment method require them.
  • Send fulfillment messaging only after a fulfillment-related order update that your integration explicitly supports.
  • Do not turn a generic order/updated event into a buyer email without comparing the before-and-after state; many updates are administrative and should be silent.

Understand the webhook payload before mapping an email

A Nuvemshop webhook notification for an order event identifies the resource rather than embedding every order field. The important shape is an event name, the store ID, the resource ID, and a creation timestamp. In practice, build your handler around those identifiers, not around the assumption that product, customer, or address objects are present in the webhook body.

A representative order/created notification has this shape:

{
  "event": "order/created",
  "store_id": 123456,
  "id": 987654321,
  "created_at": "2026-10-10T14:32:11+00:00"
}

Here, id is the order ID. It is not an email ID and should not be treated as a customer ID. store_id identifies the Nuvemshop store whose credentials must be used for the subsequent API read. Your application should verify that the store is one it has connected and should look up that store’s access token from encrypted server-side storage.

The full order response includes fields such as the buyer contact email and order line items. For this pattern, the key fields are typically:

  • contact_email for the recipient address.
  • name or customer information for a personalized greeting where available.
  • number for the customer-facing order number.
  • products for line-item names and quantities.
  • total, currency-related fields, and payment information for a receipt-style summary where appropriate.
  • status fields used to decide which message is valid to send.

Do not assume every field is populated. Guest orders, incomplete customer profiles, payment-provider behavior, privacy settings, app permissions, and regional differences can all affect available data. A production integration treats contact_email as required for a buyer email, while names, addresses, and some payment fields are optional.

Fetch the order after receiving the notification

The order retrieval request is where the webhook becomes usable business data. Your server uses the store ID and order ID from the notification and its stored Nuvemshop access token:

curl --request GET "https://api.tiendanube.com/v1/123456/orders/987654321" \
  --header "Authentication: bearer $NUVEMSHOP_ACCESS_TOKEN" \
  --header "User-Agent: YourIntegrationName (ops@example.com)"

Keep this read on the server. The access token authorizes access to store data, including customer and order information. Returning it to a browser would make it available to visitors, browser extensions, logs, and potentially third-party scripts.

Build the secure middleware endpoint

The middleware can be a small Node.js, Python, PHP, Go, serverless, or containerized service. Its responsibilities are straightforward but important: accept the webhook quickly, validate the event and store, obtain the order, deduplicate the event, send through Volanea, and record the result.

The endpoint should be publicly reachable over HTTPS because Nuvemshop must deliver the webhook to it. That does not mean it should be broadly trusted. Limit it to expected methods, reject malformed bodies, validate store association, use rate limits, and keep detailed logs free of customer secrets and full payment data.

A useful data model has at least three server-side tables or collections:

  1. Connected stores: store ID, encrypted Nuvemshop access token, installation state, and allowed sender configuration.
  2. Webhook deliveries: event name, store ID, resource ID, delivery time, raw-body hash, processing state, and retry count.
  3. Email sends: idempotency key, order ID, recipient, template/version, Volanea message ID, status, and error details.

The idempotency key should represent the business action, not simply the HTTP delivery. For an order acknowledgement, nuvemshop:123456:order/created:987654321:order-received-v1 is a sensible shape. If Nuvemshop delivers the same event again, the second delivery finds the existing key and does not generate another receipt.

A Node.js example with field mapping

The following Express example shows the complete important hop: accept Nuvemshop’s compact order notification, retrieve the order, map its fields, and issue the Volanea REST send request. It deliberately reads all secrets from server environment variables or a server-side store record.

import express from "express";

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

const NUVE_BASE_URL = "https://api.tiendanube.com/v1";
const VOLANEA_SEND_URL = process.env.VOLANEA_SEND_URL;
const VOLANEA_API_KEY = process.env.VOLANEA_API_KEY;
const FROM_EMAIL = process.env.VOLANEA_FROM_EMAIL;
const FROM_NAME = process.env.VOLANEA_FROM_NAME || "Example Store";

// Replace these with encrypted database operations in production.
async function getStore(storeId) {
  if (String(storeId) !== process.env.NUVEMSHOP_STORE_ID) return null;
  return { accessToken: process.env.NUVEMSHOP_ACCESS_TOKEN };
}

async function alreadySent(idempotencyKey) {
  return false; // Query a database with a unique index on idempotencyKey.
}

async function rememberSend(idempotencyKey, messageId) {
  console.log({ idempotencyKey, messageId });
}

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

app.post("/webhooks/nuvemshop/orders", async (req, res) => {
  const event = req.body?.event;
  const storeId = req.body?.store_id;
  const orderId = req.body?.id;

  if (event !== "order/created" || !storeId || !orderId) {
    return res.status(400).json({ error: "Expected order/created with store_id and id" });
  }

  const store = await getStore(storeId);
  if (!store) return res.status(403).json({ error: "Unknown store" });

  const idempotencyKey = `nuvemshop:${storeId}:${event}:${orderId}:order-received-v1`;
  if (await alreadySent(idempotencyKey)) return res.sendStatus(204);

  try {
    const orderResponse = await fetch(`${NUVE_BASE_URL}/${storeId}/orders/${orderId}`, {
      headers: {
        Authentication: `bearer ${store.accessToken}`,
        "User-Agent": "ExampleStoreEmailIntegration (ops@example.com)"
      }
    });
    if (!orderResponse.ok) throw new Error(`Nuvemshop order fetch failed: ${orderResponse.status}`);

    const order = await orderResponse.json();
    const recipient = order.contact_email;
    if (!recipient) {
      // Persist a skipped status so retries do not repeatedly attempt an impossible send.
      return res.sendStatus(204);
    }

    const customerName = order.customer?.name || order.name || "there";
    const orderNumber = order.number || order.id;
    const items = (order.products || []).map((product) => {
      const quantity = product.quantity ?? 1;
      return `<li>${escapeHtml(product.name)} × ${escapeHtml(quantity)}</li>`;
    }).join("");

    const emailPayload = {
      from: { email: FROM_EMAIL, name: FROM_NAME },
      to: [{ email: recipient, name: customerName }],
      subject: `We received your order #${orderNumber}`,
      html: `<p>Hi ${escapeHtml(customerName)},</p>
             <p>We received your order <strong>#${escapeHtml(orderNumber)}</strong>.</p>
             <ul>${items}</ul>
             <p>Order total: ${escapeHtml(order.total || "")}</p>`,
      text: `Hi ${customerName},\n\nWe received your order #${orderNumber}.`,
      headers: {
        "X-Idempotency-Key": idempotencyKey,
        "X-Nuvemshop-Order-Id": String(orderId)
      }
    };

    const sendResponse = await fetch(VOLANEA_SEND_URL, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${VOLANEA_API_KEY}`,
        "Content-Type": "application/json"
      },
      body: JSON.stringify(emailPayload)
    });
    if (!sendResponse.ok) {
      throw new Error(`Volanea send failed: ${sendResponse.status} ${await sendResponse.text()}`);
    }

    const sendResult = await sendResponse.json();
    await rememberSend(idempotencyKey, sendResult.id || sendResult.message_id);
    return res.sendStatus(204);
  } catch (error) {
    console.error("Nuvemshop email webhook failed", { storeId, orderId, message: error.message });
    return res.sendStatus(500);
  }
});

app.listen(process.env.PORT || 3000);

Set VOLANEA_SEND_URL to the send endpoint specified for your Volanea account and API version, and use the exact request schema in the current API documentation. The mapping in the example is intentional: Nuvemshop’s contact_email becomes the recipient, number becomes the recognizable order number, and products becomes a safely escaped item list. Do not copy an order field into HTML without escaping it.

Keep the Volanea API key off the storefront

The Volanea API key belongs in your middleware’s secret manager or encrypted runtime environment. It must never sit in a Nuvemshop theme file, storefront JavaScript, public environment variable, client-side tag manager, mobile app bundle, or browser request.

Anyone who can inspect client-visible configuration can copy a key. With an email-sending credential, that can mean unauthorized mail, sender-domain reputation damage, a compromised account, unexpected usage, and exposure of customer information through message content. Rotating a leaked credential after the fact does not undo deliverability harm already caused.

On the Nuvemshop side, the webhook destination should point only to your server endpoint. The Nuvemshop access token also belongs in server-side encrypted storage, indexed by store_id. In a multi-store integration, never use a single token for every incoming notification; look up the token associated with the store in the webhook body after confirming that store is connected to your application.

Separate credentials by environment

Use different Volanea API keys and sender identities for development, staging, and production. Development should point to a test recipient allowlist or a non-production domain. Staging should exercise webhook code without accidentally sending real buyer messages. Production should use a verified sender domain with SPF, DKIM, and DMARC aligned to the domain customers recognize.

This separation has an operational benefit: it makes logs and metrics meaningful. A developer replaying an event locally should not generate a second message to a real customer, and a staging failure should not pollute production delivery statistics.

Design the email around order state

An order creation is an event, while payment and fulfillment are states that can change over time. Treating them as the same thing produces confusing customer communications. The content and trigger should match.

For an order/created message, include what is safe and useful: the order number, a concise item summary, the store name, a link to customer support, and clear next steps. If payment is pending, say that the order was received and describe what the customer should do next. Do not label a payment as confirmed merely because an order exists.

For later messages, create distinct workflows with their own idempotency keys. A payment-approved email might use payment-approved-v1; a shipment email might use a fulfillment-specific ID or status transition. That prevents an update event from being mistaken for the original acknowledgement.

Use templates without losing traceability

A template system is usually better than assembling all markup in application code. Keep a versioned template identifier in your email-send record, and pass only approved variables such as customer name, order number, item list, order total, support URL, and locale.

Record the final message purpose, not every raw order field. For example, store template=order-received, template_version=3, and the Volanea message identifier. This makes customer-support investigations possible without retaining more personal data than needed.

When this breaks: failure modes at the Nuvemshop-to-Volanea hop

A webhook integration is distributed processing. The same event can arrive more than once, requests can time out, a downstream API can return an error, and some order fields can be absent. Plan for these cases before sending production traffic.

Retries can cause duplicate sends

If your endpoint returns a non-success response, takes too long, or loses its response after Volanea accepts the message, Nuvemshop may retry the webhook delivery. Retrying is correct behavior for the platform, but it can create duplicate buyer emails if your code simply sends every time it receives a notification.

Use a database-level unique constraint on the idempotency key. Create or reserve that key before sending, and update the record with the Volanea message ID after success. If a process crashes in the ambiguous interval after Volanea receives the request, use the provider’s idempotency capability where available and reconcile pending records rather than blindly sending again.

Do not rely only on in-memory caching. It disappears when a serverless function scales, restarts, deploys, or processes the retry on another instance.

Webhook timeouts and slow downstream calls

Nuvemshop expects a timely HTTP response from the destination. Fetching a full order, rendering a template, calling Volanea, and writing multiple database records can exceed a webhook timeout under load or during a third-party incident.

The strongest design is to validate and persist the webhook quickly, return a success response once it is durably queued, then process it asynchronously with a worker. The worker can retry Nuvemshop order reads and Volanea sends with bounded exponential backoff. It also gives you a dead-letter queue for events that need human review.

If you process synchronously at low volume, set explicit HTTP timeouts on both outbound calls and measure them. Never allow a network call to hang indefinitely. A timeout should become a tracked retryable failure, not an unbounded open request.

Fields can be missing or unsuitable

Not every order has every optional field your template wants. A customer may have no name, a product may have a changed title, the product array may be empty in an unusual lifecycle state, or payment and address data may vary by country, checkout configuration, or installed integrations.

Build fallbacks. Use “Hello” when no name exists, skip an item table when products are absent, omit a payment paragraph unless the required state is confirmed, and do not send a buyer email without a syntactically valid contact_email. Persist a skipped_missing_recipient or needs_review result so the condition is visible instead of silently disappearing.

Also consider plan, app authorization, and API permission differences. A field available in a test store or one Nuvemshop configuration may not be available in another. Test against realistic connected stores and make the template degrade gracefully.

API and sender failures

A Nuvemshop order read may fail because the app token was revoked, the store disconnected, the resource is temporarily unavailable, or your app exceeded a limit. A Volanea send can fail because a key was rotated, the sender domain is not verified, the JSON is invalid, or the recipient is suppressed.

Classify errors. Retry transient network errors and temporary 5xx responses; do not repeatedly retry a malformed request, an invalid sender, or a known suppressed address. Alert on authorization failures because they usually require store reconnection or credential rotation. Include store ID, order ID, event, and correlation ID in structured logs, but avoid logging full email bodies and access tokens.

Test the full workflow before enabling customer sends

Start with a development store and a test recipient inbox. Create an order, confirm that Nuvemshop posts the order/created event, inspect the persisted webhook record, verify that the service fetches the intended order, and review the exact rendered email before enabling a production sender.

Test more than the happy path. A strong test matrix includes:

  • A guest checkout with only contact_email available.
  • A buyer name containing accents, apostrophes, angle brackets, or emoji.
  • Multiple products and quantities.
  • An unpaid or pending-payment order.
  • A duplicated webhook delivery using the same order ID.
  • A deliberately slow or failed Volanea request.
  • An order with no recipient email, ensuring it is skipped rather than sent to a fallback address.
  • A revoked Nuvemshop token, ensuring the integration alerts rather than looping forever.

Use a recognizable non-production subject prefix during testing, such as [STAGING] Order received. Confirm that your sender domain authentication is correct before judging inbox placement. Deliverability problems are often domain-authentication or reputation issues, not webhook-code issues.

Operational and privacy considerations

Order emails handle personal data. Send only information that the recipient needs. Avoid including complete delivery addresses, payment instrument details, tax identifiers, or internal notes in an email unless there is a clear customer-facing reason and your compliance requirements permit it.

Set retention rules for webhook payloads and logs. The raw notification itself contains less data than the full order response, which is one reason fetching the order only when needed is useful. Redact emails in broad-access logs where possible, encrypt stored tokens, and restrict database access to the personnel and services that operate the integration.

Monitor both sides of the pipeline. Useful metrics include received webhooks, accepted queue jobs, duplicate suppressions, missing-recipient skips, Nuvemshop API failures, Volanea API failures, send latency, and successful provider message IDs. A rising duplicate count can signal response-time trouble; a spike in missing recipients can signal a checkout or API behavior change.

Alternatives when you do not operate a backend

If you cannot host middleware, use an automation platform only if it can receive the relevant Nuvemshop event, securely call the Nuvemshop API when necessary, and make an authenticated server-side request to Volanea. Platforms such as Make or Zapier can be useful for prototypes, but check the exact Nuvemshop connector triggers, available fields, polling behavior, retry semantics, secret storage, task limits, and data-residency implications before relying on one for buyer-facing transactional mail.

The architecture does not change: the automation still needs to deduplicate order events, retrieve complete order data when the trigger supplies only an ID, and protect the Volanea key in its connection vault rather than in a customer-visible field. For high-volume stores or messages with strict timing requirements, a dedicated queue and middleware service usually offer better observability and control.

Avoid browser-only approaches. A storefront script cannot safely hold sending credentials, can be blocked by extensions or navigation, and can run multiple times. The authoritative Nuvemshop order event should be the trigger, not a client-side “thank you” page load.

Conclusion

The dependable way to send email from Nuvemshop with Volanea is not a native plugin: it is a server-side webhook integration. Subscribe to the real order/created event through the Nuvemshop app API, treat the compact webhook as a notification, retrieve the order server-side, map contact_email and order fields into a Volanea message, and store an idempotency record before delivery.

That approach protects credentials, accommodates missing fields, avoids duplicate sends during retries, and leaves room to add payment, fulfillment, and support workflows later. Start with a narrow order-received email, test failure paths as carefully as the happy path, and expand only after your event and state rules are explicit.

FAQ

Does Volanea have a native Nuvemshop app?

No. This integration uses Nuvemshop’s app API and webhooks with middleware that calls Volanea’s REST email API. There is no marketplace-install flow in this setup.

What starts the email send in this guide?

The trigger is Nuvemshop’s order/created webhook event. The webhook body supplies the store ID and order ID; the middleware then fetches the complete order before sending.

Can I put the Volanea API key in my Nuvemshop theme?

No. Theme and browser code are client-visible. Store the Volanea API key only in server-side environment variables, a secret manager, or another encrypted backend credential store.

Why do I need idempotency for an order email?

Webhook deliveries can be retried after a timeout or failed response. An idempotency key tied to the store, event, order, and message purpose prevents a retry from sending the same customer email again.

Should order/created say that payment was approved?

Not by default. Order creation and payment approval are different conditions. Use payment state from the retrieved order and a separate, explicitly defined workflow before sending payment-confirmed language.