it’s a MUST have feat I am leading an integration team and i think most 3PL services with API request body support data: (array), it must be programmatically allow us to add a JSON, rather than just a button “Add Item”
This is not a feature request topic. I don’t think there already is one for this, so might be worth creating one.
While I’m late to the thread, I thought I’d chime in with my $0.02 of my experience solving this issue.
Everytime I’ve had to programatically create Xero invoices through n8n, I have had to use something to store the data (Google Sheets) with one sheet for high-level invoice information and and another for invoice detail (both sheets containing an invoice ID).
I’ve had no luck with the OOTB Xero Nodes because of the lack of ‘dynamic’ data passthrough and have used the HTTP Nodes with the credentials passed through (as @BramKn mentioned above).
There is usually alot more data re-structuring in code nodes than I would prefer, and I will also log all invoice IDs that were successful in a new sheet (within the same spreadsheet in order to manage exceptions for the client).
I am switching from make.com to n8n but lack of array/programmatically line items for Xero invoices is very embarrassing. Still trying to find a way
Here’s the feature request that @ericsonmartin created if anyone is interested: Xero: Payments, Items and programatically OrderLines
I’m also testing n8n after using Make, and the lack of the ability to provide an array in this Node is pretty shocking, particularly as this issue was flagged almost 3 years ago.
I’m going to attempt using the HTTP Request node to make the Xero API calls directly. This thread has some info on how to do that: Xero: More Resources
Here’s a quick summary of how I call Xero to create multi-line invoices.
- The workflow is triggered from Glide, using a webhook action.
- The Get many contacts node uses the in-built n8n Xero node. This has an OAuth connection setup to the required Xero account.
- The Get Tenant ID HTTP Request node uses the previously set up OAuth connection to make a https://api.xero.com/connections GET call, which returns a
tenantId
. - The Create Line Items Code node processes the data received from the Webhook, and creates a JSON list of Line Items.
- The Create invoice HTTP Request node uses the same Xero OAuth2 API credential from earlier, and sets the xero-tenant-id header parameter using the value from #3, and the line items from #4.
Note: the contact is currently hard coded to Account Number “1”, but in future I’ll add branching logic to search for the contact dynamically, and create one if not found.
Screenshots of node configuration
Get contacts
Get Tenant ID
Create invoice
JS code
Create Line Items Code node
// Get data from Glide Webhook request body.
const request = $('Webhook').first().json.body;
// Convert hours to Xero line item format
const hoursLineItems = request.hours.map(person => ({
Description: `Labour (${person.name}) - ${person.start} to ${person.start}`,
Quantity: Number(person.hours_billable),
UnitAmount: "70",
AccountCode: "200", // Sales account
}));
// Convert materials to Xero line item format
const materialsLineItems = request.materials.map(material => {
// Don't show unit in description if sold per-item
const description = material.unit !== "Each"
? `${material.name} (${material.unit})`
: material.name;
return {
Description: description,
Quantity: Number(material.quantity),
UnitAmount: Number(material.unit_price),
AccountCode: "200", // Sales account
};
});
// Return full list of line items
const lineItems = [...hoursLineItems, ...materialsLineItems];
return [
{
lineItems,
}
];
Create invoice HTTP Request JSON body
{
"Type": "ACCREC",
"Contact": {
"ContactID": "{{ $('Get many contacts').item.json.ContactID }}"
},
"LineItems": {{ JSON.stringify($json.lineItems) }}
}