{"openapi":"3.1.0","info":{"title":"Homito External API","version":"1.1.0","description":"## Connect a system or agent\n\nUse Homito's company-scoped HTTPS API from your own server or agent. Once an administrator has supplied a key, ordinary integration work can run without the Homito portal. The [API reference](https://h2nf8ee4ch.execute-api.eu-north-1.amazonaws.com/docs) and [OpenAPI document](https://h2nf8ee4ch.execute-api.eu-north-1.amazonaws.com/openapi.json) describe the same operations and schemas.\n\n### 1. Choose a task and request only its permissions\n\nAn administrator of an existing, verified Homito company creates a key under **Settings → API & agents**. This requires their Homito user session and `settings.edit` permission. The secret is shown once: put it in your server's secret manager. The key determines the company; passing a different company ID cannot extend its access. External self-service company registration is unavailable. Key management uses the Homito web-app origin and its user session, not this external API origin.\n\n| Task | Key permissions | Start here |\n| --- | --- | --- |\n| Read properties and units | `read:properties` | `GET /api/v1/landlord/inventory/properties` |\n| Read published and unpublished listings; synchronize adverts | `read:properties`; `write:properties` for the corresponding mutation | `GET /api/v1/landlord/listings`, `GET /api/v1/landlord/listings/changes`, `PATCH /api/v1/landlord/listings/{unitId}/content`, `POST /api/v1/landlord/listings/{unitId}/media/uploads`, `POST /api/v1/landlord/listings/{unitId}/media/uploads/{uploadId}/complete`, `PATCH /api/v1/landlord/listings/{unitId}/media`, `PATCH /api/v1/landlord/listings/{unitId}/publication` |\n| Read tenant contacts | `read:tenants` | `GET /api/v1/landlord/tenants` |\n| Read lease timelines | `read:leases` | `GET /api/v1/landlord/leases` |\n| Read application summaries | `read:applications` | `GET /api/v1/landlord/applications` |\n| Preview and commit properties and units | `write:properties`; `read:properties` for readback | `POST /api/v1/landlord/portfolio-imports/preview` |\n| Read or import commercial rent rolls | `read:rent-roll`; `write:rent-roll` for import | `GET /api/v1/landlord/rent-roll` |\n| Read or update operational work | `read:fault-reports`, `read:work-orders`; `write:fault-reports`, `write:work-orders` for the corresponding mutation | `GET /api/v1/landlord/fault-reports`, `GET /api/v1/landlord/work-orders` |\n| Read or conduct commercial inspections | `read:inspections`; `write:inspections` for mutations | `GET /api/v1/landlord/commercial-inspections` |\n| Read or use commercial tenant assistance | `read:commercial-assistance`; `write:commercial-assistance` for mutations | `GET /api/v1/landlord/commercial-assistance` |\n| Start a screening and read certified status | `write:screenings`, `read:screenings`; `read:applications` to select a candidate | `POST /api/v1/landlord/screenings` |\n| Register webhooks and monitor deliveries | `write:webhooks`, `read:webhooks` | `POST /api/v1/landlord/webhooks` |\n| Use the customer-server application intake budget or hosted eID handoff | `write:applications` on a separate server key | `POST /api/v1/public/units/{slug}/application-eid/handoffs` |\n\nKeep customer keys on the server. A company key does not replace the applicant's identity, consent, submission key or upload key. Use the operation's published form and eID requirements before accepting an application.\n\n### 2. Complete the first authenticated read\n\nAsk a company administrator for a key with `read:properties`. Set `HOMITO_API_BASE_URL` to the configured [HTTPS API origin](https://h2nf8ee4ch.execute-api.eu-north-1.amazonaws.com), without a path or query. Inject `HOMITO_API_KEY` from your server secret manager; never put it in browser code, a URL or an agent conversation.\n\nThese SDK-free server examples make the same first read. curl and JavaScript use a 10-second total deadline. Python uses a 10-second blocking network timeout, not a total-response deadline. JavaScript and Python reject responses over 2 MiB and print only count/hasMore; curl discards the body and prints HTTP status. Save the JavaScript example as `first-read.mjs` and run it with Node.js 20 or later.\n\n### curl\n\n```bash\ncurl --proto '=https' --fail --silent --show-error --connect-timeout 5 --max-time 10 \\\n  --output /dev/null --write-out 'HTTP %{http_code}\\n' \\\n  \"$HOMITO_API_BASE_URL/api/v1/landlord/inventory/properties?limit=1\" \\\n  -H \"Authorization: Bearer $HOMITO_API_KEY\"\n```\n\n### JavaScript — server, Node.js 20 or later\n\n```javascript\nconst apiOrigin = process.env.HOMITO_API_BASE_URL;\nconst apiKey = process.env.HOMITO_API_KEY;\nif (!apiOrigin || !apiKey) {\n  throw new Error(\"Configure HOMITO_API_BASE_URL and HOMITO_API_KEY on the server.\");\n}\nlet base;\ntry {\n  base = new URL(apiOrigin);\n} catch {\n  throw new Error(\"Use the configured HTTPS API origin without paths, ports, query or credentials.\");\n}\nif (base.protocol !== \"https:\" || base.username || base.password || base.port ||\n    !(apiOrigin === base.origin || apiOrigin === base.origin + \"/\")) {\n  throw new Error(\"Use the configured HTTPS API origin without paths, ports, query or credentials.\");\n}\nconst MAX_RESPONSE_BYTES = 2 * 1024 * 1024;\nlet response;\ntry {\n  response = await fetch(new URL(\"/api/v1/landlord/inventory/properties?limit=1\", base.origin), {\n    headers: { Authorization: \"Bearer \" + apiKey },\n    signal: AbortSignal.timeout(10000),\n    redirect: \"error\",\n  });\n} catch {\n  throw new Error(\"Homito request failed (network or timeout).\");\n}\nif (!response.ok) {\n  throw new Error(\"Homito read failed (HTTP \" + response.status + \").\");\n}\nconst declared = response.headers.get(\"content-length\");\nif (declared !== null && (!/^[0-9]+$/.test(declared) ||\n    !Number.isSafeInteger(Number(declared)) || Number(declared) > MAX_RESPONSE_BYTES)) {\n  throw new Error(\"Homito response exceeded the safe size limit.\");\n}\nif (!response.body) throw new Error(\"Homito returned an empty response.\");\nconst reader = response.body.getReader();\nconst chunks = [];\nlet byteLength = 0;\ntry {\n  while (true) {\n    const { done, value } = await reader.read();\n    if (done) break;\n    byteLength += value.byteLength;\n    if (byteLength > MAX_RESPONSE_BYTES) {\n      await reader.cancel();\n      throw new Error(\"Response too large.\");\n    }\n    chunks.push(value);\n  }\n} catch {\n  throw new Error(\"Homito response could not be read within the configured bounds.\");\n} finally {\n  reader.releaseLock();\n}\nconst bytes = new Uint8Array(byteLength);\nlet offset = 0;\nfor (const chunk of chunks) {\n  bytes.set(chunk, offset);\n  offset += chunk.byteLength;\n}\nlet data;\ntry {\n  data = JSON.parse(new TextDecoder(\"utf-8\", { fatal: true }).decode(bytes));\n} catch {\n  throw new Error(\"Homito returned invalid JSON.\");\n}\nif (!data || !Array.isArray(data.properties) ||\n    !Object.prototype.hasOwnProperty.call(data, \"nextCursor\") ||\n    !(data.nextCursor === null || typeof data.nextCursor === \"string\")) {\n  throw new Error(\"Unexpected Homito response shape.\");\n}\nconsole.log({ count: data.properties.length, hasMore: data.nextCursor !== null });\n```\n\n### Python — server, standard library\n\n```python\nimport json\nimport os\nimport urllib.error\nimport urllib.request\nfrom urllib.parse import urlsplit\n\nclass NoRedirect(urllib.request.HTTPRedirectHandler):\n    def redirect_request(self, req, fp, code, msg, headers, newurl):\n        return None\n\napi_origin = os.environ.get(\"HOMITO_API_BASE_URL\")\napi_key = os.environ.get(\"HOMITO_API_KEY\")\nif not api_origin or not api_key:\n    raise RuntimeError(\"Configure HOMITO_API_BASE_URL and HOMITO_API_KEY on the server.\")\ntry:\n    base = urlsplit(api_origin)\n    hostname = base.hostname\n    port = base.port\nexcept ValueError:\n    raise RuntimeError(\"Use the configured HTTPS API origin without paths, ports, query or credentials.\") from None\nif not hostname:\n    raise RuntimeError(\"Use the configured HTTPS API origin without paths, ports, query or credentials.\")\nrequest_origin = \"https://\" + (\"[\" + hostname + \"]\" if \":\" in hostname else hostname)\nif (base.scheme != \"https\" or base.username is not None or base.password is not None\n        or port is not None or any(character.isspace() for character in api_origin)\n        or chr(92) in api_origin or api_origin not in (request_origin, request_origin + \"/\")):\n    raise RuntimeError(\"Use the configured HTTPS API origin without paths, ports, query or credentials.\")\nMAX_RESPONSE_BYTES = 2 * 1024 * 1024\nrequest = urllib.request.Request(\n    request_origin + \"/api/v1/landlord/inventory/properties?limit=1\",\n    headers={\"Authorization\": \"Bearer \" + api_key},\n    method=\"GET\",\n)\nopener = urllib.request.build_opener(NoRedirect())\ntry:\n    with opener.open(request, timeout=10) as response:\n        if not 200 <= response.status < 300:\n            raise RuntimeError(\"Homito read failed (HTTP \" + str(response.status) + \").\")\n        declared = response.headers.get(\"Content-Length\")\n        if declared is not None and (not declared.isdecimal() or int(declared) > MAX_RESPONSE_BYTES):\n            raise RuntimeError(\"Homito response exceeded the safe size limit.\")\n        body = response.read(MAX_RESPONSE_BYTES + 1)\n        if len(body) > MAX_RESPONSE_BYTES:\n            raise RuntimeError(\"Homito response exceeded the safe size limit.\")\n        data = json.loads(body)\nexcept urllib.error.HTTPError as error:\n    raise RuntimeError(\"Homito read failed (HTTP \" + str(error.code) + \").\") from None\nexcept (urllib.error.URLError, TimeoutError, OSError):\n    raise RuntimeError(\"Homito request failed (network or timeout).\") from None\nexcept ValueError:\n    raise RuntimeError(\"Homito returned invalid JSON.\") from None\nif (not isinstance(data, dict) or not isinstance(data.get(\"properties\"), list)\n        or \"nextCursor\" not in data\n        or not (data[\"nextCursor\"] is None or isinstance(data[\"nextCursor\"], str))):\n    raise RuntimeError(\"Unexpected Homito response shape.\")\nprint(json.dumps({\"count\": len(data[\"properties\"]), \"hasMore\": data[\"nextCursor\"] is not None}))\n```\n\nA successful empty result is `{\"properties\":[],\"nextCursor\":null}`: the connection worked and this company has no properties to return. It is not an authentication error. For a non-empty result, take a returned property `id` and read `GET /api/v1/landlord/inventory/properties/{propertyId}` or `/{propertyId}/units`. Inspect the operation response schemas for fields and nullable values.\n\nFollow `nextCursor` until it is `null`, keeping the same list operation and filters. Use cursors only with the same company and list operation. Import previews, jobs and their history belong to the API key that created them, including access by job ID. A green public `/health` response alone does not verify your key or company access.\n\n### 3. MCP distribution readiness\n\n**A REST API origin is configured. A verified public MCP installation is not currently offered by this reference.** Ask Homito for the approved exact package version and environment configuration when distribution is verified. Do not substitute a guessed version, a floating package tag or a repository checkout.\n\nListing synchronization, versioned public application intake, webhook registration and key management use their explicit REST or administrator flows.\n\n### 4. Write deliberately and read the result back\n\nStart with the existing two-step portfolio import: create an immutable preview, inspect its validity and blocking issues, then commit that preview with `{\"confirm\":true}`. Read `GET /api/v1/landlord/portfolio-imports/{importId}` to verify the durable result. Creating a preview also persists data and requires write permission.\n\nEvery landlord mutation requires an `Idempotency-Key` of 16–200 characters, using only ASCII letters, digits, periods, underscores, colons or hyphens, without surrounding whitespace. Create one key per logical operation and preserve the exact request body and key. Use a separate key for preview and commit. Successful responses have a **24-hour replay window**, scoped to the same API key and operation.\n\nAfter a lost response, read the resource or operation back if its returned ID is known. If no returned ID is known, retry the identical request with the original `Idempotency-Key` and original API key within 24 hours of the first attempt. If that window has elapsed or safe readback/replay is unavailable, stop and reconcile the outcome; neither reusing an expired key nor choosing a fresh key guarantees that a write will not run again. Import previews, jobs and their history remain bound to the key that created them.\n\n#### Edit an existing listing's name or unit text\n\nUse a unit ID returned by the company listing feed. With `write:properties`, send `PATCH /api/v1/landlord/listings/{unitId}/content` with an `Idempotency-Key` and this JSON body:\n\n```json\n{\"name\":\"Bright two-room apartment\",\"otherFacts\":\"Two rooms and a kitchen with a balcony.\"}\n```\n\nThe response is the same `{\"listing\": ...}` projection as the listing detail read. `name` and `otherFacts` are the only accepted fields; both are optional strings and trimmed, and at least one must be supplied. The limits are 200 and 10000 characters respectively, with a 64 KiB request-body cap. Omitted fields stay unchanged. Empty `name` removes the optional unit name. Empty `otherFacts` clears the unit text, so public `description` falls back to legacy unit `facts` and then the property's description. It does not erase those fallback sources. `null` and unknown fields are rejected.\n\nRead the result back and apply listing-change events as usual. Replays still require the key's current permission and ownership; a later denial does not undo an earlier successful operation. Different operation keys changing the same field follow last-writer semantics; `listingVersion` is not a write precondition here.\n\nMedia, publication, availability and private tenant fields have no path through this content operation. Their separate administration boundaries still apply. The content write, required semantic audit and replay result commit atomically. The audit records key/operation IDs and changed field names, without storing your credential or the advertisement text in that audit record.\n\nActivate an explicit listing delegation for the exact integration key in **Settings → API & agents**. The administrator signs in again with password, passkey or an eID method enabled in Homito and grants `media` and/or `publication` with an expiry. Activation uses the currently authenticated person's own company membership and configured publication trust. `createdBy`, wildcard permission, a replacement key or a person ID supplied by a client cannot replace that delegation. It can be read or revoked at the authenticated web-app control plane `/api/v1/settings/api-keys/{keyId}/listing-grant`; that address is not on the external API origin.\n\nEvery operation below requires `write:properties`, its delegated capability and a distinct `Idempotency-Key`. Keep the exact key and body after an interrupted response; replay rechecks current authority before returning a receipt.\n\n1. Send `POST /api/v1/landlord/listings/{unitId}/media/uploads` with `{\"images\":[{\"bytes\":12345,\"sha256\":\"<64 lowercase hexadecimal characters>\",\"mimeType\":\"image/png\"}]}`. Compute size and SHA-256 from the actual original bytes. Limits: ten images per reservation and five MiB per image. The reservation expires in fifteen minutes; a returned PUT URL lasts at most five minutes.\n2. PUT those exact bytes to the returned `upload.url`, with **every** returned `upload.headers` value and no Homito Authorization header. Use binary HTTP upload, reject redirects, and check the HTTP result before completion. This private staging object is not a listing image. Replaying the reservation does not extend its URLs; after expiry create a new reservation with a new operation key.\n3. Send `POST /api/v1/landlord/listings/{unitId}/media/uploads/{uploadId}/complete` with `{}` or `{\"setAsFront\":true}`. The server verifies actual length, SHA-256, MIME, decoding and pixel limits, writes a different immutable public image, then commits the gallery, audit, change journal, durable webhook intent and receipt together. Read the returned listing back. GIF and animated WebP may retain embedded metadata; completion does not promise complete metadata stripping.\n4. Send `PATCH /api/v1/landlord/listings/{unitId}/publication` with `{\"isPublic\":true,\"allocationMethod\":\"individual_assessment\",\"creditCheckMode\":\"without_credit_check\"}` to publish, or `{\"isPublic\":false}` to unpublish. Allocation can also be `first_come`. Maintenance, company freeze, round rules and the delegated person's configured publication trust still apply. Unpublishing keeps its existing publication-trust exemption and still needs a live key, delegation, person, membership and ownership. Arbitrary slugs, credit checks and private tenant fields are not accepted.\n\nFollow `listing.changed`/`listing.unpublished` notifications through the ordered changes feed. Abandoned raw uploads and unattached derived objects have durable scheduled cleanup. A successful write receipt records the mutation and delivery intent; verify actual webhook delivery separately.\n\nAfter an approved exact MCP distribution advertises them, `homito.reserve_listing_media`, `homito.complete_listing_media` and `homito.set_listing_publication` call these same REST operations with `reservation`, `completion` and `publication` objects respectively. Each also takes `unitId` and `idempotencyKey`; completion takes `uploadId`. Enable the ordinary local write gate; you approve each call in your MCP client before it is sent. The binary PUT remains a separate HTTP upload using the returned instructions.\n\nManage existing images with `PATCH /api/v1/landlord/listings/{unitId}/media`: `{\"removeUrls\":[\"<exact URL from the current gallery>\"],\"frontImageUrl\":\"<exact retained gallery URL>\"}`. Either field can be supplied separately; use `frontImageUrl:null` to clear the explicit front selection. The operation can only remove or select existing images, never import a new URL. Managed images removed from the gallery become eligible for fenced physical cleanup. The corresponding approved MCP tool is `homito.update_listing_gallery` with a `gallery` object and the ordinary write gates.\n\nVersioned application submission has a different contract: preserve its UUID `X-Application-Submission-Key`, receipt and upload keys. Follow the published receipt/progress operations before retrying. The landlord `Idempotency-Key` does not replace those capabilities.\n\n### 5. Handle errors and event delivery\n\nKeep the safe `requestId` or `X-Request-Id` for support, together with the operation and time. Keep credentials, applicant data and document URLs out of logs.\n\n| Response | Next action |\n| --- | --- |\n| 400 / 422 | Correct the request using the operation's schema and error code; do not retry unchanged invalid input. |\n| 401 | Stop and ask the administrator to check the missing, invalid, expired or revoked key. |\n| 403 | Check the required permission and company scope. Do not automatically request broader access. |\n| 404 | Check the returned resource ID and task. Another company's resource is not made accessible by changing an ID. |\n| 409 | Read the error code and current resource/preview/form version. Resolve the conflict before another mutation. |\n| 410 | Follow the operation's meaning: an expired sync cursor requires a new full sync; a removed application must not be recreated by an old retry. |\n| 429 | Honor `Retry-After` when supplied and `X-RateLimit-Reset`; apply bounded backoff with jitter. |\n| Timeout / temporary 5xx | Treat a write outcome as unknown. Use known-ID readback or the original-key replay within the 24-hour window, with bounded backoff. Do not create a fresh operation. |\n\nRegister only events from the current catalog: `application.submitted`, `application.intake_finalized`, `listing.changed`, `listing.unpublished`, `portfolio_import.completed`, `property.created`, `screening.started`, `unit.created`, `rent_roll_import.completed`, `fault_report.created`, `work_order.updated`, `commercial_inspection.created`, `commercial_inspection.updated`, `commercial_inspection.submitted`, `commercial_inspection.reviewed`.\n\nStore the signing secret when the webhook is created. `X-Homito-Signature` has the format `sha256=<64 lowercase hexadecimal digits>`. Verify HMAC-SHA256 over the **raw request body bytes**, using that secret and a constant-time comparison. Durably store and deduplicate `X-Homito-Event-Id` before returning 2xx. `X-Homito-Delivery` identifies a delivery; it is not the event deduplication key. Delivery is at least once; duplicates and different arrival order are possible. A notification does not prove that a later domain operation or a rental decision completed.\n\nFor listing full sync, retain the `syncCursor` from the **first bootstrap page** unchanged until every bootstrap page has been applied to a temporary dataset. Follow the bootstrap `nextCursor` through all pages; only then start `/api/v1/landlord/listings/changes` from that retained first cursor. Apply each change page atomically with its `nextCursor`; continue while `hasMore=true`. Replace the previous cache only after the full bootstrap and initial change replay succeed. Webhooks wake that change reader; periodic polling recovers missed notifications.\n\nRead delivery health at `GET /api/v1/landlord/webhooks/{webhookId}/deliveries` with `read:webhooks`. Use application receipt/progress and authorized application reads for their separate status checks.\n\n### 6. Know the boundary and retire credentials safely\n\n| Action | Available path | Human/portal boundary |\n| --- | --- | --- |\n| First company access; create, rotate or revoke a key | Authenticated administrator control plane | Existing verified company, user session and `settings.edit` required |\n| Ordinary authorized reads and supported writes | External REST API; supported MCP tools after verified distribution | No dashboard interaction required for each ordinary operation |\n| Edit advert name and unit text | Listing content PATCH; supported MCP tool after verified distribution | Requires current `write:properties`; media and publication require their separate explicit listing delegation |\n| Screening execution, Detective and operator casework | Separate StaySafe service | Homito's integration returns only the permitted certified landlord projection |\n| Decisions about applicants and inspection review | Their explicitly authorized decision/review operations | Key possession or an agent instruction does not replace human authority or separation of duties |\n\nFor rotation, create a replacement key with the same or narrower permissions, deploy it to the integration and verify an authenticated read. Before revoking the old key, finish or reconcile its outstanding previews and jobs using the old key. A replacement key does not inherit their job IDs or history. Then revoke the old key. The administrator uses **Settings → API & agents** or its authenticated `/api/v1/settings/api-keys` control plane. A company integration key is not an administrator session. Key IDs are non-secret references, not credentials; the raw key cannot be retrieved later. Verify that the retired key is rejected.\n\nKeep personal data, receipts and upload capabilities out of public listing caches. Tenant and application reads intentionally return minimized operational projections; do not infer missing private fields or screening conclusions. Keep nullable/unknown values distinct from zero or a completed result.\n\nUse the API version and lifecycle shown in the API reference, the schemas for each operation, and any required form or resource version when updating an integration. Preserve opaque versions unchanged and pin an approved MCP release. Event names come from the same catalog as the API; arrival order and a product version are not substitutes for current resource readback.\n\n### 7. Build a customer-hosted application flow\n\nUse the versioned REST intake when you host an application form on your own website. Start from the confirmed API origin in the connection guide. This flow is separate from landlord application reads and from MCP tools; a company key never stands in for the applicant's identity or consent.\n\n### 1. Load the current form before collecting an application.\n\nRead `GET /api/v1/public/units/{slug}/application-form?language=sv` (also `en` or `es`). Keep the returned `unitSlug`, `listingPeriodId` and opaque `formVersion`. Render the published `inputSchema`, conditional `rules`, `policies.confirmations`, document requirements and `identityGate`; do not recreate them from assumptions. Link the supplied privacy/terms paths through the confirmed Homito web-app origin, not the API origin. Check `canApply` and `unavailableReason`; reading a form does not create or reopen an application round.\n\nUse `POST /api/v1/public/units/{slug}/application-form/validate` for draft feedback. Draft validation checks the shared field rules, confirmations and declared document metadata against a read-only form snapshot. It creates no application or consent audit, needs no submission key, verifies no file bytes and starts no identity or screening provider call. The final submission is validated again.\n\n### 2. Keep each credential in its own role.\n\n| Credential | Purpose | Boundary |\n| --- | --- | --- |\n| `X-Homito-Customer-Key` | A separate server key with `write:applications` for the customer's shared intake budget and hosted eID handoff | Server only; same company as the advertised unit; does not replace applicant capabilities |\n| `X-Application-Submission-Key` | One UUID v4 generated before the first submission | Keep the same key and accepted request body/files after a lost response; it is not a landlord `Idempotency-Key` |\n| `X-Application-Receipt` | JSON containing `kind: \"public\"`, the original unit slug as `target`, and the original submission key as `key` | Send in the receipt header, never a URL; it proves only commit existence and attachment state |\n| `X-Application-Upload-Key` | A separate capability generated from 32 cryptographically random bytes encoded as 64 lowercase hexadecimal characters | Required for manifest upload operations; a receipt, application ID or company key cannot replace it |\n\nThe customer key changes the shared company traffic budget; it does not grant another company's access or replace receipt/upload permissions. An invalid supplied key fails closed instead of falling back to public access. Keep company keys on the server and all capabilities out of public caches, URLs, logs and agent conversations. Preserve them in the visitor's protected form session before the first network request.\n\n### 3. Complete the required identity handoff, then submit once.\n\nWhen `identityGate.required` is true, use the published hosted eID handoff. An administrator first registers the customer's exact HTTPS callback through the existing authenticated control plane. On the customer server, bind random `state`, a private PKCE verifier and its `S256` challenge to the current visitor's protected form session, the current form/round and the original submission key. Create the handoff at `POST /api/v1/public/units/{slug}/application-eid/handoffs` using the same company's server key and the returned form contract.\n\nPersist the handoff state before redirecting to the returned authorization URL and honor its `expiresAt`. At the registered callback, validate `state` against that same visitor's session; a global state lookup is insufficient. Keep the code/verifier private, suppress callback query logging and redirect immediately to a clean form URL. A key, account, `hasNoPersonalNumber` flag or client assertion cannot bypass required eID.\n\nSubmit `POST /api/v1/applications` as `multipart/form-data` with `X-Homito-Application-Contract: 1` and the original `X-Application-Submission-Key`. Send an accurate `Content-Length`; a missing or mismatched length is rejected. Include `unitSlug`, `listingPeriodId`, `formVersion` and the JSON `application` fields. Where required, send the separate `identityHandoff` JSON field containing `handoffId`, `code` and `codeVerifier`; never put it inside `application` or expose the verifier to browser code. For a handoff-backed submission, also send the exact original customer key that created the handoff; another key for the same company cannot substitute. Legacy JSON intake does not provide this versioned contract.\n\nUse the form's `documents.maxExternalBodyBytes` for the whole multipart request. Inline files use the published attachment fields; larger documents use `attachmentManifest` with no inline files and the separate upload key. Follow `documents.manifestSchema`, `maxFiles`, `maxFileBytes`, `allowedMimeTypes` and `acceptedByteFormats`, including the requirements for the main applicant and every co-applicant. A manifest declares intended files; it is not received evidence.\n\n### 4. Read the receipt before deciding what to retry.\n\nRead `GET /api/v1/applications/receipt` with the original receipt header. `received` means the application committed; inspect its separate `attachments` state rather than creating another submission. An identical committed retry returns the original receipt before rechecking a consumed or expired one-use identity proof. `unknown` can mean not sent, still processing or rolled back: use bounded backoff and, when retrying, the identical request with the original key. `removed` is terminal; stop old retries. Receipt reads grant no applicant profile, document download, screening result or decision rights. `notifications: unknown` is not proof of email delivery.\n\n### 5. Upload declared bytes and finalize.\n\nAll four operations below require the original `X-Application-Upload-Key`. Preserve every manifest upload ID and the original file bytes/hash across interruption.\n\n| Operation | What it confirms |\n| --- | --- |\n| `GET /api/v1/applications/{applicationId}/uploads` | Current `finalized` flag and each declared file's `pending`, `received`, `expired` or `stale` state |\n| `POST /api/v1/applications/{applicationId}/uploads/{uploadId}/url` | A short-lived PUT URL and exact headers, or an already-`received` result that needs no PUT |\n| `POST /api/v1/applications/{applicationId}/uploads/{uploadId}/complete` | Actual bytes, length, SHA-256, byte format/MIME and current subject binding were checked and the attachment committed |\n| `POST /api/v1/applications/{applicationId}/finalize` | All declared documents are committed in the ordinary document store; otherwise the operation is refused |\n\nUpload only to the exact returned URL with its exact method, headers and byte length. Never send the company key or applicant capabilities to object storage, follow redirects or log the signed URL. A successful PUT alone is not completion. A customer-server upload proxy avoids assuming that direct browser-to-storage CORS is configured.\n\nAfter a lost PUT response, try `complete` for the same upload ID before uploading again. On `upload_missing`, obtain another URL for that same ID, upload the original bytes and complete it. Refreshing an expired PUT URL does not renew the underlying upload capability. Stop at expired capability or changed applicant/round scope; changing a file or person requires the explicitly authorized correction/completion flow, not a new submission key or a modified accepted manifest.\n\n### Recover by error code, without creating a second application.\n\n| Failure | Next action |\n| --- | --- |\n| `eid_required` (403) | Complete the approved hosted identity flow; do not invent a bypass |\n| `form_version_changed` / `application_round_changed` (409) | Reload the current contract and ask the applicant to confirm changed information before a new accepted submission; preserve any existing receipt |\n| `submission_payload_changed` (409) | Reconcile the original accepted body/files; do not automatically create another operation |\n| `upload_subject_changed` (409), stale or expired upload access | Stop upload/finalization and use the authorized completion path for the current subject |\n| `submission_removed` (410) | Stop retrying the removed submission |\n| File/format validation failure (400/411/413/415/422) | Correct the reported request or document issue before an authorized retry |\n| 429, 503 or a lost response | Honor `Retry-After` when supplied, retain the checkpoint and read receipt/progress before an original-key retry |\n\n`application.submitted` and `application.intake_finalized` are separate webhook events. Verify/deduplicate them as described in the webhook guide and use receipt/progress for current state. Neither an event nor finalization asserts email delivery, a rental decision or a completed screening. Keep applicant data and upload/receipt capabilities outside public listing caches.\n","x-mcp":{"distributionVerified":false},"x-lifecycle":"stable","x-webhook-events":["application.submitted","application.intake_finalized","listing.changed","listing.unpublished","portfolio_import.completed","property.created","screening.started","unit.created","rent_roll_import.completed","fault_report.created","work_order.updated","commercial_inspection.created","commercial_inspection.updated","commercial_inspection.submitted","commercial_inspection.reviewed"]},"servers":[{"url":"https://h2nf8ee4ch.execute-api.eu-north-1.amazonaws.com","description":"API Server"}],"components":{"securitySchemes":{"bearerAuth":{"type":"http","scheme":"bearer","bearerFormat":"JWT"},"apiKeyAuth":{"type":"apiKey","in":"header","name":"Authorization","description":"Use format: Bearer hmt_live_xxxxxxxxxxxxx"}},"schemas":{"ErrorResponse":{"type":"object","properties":{"error":{"$ref":"#/components/schemas/ApiErrorObject"},"requestId":{"type":"string","deprecated":true,"description":"Deprecated copy of error.requestId for clients written against the earlier envelope. Read error.requestId."}},"required":["error"],"description":"The error envelope of every 4xx and 5xx response of the Homito External API."},"ApiErrorObject":{"type":"object","properties":{"code":{"type":"string","description":"Stable machine-readable code, for example validation_failed, resource_not_found or rate_limit_exceeded. Branch on this, never on message. New codes can appear; treat an unknown code by its HTTP status.","example":"resource_not_found"},"message":{"type":"string","description":"Human-readable explanation. The wording can change; do not parse it.","example":"Property not found"},"details":{"type":"object","additionalProperties":{},"description":"Code-specific context. validation_failed: issues[], each with path, code and message. rate_limit_exceeded: limit, window and resetAt. insufficient_permissions: required."},"fieldErrors":{"type":"object","additionalProperties":{"type":"array","items":{"type":"string"}},"description":"validation_failed only: messages per dotted field path, for example events.1. A failure of the whole body is reported under body (the versioned application intake uses application)."},"requestId":{"type":"string","description":"The X-Request-Id of this response. Quote it to Homito support.","example":"6e6f8c83-69d0-40b2-832a-152d0172d1b6"}},"required":["code","message","requestId"]},"ApplicationEidHandoffRequest":{"type":"object","properties":{"listingPeriodId":{"type":"string","format":"uuid"},"formVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"callbackRegistrationId":{"type":"string","format":"uuid"},"state":{"type":"string","minLength":32,"maxLength":256,"pattern":"^[A-Za-z0-9_-]+$"},"codeChallenge":{"type":"string","minLength":43,"maxLength":43,"pattern":"^[A-Za-z0-9_-]{42}[AEIMQUYcgkosw048]$","description":"Canonical unpadded base64url encoding of exactly 32 bytes"},"codeChallengeMethod":{"type":"string","enum":["S256"]}},"required":["listingPeriodId","formVersion","callbackRegistrationId","state","codeChallenge","codeChallengeMethod"],"additionalProperties":false},"Webhook":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"url":{"type":"string","format":"uri"},"events":{"type":"array","items":{"type":"string"}},"description":{"type":["string","null"]},"active":{"type":["boolean","null"]},"lastSuccessAt":{"type":["string","null"],"format":"date-time"},"lastFailureAt":{"type":["string","null"],"format":"date-time"},"failureCount":{"type":["integer","null"],"minimum":0},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","url","events","description","active","lastSuccessAt","lastFailureAt","failureCount","createdAt","updatedAt"]},"ApiKeySummary":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"keyPrefix":{"type":"string"},"status":{"type":"string","enum":["active","expired","revoked"]},"permissions":{"type":"array","items":{"type":"string"}},"lastUsedAt":{"type":["string","null"],"format":"date-time"},"expiresAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"revokedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","keyPrefix","status","permissions","lastUsedAt","expiresAt","createdAt"]}},"parameters":{}},"paths":{"/api/v1/users/me":{"get":{"tags":["Users"],"summary":"Get current user","description":"Retrieve the authenticated user's profile","security":[{"bearerAuth":[]}],"responses":{"200":{"description":"User profile","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":["string","null"],"format":"uuid"},"email":{"type":"string","format":"email"},"displayName":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":["string","null"]},"avatar":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"status":{"type":"object","properties":{"isApproved":{"type":"boolean"},"emailVerified":{"type":"boolean"},"lastLogin":{"type":["string","null"],"format":"date-time"}},"required":["isApproved","emailVerified"]},"createdAt":{"type":["string","null"],"format":"date-time"},"company":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"orgNumber":{"type":["string","null"]}},"required":["id","name"]}},"required":["id","email","displayName","firstName","lastName","roles","status"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Users"],"summary":"Update current user","description":"Update basic profile fields for the authenticated user","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"firstName":{"type":"string","minLength":1,"maxLength":100},"lastName":{"type":"string","minLength":1,"maxLength":100},"phone":{"type":"string","minLength":3,"maxLength":30},"avatar":{"type":"string","format":"uri"}}}}}},"responses":{"200":{"description":"Updated user","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"companyId":{"type":["string","null"],"format":"uuid"},"email":{"type":"string","format":"email"},"displayName":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"phone":{"type":["string","null"]},"avatar":{"type":["string","null"]},"roles":{"type":"array","items":{"type":"string"}},"status":{"type":"object","properties":{"isApproved":{"type":"boolean"},"emailVerified":{"type":"boolean"},"lastLogin":{"type":["string","null"],"format":"date-time"}},"required":["isApproved","emailVerified"]},"createdAt":{"type":["string","null"],"format":"date-time"},"company":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"orgNumber":{"type":["string","null"]}},"required":["id","name"]}},"required":["id","email","displayName","firstName","lastName","roles","status"]}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"User not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/receipt":{"get":{"tags":["Applications"],"summary":"Read commit existence with a possession-only submission receipt","description":"Does not authorize application, document, identity, screening or decision access. Unknown may be in flight. Removed cannot be retried.","parameters":[{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","maxLength":1024,"description":"JSON {kind:\"public\",target:unitSlug,key:UUID-v4}; never put the key in a URL"},"required":true,"description":"JSON {kind:\"public\",target:unitSlug,key:UUID-v4}; never put the key in a URL","name":"x-application-receipt","in":"header"}],"responses":{"200":{"description":"Commit existence and separate attachment state","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"state":{"type":"string","enum":["unknown"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["removed"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["received"]},"applicationId":{"type":"string","format":"uuid"},"attachments":{"type":"string","enum":["pending","complete","partial","unknown"]},"notifications":{"type":"string","enum":["unknown"]}},"required":["state","applicationId","attachments","notifications"]}]}}}},"400":{"description":"Invalid receipt","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Customer permission or company scope denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{applicationId}/uploads":{"get":{"tags":["Applications"],"summary":"Read declared upload progress","description":"Separate applicant upload capability required. Submission receipts and application IDs do not grant upload or document access. Preserve upload IDs across retries; never put credentials in URLs.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"applicationId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"uploadId","in":"path"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"},"required":true,"name":"x-application-upload-key","in":"header"}],"responses":{"200":{"description":"Authoritative committed state","content":{"application/json":{"schema":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"finalized":{"type":"boolean"},"attachments":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"documentType":{"type":"string"},"belongsTo":{"type":"string"},"state":{"type":"string","enum":["received","pending","expired","stale"]}},"required":["id","documentType","belongsTo","state"]}}},"required":["applicationId","listingPeriodId","finalized","attachments"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Upload access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Upload absent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Pending or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"File mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable; reread progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{applicationId}/uploads/{uploadId}/url":{"post":{"tags":["Applications"],"summary":"Refresh a PUT URL for the same declared upload","description":"Separate applicant upload capability required. Submission receipts and application IDs do not grant upload or document access. Preserve upload IDs across retries; never put credentials in URLs.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"applicationId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"uploadId","in":"path"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"},"required":true,"name":"x-application-upload-key","in":"header"}],"responses":{"200":{"description":"Authoritative committed state","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["received"]}},"required":["id","state"]},{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["pending"]},"method":{"type":"string","enum":["PUT"]},"url":{"type":"string","format":"uri"},"expiresIn":{"type":"integer"},"headers":{"type":"object","properties":{"Content-Type":{"type":"string","enum":["application/octet-stream"]},"x-amz-server-side-encryption":{"type":"string","enum":["AES256"]}},"required":["Content-Type","x-amz-server-side-encryption"]}},"required":["id","state","method","url","expiresIn","headers"]}]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Upload access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Upload absent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Pending or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"File mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable; reread progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{applicationId}/uploads/{uploadId}/complete":{"post":{"tags":["Applications"],"summary":"Verify bytes and commit one attachment idempotently","description":"Separate applicant upload capability required. Submission receipts and application IDs do not grant upload or document access. Preserve upload IDs across retries; never put credentials in URLs.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"applicationId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"uploadId","in":"path"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"},"required":true,"name":"x-application-upload-key","in":"header"}],"responses":{"200":{"description":"Authoritative committed state","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["received"]}},"required":["id","state"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Upload access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Upload absent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Pending or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"File mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable; reread progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{applicationId}/finalize":{"post":{"tags":["Applications"],"summary":"Finalize only after all declared evidence was committed","description":"Separate applicant upload capability required. Submission receipts and application IDs do not grant upload or document access. Preserve upload IDs across retries; never put credentials in URLs.","parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"applicationId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"uploadId","in":"path"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$"},"required":true,"name":"x-application-upload-key","in":"header"}],"responses":{"200":{"description":"Authoritative committed state","content":{"application/json":{"schema":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"state":{"type":"string","enum":["finalized"]}},"required":["applicationId","state"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Upload access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Upload absent","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Pending or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Expired","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"File mismatch","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable; reread progress","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications":{"post":{"tags":["Applications"],"summary":"Submit public application","description":"Legacy JSON keeps its existing contract. Shared versioned intake uses multipart, X-Homito-Application-Contract: 1 and UUID-v4 X-Application-Submission-Key. Preserve listingPeriodId/formVersion and retry identical content under the same key after reading the receipt. Contract 1 accepts a separate identityHandoff JSON field from a company-authenticated customer server after a registered hosted ceremony. When APPLICATION_EID_GATE is required, a new submission without a valid matching proof is refused with 403 eid_required, independently of provider readiness. Legacy JSON has no handoff capability. Identical committed retries return the original receipt before rechecking the one-use proof.","parameters":[{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","enum":["1"]},"required":false,"name":"x-homito-application-contract","in":"header"},{"schema":{"type":"string","pattern":"^[a-f0-9]{64}$","description":"Required for manifest mode: generate 32 random bytes; separate from submission receipt"},"required":false,"description":"Required for manifest mode: generate 32 random bytes; separate from submission receipt","name":"x-application-upload-key","in":"header"},{"schema":{"type":"string","description":"Required UUID v4 for contract 1; reuse for identical retries"},"required":false,"description":"Required UUID v4 for contract 1; reuse for identical retries","name":"x-application-submission-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"unitSlug":{"type":"string","minLength":1},"application":{"type":"object","properties":{"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"personalNumber":{"type":"string","minLength":1},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string","minLength":1},"phone":{"type":"string","minLength":1},"email":{"type":"string","format":"email"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"integer","minimum":1,"maximum":20},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"personalNumber":{"type":"string","minLength":1},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string","minLength":1},"age":{"type":"integer","minimum":0,"maximum":120},"contributesToIncome":{"type":"boolean"},"incomeSource":{"type":"string","enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other"]},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName","age"]},"maxItems":19},"nationality":{"type":"string"},"idNumber":{"type":"string"},"primaryIncomeSource":{"type":["string","null"],"enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other",null]},"monthlyGrossIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0,"maximum":1000000},"nonSmoker":{"type":"boolean"},"noPets":{"type":"boolean"},"numberOfChildren":{"type":"integer","minimum":0,"maximum":15},"childrenAges":{"type":"array","items":{"type":"integer","minimum":0,"maximum":120},"maxItems":15},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"}}},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":100},"relation":{"type":"string","minLength":2,"maxLength":50},"phone":{"type":"string"},"email":{"anyOf":[{"type":"string","maxLength":100,"format":"email"},{"type":"string","enum":[""]}]}},"required":["name","relation","phone"]},"maxItems":5},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"}},"required":["firstName","lastName","phone","email","householdSize","numberOfChildren","gdprConsent"]}},"required":["unitSlug","application"]}},"multipart/form-data":{"schema":{"type":"object","properties":{"unitSlug":{"type":"string"},"listingPeriodId":{"type":"string","format":"uuid"},"formVersion":{"type":"string"},"application":{"type":"string","description":"JSON matching application-form inputSchema"},"identityHandoff":{"type":"string","description":"Separate JSON: {handoffId,code,codeVerifier} from the hosted handoff; requires the same customer key. Excluded from the payload hash; keep it on your server."},"attachmentManifest":{"type":"string","description":"JSON matching application-form documents.manifestSchema; alternative to inline files"},"attachments[0]":{"type":"string","format":"binary"},"attachmentTypes[0]":{"type":"string"},"attachmentBelongsTo[0]":{"type":"string"}},"required":["unitSlug","listingPeriodId","formVersion","application"],"additionalProperties":{}}}}},"responses":{"200":{"description":"Identical replay receipt","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"state":{"type":"string","enum":["unknown"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["removed"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["received"]},"applicationId":{"type":"string","format":"uuid"},"attachments":{"type":"string","enum":["pending","complete","partial","unknown"]},"notifications":{"type":"string","enum":["unknown"]}},"required":["state","applicationId","attachments","notifications"]}]}}}},"201":{"description":"Application created","content":{"application/json":{"schema":{"anyOf":[{"type":"object","properties":{"success":{"type":"boolean"},"application":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"invitationId":{"type":"string","format":"uuid"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"},"householdAnswersReceivedAt":{"type":"object","properties":{"pets":{"type":"string","format":"date-time"},"smoking":{"type":"string","format":"date-time"}},"description":"Per question, when Homito received an explicit yes or no at intake (ISO 8601). Set by the server only; a key that is absent was not answered explicitly."}}},"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"profileImageUrl":{"type":"string","format":"uri"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"previousAddresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"}},"required":["address","fromDate","toDate"]}},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"number"},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","description":"Co-applicant has no Swedish personal number; birthDate identifies them"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"string","format":"date-time"}]},"age":{"type":"number"},"contributesToIncome":{"type":"boolean"},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName","age"]}},"nationality":{"type":"string"},"idNumber":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"monthlyIncome":{"type":"number"},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0},"nonSmoker":{"type":["boolean","null"]},"noPets":{"type":["boolean","null"]},"numberOfChildren":{"type":"number"},"childrenAges":{"type":"array","items":{"type":"string"}},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string","format":"date-time"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"relation":{"type":"string"}},"required":["name","phone","relation"]}},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"},"gdprConsentedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","screening","approved","offered","accepted","rejected","withdrawn"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","unitId","applicationSource","firstName","lastName","phone","email","status","createdAt","updatedAt"]}},"required":["success","application"]},{"type":"object","properties":{"state":{"type":"string","enum":["unknown"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["removed"]}},"required":["state"]},{"type":"object","properties":{"state":{"type":"string","enum":["received"]},"applicationId":{"type":"string","format":"uuid"},"attachments":{"type":"string","enum":["pending","complete","partial","unknown"]},"notifications":{"type":"string","enum":["unknown"]}},"required":["state","applicationId","attachments","notifications"]}]}}}},"400":{"description":"Validation error (validation_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Electronic identification required (eid_required), or customer permission/company scope denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Changed payload, form/policy/round, unavailable unit or duplicate","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Submission was removed; no retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"411":{"description":"Content-Length required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Body limit exceeded","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"Wrong content type","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Rejected attachment","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable; reread receipt before retry","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Applications"],"summary":"List applications","description":"Fetch applications for a specific unit or property. Requires authentication. Screening scores are included only from server-verified certified frozen reports.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"unitId","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"}],"responses":{"200":{"description":"Applications retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"applications":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"publishedScreening":{"type":"object","properties":{"screeningId":{"type":"string","format":"uuid"},"generation":{"type":"integer","exclusiveMinimum":0},"screeningTier":{"type":"string","enum":["advanced","premium"]},"publicationId":{"type":"string"},"basis":{"type":"string","enum":["certified","manual"]},"snapshotAt":{"type":"string","format":"date-time"},"finalScore":{"type":["number","null"],"minimum":0,"maximum":100},"profileScore":{"type":["number","null"],"minimum":0,"maximum":100},"financeScore":{"type":["number","null"],"minimum":0,"maximum":100},"securityScore":{"type":["number","null"],"minimum":0,"maximum":100},"decisionThresholds":{"type":["object","null"],"properties":{"approveAt":{"type":"number"},"reviewAt":{"type":"number"}},"required":["approveAt","reviewAt"]},"reviewBasis":{"type":["string","null"],"enum":["findings","verification_incomplete",null]},"report":{"type":"object","properties":{"reportId":{"type":"string"},"status":{"type":"string","enum":["certified","manual"]},"downloadUrl":{"type":"string"}},"required":["reportId","status","downloadUrl"]}},"required":["screeningId","generation","screeningTier","publicationId","basis","snapshotAt","finalScore","profileScore","financeScore","securityScore","decisionThresholds","reviewBasis","report"],"description":"Last authenticated immutable publication; independent of current screening run status and never used for writes or charges."},"leaseId":{"type":"string","format":"uuid"},"applicantName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"status":{"type":"string","enum":["pending","screening","approved","offered","accepted","rejected","withdrawn","in_review"]},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"monthlyIncome":{"type":"number"},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0},"livingArrangement":{"type":"string"},"occupation":{"type":"string"},"employer":{"type":"string"},"householdSize":{"type":"number"},"createdAt":{"type":["string","null"],"format":"date-time"},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"}},"required":["id","propertyName"]},"screening":{"type":"object","properties":{"finalScore":{"type":"number","minimum":0,"maximum":100,"description":"Certified frozen landlord score; 0 is a valid score."},"scoreCertification":{"type":"string","enum":["certified"]},"historicalScores":{"type":"object","properties":{"basis":{"type":"string","enum":["historical_reviewed"]},"screeningId":{"type":"string","format":"uuid"},"reviewedAt":{"type":"string","format":"date-time"},"finalScore":{"type":["number","null"],"minimum":0,"maximum":100},"profileScore":{"type":["number","null"],"minimum":0,"maximum":100},"financeScore":{"type":["number","null"],"minimum":0,"maximum":100},"securityScore":{"type":["number","null"],"minimum":0,"maximum":100}},"required":["basis","screeningId","reviewedAt","finalScore","profileScore","financeScore","securityScore"]},"status":{"type":"string"},"completedAgents":{"type":"number","description":"Completed screening agent runs — counts only, never run payloads."},"totalAgents":{"type":"number","description":"Total counted screening agent runs for the current generation."},"decisionThresholds":{"type":"object","properties":{"approveAt":{"type":"number","minimum":0,"maximum":100},"reviewAt":{"type":"number","minimum":0,"maximum":100}},"required":["approveAt","reviewAt"],"description":"Governed decision boundary for this row — the certified report's frozen thresholds when present, otherwise the live approved policy."},"basicAssessment":{"oneOf":[{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["homito-bas-assessment/v1"]},"requirements":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"status":{"type":"string","enum":["met","partial","not_met","unknown"]},"severity":{"type":"string","enum":["hard"]},"exemption":{"type":"string","enum":["assistance_dog"]}},"required":["code","status","severity"]}},"requirementSummary":{"type":"object","properties":{"met":{"type":"number"},"partial":{"type":"number","default":0},"notMet":{"type":"number"},"unknown":{"type":"number"},"total":{"type":"number"}},"required":["met","notMet","unknown","total"]},"finance":{"type":"object","properties":{"rent":{"type":"number"},"totalNetIncome":{"type":["number","null"]},"incomeRatio":{"type":"number"},"threshold":{"type":"number"},"kalp":{"type":"object","properties":{"status":{"type":"string","enum":["surplus","deficit","unavailable"]},"resultSek":{"type":"number"},"totalNetIncomeSek":{"type":["number","null"]},"rentSek":{"type":"number"},"declaredCommitmentsSek":{"type":["number","null"]},"commitmentsEvidence":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["provided"]},"source":{"type":"string","enum":["applicant_declared"]}},"required":["status","source"]},{"type":"object","properties":{"status":{"type":"string","enum":["missing","invalid"]},"source":{"type":"string","enum":["applicant_declared"]},"recommendedAction":{"type":"string","enum":["confirm_monthly_commitments"]}},"required":["status","source","recommendedAction"]}]},"householdNormalAmountSek":{"type":["number","null"]},"missingInputs":{"type":"array","items":{"type":"string","enum":["income","rent","declared_commitments","household"]}},"estimate":{"type":"boolean","enum":[true]},"policyVersion":{"type":"string","enum":["homito-bas-kalp/2026.1","homito-bas-kalp/2026.2","homito-bas-kalp/2026.3","homito-bas-kalp/2026.4"]},"policySource":{"type":"string","enum":["KFMFS 2025:1"]}},"required":["status","totalNetIncomeSek","declaredCommitmentsSek","householdNormalAmountSek","missingInputs","estimate","policyVersion","policySource"],"additionalProperties":false}},"required":["totalNetIncome","threshold","kalp"],"additionalProperties":false},"completenessV2":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100},"classes":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","enum":["obligatorisk","rekommenderad","frivillig"]},"delivered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"weightDelivered":{"type":"integer","minimum":0},"weightTotal":{"type":"integer","minimum":0}},"required":["class","delivered","total","weightDelivered","weightTotal"],"additionalProperties":false}},"items":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"class":{"type":"string","enum":["obligatorisk","rekommenderad","frivillig"]},"category":{"type":"string","minLength":1},"delivered":{"type":"boolean"},"countedWeight":{"type":"integer","minimum":0}},"required":["code","class","category","delivered","countedWeight"],"additionalProperties":false}},"missing":{"type":"array","items":{"type":"string"}},"source":{"type":"string","enum":["requested_documents","product_default"]},"setVersions":{"type":"object","properties":{"company":{"type":"integer","minimum":0},"property":{"type":"integer","minimum":0},"unit":{"type":"integer","minimum":0}},"additionalProperties":false}},"required":["score","classes","items","missing","source","setVersions"],"additionalProperties":false},"decisionSupportOnly":{"type":"boolean","enum":[true]},"completeness":{"type":"object","properties":{"completed":{"type":"number"},"total":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["contact","identity_data","household","employment","income","declared_commitments","identity_document","selfie","income_document"]},"status":{"type":"string","enum":["present","missing"]}},"required":["code","status"]}},"missing":{"type":"array","items":{"type":"string","enum":["contact","identity_data","household","employment","income","declared_commitments","identity_document","selfie","income_document"]}}},"required":["completed","total","items","missing"]},"summary":{"type":"object","properties":{"positive":{"type":"array","items":{"type":"string","enum":["requirements_met","requirements_partial","requirements_not_met","requirements_unknown","kalp_surplus","kalp_deficit","kalp_unavailable","identity_evidence_present","application_complete","application_incomplete","identity_data_missing","identity_document_missing","selfie_missing","income_document_missing","employment_missing"]}},"attention":{"type":"array","items":{"type":"string","enum":["requirements_met","requirements_partial","requirements_not_met","requirements_unknown","kalp_surplus","kalp_deficit","kalp_unavailable","identity_evidence_present","application_complete","application_incomplete","identity_data_missing","identity_document_missing","selfie_missing","income_document_missing","employment_missing"]}}},"required":["positive","attention"],"description":"Bas summary codes. selfie_missing appears only for an applicant who consented to face comparison and sent no selfie; without that consent the selfie is not asked for, and identity_evidence_present rests on the identity data and the ID document."}},"required":["schemaVersion","requirements","requirementSummary","finance","decisionSupportOnly"]},{"type":"object","properties":{"schemaVersion":{"type":"string","enum":["homito-bas-assessment/v2"]},"requirements":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"status":{"type":"string","enum":["met","partial","not_met","unknown"]},"severity":{"type":"string","enum":["hard"]},"exemption":{"type":"string","enum":["assistance_dog"]}},"required":["code","status","severity"]}},"requirementSummary":{"type":"object","properties":{"met":{"type":"number"},"partial":{"type":"number","default":0},"notMet":{"type":"number"},"unknown":{"type":"number"},"total":{"type":"number"}},"required":["met","notMet","unknown","total"]},"finance":{"type":"object","properties":{"rent":{"type":"number"},"totalNetIncome":{"type":["number","null"]},"incomeRatio":{"type":"number"},"threshold":{"type":"number"},"kalp":{"type":"object","properties":{"status":{"type":"string","enum":["surplus","deficit","unavailable"]},"resultSek":{"type":"number"},"totalNetIncomeSek":{"type":["number","null"]},"rentSek":{"type":"number"},"declaredCommitmentsSek":{"type":["number","null"]},"commitmentsEvidence":{"anyOf":[{"type":"object","properties":{"status":{"type":"string","enum":["provided"]},"source":{"type":"string","enum":["applicant_declared"]}},"required":["status","source"]},{"type":"object","properties":{"status":{"type":"string","enum":["missing","invalid"]},"source":{"type":"string","enum":["applicant_declared"]},"recommendedAction":{"type":"string","enum":["confirm_monthly_commitments"]}},"required":["status","source","recommendedAction"]}]},"householdNormalAmountSek":{"type":["number","null"]},"missingInputs":{"type":"array","items":{"type":"string","enum":["income","rent","declared_commitments","household"]}},"estimate":{"type":"boolean","enum":[true]},"policyVersion":{"type":"string","enum":["homito-bas-kalp/2026.1","homito-bas-kalp/2026.2","homito-bas-kalp/2026.3","homito-bas-kalp/2026.4"]},"policySource":{"type":"string","enum":["KFMFS 2025:1"]}},"required":["status","totalNetIncomeSek","declaredCommitmentsSek","householdNormalAmountSek","missingInputs","estimate","policyVersion","policySource"],"additionalProperties":false}},"required":["totalNetIncome","threshold","kalp"],"additionalProperties":false},"completenessV2":{"type":"object","properties":{"score":{"type":"integer","minimum":0,"maximum":100},"classes":{"type":"array","items":{"type":"object","properties":{"class":{"type":"string","enum":["obligatorisk","rekommenderad","frivillig"]},"delivered":{"type":"integer","minimum":0},"total":{"type":"integer","minimum":0},"weightDelivered":{"type":"integer","minimum":0},"weightTotal":{"type":"integer","minimum":0}},"required":["class","delivered","total","weightDelivered","weightTotal"],"additionalProperties":false}},"items":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"class":{"type":"string","enum":["obligatorisk","rekommenderad","frivillig"]},"category":{"type":"string","minLength":1},"delivered":{"type":"boolean"},"countedWeight":{"type":"integer","minimum":0}},"required":["code","class","category","delivered","countedWeight"],"additionalProperties":false}},"missing":{"type":"array","items":{"type":"string"}},"source":{"type":"string","enum":["requested_documents","product_default"]},"setVersions":{"type":"object","properties":{"company":{"type":"integer","minimum":0},"property":{"type":"integer","minimum":0},"unit":{"type":"integer","minimum":0}},"additionalProperties":false}},"required":["score","classes","items","missing","source","setVersions"],"additionalProperties":false},"decisionSupportOnly":{"type":"boolean","enum":[true]},"completeness":{"type":"object","properties":{"completed":{"type":"number"},"total":{"type":"number"},"items":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string","enum":["contact","identity_data","household","employment","income","declared_commitments","identity_document","selfie","income_document"]},"status":{"type":"string","enum":["present","missing"]}},"required":["code","status"]}},"missing":{"type":"array","items":{"type":"string","enum":["contact","identity_data","household","employment","income","declared_commitments","identity_document","selfie","income_document"]}}},"required":["completed","total","items","missing"]},"summary":{"type":"object","properties":{"positive":{"type":"array","items":{"type":"string","enum":["requirements_met","requirements_partial","requirements_not_met","requirements_unknown","kalp_surplus","kalp_deficit","kalp_unavailable","identity_evidence_present","application_complete","application_incomplete","identity_data_missing","identity_document_missing","selfie_missing","income_document_missing","employment_missing"]}},"attention":{"type":"array","items":{"type":"string","enum":["requirements_met","requirements_partial","requirements_not_met","requirements_unknown","kalp_surplus","kalp_deficit","kalp_unavailable","identity_evidence_present","application_complete","application_incomplete","identity_data_missing","identity_document_missing","selfie_missing","income_document_missing","employment_missing"]}}},"required":["positive","attention"],"description":"Bas summary codes. selfie_missing appears only for an applicant who consented to face comparison and sent no selfie; without that consent the selfie is not asked for, and identity_evidence_present rests on the identity data and the ID document."}},"required":["schemaVersion","requirements","requirementSummary","finance","decisionSupportOnly","completeness","summary"]}],"description":"Customer-safe Bas assessment projection (schemas homito-bas-assessment/v1 and v2) — requirement checks, KALP estimate with its terms and the state of each input (never the household or income records behind them) and, for v2, evidence completeness; decision support only."}},"required":["status"],"description":"Lifecycle metadata plus a score only when certified. Mutable row scores are omitted."}},"required":["id","applicantName","email","phone","status","createdAt","unit"]}},"total":{"type":"number"}},"required":["applications","total"]}}}},"400":{"description":"Missing query parameters","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{id}":{"get":{"tags":["Applications"],"summary":"Get application details","description":"Fetch a single application by id. Requires authentication. The screening result is omitted until a frozen landlord report is server-verified and certified; mutable working scores and AI data are never returned here.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Application retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"invitationId":{"type":"string","format":"uuid"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"},"householdAnswersReceivedAt":{"type":"object","properties":{"pets":{"type":"string","format":"date-time"},"smoking":{"type":"string","format":"date-time"}},"description":"Per question, when Homito received an explicit yes or no at intake (ISO 8601). Set by the server only; a key that is absent was not answered explicitly."}}},"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"previousAddresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"}},"required":["address","fromDate","toDate"]}},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"number"},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","description":"Co-applicant has no Swedish personal number"},"contributesToIncome":{"type":"boolean"},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName"]},"description":"The adult co-applicants. No age, birth date or child is returned; householdSize is the household's size."},"nationality":{"type":"string"},"idNumber":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"monthlyIncome":{"type":"number"},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0},"nonSmoker":{"type":["boolean","null"]},"noPets":{"type":["boolean","null"]},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string","format":"date-time"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"relation":{"type":"string"}},"required":["name","phone","relation"]}},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"},"gdprConsentedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","screening","approved","offered","accepted","rejected","withdrawn"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"identityEvidence":{"type":"object","properties":{"documentSubmitted":{"type":"boolean"},"selfieSubmitted":{"type":"boolean","description":"The selfie is voluntary: an applicant sends one only with their own consent to face comparison. false is a full answer, never missing evidence."}},"required":["documentSubmitted","selfieSubmitted"],"description":"Submission presence only; original identity media is operator-only."},"publishedScreening":{"type":"object","properties":{"screeningId":{"type":"string","format":"uuid"},"generation":{"type":"integer","exclusiveMinimum":0},"screeningTier":{"type":"string","enum":["advanced","premium"]},"publicationId":{"type":"string"},"basis":{"type":"string","enum":["certified","manual"]},"snapshotAt":{"type":"string","format":"date-time"},"finalScore":{"type":["number","null"],"minimum":0,"maximum":100},"profileScore":{"type":["number","null"],"minimum":0,"maximum":100},"financeScore":{"type":["number","null"],"minimum":0,"maximum":100},"securityScore":{"type":["number","null"],"minimum":0,"maximum":100},"decisionThresholds":{"type":["object","null"],"properties":{"approveAt":{"type":"number"},"reviewAt":{"type":"number"}},"required":["approveAt","reviewAt"]},"reviewBasis":{"type":["string","null"],"enum":["findings","verification_incomplete",null]},"report":{"type":"object","properties":{"reportId":{"type":"string"},"status":{"type":"string","enum":["certified","manual"]},"downloadUrl":{"type":"string"}},"required":["reportId","status","downloadUrl"]}},"required":["screeningId","generation","screeningTier","publicationId","basis","snapshotAt","finalScore","profileScore","financeScore","securityScore","decisionThresholds","reviewBasis","report"],"description":"Last authenticated immutable publication; independent of current screening run status and never used for writes or charges."},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":"string"},"propertyId":{"type":"string","format":"uuid"},"propertyName":{"type":"string"},"address":{"type":"string"},"rent":{"type":"number"},"rooms":{"type":"number"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Deprecated: always false since 2026-09-17; the criterion is no longer applied."},"onlyStudents":{"type":"boolean","description":"Deprecated: always false since 2026-09-17; the criterion is no longer applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number","description":"Deprecated: never set since 2026-09-17; the minimum age is a system requirement of 18."},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"}},"required":["id","propertyId","propertyName","address"]},"documents":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"documentType":{"type":"string","enum":["salary_specification","employment_contract","business_financial_statement","accountant_certificate","bank_statement","tax_return","student_finance_decision","pension_statement","unemployment_benefit","social_insurance_decision","guarantor_documentation"]},"documentName":{"type":"string"},"documentKey":{"type":"string"},"documentSize":{"type":"number"},"belongsTo":{"type":"string"},"personName":{"type":"string"},"uploadedAt":{"type":"string","format":"date-time"},"documentUrl":{"type":"string"}},"required":["id","documentType","documentName","documentKey","uploadedAt"]}},"screening":{"type":"object","properties":{"id":{"type":"string"},"status":{"type":"string"},"scoreCertification":{"type":"string","enum":["certified"],"description":"Present only when the landlord result comes from a server-verified certified frozen report."},"scores":{"type":"object","properties":{"finance":{"type":"number"},"security":{"type":"number"},"profile":{"type":"number"},"overall":{"type":"number"},"final":{"type":["number","null"]}}},"scoreSource":{"type":"string","enum":["human","none"],"description":"'human' when the scores are the operator's certified decision. No AI recommendation or AI-sourced score is published (GDPR art. 22)."},"humanDecision":{"type":"string","enum":["approve","review","reject"]},"riskLevel":{"type":"string","enum":["low","medium","high","critical"]},"completedAgents":{"type":"number"},"totalAgents":{"type":"number"},"reviewedBy":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"reviewedAt":{"type":"string","format":"date-time"}},"required":["id","name"]},"completedAt":{"type":"string","format":"date-time"}},"required":["id","status"],"description":"Certified frozen landlord screening result. Omitted while the report is missing, invalid, or finalized but not certified."}},"required":["id","unitId","applicationSource","firstName","lastName","phone","email","status","createdAt","updatedAt","unit","documents"]}}}},"404":{"description":"Application not found (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{id}/reject":{"post":{"tags":["Applications"],"summary":"Reject an application","description":"Records a person's decision to reject an application. Requires authentication with a role that may decide on applications. Runs the same decision as the Homito dashboard: in one transaction it rejects the application, rescinds any offer that still binds you, freezes the evidence the decision was made on, schedules the applicant's e-mail with your motivation and writes the decision trail with the authenticated account, the client and the attested human decision. A repeated call for an already rejected application changes nothing and answers 200 with alreadyRejected true.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"reasonCode":{"type":"string","enum":["requirement_not_met","ranked_below_principle","unit_let_to_other","listing_withdrawn","other"],"description":"The reason as a code. 'ranked_below_principle' is refused with 422 REASON_NOT_AVAILABLE unless an applicant ranked below this one has been picked."},"reason":{"type":"string","minLength":10,"maxLength":2000,"description":"The motivation in your own words, 10-2000 characters after trimming. Stored on the application, shown to the applicant in their portal and sent to them by e-mail."},"humanAssessment":{"type":"object","properties":{"decidedBy":{"type":"string","minLength":2,"maxLength":200,"description":"The person at your company who assessed this applicant and made the decision: name or work e-mail. Recorded in the decision trail."},"attestedIndividualAssessment":{"type":"boolean","enum":[true],"description":"Must be true: that person assessed this applicant individually, and the decision is theirs, not a score's or a rule's alone."}},"required":["decidedBy","attestedIndividualAssessment"],"additionalProperties":false,"description":"The human decision behind the rejection (GDPR art. 22). An integration may carry a decision; it may not make one."}},"required":["reasonCode","reason","humanAssessment"],"additionalProperties":false}}}},"responses":{"200":{"description":"Application rejected, or already rejected","content":{"application/json":{"schema":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["rejected"]},"alreadyRejected":{"type":"boolean","description":"True when the application was already rejected: nothing was changed, mailed or recorded again."},"reasonCode":{"type":"string","enum":["requirement_not_met","ranked_below_principle","unit_let_to_other","listing_withdrawn","other"]},"applicantNotified":{"type":"boolean","description":"Whether a rejection e-mail to the applicant was scheduled by this call."},"applicantMailScheduledFor":{"type":["string","null"],"format":"date-time"}},"required":["applicationId","status","alreadyRejected","applicantNotified","applicantMailScheduledFor"]}}}},"400":{"description":"Invalid payload: reasonCode, reason or humanAssessment missing or invalid (validation_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"The application belongs to another company (forbidden)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Application not found (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"The application was withdrawn, already accepted, or changed while the rejection was written: application_withdrawn, application_already_decided, application_offered or conflict. Nothing was changed.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The reason code is not available for this application (REASON_NOT_AVAILABLE)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/applications/{id}/review":{"put":{"tags":["Applications"],"summary":"Update application working status","description":"Moves an undecided application between pending and screening, or updates its household and previous addresses. Requires authentication. It makes no decision: 'approved' and 'rejected' are refused with 422 DECISION_REQUIRES_DECISION_ENDPOINT. Reject through POST /{id}/reject; approve in Homito. A decided application (offered, accepted or rejected) changes status only through its offer, its lease or its rejection, never here.","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["screening","pending"],"description":"New working status for the application. 'approved' and 'rejected' are decisions and are refused here with 422 DECISION_REQUIRES_DECISION_ENDPOINT: reject through POST /{id}/reject, approve in Homito. A decided application (offered, accepted or rejected) keeps its status: any other status is refused with 409 APPLICATION_STATUS_DECIDED."},"profileImageUrl":{"type":"string","format":"uri"},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","description":"Co-applicant has no Swedish personal number; birthDate identifies them"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"string","format":"date-time"}]},"age":{"type":"number"},"contributesToIncome":{"type":"boolean"},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName","age"]}},"previousAddresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"}},"required":["address","fromDate","toDate"]}}},"required":["status"]}}}},"responses":{"200":{"description":"Application updated, as GET /{id} gives it: personal numbers only past the applicant PII gate","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"invitationId":{"type":"string","format":"uuid"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"},"householdAnswersReceivedAt":{"type":"object","properties":{"pets":{"type":"string","format":"date-time"},"smoking":{"type":"string","format":"date-time"}},"description":"Per question, when Homito received an explicit yes or no at intake (ISO 8601). Set by the server only; a key that is absent was not answered explicitly."}}},"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"previousAddresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"}},"required":["address","fromDate","toDate"]}},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"number"},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","description":"Co-applicant has no Swedish personal number"},"contributesToIncome":{"type":"boolean"},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName"]},"description":"The adult co-applicants. No age, birth date or child is returned; householdSize is the household's size."},"nationality":{"type":"string"},"idNumber":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"monthlyIncome":{"type":"number"},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0},"nonSmoker":{"type":["boolean","null"]},"noPets":{"type":["boolean","null"]},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string","format":"date-time"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"relation":{"type":"string"}},"required":["name","phone","relation"]}},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"},"gdprConsentedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","screening","approved","offered","accepted","rejected","withdrawn"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","unitId","applicationSource","firstName","lastName","phone","email","status","createdAt","updatedAt"]}}}},"400":{"description":"Invalid update payload (validation_failed or PROFILE_IMAGE_DIRECT_WRITE_RETIRED)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Application not found (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Application lifecycle is closed, or the application is decided and keeps its status: APPLICATION_WITHDRAWN or APPLICATION_STATUS_DECIDED","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"The status is a decision ('approved' or 'rejected'): DECISION_REQUIRES_DECISION_ENDPOINT, with details.rejectEndpoint. Reject through POST /{id}/reject; approve in Homito.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/invitations":{"post":{"tags":["Invitations"],"summary":"Create tenant invitation","description":"Send an invitation to a potential tenant","security":[{"bearerAuth":[]}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"unitId":{"type":"string","format":"uuid"},"inviteeEmail":{"type":"string","format":"email"},"inviteePhone":{"type":"string"},"message":{"type":"string","maxLength":500},"expiresInDays":{"type":"integer","exclusiveMinimum":0,"maximum":90}},"required":["unitId"]}}}},"responses":{"201":{"description":"Invitation created successfully","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"invitation":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"invitedByUserId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"inviteeEmail":{"type":"string","format":"email"},"inviteePhone":{"type":"string"},"inviteCode":{"type":"string"},"message":{"type":"string"},"status":{"type":"string","enum":["pending","viewed","accepted","expired","cancelled"]},"expiresAt":{"type":"string","format":"date-time"},"viewedAt":{"type":"string","format":"date-time"},"acceptedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","invitedByUserId","unitId","inviteCode","status","expiresAt","createdAt","updatedAt"]}},"required":["success","invitation"]}}}},"400":{"description":"Invalid request data","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Invitations"],"summary":"List invitations","description":"Get invitations for a specific unit or property","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":false,"name":"unitId","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"}],"responses":{"200":{"description":"Invitations retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"invitations":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"inviteCode":{"type":"string"},"status":{"type":"string","enum":["pending","viewed","accepted","expired","cancelled"]},"inviteeEmail":{"type":"string","format":"email"},"inviteePhone":{"type":"string"},"message":{"type":"string"},"viewedAt":{"type":"string","format":"date-time"},"expiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"}},"required":["id","propertyName"]},"invitedBy":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]}},"required":["id","inviteCode","status","expiresAt","createdAt","unit","invitedBy"]}},"total":{"type":"number"}},"required":["invitations","total"]}}}},"401":{"description":"Unauthorized","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/invitations/{id}":{"get":{"tags":["Invitations"],"summary":"Get invitation details","description":"Fetch a single invitation by id","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invitation retrieved","content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"invitedByUserId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"inviteeEmail":{"type":"string","format":"email"},"inviteePhone":{"type":"string"},"inviteCode":{"type":"string"},"message":{"type":"string"},"status":{"type":"string","enum":["pending","viewed","accepted","expired","cancelled"]},"expiresAt":{"type":"string","format":"date-time"},"viewedAt":{"type":"string","format":"date-time"},"acceptedAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":"string"},"propertyId":{"type":"string","format":"uuid"},"propertyName":{"type":"string"},"address":{"type":"string"},"rent":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"frontImage":{"type":"string"}},"required":["id","propertyId","propertyName","address"]},"invitedBy":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"email":{"type":"string","format":"email"}},"required":["id","name"]},"application":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","status","createdAt"]}},"required":["id","invitedByUserId","unitId","inviteCode","status","expiresAt","createdAt","updatedAt","unit","invitedBy"]}}}},"404":{"description":"Invitation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Invitations"],"summary":"Cancel invitation","description":"Cancel an invitation that has not been accepted","security":[{"bearerAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"id","in":"path"}],"responses":{"200":{"description":"Invitation cancelled","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"}},"required":["success"]}}}},"404":{"description":"Invitation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/invitations/{code}/applications":{"post":{"tags":["Invitations"],"summary":"Submit application via invitation","description":"Create an application using a valid invitation code. Unauthenticated, so it cannot carry the applicant's electronic identification: while the identity gate (APPLICATION_EID_GATE) is required, every submission is refused with 403 eid_required.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"code","in":"path"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"application":{"type":"object","properties":{"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"personalNumber":{"type":"string","minLength":1},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string","minLength":1},"phone":{"type":"string","minLength":1},"email":{"type":"string","format":"email"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"integer","minimum":1,"maximum":20},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","minLength":1},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string","minLength":1},"lastName":{"type":"string","minLength":1},"personalNumber":{"type":"string","minLength":1},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string","minLength":1},"age":{"type":"integer","minimum":0,"maximum":120},"contributesToIncome":{"type":"boolean"},"incomeSource":{"type":"string","enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other"]},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName","age"]},"maxItems":19},"nationality":{"type":"string"},"idNumber":{"type":"string"},"primaryIncomeSource":{"type":["string","null"],"enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other",null]},"monthlyGrossIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":["number","null"],"minimum":0,"maximum":1000000},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0,"maximum":1000000},"nonSmoker":{"type":"boolean"},"noPets":{"type":"boolean"},"numberOfChildren":{"type":"integer","minimum":0,"maximum":15},"childrenAges":{"type":"array","items":{"type":"integer","minimum":0,"maximum":120},"maxItems":15},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"}}},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":2,"maxLength":100},"relation":{"type":"string","minLength":2,"maxLength":50},"phone":{"type":"string"},"email":{"anyOf":[{"type":"string","maxLength":100,"format":"email"},{"type":"string","enum":[""]}]}},"required":["name","relation","phone"]},"maxItems":5},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"}},"required":["firstName","lastName","phone","email","householdSize","numberOfChildren","gdprConsent"]}},"required":["application"]}}}},"responses":{"201":{"description":"Application submitted","content":{"application/json":{"schema":{"type":"object","properties":{"success":{"type":"boolean"},"application":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"invitationId":{"type":"string","format":"uuid"},"applicationSource":{"type":"string","enum":["invitation","public_url","qr_code","direct_link","social_media"]},"sourceDetails":{"type":"object","properties":{"referer":{"type":"string"},"utmSource":{"type":"string"},"utmMedium":{"type":"string"},"utmCampaign":{"type":"string"},"userAgent":{"type":"string"},"ipCountry":{"type":"string"},"householdAnswersReceivedAt":{"type":"object","properties":{"pets":{"type":"string","format":"date-time"},"smoking":{"type":"string","format":"date-time"}},"description":"Per question, when Homito received an explicit yes or no at intake (ISO 8601). Set by the server only; a key that is absent was not answered explicitly."}}},"signingType":{"type":"string","enum":["private","company"]},"companyName":{"type":"string"},"organisationNumber":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean"},"birthDate":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"profileImageUrl":{"type":"string","format":"uri"},"hasTemporaryAddress":{"type":"boolean"},"currentAddress":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"country":{"type":"string"},"registeredAddress":{"type":"string"},"registeredPostalCode":{"type":"string"},"registeredCity":{"type":"string"},"previousAddresses":{"type":"array","items":{"type":"object","properties":{"address":{"type":"string"},"postalCode":{"type":"string"},"city":{"type":"string"},"fromDate":{"type":"string"},"toDate":{"type":"string"}},"required":["address","fromDate","toDate"]}},"livingArrangement":{"type":"string","enum":["alone","couple","family","co-living","company"]},"householdSize":{"type":"number"},"householdMembers":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string"},"lastName":{"type":"string"},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","description":"Co-applicant has no Swedish personal number; birthDate identifies them"},"birthDate":{"anyOf":[{"type":"string","format":"date"},{"type":"string","format":"date-time"}]},"age":{"type":"number"},"contributesToIncome":{"type":"boolean"},"employmentType":{"type":"string"},"employer":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"hasIdDocument":{"type":"boolean"},"hasIncomeVerification":{"type":"boolean"}},"required":["type","firstName","lastName","age"]}},"nationality":{"type":"string"},"idNumber":{"type":"string"},"monthlyGrossIncome":{"type":"number"},"monthlyNetIncome":{"type":"number"},"monthlyIncome":{"type":"number"},"declaredMonthlyCommitments":{"type":["number","null"],"minimum":0},"nonSmoker":{"type":["boolean","null"]},"noPets":{"type":["boolean","null"]},"numberOfChildren":{"type":"number"},"childrenAges":{"type":"array","items":{"type":"string"}},"employer":{"type":"string"},"occupation":{"type":"string"},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string","format":"date-time"},"linkedinProfile":{"type":"string"},"facebookProfile":{"type":"string"},"xProfile":{"type":"string"},"tiktokProfile":{"type":"string"},"websiteUrl":{"type":"string"},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string"},"phone":{"type":"string"},"email":{"type":"string","format":"email"},"relation":{"type":"string"}},"required":["name","phone","relation"]}},"gdprConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"},"gdprConsentedAt":{"type":"string","format":"date-time"},"status":{"type":"string","enum":["pending","screening","approved","offered","accepted","rejected","withdrawn"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","unitId","applicationSource","firstName","lastName","phone","email","status","createdAt","updatedAt"]}},"required":["success","application"]}}}},"403":{"description":"Electronic identification required (eid_required)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Invitation not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Invitation no longer valid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/public/units/{slug}/application-eid/handoffs":{"post":{"tags":["Applications"],"summary":"Create a company-scoped hosted electronic identity handoff","description":"Server only: write:applications customer key, original submission key, registered exact HTTPS callback and PKCE-S256. Redirect the applicant to authorizationUrl as a top-level page. Preserve the fragment; keep the key/verifier on your server. A create retry may open another short-lived attempt; no eID provider order is started until the applicant chooses it.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":256},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["sv","en","es"],"default":"sv"},"required":false,"name":"language","in":"query"},{"schema":{"type":"string","description":"Required server-only key with write:applications"},"required":true,"description":"Required server-only key with write:applications","name":"x-homito-customer-key","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"x-application-submission-key","in":"header"},{"schema":{"type":"string","enum":["1"]},"required":true,"name":"x-homito-application-contract","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ApplicationEidHandoffRequest"}}}},"responses":{"201":{"description":"Short-lived handoff; authorizationUrl is a private bootstrap capability","content":{"application/json":{"schema":{"type":"object","properties":{"handoffId":{"type":"string","format":"uuid"},"authorizationUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"}},"required":["handoffId","authorizationUrl","expiresAt"]}}}},"400":{"description":"Invalid request/submission key/contract","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid customer key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing permission, company mismatch or callback not registered","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit or callback unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Form/round changed or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"411":{"description":"Content-Length required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Body exceeds 4 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"Use uncompressed JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Company budget exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Identity handoff unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/public/units/{slug}/application-form/validate":{"post":{"tags":["Public Units"],"summary":"Validate a draft before freezing a submission; no application is created","description":"Uses the shared intake validation and a read-only form snapshot. Maximum 256 KiB actual JSON bytes. No receipt/upload key, case, consent audit, screening/provider or reservation is created. It validates declared document metadata, not file bytes; POST rechecks all rules under arrival locks.","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":256},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"listingPeriodId":{"type":"string","format":"uuid"},"formVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"application":{"type":"object","properties":{"signingType":{"type":"string","enum":["private","company"],"default":"private"},"applicantPreferredMoveInDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"applicantPreferredRentalPeriod":{"type":"string","enum":["indefinite","fixed"]},"applicantPreferredRentalMonths":{"type":"integer","minimum":1,"maximum":120},"companyName":{"type":"string","minLength":2,"maxLength":100},"organisationNumber":{"type":"string"},"firstName":{"type":"string","minLength":2,"maxLength":30},"lastName":{"type":"string","minLength":2,"maxLength":30},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","default":false},"birthDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"phone":{"type":"string"},"email":{"type":"string","maxLength":100,"format":"email"},"registeredAddress":{"type":"string","minLength":5,"maxLength":100},"registeredPostalCode":{"type":"string","pattern":"^\\d{3}\\s?\\d{2}$"},"registeredCity":{"type":"string","minLength":2,"maxLength":50},"hasTemporaryAddress":{"type":"boolean","default":false},"currentAddress":{"type":"string","maxLength":100},"postalCode":{"type":"string","pattern":"^\\d{3}\\s?\\d{2}$"},"city":{"type":"string","maxLength":50},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"employmentStartDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"employer":{"type":"string","maxLength":50},"occupation":{"type":"string","maxLength":50},"primaryIncomeSource":{"type":"string","enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other"]},"monthlyGrossIncome":{"type":"number","minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":"number","minimum":0,"maximum":1000000},"declaredMonthlyCommitments":{"type":"number","minimum":0,"maximum":1000000},"householdSize":{"type":"integer","minimum":1,"maximum":20},"numberOfChildren":{"type":"integer","minimum":0,"maximum":15},"childrenAges":{"type":"array","items":{"anyOf":[{"type":"integer","minimum":0,"maximum":120},{"type":"string","pattern":"^\\d+$"}]},"maxItems":15},"householdMembers":{"type":["array","null"],"items":{"type":"object","properties":{"id":{"type":"string"},"type":{"type":"string","enum":["co-applicant","child"]},"firstName":{"type":"string","minLength":2,"maxLength":30},"lastName":{"type":"string","minLength":2,"maxLength":30},"personalNumber":{"type":"string"},"hasNoPersonalNumber":{"type":"boolean","default":false},"birthDate":{"type":"string"},"age":{"type":"number","minimum":0,"maximum":120},"contributesToIncome":{"type":"boolean","default":false},"employmentType":{"type":"string","enum":["permanent","probation","temporary","self-employed","student","retired","unemployed","parental_leave","sick_leave","a-kassa","social_benefits","other"]},"incomeSource":{"type":"string","enum":["salary","self_employed","unemployment_benefit","social_assistance","pension","student_aid","sick_leave_benefit","parental_benefit","capital_income","other"]},"employer":{"type":"string","maxLength":50},"monthlyGrossIncome":{"type":"number","minimum":0,"maximum":1000000},"monthlyNetIncome":{"type":"number","minimum":0,"maximum":1000000},"hasIdDocument":{"type":"boolean","default":false},"hasIncomeVerification":{"type":"boolean","default":false}},"required":["id","type","firstName","lastName","age"]},"maxItems":19},"nonSmoker":{"type":"boolean"},"noPets":{"type":"boolean"},"assistanceDog":{"type":"boolean"},"references":{"type":"array","items":{"type":"object","properties":{"name":{"type":"string","minLength":1,"maxLength":100},"phone":{"type":"string","minLength":1,"maxLength":30},"email":{"type":"string","maxLength":100,"format":"email"},"relation":{"type":"string","enum":["current_landlord","employer","personal","coordinator"]}},"required":["name","phone","relation"],"additionalProperties":false},"maxItems":10},"noPreviousLandlord":{"type":"boolean"},"gdprConsent":{"type":"boolean"},"staySafeConsent":{"type":"boolean"},"backgroundCheckConsent":{"type":"boolean"},"activeDataDeletion":{"type":"boolean"},"biometricConsent":{"type":"boolean"},"language":{"type":"string","enum":["sv","en","es"],"default":"sv"}},"required":["firstName","lastName","phone","email","registeredAddress","registeredPostalCode","registeredCity","primaryIncomeSource","householdSize","numberOfChildren","gdprConsent","staySafeConsent","backgroundCheckConsent"],"additionalProperties":false},"attachmentManifest":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"documentType":{"type":"string","enum":["salary_specification","employment_contract","business_financial_statement","accountant_certificate","bank_statement","tax_return","student_finance_decision","pension_statement","unemployment_benefit","social_insurance_decision","passport","id_document_front","id_document_back","drivers_license_front","drivers_license_back","selfie","guarantor_documentation"]},"belongsTo":{"type":"string","minLength":1,"maxLength":100,"default":"main"},"name":{"type":"string","minLength":1,"maxLength":200},"size":{"type":"integer","minimum":1,"maximum":10485760},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"mimeType":{"type":"string","enum":["application/pdf","image/jpeg","image/jpg","image/png"]}},"required":["id","documentType","name","size","sha256","mimeType"],"additionalProperties":false},"minItems":1,"maxItems":20}},"required":["listingPeriodId","formVersion","application","attachmentManifest"],"additionalProperties":false}}}},"responses":{"200":{"description":"Draft valid against this snapshot only","content":{"application/json":{"schema":{"type":"object","properties":{"valid":{"type":"boolean","enum":[true]},"listingPeriodId":{"type":"string","format":"uuid"},"formVersion":{"type":"string"},"language":{"type":"string","enum":["sv","en","es"]}},"required":["valid","listingPeriodId","formVersion","language"],"additionalProperties":false}}}},"400":{"description":"Draft validation failed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Customer permission or company scope denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Form/round changed or closed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Draft body too large","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"415":{"description":"Use JSON","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"422":{"description":"Unknown document owner","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Read budget exhausted","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/public/units/{slug}/application-form":{"get":{"tags":["Applications"],"summary":"Read versioned application fields, policies and attachment requirements","parameters":[{"schema":{"type":"string","minLength":1,"maxLength":256},"required":true,"name":"slug","in":"path"},{"schema":{"type":"string","enum":["sv","en","es"],"default":"sv"},"required":false,"name":"language","in":"query"},{"schema":{"type":"string","description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed."},"required":false,"description":"Optional server-only hmt_ key with write:applications. Replaces the source-IP budget with a shared company budget; never replaces receipt/upload credentials or authorizes another company. Invalid supplied keys fail closed.","name":"x-homito-customer-key","in":"header"}],"responses":{"200":{"description":"Preserve formVersion/listingPeriodId when submitting","content":{"application/json":{"schema":{"type":"object","properties":{"unitId":{"type":"string","format":"uuid"},"unitSlug":{"type":"string"},"listingPeriodId":{"type":"string","format":"uuid"},"formVersion":{"type":"string"},"canApply":{"type":"boolean","description":"Inventory and application-round availability; also check identityGate.required before offering submission."},"identityGate":{"type":"object","properties":{"mode":{"type":"string","enum":["required","optional","off"]},"required":{"type":"boolean","description":"When true, a new intake needs a valid matching proof, independently of provider readiness."},"ceremonySupported":{"type":"boolean","enum":[true],"description":"Hosted handoff supported for a customer server; the key alone is never identity proof."},"handoff":{"type":"object","properties":{"startPathTemplate":{"type":"string","enum":["/api/v1/public/units/{unitSlug}/application-eid/handoffs"]},"proofField":{"type":"string","enum":["identityHandoff"]},"pkceMethod":{"type":"string","enum":["S256"]},"requiresCustomerKey":{"type":"boolean","enum":[true]}},"required":["startPathTemplate","proofField","pkceMethod","requiresCustomerKey"]}},"required":["mode","required","ceremonySupported","handoff"]},"inputSchema":{"type":"object","additionalProperties":{}},"policies":{"type":"object","additionalProperties":{}},"documents":{"type":"object","additionalProperties":{}}},"required":["unitId","unitSlug","listingPeriodId","formVersion","canApply","identityGate","inputSchema","policies","documents"],"additionalProperties":{}}}}},"400":{"description":"Invalid form query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Supplied customer key invalid","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Customer permission or company scope denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Published round missing","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Intake unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/public/units":{"get":{"tags":["Public Units"],"summary":"List publicly available units","description":"Return published units open for the next tenancy, including re-letting during notice. Expired application deadlines are represented by canApply=false.","responses":{"200":{"description":"Public units","content":{"application/json":{"schema":{"type":"object","properties":{"units":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl"]}}},"required":["units"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/public/units/{slug}":{"get":{"tags":["Public Units"],"summary":"Get public unit details","description":"Fetch the public presentation of a specific unit using its slug.","parameters":[{"schema":{"type":"string","minLength":1},"required":true,"name":"slug","in":"path"}],"responses":{"200":{"description":"Public unit","content":{"application/json":{"schema":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl"]}}}},"404":{"description":"Unit not found (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/portfolio-imports/preview":{"post":{"tags":["Portfolio imports"],"summary":"Validate and persist an immutable portfolio import preview","description":"Accepts properties and units only. No tenant, lease, payment or screening data is mutated. Correct blocking issues by creating a new preview.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,79}$","default":"agent"},"properties":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"property-kungsgatan-1"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Kungsgatan 1"},"address":{"type":"string","minLength":1,"maxLength":300,"example":"Kungsgatan 1"},"postalCode":{"type":"string","minLength":1,"maxLength":20},"city":{"type":"string","minLength":1,"maxLength":120},"country":{"type":"string","minLength":1,"maxLength":80,"default":"Sweden"},"description":{"type":"string","maxLength":10000},"propertyCategory":{"type":"string","enum":["residential","commercial","mixed","industrial","other"],"default":"residential"},"units":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"unit-1101"},"unitNumber":{"type":"string","minLength":1,"maxLength":100,"example":"1101"},"name":{"type":"string","minLength":1,"maxLength":200},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"],"default":"apartment"},"floor":{"type":"integer","minimum":-10,"maximum":200},"size":{"type":"integer","exclusiveMinimum":0,"maximum":1000000},"rooms":{"type":"integer","exclusiveMinimum":0,"maximum":1000},"rent":{"type":"number","minimum":0,"maximum":1000000000}},"required":["externalRef","unitNumber"],"additionalProperties":false},"maxItems":1000,"default":[]}},"required":["externalRef","name","address"],"additionalProperties":false},"minItems":1,"maxItems":100}},"required":["properties"],"additionalProperties":false}}}},"responses":{"201":{"description":"Preview created; inspect import.status and import.preview.valid before commit","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","units","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]}},"required":["properties","units"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/portfolio-imports/{importId}/commit":{"post":{"tags":["Portfolio imports"],"summary":"Atomically commit a valid immutable preview","description":"Requires explicit confirmation and an Idempotency-Key. Repeated commits converge on the same completed result.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"importId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","enum":[true]}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Import completed","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","units","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]}},"required":["properties","units"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Import not found for this API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Preview invalid, expired or stale, or lease_template_unit_type_mismatch: an imported unit type no longer fits the unit's stored lease basis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/portfolio-imports/{importId}":{"get":{"tags":["Portfolio imports"],"summary":"Read a portfolio import status","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"importId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Import status","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","units","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]}},"required":["properties","units"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"404":{"description":"Import not found for this API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/portfolio-imports":{"get":{"tags":["Portfolio imports"],"summary":"List recent portfolio imports created by this API key","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Recent import jobs","content":{"application/json":{"schema":{"type":"object","properties":{"imports":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","units","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]},"units":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0}},"required":["create","update"]}},"required":["properties","units"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["imports","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/changes":{"get":{"tags":["Listings"],"summary":"Replay company advertisement changes after a full sync or interrupted webhook delivery","description":"Requires read:properties. Journal ordered by finished transaction and event; listing is the current projection, not a historical snapshot. Save nextCursor after applying the complete page. A long-running database transaction can delay the safe frontier. A 410 requires a new full sync.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":true,"name":"cursor","in":"query"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","description":"Bearer hmt_live_...; server-only company key with read:properties"},"required":true,"description":"Bearer hmt_live_...; server-only company key with read:properties","name":"authorization","in":"header"},{"schema":{"type":"string"},"required":false,"name":"if-none-match","in":"header"}],"responses":{"200":{"description":"Apply all changes, persist nextCursor; immediately continue while hasMore=true","content":{"application/json":{"schema":{"type":"object","properties":{"changes":{"type":"array","items":{"type":"object","properties":{"eventId":{"type":"string","format":"uuid"},"operation":{"type":"string","enum":["changed","unpublished"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"occurredAt":{"type":"string","format":"date-time"},"listingVersion":{"type":["string","null"]},"listing":{"type":["object","null"],"properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["eventId","operation","unitId","propertyId","occurredAt","listingVersion","listing"]}},"nextCursor":{"type":"string"},"hasMore":{"type":"boolean"}},"required":["changes","nextCursor","hasMore"]}}}},"400":{"description":"Invalid cursor or query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"sync_cursor_expired: perform a full sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings":{"get":{"tags":["Listings"],"summary":"Read a complete company-scoped apartment advertisement feed","description":"Requires read:properties. Defaults to published listings; includeUnpublished=true includes private/unavailable company units. Page cursors are bound to company and filters. Each page is a repeatable-read snapshot. Keep syncCursor from the first page, finish paging, then replay /changes from it to close concurrent-write gaps.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":2048},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","enum":["true","false"],"default":"false"},"required":false,"name":"includeUnpublished","in":"query"},{"schema":{"type":"string","description":"Bearer hmt_live_...; server-only company key with read:properties"},"required":true,"description":"Bearer hmt_live_...; server-only company key with read:properties","name":"authorization","in":"header"},{"schema":{"type":"string"},"required":false,"name":"if-none-match","in":"header"}],"responses":{"200":{"description":"Advertisement page. Follow nextCursor until null.","content":{"application/json":{"schema":{"type":"object","properties":{"listings":{"type":"array","items":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"nextCursor":{"type":["string","null"]},"syncCursor":{"type":"string"}},"required":["listings","nextCursor","syncCursor"]}}}},"304":{"description":"Representation unchanged for If-None-Match"},"400":{"description":"Invalid cursor or query","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"410":{"description":"Bootstrap cursor expired: restart full sync","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}":{"get":{"tags":["Listings"],"summary":"Read current advertisement data and publication state for one company unit","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","description":"Bearer hmt_live_...; server-only company key with read:properties"},"required":true,"description":"Bearer hmt_live_...; server-only company key with read:properties","name":"authorization","in":"header"},{"schema":{"type":"string"},"required":false,"name":"if-none-match","in":"header"}],"responses":{"200":{"description":"Advertisement, including unpublished state for an owned unit","content":{"application/json":{"schema":{"type":"object","properties":{"listing":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["listing"]}}}},"304":{"description":"Representation unchanged for If-None-Match"},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown unit or unit belonging to a different company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}/content":{"patch":{"tags":["Listings"],"summary":"Update the name and unit-specific advertisement text of an owned unit","description":"Requires write:properties and Idempotency-Key. Only name and otherFacts are accepted; omitted fields stay unchanged. Both are trimmed. An empty name removes the optional unit name. Empty otherFacts clears the unit-specific text; public description then falls back to legacy unit facts and property description. Publication, status, availability, media and private tenant fields cannot be changed here.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","description":"Bearer server-only company key with write:properties"},"required":true,"description":"Bearer server-only company key with write:properties","name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","maxLength":200},"otherFacts":{"type":"string","maxLength":10000}},"additionalProperties":false}}}},"responses":{"200":{"description":"The same company advertisement projection returned by GET, captured with the content write","content":{"application/json":{"schema":{"type":"object","properties":{"listing":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["listing"]}}}},"400":{"description":"Empty, unknown, invalid or oversized content fields","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing current write:properties permission","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unknown unit or unit no longer owned by the key company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency key reused for a different request, a busy row, or an existing screening input guard","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request body exceeds 64 KiB","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage or encryption unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}/media/uploads":{"post":{"tags":["Listings"],"summary":"Reserve private image uploads for a company-owned listing","description":"Requires write:properties, an explicit revocable human delegation for this key and Idempotency-Key. Up to ten images, five MiB each. PUT the exact declared bytes to the short-lived private upload URL with every returned header; do not send the Homito API key to object storage. Then call completion. Reservation expires after fifteen minutes; replay does not extend its upload URLs. Use a new reservation and idempotency key after expiry.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","description":"Bearer server-only company API key with write:properties and an explicit active listing delegation"},"required":true,"description":"Bearer server-only company API key with write:properties and an explicit active listing delegation","name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"images":{"type":"array","items":{"type":"object","properties":{"bytes":{"type":"integer","minimum":1,"maximum":5242880},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"mimeType":{"type":"string","enum":["image/jpeg","image/jpg","image/png","image/gif","image/webp","image/heic","image/heif","image/heic-sequence","image/heif-sequence","image/avif"]}},"required":["bytes","sha256","mimeType"],"additionalProperties":false},"minItems":1,"maxItems":10}},"required":["images"],"additionalProperties":false}}}},"responses":{"201":{"description":"Private PUT instructions; no gallery image is attached yet","content":{"application/json":{"schema":{"type":"object","properties":{"uploads":{"type":"array","items":{"type":"object","properties":{"uploadId":{"type":"string","format":"uuid"},"expiresAt":{"type":"string","format":"date-time"},"upload":{"type":"object","properties":{"method":{"type":"string","enum":["PUT"]},"url":{"type":"string","format":"uri"},"headers":{"type":"object","properties":{"Content-Type":{"type":"string","enum":["application/octet-stream"]},"x-amz-checksum-sha256":{"type":"string","pattern":"^[A-Za-z0-9+/]{43}=$"},"x-amz-server-side-encryption":{"type":"string","enum":["AES256"]}},"required":["Content-Type","x-amz-checksum-sha256","x-amz-server-side-encryption"],"additionalProperties":false},"bytes":{"type":"integer","minimum":1,"maximum":5242880},"expiresIn":{"type":"integer","minimum":1,"maximum":300}},"required":["method","url","headers","bytes","expiresIn"],"additionalProperties":false}},"required":["uploadId","expiresAt","upload"],"additionalProperties":false},"minItems":1,"maxItems":10}},"required":["uploads"],"additionalProperties":false}}}},"400":{"description":"Invalid or unknown fields, malformed bytes or image metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing or revoked explicit delegation, person, company membership, permission or required publication trust","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit or upload not owned by this key and company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflicting idempotency request, frozen company, maintenance, busy mutation or expired upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request exceeds the 64 KiB JSON body limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage, encryption or image service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}/media/uploads/{uploadId}/complete":{"post":{"tags":["Listings"],"summary":"Verify a private upload and atomically attach an immutable normalized listing image","description":"Rechecks live key, delegation, person, membership and ownership inside the mutation transaction, including replay. Verifies actual length, SHA-256, MIME and decoding before writing a different immutable public image. Commits the gallery, required audit, change journal, durable webhook and replay receipt together. GIF and animated WebP may retain embedded metadata. Retry the same request with the same Idempotency-Key after an interrupted response.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"uploadId","in":"path"},{"schema":{"type":"string","description":"Bearer server-only company API key with write:properties and an explicit active listing delegation"},"required":true,"description":"Bearer server-only company API key with write:properties and an explicit active listing delegation","name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"setAsFront":{"type":"boolean"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Attached image and the committed company listing projection","content":{"application/json":{"schema":{"type":"object","properties":{"uploadId":{"type":"string","format":"uuid"},"image":{"type":"object","properties":{"url":{"type":"string","format":"uri"},"sha256":{"type":"string","pattern":"^[a-f0-9]{64}$"},"bytes":{"type":"integer","minimum":1,"maximum":5242880},"mimeType":{"type":"string","enum":["image/jpeg","image/png","image/gif","image/webp"]}},"required":["url","sha256","bytes","mimeType"],"additionalProperties":false},"listing":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["uploadId","image","listing"],"additionalProperties":false}}}},"400":{"description":"Invalid or unknown fields, malformed bytes or image metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing or revoked explicit delegation, person, company membership, permission or required publication trust","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit or upload not owned by this key and company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflicting idempotency request, frozen company, maintenance, busy mutation or expired upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request exceeds the 64 KiB JSON body limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage, encryption or image service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}/media":{"patch":{"tags":["Listings"],"summary":"Remove existing listing images or select an existing front image","description":"Requires write:properties, an explicit current media delegation and Idempotency-Key. Only exact URLs already in the locked gallery can be removed or selected. No URL is fetched or imported. Gallery, required audit, change journal, webhook intent and replay receipt commit atomically. Removing a managed image makes it eligible for fenced scheduled physical cleanup.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","description":"Bearer server-only company API key with write:properties and an explicit active listing delegation"},"required":true,"description":"Bearer server-only company API key with write:properties and an explicit active listing delegation","name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"removeUrls":{"type":"array","items":{"type":"string","maxLength":2048,"format":"uri"},"minItems":1,"maxItems":10},"frontImageUrl":{"type":["string","null"],"maxLength":2048,"format":"uri"}},"additionalProperties":false}}}},"responses":{"200":{"description":"The listing projection committed with the gallery change","content":{"application/json":{"schema":{"type":"object","properties":{"listing":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["listing"]}}}},"400":{"description":"Invalid or unknown fields, malformed bytes or image metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing or revoked explicit delegation, person, company membership, permission or required publication trust","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit or upload not owned by this key and company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflicting idempotency request, frozen company, maintenance, busy mutation or expired upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request exceeds the 64 KiB JSON body limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage, encryption or image service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/listings/{unitId}/publication":{"patch":{"tags":["Listings"],"summary":"Publish or unpublish a company-owned listing using an explicit human delegation","description":"Requires write:properties, an active explicit listing delegation and Idempotency-Key. Publication applies the same maintenance, company freeze, allocation, no-credit and round rules as the portal, with the delegated person's current configured publication trust. Unpublishing preserves the existing publication-trust exemption and still requires live key, delegation, person, membership, permission and ownership. Arbitrary public URLs and credit checks cannot be requested.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"unitId","in":"path"},{"schema":{"type":"string","description":"Bearer server-only company API key with write:properties and an explicit active listing delegation"},"required":true,"description":"Bearer server-only company API key with write:properties and an explicit active listing delegation","name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"isPublic":{"type":"boolean"},"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["without_credit_check"]}},"required":["isPublic"],"additionalProperties":false}}}},"responses":{"200":{"description":"The listing projection committed with publication, audit and durable change notification","content":{"application/json":{"schema":{"type":"object","properties":{"listing":{"type":"object","properties":{"slug":{"type":"string"},"name":{"type":"string"},"unitNumber":{"type":"string"},"propertyName":{"type":"string"},"propertyAddress":{"type":"string"},"propertyImage":{"type":"string"},"postalCode":{"type":"string"},"area":{"type":"string"},"city":{"type":"string"},"floor":{"type":"number"},"size":{"type":"number"},"rooms":{"type":"number"},"rent":{"type":"number"},"deposit":{"type":"number"},"availableFrom":{"type":"string","format":"date-time"},"availableTo":{"type":"string","format":"date-time"},"description":{"type":"string"},"hasBalcony":{"type":"boolean"},"hasDishwasher":{"type":"boolean"},"hasWashingMachine":{"type":"boolean"},"hasElevator":{"type":"boolean"},"hasEvCharging":{"type":["boolean","null"]},"furnished":{"type":"boolean"},"furnishingLevel":{"type":"string","enum":["unfurnished","partially_furnished","furnished"]},"otherFacts":{"type":"string"},"facts":{"type":"string"},"noSmoking":{"type":"boolean"},"noPets":{"type":"boolean"},"noColiving":{"type":"boolean"},"noSubletting":{"type":"boolean"},"noChildren":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"onlyStudents":{"type":"boolean","description":"Retained for legacy clients; always false, never applied."},"maxOccupants":{"type":"number"},"minAge":{"type":"number"},"status":{"type":"string","enum":["vacant","reserved","booked","occupied"]},"amenities":{"type":"array","items":{"type":"object","properties":{"type":{"type":"string","enum":["electricity","water","heating","internet","cable_tv","cleaning","parking","insurance"]},"included":{"type":"boolean"},"cost":{"type":"number"},"period":{"type":"string","enum":["per_month","per_year"]},"notes":{"type":"string"}},"required":["type","included"]}},"companySigningAccepted":{"type":"boolean"},"privateSigningAccepted":{"type":"boolean"},"rentalPeriodType":{"type":"string","enum":["indefinite","fixed","now","custom","rented"]},"fixedPeriod":{"type":"number"},"frontImage":{"type":"string"},"images":{"type":"array","items":{"type":"object","properties":{"url":{"type":"string"},"caption":{"type":"string"}},"required":["url"]}},"videoUrl":{"type":"string"},"unitType":{"type":"string","enum":["apartment","studio","house","villa","townhouse","room","studentroom","office","retail","warehouse","garage","storage","parking","patio","ev_charging","bicycle","vacation_home","other"]},"applicationProcess":{"type":"object","properties":{"allocationMethod":{"type":"string","enum":["individual_assessment","first_come"]},"creditCheckMode":{"type":"string","enum":["with_credit_check","without_credit_check"]},"applicationDeadline":{"type":"string","format":"date-time"},"openedAt":{"type":"string","format":"date-time"}},"required":["allocationMethod"]},"property":{"type":"object","properties":{"id":{"type":"string"},"name":{"type":"string"},"companyId":{"type":"string"},"description":{"type":"string"},"image":{"type":"string"},"propertyCategory":{"type":"string"}},"required":["id","name"]},"landlord":{"type":"object","properties":{"name":{"type":"string"},"avatar":{"type":"string"}},"required":["name"]},"landlordTrust":{"type":"object","properties":{"verified":{"type":"boolean"},"label":{"type":["string","null"],"enum":["verified","new",null]}},"required":["verified","label"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"publicationStatus":{"type":"string","enum":["published","unpublished"]},"canApply":{"type":"boolean"},"unavailableReason":{"type":["string","null"],"enum":["unpublished","company_frozen","maintenance","not_available","application_deadline_passed",null]},"effectiveAvailableFrom":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"listingVersion":{"type":"string","pattern":"^sha256:[a-f0-9]{64}$"},"currency":{"type":"string","enum":["SEK"]},"rentPeriod":{"type":"string","enum":["month"]},"homitoUrl":{"type":["string","null"],"format":"uri"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}}},"required":["slug","propertyName","propertyAddress","hasBalcony","hasDishwasher","hasWashingMachine","hasElevator","furnished","noSmoking","noPets","noColiving","noSubletting","noChildren","onlyStudents","status","companySigningAccepted","privateSigningAccepted","property","unitId","propertyId","listingPeriodId","publicationStatus","canApply","unavailableReason","effectiveAvailableFrom","updatedAt","listingVersion","currency","rentPeriod","homitoUrl","externalReferences"]}},"required":["listing"]}}}},"400":{"description":"Invalid or unknown fields, malformed bytes or image metadata","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid, revoked or expired API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing or revoked explicit delegation, person, company membership, permission or required publication trust","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Unit or upload not owned by this key and company","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Conflicting idempotency request, frozen company, maintenance, busy mutation or expired upload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"413":{"description":"Request exceeds the 64 KiB JSON body limit","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage, encryption or image service unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll-imports/preview":{"post":{"tags":["Commercial rent roll"],"summary":"Validate and persist an immutable commercial rent-roll preview","description":"Returns field-level create/update changes, financial totals and blocking issues. It does not mutate the live rent roll.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,79}$","default":"agent"},"rows":{"type":"array","items":{"type":"object","properties":{"property":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"property-vasteras-1"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Västerås Logistik 1"},"address":{"type":"string","minLength":1,"maxLength":300,"example":"Lantbruksvägen 1"},"postalCode":{"type":"string","minLength":1,"maxLength":20},"city":{"type":"string","minLength":1,"maxLength":120},"country":{"type":"string","minLength":1,"maxLength":80,"default":"Sweden"},"propertyCategory":{"type":"string","enum":["commercial","mixed","industrial","other"],"default":"commercial"}},"required":["externalRef","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"premises-vasteras-1-office"},"unitNumber":{"type":"string","minLength":1,"maxLength":100,"example":"Kontor 01"},"name":{"type":"string","minLength":1,"maxLength":200},"unitType":{"type":"string","enum":["office","retail","warehouse","garage","storage","parking","other"],"default":"office"},"floor":{"type":"integer","minimum":-10,"maximum":200},"sizeSqm":{"type":"integer","exclusiveMinimum":0,"maximum":10000000}},"required":["externalRef","unitNumber"],"additionalProperties":false},"tenant":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"tenant-acme-ab"},"legalName":{"type":"string","minLength":1,"maxLength":300,"example":"Acme AB"},"organisationNumber":{"type":"string","minLength":1,"maxLength":80,"example":"556000-0000"},"internalTenant":{"type":"boolean","default":false},"contacts":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"contact-anna"},"name":{"type":"string","minLength":1,"maxLength":200,"example":"Anna Andersson"},"role":{"type":"string","minLength":1,"maxLength":120,"example":"Facility manager"},"email":{"type":"string","maxLength":320,"format":"email"},"phone":{"type":"string","minLength":1,"maxLength":80},"isPrimary":{"type":"boolean","default":false},"operationsAuthorized":{"type":"boolean","default":false}},"required":["externalRef","name"],"additionalProperties":false},"maxItems":25,"default":[]}},"required":["externalRef","legalName"],"additionalProperties":false},"lease":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":200,"example":"lease-2026-001"},"leaseNumber":{"type":"string","minLength":1,"maxLength":120},"status":{"type":"string","enum":["draft","active","notice","expired"],"default":"active"},"startDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"endDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"breakDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"annualBaseRent":{"type":"number","minimum":0,"maximum":100000000000},"annualAdditionalCosts":{"type":"number","minimum":0,"maximum":100000000000,"default":0},"vatRate":{"type":"number","minimum":0,"maximum":100,"default":25},"currency":{"type":"string","pattern":"^[A-Z]{3}$","default":"SEK"},"leasedAreaSqm":{"type":"number","exclusiveMinimum":0,"maximum":10000000},"indexation":{"type":"object","properties":{"type":{"type":"string","enum":["none","cpi","fixed","custom"],"default":"none"},"baseMonth":{"type":"string","pattern":"^\\d{4}-(0[1-9]|1[0-2])$"},"nextAdjustmentDate":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"fixedPercent":{"type":"number","minimum":-100,"maximum":1000},"floorPercent":{"type":"number","minimum":-100,"maximum":1000},"capPercent":{"type":"number","minimum":-100,"maximum":1000}},"default":{"type":"none"},"additionalProperties":false},"noticePeriodMonths":{"type":"integer","minimum":0,"maximum":600},"extensionMonths":{"type":"integer","minimum":0,"maximum":1200}},"required":["externalRef","startDate","annualBaseRent"],"additionalProperties":false}},"required":["property","premises","tenant","lease"],"additionalProperties":false},"minItems":1,"maxItems":2000}},"required":["rows"],"additionalProperties":false}}}},"responses":{"201":{"description":"Preview created","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"financials":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"annualBaseRent":{"type":"number","minimum":0},"annualAdditionalCosts":{"type":"number","minimum":0}},"required":["currency","annualBaseRent","annualAdditionalCosts"]}},"leasedAreaSqm":{"type":"number","minimum":0},"expiringWithin12Months":{"type":"integer","minimum":0},"changes":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string","enum":["property","premises","tenant","contact","lease"]},"externalRef":{"type":"string"},"action":{"type":"string","enum":["create","update"]},"changedFields":{"type":"array","items":{"type":"string"}}},"required":["resource","externalRef","action","changedFields"]}},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","premises","tenants","contacts","leases","financials","leasedAreaSqm","expiringWithin12Months","changes","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]}},"required":["properties","premises","tenants","contacts","leases"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"400":{"description":"Invalid payload","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:rent-roll","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll-imports/{importId}/commit":{"post":{"tags":["Commercial rent roll"],"summary":"Atomically commit a valid immutable rent-roll preview","description":"Requires explicit confirmation and an Idempotency-Key. A stale or overlapping rent roll is never partially written.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"importId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","enum":[true]}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Rent roll committed","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"financials":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"annualBaseRent":{"type":"number","minimum":0},"annualAdditionalCosts":{"type":"number","minimum":0}},"required":["currency","annualBaseRent","annualAdditionalCosts"]}},"leasedAreaSqm":{"type":"number","minimum":0},"expiringWithin12Months":{"type":"integer","minimum":0},"changes":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string","enum":["property","premises","tenant","contact","lease"]},"externalRef":{"type":"string"},"action":{"type":"string","enum":["create","update"]},"changedFields":{"type":"array","items":{"type":"string"}}},"required":["resource","externalRef","action","changedFields"]}},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","premises","tenants","contacts","leases","financials","leasedAreaSqm","expiringWithin12Months","changes","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]}},"required":["properties","premises","tenants","contacts","leases"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Import not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Preview invalid, expired, stale or conflicting, or lease_template_unit_type_mismatch: an imported unit type no longer fits the unit's stored lease basis","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll-imports/{importId}":{"get":{"tags":["Commercial rent roll"],"summary":"Read a rent-roll import status","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"importId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Import status","content":{"application/json":{"schema":{"type":"object","properties":{"import":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"financials":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"annualBaseRent":{"type":"number","minimum":0},"annualAdditionalCosts":{"type":"number","minimum":0}},"required":["currency","annualBaseRent","annualAdditionalCosts"]}},"leasedAreaSqm":{"type":"number","minimum":0},"expiringWithin12Months":{"type":"integer","minimum":0},"changes":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string","enum":["property","premises","tenant","contact","lease"]},"externalRef":{"type":"string"},"action":{"type":"string","enum":["create","update"]},"changedFields":{"type":"array","items":{"type":"string"}}},"required":["resource","externalRef","action","changedFields"]}},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","premises","tenants","contacts","leases","financials","leasedAreaSqm","expiringWithin12Months","changes","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]}},"required":["properties","premises","tenants","contacts","leases"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"required":["import"]}}}},"404":{"description":"Import not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll-imports":{"get":{"tags":["Commercial rent roll"],"summary":"List recent rent-roll imports created by this API key","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":25},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Recent import jobs","content":{"application/json":{"schema":{"type":"object","properties":{"imports":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"status":{"type":"string","enum":["ready","invalid","completed"]},"preview":{"type":"object","properties":{"valid":{"type":"boolean"},"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"financials":{"type":"array","items":{"type":"object","properties":{"currency":{"type":"string"},"annualBaseRent":{"type":"number","minimum":0},"annualAdditionalCosts":{"type":"number","minimum":0}},"required":["currency","annualBaseRent","annualAdditionalCosts"]}},"leasedAreaSqm":{"type":"number","minimum":0},"expiringWithin12Months":{"type":"integer","minimum":0},"changes":{"type":"array","items":{"type":"object","properties":{"resource":{"type":"string","enum":["property","premises","tenant","contact","lease"]},"externalRef":{"type":"string"},"action":{"type":"string","enum":["create","update"]},"changedFields":{"type":"array","items":{"type":"string"}}},"required":["resource","externalRef","action","changedFields"]}},"issues":{"type":"array","items":{"type":"object","properties":{"code":{"type":"string"},"path":{"type":"string"},"message":{"type":"string"}},"required":["code","path","message"]}}},"required":["valid","properties","premises","tenants","contacts","leases","financials","leasedAreaSqm","expiringWithin12Months","changes","issues"]},"result":{"type":["object","null"],"properties":{"properties":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"premises":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"tenants":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"contacts":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]},"leases":{"type":"object","properties":{"create":{"type":"integer","minimum":0},"update":{"type":"integer","minimum":0},"unchanged":{"type":"integer","minimum":0}},"required":["create","update","unchanged"]}},"required":["properties","premises","tenants","contacts","leases"]},"expiresAt":{"type":"string","format":"date-time"},"committedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"}},"required":["id","source","status","preview","result","expiresAt","committedAt","completedAt","createdAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["imports","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll":{"get":{"tags":["Commercial rent roll"],"summary":"List canonical commercial rent-roll lines","description":"Returns property, premises, tenant and lease economics as one agent-friendly line per commercial agreement.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","enum":["draft","active","notice","expired"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"tenantExternalRef","in":"query"},{"schema":{"type":"string","pattern":"^\\d{4}-\\d{2}-\\d{2}$"},"required":false,"name":"asOf","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Rent-roll page","content":{"application/json":{"schema":{"type":"object","properties":{"rentRoll":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]}},"required":["id","name","address","postalCode","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]},"unitType":{"type":["string","null"]},"sizeSqm":{"type":["number","null"]}},"required":["id","externalRef","unitNumber","name","unitType","sizeSqm"]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"},"organisationNumber":{"type":["string","null"]},"internalTenant":{"type":"boolean"}},"required":["id","externalRef","legalName","organisationNumber","internalTenant"]},"lease":{"type":"object","properties":{"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","notice","expired"]},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"breakDate":{"type":["string","null"],"format":"date-time"},"annualBaseRent":{"type":"number"},"annualAdditionalCosts":{"type":"number"},"vatRate":{"type":"number"},"currency":{"type":"string"},"leasedAreaSqm":{"type":["number","null"]},"indexation":{"type":"object","properties":{"type":{"type":"string","enum":["none","cpi","fixed","custom"]},"baseMonth":{"type":["string","null"]},"nextAdjustmentDate":{"type":["string","null"],"format":"date-time"},"fixedPercent":{"type":["number","null"]},"floorPercent":{"type":["number","null"]},"capPercent":{"type":["number","null"]}},"required":["type","baseMonth","nextAdjustmentDate","fixedPercent","floorPercent","capPercent"]},"noticePeriodMonths":{"type":["integer","null"]},"extensionMonths":{"type":["integer","null"]}},"required":["leaseNumber","status","startDate","endDate","breakDate","annualBaseRent","annualAdditionalCosts","vatRate","currency","leasedAreaSqm","indexation","noticePeriodMonths","extensionMonths"]}},"required":["id","source","externalRef","property","premises","tenant","lease"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["rentRoll","nextCursor"]}}}},"403":{"description":"Missing read:rent-roll","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/rent-roll/{leaseId}":{"get":{"tags":["Commercial rent roll"],"summary":"Read one commercial rent-roll line","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"leaseId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Rent-roll line","content":{"application/json":{"schema":{"type":"object","properties":{"rentRollLine":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]}},"required":["id","name","address","postalCode","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]},"unitType":{"type":["string","null"]},"sizeSqm":{"type":["number","null"]}},"required":["id","externalRef","unitNumber","name","unitType","sizeSqm"]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"},"organisationNumber":{"type":["string","null"]},"internalTenant":{"type":"boolean"}},"required":["id","externalRef","legalName","organisationNumber","internalTenant"]},"lease":{"type":"object","properties":{"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["draft","active","notice","expired"]},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"breakDate":{"type":["string","null"],"format":"date-time"},"annualBaseRent":{"type":"number"},"annualAdditionalCosts":{"type":"number"},"vatRate":{"type":"number"},"currency":{"type":"string"},"leasedAreaSqm":{"type":["number","null"]},"indexation":{"type":"object","properties":{"type":{"type":"string","enum":["none","cpi","fixed","custom"]},"baseMonth":{"type":["string","null"]},"nextAdjustmentDate":{"type":["string","null"],"format":"date-time"},"fixedPercent":{"type":["number","null"]},"floorPercent":{"type":["number","null"]},"capPercent":{"type":["number","null"]}},"required":["type","baseMonth","nextAdjustmentDate","fixedPercent","floorPercent","capPercent"]},"noticePeriodMonths":{"type":["integer","null"]},"extensionMonths":{"type":["integer","null"]}},"required":["leaseNumber","status","startDate","endDate","breakDate","annualBaseRent","annualAdditionalCosts","vatRate","currency","leasedAreaSqm","indexation","noticePeriodMonths","extensionMonths"]}},"required":["id","source","externalRef","property","premises","tenant","lease"]}},"required":["rentRollLine"]}}}},"404":{"description":"Rent-roll line not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/fault-reports/image-uploads":{"post":{"tags":["Fault reports"],"summary":"Create a short-lived direct image-upload contract","description":"The exact byte length and MIME type are signed. Uploaded bytes remain untrusted until fault-report creation validates and canonicalizes them.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"filename":{"type":"string","minLength":1,"maxLength":240},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/heic","image/heif","image/avif"]},"contentLength":{"type":"integer","minimum":1,"maximum":5242880}},"required":["filename","contentType","contentLength"],"additionalProperties":false}}}},"responses":{"201":{"description":"Upload contract created","content":{"application/json":{"schema":{"type":"object","properties":{"uploadUrl":{"type":"string","format":"uri"},"uploadRef":{"type":"string"},"requiredHeaders":{"type":"object","properties":{"content-type":{"type":"string"},"content-length":{"type":"integer","exclusiveMinimum":0}},"required":["content-type","content-length"]},"expiresAt":{"type":"string","format":"date-time"}},"required":["uploadUrl","uploadRef","requiredHeaders","expiresAt"]}}}},"403":{"description":"Missing write:fault-reports","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/fault-reports":{"post":{"tags":["Fault reports"],"summary":"Create an attributable fault report and materialize its operational flow","description":"Requires write:fault-reports. Validates company premises and any commercial tenant/contact authority, then creates the report, notifications, SLA task and Service Desk case idempotently.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,79}$","default":"agent"},"unitId":{"type":"string","format":"uuid"},"tenantExternalRef":{"type":"string","minLength":1,"maxLength":200},"contactExternalRef":{"type":"string","minLength":1,"maxLength":200},"title":{"type":"string","minLength":3,"maxLength":240},"description":{"type":"string","minLength":5,"maxLength":20000},"priority":{"type":"string","enum":["low","medium","high","urgent"],"default":"medium"},"images":{"type":"array","items":{"type":"object","properties":{"uploadRef":{"type":"string","minLength":1,"maxLength":500},"filename":{"type":"string","minLength":1,"maxLength":240},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp","image/heic","image/heif","image/avif"]},"contentLength":{"type":"integer","minimum":1,"maximum":5242880}},"required":["uploadRef","filename","contentType","contentLength"],"additionalProperties":false},"maxItems":5,"default":[]}},"required":["unitId","title","description"],"additionalProperties":false}}}},"responses":{"200":{"description":"Idempotent replay","content":{"application/json":{"schema":{"type":"object","properties":{"faultReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"status":{"type":["string","null"],"enum":["reported","in_progress","resolved","closed",null]},"slaBreach":{"type":["boolean","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":["string","null"]}},"required":["id","name","address","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialReporter":{"type":["object","null"],"properties":{"source":{"type":"string"},"tenantExternalRef":{"type":["string","null"]},"tenantLegalName":{"type":["string","null"]},"contactExternalRef":{"type":["string","null"]},"contactName":{"type":["string","null"]}},"required":["source","tenantExternalRef","tenantLegalName","contactExternalRef","contactName"]},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"analysis":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","reviewed","dismissed"]},"provider":{"type":"string"},"model":{"type":"string"},"suggestedCategory":{"type":"string","enum":["electrical","plumbing","ventilation","carpentry","gardening","cleaning","other"]},"suggestedPriority":{"type":"string","enum":["low","medium","high","urgent"]},"confidence":{"type":"number","minimum":0,"maximum":1},"safetyRiskDetected":{"type":"boolean"},"summary":{"type":"string"},"observedIssues":{"type":"array","items":{"type":"string"}},"safetySignals":{"type":"array","items":{"type":"string"}},"recommendedQuestions":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"humanReviewRequired":{"type":"boolean","enum":[true]},"autonomousActionAllowed":{"type":"boolean","enum":[false]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","documentId","status","provider","model","suggestedCategory","suggestedPriority","confidence","safetyRiskDetected","summary","observedIssues","safetySignals","recommendedQuestions","limitations","humanReviewRequired","autonomousActionAllowed","reviewedAt","reviewNote","createdAt"]}},"required":["id","filename","analysis"]}},"imageCount":{"type":"integer","minimum":0}},"required":["id","title","description","priority","status","slaBreach","createdAt","updatedAt","resolvedAt","property","premises","commercialReporter","images","imageCount"]}},"required":["faultReport"]}}}},"201":{"description":"Fault report created","content":{"application/json":{"schema":{"type":"object","properties":{"faultReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"status":{"type":["string","null"],"enum":["reported","in_progress","resolved","closed",null]},"slaBreach":{"type":["boolean","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":["string","null"]}},"required":["id","name","address","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialReporter":{"type":["object","null"],"properties":{"source":{"type":"string"},"tenantExternalRef":{"type":["string","null"]},"tenantLegalName":{"type":["string","null"]},"contactExternalRef":{"type":["string","null"]},"contactName":{"type":["string","null"]}},"required":["source","tenantExternalRef","tenantLegalName","contactExternalRef","contactName"]},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"analysis":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","reviewed","dismissed"]},"provider":{"type":"string"},"model":{"type":"string"},"suggestedCategory":{"type":"string","enum":["electrical","plumbing","ventilation","carpentry","gardening","cleaning","other"]},"suggestedPriority":{"type":"string","enum":["low","medium","high","urgent"]},"confidence":{"type":"number","minimum":0,"maximum":1},"safetyRiskDetected":{"type":"boolean"},"summary":{"type":"string"},"observedIssues":{"type":"array","items":{"type":"string"}},"safetySignals":{"type":"array","items":{"type":"string"}},"recommendedQuestions":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"humanReviewRequired":{"type":"boolean","enum":[true]},"autonomousActionAllowed":{"type":"boolean","enum":[false]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","documentId","status","provider","model","suggestedCategory","suggestedPriority","confidence","safetyRiskDetected","summary","observedIssues","safetySignals","recommendedQuestions","limitations","humanReviewRequired","autonomousActionAllowed","reviewedAt","reviewNote","createdAt"]}},"required":["id","filename","analysis"]}},"imageCount":{"type":"integer","minimum":0}},"required":["id","title","description","priority","status","slaBreach","createdAt","updatedAt","resolvedAt","property","premises","commercialReporter","images","imageCount"]}},"required":["faultReport"]}}}},"403":{"description":"Permission or commercial contact authority denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Actor, lease or idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Fault reports"],"summary":"List company-scoped fault reports","description":"Requires read:fault-reports. Raw image URLs, internal resolution cost and private user records are excluded.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"unitId","in":"query"},{"schema":{"type":"string","enum":["reported","in_progress","resolved","closed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["low","medium","high","urgent"]},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Fault-report page","content":{"application/json":{"schema":{"type":"object","properties":{"faultReports":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"status":{"type":["string","null"],"enum":["reported","in_progress","resolved","closed",null]},"slaBreach":{"type":["boolean","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":["string","null"]}},"required":["id","name","address","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialReporter":{"type":["object","null"],"properties":{"source":{"type":"string"},"tenantExternalRef":{"type":["string","null"]},"tenantLegalName":{"type":["string","null"]},"contactExternalRef":{"type":["string","null"]},"contactName":{"type":["string","null"]}},"required":["source","tenantExternalRef","tenantLegalName","contactExternalRef","contactName"]},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"analysis":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","reviewed","dismissed"]},"provider":{"type":"string"},"model":{"type":"string"},"suggestedCategory":{"type":"string","enum":["electrical","plumbing","ventilation","carpentry","gardening","cleaning","other"]},"suggestedPriority":{"type":"string","enum":["low","medium","high","urgent"]},"confidence":{"type":"number","minimum":0,"maximum":1},"safetyRiskDetected":{"type":"boolean"},"summary":{"type":"string"},"observedIssues":{"type":"array","items":{"type":"string"}},"safetySignals":{"type":"array","items":{"type":"string"}},"recommendedQuestions":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"humanReviewRequired":{"type":"boolean","enum":[true]},"autonomousActionAllowed":{"type":"boolean","enum":[false]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","documentId","status","provider","model","suggestedCategory","suggestedPriority","confidence","safetyRiskDetected","summary","observedIssues","safetySignals","recommendedQuestions","limitations","humanReviewRequired","autonomousActionAllowed","reviewedAt","reviewNote","createdAt"]}},"required":["id","filename","analysis"]}},"imageCount":{"type":"integer","minimum":0}},"required":["id","title","description","priority","status","slaBreach","createdAt","updatedAt","resolvedAt","property","premises","commercialReporter","images","imageCount"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["faultReports","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/fault-reports/{reportId}":{"get":{"tags":["Fault reports"],"summary":"Read one safe fault-report projection","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"reportId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Fault report","content":{"application/json":{"schema":{"type":"object","properties":{"faultReport":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"title":{"type":"string"},"description":{"type":"string"},"priority":{"type":["string","null"],"enum":["low","medium","high","urgent",null]},"status":{"type":["string","null"],"enum":["reported","in_progress","resolved","closed",null]},"slaBreach":{"type":["boolean","null"]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"resolvedAt":{"type":["string","null"],"format":"date-time"},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"city":{"type":["string","null"]}},"required":["id","name","address","city"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialReporter":{"type":["object","null"],"properties":{"source":{"type":"string"},"tenantExternalRef":{"type":["string","null"]},"tenantLegalName":{"type":["string","null"]},"contactExternalRef":{"type":["string","null"]},"contactName":{"type":["string","null"]}},"required":["source","tenantExternalRef","tenantLegalName","contactExternalRef","contactName"]},"images":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"filename":{"type":["string","null"]},"analysis":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","reviewed","dismissed"]},"provider":{"type":"string"},"model":{"type":"string"},"suggestedCategory":{"type":"string","enum":["electrical","plumbing","ventilation","carpentry","gardening","cleaning","other"]},"suggestedPriority":{"type":"string","enum":["low","medium","high","urgent"]},"confidence":{"type":"number","minimum":0,"maximum":1},"safetyRiskDetected":{"type":"boolean"},"summary":{"type":"string"},"observedIssues":{"type":"array","items":{"type":"string"}},"safetySignals":{"type":"array","items":{"type":"string"}},"recommendedQuestions":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"humanReviewRequired":{"type":"boolean","enum":[true]},"autonomousActionAllowed":{"type":"boolean","enum":[false]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","documentId","status","provider","model","suggestedCategory","suggestedPriority","confidence","safetyRiskDetected","summary","observedIssues","safetySignals","recommendedQuestions","limitations","humanReviewRequired","autonomousActionAllowed","reviewedAt","reviewNote","createdAt"]}},"required":["id","filename","analysis"]}},"imageCount":{"type":"integer","minimum":0}},"required":["id","title","description","priority","status","slaBreach","createdAt","updatedAt","resolvedAt","property","premises","commercialReporter","images","imageCount"]}},"required":["faultReport"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/fault-reports/{reportId}/images/{documentId}/analyze":{"post":{"tags":["Fault reports"],"summary":"Generate persisted advisory image triage","description":"The analysis is human-review-required and cannot update priority, assign responsibility, dispatch a vendor or estimate cost.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"reportId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"documentId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"confirm":{"type":"boolean","enum":[true]}},"required":["confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Advisory analysis","content":{"application/json":{"schema":{"type":"object","properties":{"analysis":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"documentId":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["completed","reviewed","dismissed"]},"provider":{"type":"string"},"model":{"type":"string"},"suggestedCategory":{"type":"string","enum":["electrical","plumbing","ventilation","carpentry","gardening","cleaning","other"]},"suggestedPriority":{"type":"string","enum":["low","medium","high","urgent"]},"confidence":{"type":"number","minimum":0,"maximum":1},"safetyRiskDetected":{"type":"boolean"},"summary":{"type":"string"},"observedIssues":{"type":"array","items":{"type":"string"}},"safetySignals":{"type":"array","items":{"type":"string"}},"recommendedQuestions":{"type":"array","items":{"type":"string"}},"limitations":{"type":"array","items":{"type":"string"}},"humanReviewRequired":{"type":"boolean","enum":[true]},"autonomousActionAllowed":{"type":"boolean","enum":[false]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"reviewNote":{"type":["string","null"]},"createdAt":{"type":"string","format":"date-time"}},"required":["id","documentId","status","provider","model","suggestedCategory","suggestedPriority","confidence","safetyRiskDetected","summary","observedIssues","safetySignals","recommendedQuestions","limitations","humanReviewRequired","autonomousActionAllowed","reviewedAt","reviewNote","createdAt"]}},"required":["analysis"]}}}},"503":{"description":"Image analysis unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/work-orders":{"get":{"tags":["Work orders"],"summary":"List company-scoped operational work orders","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["pending","in_progress","on_hold","completed","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["urgent","high","medium","low"]},"required":false,"name":"priority","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"vendorId","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"relatedEntityId","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Work-order page","content":{"application/json":{"schema":{"type":"object","properties":{"workOrders":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"taskType":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["pending","in_progress","on_hold","completed","cancelled",null]},"source":{"type":"string","enum":["tenant_report","system_event","manager_assigned","self_created"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"relatedEntityType":{"type":["string","null"]},"relatedEntityId":{"type":["string","null"],"format":"uuid"},"dueDate":{"type":["string","null"],"format":"date-time"},"onHoldUntil":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"assignee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"vendor":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"companyName":{"type":["string","null"]}},"required":["id","name","companyName"]}},"required":["id","taskType","title","description","status","source","priority","relatedEntityType","relatedEntityId","dueDate","onHoldUntil","completedAt","createdAt","updatedAt","assignee","vendor"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["workOrders","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/work-orders/vendors":{"get":{"tags":["Work orders"],"summary":"List company-scoped vendors available for dispatch","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":200,"default":100},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Vendors","content":{"application/json":{"schema":{"type":"object","properties":{"vendors":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"companyName":{"type":["string","null"]},"specialty":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["active","inactive","suspended",null]},"rating":{"type":["number","null"]}},"required":["id","name","companyName","specialty","status","rating"]}}},"required":["vendors"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/work-orders/{workOrderId}":{"get":{"tags":["Work orders"],"summary":"Read one work order","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workOrderId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Work order","content":{"application/json":{"schema":{"type":"object","properties":{"workOrder":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"taskType":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["pending","in_progress","on_hold","completed","cancelled",null]},"source":{"type":"string","enum":["tenant_report","system_event","manager_assigned","self_created"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"relatedEntityType":{"type":["string","null"]},"relatedEntityId":{"type":["string","null"],"format":"uuid"},"dueDate":{"type":["string","null"],"format":"date-time"},"onHoldUntil":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"assignee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"vendor":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"companyName":{"type":["string","null"]}},"required":["id","name","companyName"]}},"required":["id","taskType","title","description","status","source","priority","relatedEntityType","relatedEntityId","dueDate","onHoldUntil","completedAt","createdAt","updatedAt","assignee","vendor"]}},"required":["workOrder"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/work-orders/{workOrderId}/update":{"post":{"tags":["Work orders"],"summary":"Transition, schedule or dispatch a work order","description":"Requires write:work-orders. Terminal states cannot be reopened through the agent API. Vendor IDs must belong to the same company and be active.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"workOrderId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"status":{"type":"string","enum":["pending","in_progress","on_hold","completed","cancelled"]},"vendorId":{"type":["string","null"],"format":"uuid"},"dueDate":{"type":["string","null"],"format":"date-time"},"onHoldUntil":{"type":["string","null"],"format":"date-time"}},"additionalProperties":false}}}},"responses":{"200":{"description":"Work order updated","content":{"application/json":{"schema":{"type":"object","properties":{"workOrder":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"taskType":{"type":"string"},"title":{"type":"string"},"description":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["pending","in_progress","on_hold","completed","cancelled",null]},"source":{"type":"string","enum":["tenant_report","system_event","manager_assigned","self_created"]},"priority":{"type":"string","enum":["urgent","high","medium","low"]},"relatedEntityType":{"type":["string","null"]},"relatedEntityId":{"type":["string","null"],"format":"uuid"},"dueDate":{"type":["string","null"],"format":"date-time"},"onHoldUntil":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"},"assignee":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"}},"required":["id","name"]},"vendor":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"companyName":{"type":["string","null"]}},"required":["id","name","companyName"]}},"required":["id","taskType","title","description","status","source","priority","relatedEntityType","relatedEntityId","dueDate","onHoldUntil","completedAt","createdAt","updatedAt","assignee","vendor"]}},"required":["workOrder"]}}}},"409":{"description":"Invalid transition","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-inspections":{"get":{"tags":["Commercial inspections"],"summary":"List versioned digital commercial inspections","description":"Requires read:inspections. Each result includes the current checklist, review state and optimistic-lock version.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"unitId","in":"query"},{"schema":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"required":false,"name":"inspectionType","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Inspection page","content":{"application/json":{"schema":{"type":"object","properties":{"inspections":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["inspections","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Commercial inspections"],"summary":"Create and optionally schedule a commercial inspection","description":"Requires write:inspections. Stable externalRef and Idempotency-Key prevent duplicate inspections.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,79}$","default":"agent"},"externalRef":{"type":"string","minLength":1,"maxLength":200},"propertyId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"commercialLeaseId":{"type":"string","format":"uuid"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string","minLength":3,"maxLength":240},"scheduledAt":{"type":"string","format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true}},"required":["externalRef","section","label"],"additionalProperties":false},"minItems":1,"maxItems":200}},"required":["externalRef","propertyId","unitId","inspectionType","title","checklist"],"additionalProperties":false}}}},"responses":{"201":{"description":"Inspection created","content":{"application/json":{"schema":{"type":"object","properties":{"inspection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"required":["inspection"]}}}},"409":{"description":"External reference conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-inspections/{inspectionId}":{"get":{"tags":["Commercial inspections"],"summary":"Read one commercial inspection","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"inspectionId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Inspection","content":{"application/json":{"schema":{"type":"object","properties":{"inspection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"required":["inspection"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-inspections/{inspectionId}/checklist":{"post":{"tags":["Commercial inspections"],"summary":"Update checklist observations with optimistic locking","description":"Requires write:inspections. expectedVersion prevents an agent from overwriting concurrent field work.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"inspectionId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"expectedVersion":{"type":"integer","exclusiveMinimum":0},"items":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"],"maxLength":5000}},"required":["externalRef","status"],"additionalProperties":false},"minItems":1,"maxItems":200}},"required":["expectedVersion","items"],"additionalProperties":false}}}},"responses":{"200":{"description":"Checklist updated","content":{"application/json":{"schema":{"type":"object","properties":{"inspection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"required":["inspection"]}}}},"409":{"description":"Version or state conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-inspections/{inspectionId}/submit":{"post":{"tags":["Commercial inspections"],"summary":"Freeze and submit a completed checklist for human review","description":"Required items must be complete and every attention item must have notes. Submission never self-approves.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"inspectionId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"expectedVersion":{"type":"integer","exclusiveMinimum":0},"confirm":{"type":"boolean","enum":[true]}},"required":["expectedVersion","confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Inspection submitted","content":{"application/json":{"schema":{"type":"object","properties":{"inspection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"required":["inspection"]}}}},"409":{"description":"Incomplete checklist or version conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-inspections/{inspectionId}/review":{"post":{"tags":["Commercial inspections"],"summary":"Human-review a submitted commercial inspection","description":"Requires write:inspections and an attributable active company member different from the submitter. Accept completes the frozen snapshot; changes_requested requires a note.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"inspectionId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"expectedVersion":{"type":"integer","exclusiveMinimum":0},"decision":{"type":"string","enum":["accepted","changes_requested"]},"note":{"type":"string","minLength":3,"maxLength":5000},"confirm":{"type":"boolean","enum":[true]}},"required":["expectedVersion","decision","confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Inspection reviewed","content":{"application/json":{"schema":{"type":"object","properties":{"inspection":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"inspectionType":{"type":"string","enum":["move_in","move_out","condition","safety","handover","periodic"]},"title":{"type":"string"},"status":{"type":"string","enum":["draft","scheduled","in_progress","awaiting_review","changes_requested","completed","cancelled"]},"version":{"type":"integer","exclusiveMinimum":0},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"]},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"]},"commercialLeaseId":{"type":["string","null"],"format":"uuid"},"scheduledAt":{"type":["string","null"],"format":"date-time"},"startedAt":{"type":["string","null"],"format":"date-time"},"submittedAt":{"type":["string","null"],"format":"date-time"},"completedAt":{"type":["string","null"],"format":"date-time"},"checklist":{"type":"array","items":{"type":"object","properties":{"externalRef":{"type":"string","minLength":1,"maxLength":120},"section":{"type":"string","minLength":1,"maxLength":160},"label":{"type":"string","minLength":1,"maxLength":300},"required":{"type":"boolean","default":true},"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["pending","ok","attention","not_applicable"]},"notes":{"type":["string","null"]},"evidence":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"displayName":{"type":"string"},"contentType":{"type":"string","enum":["image/jpeg","image/png","image/webp"]},"byteSize":{"type":"integer","exclusiveMinimum":0},"contentHash":{"type":"string","pattern":"^[0-9a-f]{64}$"},"caption":{"type":["string","null"]},"imageUrl":{"type":"string"},"createdAt":{"type":"string","format":"date-time"},"createdBy":{"type":"string","format":"uuid"}},"required":["id","displayName","contentType","byteSize","contentHash","caption","imageUrl","createdAt","createdBy"],"additionalProperties":false}},"updatedAt":{"type":["string","null"],"format":"date-time"},"updatedBy":{"type":["string","null"],"format":"uuid"}},"required":["externalRef","section","label","id","status","notes","evidence","updatedAt","updatedBy"],"additionalProperties":false}},"summary":{"type":"object","properties":{"total":{"type":"integer","minimum":0},"pending":{"type":"integer","minimum":0},"ok":{"type":"integer","minimum":0},"attention":{"type":"integer","minimum":0},"notApplicable":{"type":"integer","minimum":0},"requiredPending":{"type":"integer","minimum":0}},"required":["total","pending","ok","attention","notApplicable","requiredPending"]},"review":{"type":"object","properties":{"decision":{"type":["string","null"],"enum":["accepted","changes_requested",null]},"note":{"type":["string","null"]},"reviewedAt":{"type":["string","null"],"format":"date-time"},"separationOfDutiesEnforced":{"type":"boolean","enum":[true]}},"required":["decision","note","reviewedAt","separationOfDutiesEnforced"]},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","inspectionType","title","status","version","property","premises","commercialLeaseId","scheduledAt","startedAt","submittedAt","completedAt","checklist","summary","review","createdAt","updatedAt"]}},"required":["inspection"]}}}},"409":{"description":"State or version conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/readiness":{"get":{"tags":["Commercial assistance"],"summary":"Verify the current API key's commercial-assistance capabilities","description":"Returns only the authenticated key's company binding and capability booleans. Dashboard member delegation requires its own explicit permission and never trusts a browser-supplied actor without it.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Company binding and least-privilege capability receipt","content":{"application/json":{"schema":{"type":"object","properties":{"companyId":{"type":"string","format":"uuid"},"capabilities":{"type":"object","properties":{"read":{"type":"boolean"},"write":{"type":"boolean"},"delegateMember":{"type":"boolean"}},"required":["read","write","delegateMember"],"additionalProperties":false}},"required":["companyId","capabilities"],"additionalProperties":false}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance":{"post":{"tags":["Commercial assistance"],"summary":"Start an attributable commercial tenant-assistance journey","description":"Requires write:commercial-assistance. The contact must be operations-authorized and hold a current commercial lease for the selected premises. Tenant, contact, lease and premises become immutable thread scope.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"x-homito-actor-user-id","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"source":{"type":"string","pattern":"^[a-z0-9][a-z0-9._-]{0,79}$","default":"agent"},"externalRef":{"type":"string","minLength":1,"maxLength":200},"tenantExternalRef":{"type":"string","minLength":1,"maxLength":200},"contactExternalRef":{"type":"string","minLength":1,"maxLength":200},"unitId":{"type":"string","format":"uuid"},"locale":{"type":"string","enum":["sv","en","es"],"default":"sv"}},"required":["externalRef","tenantExternalRef","contactExternalRef","unitId"],"additionalProperties":false}}}},"responses":{"200":{"description":"Idempotent thread readback","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]},"created":{"type":"boolean"}},"required":["thread","created"]}}}},"201":{"description":"Thread created","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]},"created":{"type":"boolean"}},"required":["thread","created"]}}}},"403":{"description":"Contact authority denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Immutable scope conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Commercial assistance"],"summary":"List commercial tenant-assistance journeys","description":"Requires read:commercial-assistance. Returns company-scoped contact, lease, premises, outcome and Service Desk status without internal event payloads.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["active","handed_off","closed"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","minLength":1,"maxLength":200},"required":false,"name":"tenantExternalRef","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Thread page","content":{"application/json":{"schema":{"type":"object","properties":{"threads":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["threads","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/metrics":{"get":{"tags":["Commercial assistance"],"summary":"Measure the retained commercial tenant-assistance loop","description":"Requires read:commercial-assistance. Returns explicitly defined 7/30/90-day self-service, handoff, feedback and knowledge-gap metrics; empty denominators are null, never invented as zero performance.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"number","default":30},"required":false,"name":"days","in":"query"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Commercial assistance metrics","content":{"application/json":{"schema":{"type":"object","properties":{"window":{"type":"object","properties":{"days":{"anyOf":[{"type":"number","enum":[7]},{"type":"number","enum":[30]},{"type":"number","enum":[90]}]},"from":{"type":"string","format":"date-time"},"to":{"type":"string","format":"date-time"}},"required":["days","from","to"],"additionalProperties":false},"counts":{"type":"object","properties":{"totalTurns":{"type":"integer","minimum":0},"uniqueThreads":{"type":"integer","minimum":0},"guidanceShown":{"type":"integer","minimum":0},"followUps":{"type":"integer","minimum":0},"handoffSignals":{"type":"integer","minimum":0},"safetyEscalations":{"type":"integer","minimum":0},"humanHandoffsCreated":{"type":"integer","minimum":0},"feedbackReceived":{"type":"integer","minimum":0},"helpfulFeedback":{"type":"integer","minimum":0},"unhelpfulFeedback":{"type":"integer","minimum":0}},"required":["totalTurns","uniqueThreads","guidanceShown","followUps","handoffSignals","safetyEscalations","humanHandoffsCreated","feedbackReceived","helpfulFeedback","unhelpfulFeedback"],"additionalProperties":false},"rates":{"type":"object","properties":{"guidanceRate":{"type":["number","null"],"minimum":0,"maximum":1},"handoffSignalRate":{"type":["number","null"],"minimum":0,"maximum":1},"feedbackCoverage":{"type":["number","null"],"minimum":0,"maximum":1},"helpfulRate":{"type":["number","null"],"minimum":0,"maximum":1}},"required":["guidanceRate","handoffSignalRate","feedbackCoverage","helpfulRate"],"additionalProperties":false},"knowledgeGapsByCategory":{"type":"array","items":{"type":"object","properties":{"category":{"type":"string","enum":["general","maintenance","billing","lease","access"]},"turns":{"type":"integer","exclusiveMinimum":0}},"required":["category","turns"],"additionalProperties":false}},"definitions":{"type":"object","properties":{"guidanceRate":{"type":"string","enum":["guidance_shown / total_turns"]},"handoffSignalRate":{"type":"string","enum":["handoff_recommended_or_safety_escalation / total_turns"]},"feedbackCoverage":{"type":"string","enum":["feedback_received / total_turns"]},"helpfulRate":{"type":"string","enum":["helpful_feedback / feedback_received"]},"knowledgeGap":{"type":"string","enum":["follow_up_or_handoff_recommended_without_safety_escalation"]},"retentionBoundary":{"type":"string","enum":["metrics_include_only_retained_turns_in_the_selected_window"]}},"required":["guidanceRate","handoffSignalRate","feedbackCoverage","helpfulRate","knowledgeGap","retentionBoundary"],"additionalProperties":false}},"required":["window","counts","rates","knowledgeGapsByCategory","definitions"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/{threadId}":{"get":{"tags":["Commercial assistance"],"summary":"Read the safe, attributable commercial assistance transcript and case readback","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"threadId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Thread and immutable turns","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]},"turns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"},"question":{"type":"string"},"replyToPrompt":{"type":["string","null"]},"outcome":{"type":"string","enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency"]},"category":{"type":"string","enum":["general","maintenance","billing","lease","access"]},"answer":{"type":["string","null"]},"followUpQuestions":{"type":"array","items":{"type":"string"}},"contextTurnIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":3},"actionPlan":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"minItems":1,"maxItems":3},"sources":{"type":"array","items":{"type":"object","properties":{"packageId":{"type":"string","format":"uuid"},"itemId":{"type":"string","format":"uuid"},"title":{"type":"string"},"category":{"type":"string"},"packageVersion":{"type":"integer","exclusiveMinimum":0},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["packageId","itemId","title","category","packageVersion","contentSha256"],"additionalProperties":false}},"safetyRiskDetected":{"type":"boolean"},"helpful":{"type":["boolean","null"]},"feedbackNote":{"type":["string","null"]},"feedbackAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"grounding":{"type":"object","properties":{"exactSourceTextOnly":{"type":"boolean","enum":[true]},"providerMayAuthorClaims":{"type":"boolean","enum":[false]}},"required":["exactSourceTextOnly","providerMayAuthorClaims"],"additionalProperties":false},"autonomousOperationalActionAllowed":{"type":"boolean","enum":[false]}},"required":["id","requestId","question","replyToPrompt","outcome","category","answer","followUpQuestions","contextTurnIds","actionPlan","sources","safetyRiskDetected","helpful","feedbackNote","feedbackAt","createdAt","grounding","autonomousOperationalActionAllowed"]}},"assistantState":{"type":"object","properties":{"phase":{"type":"string","enum":["ready","clarifying","action_ready","awaiting_confirmation","tracking","resolved","closed"]},"activeTurnId":{"type":["string","null"],"format":"uuid"},"nextAction":{"type":["object","null"],"properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"progress":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["context","understand","act","follow_up"]},"status":{"type":"string","enum":["completed","current","pending"]}},"required":["id","status"],"additionalProperties":false}}},"required":["phase","activeTurnId","nextAction","progress"],"additionalProperties":false}},"required":["thread","turns","assistantState"]}}}},"404":{"description":"Not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/{threadId}/messages":{"post":{"tags":["Commercial assistance"],"summary":"Ask the grounded commercial tenant assistant","description":"The model may select exact text from the current unit/property information package but may not author tenant guidance or take an operational action. The server composes up to three unresolved turns, records their contextTurnIds and emits a deterministic actionPlan for clarification, fault report, inspection, rent roll or confirmed human handoff. Safety language always fails toward urgent handoff.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"threadId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"x-homito-actor-user-id","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"question":{"type":"string","minLength":3,"maxLength":2000},"replyToPrompt":{"type":"string","minLength":3,"maxLength":1000}},"required":["question"],"additionalProperties":false}}}},"responses":{"200":{"description":"Grounded answer, follow-up or handoff recommendation","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]},"turn":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"},"question":{"type":"string"},"replyToPrompt":{"type":["string","null"]},"outcome":{"type":"string","enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency"]},"category":{"type":"string","enum":["general","maintenance","billing","lease","access"]},"answer":{"type":["string","null"]},"followUpQuestions":{"type":"array","items":{"type":"string"}},"contextTurnIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":3},"actionPlan":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"minItems":1,"maxItems":3},"sources":{"type":"array","items":{"type":"object","properties":{"packageId":{"type":"string","format":"uuid"},"itemId":{"type":"string","format":"uuid"},"title":{"type":"string"},"category":{"type":"string"},"packageVersion":{"type":"integer","exclusiveMinimum":0},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["packageId","itemId","title","category","packageVersion","contentSha256"],"additionalProperties":false}},"safetyRiskDetected":{"type":"boolean"},"helpful":{"type":["boolean","null"]},"feedbackNote":{"type":["string","null"]},"feedbackAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"grounding":{"type":"object","properties":{"exactSourceTextOnly":{"type":"boolean","enum":[true]},"providerMayAuthorClaims":{"type":"boolean","enum":[false]}},"required":["exactSourceTextOnly","providerMayAuthorClaims"],"additionalProperties":false},"autonomousOperationalActionAllowed":{"type":"boolean","enum":[false]}},"required":["id","requestId","question","replyToPrompt","outcome","category","answer","followUpQuestions","contextTurnIds","actionPlan","sources","safetyRiskDetected","helpful","feedbackNote","feedbackAt","createdAt","grounding","autonomousOperationalActionAllowed"]}},"required":["thread","turn"]}}}},"409":{"description":"Inactive thread or idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/{threadId}/handoff":{"post":{"tags":["Commercial assistance"],"summary":"Create one human-owned Service Desk handoff from the verified journey","description":"Requires write:commercial-assistance, optimistic expectedVersion and explicit confirmation. The handoff creates one routed SLA case and queues the existing staff copilot; the copilot cannot reply or change triage without human review.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"threadId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"x-homito-actor-user-id","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"expectedVersion":{"type":"integer","exclusiveMinimum":0},"title":{"type":"string","minLength":3,"maxLength":240},"description":{"type":"string","minLength":5,"maxLength":20000},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"confirm":{"type":"boolean","enum":[true]}},"required":["expectedVersion","confirm"],"additionalProperties":false}}}},"responses":{"200":{"description":"Handoff created or read back","content":{"application/json":{"schema":{"type":"object","properties":{"thread":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"source":{"type":"string"},"externalRef":{"type":"string"},"locale":{"type":"string","enum":["sv","en","es"]},"status":{"type":"string","enum":["active","handed_off","closed"]},"version":{"type":"integer","exclusiveMinimum":0},"lastOutcome":{"type":["string","null"],"enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency",null]},"tenant":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"legalName":{"type":"string"}},"required":["id","externalRef","legalName"],"additionalProperties":false},"contact":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"name":{"type":"string"},"role":{"type":["string","null"]},"operationsAuthorized":{"type":"boolean","enum":[true]}},"required":["id","externalRef","name","role","operationsAuthorized"],"additionalProperties":false},"lease":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"externalRef":{"type":"string"},"leaseNumber":{"type":["string","null"]},"status":{"type":"string","enum":["active","notice"]}},"required":["id","externalRef","leaseNumber","status"],"additionalProperties":false},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"}},"required":["id","name","address"],"additionalProperties":false},"premises":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitNumber":{"type":["string","null"]},"name":{"type":["string","null"]}},"required":["id","unitNumber","name"],"additionalProperties":false},"supportCase":{"type":["object","null"],"properties":{"id":{"type":"string","format":"uuid"},"status":{"type":"string","enum":["new","open","waiting_for_tenant","waiting_for_internal","waiting_for_vendor","resolved","closed"]},"priority":{"type":"string","enum":["low","normal","high","urgent"]},"version":{"type":"integer","exclusiveMinimum":0},"resolutionSummary":{"type":["string","null"]}},"required":["id","status","priority","version","resolutionSummary"],"additionalProperties":false},"turnCount":{"type":"integer","minimum":0},"lastMessageAt":{"type":["string","null"],"format":"date-time"},"handedOffAt":{"type":["string","null"],"format":"date-time"},"retentionExpiresAt":{"type":"string","format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"updatedAt":{"type":"string","format":"date-time"}},"required":["id","source","externalRef","locale","status","version","lastOutcome","tenant","contact","lease","property","premises","supportCase","turnCount","lastMessageAt","handedOffAt","retentionExpiresAt","createdAt","updatedAt"]},"turns":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"},"question":{"type":"string"},"replyToPrompt":{"type":["string","null"]},"outcome":{"type":"string","enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency"]},"category":{"type":"string","enum":["general","maintenance","billing","lease","access"]},"answer":{"type":["string","null"]},"followUpQuestions":{"type":"array","items":{"type":"string"}},"contextTurnIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":3},"actionPlan":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"minItems":1,"maxItems":3},"sources":{"type":"array","items":{"type":"object","properties":{"packageId":{"type":"string","format":"uuid"},"itemId":{"type":"string","format":"uuid"},"title":{"type":"string"},"category":{"type":"string"},"packageVersion":{"type":"integer","exclusiveMinimum":0},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["packageId","itemId","title","category","packageVersion","contentSha256"],"additionalProperties":false}},"safetyRiskDetected":{"type":"boolean"},"helpful":{"type":["boolean","null"]},"feedbackNote":{"type":["string","null"]},"feedbackAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"grounding":{"type":"object","properties":{"exactSourceTextOnly":{"type":"boolean","enum":[true]},"providerMayAuthorClaims":{"type":"boolean","enum":[false]}},"required":["exactSourceTextOnly","providerMayAuthorClaims"],"additionalProperties":false},"autonomousOperationalActionAllowed":{"type":"boolean","enum":[false]}},"required":["id","requestId","question","replyToPrompt","outcome","category","answer","followUpQuestions","contextTurnIds","actionPlan","sources","safetyRiskDetected","helpful","feedbackNote","feedbackAt","createdAt","grounding","autonomousOperationalActionAllowed"]}},"assistantState":{"type":"object","properties":{"phase":{"type":"string","enum":["ready","clarifying","action_ready","awaiting_confirmation","tracking","resolved","closed"]},"activeTurnId":{"type":["string","null"],"format":"uuid"},"nextAction":{"type":["object","null"],"properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"progress":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["context","understand","act","follow_up"]},"status":{"type":"string","enum":["completed","current","pending"]}},"required":["id","status"],"additionalProperties":false}}},"required":["phase","activeTurnId","nextAction","progress"],"additionalProperties":false},"created":{"type":"boolean"}},"required":["thread","turns","assistantState","created"]}}}},"409":{"description":"Version or journey conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/commercial-assistance/{threadId}/turns/{requestId}/feedback":{"post":{"tags":["Commercial assistance"],"summary":"Record idempotent answer feedback","description":"Feedback is tied to the exact immutable turn and may not trigger an operational action.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"threadId","in":"path"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"requestId","in":"path"},{"schema":{"type":"string"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"x-homito-actor-user-id","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"helpful":{"type":"boolean"},"note":{"type":"string","minLength":2,"maxLength":2000}},"required":["helpful"],"additionalProperties":false}}}},"responses":{"200":{"description":"Feedback receipt","content":{"application/json":{"schema":{"type":"object","properties":{"turn":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"requestId":{"type":"string","format":"uuid"},"question":{"type":"string"},"replyToPrompt":{"type":["string","null"]},"outcome":{"type":"string","enum":["guidance_shown","follow_up","handoff_recommended","urgent_handoff","emergency"]},"category":{"type":"string","enum":["general","maintenance","billing","lease","access"]},"answer":{"type":["string","null"]},"followUpQuestions":{"type":"array","items":{"type":"string"}},"contextTurnIds":{"type":"array","items":{"type":"string","format":"uuid"},"maxItems":3},"actionPlan":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"kind":{"type":"string","enum":["provide_guidance","collect_details","create_fault_report","create_service_case","track_service_case","open_inspection","review_lease","continue_conversation"]},"system":{"type":"string","enum":["homito_assist","knowledge","fault_reports","service_desk","inspections","rent_roll"]},"status":{"type":"string","enum":["completed","needs_input","ready","requires_confirmation","in_progress"]},"confirmation":{"type":"string","enum":["none","explicit"]},"contextBound":{"type":"boolean"}},"required":["id","kind","system","status","confirmation","contextBound"],"additionalProperties":false},"minItems":1,"maxItems":3},"sources":{"type":"array","items":{"type":"object","properties":{"packageId":{"type":"string","format":"uuid"},"itemId":{"type":"string","format":"uuid"},"title":{"type":"string"},"category":{"type":"string"},"packageVersion":{"type":"integer","exclusiveMinimum":0},"contentSha256":{"type":"string","pattern":"^[a-f0-9]{64}$"}},"required":["packageId","itemId","title","category","packageVersion","contentSha256"],"additionalProperties":false}},"safetyRiskDetected":{"type":"boolean"},"helpful":{"type":["boolean","null"]},"feedbackNote":{"type":["string","null"]},"feedbackAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":"string","format":"date-time"},"grounding":{"type":"object","properties":{"exactSourceTextOnly":{"type":"boolean","enum":[true]},"providerMayAuthorClaims":{"type":"boolean","enum":[false]}},"required":["exactSourceTextOnly","providerMayAuthorClaims"],"additionalProperties":false},"autonomousOperationalActionAllowed":{"type":"boolean","enum":[false]}},"required":["id","requestId","question","replyToPrompt","outcome","category","answer","followUpQuestions","contextTurnIds","actionPlan","sources","safetyRiskDetected","helpful","feedbackNote","feedbackAt","createdAt","grounding","autonomousOperationalActionAllowed"]}},"required":["turn"]}}}},"409":{"description":"Conflicting feedback","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/inventory/properties":{"get":{"tags":["Portfolio"],"summary":"List a safe, paginated property inventory projection","description":"Requires read:properties. Payment configuration and internal ownership fields are excluded.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Property inventory page","content":{"application/json":{"schema":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","externalReferences","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["properties","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/inventory/properties/{propertyId}":{"get":{"tags":["Portfolio"],"summary":"Read one safe property inventory projection","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"propertyId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Property","content":{"application/json":{"schema":{"type":"object","properties":{"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","externalReferences","createdAt","updatedAt"]}},"required":["property"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/inventory/properties/{propertyId}/units":{"get":{"tags":["Portfolio"],"summary":"List a safe, paginated unit inventory projection","description":"Access codes, tenant-only information and deposits are excluded.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"propertyId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Unit page","content":{"application/json":{"schema":{"type":"object","properties":{"units":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"unitType":{"type":["string","null"]},"floor":{"type":["integer","null"]},"size":{"type":["integer","null"]},"rooms":{"type":["integer","null"]},"rent":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["vacant","reserved","booked","occupied",null]},"availableFrom":{"type":["string","null"],"format":"date-time"},"availableTo":{"type":["string","null"],"format":"date-time"},"externalReferences":{"type":"array","items":{"type":"object","properties":{"source":{"type":"string"},"externalRef":{"type":"string"}},"required":["source","externalRef"]}},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","propertyId","name","unitNumber","unitType","floor","size","rooms","rent","status","availableFrom","availableTo","externalReferences","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["units","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/applications":{"get":{"tags":["Applications"],"summary":"List paginated company-scoped application summaries","description":"Requires read:applications. Identity numbers, household/income data, consent records and acquisition telemetry are excluded.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","enum":["pending","screening","offered","accepted","approved","rejected","withdrawn"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Application summary page","content":{"application/json":{"schema":{"type":"object","properties":{"applications":{"type":"array","items":{"type":"object","properties":{"application":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"intakeDocumentsState":{"type":["string","null"],"enum":["pending","partial","complete",null]},"intakeFinalizedAt":{"type":["string","null"],"format":"date-time"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"status":{"type":["string","null"],"enum":["pending","screening","offered","accepted","approved","rejected","withdrawn",null]},"intendedMoveInDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","unitId","listingPeriodId","intakeDocumentsState","intakeFinalizedAt","firstName","lastName","email","phone","status","intendedMoveInDate","createdAt","updatedAt"]},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"unitType":{"type":["string","null"]},"floor":{"type":["integer","null"]},"size":{"type":["integer","null"]},"rooms":{"type":["integer","null"]},"rent":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["vacant","reserved","booked","occupied",null]},"availableFrom":{"type":["string","null"],"format":"date-time"},"availableTo":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","propertyId","name","unitNumber","unitType","floor","size","rooms","rent","status","availableFrom","availableTo","createdAt","updatedAt"]},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","createdAt","updatedAt"]}},"required":["application","unit","property"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["applications","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/applications/{applicationId}":{"get":{"tags":["Applications"],"summary":"Read one company-scoped application summary","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"applicationId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Application summary","content":{"application/json":{"schema":{"type":"object","properties":{"application":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":["string","null"],"format":"uuid"},"intakeDocumentsState":{"type":["string","null"],"enum":["pending","partial","complete",null]},"intakeFinalizedAt":{"type":["string","null"],"format":"date-time"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"status":{"type":["string","null"],"enum":["pending","screening","offered","accepted","approved","rejected","withdrawn",null]},"intendedMoveInDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","unitId","listingPeriodId","intakeDocumentsState","intakeFinalizedAt","firstName","lastName","email","phone","status","intendedMoveInDate","createdAt","updatedAt"]},"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"unitType":{"type":["string","null"]},"floor":{"type":["integer","null"]},"size":{"type":["integer","null"]},"rooms":{"type":["integer","null"]},"rent":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["vacant","reserved","booked","occupied",null]},"availableFrom":{"type":["string","null"],"format":"date-time"},"availableTo":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","propertyId","name","unitNumber","unitType","floor","size","rooms","rent","status","availableFrom","availableTo","createdAt","updatedAt"]},"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","createdAt","updatedAt"]}},"required":["application","unit","property"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/tenants":{"get":{"tags":["Portfolio"],"summary":"List company-scoped tenants using a minimal contact/status projection","description":"Requires read:tenants. Personnummer, household members, deposits, provider IDs and internal notes are never returned.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","enum":["pending","active","notice_given","moved_out"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Tenant page","content":{"application/json":{"schema":{"type":"object","properties":{"tenants":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"leaseId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"firstName":{"type":"string"},"lastName":{"type":"string"},"email":{"type":"string","format":"email"},"phone":{"type":"string"},"status":{"type":["string","null"],"enum":["pending","active","notice_given","moved_out",null]},"moveInDate":{"type":"string","format":"date-time"},"moveOutDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","leaseId","unitId","propertyId","firstName","lastName","email","phone","status","moveInDate","moveOutDate","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["tenants","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/leases":{"get":{"tags":["Portfolio"],"summary":"List company-scoped leases and operational status","description":"Requires read:leases. Returns the operational contract timeline without signed documents, deposits or legal free text.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"propertyId","in":"query"},{"schema":{"type":"string","enum":["draft","sent","pending_signature","signed","future","active","notice_given","expiring","terminated","completed","cancelled","expired"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Lease page","content":{"application/json":{"schema":{"type":"object","properties":{"leases":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"leaseNumber":{"type":["string","null"]},"unitId":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"startDate":{"type":"string","format":"date-time"},"endDate":{"type":["string","null"],"format":"date-time"},"monthlyRent":{"type":"string"},"status":{"type":["string","null"],"enum":["draft","sent","pending_signature","signed","future","active","notice_given","expiring","terminated","completed","cancelled","expired",null]},"noticeDate":{"type":["string","null"],"format":"date-time"},"terminationDate":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","leaseNumber","unitId","propertyId","startDate","endDate","monthlyRent","status","noticeDate","terminationDate","createdAt","updatedAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["leases","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/webhooks":{"get":{"tags":["Webhooks"],"summary":"List company-scoped webhook health","description":"Requires read:webhooks. Signing secrets, deleted registrations and delivery payloads are never returned.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Webhook page","content":{"application/json":{"schema":{"type":"object","properties":{"webhooks":{"type":"array","items":{"$ref":"#/components/schemas/Webhook"}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["webhooks","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Webhooks"],"summary":"Subscribe to current external API events","description":"Requires write:webhooks and an Idempotency-Key. Answers the new subscription and its signing secret, which is shown this once.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["application.submitted","application.intake_finalized","listing.changed","listing.unpublished","portfolio_import.completed","property.created","screening.started","unit.created","rent_roll_import.completed","fault_report.created","work_order.updated","commercial_inspection.created","commercial_inspection.updated","commercial_inspection.submitted","commercial_inspection.reviewed","*"]},"minItems":1},"description":{"type":"string"}},"required":["url","events"]}}}},"responses":{"200":{"description":"Webhook registered, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"},"secret":{"type":"string","description":"The HMAC-SHA256 signing secret for X-Homito-Signature. Returned on creation, and again only by an idempotent replay of the same request within 24 hours; reads never return it. Store it in a secret manager.","example":"whsec_3q2-7wJb1VbH8jYQm4c1Xn0aZpQeR5sT6uV7wX8yZ9A"},"message":{"type":"string"}},"required":["webhook","secret","message"]}}}},"400":{"description":"Invalid configuration (validation_failed): an unknown event name is reported at its events index, for example events.1","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:webhooks (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/webhooks/{webhookId}":{"get":{"tags":["Webhooks"],"summary":"Read one company-scoped webhook health record","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"webhookId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Webhook health","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}},"required":["webhook"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"put":{"tags":["Webhooks"],"summary":"Update a webhook subscription","description":"Requires write:webhooks and an Idempotency-Key. Omitted fields are unchanged. An empty event list remains allowed; wildcard and duplicate entries are preserved. Answers the subscription as the reads do; the secret never changes here.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"webhookId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"url":{"type":"string","maxLength":2048,"format":"uri"},"events":{"type":"array","items":{"type":"string","enum":["application.submitted","application.intake_finalized","listing.changed","listing.unpublished","portfolio_import.completed","property.created","screening.started","unit.created","rent_roll_import.completed","fault_report.created","work_order.updated","commercial_inspection.created","commercial_inspection.updated","commercial_inspection.submitted","commercial_inspection.reviewed","*"]}},"description":{"type":"string"},"active":{"type":"boolean"}}}}}},"responses":{"200":{"description":"Webhook updated, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"webhook":{"$ref":"#/components/schemas/Webhook"}},"required":["webhook"]}}}},"400":{"description":"Invalid configuration (validation_failed): an unknown event name is reported at its events index, for example events.1","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:webhooks (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No webhook with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"delete":{"tags":["Webhooks"],"summary":"Delete a webhook subscription","description":"Requires write:webhooks and an Idempotency-Key. No new event is queued for the subscription, and it leaves the webhook reads with its delivery history. Deliveries queued before the delete can still arrive, signed with the secret of that time.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"webhookId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"responses":{"200":{"description":"Webhook deleted, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"400":{"description":"webhookId is not a UUID (validation_failed) or invalid Idempotency-Key (invalid_input)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:webhooks (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No webhook with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/webhooks/{webhookId}/deliveries":{"get":{"tags":["Webhooks"],"summary":"List safe delivery health for one company-scoped webhook","description":"Requires read:webhooks. Optional status filter and order=oldest|newest (default newest). Default newest order preserves legacy nulls-first ordering; oldest places missing timestamps last. Ties and missing timestamps paginate by id, without fabricating dates. Cursors are row anchors within the owned webhook. Restart paging when changing filters/order. Payloads, destination snapshots, signing secrets, response bodies and internal lease state are never returned.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"webhookId","in":"path"},{"schema":{"type":"integer","minimum":1,"maximum":100,"default":50},"required":false,"name":"limit","in":"query"},{"schema":{"type":"string","format":"uuid"},"required":false,"name":"cursor","in":"query"},{"schema":{"type":"string","enum":["pending","success","failed","retrying"]},"required":false,"name":"status","in":"query"},{"schema":{"type":"string","enum":["newest","oldest"],"default":"newest"},"required":false,"name":"order","in":"query"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Delivery page","content":{"application/json":{"schema":{"type":"object","properties":{"deliveries":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"eventId":{"type":"string"},"event":{"type":"string"},"status":{"type":"string","enum":["pending","success","failed","retrying"]},"attempts":{"type":"integer","minimum":0},"maxAttempts":{"type":"integer","minimum":1},"nextRetryAt":{"type":["string","null"],"format":"date-time"},"lastAttemptAt":{"type":["string","null"],"format":"date-time"},"responseStatus":{"type":["integer","null"]},"errorCode":{"type":["string","null"],"enum":["http_non_success","transport_error","delivery_lease_expired",null]},"deliveredAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"}},"required":["id","eventId","event","status","attempts","maxAttempts","nextRetryAt","lastAttemptAt","responseStatus","errorCode","deliveredAt","createdAt"]}},"nextCursor":{"type":["string","null"],"format":"uuid"}},"required":["deliveries","nextCursor"]}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/embed/sessions":{"post":{"tags":["Embed Framework"],"summary":"Create a short-lived one-time embed bootstrap","description":"Requires embed:sessions. The returned URL contains a two-minute one-time code; raw credentials are never persisted.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"module":{"type":"string","enum":["product_insights"],"default":"product_insights"},"locale":{"type":"string","enum":["sv","en","es"],"default":"sv"},"theme":{"type":"string","enum":["light","dark","system"],"default":"system"}},"required":["applicationId"],"additionalProperties":false}}}},"responses":{"201":{"description":"One-time embed bootstrap","content":{"application/json":{"schema":{"type":"object","properties":{"sessionId":{"type":"string","format":"uuid"},"embedUrl":{"type":"string","format":"uri"},"expiresAt":{"type":"string","format":"date-time"}},"required":["sessionId","embedUrl","expiresAt"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing or invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Permission, entitlement or module denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Application not found in the API-key tenant","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Application disabled","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"503":{"description":"Embed entitlement unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/register":{"post":{"tags":["Onboarding"],"deprecated":true,"summary":"Retired: self-service landlord registration","description":"Always answers 410 self_service_registration_disabled. A company administrator creates API keys in Homito under Settings -> API & agents.","responses":{"410":{"description":"Registration is retired (self_service_registration_disabled)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/api-keys":{"get":{"tags":["API keys"],"summary":"List the company's API keys","description":"Requires read:api-keys. Secrets are never returned; keyPrefix identifies a key. Create keys in Homito under Settings -> API & agents.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"The company's keys, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"keys":{"type":"array","items":{"$ref":"#/components/schemas/ApiKeySummary"}}},"required":["keys"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:api-keys (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/api-keys/rotate":{"post":{"tags":["API keys"],"deprecated":true,"summary":"Retired: rotate the calling key","description":"Always answers 410 external_api_key_rotation_retired. Rotate in Homito under Settings -> API & agents: create the replacement, switch the integration, then revoke the old key.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"responses":{"410":{"description":"Rotation through the API is retired (external_api_key_rotation_retired)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/api-keys/{keyId}":{"delete":{"tags":["API keys"],"summary":"Revoke another API key of the company","description":"Requires write:api-keys and an Idempotency-Key. The calling key cannot revoke itself (cannot_revoke_current_api_key): revoke it with another key or in Homito.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"keyId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"responses":{"200":{"description":"Key revoked, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"message":{"type":"string"}},"required":["message"]}}}},"400":{"description":"Invalid key id or Idempotency-Key, or the calling key itself (cannot_revoke_current_api_key)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:api-keys (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No active key with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/properties":{"post":{"tags":["Portfolio"],"summary":"Create a property","description":"Requires write:properties and an Idempotency-Key. Emits property.created.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"address":{"type":"object","properties":{"street":{"type":"string"},"city":{"type":"string"},"postalCode":{"type":"string"},"country":{"type":"string","default":"SE"}},"required":["street","city","postalCode"]},"landlordName":{"type":"string"},"description":{"type":"string"}},"required":["name","address"]}}}},"responses":{"200":{"description":"Property created, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","createdAt","updatedAt"]}},"required":["property"]}}}},"400":{"description":"Invalid body (validation_failed) or Idempotency-Key (invalid_input)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:properties (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"get":{"tags":["Portfolio"],"deprecated":true,"summary":"List every property (unpaginated)","description":"Requires read:properties. Superseded by GET /api/v1/landlord/inventory/properties, which pages with nextCursor and carries external references.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Every property of the company, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"properties":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","createdAt","updatedAt"]}}},"required":["properties"]}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/properties/{propertyId}":{"get":{"tags":["Portfolio"],"deprecated":true,"summary":"Read one property","description":"Requires read:properties. Superseded by GET /api/v1/landlord/inventory/properties/{propertyId}.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"propertyId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Property","content":{"application/json":{"schema":{"type":"object","properties":{"property":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"name":{"type":"string"},"address":{"type":"string"},"postalCode":{"type":["string","null"]},"city":{"type":["string","null"]},"country":{"type":["string","null"]},"description":{"type":["string","null"]},"propertyCategory":{"type":["string","null"],"enum":["residential","commercial","mixed","industrial","other",null]},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","name","address","postalCode","city","country","description","propertyCategory","createdAt","updatedAt"]}},"required":["property"]}}}},"400":{"description":"propertyId is not a UUID (validation_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No property with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/properties/{propertyId}/units":{"get":{"tags":["Portfolio"],"deprecated":true,"summary":"List every unit of a property (unpaginated)","description":"Requires read:properties. Superseded by GET /api/v1/landlord/inventory/properties/{propertyId}/units.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"propertyId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Every unit of the property, newest first","content":{"application/json":{"schema":{"type":"object","properties":{"units":{"type":"array","items":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"unitType":{"type":["string","null"]},"floor":{"type":["integer","null"]},"size":{"type":["integer","null"]},"rooms":{"type":["integer","null"]},"rent":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["vacant","reserved","booked","occupied",null]},"availableFrom":{"type":["string","null"],"format":"date-time"},"availableTo":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","propertyId","name","unitNumber","unitType","floor","size","rooms","rent","status","availableFrom","availableTo","createdAt","updatedAt"]}}},"required":["units"]}}}},"400":{"description":"propertyId is not a UUID (validation_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:properties (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No property with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}},"post":{"tags":["Portfolio"],"summary":"Create an apartment in a property","description":"Requires write:properties and an Idempotency-Key. The unit is always an apartment; create commercial premises through portfolio imports. Emits unit.created.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"propertyId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","pattern":"^[A-Za-z0-9._:-]{16,200}$","description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","example":"erp-2026-10-30-property-0001"},"required":true,"description":"16-200 characters [A-Za-z0-9._:-]. Reuse it only to retry the same request with the same body.","name":"idempotency-key","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"name":{"type":"string","minLength":1},"unitNumber":{"type":"string"},"rooms":{"type":"integer","exclusiveMinimum":0},"squareMeters":{"type":"number","exclusiveMinimum":0},"rent":{"type":"number","exclusiveMinimum":0},"deposit":{"type":"number","exclusiveMinimum":0},"availableFrom":{"type":"string","format":"date-time"},"rentalLegalType":{"type":["string","null"],"enum":["hyresratt","private",null]},"boendetyp":{"type":["string","null"],"enum":["hyresratt","bostadsratt","villa",null]},"isSublet":{"type":["boolean","null"]},"landlordLegalCapacity":{"type":["string","null"],"enum":["natural_person","estate","legal_entity",null]},"regularlyLetsMoreThanTwoNonHomeDwellings":{"type":["boolean","null"]},"dwellingHeldWithTenancyRight":{"type":["boolean","null"]},"lettingPurpose":{"type":["string","null"],"enum":["residential","leisure","other","commercial",null]}},"required":["name","rooms","squareMeters","rent"]}}}},"responses":{"200":{"description":"Unit created, or the idempotent replay of that answer","content":{"application/json":{"schema":{"type":"object","properties":{"unit":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"propertyId":{"type":"string","format":"uuid"},"name":{"type":["string","null"]},"unitNumber":{"type":["string","null"]},"unitType":{"type":["string","null"]},"floor":{"type":["integer","null"]},"size":{"type":["integer","null"]},"rooms":{"type":["integer","null"]},"rent":{"type":["string","null"]},"status":{"type":["string","null"],"enum":["vacant","reserved","booked","occupied",null]},"availableFrom":{"type":["string","null"],"format":"date-time"},"availableTo":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"},"updatedAt":{"type":["string","null"],"format":"date-time"}},"required":["id","propertyId","name","unitNumber","unitType","floor","size","rooms","rent","status","availableFrom","availableTo","createdAt","updatedAt"]}},"required":["unit"]}}}},"400":{"description":"Invalid body, including a legal basis that does not fit an apartment (validation_failed)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Missing, invalid, expired or revoked API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:properties (insufficient_permissions)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"No property with this id in the company (resource_not_found)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency-Key already used for a different request (idempotency_key_reused)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited (rate_limit_exceeded); wait Retry-After seconds","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable (service_unavailable)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/screenings":{"post":{"tags":["Screenings"],"summary":"Start or read back an application screening","description":"Requires write:screenings and an Idempotency-Key. The response exposes only the certified landlord decision projection; Detective and operator work remain in StaySafe.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"},{"schema":{"type":"string","minLength":16,"maxLength":200},"required":true,"name":"idempotency-key","in":"header"}],"requestBody":{"content":{"application/json":{"schema":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"}},"required":["applicationId"]}}}},"responses":{"200":{"description":"Screening created or existing screening returned","content":{"application/json":{"schema":{"type":"object","properties":{"screening":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"applicationId":{"type":"string","format":"uuid"},"status":{"type":["string","null"],"enum":["pending","in_progress","completed","failed",null]},"riskScore":{"type":["integer","null"],"minimum":0,"maximum":100},"recommendation":{"type":["string","null"],"enum":["approve","review","reject",null]},"forensicRisk":{"type":["string","null"],"enum":["low","medium","high",null]},"identityVerification":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["verified","needs_review","not_verified","not_available"]},"basis":{"type":"string","enum":["screening_evidence","source_bound_manual_review","none"]}},"required":["status","basis"],"additionalProperties":false,"description":"Minimized identity outcome from the certified frozen landlord report; null until certification. No identity PII, biometric values or operator notes are returned."},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"}},"required":["id","applicationId","status","riskScore","recommendation","forensicRisk","identityVerification","completedAt","createdAt"]},"message":{"type":"string"}},"required":["screening","message"]}}}},"400":{"description":"Invalid request","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing write:screenings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Application not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"409":{"description":"Idempotency conflict","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"503":{"description":"Required safety storage unavailable","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}},"/api/v1/landlord/screenings/{screeningId}":{"get":{"tags":["Screenings"],"summary":"Read certified landlord screening status","description":"Requires read:screenings. Mutable scores, AI notes, Detective details and operator work are never returned.","security":[{"apiKeyAuth":[]}],"parameters":[{"schema":{"type":"string","format":"uuid"},"required":true,"name":"screeningId","in":"path"},{"schema":{"type":"string","example":"Bearer hmt_live_xxx"},"required":true,"name":"authorization","in":"header"}],"responses":{"200":{"description":"Certified landlord screening status","content":{"application/json":{"schema":{"type":"object","properties":{"screening":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"applicationId":{"type":"string","format":"uuid"},"status":{"type":["string","null"],"enum":["pending","in_progress","completed","failed",null]},"riskScore":{"type":["integer","null"],"minimum":0,"maximum":100},"recommendation":{"type":["string","null"],"enum":["approve","review","reject",null]},"forensicRisk":{"type":["string","null"],"enum":["low","medium","high",null]},"identityVerification":{"type":["object","null"],"properties":{"status":{"type":"string","enum":["verified","needs_review","not_verified","not_available"]},"basis":{"type":"string","enum":["screening_evidence","source_bound_manual_review","none"]}},"required":["status","basis"],"additionalProperties":false,"description":"Minimized identity outcome from the certified frozen landlord report; null until certification. No identity PII, biometric values or operator notes are returned."},"completedAt":{"type":["string","null"],"format":"date-time"},"createdAt":{"type":["string","null"],"format":"date-time"}},"required":["id","applicationId","status","riskScore","recommendation","forensicRisk","identityVerification","completedAt","createdAt"]}},"required":["screening"]}}}},"400":{"description":"Invalid screening ID","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"401":{"description":"Invalid API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"403":{"description":"Missing read:screenings","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"404":{"description":"Screening not found","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}},"429":{"description":"Rate limited","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"headers":{"Retry-After":{"description":"Whole seconds to wait before retrying. On rate-limited partner routes it is the same moment as X-RateLimit-Reset.","schema":{"type":"integer","minimum":0}}}},"default":{"description":"Any other error. Every 4xx and 5xx answer uses this envelope.","content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}}}}}}},"webhooks":{"application.submitted":{"post":{"tags":["Application intake webhooks"],"summary":"Versioned intake committed","description":"Customer endpoint. Verify raw-body HMAC and persist/deduplicate before 2xx. Arrival order is not current status. No screening, eID, email delivery or rental decision is asserted.","parameters":[{"schema":{"type":"string","pattern":"^sha256=[a-f0-9]{64}$"},"required":true,"name":"X-Homito-Signature","in":"header"},{"schema":{"type":"string","enum":["application.submitted"]},"required":true,"name":"X-Homito-Event","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"X-Homito-Event-Id","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"X-Homito-Delivery","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event":{"type":"string","enum":["application.submitted"]},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":"string","format":"uuid"}},"required":["applicationId","unitId","listingPeriodId"],"additionalProperties":false}},"required":["id","event","timestamp","data"],"additionalProperties":false}}}},"responses":{"200":{"description":"Durably queued/deduplicated by customer"},"401":{"description":"Signature rejected"},"503":{"description":"Customer unavailable; delivery will retry"}}}},"application.intake_finalized":{"post":{"tags":["Application intake webhooks"],"summary":"Versioned intake documents finalized","description":"Customer endpoint. Verify raw-body HMAC and persist/deduplicate before 2xx. Arrival order is not current status. No screening, eID, email delivery or rental decision is asserted.","parameters":[{"schema":{"type":"string","pattern":"^sha256=[a-f0-9]{64}$"},"required":true,"name":"X-Homito-Signature","in":"header"},{"schema":{"type":"string","enum":["application.intake_finalized"]},"required":true,"name":"X-Homito-Event","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"X-Homito-Event-Id","in":"header"},{"schema":{"type":"string","format":"uuid"},"required":true,"name":"X-Homito-Delivery","in":"header"}],"requestBody":{"required":true,"content":{"application/json":{"schema":{"type":"object","properties":{"id":{"type":"string","format":"uuid"},"event":{"type":"string","enum":["application.intake_finalized"]},"timestamp":{"type":"string","format":"date-time"},"data":{"type":"object","properties":{"applicationId":{"type":"string","format":"uuid"},"unitId":{"type":"string","format":"uuid"},"listingPeriodId":{"type":"string","format":"uuid"}},"required":["applicationId","unitId","listingPeriodId"],"additionalProperties":false}},"required":["id","event","timestamp","data"],"additionalProperties":false}}}},"responses":{"200":{"description":"Durably queued/deduplicated by customer"},"401":{"description":"Signature rejected"},"503":{"description":"Customer unavailable; delivery will retry"}}}}}}