App guides

The Resend app sends your store's notification emails through your own Resend account, from an address on your own domain. It uses the notification templates you already have in Settings > Notifications, so there's no second set of templates to keep up to date.

Each email the app covers has its own setting, and Custom notifications sends other notification templates on events you choose. An email is sent through Resend only after you turn off Swell's own version of it.

WhenWhat the app does
An order, shipment, refund, account, cart or subscription event happens, and its email is turned onReads the notification from Settings > Notifications, renders it with the order, customer, cart or subscription, and sends it through Resend to the notification's recipient.
Swell's own version of that email is still onSkips the email and logs why, so the customer doesn't get two copies.
An event matches a row in Custom notificationsSends the named notification, without checking whether Swell also sends it.
Resend can't be reached, rate-limits the app or has a server errorFails the event, so Swell delivers it again later. Emails the event already sent aren't sent again within 24 hours.
Resend rejects an email, for example because the domain isn't verifiedLogs the error and doesn't try again.
  • A Resend account with a verified domain to send from.
  • Your notifications set up in Settings > Notifications. The app sends each one with its own subject, content and template, and to the same recipient as Swell.

Install Resend from the Swell App Store, and set it up in your test environment before the live one.

1
Verify your domain

In Resend, open Domains, add the domain you send email from, and add the DNS records Resend lists at your DNS provider. Resend sends email only from verified domains.

2
Create an API key

In Resend, open API Keys and create a key with Sending access. Copy the key, which starts with re_.

3
Add them to the app

In Swell, go to Apps > Resend > Settings and enter the API Key and the From Address, an address on your verified domain such as orders@yourstore.com. To show a sender name, enter From Name. To send customer replies to another address, enter Reply-To Address. Click Save settings.

4
Choose the emails

On the same page, turn on each email you want Resend to send and click Save settings. Order confirmation, Shipping confirmation and New subscription are on at first. Shipping and abandoned cart emails work differently; see Shipping and abandoned cart emails.

5
Turn off Swell's own emails

Go to Settings > Notifications, turn off Swell's version of each email you turned on in the app, and click Save changes. Until you do, Swell keeps sending the email and the app skips it. You can switch one email at a time. Swell's own Subscription invoice is off unless you turned it on. For abandoned cart emails, turn off the Abandoned cart switch. Shipping emails are turned off through the Swell API; see Shipping and abandoned cart emails.

6
Place a test order

Place an order with your own email address. With Order confirmation switched to Resend, one order confirmation arrives, from your From Address, and Resend lists it under Emails. Check that it looks the way you expect. If no email arrives, see Troubleshooting.

7
Go live

Settings are saved separately for each environment, and so is each notification you turn off in Settings > Notifications. In the live environment, repeat steps 3 to 5.

Each email has a setting in Apps > Resend > Settings, and uses the template of the Swell notification in the last column.

App settingSent whenSwell notification
Order confirmationAn order is placed, or a draft order is submitted. Orders created with notify set to false are skipped.Order confirmation
Shipping confirmationA shipment is created, unless it's a draft.Shipping confirmation
Shipping updateA shipment's tracking number is set or changed, unless the shipment is a draft. Other edits to a shipment are skipped.Shipping update
Order canceledAn order is canceled.Order canceled
Order refundA refund succeeds. The email lists every refund on the order.Order refunded
Customer welcomeA customer account is created with a password. Guest accounts are skipped.Customer welcome
Abandoned cart recoveryA cart is abandoned. Carts without a customer account or without items are skipped.Abandoned cart
New subscriptionA subscription is created active.New subscription
Subscription canceledA subscription is canceled.Subscription canceled
Subscription pausedA subscription is paused, unless it's canceled.Subscription paused
Subscription resumedA paused subscription resumes, unless it's canceled.Subscription resumed
Subscription invoiceA subscription invoice is created, unless the subscription total is 0. The email shows the latest invoice.Subscription invoice

An email is sent through Resend when its setting in the app is on and Swell's own version is off. For most emails, you turn Swell's version off in Settings > Notifications. Shipping and abandoned cart emails are turned off differently. While Swell's version is on, the app skips the email and logs that Swell's email is still on, so customers never get both. If Swell's version is off and the app's setting is off too, neither Swell nor the app sends the email.

The app checks Swell's version each time it sends. To switch an email back to Swell, turn Swell's version on again.

Swell's own Shipping confirmation and Shipping update have no switch in Settings > Notifications, so the app skips them until you turn Swell's versions off through the Swell API. Swell sends its own shipping emails when you check Send email confirmation to customer on a fulfillment. To turn them off with the Swell CLI, find the notification's ID, then set enabled to false:

swell api get "/:notifications?model=orders&name=shipped.v2"
swell api put /:notifications/<notification ID> --body '{"enabled": false}'

Repeat both commands for shipped-update.v2, and add --live in the live environment. Saving Settings > Notifications afterwards keeps them off. To switch shipping emails back to Swell, set enabled to true. Once Swell's versions are off, the app sends a shipping confirmation for every shipment that isn't a draft, whether or not Send email confirmation to customer is checked. It sends a shipping update when a shipment's tracking number is set or changed, and not for other edits.

Swell sends its abandoned cart emails while the Abandoned cart switch in Settings > Notifications is on. To send the abandoned cart email through Resend, turn off the Abandoned cart switch and click Save changes. Swell then sends no abandoned cart emails, including follow-ups, and the app sends one email for each abandoned cart that has a customer account and items.

Each email uses the notification's subject, content fields and template as they are when the email is sent, so your edits in Settings > Notifications apply to the next email. The record is loaded with the same related data Swell loads for its own email, and the logo and Primary color come from Branding in Settings > Notifications.

  • Prices are formatted in the record's currency.
  • Templates are rendered with Liquid. Swell's own currency and img_url filters are supported, and are the only Swell filters the standard templates use. Other Swell-specific filters aren't supported.

Each notification in Settings > Notifications has an optional From email and BCC emails, and the app uses them:

  • A From email on the same domain as the app's From Address is the sender, with your From Name and Reply-To Address.
  • A From email on any other domain becomes the Reply-To address, and the email is sent from the From Address. Resend sends only from verified domains, and Swell's own emails put the From email in Reply-To too.
  • Without a From email, the email is sent from the From Address, with the Reply-To Address if you entered one.
  • Each address in BCC emails gets a blind copy. CC addresses set on the notification through the Swell API get a copy.

To send another notification through Resend, add a row under Custom notifications in Apps > Resend > Settings:

  • Trigger event: the event that sends the email. The list includes events with no built-in email, such as order.paid, order.delivered, subscription.paid and subscription.trial_will_end.
  • Notification name: the notification's name, not its label. The names of Swell's standard notifications end in .v2, such as recovery.v2.
  • Record ID field: where the record's ID is in the event. Leave it empty to use id.
  • Enabled: turns the row off without removing it.

The notification must belong to the same kind of record as the event: an order. event sends an order notification, a subscription. event a subscription notification, and so on. A shipment. or payment. event looks for a shipment or payment notification, so it can't send an order's shipping or refund email.

Custom rows don't check whether Swell also sends the notification. Turn off Swell's version yourself, or the customer gets two emails.

When Resend can't be reached, rate-limits the app or has a server error, the app fails the event and Swell delivers it again later, for up to about 4 days. Each email is sent with a key that Resend keeps for 24 hours, so an email that was delivered isn't sent again when the event is retried within that time.

When Resend rejects an email, for example because of an invalid API key or a From Address on a domain that isn't verified, the error is logged and the email isn't retried. Fix the setting; later emails are sent normally. A failed email doesn't stop the other emails for the same event.

WhereWhat it's for
Apps > Resend > SettingsThe API key and sender, the setting for each email, and Custom notifications.
Settings > NotificationsSwell's own emails, which you turn off to send them through Resend, and the templates, From email, BCC emails and Branding the app uses.
Developer > Console > LogsA line for each email the app sends or skips, and each error.

Settings are in Apps > Resend > Settings and are saved separately for each environment.

SettingDescriptionDefault
API KeyYour Resend API key, which starts with re_ and needs Sending access. Masked on the settings page. Required.None
From AddressThe sender address, on a domain verified in Resend. A notification's From email on the same domain is used instead. Required.None
From NameThe sender name recipients see, such as Acme Store.None
Reply-To AddressThe address customer replies go to, unless the notification's From email is on another domain.None
Order confirmation (order.submitted → receipt)Sends the order confirmation when an order is submitted.On
Shipping confirmation (shipment.created → shipped)Sends the shipping confirmation when a shipment that isn't a draft is created. Sends only after Swell's version is turned off through the Swell API.On
Shipping update (shipment.updated with a new tracking number → shipped-update)Sends the shipping update when a shipment's tracking number is set or changed. Sends only after Swell's version is turned off through the Swell API.Off
Order canceled (order.canceled → canceled)Sends the order canceled email when an order is canceled.Off
Order refund (payment.refund.succeeded → refund)Sends the refund email when a refund succeeds.Off
Customer welcome (account.created → welcome)Sends the welcome email when a customer creates an account with a password.Off
Abandoned cart recovery (cart.abandoned → recovery)Sends the abandoned cart email when a cart with a customer account and items is abandoned. Sends only while the Abandoned cart switch in Settings > Notifications is off.Off
New subscription (subscription.created → new)Sends the new subscription email when an active subscription is created.On
Subscription canceled (subscription.canceled → canceled)Sends the subscription canceled email.Off
Subscription paused (subscription.paused → paused)Sends the subscription paused email.Off
Subscription resumed (subscription.resumed → resumed)Sends the subscription resumed email.Off
Subscription invoice (subscription.invoiced → invoice)Sends the subscription invoice email when an invoice is created.Off
Custom notificationsRows that each send a notification on a trigger event, with Trigger event, Notification name, Record ID field and Enabled.None
  • Swell's Shipping confirmation and Shipping update can't be turned off in the dashboard, so switching them to Resend takes the Swell API, as described under Shipping and abandoned cart emails.
  • The app doesn't see Send email confirmation to customer on a fulfillment. It sends a shipping confirmation for every shipment that isn't a draft, and a shipping update only when a tracking number is set or changed.
  • The app sends only the first abandoned cart email. Turning off the Abandoned cart switch also stops Swell's follow-up emails.
  • The app has no setting for Draft order invoice, Gift card, Password reset, Subscription payment expiring, Subscription payment failed, Payment confirmation or the Order received email to admins. Keep Swell's own version of these on.
  • Every email goes to the notification's one recipient and its BCC emails. A notification's From email is the sender only when it's on the same domain as the app's From Address. On any other domain, it becomes the Reply-To address.
  • A customer gets the welcome email only when the account is created with a password. A guest who sets a password later doesn't get one.
  • A notification template that uses one of Swell's Liquid filters other than currency and img_url may not render the same as Swell's email.
  • Protection against sending an email twice lasts 24 hours, and Swell retries a failed event for up to about 4 days. If Swell delivers an event again after 24 hours, an email it already sent can be sent again.
  • Custom notifications can send only notifications of the event's own kind of record, and don't check Swell's own emails.

The app logs each email it sends or skips, and each error, in lines that start with Resend:. In the Swell dashboard, the logs are under Developer > Console > Logs.

The app's setting for that email is off. Turn it on in Apps > Resend > Settings and click Save settings. If Swell's own version is off too, no email is sent at all.

Enter the API Key and From Address in Apps > Resend > Settings and click Save settings. No email is sent until both are set.

Swell still sends this email, so the app skipped it. Turn off Swell's version in Settings > Notifications and click Save changes. The log quotes the template's own label, which can differ from the name in Settings > Notifications, for example Order Receipt for Order confirmation. For abandoned carts, the rest of the line says to turn off the Abandoned cart switch. For shipping emails, it says to set enabled to false through the API. See Shipping and abandoned cart emails.

Swell sends no shipping emails for draft shipments, and the app sends a shipping update only when an edit sets or changes the tracking number. The email isn't sent, and there's nothing to fix.

Swell sends abandoned cart emails only for carts with a customer account and items, and the app does the same. The email isn't sent, and there's nothing to fix.

No notification with that name belongs to the event's kind of record. For a custom notification, check that Notification name is the notification's name, not its label, and that the notification belongs to the same kind of record as the Trigger event.

The record has no address in the field the notification sends to, for example a cart without a customer email. The email isn't sent.

Resend rejected the email, and the message after the status code says why, for example an invalid API key, a From Address on a domain that isn't verified, or an invalid address in a notification's BCC emails. Fix the key in Apps > Resend > Settings, verify the domain in Resend, or correct the BCC emails in Settings > Notifications. These errors aren't retried, so the email isn't sent.

Resend rate-limited the app, had a server error or couldn't be reached. Swell delivers the event again later. A 429 can also mean your Resend plan's daily or monthly limit was reached.

A custom notification sends a notification that Swell also sends. Turn off Swell's version in Settings > Notifications. For abandoned carts, leave the Abandoned cart switch off.

Swell's Liquid filters other than currency and img_url aren't supported. To compare, send Swell's version from the notification's Test email tab in Settings > Notifications.

Uninstalling the app removes its functions and settings, so emails stop going through Resend. Swell's own notifications that you turned off stay off, and customers get no email for them until you turn them on again in Settings > Notifications. To keep emails going, turn Swell's versions back on before you uninstall: the Abandoned cart switch for abandoned carts, and enabled set to true through the API for shipping emails. The app skips them from then on. Uninstalling applies to the environment you are in, so remove the app from the test and live environments separately.

Emails already sent stay in your Resend account. If you no longer need the API key, delete it in Resend under API Keys.

FunctionRuns onWhat it does
order-emailsorder.submitted, order.paid, order.canceled and order.deliveredSends the order confirmation and order canceled emails, and custom notifications on these events.
shipment-emailsshipment.created and shipment.updatedSends the shipping confirmation and update, rendered with the order and the shipment that raised the event.
payment-emailspayment.refund.succeededSends the refund email, rendered with the order and every refund on it.
account-emailsaccount.createdSends the welcome email to accounts with a password.
cart-emailscart.abandonedSends the abandoned cart email.
subscription-emailssubscription.created, activated, paused, resumed, canceled, invoiced, paid, trial_will_end and trial_endedSends the new, paused, resumed, canceled and invoice subscription emails, and custom notifications on these events.

Every function calls the same handler. It reads the notification config from /:notifications by name and model, because names such as canceled.v2 and invoice.v2 exist on more than one model. A built-in email is skipped unless the config's enabled is false. recovery.v2 is also sent while abandoned_cart.enabled in /settings/notifications isn't true. The record is loaded with the config's query.expand, and the HTML is fetched from content.html.url, with a cdn.swell.test host replaced by cdn.swell.store, and rendered with the browser build of liquidjs. The render context is the record plus store (/settings/store with the logo, logo width, footer and store_color from /settings/notifications, which defaults to #614ed0, and name and support_email from /:clients/:self when /settings/store has none, then from from_name and reply_to), content (the rendered fields) and the data Swell's own emails get through $notify.data: refunds, shipment or invoice.

Emails are sent with POST https://api.resend.com/emails and an Idempotency-Key of swell-resend/<event type>/<event id>/<model>.<name>. The config's from, or the deprecated replyto, is the from when its domain matches from_email, and the reply_to otherwise. Its comma-separated cc and bcc are sent as cc and bcc. Network errors, 429 and 5xx responses are rethrown so Swell retries the event. Other 4xx responses are thrown with retry: false. The app has no models, content views or $app fields.

Swell builds and maintains the Resend app. For help with the app, email support@swell.is. For questions about your Resend account, domains or sending limits, contact Resend.