ml-connector
TallyPrimeBambooHR

TallyPrime and BambooHR integration

TallyPrime runs accounting, inventory, and finance on the desktop. BambooHR is the system of record for people data such as headcount, org structure, and employment status. Connecting the two keeps the staff and department records you reference in TallyPrime in step with BambooHR without manual re-entry. New hires, role changes, and terminations in BambooHR flow into TallyPrime as ledgers and groups, and the BambooHR department and division structure is mirrored as TallyPrime groups for consistent cost grouping. ml-connector handles the very different interfaces on each side and moves the data on the cadence you choose.

How TallyPrime works

TallyPrime is a desktop application, not a cloud service. It exposes a local HTTP server on port 9000 that accepts XML or JSON envelopes for read (Export Data) and write (Import Data), with no individual REST resource URLs. In TallyPrime, all accounts such as customers, vendors, and expense accounts are Ledgers grouped under a parent Group, and transactions are Vouchers. The HTTP interface enforces no API key or token by default, relying on network controls, so a connector reaches it through an on-premise local agent that forwards envelopes to localhost:9000. TallyPrime never pushes events, so all change detection is by polling the Day Book or a collection with a date filter.

How BambooHR works

BambooHR is a cloud HRIS that exposes employees, job information, compensation, employment status, and time off through a REST API over HTTPS, returning JSON. The base URL is per customer at https://{companyDomain}.bamboohr.com/api/v1/, so the subdomain is a required credential. New applications authenticate with OAuth 2.0 Authorization Code, where access tokens last one hour and a refresh token is issued only when the offline_access scope is requested; the token URL is also subdomain-scoped. Employees list with cursor pagination, fields must be requested explicitly, and compensation, job info, and employment status are tabular history. BambooHR also pushes employee.created, employee.updated, and employee.deleted webhooks signed with SHA-256 HMAC.

What moves between them

The flow runs from BambooHR into TallyPrime. ml-connector reads BambooHR employees and their current job information and writes each person into TallyPrime as a Ledger under the appropriate Group, keyed on a stable identifier so a person is updated rather than duplicated. BambooHR departments and divisions are mirrored into TallyPrime as Groups so the cost structure on both sides matches. Hires, role and department changes, and terminations keep the TallyPrime ledgers and groups current. BambooHR has no vendor, invoice, purchase order, or GL account objects, so no finance records move from TallyPrime back into BambooHR; BambooHR is treated as the source of people and org data only.

How ml-connector handles it

ml-connector stores both credential sets encrypted. For BambooHR it runs the OAuth 2.0 Authorization Code flow with offline_access, sends the bearer token on every request, and refreshes it before the one-hour access token expires, using the customer subdomain for both the API and the subdomain-scoped token URL. Because BambooHR returns only the id by default, the connector enumerates each field it needs, reads the tabular job info for the current department and division, and only an admin-scoped token can read work email. BambooHR employee webhooks are verified with SHA-256 HMAC over the raw body plus timestamp using a timing-safe compare, and since the payload is lightweight the connector then calls GET employees by id for current values. TallyPrime is reached through the customer's local agent to port 9000, since the desktop app is not internet-reachable and the company must be open; the connector polls because Tally cannot push, sends dates as YYYYMMDD, and matches the exact company name. Each person is written with an Import Data envelope as a Ledger, which TallyPrime updates in place when the name already exists, avoiding duplicates that Tally has no idempotency key to prevent. BambooHR 503 throttling honors Retry-After, and every record carries a full audit trail and can be replayed if a downstream call fails.

A real-world example

A growing services firm of about 250 staff across three offices keeps its books in TallyPrime and manages people in BambooHR. Before the integration, whenever someone was hired, changed teams, or left, the bookkeeper re-typed the change into TallyPrime by hand to keep the staff ledgers and department grouping accurate, and the two systems drifted apart between updates. With TallyPrime and BambooHR connected, a new hire or department move in BambooHR creates or updates the matching TallyPrime ledger under the right group within minutes, and terminations are reflected the same way. The bookkeeper stops re-keying employee changes and the department structure in the books matches the HR system.

What you can do

  • Create and update TallyPrime ledgers from BambooHR employees, keyed so a person is updated rather than duplicated.
  • Mirror BambooHR departments and divisions into TallyPrime groups so cost grouping stays aligned.
  • Keep TallyPrime current with BambooHR hires, role changes, and terminations.
  • Bridge BambooHR OAuth 2.0 tokens to TallyPrime's on-premise local agent on port 9000.
  • React to BambooHR employee webhooks verified by SHA-256 HMAC, then poll TallyPrime because the desktop app cannot push, with retries and a full audit trail.

Questions

Which direction does data move between TallyPrime and BambooHR?
The flow is BambooHR into TallyPrime. Employees, job information, departments, and divisions move from BambooHR into TallyPrime as ledgers and groups. BambooHR has no vendor, invoice, purchase order, or GL account objects, so no finance records move back from TallyPrime into BambooHR.
Why does TallyPrime need a local agent instead of a direct cloud connection?
TallyPrime is a desktop application whose HTTP server on port 9000 is only reachable on the local machine or LAN, not from the internet. ml-connector therefore talks to a small on-premise agent that forwards XML or JSON envelopes to localhost:9000 and relays the responses. TallyPrime must also be running with the target company open for any call to succeed.
How are duplicate records avoided when there is no idempotency key?
BambooHR returns 409 Conflict on a duplicate employee email, and TallyPrime has no idempotency key on its HTTP interface, so ml-connector handles dedup itself. Each person is written as a Ledger whose name TallyPrime updates in place when it already exists rather than creating a second one, and the connector tracks the BambooHR employee id it has already written. This keeps repeated syncs and webhook re-deliveries from creating duplicates.

Related integrations

Connect TallyPrime and BambooHR

Free to use. Add your credentials, ping your real systems, and see if we fit.

Get started