CiviCRM integration with Xero

It is possible to integrate CiviCRM with Xero - although the extension (purposefully) cannot be downloaded through the UI as it defintely requires someone technically savy to be involved in setting it up & maintaining it. In this blog I'm going to explain what you can expect and what you can't expect from the Xero integration. In order to get install and configure it you should refer to the Readme.


What you can expect to see?

CiviCRM Xero integration relies on a supporting extension CiviCRM Account Sync. This extension adds a table in your database that stores the connections between your contacts in CiviCRM and your contacts in Xero and a second table that stores connections between contributions in CiviCRM and invoices in Xero. If you have a 'match' in this table then you will see links in CiviCRM that point to the contact in Xero and to a list of their transactions. On the contributions page linked transactions will be also show links to the relevant contribution.

Contact Links From CiviCRM to XeroLink to Xero Invoice From CiviCRM

You will also see a new Xero link in your Menu. This is for configuration only (and actually the CiviCRM Dashboard link goes nowhere at the moment). See the Readme for more.

The only other place you will see Xero integration in the user interface is the Scheduled Jobs page. CiviXero integration runs using the API and scheduled jobs is the interface to this - providing pull & push actions for contacts & invoices along with actions to complete or cancel contributions depending on their status in Xero. Note that start_date really means 'modified_since' & I am considering renaming it to this. More specifically it means "modified in Xero since this date & time".

You can schedule these jobs or run them manually using the 'more' link & 'execute now'


Xero on scheduled jobs


How do CiviCRM contacts and invoices get matched to Xero?

There are currently 2 ways

1) the invoice or contact was created in CiviCRM and pushed to Xero

2) the invoice or contact was created in Xero, pulled to CiviCRM via the scheduled job and you have taken an action to match them. There is currently not an interface for this so you need to do it via the DB in the civicrm_accounts_* table or a hook in your current module. So far the customers we are supporting use either a highly customised flow where a hook makes sense or a flow where CiviCRM is the master so only #1 occurs. I have a few ideas where we might go with #2 but it will depend on customer requirements (or the contributions of other developers).


Which CiviCRM contacts & invoices get pushed to Xero?

In the Xero Settings page you configure which actions should cause a contact to be marked for update in Xero. In the screenshot below you can see that if you create or edit a contact in CiviCRM then an entry for that contact will be created in the synchronisation table (civicrm_accounts_contact*) if it does not exist and the 'needs_update' flag will be set to TRUE. Next time the contactpush job is done all contacts set to 'needs_update' will be created in Xero.

The second selection allows you to specify what 'create' or 'update' actions will cause a contact to be updated. ie. if the contact has not been pushed to Xero nothing will happen if you update the address. But, if it has then when the address is updated it will set the needs_update flag to TRUE and on the next contactpush it will be updated in Xero.

The third selection allows you to specify what 'create' actions will cause the contribution to be pushed through as an invoice into Xero. Currently the choices are to push all Contributions to Xero or none.

It should be noted that if you have custom requirements you can update the synchronisation tables using the relevant api yourself to implement your needs. For this reason the actions of determining who to update / create is separate from the updating.

I am pondering making it so that an activity is created when a sync is scheduled

CiviXero Trigger Config

Why does my contact have a number after it in Xero?

Xero enforces name as a unique field. For unknown reasons this isn't always the case in the real world. So, we have appended the CiviCRM id - if you have an alternative solution you can propose it on github as an issue. Or simply override this as a hook. Appending the id also prevents Xero from automatically matching based on name to existing contacts. This seems like a good thing as it is a 'cautious' approach - if you wind up with duplicates in Xero you should merge the one without an ID after the name into the one with an ID.

What happens to my invoices in Xero?

Invoices are pushed into Xero as 'draft invoices'. You need to approve them for them to show in your reconcilliation screen. By default the account code is 200 which is the CiviCRM default for 'Sales'. This is over-ridable by hook & if we get a customer requirement it would make sense to make this a configurable option.

Once approved it is possible to reconcile a payment from your bank feed with it in Xero or add a payment to it in Xero. Next time the 'invoicepull' job runs the updates to the invoice will be pulled back and stored in the synchronisation table. If the contribution is pending in CiviCRM and has been completed in Xero then next time the 'completetransaction' scheduled job runs the contribution will be updated to 'completed' as will any associated event registrations or memberships. If this completes a registration for which a confirmation receipt is configured that will be sent. If the invoice has been voided in Xero the CiviCRM transaction will be cancelled but at this stage participant records & membership records will not be.

What happens if I delete a Contact in CiviCRM?

If you delete a contact that has not been synced or permanently delete a contact that has been synced it will be removed from the synchronisation table. If you permanently delete a contact that has been previously synced it will be removed and you should see a message on the screen to encourage you to ensure you have taken an appropriate action in Xero. If you delete a contact to trash in CiviCRM then you should see a message alerting you but the synchronisation record will remain.

How do I make Xero link back to CiviCRM?

You can get a link like

Link from Xero to Civi

by configuring Xero with a custom link like this (under settings/ general settings / customise links)

Xero Customise Link

What happens when I merge contacts in CiviCRM?

If the record being removed has been linked with a Xero record and the contact being kept has not then the linkage will be transferred. Otherwise no action will be taken. This is handled by the accountsync module & I have not yet determined the best approach when both have been synced. However, 'trashing' a synced record should trigger an alert per the discussion on deleting above.


How can I use the API with CiviXero?

Refer to The API Documentation on for information on how to call the API outside 'scheduled jobs'. The most up-to-date information about the api will always be accessible by going to /civicrm/api/explorer on a site that has CiviXero install. Currently accountsync extension adds create, get & delete accounts for the sync table account_contact and account_invoice along with a special 'account_invoice.getderived' api which outputs a contribution with all it's lineitems & account codes. As of 4.4 this is a bit hard to construct yourself but in 4.5 it is hoped some proposed changes will mitigate this. CiviXero provides pull & push for contacts & invoices and pull for tracking categories (these are not stored in the DB)

What hooks can I use?

You can use standard _pre & _post database hooks on the synchronisation entities (account_contact, account_invoice)

To alter the data being pushed to Xero use

hook_civicrm_accountPushAlterMapped($entity, $contact, &$proceed, &$new_contact);

Note that setting $proceed to FALSE wil block it

To alter the data coming back from Xero before it is stored in the synchronisation tables use

hook_civicrm_accountPullPreSave($entity, $contact, &$save, &$params);

In particular setting $save to FALSE will mean that the contact is effectively skipped.