First of all: approval
The integrator access is granted by Housera. Write to us at office@housera.ro with:- the name of the application, as you want the agencies to see it;
- the website;
- return addresses (
redirect_uri), exactly as you will send them. We compare character by character, with no wildcard. We only accepthttps, plushttp://localhostfor development; - rights you need (
listings:read,listings:write,media:write); - optionally, a
httpswebhook address for events of connected accounts.
client_id (hsrc_…), client_secret (hsrs_…) and, if you requested a webhook, its secret (whsec_…). You receive them only once; keep them only on the server. For the sandbox, you get separate data, on staging.housera.ro.
The Flow
1
You are preparing the request
For each connection you generate two random values and keep them in the agent’s session, on your server:
state: protects against forged requests; you check it on return;code_verifier: 43–128 characters fromA-Z a-z 0-9 - . _ ~. From it you calculatecode_challenge = BASE64URL(SHA256(code_verifier)), without=at the end.
2
You send the agent to the consent page
You redirect the agent’s browser to:In the sandbox, the address is
https://staging.housera.ro/setari/api/conectare. Staging is not open to the public: for your tests, we provide, upon request, a test account with access to it. The English version, /en/settings/api/connect, is equivalent.scope is optional: without it you request all rights that Housera has approved for you. You cannot request more than that, and the platform catalog is never granted through connection.3
The agent accepts or declines
If the agent is not authenticated, housera.ro first asks him to log in. Then he sees the name of your application, the account or agency for which access is granted, the rights, and the domain to which he returns.The browser goes back to your return address:
- to consent:
https://crm.exemplu.ro/housera/callback?code=…&state=…; - to decline:
…?error=access_denied&state=….
state is the one from the session. If it is not, you stop the flow.4
You change the code on the key, from the server
The code expires in 60 seconds and is used only once. You send it immediately to You can also send
POST /oauth/token:client_id and client_secret via HTTP Basic instead of the body.5
You work with the key, like any key
You keep
access_token and connection_id next to the agency in your CRM and use the key just like in the rest of the documentation: Authorization: Bearer …. The same rules, the same limits, the same moderation.What happens with listings
- The listings you publish are the agency’s. Agents can also edit them from the portal; then you receive
listing.edited_in_portaland the newetag. - Your ids (
PUT /listings/ref/{ref}) are only yours: two CRMs connected to the same agency do not interfere, even if they use the same ids. - In the requests log, the agency sees every request made through your connection, with the name of the application.
Events
If you declared a webhook for approval, you receive on it the events of all connected accounts, signed with the webhook secret (see Webhooks). Each delivery additionally includes theconnection field, equal to connection_id from the response of the code exchange:
GET /events?after=…, using its key.
Expiration and disconnection
- The key expires after 365 days (
expires_in). Before the deadline, send the agent through the consent page again: the new key replaces the old one. - A new connection of the same account gives you a new key and invalidates the old one.
- The agency can disconnect you from Settings → API → Connected Applications. From that moment on, the key receives
401 unauthenticated, and the webhook no longer receives the events of the account. Treat401as a disconnection and suggest to the agent to reconnect. - If Housera disables your access, all your keys receive
401until reactivation.
Errors
On the consent page, as long as the application or return address are not confirmed, the error remains on housera.ro and does not reach you:
Once confirmed, the errors return to your return address, with
error and state:
At
POST /oauth/token, the errors take the form of RFC 6749, {"error": "…", "error_description": "…"}: