Short Answer
A fully automated pipeline where Dext-extracted data is validated, filtered by value, and uploaded to Xero with binary attachments. High-value items are routed for approval, and all errors are caught by n8n’s Error Trigger system.
The Problem
Manual data entry from receipts into Xero is error-prone and time-consuming. While Dext has a native sync, businesses often need custom logic—such as approval gates for high-value invoices or automated tracking category assignment—that standard integrations cannot provide.
The Outcome
A fully automated pipeline where Dext-extracted data is validated, filtered by value, and uploaded to Xero with binary attachments. High-value items are routed for approval, and all errors are caught by n8n’s Error Trigger system.
Step-by-Step Guide
1. **Establish Credentials**: In n8n, go to 'Credentials' and create 'Xero OAuth2 API' credentials. For Dext, use the 'HTTP Request' node with a 'Header Auth' (API Key) or OAuth2 if available for your region.
2. **Configure Trigger**: Add an 'HTTP Request' node to poll the Dext `GET /items/ready` endpoint on a Cron schedule (e.g., every 15 minutes) or use a Webhook node if your Dext plan supports outbound webhooks.
3. **Extract Item Details**: Use a 'Set' or 'Edit Image' node to isolate key fields: `supplier_name`, `total_amount`, `tax_amount`, and `image_url`.
4. **Handle Item Binary**: Dext provides a URL for the image. Use an 'HTTP Request' node set to 'Response Format: File' to download the original PDF/Image into n8n's memory.
5. **Duplicate Check**: Add a 'Xero' node with the 'Get Many' operation for Bills. Use an expression to filter by `Reference` (using the Dext Invoice ID) to ensure the bill hasn't already been created.
6. **Contact Logic**: Add a 'Xero' node set to 'Contact: Get' by name. Follow this with an 'IF' node; if no contact exists, use a second 'Xero' node to 'Contact: Create'.
7. **Conditional Logic (Approval)**: Add an 'IF' node to check `{{$json.total_amount}} > 1000`. If true, route to a 'Wait for Webhook' or 'Slack' node for human approval before proceeding.
8. **Create Transaction**: Add a 'Xero' node to 'Bill: Create'. Map the extracted fields using n8n expressions (e.g., `{{ $node["Transform"].json["net"] }}`).
9. **Attach Document**: Immediately following the Bill creation, add a 'Xero' node with 'File: Upload'. Use the Binary data from Step 4 and the `invoice_id` returned from Step 8.
10. **Error Handling**: Create a separate workflow or a 'Sticky' Error Trigger node. Use this to notify the team if the Xero API returns a validation error (e.g., locked accounting period).
Data Mapping
| Dext Source Field | Xero Target Field | n8n Transformation Expression |
| :--- | :--- | :--- |
| `supplier_name` | Contact Name | `{{ $json.supplier_name.trim() }}` |
| `invoice_ref` | Reference | `{{ $json.invoice_ref || 'No-Ref' }}` |
| `date` | Date | `{{ $now.format('YYYY-MM-DD') || $json.date }}` |
| `net_amount` | Subtotal | `{{ parseFloat($json.net_amount) }}` |
| `tax_amount` | Tax Amount | `{{ parseFloat($json.tax_amount) }}` |
| `currency` | Currency Code | `{{ $json.currency.toUpperCase() }}` |
| `category` | Account Code | `{{ $json.category_code ?? '400' }}` |
| `image_url` | Attachment | `Downloaded via HTTP Request (Binary)` |
Gotchas & Failure Modes
* **Binary Data Memory**: n8n stores binary data in memory or disk depending on your config. For large PDFs, ensure your n8n instance has sufficient RAM or uses the 'Filesystem' storage mode.
* **Xero Rate Limits**: Xero has a limit of 60 requests per minute. Use the 'Split In Batches' node if processing more than 50 Dext items at once.
* **Date Formats**: Dext may provide ISO dates; Xero is picky about date strings. Use n8n's `$dateTime` or Luxon within expressions to format as `YYYY-MM-DD`.
* **Tax Types**: Don't just send the amount; ensure the 'TaxType' code in Xero matches your Chart of Accounts (e.g., 'INPUT' or 'OUTPUT').
Verification Checklist
- [ ] **Trigger Test**: Run the trigger node manually and verify Dext JSON response contains expected fields.
- [ ] **Binary Check**: Verify the 'HTTP Request' node successfully shows a preview of the invoice image in n8n.
- [ ] **Contact Match**: Test with an existing supplier and a new supplier to ensure no duplicate contacts are created.
- [ ] **Draft vs Authorised**: Verify in n8n that the Xero node status is set to 'DRAFT' for your initial tests.
- [ ] **Attachment Confirmation**: Search for the created Bill in Xero and verify the side-panel shows the blue '1' icon on the file attachment.
Ready to Automate?
Build this automation with n8n in minutes.