# How to Build Branded Polar.sh Email Receipts and License Delivery (2026 Guide)

_By Tayyab Mughal, Founder & Chief Architect · 06 November 2026 · 5 min read_

> Learn how to connect Polar.sh webhooks with SadaSend and React Email for sub-150ms branded purchase receipts, license keys, and VAT invoices.

A production-ready walkthrough for building branded Polar.sh purchase receipts, license delivery, and subscription notifications with Next.js 15 and React Email.

## The Merchant of Record dilemma: Global tax compliance vs. branded customer experience

Polar.sh has become the preferred Merchant of Record (MoR) for software engineers, open-source maintainers, and micro-SaaS founders in 2026. By acting as the merchant of record, Polar relieves developers of the overwhelming complexity of calculating and remitting global sales tax, EU VAT, and country-specific reverse charges.

However, relying on standard platform checkout notifications creates an impersonal post-purchase experience. When customers buy your software tool or SaaS subscription, receiving an unbranded receipt from a generic platform domain creates friction. Customers frequently contact support asking "Where do I log in?" or "Where is my API license key?".

By listening to Polar.sh Svix webhooks and dispatching branded purchase receipts through SadaSend with React Email, you get complete creative control over your onboarding journey. Every invoice originates from your verified custom domain with Dual-DKIM signing and sub-150ms edge delivery.

| Feature | Default Polar Notification | SadaSend Branded Webhook Delivery |
| --- | --- | --- |
| Sending Domain | Generic polar.sh notifications | billing@yourdomain.com (100% Branded) |
| Email Markup & Layout | Standard platform receipt template | Custom React Email with product onboarding |
| License Key Injection | Requires manual customer dashboard visit | Directly embedded in receipt with 1-click copy |
| Delivery Speed | Standard background queue | Sub-150ms direct MX injection at edge |
| Bounce Protection | Penalizes sending domain | In-flight syntax & MX shield before queue |

## 1. Configuring Polar.sh webhooks in your developer dashboard

To receive real-time purchase events, configure a webhook endpoint in your Polar.sh Dashboard:

1. Navigate to Settings -> Webhooks -> Add Endpoint.

2. Enter your production webhook URL (e.g. https://yourdomain.com/api/webhooks/polar).

3. Select the events you want to listen for: order.created, subscription.created, and subscription.canceled.

4. Copy your Webhook Secret (beginning with polar_whsec_ or whsec_).

```bash
# Environment Variables (.env.local)
POLAR_WEBHOOK_SECRET=whsec_your_polar_webhook_secret_here
SADASEND_API_KEY=sada_sec_live_your_sadasend_api_key_here
```

## 2. Designing a modular purchase receipt with React Email

React Email allows you to design maintainable, responsive HTML emails using standard React components. Here is an invoice receipt component displaying itemized costs, order ID, and license key credentials:

```typescript
// emails/ReceiptEmail.tsx
import { Body, Container, Head, Heading, Html, Preview, Section, Text } from '@react-email/components';
import * as React from 'react';

interface ReceiptEmailProps {
  customerName: string;
  productName: string;
  amountFormatted: string;
  currency: string;
  licenseKey?: string;
  orderId: string;
}

export function ReceiptEmail({
  customerName,
  productName,
  amountFormatted,
  currency,
  licenseKey,
  orderId,
}: ReceiptEmailProps) {
  return (
    <Html>
      <Head />
      <Preview>Your receipt and license key for {productName}</Preview>
      <Body style={{ backgroundColor: '#f6f9fc', fontFamily: 'sans-serif' }}>
        <Container style={{ margin: '40px auto', padding: '24px', backgroundColor: '#ffffff', borderRadius: '4px' }}>
          <Heading style={{ fontSize: '20px', color: '#1a1a1a' }}>Purchase Confirmation</Heading>
          <Text style={{ fontSize: '14px', color: '#4a4a4a' }}>Hi {customerName},</Text>
          <Text style={{ fontSize: '14px', color: '#4a4a4a' }}>
            Thank you for purchasing <strong>{productName}</strong>. Your payment of {amountFormatted} {currency} has been processed.
          </Text>
          {licenseKey && (
            <Section style={{ padding: '16px', backgroundColor: '#edf2f7', borderRadius: '4px', margin: '20px 0' }}>
              <Text style={{ margin: 0, fontSize: '12px', color: '#718096', textTransform: 'uppercase' }}>Your License Key</Text>
              <Text style={{ margin: '6px 0 0', fontSize: '16px', fontFamily: 'monospace', fontWeight: 'bold' }}>{licenseKey}</Text>
            </Section>
          )}
          <Text style={{ fontSize: '12px', color: '#a0aec0' }}>Order ID: {orderId}</Text>
        </Container>
      </Body>
    </Html>
  );
}
```

## 3. Writing the Next.js 15 Route Handler with Svix signature verification

Polar.sh signs all outgoing webhook payloads using Svix. In your Next.js Route Handler, verify the signature before rendering and dispatching the email via SadaSend:

```typescript
// app/api/webhooks/polar/route.ts
import { Webhook } from 'svix';
import { headers } from 'next/headers';
import { SadaSend } from 'sadasend';
import { render } from '@react-email/render';
import { ReceiptEmail } from '@/emails/ReceiptEmail';

const sadasend = new SadaSend({ apiKey: process.env.SADASEND_API_KEY! });

export async function POST(req: Request) {
  const headerPayload = await headers();
  const svixId = headerPayload.get('webhook-id') || headerPayload.get('svix-id');
  const svixTimestamp = headerPayload.get('webhook-timestamp') || headerPayload.get('svix-timestamp');
  const svixSignature = headerPayload.get('webhook-signature') || headerPayload.get('svix-signature');

  if (!svixId || !svixTimestamp || !svixSignature) {
    return new Response('Missing Svix signature headers', { status: 400 });
  }

  const payload = await req.json();
  const body = JSON.stringify(payload);
  const wh = new Webhook(process.env.POLAR_WEBHOOK_SECRET!);

  let evt: { type: string; data: { id: string; customer: { email: string; name?: string }; product: { name: string }; amount: number; currency: string } };
  try {
    evt = wh.verify(body, {
      'svix-id': svixId,
      'svix-timestamp': svixTimestamp,
      'svix-signature': svixSignature,
    }) as typeof evt;
  } catch {
    return new Response('Invalid webhook signature', { status: 400 });
  }

  if (evt.type === 'order.created') {
    const { id, customer, product, amount, currency } = evt.data;
    const formattedPrice = (amount / 100).toFixed(2);

    // Compile React Email template to HTML string
    const emailHtml = await render(
      ReceiptEmail({
        customerName: customer.name || 'there',
        productName: product.name,
        amountFormatted: formattedPrice,
        currency: currency.toUpperCase(),
        licenseKey: `POLAR-${id.slice(0, 8).toUpperCase()}`,
        orderId: id,
      })
    );

    // Sub-150ms branded dispatch with in-flight bounce defense
    await sadasend.emails.send({
      from: 'billing@yourdomain.com',
      to: customer.email,
      subject: `Receipt & License Key: ${product.name}`,
      html: emailHtml,
      verifyBeforeSend: true,
    });
  }

  return new Response('Webhook processed successfully', { status: 200 });
}
```

## 4. Handling recurring SaaS subscription lifecycles

For recurring SaaS products, Polar emits subscription.created and subscription.canceled events. You can extend your webhook handler to dispatch welcome sequence invitations on signup and proactive feedback surveys on cancellation.

Because SadaSend provides SpendGuard, even an unexpected surge in webhook volume during a viral launch will never cause runaway overage charges.

---

_Tags: Polar.sh, Merchant of Record, React Email, Next.js 15, Invoicing_
