Inquiries
A property inquiry is a lead with a memory. Beyond "who asked about what," it carries the buyer's intent (buying vs renting, budget range), the viewing they want and whether it happened, the follow-up owed and when, the agent assigned, and — if it lands — the transaction it converted into. Working that record through a defined status lifecycle turns scattered interest into a measurable pipeline across voice and chat.
The Python examples use the inquiry resource instantiated from the client (see the overview):
property_inquiry = client.property_inquiry
Create an inquiry
The TypeScript SDK can capture the contact inline; the Python SDK links to an existing customer_id.
- TypeScript
- Python
import { PropertyInquiryType, PreferredContactMethod } from 'wiil-js';
const inquiry = await client.propertyInquiries.create({
propertyId: 'prop_456',
customer: {
firstName: 'John',
lastName: 'Smith',
email: 'john.smith@example.com',
phone: '+1-555-123-4567',
preferredContactMethod: PreferredContactMethod.EMAIL,
},
inquiryType: PropertyInquiryType.GENERAL,
message: 'I am interested in scheduling a viewing for this property.',
source: 'website',
preferredViewingDate: Math.floor(Date.now() / 1000) + 3 * 24 * 60 * 60,
preferredViewingTime: '10:00 AM',
interestedInBuying: true,
budgetMin: 500000,
budgetMax: 800000,
});
from wiil.models.business_mgt import CreatePropertyInquiry
inquiry = property_inquiry.create(
CreatePropertyInquiry(
property_id="property_123",
customer_id="cust_456",
message="Is this property still available?",
)
)
Get by property
- TypeScript
- Python
const result = await client.propertyInquiries.getByProperty('prop_456', { page: 1, pageSize: 20 });
result.data.forEach(inq => console.log(`${inq.status} — ${inq.inquiryType}`));
from wiil.types import PaginationRequest
by_property = property_inquiry.get_by_property(
"property_123", PaginationRequest(page=1, page_size=20)
)
print(by_property.meta.total_count)
Update
Assign an agent, schedule a viewing, or record notes.
- TypeScript
- Python
const updated = await client.propertyInquiries.update({
id: 'inq_123',
assignedAgentId: 'agent_456',
scheduledViewingDate: Math.floor(Date.now() / 1000) + 2 * 24 * 60 * 60,
notes: 'Client prefers morning viewings',
});
from wiil.models.business_mgt import UpdatePropertyInquiry
updated = property_inquiry.update(
UpdatePropertyInquiry(id="inq_123", notes="Customer requested weekend viewing")
)
Update status
Advance the lead through its lifecycle. The TypeScript status update can carry viewing and follow-up data alongside the new status.
- TypeScript
- Python
import { PropertyInquiryStatus } from 'wiil-js';
const scheduled = await client.propertyInquiries.updateStatus('inq_123', {
id: 'inq_123',
status: PropertyInquiryStatus.VIEWING_SCHEDULED,
scheduledViewingDate: Math.floor(Date.now() / 1000) + 2 * 24 * 60 * 60,
});
const converted = await client.propertyInquiries.updateStatus('inq_123', {
id: 'inq_123',
status: PropertyInquiryStatus.CONVERTED,
});
status_updated = property_inquiry.update_status(inquiry.id, "in_progress")
print(status_updated.status)
Viewing slots
Query a property's available viewing slots for a date, then schedule a viewing using the slot's UTC timestamp and assigned agent. Slot times are in UTC seconds — pass startTimeUtcSec straight into the API; only multiply by 1000 when building a JavaScript Date for display.
- TypeScript
- Python
import { PropertyInquiryType, PropertyInquiryStatus } from 'wiil-js';
const slots = await client.propertyInquiries.getViewingSlots('prop_123', '2026-06-25');
console.log(slots.timezone, slots.localDate);
if (slots.slots.length > 0) {
const slot = slots.slots[0]; // startTimeOfDay, providerId, startTimeUtcSec
const inquiry = await client.propertyInquiries.create({
propertyId: 'prop_123',
customerId: 'cust_456',
inquiryType: PropertyInquiryType.GENERAL,
message: "I'd like to schedule a viewing",
scheduledViewingDate: slot.startTimeUtcSec,
assignedAgentId: slot.providerId,
});
await client.propertyInquiries.updateStatus(inquiry.id, {
id: inquiry.id,
status: PropertyInquiryStatus.VIEWING_SCHEDULED,
scheduledViewingDate: slot.startTimeUtcSec,
});
}
from wiil.models.business_mgt import CreatePropertyInquiry, UpdatePropertyInquiryStatus
from wiil.models.type_definitions import PropertyInquiryType, PropertyInquiryStatus
slots = property_inquiry.get_viewing_slots(property_id="property_123", local_date="2026-06-25")
print(slots.timezone, slots.local_date)
if slots.slots:
slot = slots.slots[0] # start_time_of_day, provider_id, start_time_utc_sec
inquiry = property_inquiry.create(
CreatePropertyInquiry(
property_id="property_123",
customer_id="cust_456",
inquiry_type=PropertyInquiryType.GENERAL,
message="I'd like to schedule a viewing",
scheduled_viewing_date=slot.start_time_utc_sec,
assigned_agent_id=slot.provider_id,
)
)
property_inquiry.update_status(
inquiry.id,
UpdatePropertyInquiryStatus(
id=inquiry.id,
status=PropertyInquiryStatus.VIEWING_SCHEDULED,
scheduled_viewing_date=slot.start_time_utc_sec,
),
)
Each slot carries startTimeOfDay (display time), providerId (the agent), and startTimeUtcSec (the canonical UTC-seconds start); the response also includes the timezone and the queried localDate.
Get, get by customer, list, delete
Reading a single inquiry, fetching a customer's inquiries, listing, and deletion are exposed through the TypeScript SDK.
const inquiry = await client.propertyInquiries.get('inq_123');
const byCustomer = await client.propertyInquiries.getByCustomer('cust_123', { page: 1, pageSize: 20 });
const all = await client.propertyInquiries.list({ page: 1, pageSize: 20 });
await client.propertyInquiries.delete('inq_123');
Converting a lead
When a deal closes, record the transaction on the inquiry and move it to CONVERTED:
await client.propertyInquiries.update({
id: 'inq_123',
convertedToTransaction: true,
transactionId: 'txn_789',
transactionType: 'purchase',
});
await client.propertyInquiries.updateStatus('inq_123', {
id: 'inq_123',
status: PropertyInquiryStatus.CONVERTED,
});
PropertyInquiry fields
| Field | Type | Required | Description |
|---|---|---|---|
id | string | auto | Unique identifier |
propertyId | string | Yes | Property being inquired about |
customerId | string | null | No | Linked customer |
inquiryType | enum | Yes | general, viewing, offer, information |
message | string | null | No | Message from the contact |
source | string | Yes | Lead source (default direct) |
status | enum | Yes | Lifecycle status (default NEW) |
preferredViewingDate / preferredViewingTime | — | No | Requested viewing |
scheduledViewingDate | number | null | No | Confirmed viewing date |
viewingCompleted | boolean | Yes | Whether the viewing happened (default false) |
viewingNotes | string | null | No | Notes from the viewing |
followUpDate / followUpNotes | — | No | Next follow-up |
assignedAgentId | string | null | No | Assigned agent |
interestedInBuying / interestedInRenting | boolean | Yes | Buyer intent (default false) |
budgetMin / budgetMax | number | null | No | Budget range for qualification |
convertedToTransaction | boolean | Yes | Whether it converted (default false) |
transactionId / transactionType | — | No | Resulting transaction (purchase, lease) |
appointmentRecordId | string | null | No | Linked appointment record |
cancelReason / notes | string | null | No | Cancellation reason and internal notes |
Status & type enums
| Enum | Values |
|---|---|
PropertyInquiryType | general, viewing, offer, information |
PropertyInquiryStatus | NEW, CONTACTED, VIEWING_SCHEDULED, VIEWING_COMPLETED, NEGOTIATING, CONVERTED, CLOSED |
Query options
PropertyInquiry queries filter by search, propertyId, customerId, status[], inquiryType, assignedAgentId, source, convertedToTransaction, interestedInBuying, interestedInRenting, viewingCompleted, dateRange, and followUpDateRange, sorted by createdAt, scheduledViewingDate, followUpDate, or status (asc / desc).
Assign an agent promptly, capture budgetMin/budgetMax for qualification, and record viewing feedback in viewingNotes — a clear NEW → CONVERTED path gives a measurable pipeline.