API overview
A versioned REST API over HTTPS, authenticated with OAuth 2.0. Anything that can make an HTTP request can post to TallyPrime.
Base URL
http://localhost:4173/api/v1v1 is the Balancely API. A new version will only ever appear for a change that would break an existing integration, and it would run alongside v1.
Conventions
Every operation is a
resource.actionkey —sales_invoices.create,ledgers.search,vouchers.cancel— called at/api/v1/tally/{key}.Writes are
POSTwith a JSON body. Reads areGETwith query parameters;POSTworks for them too.Every field name, in and out, is
snake_case. Dates areYYYY-MM-DD.A record says what it is in
object, and a voucher's number is alwaysnumber.Success is the HTTP status. There is no
okflag to check.
Response shape
One record, a list of records, or an error. Every one carries the request id.
HTTP/1.1 201 Created
{
"data": {
"object": "sales_invoice",
"number": "INV-1042",
"date": "2026-04-12",
"customer": "Aurora Traders",
"amount": 2950,
"item_count": 1,
"bill_reference_name": "INV-1042"
},
"meta": { "request_id": "req_8f2c…", "operation": "sales_invoices.create", "outcome": "created" }
}meta.outcome says what a write did: created (status 201), updated, found — an existing record returned unchanged — or, for a cancel, cancelled and unchanged. meta.replayed is true when a retry was answered with the first result.
When TallyPrime saved the record but not every field as sent, data.warnings lists each one — { "code": "field_not_saved", "label": "PAN", "message": "…" }. The record is real either way, so a warning never fails the step. gst_assumed_local means GST was worked out as within your state because the party has no GSTIN or State in TallyPrime; set_by_tally means TallyPrime numbered the voucher itself.
Branch on the code, show the message
code is stable and safe to branch a workflow on. message is written for the person reading it and names the next action — show it as-is rather than replacing it with your own wording.Pagination
Search operations answer a page at a time. limit is 1 to 100 (default 50). When meta.has_more is true, send meta.next_cursor back as cursor for the next page; the last page has next_cursor: null.
http://localhost:4173/api/v1/tally/ledgers.search?search_text=traders&limit=50
http://localhost:4173/api/v1/tally/ledgers.search?search_text=traders&limit=50&cursor=eyJvIjo1MH0A search reaches at most the first 1,000 matches; narrow it with a filter to see past them.
Status codes
| Status | Means |
|---|---|
200 | Done: a read, an update, a record found, a cancel. |
201 | A new record was created in TallyPrime. |
400 | The request is malformed or a required field is missing. error.field names it. |
401 | No access token, or it is not valid. |
402 | The plan's monthly allowance is used up. |
403 | The token lacks the permission this operation needs. |
404 | No such operation, list, or record. |
405 | A write was sent as GET. |
409 | It conflicts with what TallyPrime already holds — a duplicate, an existing record, another company open. |
422 | TallyPrime's data cannot accept it — an unknown ledger, an unbalanced entry, a refused voucher. |
429 | Too many requests from this application. Wait Retry-After seconds. |
503 | The connector or TallyPrime is not reachable right now. Retry after Retry-After seconds. |
502 / 504 | TallyPrime did not confirm in time. Re-send the same request: it updates the same record. |
Tracing a request
Every response carries meta.request_id, also sent as the X-Request-Id header. Quote it when reporting a problem and we can find the exact request in our logs.
Endpoints
| Path | Purpose |
|---|---|
/api/v1/oauth | Authorization, token exchange, refresh, revoke and userinfo. |
/api/v1/tally/{operation} | Run one operation: create entries and read from a connected company. |
/api/v1/tally/batch | Run up to 50 operations in one call. |
/api/v1/tally/lists/{name} | Dropdown sources for a step editor — customers, ledgers, stock items, godowns. |
/api/v1/tally/operations | The catalogue of operations and lists. Public, so a connector can build its own step picker. Add ?fields=1 for every field and a working example of each. |
Something missing on this page? Tell us and we will fix it.