> ## Documentation Index
> Fetch the complete documentation index at: https://api.housera.ro/llms.txt
> Use this file to discover all available pages before exploring further.

# Open house

> Cum publici o zi de vizită cu notă, înscriere și locuri, cum îi anunți pe cei care au salvat anunțul și cum lucrezi cu foaia de prezență.

Într-o zi de vizită (open house), oamenii vin la anunț fără o oră anume. Prin API o publici, o modifici, îi anunți pe cei care au salvat anunțul și citești foaia de prezență. Regulile sunt cele de pe pagina Open house din contul tău de pe Housera.

## Publicarea

`POST /listings/{code}/open-house` publică una sau mai multe ferestre, cel mult 60 într-o cerere, doar pe un anunț activ. Fiecare fereastră are `starts_at` și `ends_at` și poate avea în plus:

* `note`: ce le spui vizitatorilor, de exemplu unde sună la interfon. Cel mult 500 de caractere. Pe anunțul unei firme, nota apare pe pagina anunțului. Pe anunțul unei persoane fizice, o văd doar cei care au spus că vin.
* `rsvp`: dacă oamenii pot spune că vin. Implicit `true`. Pe anunțul unei persoane fizice e mereu `true`.
* `capacity`: numărul de locuri al zilei de vizită a unui proiect de dezvoltator, de la 1 la 500. Vezi [Ziua de vizită a unui proiect](#ziua-de-vizita-a-unui-proiect).
* `notify_savers`: `true` îi anunță pe loc pe cei care au salvat anunțul, ca `POST /viewings/{id}/open-house/announce`.

```json theme={null}
{ "windows": [
  { "starts_at": "2026-11-15T10:00", "ends_at": "2026-11-15T13:00",
    "note": "Sunați la interfon, apartamentul 12.", "rsvp": true, "notify_savers": true }
] }
```

O oră fără fus se citește pe ceasul locului anunțului. O fereastră nu se suprapune cu alta, nici cu o oră de vizionare. Dacă o fereastră din cerere e refuzată (suprapunere, oră din trecut), nu se publică niciuna. Un corp fără câmpurile noi publică exact ce publica în 1.1.0.

Răspunsul conține agenda anunțului și `warnings[]`, ca la scrierea unui anunț. `capacity` trimis pe un anunț care nu e proiect se ignoră, cu avertismentul `capacity_not_applicable`.

## Ziua de vizită a unui proiect

Pe un proiect de dezvoltator care nu e finalizat (stadiul Lansare, În construcție sau fără stadiu), pe șantier se intră doar într-o zi de vizită cu locuri. Fiecare fereastră a unui astfel de proiect are nevoie de `capacity`. Înscrierea e obligatorie (`rsvp` devine `true`).

Regula se aplică în API din ziua pe care ți-o anunțăm. Până atunci, o fereastră fără `capacity` se publică în continuare, iar răspunsul are antetul `Deprecation` cu ziua (de forma `@1767225600`), antetul `Link` spre această secțiune și avertismentul `site_visit_required_soon` pe `/windows/{i}/capacity`, cu ziua în `detail`. Din acea zi, o astfel de fereastră primește `422 site_visit_required` pe `/windows/{i}/capacity` și nu se publică nimic din cerere.

Un proiect Finalizat sau Mixt are vizionări la apartamente și open house fără locuri, ca orice anunț.

## Modificarea unei ferestre

`PATCH /viewings/{id}/open-house` schimbă `starts_at`, `ends_at`, `note`, `rsvp` sau `capacity`. Ce nu trimiți rămâne cum e, iar `note: null` șterge nota. Orele se mută după aceleași reguli ca la publicare. Ziua de vizită a unui proiect își păstrează locurile: le poți schimba, dar `capacity: null` primește `422 site_visit_required`. Răspunsul e fereastra, ca oră din agendă, plus `warnings[]`.

`PATCH /viewings/{id}` mută în continuare doar orele, ca în 1.1.0.

## Anunțarea celor care au salvat anunțul

`POST /viewings/{id}/open-house/announce` le spune celor care au salvat anunțul că ai un open house. Răspunsul spune în `told` câți oameni au fost anunțați.

```json theme={null}
{ "data": { "told": 37, "already_announced": false } }
```

O fereastră se anunță o singură dată. A doua cerere, a ta sau a unui coleg, răspunde `told: 0` și `already_announced: true`. O fereastră încheiată nu se mai anunță: `told: 0`, fără eroare. Poți trimite cel mult 10 cereri pe minut, pe lângă bugetul de scrieri al contului.

## Starea ferestrei

Fiecare oră din agendă are câmpul `open_house`, `null` la o vizionare. La o fereastră de open house:

```json theme={null}
"open_house": { "note": "Sunați la interfon, apartamentul 12.", "rsvp": true, "capacity": null,
                "going": 11, "arrived": 4, "savers_notified": false, "savers_to_notify": 37, "running": false }
```

* `going`: câți oameni au spus că vin; `arrived`: câți au fost marcați ca veniți.
* `savers_notified`: dacă ai anunțat deja fereastra. `savers_to_notify` spune câți oameni ar primi anunțul acum și e `null` după anunțare.
* `running`: `true` cât timp fereastra e în desfășurare.

Numerele nu sunt date personale, așa că le citește orice cheie cu `listings:read`. Agenda arată doar ferestrele care n-au trecut. Ferestrele nu se șterg; doar rândurile foii de prezență se șterg, la 90 de zile după open house.

## Foaia de prezență

Foaia de prezență spune cine a anunțat că vine și cine a venit. Rândurile sunt persoane, așa că citirea cere `listings:read` și `leads:read`, iar schimbările cer `listings:write`, `leads:read` și `leads:write`.

`GET /viewings/{id}/attendees` dă rândurile ferestrei, cele mai recente întâi (după venire, apoi după anunțare), cu `cursor` și `per_page` (cel mult 100):

```json theme={null}
{ "data": [ {
    "id": 5521, "name": "Ana Popescu", "phone": "+40740123456", "source": "rsvp", "account": true,
    "rsvp_at": "2026-11-13T18:20:00+00:00", "arrived_at": null, "interested": false,
    "consent": false, "consent_at": null, "consent_version": null
  } ],
  "meta": { "going": 11, "arrived": 4, "private": false,
            "checkin": { "url": "https://housera.ro/prezenta-open-house/Ab3…", "opens_at": "2026-11-15T07:00:00+00:00", "closes_at": "2026-11-15T12:00:00+00:00", "open": false } } }
```

* `source` spune de unde vine rândul: `rsvp` (a anunțat de pe pagina anunțului că vine), `checkin` (a semnat la ușă) sau `manual` (l-ai adăugat tu). La `rsvp`, `name` e numele contului; la `checkin`, ce a scris omul.
* `phone` e ce păstrează foaia: telefonul contului la `rsvp`, telefonul scris la ușă doar dacă omul a fost de acord să fie contactat (`consent: true`) și ce ai scris tu la `manual`. `consent_version` e versiunea textului de informare pe care l-a acceptat.
* `meta.checkin.url` e linkul foii de la ușă, din care îți faci codul QR. Foaia primește semnături de la o oră înainte de fereastră până la o oră după ea (`opens_at`, `closes_at`), iar `open` spune dacă le primește acum. Afișul de printat rămâne în portal.
* Pe anunțul unei persoane fizice, lista arată cine a spus că vine, iar `checkin` e `null`: open house-ul unei persoane fizice nu are foaie la ușă.
* Rândurile se șterg la 90 de zile după open house. După aceea lista e goală.

`POST /viewings/{id}/attendees` adaugă pe cineva care a venit, cu `name` (cel mult 120 de caractere) și, opțional, `phone`. Telefonul se scrie în format internațional, ca în portal. Rândul e marcat venit pe loc, iar omul intră în contactele tale; dacă are telefon, contactul trece în etapa Vizionare. Răspunsul e `201` cu rândul. Cu antetul `Idempotency-Key`, aceeași cerere trimisă din nou în 10 minute, cu aceeași cheie API, întoarce același rând cu `200` și nu mai adaugă nimic. Aceeași cheie cu alt `name` sau `phone` e refuzată pe `/idempotency_key`.

Pe un rând (`/open-house-attendees/{id}`):

* `POST …/arrived` îl marchează venit, iar contactul trece în etapa Vizionare. Pe un rând deja venit răspunde `200` fără alt efect.

Adăugarea și „A venit” primesc `409 listing_action_refused`, cu motivul în `detail`, când foaia nu le primește acum, de exemplu în afara ferestrei open house-ului, ca în portal.

* `PATCH` cu `{ "interested": true }` sau `false` spune dacă omul e interesat.
* `DELETE …/consent` retrage acordul de contact, la cererea omului: telefonul pleacă din rând, numele rămâne.
* `DELETE` șterge rândul, de exemplu la cererea omului sau pentru un rând greșit. Răspunsul e `204`. Contactul din cereri nu se șterge odată cu rândul: dacă omul îți cere asta, îl ștergi și de acolo, cu `DELETE /leads/{id}`.

Un rând sau o fereastră pe care cheia nu le atinge primesc `404`, ca unele care nu există. Ce se întâmplă pe foaie, din portal, de la vizitator sau prin API, afli prin evenimentele `open_house.attendee_added`, `open_house.attendee_arrived` și `open_house.attendee_removed`. Un webhook abonat la `lead.created` le primește și pe ele. Vezi [Webhook-urile](https://api.housera.ro/ro/webhooks.md).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.