T

TechIdea

Ecosystem

Back to Tally Masterclass

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 xml2js

Step 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.

Growth Newsletter

Get practical AI tools, SEO tips, and growth guides weekly.

Join creators, students, and businesses scaling with TechIdea.