What Vectis does with Xero
- Syncs Xero contacts marked as customers to the Vectis
customerstable (auto-matched to existing PSA customers by name where possible). - Pulls accounts-receivable invoices (
Type=ACCREC) intobilling_invoiceswith total, balance, status, due date, and currency. Suppliers / payables never enter the billing pillar. - Records payments with one row per payment-invoice settlement touch in
billing_payments, and credit notes inbilling_credit_memos. - Receives webhook events for INVOICE and CONTACT updates into
xero_webhook_eventsfor audit + replay (PAYMENT and CREDITNOTE drain on the next ETL tick instead of via webhook).
What you'll need
- A Xero developer-app Client ID + Client Secret registered at
developer.xero.com→ My Apps. The app’s OAuth 2.0 redirect URI must exactly match Vectis’s callback URL on the host you’re connecting from. - At least one Xero organisation the connecting operator has access to. Partner-Edition MSPs can authorise N organisations on the same consent screen and pick which to sync from the Vectis tenant picker.
- (Optional) A webhook signing key from Xero → My Apps → Webhooks. Required only if you want INVOICE / CONTACT updates to land in Vectis without waiting for the next ETL tick.
1. Register the Vectis app on Xero
- Sign in at developer.xero.com → My Apps with the Xero login that owns the organisations you want to sync.
- Click New app. Pick Web app as the integration type. App name: “Vectis” (or whatever you prefer — the name shows on the consent screen).
- Set the OAuth 2.0 redirect URI to the value Vectis shows in Admin → Integrations → Xero. It must match character-for-character (including
https://and trailing path). - Copy the Client ID and Client Secret shown after creation. The secret is shown only once — store it in your secrets manager before leaving the page.
openid profile email offline_access plus accounting.transactions.read + accounting.contacts.read. Read-only by design — if you upgrade scopes later for write-back actions, Vectis will re-prompt for consent.2. Connect Xero in Vectis
- In Vectis, go to Admin → Integrations → Xero and click Connect Xero. The browser is redirected to Xero’s consent screen.
- Sign in with the operator account that has access to the target organisations. On the consent screen, select every organisation you want Vectis to be able to sync — you can subset further inside Vectis after connecting, but you can’t pick organisations Xero wasn’t granted in the first place.
- Xero redirects back to Vectis. The setup page flips to the tenant picker showing every authorised organisation (PRACTICE / accountant-practice tenants are filtered out automatically — they carry no billing data).
- Pick one or more tenants and click Save. The sync is enabled only after at least one tenant is selected, so a no-op sync can’t run.
3. (Optional) Wire webhooks
- In Xero → My Apps → Webhooks, register a subscription pointing at
https://<your-vectis-host>/api/webhooks/xero. Subscribe to INVOICE and CONTACT events. - Copy the signing key Xero shows. Paste it into the Vectis setup page’s Webhook key field and save.
- Xero sends an Intent-to-Receive probe (an empty events array). Vectis returns 200 +
stored: 0and the subscription becomes active. Subsequent events land inxero_webhook_eventswith HMAC verification on every request.
What appears where
- Customer hub → Billing section: invoiced this month, outstanding balance, contracted MRR, recent invoices. Xero rows display alongside QuickBooks rows on the same panel — the
sourcediscriminator is transparent at the UX level. - Alerts: Xero feeds the same
invoice_overdueandservice_without_invoicetriggers QBO ships, since the underlying tables are vendor-neutral. - Customer timeline: invoice + payment events attach to the customer’s timeline alongside PSA tickets and RMM alerts.
Limits and caps
- Refresh token lifetime: 60 days from issue. Vectis warns at 7 days + 2 days before expiry — click reconnect on the setup page to refresh before the cutoff or the token is invalidated and you’ll need to re-consent.
- Rate limit: 60 requests per minute per tenant per Xero’s published cap; Vectis defaults to 30 req/min to leave headroom.
- Daily cap: 5,000 requests per day per tenant. At 90% utilisation Vectis pauses that tenant’s sync for the current tick, saves a checkpoint, and resumes next tick — other tenants continue.
- Webhook coverage: INVOICE and CONTACT only. PAYMENT and CREDITNOTE drain on ETL polls (every tick pulls all four resource types regardless of webhook state).
- Read-only: this phase does not create invoices, send invoices, record payments, or issue credit notes. Those write verbs are deferred to a future phase on dedicated rule actions (mirroring the Datto restore pattern).
Common errors
401 Unauthorized — the access token has expired and a refresh failed (most often because the refresh token also expired or was rotated by another caller). Click Disconnect + Connect Xero again to re-consent.
403 Forbidden — the tenant you targeted no longer grants the requested scopes. Re-authorise from Xero’s side or pick a different tenant in the Vectis picker.
404 tenant removed — an operator de-selected this tenant from the consent screen on Xero’s side. Disconnect + reconnect to refresh the available-tenants list.
429 Too Many Requests — either the per-minute limit or the daily cap was hit. Vectis surfaces this as a banner on the integration page; the next tick resumes automatically once the window resets.
Webhook 401 — the signing key in Vectis doesn’t match the one Xero is signing with. Re-copy from Xero → My Apps → Webhooks and paste again.