Xero · Automation

How to Automatically Send Receipts to Customers Using Xero Receipt Rocket

The moment an invoice is marked paid in Xero, your customer gets a branded PDF receipt in their inbox — no copying, no forwarding, no manual steps. This guide walks through the full setup, from connecting the app to firing your first live receipt.

10 min read April 2026 Xero Cloud

Why Automate Customer Receipts?

Xero has rock-solid invoicing, but it doesn't email a receipt to the customer when an invoice is paid. Most businesses either skip the receipt, remember to send one manually, or paste payment details into an email and hope it looks professional. Over a year, that's thousands of missed touchpoints with paying customers.

Xero Receipt Rocket is a small, purpose-built app that closes that gap. It listens for Xero's "invoice paid" webhook, pulls the invoice data, renders a branded PDF receipt, and emails it to the customer — automatically, every time, within seconds of the payment being recorded.

🚀
What you get at the end of this guide

Every paid invoice in Xero — whether marked via the Xero UI, reconciled from a bank feed, or paid via Stripe/GoCardless — triggers an automatic receipt email with a PDF attachment. No human involvement, no duplicates, no missed receipts.

How It Works (The Flow)

Xero Receipt Rocket sits between Xero's webhook and your email server. Here's what happens from the moment a payment is reconciled:

1
Invoice is marked paid in Xero

You reconcile the bank feed, apply a payment, or a Stripe charge posts — Xero's invoice status flips to PAID.

2
Xero fires the invoice webhook

Xero pushes a signed webhook to Receipt Rocket's /webhook.php endpoint with the invoice's unique ID.

3
Signature verified, invoice fetched

The app validates the HMAC-SHA256 signature, then fetches the full invoice from Xero's API — contact, email, line items, amount, tax, payment date.

4
Duplicate guard runs

A SQLite-backed duplicate check makes sure the same invoice never gets a second receipt, even if Xero re-fires the webhook.

5
PDF receipt is generated

Your HTML template is merged with the invoice data using Dompdf — logo, business details, line items, total paid, payment method.

6
Email sent via SMTP

PHPMailer delivers the receipt email to the customer's address on file, with the PDF attached and a download link for future reference.

Prerequisites

Before you start, make sure you have:

  • A Xero organisation where you can access Advanced Settings → Connected Apps
  • Access to developer.xero.com/myapps (free, separate from your Xero login)
  • SMTP credentials for outgoing email — Gmail with an app password works well, or any transactional provider (SendGrid, Postmark, Mailgun)
  • A server or hosting account where Receipt Rocket will run — PHP 8.0+ with Composer; cPanel works fine
  • A publicly-reachable HTTPS URL (Xero will not deliver webhooks over HTTP)
⚠️
HTTPS is non-negotiable

Xero refuses to send webhooks to plain HTTP endpoints. If you're testing locally, use ngrok to tunnel a public HTTPS URL to your machine. On production, make sure your hosting has a valid SSL certificate.

Step-by-Step Setup

1

Deploy Receipt Rocket to your server

Upload the Receipt Rocket project folder to your hosting, then install dependencies:

# from the project root
composer install
# create the storage directories
mkdir -p storage/logs storage/receipts database
chmod -R 775 storage database

Point your web server's document root at the public/ folder. The app is self-contained — SQLite database, log files, and generated receipts all live inside the project folder, no external dependencies beyond PHP and SMTP.

2

Create a Xero developer app

Go to developer.xero.com/myapps and create a new app. Set the Redirect URI to:

https://your-domain.com/callback.php

Copy the Client ID and Client Secret — you'll drop these into the app's .env file in the next step.

3

Configure .env

Copy .env.example to .env and fill in your credentials. The three sections that matter:

# Xero
XERO_CLIENT_ID=your-client-id
XERO_CLIENT_SECRET=your-client-secret
XERO_REDIRECT_URI=https://your-domain.com/callback.php
XERO_WEBHOOK_KEY=set-this-after-step-5

# SMTP
SMTP_HOST=smtp.gmail.com
SMTP_PORT=587
SMTP_USER=you@yourcompany.com
SMTP_PASS=your-app-password
SMTP_FROM_NAME=Your Business Name

# Business details (shown on the receipt)
BUSINESS_NAME=Your Business Sdn Bhd
BUSINESS_ADDRESS=123 Main St, Kuala Lumpur
BUSINESS_EMAIL=info@yourcompany.com
BUSINESS_PHONE=+60 3 0000 0000
BUSINESS_WEBSITE=https://yourcompany.com
4

Connect the app to Xero (OAuth)

Open your Receipt Rocket dashboard at https://your-domain.com/ and click Connect Xero. You'll be redirected to Xero to authorise the app — choose the organisation you want to send receipts from, accept the permissions, and Xero sends you back to the dashboard.

From this point on, Receipt Rocket has a refresh token and can read invoices on your behalf. You never need to log in again.

5

Register the webhook in Xero

Back in your Xero developer app, open Webhooks and set the delivery URL:

https://your-domain.com/webhook.php

Subscribe to the Invoices event type. Xero generates a webhook signing key — copy it into your .env as XERO_WEBHOOK_KEY, then click Send intent to receive. Receipt Rocket must respond with HTTP 200 within a few seconds for Xero to activate the webhook.

🔑
Why two separate keys?

The Client ID/Secret authorise the app to read Xero data. The webhook signing key is used to verify that incoming webhook requests actually came from Xero and haven't been tampered with. Both must be set correctly for the pipeline to work.

6

Customise the receipt template

Two files control how your receipts look and read:

  • templates/pdf/receipt.html — the PDF receipt itself (logo, layout, line items)
  • templates/email/receipt.html — the covering email body

Both use simple {{VARIABLE}} placeholders that are replaced at send time — {{CUSTOMER_NAME}}, {{RECEIPT_NUMBER}}, {{AMOUNT_PAID}}, {{PAYMENT_DATE}}, and so on. Preview changes from the dashboard's Template Preview page before going live.

7

Test the full flow

The safest way to test is Xero's Demo Company — it's a sandbox org inside Xero with fake contacts and invoices. Connect Receipt Rocket to the Demo Company, then:

  • Open any invoice in Xero and set the contact's email to your own address
  • Mark the invoice as paid (or apply a payment)
  • Watch the Receipt Rocket dashboard — you should see a new row in the Sent Receipts list within seconds
  • Check your inbox for the branded PDF receipt

If something doesn't arrive, check storage/logs/app-YYYY-MM-DD.log — it logs every webhook received and every decision the app makes.

What Happens Once You Go Live

Flip your Receipt Rocket connection from the Demo Company to your production organisation, and the automation runs continuously — no cron, no scheduled tasks. Xero pushes webhooks in real time, so receipts land in customer inboxes within seconds of payment reconciliation.

📧

Every Paid Invoice

Customer gets a branded PDF receipt email automatically — no matter how the invoice was paid

🛡️

No Duplicates

The duplicate guard stops the same receipt being sent twice, even if Xero re-delivers a webhook

📂

Audit Trail

Every sent receipt is saved to the dashboard and to storage/receipts/ for re-download

🎨

Fully Branded

Your logo, colours, address, and wording — not a generic Xero template

🔄

Token Auto-Refresh

OAuth refresh tokens rotate automatically — you don't reconnect every 30 days

📝

Daily Log Files

Every decision and every send is logged so you can troubleshoot or audit later

Common Issues & Fixes

Problem Fix
Webhook not received Confirm the webhook URL in Xero matches your APP_URL, and that the site is reachable over public HTTPS.
Signature mismatch (HTTP 401) Check that XERO_WEBHOOK_KEY in .env matches the key in the Xero app dashboard exactly — no trailing spaces.
Token expired / disconnected Click Reconnect Xero from the dashboard. Going forward the refresh token rotates automatically every 30 minutes.
Email not sending For Gmail, use an App Password (not your login password) and confirm 2FA is enabled. For other providers, verify SMTP host/port/TLS are correct.
PDF is blank or missing fields Check that all BUSINESS_* variables are set in .env — missing values break template rendering.
SQLite permission error Run chmod -R 775 storage database on the server so the web user can write the database file and receipts.
Can't see what happened Open storage/logs/app-YYYY-MM-DD.log — every webhook, every skip, every send is recorded with timestamps.

Frequently Asked Questions

Does this work with multi-currency invoices?
Yes — Receipt Rocket fetches the invoice currency and total from Xero's API, so receipts match whatever currency the invoice was raised in. The PDF template shows the currency code alongside the amount.
What if the customer doesn't have an email address in Xero?
The app logs a warning, skips the email send, but still marks the receipt as generated so no duplicate is attempted. You can manually download the PDF from the dashboard and forward it yourself. A future release will surface "email missing" as a dashboard alert.
Can I send receipts only for certain invoices?
Yes — Receipt Rocket exposes a filter in receipt-settings.php where you can exclude certain invoice types, statuses, or tracking categories. For example, you might skip receipts for internal journal entries or draft credit notes.
Does it work with Stripe, GoCardless, or other payment gateways?
Yes. Receipt Rocket doesn't care how a payment was applied — only that Xero's invoice status moved to PAID. Stripe Feed, GoCardless, manual payments, and bank reconciliations all trigger the same webhook.
Can I re-send a receipt that was already sent?
Yes — the dashboard's Sent Receipts list has a "Resend" button on each row. The duplicate guard only blocks automatic re-sends from repeated webhooks; manual resends from the dashboard are always allowed.
How do I change the receipt's look and wording?
Edit templates/pdf/receipt.html for the PDF and templates/email/receipt.html for the covering email. Both are plain HTML with {{VARIABLE}} placeholders, so you can change fonts, colours, copy, and layout without touching PHP. Use the dashboard's Template Preview to check changes before they go live.
Do I need to be a developer to run this?
To deploy the app and configure the .env file you'll want someone comfortable with cPanel/SSH and basic PHP hosting. Once it's running, day-to-day use is zero-touch — the dashboard has a settings page for changing templates and SMTP details without editing code.

Need help setting it up?

Xero Receipt Rocket is built and maintained by FusionETA — Malaysia's Xero Gold Partner. We can deploy, configure, and brand the app for your business in under a week. Get in touch to discuss.

Ready to Stop Sending Receipts Manually?

We deploy Xero Receipt Rocket for businesses across Malaysia — fully branded, configured for your SMTP, and wired to your Xero organisation. Most setups go live in under a week.