Expense and spend tools
Use this recipe when a finance or operations workflow needs clean people, employment, department, cost-centre, legal-entity, and leaver context from HollyHR while a specialist tool owns expenses, cards, receipt capture, reimbursements, VAT, and accounting reconciliation.
HollyHR is not a native expense-management product and this is not a first-party connector. It is the launch-safe integration pattern for teams using tools such as Xero Expenses, FreeAgent, Dext, Pleo, Soldo, Expensify, or Zoho Expense.
What HollyHR should own
| Data | HollyHR source | Use in a spend tool |
|---|---|---|
| Person identity | GET /people, GET /people/{personId} | Create or match employee/user records. |
| Work email | people:read | Primary matching key when the spend tool also keys users by work email. |
| Employment status | status, start_date, end_date | Decide who can receive access or a card. |
| Job title and manager | People detail and employment context | Approval-routing context where the spend tool supports it. |
| Departments | GET /org-units?type=department and People projections | Reporting and approval grouping. |
| Cost centres | GET /org-units?type=cost_centre | Accounting dimensions, budget ownership, and spend reporting. |
| Legal entities | GET /org-units?type=legal_entity | Entity-aware accounting setup; not payroll registration data. |
| Provider ids | Org-unit provider identity fields and GET /provider-mappings | Reconcile HollyHR resources with downstream ids without overloading staff_id. |
What the spend tool should own
- expense claims, mileage, receipt capture, OCR, and evidence retention;
- card issuance, spend limits, merchant rules, subscriptions, and transaction feeds;
- reimbursement workflow and payment status;
- VAT, MTD, ledger posting, account codes, and bank reconciliation;
- expense-policy approval semantics and exception handling;
- spend analytics and finance-close reporting.
Do not store card numbers, bank details, receipt images, reimbursable amounts, merchant data, or accounting-ledger payloads in HollyHR custom fields.
Recommended scopes
Create the smallest API key that fits the sync:
Code
Add people:write or org_units:write only if your integration creates safe
setup data in HollyHR. Do not add people:personal:read,
payroll_exports:read, payroll-financial grants, custom sensitive fields, or
document scopes for a spend-tool user lifecycle sync.
provider_mappings:read also requires the matching resource read scope. For
example, reading org-unit mappings requires provider_mappings:read and
org_units:read.
Readiness check
Call GET /integration-readiness before building or activating a spend sync.
The endpoint gives one aggregate answer for whether HollyHR is ready to act as
the HR source of truth for tools such as Xero Expenses, FreeAgent, Dext, Pleo,
and Soldo.
The response includes provider cards with native_connector: false, because
v1 is a readiness/playbook/API handoff, not a first-party connector. Treat these
statuses as operational setup guidance:
not_configured: fix blockers first, especially archived members without an employment end date;needs_attention: the handoff can be useful, but cost-centres, departments, or webhook health need review;ready: HollyHR has the people, org-structure, and webhook posture expected for that provider pattern.
For Pleo and Soldo-style card tools, person.ended webhook coverage matters:
that is the event a downstream system needs to deactivate a leaver. Keep a
scheduled reconciliation job as a backstop even when webhooks are healthy.
Initial sync
- Fetch people with
GET /people?limit=100. - Store HollyHR
person_idas the stable source id. - Store work email as the human-readable matching key.
- Fetch departments, cost centres, and legal entities with
GET /org-units. - Fetch
GET /people/{personId}/org-linkswhen the downstream tool supports multiple memberships or needs cost-centre/legal-entity context. - Store downstream ids in the downstream tool, or use HollyHR provider-mapping
reads where mappings already exist. Do not repurpose
staff_idas a connector id.
Use cursor pagination and updated_since for repeat syncs.
Change handling
Subscribe to these events where the current event source covers your workflow:
Code
Webhook deliveries are notifications, not the integration's database. Verify
the signature, deduplicate by HollyHR-Webhook-Id, then fetch current state
through REST before updating the spend tool.
Current source coverage is mixed:
- public API writes emit the matching public webhook events for implemented people, employment, org-unit, time-off, working-pattern, and time-off configuration writes;
- in-app mutations emit
source: "app"events for person creation/person profile updates and time-off create/update/cancel flows wired through the domain-event spine; - some UI-origin paths, including access-removal/offboarding without a recorded
employment end date, still need incremental
updated_sincepolling or a follow-up product slice before they can be treated as real-time card-disable automation.
For Pleo or Soldo-style company-card tools, run a daily reconciliation job even if you also subscribe to webhooks. A leaver should lose spend access based on a recorded end date or inactive status, not solely on a single webhook delivery.
Provider patterns
| Tool type | Examples | Practical HollyHR role |
|---|---|---|
| Accounting-native expenses | Xero Expenses, FreeAgent | Provide employee, department, cost-centre, and legal-entity context; the accounting product owns claims and posting. |
| Receipt/accountant capture | Dext | Provide who-submitted and cost-centre context for accountant workflows; Dext owns receipt capture and extraction. |
| Card-first spend control | Pleo, Soldo | Provide joiner/mover/leaver and cost-centre context; the spend platform owns cards, limits, receipts, and transactions. |
| Dedicated T&E | Expensify, Zoho Expense | Provide HR identity/org context; the T&E platform owns travel, claim workflow, policy, and reimbursement. |
Boundaries
- This recipe does not mean HollyHR has a native connector to any named spend product.
- HollyHR does not expose an expenses API, card API, receipt API, reimbursement API, or accounting-ledger API.
- Home address, date of birth, government identifiers, compensation, bank details, document bytes, and payroll export grants are not needed for this pattern.
- Legal-entity org units are structural context only. They are not payroll or Companies House registration records.
- Native connector work should be demand-gated by a named buyer, bureau, accountant, or provider partner.
Demand gate for a native connector
Open a connector/product slice only when a named opportunity can answer:
- Which spend tool is the buyer actually using?
- Which data must move that cannot be handled by API, webhooks,
updated_since, or a no-code tool? - Who owns support when a card is not disabled, a cost centre is wrong, or a claim posts to the wrong ledger account?
- Which sensitive fields cross the boundary, and which scopes/audit/DSAR rules cover them?
- Is this a one-customer convenience or a repeatable channel bet?
Until those answers are strong, keep expenses in the specialist system and use HollyHR as the clean HR source of truth.