When to use this module

  • Add or edit contacts → CRUD endpoints (POST /contact/create, PUT /contact/update)
  • Organize contacts with labels → tagging endpoints (PUT /contact/add-or-remove-tags)
  • Import contacts from spreadsheet → CSV import (POST /contact/import/upload)
  • Send WhatsApp messages → contacts provide recipient data (phone numbers)

All Endpoints

MethodRouteAuthDescription
POST/api/v1/Contact/create🔑 API KeyCreate a new contact
GET/api/v1/Contact/get/{id}🔑 API KeyGet contact by ID
POST/api/v1/Contact/getall🔑 API KeyPaginated contact list (filter, sort, tag filter)
PUT/api/v1/Contact/update🔑 API KeyUpdate contact + nested children (phones, emails, addresses)
DELETE/api/v1/Contact/delete🔑 API KeySoft-delete a single contact
DELETE/api/v1/Contact/bulkdelete🔑 API KeyBulk soft-delete by list of IDs
GET/api/v1/Contact/search🔑 API KeySearch contacts (mode: whatsapp filters by phone)
PUT/api/v1/Contact/add-or-remove-tags🔑 API KeyAdd/remove tags on one contact
PUT/api/v1/Contact/bulk-add-or-remove-tags🔑 API KeyBulk tag operations across multiple contacts
GET/api/v1/Contact/tags/search🔑 API KeySearch existing tag names in the firm
POST/api/v1/Contact/import/upload🔑 API KeyQueue CSV import job (returns 202 Accepted)
POST

/api/v1/Contact/create

Creates a new contact scoped to the current firm (authenticated via API Key). Accepts nested phone numbers, email addresses, and postal addresses in a single request.

Request Body

JSON
{
  "firstName": "John",
  "lastName": "Smith",
  "gender": "Male",
  "isActive": true,
  "profilePic": "https://url.to.pic/john.png",
  "phones": [
    { "phone": "9876543210", "phoneCC": "+91", "type": 1, "isPrimary": true }
  ],
  "emails": [
    { "email": "john@company.com", "type": 1, "isPrimary": true }
  ],
  "addresses": [
    {
      "type": 1,
      "line1": "123 Main St",
      "line2": "Suite 400",
      "landmark": "Near Central Park",
      "city": "Mumbai",
      "state": "Maharashtra",
      "country": "India",
      "pinCode": "400001"
    }
  ],
  "tags": ["VIP", "Lead"]
}

Request Parameters

FieldTypeRequiredDescription
firstNamestring(50)requiredContact's first name
lastNamestring(50)requiredContact's last name
genderstringoptionalMale / Female / Other
isActivebooloptionalDefaults to true
profilePicstringoptionalAzure Blob URL of profile picture
phonesarrayoptionalList of phone entries; only one can be isPrimary
emailsarrayoptionalList of email entries; only one can be isPrimary
addressesarrayoptionalList of postal addresses
tagsstring[]optionalList of free-form tags
POST

/api/v1/Contact/getall

Returns a paginated, filtered, and sortable list of contacts belonging to the current firm. Supports optional tag-based filtering to narrow results by label.

Request Body

JSON
{
  "page": 1,
  "pageSize": 20,
  "searchTerm": "",
  "sortBy": "firstName",
  "sortDesc": false,
  "tags": []
}

Request Parameters

FieldTypeDescription
pageint1-based page number
pageSizeintNumber of records per page (max 100)
searchTermstringFree-text search across name, email, phone
sortBystringField to sort by (e.g. firstName, lastName)
sortDescboolDescending sort when true
tagsstring[]Filter to contacts having ALL listed tags
DELETE

/api/v1/Contact/bulkdelete

Soft-deletes multiple contacts in a single request. Contacts are not permanently removed — they are marked as deleted and excluded from normal queries.

Request Body

JSON
{
  "ids": [
    "3fa85f64-5717-4562-b3fc-2c963f66afa6",
    "7cb2a123-1234-5678-abcd-ef9876543210"
  ]
}
Soft-delete is irreversible via the API. Deleted contacts are hidden from all listing and search endpoints but remain in the database for audit purposes.
PUT

/api/v1/Contact/add-or-remove-tags

Adds and/or removes tags on a single contact in one atomic operation. Tags are free-form strings — they are created on-the-fly if they don't already exist. Use /bulk-add-or-remove-tags for multi-contact tag operations.

Request Body

JSON
{
  "contactId": "guid-here",
  "tagsToAdd": ["VIP", "Lead"],
  "tagsToRemove": ["Prospect"]
}

Tag Search

Use GET /api/v1/Contact/tags/searchvi to autocomplete tag names from existing firm tags. Ideal for building tag-picker UIs.

Tags are case-insensitive and deduplicated per contact. A contact cannot have the same tag twice regardless of casing.
POST

/api/v1/Contact/import/upload

Queues an asynchronous CSV import job. The file must first be uploaded via the File Upload module to obtain a fileId. This endpoint publishes the job to a RabbitMQ queue and immediately returns HTTP 202 Accepted.

CSV Import Flow

Step 1 — Upload CSV User uploads CSV file via POST /api/v1/file/upload → Receives FileId (GUID) in response Step 2 — Trigger Import POST /api/v1/Contact/import/upload<FileId> → Service publishes message to RabbitMQ 'contact-import' queue Step 3 — Immediate Response (HTTP 202) { "isSuccess": true, "data": null, "message": "Import queued successfully" } Step 4 — Background Worker Processes Worker downloads CSV from Azure Blob Storage → Parses rows → Validates fields → Creates FirmContact + nested Phone/Email/Address records → Handles duplicates (skip or update by phone/email match) Step 5 — Completion Notification Worker pushes SignalR notification to frontend → UI receives real-time import summary (created / skipped / failed counts)

Response (HTTP 202)

JSON
{
  "isSuccess": true,
  "data": null,
  "message": "Import queued successfully"
}
Expected CSV columns: FirstName, LastName, PhoneNumber, PhoneCC, Email, City, Country. Additional columns are silently ignored.