The Invoice Problem Every SaaS Faces
Your SaaS is growing. Customers are paying through Stripe. But someone — usually you — is still manually creating invoices in Google Docs or Word. Or you're paying $50+/month for an invoicing tool that does way more than you need.
There's a better way: generate invoices programmatically with an API. When a Stripe payment succeeds, call the API, get a professional PDF, and email it to the customer. Fully automated, zero manual work.
Architecture: Event-Driven Invoice Generation
The flow is simple:
- Stripe webhook fires —
invoice.payment_succeededevent - Your server receives it — validates the signature, extracts payment details
- Call an invoice API — send the line items, customer info, and payment metadata as JSON
- Get a PDF back — professional, branded, ready to send
- Email or store it — attach the PDF to a transactional email or save to S3
This entire flow runs in under 2 seconds. No human involvement. No missed invoices.
Setting Up the Stripe Webhook
First, create a webhook endpoint that listens for payment events:
@app.post("/webhooks/stripe")
async def stripe_webhook(request: Request):
payload = await request.body()
sig = request.headers.get("stripe-signature")
event = stripe.Webhook.construct_event(
payload, sig, WEBHOOK_SECRET
)
if event["type"] == "invoice.payment_succeeded":
invoice_data = event["data"]["object"]
await generate_and_send_invoice(invoice_data)
return {"status": "ok"}
Generating the Invoice PDF
Transform the Stripe event data into an invoice API request:
async def generate_and_send_invoice(stripe_invoice):
invoice_json = {
"from": {"name": "Your Company", "email": "[email protected]"},
"to": {"name": stripe_invoice["customer_name"],
"email": stripe_invoice["customer_email"]},
"items": [
{"description": line["description"],
"quantity": line["quantity"],
"unit_price": line["amount"] / 100}
for line in stripe_invoice["lines"]["data"]
],
"currency_symbol": "$",
"invoice_number": stripe_invoice["number"],
"template": "modern"
}
# Call DocuMint API
resp = httpx.post(
"https://documint.anethoth.com/api/v1/invoice",
json=invoice_json,
headers={"X-API-Key": DOCUMINT_KEY}
)
pdf_bytes = resp.content
await send_invoice_email(
stripe_invoice["customer_email"], pdf_bytes
)
Why Not Use Stripe's Built-in Invoices?
Stripe does have invoicing, but it's limited:
- No custom templates — Stripe invoices look like Stripe invoices. You can add a logo, but the layout is fixed.
- No custom fields — Need a PO number, tax ID, or custom footer? Limited options.
- PDF generation costs extra — Stripe charges for invoice finalization at scale.
- Tied to Stripe — If you ever switch payment processors, your invoicing breaks.
An API-based approach gives you full control over the design, fields, and delivery — decoupled from any payment provider.
Handling Edge Cases
Production invoice generation needs to handle:
- Failed webhook deliveries — Stripe retries, so make your handler idempotent. Check if an invoice was already generated for this payment.
- Multi-currency — Pass the currency code from Stripe. Format amounts appropriately (¥ has no decimals).
- Tax compliance — Different regions require different tax line items. Build this into your invoice JSON structure from day one.
- Credit notes and refunds — Listen for
credit_note.createdevents and generate matching credit note PDFs.
The Result
With this setup, every payment automatically produces a professional invoice. Your customers get PDFs instantly. Your accountant gets consistent, machine-readable documents. And you never manually create an invoice again.
DocuMint handles the PDF generation — send JSON, get a PDF in under 500ms. Free tier includes 10 invoices/month, enough to set this up and test it end-to-end before you need a paid plan.
Try DocuMint free
Stop manually creating invoices. Get started with our free tier — no credit card required.
Get started free →