Skip to main content
This page is for those who automatically synchronize an entire inventory: real estate CRMs, agency ERPs, scripts that publish from a database. The template below keeps Housera up to date with your system, withstands network failures, and never overwrites the work of agents done directly in the portal.
1

You publish and update by your id

For each property in the CRM, you send PUT /listings/ref/{id-ul tău} with all the fields you know. There’s no need to remember if the listing already exists: the first time it gets created (201), then it’s updated (200 or 202).
Keep in the CRM, next to each property, code and etag from the last response. When creating a new listing, send without If-Match.
2

You send the pictures

Once the listing exists, PUT /listings/{code}/photos with the complete list, in order. Resend the list only when something has changed with the pictures in the CRM: the same URLs don’t get downloaded again, but each list sent for a published listing goes into moderation.
3

You listen to the webhooks

You configure a webhook for all events. You update in the CRM the status of the listing to listing.published, listing.rejected, listing.paused, listing.reactivated, listing.sold, and listing.withdrawn, and at listing.edited_in_portal you apply your conflict rule (below).
4

You recover what was missed

When the service starts and every few minutes, you run GET /events?after=<ultimul id procesat>. A lost webhook while your server was down is no longer a lost change.
5

You reconcile daily

Once a day you go through GET /account/listings?fields=code,external_ref,etag,updated_at,status and compare with the CRM: etag different means a change on Housera, a missing id means a listing to resend. The details are in Identifiers.

Edits made in the portal

Listings published via API remain editable on housera.ro: an agent can correct the price or description directly from their account. When this happens:
  1. You receive the webhook listing.edited_in_portal, with the new etag.
  2. The etag you have in the CRM is no longer the current one.
  3. Your next PUT or PATCH with old If-Match receives 412 listing_changed_meanwhile and does not write anything.
What you do at 412 is your decision. Common options:
You read the listing with GET /account/listings/{code}, update the CRM with the values from Housera and save the new etag. Appropriate when agents work directly in the portal.
Without If-Match, PUT and PATCH apply across any version. For automatic synchronization, always send If-Match on existing listings.

Fields you don’t know

PUT /listings/ref/{ref} on an existing listing acts like a patch: fields you do not send retain their value. Send only the fields that your CRM actually manages. If an agent fills in a field in the portal that the CRM doesn’t have, your synchronization does not delete it. To explicitly clear a field, you send it with null.

Resubmissions without changes

An identical body to the last successful write does not write anything and does not go to moderation: you receive 200 with the header X-Housera-Unchanged: true. You can thus resend the entire inventory at every synchronization. To take advantage of this, serialize the body the same way every time (the same field order, the same number format).

Robustness

Retries

Idempotence

  • PUT /listings/ref/{ref} is safe to repeat: the same id never creates two listings.
  • For POST /listings, always send Idempotency-Key and reuse the same value on retries of the same operation.
  • PATCH and PUT /listings/{code}/photos yield the same result if repeated. With If-Match, a repeat after a successful write receives 412, because the version changed right through the first write: you read the listing and check if it already has your values.
  • A transition (/pause, /resume, /sold) repeated after it succeeded receives 404, because the listing is no longer in the departing state. Treat this as success if the current state is the desired one.

Rate

The limit is 300 requests per minute for each key. Monitor X-RateLimit-Remaining and throttle when it approaches zero, instead of waiting 429. At this limit, 3,000 listings are resent in about 10 minutes, including unchanged ones. See Limits.

Validation before launch

Before the first real synchronization, pass the entire inventory through POST /listings/validate (in sandbox or in production, it does not write anything) and clean both errors[] and warnings[]. The error codes are stable, so you can turn them into clear messages for agents filling in data in the CRM.

Checklist

  • Sandbox key with listings:read, listings:write, media:write.
  • The entire inventory passes POST /listings/validate, without warnings[].
  • Webhook configured, signature verified, with a 5-minute tolerance.
  • You treat 412, 409, 429, and 5xx as above.
  • GET /events run periodically, with the last id saved.
  • New hsr_live_ key from the account on housera.ro.
  • The webhook created again in production, with its secret.
  • The base address changed to https://housera.ro/api/v1.
  • A reminder in the calendar before the key expires.