> ## 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.

# Programul săptămânal

> Cum se formează orele de vizionare din programul tău: programul de bază, programul fiecărui anunț și aplicarea lui pe mai multe anunțuri.

Orele pe care clienții le rezervă vin, de obicei, dintr-un program: zilele și orele în care faci vizionări, durata uneia, pauza dintre ele, cu cât timp înainte se poate rezerva și pe câte zile înainte. Prin API citești și schimbi programul la fel ca în pagina „Programul meu” din cont. Citirea cere dreptul `listings:read`, iar schimbările cer `listings:write` și consumă bugetul de tranziții al contului (60 pe minut).

## Cum se formează orele

Fiecare anunț își ia orele într-unul din trei moduri:

* `inherit`: urmează programul de bază al celui care face vizionările anunțului. E modul unui anunț la care n-ai schimbat nimic.
* `own`: are orele lui, pe zile.
* `on_request`: nu are ore. Clienții cer o zi prin mesaj.

Din program, Housera generează orele libere pe orizontul ales (7, 14, 21 sau 28 de zile) și le prelungește pe măsură ce trec zilele. Orele noi apar la scurt timp după ce salvezi programul. Programul doar adaugă și retrage ore libere generate de el: orele publicate de mână, rezervările, cererile și zilele de vizită liberă rămân cum sunt. O oră generată pe care ai retras-o sau ai mutat-o de mână nu se mai creează la loc.

Ordinea regulilor, de la cea care câștigă: zilele libere și ziua de la care se poate vizita scot zile întregi, preavizul închide orele prea apropiate de acum, iar durata plus pauza împart fiecare interval în ore. Orele se citesc pe ceasul locului fiecărui anunț.

O zi are o listă de intervale `{from, to}`, cel mult 6, pe un pas de 15 minute (`09:00`, `09:15`…), fără suprapuneri. `24:00` e acceptat ca sfârșit de zi. O zi lipsă e o zi fără vizionări.

## Programul tău de bază

`GET /account/viewing-schedule`:

```json theme={null}
{ "data": {
  "saved": true,
  "hours": { "mon": [ { "from": "09:00", "to": "12:00" }, { "from": "14:00", "to": "18:00" } ], "sat": [ { "from": "10:00", "to": "13:00" } ] },
  "duration_min": 30, "buffer_min": null, "notice_min": 120, "horizon_days": 21,
  "confirmation": "manual",
  "blocked_dates": [ { "from": "2026-12-24", "to": "2026-12-26" } ],
  "effective": { "duration_min": 30, "buffer_min": 15, "notice_min": 120, "horizon_days": 21 },
  "options": { "duration_min": [15, 30, 45, 60, 90], "buffer_min": [0, 15, 30], "notice_min": [0, 60, 120, 240, 1440, 2880], "horizon_days": [7, 14, 21, 28] },
  "listings_following": 42
} }
```

* `saved` e `false` cât timp n-ai salvat programul. Atunci `effective` arată valorile de la care pornește.
* Un câmp `null` înseamnă că n-ai ales nimic. Valoarea aplicată e în `effective`.
* `confirmation` e setarea contului tău pentru toate anunțurile care n-au o alegere a lor: `auto` confirmă rezervările pe loc, `manual` le lasă să aștepte răspunsul tău.
* `listings_following` numără anunțurile publice ale căror vizionări le faci tu și care urmează programul de bază.

`PATCH /account/viewing-schedule` schimbă doar câmpurile trimise:

```bash theme={null}
curl -X PATCH https://housera.ro/api/v1/account/viewing-schedule \
  -H "Authorization: Bearer $HOUSERA_KEY" -H "Content-Type: application/json" \
  -d '{ "hours": { "tue": [ { "from": "17:00", "to": "20:00" } ] }, "notice_min": 240, "confirmation": "auto", "confirm_pending": true }'
```

* Un câmp lipsă rămâne cum era, iar `null` readuce valoarea implicită. `confirmation` primește doar `auto` sau `manual`.
* `hours`, când îl trimiți, înlocuiește toată săptămâna.
* `blocked_dates` are cel mult 50 de intervale. Un interval cu o singură zi poate lipsi de `to`.
* Cu `confirm_pending: true`, când setarea contului e `auto` (trimisă acum sau salvată deja), se confirmă și cererile care așteaptă la anunțurile tale care urmează setarea contului, cel mult 100 odată, iar fiecare client primește confirmarea. Răspunsul spune câte s-au confirmat și câte mai așteaptă: `"confirmed_pending": { "confirmed": 12, "still_waiting": 0 }`.
* Răspunsul are aceeași formă ca la `GET` și nu așteaptă generarea orelor.
* Programul de bază e al contului: îl urmează anunțurile ale căror vizionări le faci, din orice firmă în care lucrezi. Cererile confirmate cu `confirm_pending` și numerele din răspuns țin doar de firma cheii și de anunțurile tale fără firmă.

## Programul unui anunț

`GET /account/listings/{code}/viewing-schedule`:

```json theme={null}
{ "data": {
  "code": "HEWPUTA8", "mode": "own", "timezone": "Europe/Bucharest",
  "hours": { "tue": [ { "from": "17:00", "to": "20:00" } ] },
  "duration_min": 45, "notice_min": null, "available_from": "2026-12-01",
  "confirmation": null,
  "runner": { "name": "Maria Popa", "email": "maria@exemplu.ro" },
  "blocked_dates": [],
  "occupant": { "notify": true, "phone": "+40740123456" },
  "effective": { "hours": { "tue": [ { "from": "17:00", "to": "20:00" } ] }, "duration_min": 45, "buffer_min": 15, "notice_min": 120, "horizon_days": 21, "confirmation": "auto", "blocked_dates": [] },
  "base_saved": true, "pending_requests": 3
} }
```

* `hours` sunt orele proprii ale anunțului. Rămân păstrate și când anunțul urmează alt mod, ca să le regăsești la întoarcere.
* `duration_min`, `notice_min` și `confirmation` cu `null` înseamnă „ca de obicei”: programul de bază al celui care face vizionările, respectiv setarea titularului.
* `runner` e cel care face vizionările: un coleg căruia i le-ai dat sau, altfel, titularul. Emailul lui îl primesc cheile titularului, ale administratorilor și ale managerului care îl are în echipă, plus cheia lui; celelalte primesc `email: null`, ca pe pagina Echipa din portal.
* `occupant.phone` e telefonul unei persoane, așa că îl primește doar o cheie cu `leads:read`. Altfel e `null`.
* `effective` e ce generează orele acum și e doar de citit. Pauza și orizontul vin mereu din programul de bază al celui care face vizionările.
* `base_saved` spune dacă acel om are un program de bază salvat. Fără el, `inherit` nu le dă clienților nicio oră.

`PATCH /listings/{code}/viewing-schedule` schimbă doar câmpurile trimise: `mode`, `hours` (doar cu `mode: own`), `duration_min`, `notice_min`, `available_from` (`YYYY-MM-DD`), `confirmation` (`auto`, `manual` sau `null`), `runner`, `occupant` (`notify`, `phone`), `blocked_dates`, `confirm_pending`.

* Doar `{"mode": "inherit"}` (sau alt mod) schimbă modul și atât, ca în portal: regulile și orele proprii rămân. Un anunț care trece pe `own` fără ore proprii pornește de la programul de bază al celui care face vizionările, deci pentru clienți nu se schimbă nimic până nu editezi orele.
* `runner` e emailul unui coleg activ din firma anunțului, unul pe care l-ai putea alege și în portal (un manager își alege echipa). `null` sau emailul titularului lasă vizionările titularului. La un anunț fără firmă, singurul `runner` posibil e titularul.
* `occupant.phone` e obligatoriu când `occupant.notify` e `true`. Numărul e păstrat cu programul anunțului cât timp `notify` e `true`; cu `notify: false` se șterge, ca în aplicație.
* `confirm_pending: true` confirmă cererile care așteaptă la acest anunț, dacă după salvare anunțul confirmă pe loc.
* Pe un anunț care nu e public, programul se salvează, dar nu generează ore până anunțul redevine activ.

`PATCH /listings/{code}/viewings` (setările din [Vizionările](https://api.housera.ro/ro/guides/viewings.md)) scrie aceeași durată și aceeași confirmare. Acolo un `null` e ignorat. Aici, `null` înseamnă „ca de obicei”.

Durata și confirmarea anunțului schimbă `etag`-ul anunțului, ca prin `PATCH /listings/{code}/viewings`. Orele, modul, preavizul, zilele libere și `runner` nu îl schimbă.

## Programul tău pe mai multe anunțuri

`POST /account/viewing-schedule/apply` face ce face „Folosește programul meu” pe anunțurile selectate în portal. Trimiți cel mult 100 de coduri:

```json theme={null}
{ "codes": ["HEWPUTA8", "HEWPUTB2", "HEWPUTC3"] }
```

```json theme={null}
{ "data": { "applied": ["HEWPUTA8"], "skipped": [ { "code": "HEWPUTB2", "reason": "base_schedule_missing" }, { "code": "HEWPUTC3", "reason": "not_active" } ] } }
```

Un anunț trece pe `inherit` dacă e activ, îl gestionezi și cel care îi face vizionările are un program de bază salvat. Altfel primești motivul: `base_schedule_missing`, `not_active` sau `not_found`. Un cod care nu există și unul la care cheia ta nu ajunge primesc amândouă `not_found`. Aceeași listă trimisă de două ori dă același rezultat.

## Erorile

| Status | `code` | Când |
| - | - | - |
| `422` | `viewing_hours` | `hours` nu e o săptămână validă: interval în afara pasului de 15 minute, sfârșit înaintea începutului, intervale suprapuse, mai mult de 6 pe zi sau o zi necunoscută. |
| `422` | `hours_need_own_mode` | Ai trimis `hours` pe un anunț care rămâne pe `inherit` sau `on_request`. Trimite și `mode: own`. |
| `422` | `runner_not_member` | Emailul din `runner` nu e al unui coleg pe care îl poți pune să facă vizionările anunțului. |
| `422` | `occupant_phone_required` | `occupant.notify` e `true`, dar lipsește `occupant.phone`. |
| `422` | `in`, `max`, `date_format`, `regex` | O valoare care nu e în `options`, peste 50 de zile libere sau peste 100 de coduri, o dată în alt format, un telefon greșit. |
| `404` | `not_found` | Un anunț pe care nu îl gestionezi și nu îi faci vizionările. Răspunsul vine înaintea oricărei verificări a corpului. |
| `403` | `missing_ability` | O cheie fără `listings:write` încearcă o schimbare. |


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