Contacts, Customers & Customer Ledgers
The unified party directory in Katixo. Manage customer and vendor masters, credit limits, statutory GSTIN numbers, billing and shipping addresses, and live chronological ledger statements.
1. Module Overview: Unified Contact Subledgers
In Katixo, contacts represent customers, vendors, or dual-role partners (who both buy and sell goods). Every contact maintains a live chronological subledger tracking opening balances, invoices, payments, and credit notes:
Credit Limit Enforcement
Set maximum credit limits (e.g. ₹2,00,000). System alerts cashiers or blocks new orders when exceeded.
GSTIN Validation
Validates 15-character statutory GSTIN structure and auto-derives the state code for tax determination.
Outstanding Balance Invariant
Outstanding = Opening Balance + Total Invoiced - Payments Received - Credit Notes.
2. How to Add a Contact (Step-by-Step UI Guide)
- 1Go to Contacts > Click "Add Contact":Choose Contact Type: Customer, Vendor, or Both.
- 2Enter Business & GST Details:Input Trade Name, Legal Name, and 15-digit GSTIN. The system automatically confirms the Place of Supply state code.
- 3Set Payment Terms & Credit Limits:Define agreed payment terms (e.g. Net 15, Net 30, Due on Receipt) and maximum credit limit in INR.
- 4View Unified Statement of Accounts:From any contact details page, click "View Ledger" to see all invoices, debit notes, receipts, and running balance.
Developer & REST API Reference
Programmatically query, create, update, and fetch customer ledgers via REST:
Authentication
All endpoints require a valid JWT Bearer token in the Authorization header.
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...Response envelope
Every response is wrapped in ApiResponse<T>.
{
"success": true,
"message": "Contact created successfully",
"data": { ... },
"errors": null
}Endpoints
/api/v1/contacts/api/v1/contacts/{id}/api/v1/contacts/api/v1/contacts/{id}/api/v1/contacts/{id}/api/v1/contacts/{id}/persons/api/v1/contacts/{id}/persons/{personId}Enums
ContactType
| Value | Description |
|---|---|
CUSTOMER | A customer you sell to. |
VENDOR | A vendor/supplier you buy from. |
BOTH | Acts as both customer and vendor. |
GstTreatment
| Value | Description |
|---|---|
REGISTERED | Registered under GST with a valid GSTIN. |
UNREGISTERED | Not registered under GST. |
COMPOSITION | Registered under the composition scheme. |
CONSUMER | End consumer (B2C). |
OVERSEAS | Located outside India; exports/imports. |
SEZ | Located in a Special Economic Zone. |
The ContactResponse object
{
"id": "f47ac10b-58cc-4372-a567-0e02b2c3d479",
"contactType": "CUSTOMER",
"displayName": "Sharma Traders",
"companyName": "Sharma Traders Pvt. Ltd.",
"firstName": "Rajesh",
"lastName": "Sharma",
"gstin": "27AAECS1234F1Z5",
"pan": "AAECS1234F",
"gstTreatment": "REGISTERED",
"placeOfSupply": "27",
"email": "[email protected]",
"phone": "+912026543210",
"mobile": "+919876543210",
"website": "https://sharmatraders.in",
"billingAddressLine1": "Shop 12, Laxmi Market",
"billingAddressLine2": "M.G. Road",
"billingCity": "Pune",
"billingState": "Maharashtra",
"billingStateCode": "27",
"billingPostalCode": "411001",
"billingCountry": "IN",
"shippingAddressLine1": "Warehouse 5, Hadapsar Industrial Estate",
"shippingAddressLine2": "",
"shippingCity": "Pune",
"shippingState": "Maharashtra",
"shippingStateCode": "27",
"shippingPostalCode": "411028",
"shippingCountry": "IN",
"paymentTermsDays": 30,
"creditLimit": 500000.00,
"openingBalance": 0.00,
"outstandingAr": 152250.00,
"outstandingAp": 0.00,
"salesHold": false,
"salesHoldReason": null,
"salesHoldUntil": null,
"tdsApplicable": false,
"tdsSection": null,
"tdsRate": null,
"bankName": "HDFC Bank",
"bankAccountNo": "50100123456789",
"bankIfsc": "HDFC0001234",
"upiId": "sharmatraders@hdfcbank",
"active": true,
"notes": "Wholesale customer since 2019. Preferred payment via NEFT.",
"createdAt": "2026-02-01T03:30:00Z",
"persons": [
{
"id": "c9bf9e57-1685-4c89-bafb-ff5af830be8a",
"salutation": "Mr.",
"firstName": "Rajesh",
"lastName": "Sharma",
"designation": "Managing Director",
"department": "Management",
"email": "[email protected]",
"phone": "+912026543210",
"mobile": "+919876543210",
"primary": true
},
{
"id": "a3e8f7c2-4d6b-4912-8e5a-1b2c3d4e5f6a",
"salutation": "Ms.",
"firstName": "Priya",
"lastName": "Sharma",
"designation": "Accounts Manager",
"department": "Finance",
"email": "[email protected]",
"phone": null,
"mobile": "+919823456789",
"primary": false
}
]
}List contacts
/api/v1/contactsReturns a paginated list of contacts. The response is wrapped in ApiResponse<Page<ContactResponse>>.
Query parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
type | string | -- | Filter by CUSTOMER, VENDOR, or BOTH. |
search | string | -- | Search by display name, company name, email, phone, or GSTIN. |
page | integer | 0 | Zero-based page number. |
size | integer | 20 | Number of results per page. |
sort | string | -- | Sort field and direction, e.g. displayName,asc. |
curl -X GET "https://erp.katasticho.com/api/v1/contacts?type=CUSTOMER&size=10&page=0" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Get a contact
/api/v1/contacts/{id}Retrieves a single contact by UUID. Returns ApiResponse<ContactResponse>.
curl -X GET "https://erp.katasticho.com/api/v1/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Create a contact
/api/v1/contactsCreates a new contact. Returns 201 Created with ApiResponse<ContactResponse>.
curl -X POST "https://erp.katasticho.com/api/v1/contacts" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"contactType": "CUSTOMER",
"displayName": "Gupta Electronics",
"companyName": "Gupta Electronics Pvt. Ltd.",
"firstName": "Amit",
"lastName": "Gupta",
"salutation": "Mr.",
"gstin": "07AABCG1234H1Z9",
"pan": "AABCG1234H",
"gstTreatment": "REGISTERED",
"placeOfSupply": "07",
"email": "[email protected]",
"phone": "+911141234567",
"mobile": "+919811234567",
"website": "https://guptaelectronics.co.in",
"billingAddressLine1": "45, Nehru Place",
"billingAddressLine2": "Near Lotus Temple",
"billingCity": "New Delhi",
"billingState": "Delhi",
"billingStateCode": "07",
"billingPostalCode": "110019",
"billingCountry": "IN",
"shippingAddressLine1": "45, Nehru Place",
"shippingAddressLine2": "Near Lotus Temple",
"shippingCity": "New Delhi",
"shippingState": "Delhi",
"shippingStateCode": "07",
"shippingPostalCode": "110019",
"shippingCountry": "IN",
"paymentTermsDays": 45,
"creditLimit": 1000000.00,
"openingBalance": 75000.00,
"defaultPriceListId": null,
"salesHold": false,
"salesHoldReason": null,
"salesHoldUntil": null,
"tdsApplicable": false,
"tdsSection": null,
"tdsRate": null,
"bankName": "ICICI Bank",
"bankAccountNo": "123456789012",
"bankIfsc": "ICIC0001234",
"upiId": "guptaelectronics@icici",
"notes": "Key distributor for consumer electronics in Delhi NCR."
}'CreateContactRequest fields
| Field | Type | Required | Description |
|---|---|---|---|
contactType | ContactType | Yes | CUSTOMER, VENDOR, or BOTH. |
displayName | String | Yes | Primary display name shown across the application. |
companyName | String | No | Legal company name. |
firstName | String | No | First name of the primary contact. |
lastName | String | No | Last name of the primary contact. |
salutation | String | No | E.g. Mr., Mrs., Ms., Dr. |
gstin | String | No | 15-character GSTIN (validated on server). |
pan | String | No | 10-character PAN. |
taxId | String | No | Tax identification number (for overseas contacts). |
gstTreatment | GstTreatment | No | GST treatment type. See enum above. |
placeOfSupply | String | No | 2-digit state code (e.g., "27" for Maharashtra). |
email | String | No | Primary email address. |
phone | String | No | Landline phone number. |
mobile | String | No | Mobile phone number. |
website | String | No | Website URL. |
billingAddressLine1 | String | No | Billing address line 1. |
billingAddressLine2 | String | No | Billing address line 2. |
billingCity | String | No | Billing city. |
billingState | String | No | Billing state name (e.g., "Maharashtra"). |
billingStateCode | String | No | 2-digit GST state code. |
billingPostalCode | String | No | Billing PIN code. |
billingCountry | String | No | ISO 3166-1 alpha-2 country code (e.g., "IN"). |
shippingAddress* | String | No | Same structure as billing address fields (Line1, Line2, City, State, StateCode, PostalCode, Country). |
paymentTermsDays | Integer | No | Default payment terms in days (e.g., 30). |
creditLimit | BigDecimal | No | Maximum credit limit in INR. |
openingBalance | BigDecimal | No | Opening balance when migrating from another system. |
defaultPriceListId | UUID | No | UUID of the default price list to apply for this contact. |
salesHold | Boolean | No | Whether sales are on hold for this contact. |
salesHoldReason | String | No | Reason for the sales hold. |
salesHoldUntil | LocalDate | No | Date until which the sales hold is active (YYYY-MM-DD). |
tdsApplicable | Boolean | No | Whether TDS is applicable (typically for vendors). |
tdsSection | String | No | TDS section code (e.g., "194C", "194J"). |
tdsRate | BigDecimal | No | TDS deduction rate as a percentage. |
bankName | String | No | Bank name for payments. |
bankAccountNo | String | No | Bank account number. |
bankIfsc | String | No | IFSC code of the bank branch. |
upiId | String | No | UPI virtual payment address. |
notes | String | No | Free-text internal notes. |
Update a contact
/api/v1/contacts/{id}Updates an existing contact. The request body uses the same CreateContactRequest schema. Returns ApiResponse<ContactResponse>.
curl -X PUT "https://erp.katasticho.com/api/v1/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"contactType": "CUSTOMER",
"displayName": "Sharma Traders",
"companyName": "Sharma Traders Pvt. Ltd.",
"firstName": "Rajesh",
"lastName": "Sharma",
"gstin": "27AAECS1234F1Z5",
"gstTreatment": "REGISTERED",
"placeOfSupply": "27",
"email": "[email protected]",
"mobile": "+919876543210",
"paymentTermsDays": 45,
"creditLimit": 750000.00,
"billingAddressLine1": "Shop 12, Laxmi Market",
"billingCity": "Pune",
"billingState": "Maharashtra",
"billingStateCode": "27",
"billingPostalCode": "411001",
"billingCountry": "IN"
}'Delete a contact
/api/v1/contacts/{id}Deletes a contact. Returns 204 No Content with no response body.
curl -X DELETE "https://erp.katasticho.com/api/v1/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Contact persons
Each contact can have multiple contact persons. Contact persons are individuals associated with the contact (e.g., an accounts manager, a procurement head). One person can be marked as primary.
Add a contact person
/api/v1/contacts/{id}/personsAdds a contact person to an existing contact. Returns 201 Created.
curl -X POST "https://erp.katasticho.com/api/v1/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479/persons" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..." \
-H "Content-Type: application/json" \
-d '{
"salutation": "Mr.",
"firstName": "Vikram",
"lastName": "Mehta",
"designation": "Purchase Manager",
"department": "Procurement",
"email": "[email protected]",
"phone": "+912026543211",
"mobile": "+919823012345",
"primary": false
}'ContactPersonRequest fields
| Field | Type | Required | Description |
|---|---|---|---|
salutation | String | No | E.g. Mr., Mrs., Ms., Dr. |
firstName | String | Yes | First name of the contact person. |
lastName | String | No | Last name of the contact person. |
designation | String | No | Job title or designation. |
department | String | No | Department within the organization. |
email | String | No | Email address of the contact person. |
phone | String | No | Landline phone number. |
mobile | String | No | Mobile phone number. |
primary | Boolean | No | Whether this is the primary contact person. |
Delete a contact person
/api/v1/contacts/{id}/persons/{personId}Removes a contact person from a contact. Returns 204 No Content with no response body.
curl -X DELETE "https://erp.katasticho.com/api/v1/contacts/f47ac10b-58cc-4372-a567-0e02b2c3d479/persons/c9bf9e57-1685-4c89-bafb-ff5af830be8a" \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIs..."Vendor example
Vendors use the same API. Set contactType to VENDOR and optionally configure TDS fields.
{
"contactType": "VENDOR",
"displayName": "Bharat Steel Suppliers",
"companyName": "Bharat Steel Suppliers LLP",
"firstName": "Suresh",
"lastName": "Patel",
"gstin": "24AABFB5678K1Z2",
"pan": "AABFB5678K",
"gstTreatment": "REGISTERED",
"placeOfSupply": "24",
"email": "[email protected]",
"mobile": "+919725012345",
"billingAddressLine1": "Plot 42, GIDC Industrial Estate",
"billingAddressLine2": "Phase II",
"billingCity": "Ahmedabad",
"billingState": "Gujarat",
"billingStateCode": "24",
"billingPostalCode": "382445",
"billingCountry": "IN",
"paymentTermsDays": 60,
"creditLimit": 2000000.00,
"openingBalance": 0.00,
"tdsApplicable": true,
"tdsSection": "194C",
"tdsRate": 2.00,
"bankName": "State Bank of India",
"bankAccountNo": "38765432109",
"bankIfsc": "SBIN0012345",
"upiId": "bharatsteel@sbi",
"notes": "Primary raw material supplier. MSME registered."
}Error responses
When validation fails or a resource is not found, the API returns an ApiResponse with success: false and the errors array populated.
{
"success": false,
"message": "Validation failed",
"data": null,
"errors": [
"contactType: must not be null",
"displayName: must not be blank"
]
}