How to Build a Tally REST API using Node.js
A practical guide to converting TallyPrime's archaic XML interface into a clean, modern REST API that any frontend or mobile app can consume.
Introduction
If you have tried connecting a modern web application (like React or Next.js) directly to TallyPrime, you already know the pain. Tally does not return clean JSON arrays; it requires complex XML requests and returns massive, bloated XML responses.
In this tutorial, we will build a Node.js Middleware Server using Express. This server will expose a clean REST endpoint (GET /api/ledgers), communicate with Tally using XML behind the scenes, and return a beautiful JSON array to your frontend.
Prerequisites
- TallyPrime installed and running on your machine.
- Tally ODBC/HTTP server enabled (usually on port 9000).
- Basic knowledge of JavaScript, Node.js, and Express.
Step 1: Setup the Express Server
First, initialize a new Node project and install express, axios (to make HTTP requests to Tally), and xml2js (to parse the XML response).
mkdir tally-api-middleware
cd tally-api-middleware
npm init -y
npm install express axios xml2jsStep 2: Write the XML Payload
To ask Tally for a list of all ledgers, we need to construct a specific XML request envelope.
// tallyRequests.js
const getLedgersXML = () => `<ENVELOPE>
<HEADER>
<TALLYREQUEST>Export Data</TALLYREQUEST>
</HEADER>
<BODY>
<EXPORTDATA>
<REQUESTDESC>
<REPORTNAME>List of Accounts</REPORTNAME>
</REQUESTDESC>
</EXPORTDATA>
</BODY>
</ENVELOPE>`;
module.exports = { getLedgersXML };Step 3: Create the REST Endpoint
Now, we create our Express server. When a user calls our /api/ledgers endpoint, our server will send the XML to Tally, parse the XML response, and send back JSON.
// server.js
const express = require('express');
const axios = require('axios');
const xml2js = require('xml2js');
const { getLedgersXML } = require('./tallyRequests');
const app = express();
const TALLY_URL = 'http://localhost:9000'; // Default Tally Port
app.get('/api/ledgers', async (req, res) => {
try {
// 1. Send XML to Tally
const tallyResponse = await axios.post(TALLY_URL, getLedgersXML(), {
headers: { 'Content-Type': 'text/xml' }
});
// 2. Parse XML to JSON
const parser = new xml2js.Parser({ explicitArray: false });
const jsonResult = await parser.parseStringPromise(tallyResponse.data);
// 3. Extract the Ledgers (This path depends on the exact XML Tally returns)
const ledgers = jsonResult.ENVELOPE.BODY.DATA.COLLECTION.LEDGER;
// 4. Send clean JSON to the client
res.json({
success: true,
data: ledgers.map(l => ({
name: l.$.NAME,
parent: l.PARENT,
openingBalance: l.OPENINGBALANCE
}))
});
} catch (error) {
console.error("Error communicating with Tally:", error.message);
res.status(500).json({ success: false, error: "Failed to fetch from Tally" });
}
});
app.listen(3000, () => {
console.log('Middleware API running on http://localhost:3000');
});Step 4: Test Your New API
Make sure Tally is open with a Company loaded. Start your node server: node server.js. Then visit http://localhost:3000/api/ledgers in your browser or Postman.
You should see a beautifully formatted JSON array containing your Tally ledgers, which you can easily consume in a React or mobile application!
Struggling with Complex TDL?
The example above is basic. In production, you need authentication, error queues, and custom TDL to extract specific fields like batch-wise stock. We build enterprise-grade APIs for Tally.