WonderSoft

Wondersoft eShopaid has two real integration surfaces, a token-based REST service and an ASMX SOAP sales feed, but publishes no developer documentation.

Wondersoft is a Chennai-based retail software vendor with more than 25 years in the market. Its flagship is eShopaid, described by the vendor as a "Web based ERP for Retail Chains", alongside Shopaid for independent retailers and distributors, a promotion engine and a biometric attendance product. The vendor's published scale, read on 2026-09-22, is over 15,000 customers, more than 25,000 stores, over 38,000 point of sale installations and presence in more than 25 countries, across apparel, pharmacy, footwear, salons, supermarkets, electronics, food and beverage, home decor and pet supplies.

Wondersoft publishes no developer documentation. What it does have is two distinct, real integration surfaces that can be reconstructed from several independent public artefacts: a token-authenticated REST service for orders, inventory and invoices, and a SOAP service that streams store sales in three segments, used by malls and landlords to pull tenant sales. Both are per-customer deployments, not a shared vendor host.

At a glance

Warning

Provenance and hygiene. Nothing on this page comes from Wondersoft's own documentation. It is reconstructed from public Postman workspaces belonging to Wondersoft customers and integrators, plus a public GitHub repository containing a working eShopaid integration. Those artefacts also contain what appear to be live authentication tokens, and the same vendor user name and password pair appears as a default in more than one unrelated workspace. Treat every specific value in them as a secret that has leaked, not as a credential to use, and raise the exposure with Wondersoft if you engage with them.

What it is

The product line, from the vendor's own site:

  • eShopaid. Web-based ERP for retail chains. Head office plus store, with a cloud point of sale and what the vendor calls a "Thin Offline POS" for stores with poor connectivity, described as sharing the same interface.
  • Shopaid. The product for independent retailers and distributors. The REST service path appears in the wild both as eShopaidService.svc and ShopaidService.svc, which suggests a shared codebase.
  • Promotion Engine and Whoisin, a biometric attendance tracker.

Wondersoft also publishes an ONDC page and a marketplace integrations page, and names SAP Business One, SAP HANA, SAP ECC, Microsoft Dynamics NAV and AX, Oracle Business Suite, NetSuite, Epicor, Sage, Infor and IFS as ERP integration targets. The integration page describes benefits only and gives no protocol, endpoint or authentication detail. The nearest the vendor comes to a technical statement is that it offers "standard connectors for efficient ERP onboarding and open APIs for custom integration".

Deployment shape matters more here than for a cloud product. Observed hosts follow two patterns:

  • <something>.wondersoft.in on a non-standard port, for example ports 6010, 8989 and 9032, for vendor-hosted or vendor-managed instances.
  • <brand>.eshopaid.com for tenant-branded instances, which is where the SOAP sales feed lives.

Private LAN addresses also appear in the same collections next to public ones, which is consistent with the service being installed inside a customer's network and exposed selectively. There is no single shared API host.

API access

There is no developer signup, no console and no published key issuance. Access requires Wondersoft or the customer to provide:

  1. The base host and port for that installation.
  2. A service user name and password.
  3. For the SOAP feed, the tenant host and a store or group scope.

No API version appears anywhere in any path or header. No SDK, no OpenAPI specification and no official Postman collection exists.

Authentication

REST service

Two steps.

Step one, get a token. The operation is selected by a header, not by the path, and the credentials are also headers with no body at all.

POST /eShopaidService.svc/Token HTTP/1.1
Host: your-eshopaid-host:8989
SERVICE_METHODNAME: GetToken
UserName: YOUR_SERVICE_USER
Password: YOUR_SERVICE_PASSWORD

The response carries a long uppercase hexadecimal string, several hundred characters, which reads as an encrypted blob rather than a random identifier.

Step two, call an operation. The token goes in Authorization with no scheme prefix, and the operation name goes in SERVICE_METHODNAME.

POST /eShopaidService.svc/ProcessData HTTP/1.1
Host: your-eshopaid-host:8989
SERVICE_METHODNAME: GetInventory
Authorization: YOUR_TOKEN
Content-Type: application/json

{
  "Params": {
    "Location": "1",
    "DateFilter": "12/21/23",
    "ChannelTypeCode": "2",
    "ProviderCode": "202"
  }
}

Points to design around:

  • The header name is capitalised inconsistently in the wild, UserName in most places and Username in others. HTTP headers are case-insensitive so this does not matter, but it is a sign of a hand-built surface.
  • Token lifetime is not stated anywhere. Assume it expires and rebuild the token on any authentication failure rather than on a timer.
  • There is one path, ProcessData, for every operation. Routing is entirely by header. A proxy or gateway that strips unknown headers will silently break the integration.
  • Both JSON and XML bodies are accepted for the same operation, with Content-Type selecting. Pick one and stay with it.

SOAP feed

Credentials travel inside a custom SOAP header on every call. There is no token.

<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:esh="http://eshopaid.in">
  <soapenv:Header>
    <esh:eShopaidSoapHeader>
      <esh:UserName>YOUR_USER</esh:UserName>
      <esh:Password>YOUR_PASSWORD</esh:Password>
      <esh:MethodName>TransactionSegment</esh:MethodName>
      <esh:FromDate>2026-09-01</esh:FromDate>
      <esh:ToDate>2026-09-07</esh:ToDate>
      <esh:OptionalData></esh:OptionalData>
    </esh:eShopaidSoapHeader>
  </soapenv:Header>
  <soapenv:Body>
    <esh:GetResponseAsDataSet />
  </soapenv:Body>
</soapenv:Envelope>

Posted to https://<tenant>.eshopaid.com/ADSR/eShopaidservices.asmx with Content-Type: text/xml; charset=utf-8. The SOAPAction header is present but empty in the working integration.

The design is unusual and worth understanding: there is exactly one SOAP operation, GetResponseAsDataSet, and what you actually asked for is MethodName in the header. The date range is also in the header, not the body. The body is an empty element.

Objects we can read

Orders and sales

Through the SOAP feed, sales come back in three separate calls that must be joined on the client:

All three are keyed on RECEIPT_NO. A working integration calls all three for the same date range in parallel and groups by that field into a receipt with its items and payments. The response is a .NET typed DataSet serialised as a diffgram, so the JSON or XML path to the rows is deep: the response element, then the result element, then diffgr:diffgram, then a dataset element such as eShopaidTransactionSegment, then the repeated row element TransactionSegment.

Three practical consequences:

  • The rows are a flat recordset, not a document. Column names are upper case with underscores. The full column list is not published and has to be discovered from a live response for the specific customer, because eShopaid deployments are configured separately for each retail group.
  • A diffgram carries no schema guarantees between deployments. Parse defensively.
  • There is no cursor and no changed-since filter. The only selector is the date range, so incremental sync is a rolling window, and edits to a closed day are invisible unless that day is re-read.

Through the REST service, GetInvoiceDetails takes a date range and returns invoices:

{
  "Order": {
    "Params": {
      "FromDate": "20210902",
      "ToDate": "20210914"
    }
  }
}

Dates in the REST service are YYYYMMDD strings with no separators, while the SOAP feed uses YYYY-MM-DD. The two surfaces do not share a date convention.

GetOrderStatus looks up one order:

{
  "SalesOrderStatus": {
    "Order": {
      "OrderNumber": "ORD10123",
      "OrderDate": "20170613",
      "OrderLocation": "A21"
    }
  }
}

Note the composite key: an order is identified by number, date and location together, not by number alone. Any store of eShopaid orders must key on all three.

Products and listings

GetProducts exists as a named operation but no worked example with a request body was found. Ask Wondersoft for its parameters.

Inventory

GetInventory takes Location, DateFilter, ChannelTypeCode and ProviderCode. Location is a store code. ChannelTypeCode and ProviderCode point at a channel model inside eShopaid, which matters for anyone doing marketplace or ONDC work, since stock can evidently be scoped per channel and per provider. The response shape was not observed. DateFilter in the observed example uses United States style MM/DD/YY, a third date format in the same product, which should be confirmed rather than assumed.

Customers

Customer data is embedded in the order creation request, not exposed as its own object. No customer read operation was observed.

Locations

No list operation was observed. Store codes appear as OrderLocation, Location and StoreCode, and the same installation uses both a StoreCode and an AlternateStoreCode, so two code systems coexist. Establish which is authoritative for the customer before mapping.

Shipments, returns and settlements

No shipment object, no carrier data and no settlement object. Returns are presumably receipts with a negative or typed transaction, which would surface in the SOAP feed, but no return-specific operation was observed.

Writing back: listings, price and stock

For eShopaid, read this as pushing sales orders and order status in. Price and stock have no documented write path.

Create a sales order

SERVICE_METHODNAME: CreateSalesOrder against ProcessData. Both JSON and XML forms are in use. The JSON form, trimmed:

{
  "Order": {
    "Customer": {
      "FirstName": "Tamil",
      "MobileNumber": "9524524496"
    },
    "Header": {
      "OrderDate": "20231221",
      "OrderNumber": "ORD100101",
      "OrderLocation": "1",
      "TotalOrderValue": "2"
    },
    "Items": {
      "Item": [
        { "ItemCode": "2", "Quantity": "1", "Rate": "100" },
        { "ItemCode": "3", "Quantity": "1", "Rate": "100" }
      ]
    },
    "Payments": {
      "Payment": {
        "PaymentMode": "CASH",
        "PaymentValue": "100",
        "ModeType": "1",
        "PaymentReference": "123r"
      }
    }
  }
}

The XML form of the same operation carries a much richer customer block: TitleName, FirstName, MiddleName, LastName, Gender, MobileNumber, EmailID, UIN, GSTIN, three customer address lines, CustomerCityName, CustomerStateName, CustomerStateGSTCode, Pincode and a date of birth given four times over as a combined value and as separate day, month and year fields. The header carries OrderDate, OrderNumber, OrderLocation, CustomerCode and three delivery address lines.

All of that is PII, and GSTIN and UIN are tax and identity numbers that need handling as sensitive data, not as ordinary attributes.

Numbers arrive as strings throughout. Payments.Payment is an object in the observed sample while Items.Item is an array, which is the classic XML-to-JSON single-element problem: a one-tender order will probably serialise as an object and a multi-tender order as an array. Handle both.

OrderNumber is your external reference and, with OrderDate and OrderLocation, forms the lookup key for GetOrderStatus. There is no documented idempotency behaviour, so check with GetOrderStatus before retrying a create.

Update order status

A separate, older endpoint outside the service: an ASPX page at /shopaid/coutil/ProcessStatusUpdate.aspx, taking Content-Type: application/xml and an <OrderStatusUpdate> document. Its fields include OrderDate, OrderNumber, OrderSeries, TerminalNumber, StoreCode, VendorOrderNumber, AlternateStoreCode, IsClosed, OldStatus, NewStatus, UserName, Remarks, Mode, SourceChannel, BillDate, BillWSDN, BillAmount, CycleCount, and a reference block of RefDate, RefSeries, RefNumber, RefTransID, RefStoreCode and RefTerminalNo, plus IsCompletelyProcessed.

The interesting parts: statuses are numeric and the transition is expressed as both OldStatus and NewStatus, so the caller must know the current state. Mode carries a human label alongside. SourceChannel names the originating system, which is how eShopaid attributes an order to a channel partner. BillWSDN links the order to the resulting bill.

The numeric status list is not published and is the single most important thing to obtain before building an order integration.

Price and stock

No operation that sets price or stock was observed on either surface. Stock in eShopaid moves through its own goods receipt and transfer documents, which are not exposed. If pushing stock is a requirement, it must be raised with Wondersoft directly; do not assume it is possible.

Webhooks and notifications

No outbound webhook, no subscription mechanism, no signature scheme and no retry policy is documented or observable.

The status update ASPX endpoint is the opposite direction: an external system pushing state into eShopaid. It is useful, but it is not a notification.

Poll. A workable pattern for a chain:

  • Sales through the SOAP feed on a rolling window, for example every hour for the current day plus a nightly re-read of the previous two days to absorb late edits and back-dated bills.
  • Orders through GetOrderStatus per outstanding order, or GetInvoiceDetails over a short date range.
  • Inventory through GetInventory per location, on a cadence agreed with the customer, since the service usually runs on hardware they own.

Agree all of this with the customer's IT contact first. These services are frequently installed inside a customer network on a machine that is also doing other work.

Rate limits and pagination

Nothing published and nothing observable. There is no quota header, no page parameter and no cursor on either surface.

The SOAP feed returns an entire date range in one DataSet, so the response size is bounded only by how many receipts the range contains. For a busy chain a week of receipts across three segments is a large XML document. Keep the window small, one or two days, and expect to tune it per customer.

The working integration found in the wild uses a 30 second default timeout and fetches the three segments in parallel. That is a reasonable starting point.

Mapping to the unified model

Field names below are the ones actually observed. The SOAP feed's column names are deployment-specific beyond RECEIPT_NO and must be discovered per customer.

Gaps and open questions

  • No vendor documentation exists. Everything here needs confirming with Wondersoft before a customer commitment.
  • The numeric order status list is unpublished and blocks any order integration. Get it first.
  • The SOAP feed's column names beyond RECEIPT_NO are unknown and are deployment-specific. Obtain a live sample per customer.
  • GetInventory and GetProducts response shapes were not observed.
  • Token lifetime, renewal behaviour and what the encrypted token actually encodes are unknown.
  • The full list of SERVICE_METHODNAME values is unknown. Seven were observed: GetToken, ValidateLogin, CreateSalesOrder, GetInventory, GetInvoiceDetails, GetOrderStatus and GetProducts. There are almost certainly more.
  • Whether price or stock can be written at all is unresolved, and the answer changes the value of this connector considerably.
  • Three date formats coexist across the two surfaces. Each must be confirmed per operation.
  • Whether eShopaidService.svc and ShopaidService.svc are the same contract is unconfirmed, though both appear with identical headers and body shapes.
  • ChannelTypeCode and ProviderCode imply a channel model that is not documented. For ONDC or marketplace work this is the first thing to ask about.
  • Several public Postman workspaces expose what look like live tokens and a repeated vendor default credential pair. That is a security finding to raise, not a shortcut to use.
  • wondersoft.in redirects to wondersoft.com, but the service hosts remain on wondersoft.in. Do not assume the marketing domain and the service domain are interchangeable.

Sources

  • Wondersoft product site, read 2026-09-22. Product line, scale figures, the "open APIs for custom integration" statement, cloud and thin offline POS deployment
  • Wondersoft ERP integration page, read 2026-09-22. Named ERP targets, no technical detail
  • UthSoftware/POS_Integration_Chennai_Airport_LIVE, public repository, read 2026-09-22. A working Node.js eShopaid integration. Source of the SOAP envelope, the eShopaidSoapHeader structure, the http://eshopaid.in namespace, the GetResponseAsDataSet body, the TransactionSegment, ItemSegment and PaymentSegment method names, the RECEIPT_NO join key, the diffgram response path and the <tenant>.eshopaid.com/ADSR/eShopaidservices.asmx host pattern
  • Public Postman collection "Rodeo-API", uid 31303919-6d1952ce-3575-44e6-85c2-feade0548a88, retrieved 2026-09-22. Source of GetToken, ValidateLogin, CreateSalesOrder, GetInventory, GetInvoiceDetails, GetOrderStatus and the SERVICE_METHODNAME plus Authorization header pattern
  • Public Postman collection "Dusminute", uid 31303919-b65eee26-82b8-4c42-86c8-02fd6d713d56, retrieved 2026-09-22. Source of the XML form of CreateSalesOrder and of the ProcessStatusUpdate.aspx <OrderStatusUpdate> document
  • Public Postman collection "khimani", uid 27071637-d7a1b234-cd83-48df-9108-b31026afc8a7, retrieved 2026-09-22. A third independent installation on the same eShopaidService.svc/ProcessData contract
  • DNS and certificate transparency checks on 2026-09-22: api.wondersoft.in and docs.wondersoft.in do not resolve; certificate records for wondersoft.in show a UAT host and a wildcard; wondersoft.in redirects to wondersoft.com
  • GitHub repository and code search for eshopaid and wondersoft, run 2026-09-22: no vendor owned repository or SDK