Skip to content

List Columns and Saved Layouts API

Applies to: All subscriptions (Audit Logs, saved layouts) · e-Invoice · e-Way Bill · Which modules do I have?

Purpose

Explain two things a team reading Complifly's list endpoints directly needs to know since October 2026.

The fact that changes what you do: the list endpoints return a fixed base set of fields. Any other field you want — the IRN, the NIC error message, the tax split, transport details — you must ask for by name with ?cols=. A field you do not ask for is not in the response, and a field that is not in the endpoint's published list below cannot be obtained this way at all, whatever you send.

These are application endpoints, not a versioned integration contract (see Endpoint Index). Pin to the fields listed here and ignore the rest.

Audience

Integration developers and administrators who read Complifly's list endpoints from their own reporting or reconciliation tools, and administrators supporting users who ask why a column is or is not available.

Prerequisites

  • API Authentication — a user token. Each list endpoint keeps its existing permission (for example irn.view for the IRN workbench, audit.view for audit logs). cols never widens what a role may see.
  • An active GSTIN in the X-GSTIN header, as for every GSTIN-scoped call.

Reference

Requesting extra columns — ?cols=

Add a comma-separated list of column keys:

GET /api/irn/workbench?cols=irn,errorMessage,cgst,sgst

Each extra field comes back on every row under the key you asked for.

Behaviour Detail
Unknown key Ignored silently. No error, no field
Key not in the endpoint's list Ignored silently, even if a database column of that name exists
Invalid key (spaces, punctuation) Ignored silently
More than 120 keys Only the first 120 are considered
Omitted cols Base fields only — the same response as before October 2026, except Audit Logs (below)

Because unknown keys are ignored rather than rejected, check that the field you asked for is present before relying on it. A typo returns a row without the field, not an error.

What each endpoint offers

Endpoint Extra columns you may request
GET /api/irn/workbench discount, otherCharges, roundOff, totalFc, buyerTradeName, buyerPin, buyerPlace, shipToGstin, shipToName, shipToState, dispatchFromName, dispatchFromPlace, dispatchFromState, precDocNo, precDocDate, poRef, poRefDate, expShipBillNo, expShipBillDate, expPort, expCountry, expCurrency, payMode, payDue, payCreditDays, payPaid, ewbValidTill, transDocNo, transDocDate, errorCode, errorMessage, cancelDate, cancelReason, cancelRemark, gspProvider, docSource, sourceSystem, erpRef, uploadJob, createdBy, updatedBy, updatedAt, revisionNo, revisionSource, fiscalYear
GET /api/ewb-doc/list recipientName, toPlace, toPin, toState, taxable, total, cgst, sgst, igst, cess, vehicleNo, transMode, transporterId, transporterName, distance, transDocNo, transDocDate, partASlip, partBProvided, errorCode, errorMessage, cancelReason, cancelRemark, generationMode, gspProvider, erpRef, sourceSystem, createdAt, createdBy, updatedBy, updatedAt
GET /api/ewb/list recipientGstin, recipientName, totalValue, cgst, sgst, igst, cess, transMode, distance, transDocNo, transDocDate, fromState, generationMode, processingRoute, nicAlert, cancelReason, cancelRemark, errorCode, errorMessage, gspProvider, createdBy, createdAt, updatedBy, updatedAt
GET /api/cewb/list validUpto, cewbDate, transMode, transporterId, generatedBy, errorCode, errorMessage, previousEwb, tripStart, gspProvider
GET /api/correction/invoices fileName, taxable, cgst, sgst, igst, caseRef, supplierGstin, pos, supplyType, uploadedBy
GET /api/intelligence/list-findings transporterId
GET /api/admin/audit-logs sessionId, userAgent, and orgId (Super Admin only — the key is ignored for every other role)

Long free-text fields (errorMessage, cancelRemark, nicAlert, userAgent) are cut to a few hundred characters in a list. The full text is on the document's own detail endpoint.

What you can never request

Phone numbers and e-mail addresses (personal data under the DPDP Act), payee bank account details, credential identifiers such as the audit log's token ID, raw NIC and upload payloads, and internal keys. These are left out of the lists above on purpose, and the server enforces it: asking for them by any name returns nothing.

Changes to base fields in October 2026

Endpoint Change What to do
GET /api/irn/workbench Adds irn (the 64-character IRN) and doc_type (INV, CRN, DBN) Nothing — additive
GET /api/ewb/list Adds ewb_date, doc_date, from_pincode, to_pincode, from_place_name, to_place_name, transporter_id, transporter_name Read these instead of from_place, to_place and doc_dt. Those three keep their old content for compatibility: from_place / to_place hold the PIN codes and doc_dt holds the e-Way Bill date, not the document date
GET /api/cewb/list status is now GENERATED, REGENERATED or FAILED. It was the constant ACT on every row. Adds to_place (the delivery places of the bills on the sheet) If you matched on status = 'ACT', match on GENERATED or REGENERATED instead
GET /api/ewb-doc/list Adds api_name, the NIC operation that produced the bill Nothing — additive
GET /api/irn/workbench, GET /api/ewb-doc/list, GET /api/ewb/list, GET /api/dashboard/irn-detail, GET /api/dashboard/ewb-detail Add irn_state and/or ewb_state: the document's status as one of a small fixed set of values (see Canonical status fields) Nothing — additive. Every existing status field (irn_status, ewb_status, status) is unchanged, in name, value and meaning
GET /api/correction/invoices Adds BillTo_Gstin, the buyer's GSTIN Use it for the buyer. GSTIN is the uploading registration, not the buyer
GET /api/admin/audit-logs OrgId is no longer in the base response. Super Admin can request it with cols=orgId If you read OrgId, a non-Super-Admin caller already only ever receives its own organisation's rows, so the value was constant. Drop the dependency, or call as Super Admin with cols=orgId

Canonical status fields

Five list responses carry irn_state and/or ewb_state next to the status fields they always had. The raw status fields are not touched. The same status can be spelled several ways in stored data (ACT and ACTIVE, CNL and CANCELLED); the state fields give you one value to match on.

Field Values Where
irn_state NOT_GENERATED, GENERATED, CANCELLED, FAILED, EWB_ONLY, IN_DOUBT, UNKNOWN /api/irn/workbench, /api/ewb-doc/list, /api/dashboard/irn-detail
ewb_state NOT_GENERATED, ACTIVE, CANCELLED, EXPIRED, DELIVERED, FAILED, UNKNOWN /api/irn/workbench, /api/ewb-doc/list, /api/ewb/list, /api/dashboard/ewb-detail
  • IN_DOUBT means NIC has not confirmed the IRN. It comes from the stored status INDETERMINATE: the request timed out or came back unclear, so the IRN may already exist. Do not treat it as NOT_GENERATED or FAILED, and do not resubmit corrected data; resubmitting the document unchanged is the supported way to settle it.
  • A document stored as EWB_PENDING is EWB_ONLY for irn_state and NOT_GENERATED for ewb_state: it has no IRN and is waiting for its e-way bill.
  • UNKNOWN means the stored status is not one the product recognises. Do not treat it as "not generated". On /api/ewb/list and /api/dashboard/ewb-detail every row is an existing e-way bill, so a row with no status is UNKNOWN, never NOT_GENERATED.
  • irn_status on /api/ewb/list is a different thing (GENERATED, NOT_APPLICABLE or MISSING: whether the source invoice has an IRN). That endpoint has no irn_state.
  • Treat the value set as open: write your code so that a value it does not know is handled, not a failure.

Paged lists — grid=2 (IRN Workbench)

The fact that changes what you do: GET /api/irn/workbench returns at most the newest 1,000 documents, in one array, with no filter parameters, and a registration with more than 1,000 documents cannot reach the oldest ones through it. Add grid=2 and, only for a registration whose ENTERPRISE_GRID_V2 control is on (off by default, Super Admin only; see Feature flags), you get one page at a time, filtered, searched and sorted by the server, over every document. A request without grid is answered exactly as before. With the control off, grid=2 is refused with 403 FEATURE_DISABLED_BY_OPERATOR.

The paged form is one registration only: the header x-gstin must name a GSTIN (all is refused with 400 GSTIN_REQUIRED).

Parameter Meaning Limits
grid=2 Selects the paged form Required; any other value is 400 GRID_VERSION
page, size 1-based page and rows per page size 10 to 200, default 50; page up to 100,000
sort key:dir, comma-separated, dir is asc (default) or desc At most 3 keys, from the sort keys below
f A filter, key:operator:value. Repeat the parameter for more filters (they are ANDed) At most 10 filters; at most 25 values each, each at most 40 printable ASCII characters
q Search: the characters you type must appear in that order, anywhere in the document number or the buyer name, ignoring case (so invc123 finds INV-2025-00123) At most 40 characters
fy, month The financial-year filter: fy=2026-27, month=all or 1 to 12. A document with no date is not excluded month needs fy
attention or finding Only the documents an Attention Center rule (attention=IRN_WINDOW_PASSED) or one finding (finding=42) points at. Only rules your role may see match Not both
facets=only Return the distinct values and counts the filter dropdowns offer, and no rows See "What is slow"
cols Extra columns, as above Unchanged

Sort keys: doc_no, doc_date, doc_type, buyer_name, supply_type, irn_status, total_invoice_value, taxable_value, created_at. Ties always end in the same order the unpaged list uses, so a page does not reshuffle between requests. The e-way bill status cannot be sorted on (it lives in two other tables).

Filter keys (operator in takes comma-separated values; doc_date takes between a,b, before or after, with dates as YYYY-MM-DD):

Key Matches
irn_state, ewb_state The status as the new status vocabulary reads it: GENERATED, FAILED, IN_DOUBT and the other canonical states from Canonical status fields, plus EWB_PENDING, and RAW:<WORD> for a word the product does not recognise. Two spellings of one state (ACT, ACTIVE) match together
irn_status, ewb_status The stored word itself, compared ignoring case but not spaces (Pending, ACT). Use this when you want exactly what the older screens filter on
supply_type B2B, EXPWP, SEZWP and so on
doc_type INV, CRN, DBN; a blank type counts as INV
doc_date The document date

Response

{ "grid": 2, "page": 1, "size": 50, "total": 838, "pages": 17, "rows": [ { "inv_hdr_id": 7077, "doc_no": "INMF26-0000132", "irn_status": "ACTIVE", "irn_state": "GENERATED", "ewb_state": "NOT_GENERATED" } ] }

Rows have the same fields as the unpaged list (including irn_state and ewb_state). total is every document behind your filters, not the page. facets=only returns { "grid": 2, "facets": { "irn_status": [ { "value": "ACTIVE", "count": 413 } ], "ewb_status": [...], "supply_type": [...], "doc_type": [...] } }.

Errors. Each is 400 with { "code", "message" } and runs no query; an unknown parameter, key or operator is refused rather than ignored, because a filter that is silently dropped shows the wrong documents with no error. See Platform error codes.

What is slow. Everything above answered in under a second (0.2 to 0.9 s) for 90,000 documents on one registration, on the machine we measured on, with two exceptions. A filter on the e-way bill status (ewb_state, ewb_status) and the ewb_status facet read the e-invoice and e-way bill tables for every document, and those tables are guarded by row-level security that looks each row up in the document table. Before Complifly applies the faster lookup to the database that was about 8 seconds at that size; in our test with the faster lookup it was about 1.5 seconds. The time is in proportion to the number of documents on the registration (roughly 10 times less at 9,000). The screen therefore asks for facets in a request of its own, after the first page is shown.

Saved layouts — /api/layouts

Stores each user's column layout per screen, so it follows them across browsers. Used by the Layout Management dialog; documented here so an administrator can see what is stored.

Method Path Body Returns
GET /api/layouts — { layouts: { "<layoutKey>": { columnsVisible, order, updatedAt } } } for the caller
PUT /api/layouts/{layoutKey} { "order": ["docNo", "irn", …] } { layout: { columnsVisible, order } }
DELETE /api/layouts/{layoutKey} — 204

Any signed-in user may call these; they only ever act on the caller's own layouts. The user and organisation come from the token, never from the request. A layout holds column keys only, never data.

Response Condition
400 — Invalid layout key layoutKey is not lower-case letters, digits, _ or -, 3–100 characters
400 — order must be an array order missing or not an array
400 — order contains an invalid column key A key is not a plain identifier
400 — order has too many columns More than 150 keys
401 No valid token

Validation

  • Call a list endpoint with ?cols= naming one field from the table and one made-up key. The response contains the real field and not the made-up one.
  • As a role other than Super Admin, call /api/admin/audit-logs?cols=orgId. The rows carry no orgId.
  • PUT a layout, then GET /api/layouts from a different browser signed in as the same user. The layout is returned.

Troubleshooting

Symptom Cause Action
A field you asked for is missing from every row The key is misspelt, or the endpoint does not offer it Check the key against the table above; keys are case-sensitive
Audit log rows lost OrgId after an upgrade OrgId moved out of the base response in October 2026 Request cols=orgId as Super Admin, or drop the dependency
from_place shows a six-digit number It is the legacy PIN-code alias Read from_place_name and from_pincode
403 FEATURE_DISABLED_BY_OPERATOR on grid=2 ENTERPRISE_GRID_V2 is off for the registration A Complifly Super Admin switches it on for that GSTIN, or call without grid
Paging through the unpaged list never shows an older document The unpaged list stops at the newest 1,000 documents Use grid=2 once the control is on
Filtering by e-way bill status takes several seconds on a very large registration That filter reads two guarded tables for every document Filter by IRN status or search first; see "What is slow" above
A user's columns differ between two browsers The layout was changed in one browser while the server could not be reached; that copy stayed local Open Layout Management in the browser with the wanted layout and select Apply Layout again