Hoppa till dokumentationen
Utvecklare
Visa Markdown

Anslut till Homito

På den här sidan
  1. Anslut ett system eller en agent
  2. Företagsåtkomst
  3. Använd den konfigurerade API-adressen
  4. curl
  5. JavaScript — server, Node.js 20 eller senare
  6. Python — server, standardbiblioteket
  7. Förstå den första autentiserade läsningen
  8. REST-operationer och nyckelbehörigheter
  9. Fortsätt läsningar säkert
  10. Sökandens identitet och integrationsnycklar

Välj behörigheter och gör din första autentiserade läsning från servern.

Anslut ett system eller en agent

Använd Homitos företagsavgränsade HTTPS-API från din egen server eller agent. När en administratör har tillhandahållit en nyckel kan det vanliga integrationsarbetet ske utan Homito-portalen. API-referensen och OpenAPI-dokumentet beskriver samma operationer och scheman.

Företagsåtkomst

En administratör för ett befintligt, verifierat Homito-företag skapar en nyckel under Settings → API & agents. Detta kräver administratörens Homito-användarsession och behörigheten settings.edit. Hemligheten visas en gång: lägg den i serverns hemlighetshanterare. Nyckeln bestämmer företaget; ett annat företags-ID i anropet utökar inte åtkomsten. Extern självregistrering av företag är inte tillgänglig. Nyckelhantering använder Homito-webbappens adress och dess användarsession, inte den här externa API-adressen.

Använd den konfigurerade API-adressen

Be en företagsadministratör om en nyckel med read:properties. Sätt HOMITO_API_BASE_URL till den konfigurerade HTTPS-adressen för API:t, utan sökväg eller frågeparametrar. Tillför HOMITO_API_KEY från serverns hemlighetshanterare; lägg den aldrig i webbläsarkod, en URL eller en agentkonversation.

Dessa serverexempel utan SDK gör samma första läsning. curl och JavaScript har en total tidsgräns på 10 sekunder. Python har en blockerande nätverkstidsgräns på 10 sekunder, inte en total tidsgräns för hela svaret. JavaScript och Python avvisar svar över 2 MiB och skriver bara ut count/hasMore; curl kasserar svarskroppen och skriver ut HTTP-status. Spara JavaScript-exemplet som first-read.mjs och kör det med Node.js 20 eller senare.

curl

Kodexempel
curl --proto '=https' --fail --silent --show-error --connect-timeout 5 --max-time 10 \
  --output /dev/null --write-out 'HTTP %{http_code}\n' \
  "$HOMITO_API_BASE_URL/api/v1/landlord/inventory/properties?limit=1" \
  -H "Authorization: Bearer $HOMITO_API_KEY"

JavaScript — server, Node.js 20 eller senare

Kodexempel
const apiOrigin = process.env.HOMITO_API_BASE_URL;
const apiKey = process.env.HOMITO_API_KEY;
if (!apiOrigin || !apiKey) {
  throw new Error("Configure HOMITO_API_BASE_URL and HOMITO_API_KEY on the server.");
}
let base;
try {
  base = new URL(apiOrigin);
} catch {
  throw new Error("Use the configured HTTPS API origin without paths, ports, query or credentials.");
}
if (base.protocol !== "https:" || base.username || base.password || base.port ||
    !(apiOrigin === base.origin || apiOrigin === base.origin + "/")) {
  throw new Error("Use the configured HTTPS API origin without paths, ports, query or credentials.");
}
const MAX_RESPONSE_BYTES = 2 * 1024 * 1024;
let response;
try {
  response = await fetch(new URL("/api/v1/landlord/inventory/properties?limit=1", base.origin), {
    headers: { Authorization: "Bearer " + apiKey },
    signal: AbortSignal.timeout(10000),
    redirect: "error",
  });
} catch {
  throw new Error("Homito request failed (network or timeout).");
}
if (!response.ok) {
  throw new Error("Homito read failed (HTTP " + response.status + ").");
}
const declared = response.headers.get("content-length");
if (declared !== null && (!/^[0-9]+$/.test(declared) ||
    !Number.isSafeInteger(Number(declared)) || Number(declared) > MAX_RESPONSE_BYTES)) {
  throw new Error("Homito response exceeded the safe size limit.");
}
if (!response.body) throw new Error("Homito returned an empty response.");
const reader = response.body.getReader();
const chunks = [];
let byteLength = 0;
try {
  while (true) {
    const { done, value } = await reader.read();
    if (done) break;
    byteLength += value.byteLength;
    if (byteLength > MAX_RESPONSE_BYTES) {
      await reader.cancel();
      throw new Error("Response too large.");
    }
    chunks.push(value);
  }
} catch {
  throw new Error("Homito response could not be read within the configured bounds.");
} finally {
  reader.releaseLock();
}
const bytes = new Uint8Array(byteLength);
let offset = 0;
for (const chunk of chunks) {
  bytes.set(chunk, offset);
  offset += chunk.byteLength;
}
let data;
try {
  data = JSON.parse(new TextDecoder("utf-8", { fatal: true }).decode(bytes));
} catch {
  throw new Error("Homito returned invalid JSON.");
}
if (!data || !Array.isArray(data.properties) ||
    !Object.prototype.hasOwnProperty.call(data, "nextCursor") ||
    !(data.nextCursor === null || typeof data.nextCursor === "string")) {
  throw new Error("Unexpected Homito response shape.");
}
console.log({ count: data.properties.length, hasMore: data.nextCursor !== null });

Python — server, standardbiblioteket

Kodexempel
import json
import os
import urllib.error
import urllib.request
from urllib.parse import urlsplit

class NoRedirect(urllib.request.HTTPRedirectHandler):
    def redirect_request(self, req, fp, code, msg, headers, newurl):
        return None

api_origin = os.environ.get("HOMITO_API_BASE_URL")
api_key = os.environ.get("HOMITO_API_KEY")
if not api_origin or not api_key:
    raise RuntimeError("Configure HOMITO_API_BASE_URL and HOMITO_API_KEY on the server.")
try:
    base = urlsplit(api_origin)
    hostname = base.hostname
    port = base.port
except ValueError:
    raise RuntimeError("Use the configured HTTPS API origin without paths, ports, query or credentials.") from None
if not hostname:
    raise RuntimeError("Use the configured HTTPS API origin without paths, ports, query or credentials.")
request_origin = "https://" + ("[" + hostname + "]" if ":" in hostname else hostname)
if (base.scheme != "https" or base.username is not None or base.password is not None
        or port is not None or any(character.isspace() for character in api_origin)
        or chr(92) in api_origin or api_origin not in (request_origin, request_origin + "/")):
    raise RuntimeError("Use the configured HTTPS API origin without paths, ports, query or credentials.")
MAX_RESPONSE_BYTES = 2 * 1024 * 1024
request = urllib.request.Request(
    request_origin + "/api/v1/landlord/inventory/properties?limit=1",
    headers={"Authorization": "Bearer " + api_key},
    method="GET",
)
opener = urllib.request.build_opener(NoRedirect())
try:
    with opener.open(request, timeout=10) as response:
        if not 200 <= response.status < 300:
            raise RuntimeError("Homito read failed (HTTP " + str(response.status) + ").")
        declared = response.headers.get("Content-Length")
        if declared is not None and (not declared.isdecimal() or int(declared) > MAX_RESPONSE_BYTES):
            raise RuntimeError("Homito response exceeded the safe size limit.")
        body = response.read(MAX_RESPONSE_BYTES + 1)
        if len(body) > MAX_RESPONSE_BYTES:
            raise RuntimeError("Homito response exceeded the safe size limit.")
        data = json.loads(body)
except urllib.error.HTTPError as error:
    raise RuntimeError("Homito read failed (HTTP " + str(error.code) + ").") from None
except (urllib.error.URLError, TimeoutError, OSError):
    raise RuntimeError("Homito request failed (network or timeout).") from None
except ValueError:
    raise RuntimeError("Homito returned invalid JSON.") from None
if (not isinstance(data, dict) or not isinstance(data.get("properties"), list)
        or "nextCursor" not in data
        or not (data["nextCursor"] is None or isinstance(data["nextCursor"], str))):
    raise RuntimeError("Unexpected Homito response shape.")
print(json.dumps({"count": len(data["properties"]), "hasMore": data["nextCursor"] is not None}))

Förstå den första autentiserade läsningen

Ett lyckat tomt resultat är {"properties":[],"nextCursor":null}: anslutningen fungerade och företaget har inga fastigheter att returnera. Det är inte ett autentiseringsfel. För ett resultat med innehåll: använd ett returnerat fastighets-id och läs GET /api/v1/landlord/inventory/properties/{propertyId} eller /{propertyId}/units. Läs operationens svarsscheman för fält och värden som kan vara null.

REST-operationer och nyckelbehörigheter

UppgiftNyckelbehörigheterBörja här
Läs fastigheter och lägenheterread:propertiesGET /api/v1/landlord/inventory/properties

Fortsätt läsningar säkert

Följ nextCursor tills värdet är null och behåll samma listoperation och filter. Använd en cursor endast med samma företag och listoperation. Förhandsgranskningar av importer, jobb och deras historik tillhör API-nyckeln som skapade dem, även vid åtkomst via jobb-ID. Ett grönt offentligt /health-svar verifierar inte i sig nyckeln eller företagsåtkomsten.

Sökandens identitet och integrationsnycklar

Förvara kundnycklar på servern. En företagsnyckel ersätter inte sökandens identitet, samtycke, inskickningsnyckel eller uppladdningsnyckel. Följ operationens publicerade formulär- och eID-krav innan en ansökan tas emot.