Tenancy comes from the token, never the request. There is no buildingId parameter. A resource outside your scope returns 404 rather than 403.
Scopes fail closed. An endpoint you have not been granted is denied, and an endpoint with no declared scope is denied to everyone.
Every call is audited and metered, including denied ones. Repeatedly probing an endpoint you lack consent for consumes your quota.
Response shapes
ExtensionDataEntry
A single entry's full projection for `GET /data/:collection/:key`.
| Field | Type | Required | Description |
|---|
| collection | string | yes | — |
| key | string | yes | — |
| value | any JSON value | yes | — |
| byteSize | number | yes | — |
| updatedAt | string (ISO-8601) | yes | — |
ExtensionDataKeyMeta
One row's metadata in a `GET /data/:collection` listing — never the value.
| Field | Type | Required | Description |
|---|
| key | string | yes | — |
| byteSize | number | yes | Stored byte size of the value (the metered unit). |
| updatedAt | string (ISO-8601) | yes | — |
ExtensionDataWriteResult
Metadata echoed by a `PUT /data/:collection/:key` upsert (never the value).
| Field | Type | Required | Description |
|---|
| collection | string | yes | — |
| key | string | yes | — |
| byteSize | number | yes | — |
| updatedAt | string (ISO-8601) | yes | — |
GatewayCalendarEventDto
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| category | string | yes | — |
| visibility | string | yes | — |
| title | string | yes | — |
| description | string | null | yes | — |
| location | string | null | yes | — |
| startsAtUtc | string | yes | — |
| endsAtUtc | string | null | yes | — |
| isAllDay | boolean | yes | — |
| rrule | string | null | yes | — |
| recurrenceEndUtc | string | null | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayDepositLedgerDto
Deposit-ledger projection (§6.4): a summary-level view of a held deposit's money state — agreed amount, running balance, accrued interest, lifecycle status — plus the correlating leaseId and deposit kind. Deliberately excludes the individual DepositMovement log and every free-text field on it. Deposit free text (movement `notes`, `deductionReason`, `disputeReason`, the term's `notes`) is MODERATE PII — it can describe a tenant's conduct or damages (see #1398 / the `deposit.ledger.deducted` event's MODERATE tier) — so it never crosses the Gateway boundary. Also excluded: `referenceNumber` (a cheque/e-transfer financial identifier), `recordedByUserId` (audit actor), `method`/`supportingFileId` (movement internals), and the dispute-event log (attestation/audit trail). An extension needing the money figures gets them; the deduction/dispute narrative stays internal.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| leaseId | string | yes | — |
| depositKind | string | yes | LeaseDepositKind (SECURITY / LAST_MONTH / PET …). |
| agreedAmountCents | number | yes | The agreed deposit amount from the lease term (not the current balance). |
| balanceCents | number | yes | Running balance after every movement. |
| interestAccruedCents | number | yes | Lifetime accrued statutory interest (cumulative). |
| status | string | yes | DepositLedgerStatus (OPEN / PARTIALLY_RETURNED / RETURNED / WRITE_OFF …). |
| openedAt | string | yes | — |
| closedAt | string | null | yes | — |
| reopenedAt | string | null | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayDirectoryMemberDto
Directory-limited member projection (§6.4): the documented contract is display name + unit number only. Role/tenure/verification/status (isOwner/isResident/managerRole/verification/status) are deliberately NOT exposed — `DIRECTORY_VIEW` is a manager-only read of *who lives where*, not a governance view of each member's standing, and widening it here would leak organizing signal (who the owners/council are) beyond the stated contract. Never email/phone/entitlement either.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| userId | string | yes | — |
| displayName | string | null | yes | — |
| unitId | string | null | yes | — |
| unitNumber | string | null | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayDocumentDetailDto
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| title | string | yes | — |
| category | string | yes | — |
| categoryDefId | string | null | yes | — |
| status | string | yes | — |
| accessLevel | string | yes | — |
| tags | string[] | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
| currentVersion | object | null | yes | The document's current version, or null when no version has been uploaded yet. Object members: `id` (string), `versionNumber` (number, 1-based), `effectiveDate` (ISO-8601 string or null) and `createdAt` (ISO-8601 string). Spelled out here because the docs generator publishes a nested object literal as `object` — this JSDoc is the only description a partner gets. |
GatewayDocumentDto
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| title | string | yes | — |
| category | string | yes | — |
| categoryDefId | string | null | yes | — |
| status | string | yes | — |
| accessLevel | string | yes | — |
| tags | string[] | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayInvoiceDto
Vendor-invoice projection (§6.4): the money + lifecycle state of a vendor invoice an accounting partner needs to sync — amounts, dates, status, the settlement fields, and the `expenseId` correlating it to the booked expense. Deliberately excludes the free-text `description`/`notes`/`rejectionReason` (operator-entered narrative — can name people or describe disputes), the `paymentReference` (a cheque/e-transfer financial identifier, dropped like the deposit DTO's `referenceNumber`), the internal `documentUrl`, and every audit actor id (`submittedByUserId`/`approvedByUserId`/`rejectedByUserId`). The status-transition timestamps (`approvedAt`/`paidAt`) are kept; the actors are not. `invoiceNumber` is the vendor's own document number (a business identifier, not personal data) — required for reconciliation.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| vendorId | string | yes | — |
| workOrderId | string | null | yes | — |
| invoiceNumber | string | yes | — |
| invoiceDate | string | yes | — |
| dueDate | string | null | yes | — |
| amountCents | number | yes | Pre-tax invoice amount. |
| taxCents | number | yes | — |
| currency | string | yes | — |
| status | string | yes | InvoiceStatus (DRAFT / APPROVED / PAID …). |
| approvedAt | string | null | yes | — |
| paidAt | string | null | yes | — |
| paymentMethod | string | null | yes | PaymentMethod the invoice was settled with, when paid. |
| expenseId | string | null | yes | Opaque id of the booked BuildingExpense, once the invoice is marked PAID. |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayLeaseDto
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| unitId | string | yes | — |
| status | string | yes | — |
| termType | string | yes | — |
| startDate | string | yes | — |
| endDate | string | null | yes | — |
| monthlyRentCents | number | yes | — |
| rentDueDayOfMonth | number | yes | — |
| rentCollectionMode | string | yes | — |
| renewalMode | string | yes | — |
| landlordUserId | string | null | yes | — |
| namedTenantUserIds | string[] | yes | — |
| jurisdictionCode | string | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayPaymentDto
Resident-payment projection (§6.4): a Stripe-backed resident payment — the `paymentId` carried by the `payment.transaction.*` catalog events. The money state (amount, fee, refunds), lifecycle (status + paid/failed timestamps), and the opaque source correlation (sourceType/sourceId) an accounting partner needs to reconcile a transaction. Deliberately excludes the free-text `description`, the arbitrary `metadata` JSON (either can carry operator-entered PII), and every Stripe identifier (`stripePaymentIntentId`/`stripeChargeId`/`stripeTransferId` — payment-rail account identifiers, out of the partner contract by the same rule the deposit DTO drops `referenceNumber`). `userId` is the opaque payer id, consistent with the other Gateway DTOs that expose it.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| userId | string | yes | Opaque payer user id. |
| amountCents | number | yes | Amount charged, in cents (before platform fee). |
| applicationFeeCents | number | null | yes | Pastrata's platform fee in cents, when one applied. |
| currency | string | yes | — |
| sourceType | string | yes | PaymentSourceType (BOOKING / CHARGE …) — what the payment settled. |
| sourceId | string | yes | Opaque id of the settled source row (booking, charge, …). |
| status | string | yes | ResidentPaymentStatus (PENDING / SUCCEEDED / FAILED …). |
| paidAt | string | null | yes | — |
| failedAt | string | null | yes | — |
| failureReason | string | null | yes | Failure reason (e.g. CARD_DECLINED) — LOW, mirrors the event's `reason`. |
| totalRefundedCents | number | yes | Cumulative amount refunded against this payment, in cents. |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayRentChargeDto
Rent-ledger charge projection (§6.4): a rent period's expected charge — the `chargeId` carried by the `rent.charge.*` catalog events, so a partner that hears a charge event can fetch its detail here. Scoped through the parent lease (RentPeriod has no direct buildingId). Money figures + billing-cycle dates only; no payer/tenant identity beyond the opaque leaseId (the correlating lease read is a separate `LEASE_VIEW` grant). Date columns are rendered as full ISO-8601 for consistency with the lease DTO.
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| leaseId | string | yes | — |
| status | string | yes | RentPeriodStatus (UPCOMING / DUE / LATE / PAID …). |
| periodStart | string | yes | — |
| periodEnd | string | yes | — |
| dueDate | string | yes | — |
| expectedCents | number | yes | Expected rent for the period. |
| currency | string | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |
GatewayRequestDto
| Field | Type | Required | Description |
|---|
| id | string | yes | — |
| buildingId | string | yes | — |
| status | string | yes | — |
| customStatus | string | null | yes | — |
| title | string | null | yes | — |
| isUrgent | boolean | yes | — |
| isOutbound | boolean | yes | — |
| source | string | yes | — |
| categoryId | string | null | yes | — |
| typeId | string | null | yes | — |
| requesterUnitId | string | null | yes | — |
| createdByUserId | string | yes | — |
| assigneeUserId | string | null | yes | — |
| lastActivityAt | string | yes | — |
| resolvedAt | string | null | yes | — |
| closedAt | string | null | yes | — |
| createdAt | string | yes | — |
| updatedAt | string | yes | — |