Focus 9 is an ERP from Focus Softnet, a vendor founded in 1992 with headquarters in Dubai and a large development and support operation in Hyderabad, selling across the GCC, India, South and South East Asia, Africa, the United Kingdom and North America. It is a full finance, inventory, distribution, manufacturing, CRM, HCM and point of sale suite, and in Indian and Gulf retail and distribution accounts it is the system of record for sales orders, invoices, item master, stock by warehouse, customers and receipts. Focus Softnet has since launched FocusX as its fourth-generation flagship, but Focus 9 is still marketed and still widely deployed, and both share the same underlying service layer.
Focus Softnet publishes no developer portal. However, unlike most vendors in this part of the catalogue, the actual contract is recoverable: a public Postman team workspace contains a collection called FocusAPI with ninety requests against a /8API/ path, complete with the login request, real session responses and real voucher bodies, and a second collection posting a sales voucher against a live customer tenant at ymt-9.focus9erp.com/focus8api/. Two independent artefacts agree on the path prefix and the header name, which is why this page can be specific where the Logic ERP page cannot.
At a glance
Provenance matters here. Everything technical on this page comes from a public Postman team workspace under the handle cloudy-star-9788 (team 247201), which is not badged as Focus Softnet. It is treated as credible because the collections reference a real Focus customer tenant (ymt-9.focus9erp.com), internal Focus development IP addresses, and a WCF service layer named Focus8Library that matches Focus's own product naming, and because two separately created collections agree on the 8API prefix and the fSessionId header. Confirm every endpoint with Focus Softnet before shipping. Do not treat the field lists as a contract.
What it is
Focus Softnet sells a family of products: FocusX, the current flagship described as a fourth-generation AI-enabled ERP; Focus 9, the previous flagship and still a live product page; and vertical products including Focus WMS, Focus MRP, Focus POS, Focus CRM, Focus HCM, Focus REMS for real estate and Focus CAFM. The company runs country sites for India, the United States, the United Arab Emirates, Saudi Arabia, Kuwait, Qatar, Oman, Bahrain, Kenya, Singapore, Malaysia, Indonesia, the Philippines, Bangladesh, Canada, Nigeria and the United Kingdom.
The stack is Microsoft: an ASP.NET application with a WCF service layer and a Microsoft SQL Server database. Deployments are either on the customer's own server or on a Focus-hosted cloud tenant, and the cloud tenants use a per-customer hostname pattern, <customer>-9.focus9erp.com, resolving to Azure. That pattern is the practical thing to know: the base URL is per customer, and "the Focus 9 API" is not a single shared host.
FocusX marketing lists "3rd Party Apps and RESTful APIs" as a feature and names Xero, Tally, QuickBooks, Stripe, PayPal, ICICI Bank, Pine Labs, Mada, Shopify, Magento, WooCommerce, Amazon, Twilio, Office 365, UPS, ShipStation, ShipHawk, MailChimp, SendGrid and Zapier as integrations. No Zapier app under any Focus Softnet name could be found on Zapier, so treat that list as a statement of capability rather than a list of shipped connectors.
API access
There is no developer console, no API key issuance page and no published plan. Access works like this:
- The customer already has a Focus 9 installation, either on-premise or on a Focus-hosted tenant.
- You obtain a Focus user account on that installation, with the company code for the company you are integrating against. The login request takes a user name, a password and a company code, so the credential is an ordinary ERP user, not a separate application credential.
- Your base URL is that installation's host plus the API path. The recovered collections use
http://localhost/8API/...for a local install andhttps://ymt-9.focus9erp.com/focus8api/...for a hosted tenant. The casing of the prefix varies between8API,8apiandfocus8apiin the same collection, which suggests the server is case-insensitive, but confirm rather than assume.
No API version number appears in any path or header. That is a risk: there is no visible contract for what breaks on upgrade.
No official SDK exists in any language. No first-party OpenAPI specification could be found. GitHub has no Focus Softnet owned organisation or repository.
Authentication
The model is a session token, not OAuth and not a static key.
- Call the login endpoint with the user name, password and company code.
bfrommobileandbwithmobileappdatacontrol whether the server also returns mobile application data, and both can be sent as false for a server-to-server integration. - Read
fSessionIdfromdata[0]. - Send that value in an
fSessionIdheader on every subsequent request, alongsideContent-Type: application/json.
Token request:
POST /8api/MobileLogin HTTP/1.1
Host: yourtenant-9.focus9erp.com
Content-Type: application/json
{
"data": [
{
"UserName": "su",
"password": "su",
"Companycode": "4p0",
"bwithmobileappdata": false,
"bfrommobile": true
}
]
}
Response:
{
"url": "http://localhost/8api/MobileLogin",
"data": [
{
"iLoginId": 1,
"Status": 4,
"EmployeeId": 0,
"iLogId": 4985,
"LoginName": "SU",
"AltLanguageId": 0,
"fSessionId": "4P0-020120261239336460841",
"EmployeeName": ""
}
],
"result": 1,
"message": ""
}
Authenticated call:
GET /8API/List/Transactions/Sales%20Orders?pageNo=0&NoOfRows=2 HTTP/1.1 Host: yourtenant-9.focus9erp.com fSessionId: 4P0-020120261239336460841 Content-Type: application/json
Notes on the token:
- The
fSessionIdvalue is structured, not opaque:4P0-020120261239336460841begins with the company code in upper case, then what reads as a date and time stamp. Another sample,0X0-0412202511332922111881, has the same shape. Do not parse it, but do expect it to be company-scoped, which means one session per company rather than one session across companies. - Lifetime is not published. Treat it as a server session that can expire, and build a re-login path triggered by an authentication failure rather than a fixed refresh timer.
- Header capitalisation is inconsistent across the collections:
fSessionIdon most calls,fsessionIdon the voucher post,fsessionidon the OTP call, and an emptyfsessionheader on login. HTTP headers are case-insensitive so this should not matter, but it is a sign of a hand-built surface. - Multi-account: select the company at login with
Companycode, and useGET /8API/List/Companyto enumerate companies. Several utility calls take aCompanyId, for exampleGET /8API/List/Company/SupportedLanguage?where=CompanyId=36andGET /8API/utility/companycodefromid/36. For multiple sellers on separate installations, keep a credential and base URL per installation. - An OTP login exists,
POST /8api/LoginWithOTP, takingUserName,OTP,CompanyIdandloginid. It is unsuitable for an unattended connector. - A licence check exists,
POST /8api/GetLiceneceInfo, takingcompanyid. The endpoint name is misspelled on the server, which is worth remembering when it returns 404.
Objects we can read
Focus models almost everything as a voucher. The generic reading pattern is: list voucher types, list vouchers of one type, then fetch one voucher by id.
Orders
Sales orders are a voucher type named Sales Orders.
- List:
GET /8API/List/Transactions/Sales Orders?pageNo=0&NoOfRows=2. Pagination is page number plus rows per page, and the response carriesEndOfFileas the stop condition. - Detail:
GET /8API/Screen/Transactions/Sales%20Orders/{headerId}. - Field definitions for the type:
GET /8API/Field/Transactions/Sales%20Orders. This returns the configured field list, which matters because Focus vouchers are user-configurable and two installations of the same version will not have the same fields. - Voucher settings:
GET /8API/Screen/Transactions/VoucherSettings/{abbr}. - All voucher types:
GET /8API/List/Transactions. - Classification helpers:
GET /8API/utility/isitsales/Sales%20Orders,GET /8API/utility/IsItOrder/Sales%20Orders,GET /8API/utility/isitinwardvoucher/{abbr},GET /8API/utility/isittransfer/{abbr},GET /8API/utility/isitwms/{abbr}.
The list response is a grid, not a record set. Columns are described separately from the rows, so the connector has to zip Columns onto ColumnData by position.
{
"data": [
{
"ColumnData": [
[580, "Ajay", "1/191", "23/12/2025", "SU", "False", "Pending"]
],
"TotalRow": 0,
"EndOfFile": false,
"Error": false,
"Columns": [
{ "ColumnAlias": "HeaderId", "IsHidden": true },
{ "ColumnAlias": "Customer Account Name", "IsHidden": false },
{ "ColumnAlias": "Voucher Number", "IsHidden": false },
{ "ColumnAlias": "Date", "IsHidden": false },
{ "ColumnAlias": "Created by", "IsHidden": false },
{ "ColumnAlias": "Suspended", "IsHidden": false },
{ "ColumnAlias": "Authorization Status", "IsHidden": false }
]
}
],
"result": 1,
"message": null
}
The detail response splits into Header, Body and Footer.
{
"data": [
{
"Header": {
"DocNo": "1",
"Date": 132317982,
"Time": 929590,
"CustomerAC__Id": 19,
"CustomerAC__Name": "Customer A",
"CustomerAC__Code": "122-001",
"Department__Id": 0,
"sNarration": "su",
"HeaderId": 585,
"Net": 525,
"TransactionNet": 525
},
"Body": [
{
"Item__Id": 1,
"Item__Name": "item",
"Item__Code": "0",
"Unit__Id": 0,
"Quantity": 5,
"Rate": 105,
"Gross": 525,
"Discount": { "Input": 0, "FieldName": "Discount", "FieldId": 8, "Value": 0 },
"TransactionId": 585,
"BaseQuantity": -5
}
],
"Footer": [
{ "FieldId": 25, "FieldName": "FooterVal", "Input": 0, "Value": 0, "ColMap": 1 }
]
}
]
}
Fields marked PII: CustomerAC__Name, CustomerAC__Code, any delivery address field, and the Signature field, which returns a base64 JPEG of a captured signature inline in the header. Strip it before storing.
Date is an integer date identifier in Focus's internal format, not Unix epoch seconds and not an ISO date. Differences between samples behave like minutes but the epoch is not published. Get the conversion from Focus Softnet rather than reverse engineering it, and never persist the raw integer as if it were a timestamp.
Order items
Body lines as shown above: Item__Id, Item__Name, Item__Code, Item__Alias, Unit__Id, Unit__Name, Quantity, Rate, Gross, Discount, TransactionId, BaseQuantity, BodyFlags. The double underscore is Focus's convention for a master reference expanded into id, name, code and alias.
Products and listings
GET /8API/List/Masterslists the master types available.GET /8API/List/Masters/Core__Product/Grouplists product groups.GET /8API/List/Masters/Core__Accountlists accounts, andGET /8API/List/Masters/Core__Account/{groupCode}lists within a group. Focus treats products and ledgers through the same master machinery, so the master name selects what you get.GET /8api/Screen/Masters/Core__Account/{id}fetches one master record.GET /8API/List/Masters/Core__Account/Trees,/TreeViewsand/Leafexpose the master hierarchy.POST /8API/Masters/masterdatacoloumnwisereturns master data column-wise. The spelling is the server's.GET /8API/Screen/CoreMasters/UnitsandGET /8API/List/CoreMasters/UnitConversioncover units and conversions, which matter for any retail catalogue with cases and pieces.- Price books:
GET /8API/List/CoreMasters/BuyerPriceBook. A seller price book list uses the same path in the recovered collection, which looks like a copy and paste error in the collection rather than a real duplicate. - Rates for a product in context:
POST /8API/Transactions/Rateswithproduct__id,currency__id,date__id,pbabbr(price book abbreviation),pricebooktype,quantity,unit__code,customer__id. This is the call that answers "what price does this customer pay for this item today". - Tax rates:
GET /8API/List/Transactions/Taxrates. - Product images: the WCF layer has
POST /Focus8Library/MasterService.svc/GetProductImage.
Sample responses for the master endpoints are not published in the recovered material.
Inventory
POST /8API/Transactions/Stockwith a body of{"data": [{"Product__Id": "2", "Date__Id": "132317971"}]}returns stock for a product as at a date. Sample response not published.- Batches:
GET /8API/Transactions/Batches. Bins:GET /8API/Transactions/bins. - The WCF warehouse layer is richer:
POST /Focus8Library/wms2service.svc/LoadProductInquiryfor item enquiry,LoadBinInquiryfor bin enquiry,LoadSkidInquiryfor pallet enquiry,ValidateBin,ValidateSkid,LoadAllocationDataandPostAutoAllocate. Warehouse is a separate service, not part of8API.
Note that the stock read takes a single product id. There is no documented bulk stock endpoint in the recovered material, which is the single biggest practical problem for a catalogue sync. Ask Focus Softnet for a bulk stock or changed-since stock call before designing around per-product polling.
Shipments and tracking
Not present as an object. Focus is not a carrier and holds no AWB or carrier event. The warehouse layer has dispatch confirmation, POST /Focus8Library/wms2service.svc/SaveDispatchConfirm, and GetLogisticInfo, which is as close as it gets. Carrier data must come from the logistics provider.
Returns and cancellations
Returns are voucher types like any other, reachable through the same list and detail pattern once you know the type name and abbreviation for the installation. GET /8API/List/Transactions enumerates them. No dedicated returns endpoint exists.
Payments and settlements
- Receipts are a voucher type: the authorisation endpoints use
Receiptsas their worked example,GET /8API/Screen/Transactions/AuthorizeVouchers/Receipts/Rct:1andGET /8API/Screen/Transactions/RejectVouchers/Receipts/Rct:1. POST /8API/Transactions/accountbalancewithaccount__id,date__idandbalancetypereturns a ledger balance.POST /8API/Transactions/ExchangeRateForLocalCurrencyhandles multi-currency, which matters for the Gulf deployments.- There is no marketplace settlement object. Settlements come from the channel, not from Focus.
Customers
Customers are accounts under the account master, read through GET /8API/List/Masters/Core__Account and GET /8api/Screen/Masters/Core__Account/{id}. Treat name, code, address and contact fields as PII.
Locations
Warehouses appear as an id on voucher lines (Warehouse in the posting body) and as bins and stores in the warehouse layer, for example GET /Focus8Library/TransactionService.svc/LoadDistributionStoreList?iASNId=123. There is no simple documented "list locations" call in 8API; enumerate through the master list.
Reports
Focus exposes its report engine over the API, which is often the fastest route to a bulk extract when no object endpoint fits.
GET /8API/List/Reports,GET /8API/List/Reports/ReportParameters/{reportName},GET /8API/Screen/Reports/ReportLayouts/{reportName}/{id}.POST /8API/Reports/pagedatawithReportId,LayoutId,StartingDate,EndingDate,RowsPerPage,CurrentPage,MastersandInputsreturns a page of report rows.POST /8API/Reports/pagedatahtmlreturns the same as HTML.GET /8API/Screen/Reports/Closereport?where=UniqueId={guid}releases the server-side report session. Call it. Report sessions that are never closed are a classic way to exhaust a Focus server.
The collection also contains POST /8API/utility/ExecuteSqlQuery and POST /8API/utility/ExecuteNonQuery, which take a raw SQL string and run it against the ERP database. If that is enabled on a customer installation it is both the easiest extraction route and a serious security problem. Do not build on it. Raise it with the customer as a finding.
Writing back: listings, price and stock
For an ERP, read this as: can we push sales orders, invoices and stock adjustments in. The answer is yes, through one generic voucher endpoint.
Create a voucher:
POST /focus8api/Transactions/Vouchers/5634 HTTP/1.1
Host: yourtenant-9.focus9erp.com
fSessionId: 0V0-121220251194096311161
Content-Type: application/json
{
"data": [
{
"Header": {
"Salesman": "14",
"bIsNew": true,
"CustomerAC": "2966",
"Department": "1",
"Tax Code": "2",
"OrderedBy": "",
"DeliveryAddress": "",
"DocNo": "",
"Date": "132713484"
},
"Body": [
{
"Item": "5295",
"Warehouse": "1",
"Description": "OOTY GOLD PONNI PARBOILED RICE - 5KG X 6",
"Rate": "10.00",
"Quantity": "12.00",
"Gross": "120.00",
"Unit": "2",
"TransactionId": "0"
}
]
}
]
}
Points that decide the design:
5634in the path is the numeric voucher type id. It is installation-specific, so resolve it fromGET /8API/List/Transactionsrather than hard-coding it. The same collection shows a second posting form,POST /8API/Transactions/{voucherTypeId}-{abbr}, for example/8API/Transactions/944-RTS, used for a richer body with batches and bins. Which form applies to which voucher type is not documented.bIsNew: truemarks a create. Setting it false is presumably an update, but no update example exists and this has not been verified.DocNois sent empty and the server allocates. If you need the number in advance,POST /8API/Transactions/NewVoucherNumberwith{"data":[{"VoucherType":"Sales Orders"}]}returns one.- Every reference in the body is an internal id, not a code:
CustomerAC,Item,Unit,Warehouse,Salesman,DepartmentandTax Codeare all numeric. A write connector therefore needs a resolution step from your SKU and customer code to Focus ids, and a cache of that mapping. This is the main build cost. - There is no documented idempotency key and no documented external reference field. Duplicate protection has to be built on your side, most safely by writing your own reference into a user-defined field on the voucher and checking for it before posting. Focus vouchers are user-configurable so such a field can be added by the customer.
- The richer posting form carries
Batch,ExpDate__Id,BinswithBins__Idandskidid,LPN_Line_NoandUsecase, so batch and bin level stock movements are writable where the installation is configured for them. - Delete:
DELETE /8API/Transactions/{voucherTypeId}/{voucherNumber}, for example/8API/Transactions/2564/SCN2026~~00001. Note the double tilde separator inside the voucher number. - Authorise or reject a posted voucher:
GET /8API/Screen/Transactions/AuthorizeVouchers/{type}/{ref}and.../RejectVouchers/{type}/{ref}. Whether a created voucher lands authorised or pending depends on the installation's workflow, and the list response'sAuthorization Statuscolumn showsPendingin the sample, so do not assume a write is final. - Masters:
POST /8API/Masters/CreateMasterdefines a new master type, andPOST /8API/Masters/{masterName}saves a record, for examplePOST /8API/Masters/Core__jobnowith{"data":[{"sName":"j1","sCode":"j1"}]}. The warehouse layer also hasPOST /Focus8Library/MasterService.svc/SaveMasterByNames, which resolves references by name instead of id and is worth asking about, because it would remove most of the id resolution work.
Price and stock are not written directly. Price is a master and price book concern, stock changes only through vouchers. There is no "set stock to N" call, and there should not be.
No sample success or error response for a voucher post is published. The collection that contains the live posting is named "Ambikas Posting Null Return", which reads as a support ticket about a posting that returned null. Take that as a warning that error handling on this endpoint is not obvious and needs to be established empirically with the vendor.
Webhooks and notifications
None found. No subscription endpoint, no event catalogue, no signature header and no retry policy appears in any recovered material, and Focus Softnet publishes nothing on the subject.
There is an in-application alert system, GET /8API/Screen/Transactions/Alerts, GET /8API/Screen/Transactions/Alerts/{id} and GET /8API/Screen/Transactions/AlertApprovalCount, but it notifies Focus users inside the product, not external systems.
Poll instead. A workable cadence for a single installation, to be agreed with the customer because most installations are on hardware they own:
- Sales and financial vouchers: every 15 minutes, using the voucher list with page numbers and stopping on
EndOfFile. There is no documented modified-since filter, so either use the report engine with a date range or filter client side on the date column. - Masters: hourly for changed items, daily for a full refresh.
- Stock: this is the problem case, because the only documented read is one product at a time. Prefer a stock report through
POST /8API/Reports/pagedataover looping the stock endpoint, and agree the schedule with the customer.
Rate limits and pagination
No rate limit is published, no quota header appears in any sample, and for on-premise installations the binding constraint is the customer's own server rather than a vendor quota.
Pagination on list endpoints is page number and page size: ?pageNo=0&NoOfRows=2, with EndOfFile in the response as the terminator and TotalRow present but zero in the sample, so do not rely on a total. The report engine paginates with CurrentPage and RowsPerPage in the request body.
Practical guidance: keep concurrency at one request at a time per installation until the customer's IT contact agrees otherwise, always close report sessions with the close endpoint, and prefer the report engine over row-by-row endpoints for anything bulk.
Mapping to the unified model
Field names below are the ones observed in the recovered collections. They are configurable per installation, so verify against GET /8API/Field/Transactions/{voucherType} for the specific customer before relying on any of them.
Gaps and open questions
- Provenance. Nothing here is vendor-published. The Postman workspace is public and internally consistent and matches a real customer tenant, but Focus Softnet has not confirmed any of it. Every endpoint needs confirming before a customer commitment.
- Versioning. No version appears in any path or header, and the prefix is
8API, inherited from Focus 8. Whether FocusX keeps the same surface is unknown and is the first question to ask, since Focus is actively moving customers onto FocusX. - The date and time integer format is unresolved. This blocks any date filtering and is the highest priority item for a vendor conversation.
- There is no documented modified-since filter on any list endpoint. Incremental sync may have to go through the report engine, which changes the whole design.
- There is no documented bulk stock read. Per-product polling will not scale for a retail catalogue.
- There is no documented idempotency mechanism on voucher creation. Double-posting an order is a real risk and needs a customer-side guard.
- The two voucher posting path forms,
/Transactions/Vouchers/{id}and/Transactions/{id}-{abbr}, are unexplained. Which to use when is unknown. - Rate limits, session lifetime, error codes and the response shape of a failed write are all unpublished.
ExecuteSqlQueryandExecuteNonQueryaccept raw SQL. If present and reachable on a customer installation, that is a security finding to escalate, not a feature to use.- Focus 9 versus FocusX. The Focus 9 product page is still live but Focus 9 is absent from the current product sitemap, which lists FocusX instead. Confirm which product a given customer runs before quoting this page.
- Do not confuse this vendor with Focus POS, an unrelated United States restaurant point of sale company that also has a public Postman collection.
Sources
- Focus Softnet Focus 9 product page, read 2026-09-22
- Focus Softnet FocusX product page, read 2026-09-22, source of the "3rd Party Apps and RESTful APIs" claim and the integration list
- Focus Softnet product sitemap, read 2026-09-22, showing the current product line and country sites
- Public Postman collection
FocusAPI, uid5953841-6f16752e-8a88-4b5a-8836-615919f2b4f1, team 247201, publisher handlecloudy-star-9788, created 21 November 2025 and updated 5 May 2026, retrieved 2026-09-22. Ninety requests under/8API/, description: "Focus Softnet offer a robust REST API for developers a seamless integration platorm. It allows access to all the modules and nearly all the feautes available in Focus-ERP." Spelling as published - Public Postman collection
Focus8Library, uid5953841-13b75822-6e1d-4720-9197-f2e97913e7cc, same team, retrieved 2026-09-22. The WCF warehouse service layer - Public Postman collection
Ambikas Posting Null Return, uid5953841-c4947499-978c-4b53-90da-11cb28f55797, same team, retrieved 2026-09-22. Source of the live voucher posting request againstymt-9.focus9erp.com/focus8api/ - DNS and HTTP probes on 2026-09-22:
docs.focussoftnet.com,api.focussoftnet.comanddeveloper.focussoftnet.comresolve through a wildcard but serve nothing;ymt-9.focus9erp.comresolves to an Azure address - Zapier app directory search for Focus Softnet, FocusX, Focus 9 and Focus ERP, run 2026-09-22: no matching app, despite the Zapier logo on the FocusX integrations panel
- GitHub repository and code search for
focussoftnet, run 2026-09-22: no vendor owned repository or SDK