listings:read ability. The clients’ details also need leads:read.
What the agenda holds
A key’s agenda is its account’s agenda in the portal:- the account’s active listings;
- the listings whose viewings a colleague gave to it;
- for the owner, the admins and the managers, the team’s listings (a manager sees their team);
- for a developer’s consultant, the projects they work on, and there only the clients who came to them and the open days.
Reading the agenda
GET /account/viewings returns the hours of a range, one page at a time, in order of time:
meta.pending_requests counts every request waiting for your answer in the agenda, not only those in the range. A request you answered with another time waits for the client and is not counted, as in the portal. meta.next_at is the next viewing or request.
GET /viewings/{id} returns one hour, in the same shape. An hour outside the agenda answers 404.
The states
available: a free hour.pending: a request waiting for your answer, untilrequest_expires_at.booked: a booked viewing that has not passed.completed: a booked viewing whose hour has ended. The state is worked out when you read it: a viewing becomescompletedas soon as its hour ends.
completed appears only here and in GET /viewings/{id}. A listing’s agenda (GET /account/listings/{code}/viewings) shows only the hours that have not passed, with the states available, pending and booked.
The client and their details
visitor and outcome_note come only to a key with the leads:read ability. For other keys they are null, while outcome and outcome_at stay.
account: true: the client has a Housera account, with a name, an email and a phone.account: false: a client without an account, added by hand. They have a name and, if you entered it, a phone, but no email. A listing’s agenda does not name them (visitor: null).
visitor is then null. The note from “How did it go?” is erased after 24 months.
Free hours
source:schedulefor the hours generated by the weekly schedule,manualfor those put in by hand.held: the hour is kept for a short while for someone signing in to book it.bookable: whether a client can book the hour now. It isfalsewhen the hour is too close (the notice), when whoever runs the viewings is busy at the same time at another listing (with the break between viewings), or when the hour is kept. On hours that are not free it isnull.
Developers’ projects
On a project with several consultants, each hour has one row per consultant, with the samestarts_at and a different seat. The rows are not duplicates: they are the hour’s places. Once booked, agent is the consultant who meets the client, and place says where: office (the sales office), show_flat (the show flat) or unit (a finished flat, with place_rooms rooms). Elsewhere, agent is whoever runs the listing’s viewings. agent.email goes to the keys of the holder, the admins and the manager who has that person on their team, and to the person’s own key; any other key gets null, as on the Team page in the portal.
A listing’s agenda
GET /account/listings/{code}/viewings gets the same new fields on each hour (source, duration_min, held, bookable, booked_at, proposed_starts_at, attendance_confirmed_at, reminded_day_at, reminded_soon_at, outcome, outcome_at, agent, place, place_rooms, seat), plus timezone and schedule_mode on the listing.
The client who called
POST /listings/{code}/viewings/clients puts in the agenda a client without an account with whom you agreed a time on the phone, as „Adaugă în agendă” does in the portal. It needs listings:write, leads:read and leads:write, since it adds a contact.
starts_atis read as for published times: without a time zone, on the clock of the listing’s place.duration_minis 15, 30, 45, 60 or 90.namehas at most 120 characters, andphoneis optional.- The time is booked at once, under the same overlap rules as a time published on the listing. The free times under it go.
- The client lands in the contacts with the source
other. With a phone, the contact moves to the Viewing stage. - The answer is
201, with the time (visitorwithaccount: false). - With the
Idempotency-Keyheader, the same request again within 10 minutes adds nothing and returns the time added the first time, as it is now, with200. The same key with another body is refused on/idempotency_key. Without a key, a second request for the same time gets409 listing_action_refused, since the time is no longer free. - A time that overlaps another viewing or an open house, one in the past or one that does not exist at a clock change is refused on
/starts_at.
PATCH /viewings/{id}.
Another hour for a client with an account
POST /viewings/{id}/proposal with {"starts_at": "2026-11-15T10:00"} proposes another time to the client. The viewing keeps its time until they answer, and the answer now has proposed_starts_at. The client gets the message as from the portal. When they accept, starts_at becomes the proposed time and proposed_starts_at is null again.
An open house, a viewing without a client with an account and one that is over get 409 listing_action_refused. A time that overlaps another, or at which whoever runs the viewings is not free (with the break between viewings, at all their listings), is refused on /starts_at.
Cancelling with a note
POST /viewings/{id}/cancel optionally takes note, at most 300 characters, which goes into the message to the client with an account (a client added by hand gets no messages from Housera). note is optional.
“How did it go?”
PUT /viewings/{id}/outcome says what came of a viewing that took place:
outcomeisoffer(wants to make an offer),again(comes back),not_interestedorno_show.notehas at most 500 characters.- The answer can be changed at any time, and a new request without
noteclears the note. - On
offer, the client’s contact on the listing moves to the Offer stage, if it had not gone that far. The answer hasmeta.lead_moved_to_offer. - It needs
listings:writeandleads:write, since it moves a contact between stages. - A viewing that has not taken place yet gets
409 listing_action_refused.
The line of viewings in “My listings”
GET /account/listings?include=viewings adds the viewings field to each listing:
next_at and next_kind are the next appointment (a viewing or an open house), more how many follow it, bookable whether it has free hours to book, on_request whether it is “On request”. Without include, the answer doesn’t have these fields, and the listing’s etag does not change.
GET /account/listings?viewings=none returns only the active listings with no schedule: no free hours, nothing scheduled, and not “On request”.
What the CRM learns without asking
From the day we announce to you, every change to a viewing also goes out as an event, the same from the portal and from the API. That way you also learn what a colleague did in the portal, without reading the agenda every minute.
The events carry
slot_id and the time, with no client details. With slot_id you read the viewing through GET /viewings/{id}, and only a key with leads:read sees the client’s name and phone.
When a client with an account moves their own viewing to another free time, you get viewing.cancelled and then viewing.booked, with a new id.
When the listing comes off the market (you pause it, mark it sold or withdraw it, or it is rejected), its upcoming viewings are released without an event for each one. You learn it from the listing’s event, for example listing.paused or listing.sold, and clients with an account hear it from Housera.
viewing.completed can arrive up to an hour late. The state in GET /account/viewings is completed as soon as the time is over: if you need it right away, read it.
The full list, with each event’s fields and who receives it, is in Webhooks.