leads:read o citești și prin API, cu datele de contact ale clientului, și o aduci în CRM-ul tău.
Cine are acces
Cheia API vede cererile pe care contul le vede în portal, în firma cheii, plus cererile lui de pe anunțurile publicate în afara unei firme:- titularul și administratorii văd cererile întregii firme;
- un manager de punct de lucru vede cererile punctului său (la un dezvoltator imobiliar, ale proiectelor sale);
- un agent vede cererile pe care le are în grijă;
- un cont fără firmă își vede cererile proprii.
leads:read îl bifezi singur, în Setări → API. Un integrator îl primește doar dacă Housera i l-a aprobat, iar pagina de acord îi spune contului că integratorul va primi datele de contact ale clienților. Fără acest drept, apelurile la /leads primesc 403 missing_ability.
Lista cererilor
GET /leads întoarce cererile de la cea mai veche la cea mai nouă, cu paginare prin cursor.
Un cod sau un id pe care Housera nu îl găsește întoarce o listă goală. Filtrele se pot combina între ele și cu
inbox=true, iar o valoare care nu e în listă (de exemplu status=unassigned) primește 422.
since se compară cu updated_at, așa că o cerere deja importată poate apărea din nou. După id știi că o ai deja.
O cerere
GET /leads/{id} întoarce o singură cerere. Pentru o cerere la care cheia nu are acces, API-ul răspunde 404, ca pentru una care nu există.
Valorile lui
inbox.reason sunt cele din portal:
no_listing: clientul a scris de pe pagina firmei, deci cererea nu are anunț;left: agentul care avea cererea sau anunțul a plecat din firmă ori a fost dezactivat, iar munca lui a ajuns în „De preluat”;no_agent: anunțul nu are un agent activ.
Lucrul cu cererile
Cu dreptulleads:write faci prin API ce faci cu o cerere în portal: îi schimbi etapa, nota și suma, o ștergi, adaugi contacte de mână și preiei cererile care nu au încă responsabil. Regulile sunt aceleași ca în portal, iar schimbarea se vede imediat acolo.
leads:write merge doar împreună cu leads:read, fiindcă fiecare răspuns conține datele de contact ale clientului. Pe cheia proprie îl bifezi în Setări → API. Un integrator îl primește doar dacă Housera i l-a aprobat, iar contul îl acceptă separat pe pagina de acord. O cheie sau o legătură care are doar leads:read nu poate scrie: primește 403 missing_ability.
Etapa, nota și datele de contact
PATCH /leads/{id} schimbă câmpurile pe care le trimiți și le lasă pe celelalte cum sunt. Un câmp trimis cu null se golește, în afară de nume și etapă, care nu pot rămâne goale.
Răspunsul conține cererea, cu valorile noi. Dacă alt contact al aceluiași client pe același anunț are deja telefonul sau emailul trimis, primești
422, cu codul lead_duplicate pe /phone.
DELETE /leads/{id} șterge cererea, ca din portal. Răspunsul e 204, iar cererea dispare din liste și din GET /leads/{id}.
O cerere pe care cheia nu o vede, a unui coleg sau a altei firme, primește 404, ca una care nu există.
Un contact adăugat de mână
POST /leads adaugă un contact, ca butonul „Adaugă” din portal, cu tine ca responsabil. Doar name e obligatoriu, iar fără status contactul pornește din etapa new. Trimite un Idempotency-Key diferit pentru fiecare contact nou și același la reîncercarea unei cereri: în 10 minute, aceeași valoare întoarce contactul adăugat prima dată, cu 200 și cu același meta.possible_duplicate, fără să adauge altul.
Titularul, administratorii și managerii adaugă contactul în cererile firmei. Dacă vrei să rămână doar în cererile tale, trimiți "board": "personal". La un agent, contactul ajunge mereu în cererile lui, iar "board": "firm" primește 403.
Contactul există deja?
Înainte să salveze, portalul verifică dacă ai deja contactul: caută în aceleași cereri (ale firmei sau ale tale) ultimul contact cu același telefon sau cu exact același nume. Prin API faci aceeași verificare, între cererile pe care cheia le vede, cuPOST /leads/duplicate-check, cu name, phone și, opțional, board, ca la POST /leads:
data, ca la GET /leads/{id}, iar în meta.matched_on ce s-a potrivit: phone, name sau amândouă. Dacă nu, primești "data": null și meta.matched_on gol. Verificarea nu schimbă nimic și cere aceleași drepturi ca adăugarea, leads:read și leads:write.
Doi oameni pot avea același telefon, de exemplu linia unei agenții, așa că verificarea doar te avertizează. Tu decizi dacă adaugi contactul. POST /leads îl adaugă oricum și îți spune în meta.possible_duplicate contactul pe care îl găsește aceeași verificare, cu id și matched_on, sau null.
Cererile fără responsabil
Când un anunț al firmei nu are un agent activ, sau clientul scrie de pe pagina agenției, cererea ajunge la „De preluat” și o poate lua oricine din punctul de lucru. Prin API:GET /leads?inbox=trueîntoarce cererile din „De preluat” pe care contul le poate prelua. Un agent le vede doar pe cele ale punctului său de lucru, iar titularul și administratorii, pe toate.GET /leads/{id}le citește și pe ele.POST /leads/{id}/takeîți dă cererea. Dacă un coleg a preluat-o înainte, primești409 lead_already_taken. Dacă ai deja un contact cu același client, fără anunț, cererea se unește cu el, ca în portal: răspunsul e contactul tău, iarmeta.merged_frome id-ul cererii unite, care nu mai există.POST /leads/{id}/assign, cu{"agent_email": "coleg@agentia.ro"}, dă cererea unui coleg din echipa ta. Merge pentru titular, administratori și manageri, iar colegul primește notificarea din portal. Un email care nu e al unui coleg din echipă primește422 agent_not_member, iar un coleg dezactivat,422 agent_deactivated.
GET /leads al responsabilului, cu agent completat.
Conversația cu clientul
Când clientul îți scrie pe un anunț, cererea are o conversație, aceeași pe care o vezi în Mesaje în portal. Prin API o citești și îi răspunzi clientului, ca din portal. Conversația o citește și îi răspunde doar contul care se ocupă de anunț, ca în portal. Titularul sau managerul care vede cererea unui agent primește403 conversation_not_held la conversația ei. O cerere fără conversație (o cerere de apel, un contact adăugat de mână, un mesaj de pe pagina agenției) întoarce o listă goală.
Mesajele
GET /leads/{id}/messages întoarce mesajele de la cel mai vechi, cu paginare prin cursor. Cu after primești doar mesajele de după unul pe care îl ai deja. Citirea prin API nu marchează mesajele ca citite, deci nu le ascunde de cel care lucrează în portal.
Răspunsul
POST /leads/{id}/messages trimite un mesaj clientului, ca din portal. Clientul îl vede în conversație și primește aceleași notificări ca la un mesaj scris în portal.
201, cu mesajul. Trimite un Idempotency-Key diferit pentru fiecare mesaj nou și același la reîncercarea unui mesaj: în 10 minute, o cerere cu aceeași valoare întoarce mesajul trimis prima dată, cu 200, și nu trimite altul. Textul are cel mult 2.000 de caractere.
Răspunsul e refuzat cu 409 când cererea nu are conversație (no_conversation), când conversația e doar de citit, fiindcă anunțul sau contul clientului a fost șters (conversation_closed), și când una dintre părți a blocat-o pe cealaltă (conversation_blocked). Răspunsurile prin API și cele din portal au aceeași limită, 20 pe minut și 200 pe oră pe cont.
Editarea, ștergerea și citirea
PATCH /leads/{id}/messages/{message}, cu{"body": "…"}, schimbă textul unui mesaj scris de tine, în primele 15 minute și cât timp conversația e deschisă. După 15 minute primești409 edit_window_closed. Clientul vede mesajul marcat ca editat.DELETE /leads/{id}/messages/{message}șterge un mesaj scris de tine, oricând. Mesajul rămâne în conversație ca „Mesaj șters”, fără text.- Un mesaj al clientului nu se editează și nu se șterge: primești
403 message_not_yours. POST /leads/{id}/messages/readmarchează mesajele clientului ca citite, ca atunci când deschizi conversația în portal. Clientul nu află nimic.
Evenimentul lead.message_received
Când clientul scrie din nou în conversație, contul care se ocupă de anunț primește evenimentul lead.message_received, pe webhook și în GET /events, dacă are o cheie cu leads:read. Evenimentul are lead_id și message_id, fără textul mesajului, pe care îl citești cu GET /leads/{id}/messages?after=…. Primul mesaj al clientului, cel care deschide conversația, vine ca lead.created sau, dacă clientul avea deja o cerere pe anunț, ca lead.updated, deci nu produce și lead.message_received.
Evenimentul lead.created
Când un client îți trimite prima cerere pe un anunț, primești evenimentul lead.created, pe webhook și în GET /events. Evenimentul nu conține datele clientului: are lead_id și source, iar datele le citești cu GET /leads/{id}. În GET /events îl vezi cu orice cheie care are leads:read, chiar dacă nu are listings:read.
Evenimentul ajunge doar la conturile care văd cererea în căsuță și au o cheie cu leads:read. Din ziua pe care ți-o anunțăm, o cerere care ajunge la „De preluat” produce lead.created și pentru cei care o pot prelua, adică pentru toți cei din punctul de lucru pe care îi anunță și portalul, agenții inclusiv. Un webhook îl primește doar dacă are în spate dreptul leads:read. Detaliile sunt în Webhook-uri.
Evenimentele lead.assigned și lead.removed
Din ziua pe care ți-o anunțăm, afli și ce se întâmplă cu o cerere după ce a venit.
lead.assigned vine când cererea are un responsabil nou. by spune cum: take (cineva a preluat-o din „De preluat”), assign (titularul, un administrator sau un manager a dat-o unui coleg) sau handover (a trecut la un coleg odată cu munca cuiva care a plecat din firmă sau a fost dezactivat, ori cu un anunț mutat la alt agent). agent e noul responsabil, iar previous_agent cel de dinainte, fiecare cu name și email; previous_agent e null când cererea aștepta în „De preluat” sau când contul colegului de dinainte a fost șters. Îl primesc cei care văd cererea acum.
lead.removed vine când cererea nu mai e a ta, cu reason:
deleted: cererea a fost ștearsă, din portal sau prin API;merged: cererea s-a adăugat la cererea aceluiași client pe care o avea deja colegul care a preluat-o;out_of_reach: cererea nu mai e în raza ta, de exemplu a preluat-o un coleg din „De preluat” sau ai predat-o.
lead.removed, GET /leads/{id} răspunde 404, dar evenimentul rămâne în GET /events. Ștergi cererea din sistemul tău sau o marchezi ca ieșită din raza ta.
Ambele evenimente au lead_id, ca lead.created, și cer dreptul leads:read. Orice webhook care primește lead.created le primește și pe ele, fără să le bifezi.
Evenimentul lead.updated
Când același client revine pe același anunț cu o cerere nouă, de exemplu îți cere să-l suni după ce ți-a scris, cererea nouă se adaugă la cea pe care o ai deja. Nu apare o cerere separată, dar primești evenimentul lead.updated, cu același lead_id. source din eveniment spune pe ce canal a venit cererea nouă (aici phone), iar source din GET /leads/{id} rămâne canalul primei cereri. Momentul cererii noi e created_at al evenimentului. updated_at al cererii devine momentul cererii noi, deci GET /leads?since= o aduce din nou. La fel primești lead.updated când clientul scrie din nou de pe pagina firmei după ce un coleg i-a preluat cererea, și când o cerere din „De preluat” se unește, la preluare, cu contactul pe care îl ai deja cu același client.
lead.updated ajunge la aceleași conturi și webhook-uri ca lead.created și cere tot dreptul leads:read. Pe un webhook din Setări → API îl bifezi separat.
Ștergerea datelor clientului
Housera șterge datele unui client în două cazuri, iar tu trebuie să le ștergi și din sistemul tău. Când clientul își șterge contul, cererile lui rămân în portal, dar fără datele lui: numele devine anonim, iar telefonul, emailul, mesajul și nota se golesc. Cererea primeșteerased: true, iar updated_at devine momentul ștergerii, așa că GET /leads?since= o aduce din nou. Primești și evenimentul lead.erased, cu reason: account_deleted, chiar și pentru o cerere pe care ai șters-o deja din portal.
O cerere fără nicio activitate de 24 de luni, sau una ștearsă din portal de mai mult de 30 de zile, se șterge definitiv. Chiar înainte primești lead.erased, cu reason: retention. După aceea GET /leads/{id} răspunde 404, iar evenimentul rămâne în GET /events 35 de zile.
lead.erased ajunge la aceleași conturi ca lead.created și cere tot dreptul leads:read. Orice webhook care primește lead.created îl primește și pe el; nu apare în lista de evenimente a webhook-ului și nu se bifează.