Skip to content

Xero API incorrectly updating discount fields for invoice when updating the SentToContact field #713

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
JoeCMorgan opened this issue Apr 8, 2025 · 3 comments

Comments

@JoeCMorgan
Copy link

A quick summary and/or background
As mentioned in the title, when I'm hitting the Invoices endpoint to update an invoice, through either Postman, the API explorer, or the Python SDK (updateInvoice endpoint), the discount fields are being modified, even though I'm only marking the invoice as being sent.

Steps to reproduce
This is tricky as my invoices are being create via the Parex bridge for Shopify. However, the invoice is created with a discount, as shown below:

{
    "Id": "e91927c5-546a-40c0-8655-5daf048ed0b5",
    "Status": "OK",
    "ProviderName": "Send Invoice Emails",
    "DateTimeUTC": "/Date(1744023335310)/",
    "Invoices": [
        {
            "Type": "ACCREC",
            "InvoiceID": "21fbe4ca-8e63-45fa-a513-431976c648a7",
            "InvoiceNumber": "SHP_#1347",
            "Reference": "pos",
            "Prepayments": [],
            "Overpayments": [],
            "AmountDue": 45.55,
            "AmountPaid": 0.00,
            "SentToContact": false,
            "CurrencyRate": 1.0000000000,
            "TotalDiscount": 2.39,
            "IsDiscounted": true,
            "HasAttachments": false,
            "HasErrors": false,
            "Attachments": [],
            "InvoicePaymentServices": [],
            "Contact": {...},
            "DateString": "2025-04-07T00:00:00",
            "Date": "/Date(1743984000000+0000)/",
            "DueDateString": "2025-05-30T00:00:00",
            "DueDate": "/Date(1748563200000+0000)/",
            "BrandingThemeID": "d45ca3b8-18e1-4cca-9e79-d1f50a790575",
            "Status": "AUTHORISED",
            "LineAmountTypes": "Inclusive",
            "LineItems": [
                {
                    "ItemCode": "SOL-STH-MID-MC070-1L",
                    "Description": "Premium Standard Thinner, 1L",
                    "UnitAmount": 1.92,
                    "TaxType": "OUTPUT2",
                    "TaxAmount": 5.78,
                    "LineAmount": 34.66,
                    "AccountCode": "200",
                    "Item": {
                        "ItemID": "f688ec16-99dc-4efd-99ca-e97c56a7ba3b",
                        "Name": "Premium Standard Thinner, 1L",
                        "Code": "SOL-STH-MID-MC070-1L"
                    },
                    "Tracking": [],
                    "Quantity": 19.0000,
                    "DiscountRate": 4.99,
                    "LineItemID": "c522edc5-e632-4e0a-9ab0-147642cdd7c0",
                    "AccountID": "e15ef38f-0423-4883-82b0-fba43e00ceba",
                    "DiscountAmount": 1.8200,
                    "ValidationErrors": []
                },
                {
                    "ItemCode": "SOL-STH-MID-MC070-1L",
                    "Description": "Premium Standard Thinner, 1L",
                    "UnitAmount": 1.91,
                    "TaxType": "OUTPUT2",
                    "TaxAmount": 1.81,
                    "LineAmount": 10.89,
                    "AccountCode": "200",
                    "Item": {
                        "ItemID": "f688ec16-99dc-4efd-99ca-e97c56a7ba3b",
                        "Name": "Premium Standard Thinner, 1L",
                        "Code": "SOL-STH-MID-MC070-1L"
                    },
                    "Tracking": [],
                    "Quantity": 6.0000,
                    "DiscountRate": 4.97,
                    "LineItemID": "7520ff63-791b-41f1-bea7-94b34c062915",
                    "AccountID": "e15ef38f-0423-4883-82b0-fba43e00ceba",
                    "DiscountAmount": 0.5700,
                    "ValidationErrors": []
                }
            ],
            "SubTotal": 37.96,
            "TotalTax": 7.59,
            "Total": 45.55,
            "UpdatedDateUTC": "/Date(1744023317490+0000)/",
            "CurrencyCode": "GBP"
        }
    ]
}

The discount fields above match what is entered into Shopify, therefore the sync is correct.

However, when I attempt the mark the invoice as paid in postman, the discount values change. I'm hitting the Invoices/GUID endpoint, with the following payload:

{
    "InvoiceID": "21fbe4ca-8e63-45fa-a513-431976c648a7",
    "SentToContact": "true"
}

I get the following response:

{
    "Id": "d24a32b4-d84c-444f-9b6f-7d6078f68473",
    "Status": "OK",
    "ProviderName": "Send Invoice Emails",
    "DateTimeUTC": "/Date(1744023257300)/",
    "Invoices": [
        {
            "Type": "ACCREC",
            "InvoiceID": "21fbe4ca-8e63-45fa-a513-431976c648a7",
            "InvoiceNumber": "SHP_#1347",
            "Reference": "pos",
            "Prepayments": [],
            "Overpayments": [],
            "AmountDue": 45.55,
            "AmountPaid": 0.00,
            "SentToContact": true,
            "CurrencyRate": 1.0000000000,
            "TotalDiscount": 9.96,
            "IsDiscounted": true,
            "HasErrors": false,
            "InvoicePaymentServices": [],
            "Contact": {...},
            "DateString": "2025-04-07T00:00:00",
            "Date": "/Date(1743984000000+0000)/",
            "DueDateString": "2025-05-30T00:00:00",
            "DueDate": "/Date(1748563200000+0000)/",
            "BrandingThemeID": "d45ca3b8-18e1-4cca-9e79-d1f50a790575",
            "Status": "AUTHORISED",
            "LineAmountTypes": "Inclusive",
            "LineItems": [
                {
                    "ItemCode": "SOL-STH-MID-MC070-1L",
                    "Description": "Premium Standard Thinner, 1L",
                    "UnitAmount": 1.92,
                    "TaxType": "OUTPUT2",
                    "TaxAmount": 5.78,
                    "LineAmount": 34.66,
                    "AccountCode": "200",
                    "Item": {
                        "ItemID": "f688ec16-99dc-4efd-99ca-e97c56a7ba3b",
                        "Name": "Premium Standard Thinner, 1L",
                        "Code": "SOL-STH-MID-MC070-1L"
                    },
                    "Tracking": [],
                    "Quantity": 19.0000,
                    "DiscountRate": 13.68,
                    "LineItemID": "c522edc5-e632-4e0a-9ab0-147642cdd7c0",
                    "AccountID": "e15ef38f-0423-4883-82b0-fba43e00ceba",
                    "DiscountEnteredAsPercent": false,
                    "ValidationErrors": []
                },
                {
                    "ItemCode": "SOL-STH-MID-MC070-1L",
                    "Description": "Premium Standard Thinner, 1L",
                    "UnitAmount": 1.91,
                    "TaxType": "OUTPUT2",
                    "TaxAmount": 1.81,
                    "LineAmount": 10.89,
                    "AccountCode": "200",
                    "Item": {
                        "ItemID": "f688ec16-99dc-4efd-99ca-e97c56a7ba3b",
                        "Name": "Premium Standard Thinner, 1L",
                        "Code": "SOL-STH-MID-MC070-1L"
                    },
                    "Tracking": [],
                    "Quantity": 6.0000,
                    "DiscountRate": 43.37,
                    "LineItemID": "7520ff63-791b-41f1-bea7-94b34c062915",
                    "AccountID": "e15ef38f-0423-4883-82b0-fba43e00ceba",
                    "DiscountEnteredAsPercent": false,
                    "ValidationErrors": []
                }
            ],
            "SubTotal": 37.96,
            "TotalTax": 7.59,
            "Total": 45.55,
            "UpdatedDateUTC": "/Date(1744023257207+0000)/",
            "CurrencyCode": "GBP"
        }
    ]
}

Notice how the DiscountRate has changed, and the DiscountAmount has disappeared? Why is this happening when all I'm updating is the SentToContact field?

What you expected would happen
I would expect only the SentToContact field for that specific invoice to be modified, and no other fields.

What actually happens
Shown above.

Notes
As mentioned, I first noticed that something similar was happening in the Python SDK - an error message was returned saying Discount must be between 0.00 and 100.00 or empty.. So I tested it in the API explorer, and postman, and I get the above results. Therefore I believe this is an issue with the API.

Copy link

github-actions bot commented Apr 8, 2025

PETOSS-722

Copy link

github-actions bot commented Apr 8, 2025

Thanks for raising an issue, a ticket has been created to track your request

@JoeCMorgan
Copy link
Author

Reply from Xero:

Our product team are currently aware of a behaviour where POST requests to update an existing invoice cause any DiscountAmount entered in line items to be recalculated as an incorrect DiscountRate.
Currently the workaround to prevent this behaviour from occurring is to include the LineItems, including the original DiscountAmounts in the request body of the POST request, so that the original DiscountAmount is maintained.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant