Property Activity & Viewings
Register and manage own-listing viewings, and read the merged property activity feed.
The property-activity API manages viewings and returns a merged chronological feed for a Fondaro listing owned by the caller's organization. These routes require a Clerk session JWT and active organization. They do not accept a Fondaro property API key.
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_IDAll listing and viewing identifiers are UUIDs. A listing outside the active organization is returned as 404, the same as a missing listing.
Route catalogue
| Method | Route | Purpose |
|---|---|---|
GET | /properties/:id/viewings | List registered viewings for one own listing |
POST | /properties/:id/viewings | Register a viewing |
PATCH | /viewings/:viewingId | Change a viewing |
DELETE | /viewings/:viewingId | Delete a viewing |
GET | /properties/:id/activity | Read viewings, listing changes, deal events, and brochure links as one feed |
Any member of the owning organization can read the routes and register a viewing. A non-admin can edit or delete only a viewing whose createdBy is their Clerk user id; an organization admin can change any viewing in the organization.
Viewing object
{
"id": "67444de5-bfa4-4aa4-87c3-a1b2f1a4af59",
"organizationId": "69e9323f-e150-4317-9a8b-e952d0704fc4",
"propertyListingId": "29a1e184-237a-40c8-a1fe-624b0bcbb2f4",
"leadId": 4312,
"collaboratorLeadId": 8821,
"agentUserId": "user_2abc123",
"dealId": "5a149be6-e22f-4633-8f13-e8ddb169cd4d",
"viewingAt": "2026-07-28T09:30:00.000Z",
"kind": "in_person",
"status": "scheduled",
"notes": "Meet at reception.",
"source": "user",
"createdBy": "user_2abc123",
"createdAt": "2026-07-23T14:12:09.000Z",
"updatedAt": "2026-07-23T14:12:09.000Z"
}Closed vocabularies:
kind:in_personorvirtualstatus:scheduled,completed,cancelled, orno_showsource:user,mcp,import,n8n, orsystem; HTTP creation always writesuser
The client, collaborator, hosting member, and deal links are nullable. Deleting a linked lead or deal clears that link without deleting the viewing.
List viewings
GET /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/viewings?limit=20&offset=0
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID| Query | Type | Default | Constraints |
|---|---|---|---|
limit | integer | 20 | 1–100 |
offset | integer | 0 | 0 or greater |
The response is newest first by viewingAt:
{
"viewings": [],
"total": 0,
"hasMore": false
}This flat list returns viewing rows only. Use the Activity endpoint when you need client and collaborator name labels or the listing's other event types.
Register a viewing
POST /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/viewings
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID
Content-Type: application/json{
"viewingAt": "2026-07-28T09:30:00.000Z",
"kind": "in_person",
"leadId": 4312,
"collaboratorLeadId": 8821,
"agentUserId": "user_2abc123",
"dealId": "5a149be6-e22f-4633-8f13-e8ddb169cd4d",
"notes": "Meet at reception."
}| Field | Type | Required | Rules |
|---|---|---|---|
viewingAt | ISO 8601 string | Yes | Date and time of the viewing |
kind | string | Yes | in_person or virtual |
status | string | No | Omit to derive it from viewingAt |
leadId | integer or null | No | Client CRM lead |
collaboratorLeadId | integer or null | No | Referring external-agent lead |
agentUserId | string or null | No | Hosting Clerk user id, maximum 255 characters; omission defaults to the caller |
dealId | UUID or null | No | Optional deal in the organization |
notes | string or null | No | Maximum 5,000 characters |
When status is omitted, a time at or before the request time becomes completed; a future time becomes scheduled.
If a lead id is supplied, it must identify a purchased CRM lead with a CRM status in the active organization. A member must already be assigned to that lead; an organization admin may attach any eligible lead in the organization. The same visibility rule is applied to collaboratorLeadId. Attaching a lead does not grant CRM access. The dashboard filters the collaborator picker to collaborator-type leads; callers should preserve that convention.
The response is the created viewing object.
Update a viewing
PATCH /viewings/:viewingId accepts the same fields as create, all optional. An omitted key remains unchanged. Explicit null clears leadId, collaboratorLeadId, agentUserId, dealId, or notes.
{
"status": "completed",
"notes": "Client requested a second visit."
}Changing viewingAt does not re-derive the status on update. Send the intended status in the same patch when moving a viewing across past/future boundaries.
Delete a viewing
DELETE /viewings/67444de5-bfa4-4aa4-87c3-a1b2f1a4af59
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID{
"success": true
}Read property activity
GET /properties/29a1e184-237a-40c8-a1fe-624b0bcbb2f4/activity?types=viewing,deal&limit=20&offset=0
Authorization: Bearer CLERK_SESSION_JWT
x-organization-id: ORGANIZATION_ID| Query | Type | Default | Description |
|---|---|---|---|
types | string or repeated string[] | all | viewing, change, deal, and/or brochure; comma-separated and repeated forms are both accepted |
limit | integer | 20 | 1–100 |
offset | integer | 0 | 0 or greater |
The response merges four data sources, sorts them newest first, then applies the requested page:
{
"entries": [
{
"type": "viewing",
"date": "2026-07-28T09:30:00.000Z",
"viewing": {
"id": "67444de5-bfa4-4aa4-87c3-a1b2f1a4af59",
"propertyListingId": "29a1e184-237a-40c8-a1fe-624b0bcbb2f4",
"leadId": 4312,
"collaboratorLeadId": 8821,
"viewingAt": "2026-07-28T09:30:00.000Z",
"kind": "in_person",
"status": "scheduled"
},
"lead": { "id": 4312, "firstName": "Alex", "lastName": "Morgan" },
"collaborator": { "id": 8821, "firstName": "Sam", "lastName": "Lee" }
}
],
"total": 1,
"hasMore": false
}Entry type values are finer-grained than the filter:
viewing, withviewingand nullablelead/collaboratorname labels;change, with a server-writtenchangeevent and field-levelchanges;deal-stage-change,deal-won, ordeal-lost, each selected by thedealfilter; andbrochure, withbrochureId,slug, title, listing reference, and creation time.
total is the number of merged entries loaded for the requested window and can be a lower bound when a source has more history than the per-source cap. Use hasMore and advance offset rather than relying on total as an exact all-time count.
Common errors
| Status | Condition |
|---|---|
400 | Invalid UUID, query value, enum value, date, or field constraint |
403 | A member tries to attach a lead they cannot access, or change another member's viewing |
404 | Listing, viewing, eligible lead, or deal is unavailable in the active organization |
Related Articles
Viewings & Collaborators
Register property viewings, record the external agent who sent a client, and keep the property and CRM timelines connected.
Own-Listing Lifecycle
Understand creation, editing, terminal statuses, soft deletion, import provenance, and server-written listing history.
Authentication
How to create, use, and revoke Fondaro API keys for programmatic access.