Skip to main content
A listing represents a single affordable housing opportunity. It brings together a property address, unit types with rent and AMI (Area Median Income) information, eligibility criteria, application dates, and the method by which applicants can apply. Listings are managed by partners (property agents and jurisdictional admins) through the Partners Portal and are surfaced to the public through the public-facing portal.

Listing lifecycle

Every listing moves through a defined set of statuses. The ListingsStatusEnum (from @prisma/client) defines the valid states:
1

Draft

The listing is being authored. It is not visible to the public. Partners can save incomplete data and return to finish later. Status: active (draft variant — not yet published).
2

Pending review

Once a partner submits the listing for approval, it enters a pending review state. Jurisdictional admins or admins review the listing before it goes live. Requested changes and the requesting user are tracked in the requestedChanges, requestedChangesDate, and requestedChangesUser fields.
3

Active (open)

The listing is published and accepting applications. The applicationOpenDate and applicationDueDate fields control when the application window opens and closes. Status: active.
4

Closed

The applicationDueDate has passed, or a partner manually closes the listing. The closedAt timestamp is recorded. No new applications are accepted. Status: closed.
5

Results

For lottery listings, results are run and published after closure. The lotteryStatus field tracks progress through the lottery workflow independently of the listing status.
The PUT /listings/closeListings endpoint triggers the automated listing-close process job. It is typically invoked on a schedule and requires admin or jurisdictional admin authorization.

Key listing data

  • name — listing title (required, max 256 characters)
  • listingsBuildingAddress — the physical address of the property
  • developer — name of the housing developer
  • yearBuilt — year the building was constructed
  • buildingTotalUnits — total number of units in the building
  • neighborhood, region, configurableRegion — geographic classification
  • amenities, unitAmenities — property-level and unit-level amenities
  • smokingPolicy, petPolicy, allowsDogs, allowsCats — building policies
  • accessibility — ADA or accessibility notes
  • listingNeighborhoodAmenities — nearby transit, schools, parks, etc.
Each listing includes either units (individual unit records) or unitGroups (grouped unit definitions), but not both. A listing must have at least one unit or unit group to be published.Units reference AMI charts to define income limits per household size. Rent amounts and deposit ranges are set per unit. Summary data is available via unitsSummarized, unitGroupsSummarized, and unitsSummary.
  • depositMin, depositMax, depositType, depositValue — deposit configuration
  • rentalAssistance — notes about rental assistance programs (max 4096 characters)
  • costsNotIncluded — utilities or fees not included in rent
Partners can attach selection criteria via:
  • buildingSelectionCriteria — a URL linking to criteria documentation
  • listingsBuildingSelectionCriteriaFile — an uploaded asset file
  • creditHistory, rentalHistory, criminalBackground — screening policy text
  • requiredDocuments — document checklist for applicants
  • requiredDocumentsList — structured document list
The disableBuildingSelectionCriteria feature flag hides this section when set on the jurisdiction.
Listings can include multiselect questions that represent preferences (e.g., Live/Work in the City) or programs (e.g., veterans housing). These are managed via listingMultiselectQuestions and linked to MultiselectQuestion records. Preferences affect lottery ranking when enableGeocodingPreferences is enabled.The disableListingPreferences feature flag removes preferences support entirely for a jurisdiction.
  • listingImages — ordered array of listing images (at least minimumImagesRequired must be provided before publishing; configurable per jurisdiction via minimumListingPublishImagesRequired)
  • listingsMarketingFlyerFile, marketingFlyer, accessibleMarketingFlyer — marketing materials
  • assets — general file attachments
  • isWaitlistOpen — whether the waitlist is currently accepting applicants
  • waitlistCurrentSize — current number of households on the waitlist
  • waitlistMaxSize — maximum waitlist capacity
  • waitlistOpenSpots — number of open waitlist spots
  • displayWaitlistSize — controls whether waitlist size is shown publicly
  • showWaitlist (computed) — true when waitlistCurrentSize < waitlistMaxSize
  • leasingAgentName, leasingAgentEmail, leasingAgentPhone, leasingAgentTitle
  • leasingAgentOfficeHours
  • listingsLeasingAgentAddress

Application methods

A listing’s applicationMethods array defines how applicants submit. The ApplicationMethodsTypeEnum (from @prisma/client) supports:

Common Application (digital)

Sets digitalApplication: true and commonDigitalApplication: true. Applicants complete the multi-step Bloom Common Application form on the public portal. The listing’s applicationConfig can customize form sections.

External link

Sets paperApplication: true or uses a Referral method type. Partners supply a URL to a third-party form or a paper application mailing/drop-off address. Pick-up address (listingsApplicationPickUpAddress), drop-off address (listingsApplicationDropOffAddress), and mailing address (listingsApplicationMailingAddress) can each be configured with an ApplicationAddressTypeEnum type.
The disableCommonApplication feature flag prevents the digital application option from being selected for any listing in a jurisdiction.

Partners portal workflow

1

Create a listing

Navigate to Listings > Add listing in the Partners Portal. Fill in the required fields across all sections. The listing is saved as a draft. Required fields before publishing are enforced by the requiredFields metadata array and @ValidateListingPublish decorators.
2

Add units

Add individual units or unit groups with bedroom type, AMI percentage, monthly rent, and accessibility type. At least one unit or unit group is required.
3

Configure application settings

Choose an application method (digital Common Application or external link), set open and due dates, and configure any preferences or programs.
4

Submit for review

Submit the listing for review. Admins can request changes or approve it for publication. Approval permissions are controlled by the jurisdiction’s listingApprovalPermissions field.
5

Publish

Once approved, publish the listing. The publishedAt timestamp is recorded and the listing becomes publicly visible with status active.
6

Manage and close

Edit the listing as needed while it is active. When the due date passes (or a partner manually closes it), the listing status moves to closed.

Listing statuses and review orders

StatusDescription
activeListing is published and visible to the public
closedApplication window has ended
pendingReviewSubmitted for admin review before publishing
changesRequestedAdmin has requested edits before approval
pendingDraft saved but not yet submitted for review

Filtering and querying listings

The GET /listings endpoint accepts ListingsQueryParams for filtering. You can also use POST /listings/list with a ListingsQueryBody for richer filter expressions. Supported filter keys (ListingFilterKeys):
Filter keyDescription
statusFilter by ListingsStatusEnum value
jurisdictionFilter by jurisdiction ID
nameSearch by listing name
city, zipCode, neighborhood, countiesGeographic filters
bedrooms, bathrooms, bedroomTypesUnit type filters
monthlyRentMaximum rent filter
availability, availabilitiesAvailability state filter
reservedCommunityTypesFilter by reserved community type
multiselectQuestionsFilter by associated preference/program
listingFeaturesFilter by accessibility or building features
section8AcceptanceFilter by Section 8 acceptance
homeTypesFilter by home type
regions, configurableRegionsFilter by region
parkingTypeFilter by parking type
isVerifiedFilter by verified status
leasingAgentFilter by leasing agent
listingTypeFilter by listing type
idsFetch specific listings by ID array

API endpoints

MethodPathDescription
GET/listingsGet a paginated set of listings with query param filters
POST/listings/listGet a paginated set of listings with body-based filters
GET/listings/:idGet a single listing by UUID
GET/listings/external/:idGet a listing formatted for external consumption
POST/listingsCreate a new listing
POST/listings/duplicateDuplicate an existing listing
PUT/listings/:idUpdate a listing by UUID
DELETE/listingsDelete a listing by ID (passed in request body)
PUT/listings/closeListingsTrigger the automated listing-close cron job
GET/listings/mapMarkersGet map marker data for all active listings
GET/listings/csvExport listings and units as a ZIP of CSV files
GET/listings/csvSecureSecure CSV export (returns a signed URL)
GET/listings/byMultiselectQuestion/:idGet listing IDs associated with a multiselect question
GET/listings/byProperty/:propertyIdGet listing IDs associated with a property
POST /listings and PUT /listings/:id use the ListingCreateUpdateValidationPipe, which performs additional DTO manipulation and enforces publish-time validation rules beyond standard class-validator decorators.

CSV export

The GET /listings/csv endpoint returns a ZIP archive containing CSV files for listings and their associated units. Query parameters are defined by ListingCsvQueryParams. Access requires both an API key and partner-level permissions. The secure variant GET /listings/csvSecure returns a signed URL instead of streaming the file directly, which is suitable for use cases where the client needs to download the file independently.
CSV exports include all unit-level data including AMI limits and rent amounts. Ensure the requesting user has appropriate permissions before exposing this endpoint.

Build docs developers (and LLMs) love