OpenAPI spec
OpenAPI spec
Last updated 5/3/2026
ZoomProp API — OpenAPI 3.1 Specification
Endpoint Summary Table
| # | Method | Path | Tag | Auth Required |
|---|---|---|---|---|
| 1 | POST | /api/actions/analyze-property-investigation | Actions | ✅ |
| 2 | GET, POST | /api/ai-search-templates | AI Search | ✅ |
| 3 | POST | /api/ai/analysis | AI | ✅ |
| 4 | POST | /api/ai/chat | AI | ✅ |
| 5 | POST | /api/ai/commercial-analysis | AI | ✅ |
| 6 | POST | /api/ai/commercial-estimates | AI | ✅ |
| 7 | GET, DELETE | /api/ai/conversations/{id} | AI Conversations | ✅ |
| 8 | GET, POST | /api/ai/conversations | AI Conversations | ✅ |
| 9 | POST | /api/ai/generate-title | AI | ✅ |
| 10 | POST | /api/ai/intent | AI | ✅ |
| 11 | POST | /api/ai/maintenance-analysis | AI | ✅ |
| 12 | POST | /api/ai/offer-analysis | AI | ✅ |
| 13 | GET | /api/ai/performance-monitoring | AI | ✅ |
| 14 | GET, POST | /api/ai/personas | AI | ✅ |
| 15 | POST | /api/ai/property-analysis | AI | ✅ |
| 16 | POST | /api/ai/property-inspection-analysis | AI | ✅ |
| 17 | POST | /api/ai/suggest-tags | AI | ✅ |
| 18 | POST | /api/ai/suggestions | AI | ✅ |
| 19 | GET, POST, DELETE | /api/alert-filters/assignments | Alert Filters | ✅ |
| 20 | GET, POST, PUT, DELETE | /api/alert-filters | Alert Filters | ✅ |
| 21 | GET, POST, PUT | /api/alerts/configure | Alerts | ✅ |
| 22 | GET | /api/alerts/history | Alerts | ✅ |
| 23 | POST | /api/alerts/messages/archive | Alerts | ✅ |
| 24 | POST | /api/alerts/messages/unarchive | Alerts | ✅ |
| 25 | GET, PUT | /api/alerts/preferences | Alerts | ✅ |
| 26 | POST | /api/alerts/test | Alerts | ✅ |
| 27 | POST | /api/alerts/trigger | Alerts | ✅ |
| 28 | GET | /api/alerts/users | Alerts | ✅ |
| 29 | GET | /api/analytics-dashboard | Analytics | ✅ |
| 30 | GET | /api/analytics/appreciation-distribution | Analytics | ✅ |
| 31 | GET | /api/analytics/markets | Analytics | ✅ |
| 32 | GET | /api/analytics/performance | Analytics | ✅ |
| 33 | GET | /api/analytics/portfolio | Analytics | ✅ |
| 34 | GET | /api/analytics/properties | Analytics | ✅ |
| 35 | GET, POST | /api/articles | Content | ✅ |
| 36 | GET, PUT | /api/auth/active-org | Auth | ✅ |
| 37 | GET | /api/auth/session | Auth | ✅ |
| 38 | GET | /api/auth/test | Auth | ✅ |
| 39 | GET | /api/automation/analytics | Automation | ✅ |
| 40 | GET, PUT | /api/automation/board-config | Automation | ✅ |
openapi: 3.1.0
info:
title: ZoomProp AI Platform API
version: 0.1.0
description: |
ZoomProp is an AI-powered real estate investment intelligence platform.
This API provides endpoints for property analysis, portfolio management,
AI-assisted conversations, alert management, and market analytics.
**Authentication**: All protected endpoints require a valid Clerk session
token passed as a Bearer token in the `Authorization` header. Organization
context is resolved automatically from the session's active organization.
**Base path**: All routes are prefixed with `/api` and served from the
Next.js application server.
contact:
name: ZoomProp Engineering
email: engineering@zoomprop.com
url: https://zoomprop.com
license:
name: Private — All Rights Reserved
url: https://zoomprop.com/terms
servers:
- url: https://api.zoomprop.com
description: Production
- url: https://api-staging.zoomprop.com
description: Staging
- url: http://localhost:3000
description: Local development (Next.js dev server)
tags:
- name: Actions
description: >
Agentic action endpoints that trigger multi-step AI workflows,
such as deep property investigation pipelines.
- name: AI
description: >
Core AI inference endpoints powering property analysis, chat,
intent detection, tag suggestions, and financial estimates.
- name: AI Conversations
description: >
Conversation session management — create, list, retrieve, and
delete AI chat sessions with full message history.
- name: AI Search
description: >
AI-assisted search template management for saving and replaying
structured property search queries.
- name: Alert Filters
description: >
Reusable saved filter definitions and their assignments to users
or organization members for property alert subscriptions.
- name: Alerts
description: >
End-to-end alert system: configuration, delivery preferences,
message history, archival, triggering, and test dispatch.
- name: Analytics
description: >
Market, portfolio, property, performance, and appreciation analytics
powering dashboard visualisations and reporting.
- name: Auth
description: >
Session introspection, active-organisation switching, and
lightweight connectivity checks for the Clerk auth layer.
- name: Automation
description: >
Deal pipeline board configuration and automation analytics covering
stage transitions and workflow performance.
- name: Content
description: >
Platform content management for articles, market commentary,
and editorial pieces surfaced in the investor feed.
security:
- ClerkBearerAuth: []
# ─────────────────────────────────────────────────────────────────────────────
# PATHS
# ─────────────────────────────────────────────────────────────────────────────
paths:
# ── ACTIONS ──────────────────────────────────────────────────────────────
/api/actions/analyze-property-investigation:
post:
operationId: analyzePropertyInvestigation
tags: [Actions]
summary: Trigger a deep property investigation analysis
description: >
Initiates a multi-step LangGraph/LangChain agentic pipeline that
performs a comprehensive due-diligence investigation on a target
property. The pipeline collects market comps, financial projections,
risk signals, and inspection history before returning a structured
report.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyInvestigationRequest'
responses:
'200':
description: Investigation analysis completed successfully
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyInvestigationResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── AI SEARCH TEMPLATES ──────────────────────────────────────────────────
/api/ai-search-templates:
get:
operationId: listAISearchTemplates
tags: [AI Search]
summary: List saved AI search templates
description: >
Returns all AI-generated or user-saved search templates for the
authenticated user's organisation. Templates encode structured
property search criteria that can be replayed or shared.
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/LimitParam'
responses:
'200':
description: Paginated list of search templates
content:
application/json:
schema:
$ref: '#/components/schemas/AISearchTemplateListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createAISearchTemplate
tags: [AI Search]
summary: Save a new AI search template
description: >
Persists a structured property search query as a named template
for future reuse. The template can include natural-language intent,
filter criteria, and geographic scope.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AISearchTemplateCreateRequest'
responses:
'200':
description: Template created
content:
application/json:
schema:
$ref: '#/components/schemas/AISearchTemplate'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── AI — CORE INFERENCE ──────────────────────────────────────────────────
/api/ai/analysis:
post:
operationId: runAIAnalysis
tags: [AI]
summary: Run a general-purpose AI property analysis
description: >
Accepts a property context payload and returns an AI-generated
analytical report covering investment potential, market positioning,
and risk factors using the configured OpenAI model.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AIAnalysisRequest'
responses:
'200':
description: Analysis report generated
content:
application/json:
schema:
$ref: '#/components/schemas/AIAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/chat:
post:
operationId: sendAIChatMessage
tags: [AI]
summary: Send a message to the AI assistant (streaming)
description: >
Processes a user message within an investment-context conversation.
Supports streaming via the Vercel AI SDK (`@ai-sdk/react`). The
assistant has access to property data, portfolio context, and market
knowledge. Requires an active conversation ID in the request body.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AIChatRequest'
responses:
'200':
description: >
Streaming text response (Server-Sent Events / data stream format
per Vercel AI SDK protocol).
content:
text/event-stream:
schema:
type: string
description: AI SDK data stream chunks
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/commercial-analysis:
post:
operationId: runCommercialAnalysis
tags: [AI]
summary: Run AI analysis on a commercial property
description: >
Performs commercial real estate analysis including NOI, cap rate
valuation, tenant mix assessment, and lease expiry risk for office,
retail, and industrial asset classes.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CommercialAnalysisRequest'
responses:
'200':
description: Commercial analysis report
content:
application/json:
schema:
$ref: '#/components/schemas/CommercialAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/commercial-estimates:
post:
operationId: getCommercialEstimates
tags: [AI]
summary: Generate AI-powered financial estimates for a commercial property
description: >
Returns AI-generated financial estimates — including projected
rent, vacancy assumptions, operating expense ratios, and cap rates —
for a commercial property based on address, asset class, and
available comparable data.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/CommercialEstimatesRequest'
responses:
'200':
description: Financial estimates generated
content:
application/json:
schema:
$ref: '#/components/schemas/CommercialEstimatesResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/generate-title:
post:
operationId: generateConversationTitle
tags: [AI]
summary: Generate a title for an AI conversation
description: >
Given the first message or a brief summary of a conversation,
returns a concise AI-generated title suitable for display in the
conversation list sidebar.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateTitleRequest'
responses:
'200':
description: Generated title
content:
application/json:
schema:
$ref: '#/components/schemas/GenerateTitleResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/intent:
post:
operationId: detectAIIntent
tags: [AI]
summary: Detect user intent from a natural-language query
description: >
Classifies a natural-language user query into a structured intent
object (e.g., property search, market inquiry, portfolio question),
enabling downstream routing to the appropriate AI or data handler.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/IntentRequest'
responses:
'200':
description: Detected intent classification
content:
application/json:
schema:
$ref: '#/components/schemas/IntentResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/maintenance-analysis:
post:
operationId: runMaintenanceAnalysis
tags: [AI]
summary: Analyse maintenance needs for a property
description: >
Processes property age, condition data, and inspection records to
produce an AI-generated maintenance risk assessment and prioritised
capital expenditure forecast.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/MaintenanceAnalysisRequest'
responses:
'200':
description: Maintenance analysis report
content:
application/json:
schema:
$ref: '#/components/schemas/MaintenanceAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/offer-analysis:
post:
operationId: runOfferAnalysis
tags: [AI]
summary: Analyse an offer relative to market conditions
description: >
Evaluates a proposed purchase offer against recent comparable sales,
market trend data, and property fundamentals to produce an AI
recommendation on offer strength, negotiation headroom, and
projected returns at the offered price.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/OfferAnalysisRequest'
responses:
'200':
description: Offer analysis report
content:
application/json:
schema:
$ref: '#/components/schemas/OfferAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/performance-monitoring:
get:
operationId: getAIPerformanceMetrics
tags: [AI]
summary: Retrieve AI system performance metrics
description: >
Returns operational telemetry for the AI subsystem — including
model latency, token usage, error rates, and cost metrics —
scoped to the authenticated organisation. Used for internal
observability dashboards.
parameters:
- name: period
in: query
description: Time period for metrics aggregation
required: false
schema:
type: string
enum: [1h, 24h, 7d, 30d]
default: 24h
responses:
'200':
description: AI performance metrics
content:
application/json:
schema:
$ref: '#/components/schemas/AIPerformanceMetrics'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/personas:
get:
operationId: listAIPersonas
tags: [AI]
summary: List available AI assistant personas
description: >
Returns the set of configurable AI assistant personas available
to the organisation (e.g., Conservative Investor, Aggressive
Growth, Income-Focused). Each persona tunes the AI's analytical
framing and risk tolerance.
responses:
'200':
description: List of personas
content:
application/json:
schema:
$ref: '#/components/schemas/AIPersonaListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createAIPersona
tags: [AI]
summary: Create a custom AI assistant persona
description: >
Defines a new AI persona with custom investment philosophy, risk
tolerance parameters, and preferred analytical lenses. Once
created, the persona can be selected per conversation session.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AIPersonaCreateRequest'
responses:
'200':
description: Persona created
content:
application/json:
schema:
$ref: '#/components/schemas/AIPersona'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/property-analysis:
post:
operationId: runPropertyAnalysis
tags: [AI]
summary: Run a comprehensive AI property analysis
description: >
Performs a full investment-grade property analysis including
cap rate calculation (using the CapRateCalculationSchema inputs),
cash-on-cash return, gross rent multiplier, neighbourhood trends,
comparable sales, and AI-generated investment thesis.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyAnalysisRequest'
responses:
'200':
description: Property analysis report
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/property-inspection-analysis:
post:
operationId: runPropertyInspectionAnalysis
tags: [AI]
summary: Analyse a property inspection report
description: >
Processes structured or free-text property inspection data and
returns an AI-generated assessment of defect severity, estimated
remediation costs, and impact on investment viability.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyInspectionAnalysisRequest'
responses:
'200':
description: Inspection analysis report
content:
application/json:
schema:
$ref: '#/components/schemas/PropertyInspectionAnalysisResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/suggest-tags:
post:
operationId: suggestPropertyTags
tags: [AI]
summary: Suggest classification tags for a property
description: >
Given a property data payload, returns AI-suggested taxonomy tags
(e.g., "value-add", "turnkey", "distressed", "short-term-rental")
for classification and searchability within the platform.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SuggestTagsRequest'
responses:
'200':
description: Suggested tags
content:
application/json:
schema:
$ref: '#/components/schemas/SuggestTagsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/suggestions:
post:
operationId: getAISuggestions
tags: [AI]
summary: Get contextual AI chat suggestions
description: >
Returns a list of contextually relevant follow-up questions or
action prompts for the current conversation state. Used to
populate the quick-action chips in the chat interface.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/SuggestionsRequest'
responses:
'200':
description: List of suggestions
content:
application/json:
schema:
$ref: '#/components/schemas/SuggestionsResponse'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
# ── AI CONVERSATIONS ─────────────────────────────────────────────────────
/api/ai/conversations:
get:
operationId: listConversations
tags: [AI Conversations]
summary: List AI conversation sessions
description: >
Returns all conversation sessions for the authenticated user,
ordered by most recent activity. Each session includes its title,
message count, and last-updated timestamp.
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/LimitParam'
responses:
'200':
description: Paginated list of conversations
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createConversation
tags: [AI Conversations]
summary: Create a new AI conversation session
description: >
Initialises a new conversation session. Optionally accepts an
initial system context (e.g., a specific property, portfolio, or
market) and a persona ID to apply from the start.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationCreateRequest'
responses:
'200':
description: Conversation session created
content:
application/json:
schema:
$ref: '#/components/schemas/Conversation'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
/api/ai/conversations/{id}:
get:
operationId: getConversation
tags: [AI Conversations]
summary: Retrieve a specific conversation and its messages
description: >
Returns a full conversation session including its complete message
history, metadata, and any attached property or portfolio context.
parameters:
- $ref: '#/components/parameters/ConversationIdParam'
responses:
'200':
description: Conversation with messages
content:
application/json:
schema:
$ref: '#/components/schemas/ConversationWithMessages'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: deleteConversation
tags: [AI Conversations]
summary: Delete a conversation session
description: >
Permanently deletes a conversation session and all its messages.
This action is irreversible.
parameters:
- $ref: '#/components/parameters/ConversationIdParam'
responses:
'200':
description: Conversation deleted
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
# ── ALERT FILTERS ────────────────────────────────────────────────────────
/api/alert-filters:
get:
operationId: listAlertFilters
tags: [Alert Filters]
summary: List saved alert filter definitions
description: >
Returns all reusable property alert filter definitions belonging
to the authenticated organisation. Filters encode criteria such as
price range, property type, location, and financial thresholds.
parameters:
- $ref: '#/components/parameters/PageParam'
- $ref: '#/components/parameters/LimitParam'
responses:
'200':
description: List of alert filters
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilterListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createAlertFilter
tags: [Alert Filters]
summary: Create a new alert filter
description: >
Persists a new named alert filter definition with property search
criteria. Once created, the filter can be assigned to one or more
users via the `/api/alert-filters/assignments` endpoint.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilterCreateRequest'
responses:
'200':
description: Alert filter created
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilter'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
put:
operationId: updateAlertFilter
tags: [Alert Filters]
summary: Update an existing alert filter
description: >
Updates the criteria of an existing alert filter. The filter ID
must be provided in the request body. Assignments to users are
unaffected by this operation.
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilterUpdateRequest'
responses:
'200':
description: Alert filter updated
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilter'
'400':
$ref: '#/components/responses/BadRequest'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
delete:
operationId: deleteAlertFilter
tags: [Alert Filters]
summary: Delete an alert filter
description: >
Permanently deletes an alert filter and removes all associated
user assignments.
parameters:
- name: filterId
in: query
required: true
schema:
type: string
description: ID of the alert filter to delete
responses:
'200':
description: Alert filter deleted
content:
application/json:
schema:
$ref: '#/components/schemas/DeleteResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'404':
$ref: '#/components/responses/NotFound'
'500':
$ref: '#/components/responses/InternalServerError'
/api/alert-filters/assignments:
get:
operationId: listAlertFilterAssignments
tags: [Alert Filters]
summary: List alert filter assignments
description: >
Returns the mapping of alert filter definitions to the users
or organisation members they are currently assigned to.
parameters:
- name: filterId
in: query
required: false
schema:
type: string
description: Optionally scope assignments to a specific filter ID
responses:
'200':
description: List of assignments
content:
application/json:
schema:
$ref: '#/components/schemas/AlertFilterAssignmentListResponse'
'401':
$ref: '#/components/responses/Unauthorized'
'500':
$ref: '#/components/responses/InternalServerError'
post:
operationId: createAlertFilterAssignment
tags: [Alert Filters]
summary: Assign an alert filter to a user
description: >
Creates an assignment linking an alert filter to a specific user
within the organisation. The assigned user will begin receiving
alerts matching the filter's criteria.
requestBody:
required: