Rechnungs-E-Mail

Versenden Sie nach einer erfolgreichen Zahlung eine Zahlungsbestätigung mit angehängter Rechnungs-PDF.

Versenden Sie nach einer erfolgreichen Zahlung eine Zahlungsbestätigung mit angehängter Rechnungs-PDF.

Voraussetzungen

  • Ein veröffentlichtes transaktionales Template mit dem Slug billing-receipt, das die Variablen customerName, invoiceNumber, amountPaid, billingDate und planName enthält
  • Ein API-Schlüssel mit Berechtigungen für den transaktionalen Versand

Mit einem URL-Anhang versenden

Wenn Ihre Rechnungs-PDF unter einer URL liegt (z. B. bei Stripe oder in Ihrem eigenen Speicher), übergeben Sie sie über das Feld url:

import { Owlat } from '@owlat/sdk-js'

const owlat = new Owlat('lm_live_...')

await owlat.transactional.send({
  slug: 'billing-receipt',
  email: 'mira@acme.io',
  dataVariables: {
    customerName: 'Mira Chen',
    invoiceNumber: 'INV-2026-0042',
    amountPaid: '$49.00',
    billingDate: 'March 19, 2026',
    planName: 'Pro',
  },
  attachments: [
    {
      filename: 'invoice-INV-2026-0042.pdf',
      url: 'https://files.stripe.com/invoices/INV-2026-0042.pdf',
      contentType: 'application/pdf',
    },
  ],
})
curl -X POST https://your-deployment.convex.site/api/v1/transactional \
  -H "Authorization: Bearer lm_live_..." \
  -H "Content-Type: application/json" \
  -d '{
    "slug": "billing-receipt",
    "email": "mira@acme.io",
    "dataVariables": {
      "customerName": "Mira Chen",
      "invoiceNumber": "INV-2026-0042",
      "amountPaid": "$49.00",
      "billingDate": "March 19, 2026",
      "planName": "Pro"
    },
    "attachments": [
      {
        "filename": "invoice-INV-2026-0042.pdf",
        "url": "https://files.stripe.com/invoices/INV-2026-0042.pdf",
        "contentType": "application/pdf"
      }
    ]
  }'

Mit einem Base64-Anhang versenden

Wenn Sie die PDF im Arbeitsspeicher erzeugen (z. B. mit einer Bibliothek wie pdfkit oder jspdf), kodieren Sie sie als Base64 und verwenden das Feld content:

import { Owlat } from '@owlat/sdk-js'

const owlat = new Owlat('lm_live_...')

// pdfBuffer is a Buffer from your PDF generation library
const base64Pdf = pdfBuffer.toString('base64')

await owlat.transactional.send({
  slug: 'billing-receipt',
  email: 'mira@acme.io',
  dataVariables: {
    customerName: 'Mira Chen',
    invoiceNumber: 'INV-2026-0042',
    amountPaid: '$49.00',
    billingDate: 'March 19, 2026',
    planName: 'Pro',
  },
  attachments: [
    {
      filename: 'invoice-INV-2026-0042.pdf',
      content: base64Pdf,
      contentType: 'application/pdf',
    },
  ],
})
Grenzwerte für Anhänge

Sie können pro E-Mail bis zu 10 Dateien mit insgesamt maximal 10 MB anhängen. Halten Sie Rechnungs-PDFs schlank — entfernen Sie unnötige Schriftarten und komprimieren Sie Bilder.

Vollständiger Stripe-Webhook-Handler

Ein praxisnahes Beispiel, das auf Stripes Event invoice.payment_succeeded lauscht und die Zahlungsbestätigung versendet:

import { Hono } from 'hono'
import Stripe from 'stripe'
import { Owlat } from '@owlat/sdk-js'

const app = new Hono()
const stripe = new Stripe(process.env.STRIPE_SECRET_KEY!)
const owlat = new Owlat(process.env.OWLAT_API_KEY!)

app.post('/webhooks/stripe', async (c) => {
  const payload = await c.req.text()
  const signature = c.req.header('stripe-signature')!

  // 1. Verify the Stripe signature
  const event = stripe.webhooks.constructEvent(
    payload,
    signature,
    process.env.STRIPE_WEBHOOK_SECRET!
  )

  if (event.type === 'invoice.payment_succeeded') {
    const invoice = event.data.object as Stripe.Invoice

    // 2. Send the billing receipt
    await owlat.transactional.send({
      slug: 'billing-receipt',
      email: invoice.customer_email!,
      dataVariables: {
        customerName: invoice.customer_name ?? 'Customer',
        invoiceNumber: invoice.number ?? invoice.id,
        amountPaid: `$${(invoice.amount_paid / 100).toFixed(2)}`,
        billingDate: new Date(invoice.created * 1000).toLocaleDateString('en-US', {
          year: 'numeric',
          month: 'long',
          day: 'numeric',
        }),
        planName: invoice.lines.data[0]?.description ?? 'Subscription',
      },
      attachments: invoice.invoice_pdf
        ? [
            {
              filename: `invoice-${invoice.number}.pdf`,
              url: invoice.invoice_pdf,
              contentType: 'application/pdf',
            },
          ]
        : [],
    })
  }

  return c.json({ received: true })
})

Nächste Schritte