Customers & Prescriptions – OptoSoft API

Create and update customers, search the customer register, detect duplicates, and manage spectacle and contact-lens prescriptions (SPH, CYL, AXIS, ADD, PD) plus the referring-doctor master.

13 endpoints in this module. Every request needs a JWT bearer token — see Authentication.

JWT bearer auth JSON request & response 85 documented endpoints Reviewed monthly

Customers & Prescriptions

The customer module is the entry point for almost every OptoSoft workflow. It holds the customer register, the full optical prescription history (spectacle powers and contact-lens parameters), and the referring-doctor master used on prescriptions and orders.

A customer in OptoSoft is more than a contact record: it carries the latest recorded prescription inline (the lefT_* / righT_* fields), membership and loyalty flags, marketing consent (DND) flags, and GST details for business customers.

Typical sequence

  1. Search with /api/Customer/list by mobile number.
  2. If nothing matches, guard with /api/Customer/check-duplicate, then create via /api/Customer/upsert.
  3. Attach the eye test with /api/Customer/save-prescription.
  4. Raise the order — see Sales Orders.

Mobile number is the practical natural key. OptoSoft does not enforce uniqueness on it, so always search before creating and always run check-duplicate in an automated import, or you will fragment a customer’s prescription and purchase history across duplicates.

The search model

Six endpoints on this page share one request model. Every field is a filter: supply only the ones you want to narrow by and omit the rest. companyID and branchID are numeric here, unlike most of the API.

FieldTypeRequiredDescription
companyIDint64RequiredYour OptoSoft company (tenant).
branchIDint64RequiredThe store to search within.
yearIDint64OptionalFinancial year. Resolve from GET /api/Common/GetYears.
customerIDstringOptionalEncrypted customer ID. Set this to fetch one specific customer.
firstNamestringOptionalPartial match on given name.
lastNamestringOptionalPartial match on surname.
mobilestringOptionalMobile number. The most reliable lookup.
phoneNOstringOptionalLandline number.
emailstringOptionalEmail address.
citystringOptionalCity filter.
isActivestringOptionalActive flag, sent as a string ("true" / "false").
customerSourceStringIDstringOptionalAcquisition source. Values from GET /api/quickSale/getSources.
typeIDstringOptionalCustomer category / type.
orderBystringOptionalSort column, optionally with DESC.
fromPageint32OptionalFirst row of the range (row-range paging).
toPageint32OptionalLast row of the range.

Customer endpoints

POST /api/Customer/list Bearer token

Searches the customer register and returns a paged list. This is the endpoint you use to find a walk-in customer by mobile number.

Request body

The shared search model described above.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/list \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "mobile": "9876543210",
    "fromPage": 1,
    "toPage": 20,
    "orderBy": "FirstName"
  }'
POST /api/Customer/detail Bearer token

Returns the complete record for a single customer, including address, membership and the inline latest prescription. Set customerID to the encrypted ID returned by /api/Customer/list.

Request body

The shared search model, with customerID set.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/detail \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "customerID": "ENCRYPTED_CUSTOMER_ID"
  }'
POST /api/Customer/check-duplicate Bearer token

Tests whether a customer matching the supplied mobile, email or name already exists, without creating anything. Call this before upsert in any bulk import.

Request body

The shared search model. Populate the identifying fields you are about to insert.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/check-duplicate \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "mobile": "9876543210",
    "firstName": "Anita",
    "lastName": "Shah"
  }'
POST /api/Customer/upsert Bearer token

Creates a new customer, or updates an existing one when id is supplied. This is the largest model in the customer module (77 fields), but only a handful are needed to create a usable record.

Most-used fields

FieldTypeRequiredDescription
idstringOptionalEncrypted customer ID. Omit to create; supply to update.
companyIDstringRequiredEncrypted company ID — a string here, unlike the search model.
branchIDstringRequiredEncrypted branch ID.
yearIDstringRequiredEncrypted financial-year ID.
firstNamestringRequiredGiven name.
lastNamestringOptionalSurname.
mobilestringRequiredMobile number. Used for WhatsApp and SMS recalls.
emailIdstringOptionalEmail address.
titlestringOptionalSalutation (Mr, Mrs, Ms, Dr).
genderIDstringOptionalEncrypted gender ID from GET /api/quickSale/getGenders.
birthDatedate-timeOptionalDrives birthday marketing campaigns.
addressstringOptionalFree-text address. Structured parts are also available (see full list).
citystringOptionalCity.
zipCodestringOptionalPIN code.
stateIDstringOptionalEncrypted state ID from GET /api/Common/GetStates/{countryId}. Drives CGST/SGST vs IGST.
countryIDstringOptionalEncrypted country ID from GET /api/Common/GetCountries.
gstnostringOptionalGSTIN for B2B invoices.
customerSourceIDstringOptionalHow the customer found you.
isActivebooleanOptionalDefaults to active.
dndForPromotionalMessagebooleanOptionalSuppress marketing messages. Set from your own consent capture.
dndForTransactionalMessagebooleanOptionalSuppress order and receipt notifications.
Show all 77 fields
FieldType
idstring
branchIDstring
stateIDstring
countryIDstring
faceShapeIDstring
genderIDstring
companyIDstring
customerIDstring
yearIDstring
titlestring
firstNamestring
middleNamestring
lastNamestring
isMarriedboolean
referencestring
birthDatedate-time
remarksstring
mobilestring
emailIdstring
citystring
zipCodestring
addressstring
houseNumberstring
societyNamestring
streetstring
areastring
landmarkstring
isActiveboolean
createdBystring
createdDatedate-time
createdIPstring
modifiedBystring
modifiedDatedate-time
modifiedIPstring
newCustomerboolean
isNRIboolean
marriageDatedate-time
existingCustomerReferencestring
phoneNOstring
gstnostring
customerSourceIDstring
customerCategoryIDstring
isStoreCustomerboolean
storeIDstring
isMemberboolean
membershipIDstring
ageint32
bloodGroupstring
selfstring
isBlackListboolean
dndForPromotionalMessageboolean
dndForTransactionalMessageboolean
clientConsentImagestring
clientConsentDisplayNamestring
prescriptionDocumentstring
prescriptionDocumentDisplayNamestring
isForeignerboolean
lefT_SphericalWithSignstring
righT_SphericalWithSignstring
righT_CylinderWithSignstring
lefT_CylinderWithSignstring
lefT_AxisWithSignstring
righT_AxisWithSignstring
righT_AdditionWithSignstring
lefT_AdditionWithSignstring
leftVisionstring
rightVisionstring
leftvnstring
rightvnstring
rightpdstring
leftpdstring
leftbcstring
rightbcstring
leftdiastring
rightdiastring
prescriptionRemarksstring
salesOrderIDstring

Example request

curl -X POST https://api.opto-soft.com/api/Customer/upsert \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": "ENCRYPTED_COMPANY_ID",
    "branchID": "ENCRYPTED_BRANCH_ID",
    "yearID": "ENCRYPTED_YEAR_ID",
    "title": "Ms",
    "firstName": "Anita",
    "lastName": "Shah",
    "mobile": "9876543210",
    "emailId": "anita.shah.example.in",
    "city": "Ahmedabad",
    "zipCode": "380015",
    "isActive": true,
    "dndForPromotionalMessage": false
  }'

The scoping fields are encrypted strings on this endpoint, not the numeric values used by the search model. Take them from a prior response (for example /api/Customer/detail) rather than converting the numbers yourself.

Prescription endpoints

A prescription in OptoSoft is an eye info record identified by customerEyeInfoID, holding one row per lens type (distance, near, contact lens) with the standard optical parameters.

ParameterOptical meaning
sphSphere — myopia or hyperopia correction, in dioptres.
cylCylinder — astigmatism correction.
axisAxis of the cylinder, 0–180 degrees.
addAddition — near power for bifocal and progressive lenses.
vaVisual acuity, distance.
vnVisual acuity, near.
pdPupillary distance, in millimetres.
bcBase curve — contact lenses.
diaDiameter — contact lenses.
fhFitting height for progressive lenses.
thTotal height of the lens.
lensTypeIDEncrypted lens-type ID identifying which row this is.
POST /api/Customer/prescription-list Bearer token

Lists a customer’s prescription history, newest first. Use it to show previous eye tests before recording a new one.

Request body

The shared search model, with customerID set.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/prescription-list \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "customerID": "ENCRYPTED_CUSTOMER_ID",
    "fromPage": 1,
    "toPage": 10
  }'
POST /api/Customer/GetPrescription Bearer token

Returns the summary view of one prescription.

Request body

FieldTypeRequiredDescription
customerEyeInfoIDstringRequiredEncrypted prescription ID from prescription-list.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/GetPrescription \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "customerEyeInfoID": "ENCRYPTED_EYE_INFO_ID" }'
POST /api/Customer/prescription-full-detail Bearer token

Returns the complete prescription, including every lens-type row and the associated doctor and remarks. Use this when reprinting an Rx or pre-filling a reorder; GetPrescription returns the lighter summary.

Request body

FieldTypeRequiredDescription
customerEyeInfoIDstringRequiredEncrypted prescription ID.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/prescription-full-detail \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "customerEyeInfoID": "ENCRYPTED_EYE_INFO_ID" }'
POST /api/Customer/save-prescription Bearer token

Records a new eye test against a customer. The customer identity fields sit at the top level and the optical powers go in prescriptionList, one entry per lens type.

Request body

FieldTypeRequiredDescription
companyIDint64RequiredCompany (tenant).
branchIDint64RequiredStore.
yearIDint64RequiredFinancial year.
customerIDstringRequiredEncrypted customer ID the prescription belongs to.
idstringOptionalEncrypted prescription ID. Omit to create a new one.
firstNamestringOptionalCustomer name, echoed onto the Rx printout.
lastNamestringOptionalCustomer surname.
mobilestringOptionalContact number.
emailstringOptionalEmail address.
birthDatestringOptionalDate of birth.
genderIDstringOptionalEncrypted gender ID.
doctorIDstringOptionalEncrypted referring-doctor ID. See doctor endpoints.
presripionTypeIDstringOptionalPrescription type. Note the spelling in the API.
visitingDatestringOptionalDate of the eye test.
sourceIDstringOptionalEncrypted acquisition-source ID.
houseNOstringOptionalAddress — house number.
societyNamestringOptionalAddress — society or building.
streetstringOptionalAddress — street.
areastringOptionalAddress — area.
citystringOptionalAddress — city.
prescriptionRemarksstringOptionalFree-text clinical notes.
prescriptionListarrayRequiredOne entry per lens type — see the parameter table above.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/save-prescription \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "yearID": 9,
    "customerID": "ENCRYPTED_CUSTOMER_ID",
    "doctorID": "ENCRYPTED_DOCTOR_ID",
    "visitingDate": "2026-07-26",
    "prescriptionRemarks": "Progressive lenses advised.",
    "prescriptionList": [
      {
        "lensTypeID": "ENCRYPTED_LENS_TYPE_ID",
        "sph": "-1.75",
        "cyl": "-0.50",
        "axis": "90",
        "add": "+2.00",
        "va": "6/6",
        "vn": "N6",
        "pd": "62"
      }
    ]
  }'
POST /api/Customer/delete-prescription Bearer token

Removes a prescription record. Note this is a POST, not DELETE.

Request body

FieldTypeRequiredDescription
customerEyeInfoIDstringRequiredEncrypted prescription ID to delete.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/delete-prescription \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "customerEyeInfoID": "ENCRYPTED_EYE_INFO_ID" }'

A prescription already referenced by a dispensed order should normally be superseded by saving a new one rather than deleted, so the order keeps its clinical audit trail.

Doctor endpoints

Prescriptions can cite a referring optometrist or ophthalmologist. These four endpoints maintain that master list.

POST /api/Customer/doctor-list Bearer token

Returns the full doctor list for the branch, unpaged. Suitable for populating a dropdown at start-up.

Request body

The shared search model.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/doctor-list \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "companyID": 18, "branchID": 24 }'
POST /api/Customer/doctor-list-page Bearer token

The paged equivalent of doctor-list, for a searchable admin grid. Use the fromPage and toPage row range.

Request body

The shared search model, with paging fields set.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/doctor-list-page \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "companyID": 18,
    "branchID": 24,
    "firstName": "Mehta",
    "fromPage": 1,
    "toPage": 25,
    "orderBy": "Name"
  }'
GET /api/Customer/get-doctor/{id} Bearer token

Returns one doctor record by encrypted ID.

Path parameters

NameTypeRequiredDescription
idstringRequiredEncrypted doctor ID from doctor-list.

Example request

curl https://api.opto-soft.com/api/Customer/get-doctor/ENCRYPTED_DOCTOR_ID \
  -H "Authorization: Bearer YOUR_TOKEN"
POST /api/Customer/save-doctor Bearer token

Creates a doctor, or updates an existing one when id is supplied.

Request body

FieldTypeRequiredDescription
idstringOptionalEncrypted doctor ID. Omit to create.
namestringRequiredDoctor’s full name as it should print on the Rx.
mobilestringOptionalContact number.
emailstringOptionalEmail address.
addressstringOptionalClinic address.
citystringOptionalCity.
stateIDstringOptionalEncrypted state ID.
countryIDstringOptionalEncrypted country ID.
zipCodestringOptionalPIN code.
remarksstringOptionalInternal notes.
isActivebooleanOptionalSet false to retire without deleting.

Example request

curl -X POST https://api.opto-soft.com/api/Customer/save-doctor \
  -H "Authorization: Bearer YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Dr. R. Mehta",
    "mobile": "9825012345",
    "city": "Ahmedabad",
    "isActive": true
  }'
Chat with us Call us