Skip to main content

Building spaces

A BuildingSpace is a discrete unit inside a building — a suite, a floor, a storage unit, a lobby — with suiteNumber (its canonical name), floor, squareFootage, type, rentable, occupied, and archived. List them with GET /rest/v2/accounts/{accountId}/buildings/{buildingId}/spaces. Four fields deserve care:
  • suiteNumber is the join key. It is what tag applicableSpaces entries match against, by string. Renaming a space breaks those associations.
  • floor is not just a label. It groups spaces in the stacking plan and determines which spaces pick up floor-level encumbrances: a right whose space entry names Floor 1 reaches every space with that floor.
  • rentable marks leasable inventory. Non-rentable spaces — lobbies, elevators, shared areas — drop out of reports like the rent roll, along with any leases still associated with them.
  • occupied is an override, not a derived truth. It marks a space as occupied even without an active lease attached. occupied: false does not mean the space is vacant — only that the override isn’t set. Derive real occupancy from leases.

Archived spaces

Archiving is for a space that historical leases still reference but that no longer represents a discrete unit in the building. Archived spaces are not removed from results by default — how you exclude them depends on how you’re reading: DELETE on a building space is a hard delete, not an archive.

applicableSpaces: where a tag applies

Request a tag with include=applicableSpaces and you get the list of spaces the term applies to, as space objects:
scope sets how to read name: The same space-object shape appears on Lease.suiteNumber (the spaces a lease occupies) and inside complex-tag components (expansionSpace, refusalSpace, offeredSpace, contractionSpace, encumberedSpaces).
applicableSpaces[].name connects to a BuildingSpace by name, not by id. There is no foreign key and no referential integrity: renaming a suite in either place silently breaks the association.
To join tags to your space inventory:
  1. Restrict candidates to the entry’s buildingId — suite names are only meaningful within a building, and an entry’s building can differ from the lease’s primary building.
  2. Handle scopes first: BUILDING and ALL sentinels never match a real space record — expand them to the building’s (or lease’s) space list yourself. FLOOR entries name a floor, not a suite — match against BuildingSpace.floor.
  3. For SUITE entries, match name against BuildingSpace.suiteNumber exactly; fall back to a whitespace/case-insensitive comparison for resilience, and treat non-matches as data to reconcile rather than discard.

Encumbrances: rights that burden space

An encumbrance is an option-type term that gives someone a claim on space — the space isn’t just leased, it’s promised. In the API these are COMPLEX tags whose components are the option kinds: RENEWAL, AUTO_RENEWAL, EARLY_TERMINATION, CONTRACTION, EXPANSION, RIGHT_OF_FIRST_REFUSAL, and RIGHT_OF_FIRST_OFFER. Two different questions arise, and they are answered by different fields.

Which of the lease’s own spaces does the right cover?

Read the tag’s applicableSpaces. Most option terms are space-dependent, which means they are captured and consolidated per space — a right does not automatically extend to everything the lease occupies.
A renewal option on a lease covering Suites 100, 200, and 300 with applicableSpaces: [{ "name": "Suite 100" }] encumbers Suite 100 only. Suites 200 and 300 carry no renewal. Do not fall back to Lease.suiteNumber for a space-dependent right — that would over-report the encumbrance across the whole premises.
renewal, autoRenewal, earlyTermination, contractionRight, fee, and tenantImprovement are all space-dependent, so the same lease can carry several instances of one of them — one per space, with different terms. A handful of option terms are space-independent — expansion, rightOfFirstOffer, rightOfFirstRefusal, purchaseOffer, and the various clause-style rights (sublet, permittedUse, signage…). These are consolidated once for the lease rather than per space. The tag reference marks which is which.

Which space does the right reach for?

Some rights point at space the tenant does not currently occupy. That space is named on the component, not on applicableSpaces: This is why expansion and the two first-rights are space-independent as terms: what matters isn’t which of the tenant’s suites the clause sits under, it’s the target space named in the component. That target can be a suite in a different lease’s premises, or space that is currently vacant. RENEWAL, AUTO_RENEWAL, EARLY_TERMINATION, and PURCHASE components carry no space field at all — they act on the space the tag already applies to.

Is the right still live?

Whether a right still burdens space depends on its rightStatus: AVAILABLE encumbers; EXERCISED, DECLINED, EXPIRED, and STRICKEN generally do not (an exercised expansion has become plain occupancy). UNKNOWN means no status could be resolved — decide how you want to treat it, and be consistent.

Recipe: which of my spaces are encumbered?

For a building:
  1. GET .../buildings/{buildingId}/spaces?archived=false — your current space inventory.
  2. GET .../buildings/{buildingId}/leases — the leases in play.
  3. For each lease, GET .../leases/{leaseId}/tags?include=applicableSpaces and keep category: COMPLEX tags whose component rightStatus is AVAILABLE.
  4. Join each kept tag to the inventory:
    • If the component names a target space (expansionSpace, offeredSpace, refusalSpace, contractionSpace, encumberedSpaces), that is the encumbered space.
    • Otherwise, use the tag’s own applicableSpaces — and only those entries. Don’t widen to the lease’s full suiteNumber list.
  5. Resolve each entry against the inventory using the scope and name-matching rules above.
The result is a map of space → outstanding rights: the API-side equivalent of an encumbrance overlay on a stacking plan.