EDistribution API

Invoices and paying#

Your ledger charges become GST invoices on your billing cycle. Invoices are what you pay not bookings.

One invoice per supplier GSTIN#

This one rule explains the shape of everything else on this page.

Place of supply for accommodation is the property's state, not yours. A stay in Himachal is a supply made in Himachal and must be billed from our Himachal GST registration; a stay in Goa from our Goa one. Two registrations means two invoices.

placeOfSupply on the invoice is the property's state; supplierGstin is the registration that billed it.

Listing invoices#

GET /v1/invoices, with an issue-date window and keyset paging, newest first.

outstanding is computed across all your collectable invoices, not just the page you asked for: total, less allocated payments, less credit notes. oldestDueDate is null exactly when outstanding is zero.

Credit notes are listed as ordinary rows with creditNoteFor set and amountDue of zero.

cURL
curl -G "$BASE/v1/invoices" -u "$ELIVAAS_API_KEY:" \
  --data-urlencode 'status=ISSUED' \
  --data-urlencode 'status=PARTIALLY_PAID' \
  --data-urlencode 'size=50'
200
{
  "data": [ /* InvoiceView */ ],
  "nextCursor": null,
  "outstanding": 23600.00,
  "oldestDueDate": "2026-08-15",
  "outstandingInvoiceCount": 3
}

Reading one invoice#

GET /v1/invoices/{id} returns the invoice, every line, and its credit-note relationships.

Pay amountDue, not total#

code
amountDue = total − amountPaid − creditedAmount        (floored at zero)

total is what the document originally asked for, which stops being the right number the moment anything is paid or credited. amountDue is the only figure to collect against.

The tax fields#

code
total = subtotal + cgst + sgst + igst − discount

Enforced in the database, to the paisa.

  • cgst + sgst on an intra-state supply, igst on an inter-state one. Never both.
  • discount is post-tax. It is positive, subtracted from the total, and does not reduce subtotal a plan discount or bank offer does not reduce the taxable value of the supply.

Party fields are snapshots#

Every supplier and bill-to field is captured at issue and never re-read. An invoice renders identically years later even if your registered name has since changed. billToGstin being null means you were not registered at issue time — a legitimate state, not a missing value.

Invoice lines #

One line is one night of one booked property, or one meal or service on one date.

A two-night booking of one property bills as two stay lines, because the GST slab is decided per unit per night and is date-aware. A stay crossing a slab-change date is genuinely taxed at two rates.

FieldMeaning
lineKindSTAY, MEAL, VAS, PROPERTY (a whole property, for bookings with no per-night breakdown), ENTRY (a whole charge with no property breakdown)
nightDateThe night occupied, or the date a meal/service was supplied. Null on PROPERTY and ENTRY
quantityUnits of this supply
unitBaseThe per-unit pre-tax tariff the slab was decided on
taxableValueValue before GST. Exactly unitBase × quantity
gstRateThe slab as a percentage — 5, 12 or 18 on a real line
cgst, sgst, igstThe tax split on this line
lineTotaltaxableValue + cgst + sgst + igst. Enforced by the database
creditNoteForLineNon-null only on a credit note's lines: the original line being credited

Place of supply is not a per-line field — it lives once on the header, because one invoice covers exactly one registration and therefore one state.

The PDF#

GET /v1/invoices/{id}/pdf returns application/pdf, scoped exactly like the invoice itself.

If a PDF was never stored — a render that failed at issue does not un-issue a legally issued invoice — this renders it on demand, stores it, and serves it. You will not get a 404 for a missing document on an issued invoice.

A draft has no PDF and never will: it carries no invoice number, and a document that looks like a numbered tax invoice without being one can be forwarded, filed and paid against. That is 409 — the invoice exists, the document does not.

Paying#

Opening Checkout #

Every issued invoice carries exactly one razorpayOrderId, for its full total.

Take the amount from the invoice, never from your own records — the two diverge the moment a credit note is raised.

Node.js
const rzp = new Razorpay({
  key: ELIVAAS_RAZORPAY_KEY_ID,     // from onboarding
  order_id: invoice.razorpayOrderId,
  amount: invoice.amountDue * 100,  // paise
  currency: 'INR',
});
rzp.open();

When razorpayOrderId is null#

The invoice is still valid and still payable by other means. A null order id means no order could be raised yet — a configuration gap, not an invoice defect. A later attempt fills it in without changing the invoice.

Watching a payment land#

A payment posts a PAYMENT entry to your ledger and reduces amountDue on the invoice it is allocated to. Poll GET /v1/invoices/{id} or watch the ledger; both reflect it.

Running billing on demand #

POST /v1/invoices closes a billing period early.

You rarely want this. Billing runs on your cycle automatically, and the endpoint exists for closing a period ahead of schedule — not for routine use. An empty body {} bills the period that most recently closed, which is exactly what the schedule would have billed.

It takes an exclusive lock on your billing and is throttled well below the general rate limit — roughly a couple of runs per minute, on its own per-account bucket.

Overdue and hold#

Watch overdueSince on invoices, and onHold on your statement.

Past your grace period, an overdue balance puts the account on hold and booking stops — with 402 and reasonCode: "ACCOUNT_ON_HOLD". Reads keep working throughout. Paying clears it.

Alert on this. It is the difference between a quiet Monday and every booking failing at once.