List GST invoices with paging and filters, pull the invoice-ready data for a sales order, and post a complete invoice back to OptoSoft.
6 endpoints in this module. Every request needs a JWT bearer token — see Authentication.
An invoice is the GST tax document raised against a sales order. These six endpoints let you list invoices, discover which orders are still awaiting invoicing, pull the invoice-ready data for an order, and post a completed invoice back to OptoSoft.
In an optical store the order and the invoice are usually separated in time: the order is
taken (often with an advance), the lenses are fitted, and the invoice is raised on
delivery. That is why get-invoice-data-by-salesorder
exists — it hands you a pre-filled invoice built from the order, which you complete
and post back.
Indian GST split. Whether tax lands as CGST + SGST (intra-state) or
IGST (inter-state) is decided by the customer’s stateID
against the branch state. Set the customer’s state correctly on
customer upsert
and OptoSoft computes the split for you.
Returns a paged, filtered list of invoices. This is the endpoint an accounting
integration polls to pull sales into Tally, Zoho Books or a GST return workflow.
Paging uses the fromPage /
toPage row-range style.
| Field | Type | Required | Description |
|---|---|---|---|
| companyID | int64 | Required | Company (tenant). |
| branchID | int64 | Required | Store. |
| yearID | int64 | Required | Financial year — the GST return period you are reconciling. |
| invoiceNumber | string | Optional | Invoice number, exact or partial. |
| salesOrderNo | string | Optional | Find the invoice raised against a given order. |
| customerID | string | Optional | Encrypted customer ID. |
| customerName | string | Optional | Partial match on customer name. |
| customerMobile | string | Optional | Customer mobile number. |
| fromDate | string | Optional | Start of the invoice-date range. |
| toDate | string | Optional | End of the invoice-date range. |
| amount | string | Optional | Gross amount filter. |
| netAmount | string | Optional | Net amount filter. |
| totalRows | string | Optional | Echo field used by the OptoSoft grid. Leave unset. |
| orderBy | string | Optional | Sort column, optionally with DESC. |
| fromPage | int32 | Optional | First row of the range. |
| toPage | int32 | Optional | Last row of the range. |
curl -X POST https://api.opto-soft.com/api/Invoice/List \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"companyID": 18,
"branchID": 24,
"yearID": 9,
"fromDate": "2026-07-01",
"toDate": "2026-07-31",
"fromPage": 1,
"toPage": 50,
"orderBy": "Date DESC"
}'
| Field | Type | Description |
|---|---|---|
| TotalRows | integer | Total matching invoices, before paging. |
| Data[].ID | string | Encrypted invoice ID. Use this on follow-up calls. |
| Data[].PlainId | integer | Numeric invoice ID, for your own reconciliation only. |
| Data[].InvoiceNo | string | Invoice number as printed. |
| Data[].SalesOrderNo | string | Originating order number. |
| Data[].Date | date-time | Invoice date. |
| Data[].CustomerName | string | Customer name. |
| Data[].CustomerMobileNo | string | Customer mobile number. |
| Data[].NetAmount | number | Invoice value including GST. |
| Status | Cause |
|---|---|
| 400 | Missing scoping field, or an unparseable date. |
| 401 | Token missing or expired. |
{
"TotalRows": 87,
"Data": [
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"PlainId": 1042,
"InvoiceNo": "INV-2024-1042",
"SalesOrderNo": "SO-2024-0568",
"Date": "2024-01-20T00:00:00",
"CustomerName": "Rajesh Sharma",
"CustomerMobileNo": "9876543210",
"NetAmount": 8500.00
}
]
}
Lists customers who currently have at least one order awaiting invoicing. Step one of the "raise an invoice" workflow — it narrows a large customer register down to just those with pending work.
None. Scope comes from the bearer token.
curl https://api.opto-soft.com/api/Invoice/get-customers-for-invoice \
-H "Authorization: Bearer YOUR_TOKEN"
{
"success": true,
"data": [
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"CustomerName": "Rajesh Sharma"
},
{
"ID": "Q2ZQdGhSZVhBaVlXTnpaWFF3T0M0d01B",
"CustomerName": "Priya Patel"
}
]
}
For a chosen customer, lists their orders that are ready to be invoiced. Step two of the workflow.
| Name | Type | Required | Description |
|---|---|---|---|
| customerId | string | Required | Encrypted customer ID from the previous call. |
curl "https://api.opto-soft.com/api/Invoice/get-sales-orders-for-invoice?customerId=ENCRYPTED_CUSTOMER_ID" \
-H "Authorization: Bearer YOUR_TOKEN"
{
"success": true,
"data": [
{
"SalesOrderID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"SalesOrderNO": "SO-2024-0568"
}
]
}
Returns every order in the given company, branch and year that is still awaiting an invoice — the branch-wide view, rather than the per-customer view above. Use it to build a "pending invoicing" worklist.
| Field | Type | Required | Description |
|---|---|---|---|
| companyID | int64 | Required | Company (tenant). |
| branchID | int64 | Required | Store. |
| yearID | int64 | Required | Financial year. |
curl -X POST https://api.opto-soft.com/api/Invoice/GetOrdersForNewInvoice \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "companyID": 18, "branchID": 24, "yearID": 9 }'
{
"OrderList": [
{
"SalesOrderID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"SalesOrderNO": "SO-2024-0568"
},
{
"SalesOrderID": "Q2ZQdGhSZVhBaVlXTnpaWFF3T0M0d01B",
"SalesOrderNO": "SO-2024-0569"
}
]
}
The key endpoint of this module. Given a sales order, it returns a fully populated
invoice draft — customer, line items, GST breakdown and totals — ready to
be reviewed and posted back via
save-invoice-data.
| Name | Type | Required | Description |
|---|---|---|---|
| salesOrderId | string | Required | Encrypted sales order ID. |
curl "https://api.opto-soft.com/api/Invoice/get-invoice-data-by-salesorder?salesOrderId=ENCRYPTED_SALES_ORDER_ID" \
-H "Authorization: Bearer YOUR_TOKEN"
The response is an OMFastWizardModel —
the same composite object used by
Quick Sale.
Round-trip it: take the returned object, adjust only what you need, and post it
to save-invoice-data. Do not attempt to
build one from scratch.
{
"success": true,
"data": {
"salesOrderID": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"salesOrderDate": "20/01/2024",
"customerID": "Q2ZQdGhSZVhBaVlXTnpaWFF4TWk0d01B",
"salesRepresentative": "Amit Kumar",
"salesRepresentativeID": "Q2ZQdGhSZVhBaVlXTnpaWFF5TWk0d01B",
"taxTypeID": 1,
"taxType": "CGST + SGST",
"transport": null,
"totalQuantity": 3.00,
"totalPrice": 7200.00,
"totalMRP": 9600.00,
"totalSavings": 2400.00,
"totalDiscount": 1200.00,
"totalTaxableAmount": 6000.00,
"totalSGST": 540.00,
"totalCGST": 540.00,
"totalIGST": 0.00,
"shippingCharges": 0.00,
"otherCharges": 0.00,
"jobCharges": 200.00,
"serviceTax": 0.00,
"rounding": 0.00,
"netAmount": 8500.00,
"isForeigner": false,
"items": [
{
"id": "Q2ZQdGhSZVhBaVlXTnpaWFF6TWk0d01B",
"itemId": "Q2ZQdGhSZVhBaVlXTnpaWFF6T0M0d01B",
"name": "Titan Rimless Frame",
"code": "TIT-001",
"qty": 1.00,
"mrp": 3200.00,
"price": 2500.00,
"discountAmount": 400.00,
"discountRate": 12.50,
"taxableAmount": 2100.00,
"sgstRate": 9.00,
"sgstAmount": 189.00,
"cgstRate": 9.00,
"cgstAmount": 189.00,
"igstRate": 0.00,
"igstAmount": 0.00,
"totalAmount": 2478.00,
"pairNo": "1",
"spectacleLensType": "Single Vision",
"spherical": "-1.50",
"cylinder": "-0.50",
"axis": "180",
"addition": null,
"vision": "6/6"
}
]
}
}
Commits an invoice. The request body is the full composite
OMFastWizardModel (94 top-level properties,
most of them nested objects and UI display flags).
| Field | Type | Description |
|---|---|---|
| customerModel | object | The customer the invoice is raised against. |
| salesorderModel | object | The order being invoiced, with its line items. |
| receiptModel | object | Payment taken at the time of invoicing, if any. |
| eyeInfoModel | object | The prescription dispensed against this invoice. |
| eyecheckupRecallModel | object | Next eye-test recall to schedule for the customer. |
| purchaseOrderModel | object | Linked lab or supplier purchase order. |
| autoItemTypeSectionList | array | Item-type sections shown in the OptoSoft wizard. |
| sessionID | string | Cart session ID, when the invoice is built from a Quick Sale session. |
| orderDate | date-time | Order date. |
| expectedDate | date-time | Expected delivery date. |
| supplierID | string | Encrypted supplier ID for lab work. |
| fitterID | string | Encrypted fitter ID. |
| priorityID | string | Encrypted job-priority ID. |
| isLensAdded | boolean | Whether a lens line is present. |
| isSpectacleLensInOrder | boolean | Whether a spectacle lens is on the order. |
| isExternal | boolean | Marks an externally originated transaction. |
| userId | int64 | Operator recording the invoice. |
| branchCity | string | Branch city, printed on the invoice. |
| visitorIP | string | Client IP recorded for audit. |
| showQuickSaleAdd…Section | boolean | Roughly 60 display flags controlling OptoSoft wizard sections (frames, sunglasses, lenses, contact lenses, accessories and so on). Preserve whatever the GET returned; they do not affect the saved invoice. |
Always round-trip this model. Call
get-invoice-data-by-salesorder first, modify
only the fields you need to change, and post the whole object back. Constructing
an OMFastWizardModel by hand is not
supported and will produce incorrect tax totals.
# 1. Pull the pre-filled invoice draft for the order
curl "https://api.opto-soft.com/api/Invoice/get-invoice-data-by-salesorder?salesOrderId=ENCRYPTED_SALES_ORDER_ID" \
-H "Authorization: Bearer YOUR_TOKEN" -o draft.json
# 2. Adjust draft.json as needed (dates, payment, remarks)
# 3. Post it back to commit the invoice
curl -X POST https://api.opto-soft.com/api/Invoice/save-invoice-data \
-H "Authorization: Bearer YOUR_TOKEN" \
-H "Content-Type: application/json" \
--data-binary @draft.json
Inspect the response body before treating the invoice as saved. A
200 here confirms the request was accepted,
not necessarily that a document number was allocated.
Rendered invoice PDFs and print-ready HTML come from the catalog module — see
Catalog & Master Data
for /api/Common/invoice/pdf and
/api/Common/invoice/pdf/html.
{
"success": true,
"data": {
"InvoiceId": 1042,
"EncryptedInvoiceId": "Q2ZQdGhSZVhBaVlXTnpaWFF3TWk0d01B",
"InvoiceNo": "INV-2024-1042"
}
}