SI Data Ops

Troubleshooting guide · updated 2026-10-11

Duplicate Xero contacts: choose the identity your sync matches on before cleaning anything

Separate Xero's ContactID, ContactNumber, name and account number, and design a match order that survives a changed email, a same-name pair and an archived contact.

Four things that look like "the same customer"

Xero identifies a contact by ContactID, which Xero itself recommends for referencing a contact. A ContactNumber, up to 50 characters, can be set through the API and appears in Xero as Contact Code, which makes it a natural place to store your own customer identifier. The contact name used to be treated as unique, but Xero warns that this business rule may change, so it should not be your only key. The account number is a user-defined field and Xero does not describe it as unique.

A sync that matches on name or email text will split one customer whenever the text changes: a new email address, a trading-name suffix, different capitalisation or punctuation.

Why creates and updates behave differently

Xero describes a PUT as create-only: if an existing contact matches the name or contact number you get an error. A POST can create or update. A sync that tries one verb and falls back to the other without checking can therefore create a second contact in one path and fail in another. Archived contacts add a further trap: they are left out of contact lists unless you ask for them, so a sync that searches only active contacts will not find the old record, while Xero's release notes describe clearer validation when an archived contact already holds the contact number you are trying to assign.

  • A contact can hold only one contact number, so check whether another integration already set one before assigning yours.
  • Never overwrite an existing contact number without a decision from the person who owns that other integration.

A match order that survives change

Use a fixed order and write it down. First, the ContactID your sync stored the last time it saw this customer. Second, your own customer identifier held in the contact number. Third, and only as a flagged candidate for a person to review, a text comparison of name and email. A candidate match should never merge or update automatically, because two real customers can share a name or an email address.

The rule for the awkward cases should be explicit: two customers with the same name and different identifiers become two contacts or one held conflict, an archived contact that holds a needed number is reported, and a changed email or name updates the same contact.

A safe first investigation

Use the Xero demo company, which Xero resets automatically after 28 days and which cannot send invoices. Run three or four invented customers through the sync twice and count contacts. Change one invented customer's email and name and run again. Add a same-name pair with different identifiers. Archive one contact and run again, then list contacts including archived ones to see what the sync actually created.

  • Do not merge, archive or delete real contacts to test anything.
  • Keep the counts and contact identifiers from each step.
  • Note which connection created each duplicate; two writers need an ownership decision, not a matching rule.

What fits, what does not, and how it is accepted

The fixed-price job "Make a customer sync reuse the right Xero contact instead of creating near-duplicates" is from £345, an untested published price confirmed after your enquiry, with payment after the agreed checks pass and you sign off. It is accepted when ten invented customers replayed twice leave exactly ten contacts, a changed email updates the same contact, a same-name pair follows the written rule, and an archived contact holding a number produces a listed exception.

It does not merge or archive contacts in your real organisation; your bookkeeper does that in Xero, and the job supplies a list of suspected groups to speed it up. QuickBooks Online has different customer naming rules and would be scoped separately. This guide is written from vendor documentation read on 11 October 2026. Send invented examples and counts first, never credentials, bank details, invoices or customer records; real records are handled only after written agreement through a secure handoff.

Sources and limits

  • Xero Accounting API: contacts Checked 2026-10-11.
    • ContactID is the identifier Xero recommends for referencing a contact, and Xero warns contact name may stop being unique in future.
    • ContactNumber (up to 50 characters) can be set through the API and is shown in the Xero interface as Contact Code; AccountNumber is user-defined and is not stated to be unique.
    • A PUT only creates and returns an error if an existing contact matches the name or contact number, while a POST can create or update.
    • Archived contacts are left out of contact lists unless includeArchived is requested.
  • Xero: contact mapping best practice Checked 2026-10-11.
    • Xero advises storing the ContactID, or setting ContactNumber to the integration's own identifier, and says a contact can hold only one contact number.
    • Blindly pushing contacts between systems can create duplicates, so integrations should check for an existing match first.
  • Xero Accounting API release notes Checked 2026-10-11.
    • Xero's release note of 10 May 2016 says validation on creating and updating contacts was enhanced to make it clearer when an archived contact with the same ContactNumber already exists.
  • Xero: the demo company Checked 2026-10-11.
    • Data added to the demo company is deleted when it resets automatically after 28 days, and it can be reset manually.
    • Invoices cannot be sent from the demo company, and only the person who adds data can see it.