Short Answer
A self-hosted or cloud-based n8n workflow that triggers on every New Order, validates customer data, handles multi-line items via expressions, and generates a formatted invoice and payment record in Xero instantly.
The Problem
Manual entry of e-commerce sales into accounting software is time-consuming and prone to human error. Discrepancies between Shopify revenue and Xero ledger often lead to reconciliation nightmares during tax season and inaccurate financial reporting.
The Outcome
A self-hosted or cloud-based n8n workflow that triggers on every New Order, validates customer data, handles multi-line items via expressions, and generates a formatted invoice and payment record in Xero instantly.
Step-by-Step Guide
1. **Create Workflow**: In n8n, create a new workflow and add the 'Shopify Trigger' node. Set the event to 'Order Created'.
2. **Configure Credentials**: Select 'Shopify API' credentials. You will need your Shopify Store Name and an Admin API access token (configured in Shopify Apps > Develop Apps).
3. **Identify/Create Contact**: Add a 'Xero' node. Choose the 'Contact' resource and 'Get or Create' operation. Use an expression to map `{{ $json.customer.email }}` from Shopify to the 'Email Address' field in Xero to prevent duplicates.
4. **Handle Line Items**: Use a 'Code' node or 'Set' node with the 'Line Items' array from Shopify. n8n treats arrays as separate items; use an expression like `{{ $json.line_items.map(item => ({ Description: item.name, UnitAmount: item.price, Quantity: item.quantity })) }}` to format them for Xero's API.
5. **Format Dates & Currency**: Use the n8n expression `$now` or Shopify's `created_at` field. Ensure the date format is `YYYY-MM-DD` using the `.format('YYYY-MM-DD')` JavaScript method within the expression.
6. **Create Invoice**: Add another 'Xero' node. Set Resource to 'Invoice' and Operation to 'Create'. Map the Contact ID from Step 3 and the line items from Step 4. Set 'Status' to 'AUTHORISED' for immediate ledger impact.
7. **Log Payment**: Add a final 'Xero' node. Resource: 'Payment', Operation: 'Create'. Link this to the Invoice ID generated in Step 6 to mark the invoice as paid.
8. **Implement Error Handling**: Create an 'Error Trigger' node. Connect it to a 'Gmail' or 'Slack' node to notify you if an API limit is hit or if a tax rate is missing.
9. **Test Workflow**: Click 'Execute Workflow' and place a test order in Shopify (in Bogus Gateway mode) to verify data flow in n8n's execution log.
Data Mapping
| Shopify Field | Xero Field | Transformation / Expression | Required |
| :--- | :--- | :--- | :--- |
| `customer.email` | Contact Email | `{{ $json.customer.email }}` | Yes |
| `order_number` | Reference | `Shopify-{{ $json.order_number }}` | No |
| `line_items` | LineItems | `{{ $json.line_items }}` (Mapped via JSON Object) | Yes |
| `total_tax` | TotalTax | `{{ parseFloat($json.total_tax) }}` | Yes |
| `currency` | CurrencyCode | `{{ $json.currency }}` | Yes |
| `created_at` | Date | `{{ $json.created_at.split('T')[0] }}` | Yes |
Gotchas & Failure Modes
* **Line Item Mapping**: n8n's Xero node expects an array of objects. Mapping individual fields one-by-one in the UI often fails; use a 'Set' node with 'Keep Only Set' active to clean the data first.
* **Rate Limiting**: Xero has a limit of 60 calls per minute. If you have a high volume of orders, use an n8n 'Wait' node or the 'Split In Batches' node to throttle traffic.
* **Tax Rates**: Xero requires specific Tax Types (e.g., 'OUTPUT', 'NONE'). If Shopify tax names don't match Xero's internal codes, use an 'IF' node or 'Switch' node in n8n to map them.
* **Rounding Errors**: Ensure you use `parseFloat()` in n8n expressions to avoid string concatenation issues with price values.
Verification Checklist
- [ ] Shopify Webhook status shows 'Active' in n8n Trigger Node.
- [ ] Xero Contact is found by email (no duplicate contacts created).
- [ ] Line items display correct quantities and unit prices in Xero Invoice draft.
- [ ] Invoice status is 'AUTHORISED' (or 'DRAFT' if you prefer manual approval).
- [ ] Payment record is successfully attached to the Invoice ID.
- [ ] Execution log in n8n shows 200 OK for all node steps.
Ready to Automate?
Build this automation with n8n in minutes.