Weston
Developer API
Async co-living analysis

Weston API

Start an analysis, poll for the final report, and recompute completed runs with user overrides from your own backend. API keys are for trusted server-side code only.

Credentials

API Keys

Create named keys for production services, automations, and partner integrations. Full secrets are shown once at generation time.

Loading API keys...
Monitoring

Recent Usage

Only completed analyses started with a Weston API key appear here. Logged-in frontend runs are excluded from this table.

Loading usage...
Auth

Authentication

Direct API callers must use a Weston API key as a bearer token. Every endpoint documented here requires authentication and returns 401 for missing, invalid, or revoked credentials.

httpAuthorization header
Authorization: Bearer wk_live_...
The logged-in Weston app can also use a Supabase session, and the MCP integration can use a scoped Weston OAuth token. External partner integrations should use Weston API keys from this page.
Media

Photo Upload Intents

Create signed upload URLs before starting an analysis, upload each file with the returned method and headers, then pass the returned asset objects in inputs.photos or inputs.floor_plan_image.

POST/api/co-living/photo-assets/upload-intents
jsonRequest
{
  "files": [
    {
      "filename": "front.jpg",
      "content_type": "image/jpeg",
      "size_bytes": 1234567,
      "source": "uploaded",
      "caption": "Front exterior"
    }
  ]
}
jsonResponse
{
  "uploads": [
    {
      "upload_url": "https://storage.example/signed-put-url",
      "method": "PUT",
      "headers": {
        "Content-Type": "image/jpeg"
      },
      "asset": {
        "asset_id": "f8751c49-cc99-4215-95fc-f3891250c2d0",
        "source": "uploaded",
        "gcs_uri": "gs://bucket/photo_assets/co-living/user/batch/photo.jpg",
        "object_name": "photo_assets/co-living/user/batch/photo.jpg",
        "url": "https://storage.example/signed-read-url",
        "content_type": "image/jpeg",
        "caption": "Front exterior",
        "width": null,
        "height": null
      }
    }
  ]
}
Supported image types are JPEG, PNG, WEBP, and GIF. The default server limits are 25 files per request and 15 MB per file.
Account

Portfolio And Usage

Fetch portfolio rows and quota details for the authenticated Weston user.

MethodEndpointPurpose
GET/api/portfolioList all portfolio deals for the authenticated user.
PATCH/api/portfolio/{deal_id}Mark an error panel dismissed with { error_dismissed: true }.
DELETE/api/portfolio/{deal_id}Archive a portfolio deal.
GET/api/usageFetch report quota, remaining credits, reservations, and usage events for the authenticated user.
bashList portfolio
curl https://YOUR_DOMAIN/api/portfolio \
  -H "Authorization: Bearer wk_live_..."
jsonPortfolio response
{
  "deals": [
    {
      "id": "2f3f2d9f-08f6-4f5f-b9f2-5d2e7c9f70d1",
      "strategy": "co-living",
      "property_address": "123 Main St, Atlanta, GA",
      "listing_url": "https://example.com/listing",
      "status": "done",
      "analysis_slug": "atlanta-main-st-coliving",
      "created_at": "2026-05-14T12:00:00Z",
      "updated_at": "2026-05-14T12:06:00Z",
      "archived": false,
      "error_dismissed": false,
      "analysis_error": null,
      "failure_code": null
    }
  ],
  "summary": {
    "total": 1,
    "by_strategy": {
      "co-living": 1
    },
    "by_status": {
      "done": 1
    }
  }
}
bashGet usage
curl https://YOUR_DOMAIN/api/usage \
  -H "Authorization: Bearer wk_live_..."
jsonUsage response
{
  "quota": {
    "report_quota": 100,
    "reports_used": 26,
    "active_reservations": 1,
    "reports_remaining": 73
  },
  "reservations": {
    "total": 27,
    "reserved": 1,
    "consumed": 26,
    "released": 0
  },
  "usage": {
    "total_events": 26,
    "completed_analyses": 26,
    "by_strategy": {
      "co-living": 26
    },
    "by_route": {
      "analyze": 26
    }
  },
  "events": []
}
reports_remaining is computed from the configured quota minus completed analyses and active reservations. null means the account has unlimited report credits. Usage events contain completed analyses only; polls, denied calls, overrides, and failed runs are excluded from billable usage history.
Co-living

Quickstart

Run a co-living analysis when you need conversion feasibility, room revenue, project costs, and strategy-level outcomes.

Quickstart

Send a bearer API key, start an async run, then poll the run id until the status is terminal.

  1. Create a keyName it after the backend or workflow that will start co-living analyses.
  2. Start preflightPOST the property, listing URL, photos, optional floor plan, and analysis_tier. Omit analysis_tier for the default Pro run.
  3. Review the propertyPoll the deal until status is review or onboarding, then inspect property_summary.
  4. Complete underwritingPOST the reviewed assumptions to the complete endpoint; the original start already reserved the report credit.
  5. Follow upUse scenarios, explain-metric, assumptions, versions, messages, or the dashboard URL after status is done.
bashStart a co-living run
curl -X POST https://YOUR_DOMAIN/api/co-living/analyze \
  -H "Authorization: Bearer wk_live_..." \
  -H "Content-Type: application/json" \
  -d '{
  "property": {
    "address": "123 Main St, Atlanta, GA",
    "listing_url": "https://example.com/listing"
  },
  "analysis_tier": "pro",
  "inputs": {
    "photos": [
      { "url": "https://example.com/kitchen.jpg" }
    ],
    "floor_plan_image": null,
    "preferences": {
      "aggressiveness": "max_viable",
      "optimize_for": "revenue",
      "target_market_segment": "workforce"
    },
    "user_overrides": {},
    "buy_box": {
      "cash_flow_threshold": 500,
      "cash_on_cash_threshold": 0.07
    }
  },
  "metadata": {
    "client_reference_id": "coliving-lead-77"
  }
}'
Co-living

Endpoints

Use these endpoints for co-living analysis lifecycle operations.

MethodEndpointPurpose
POST/api/co-living/analyzeStart a coliving_v2 deal. analysis_tier defaults to pro; pass flash for a Flash run. The public run_id is the v2 deal slug.
GET/api/co-living/analyze/{run_id}Fetch status or final result. Add ?status_only=true for a lightweight status envelope.
POST/api/co-living/analyze/{run_id}/completeConfirm reviewed property details and run full underwriting.
GET/api/co-living/analyze/{run_id}/editable-fieldsList dashboard-editable fields. Add scenario_id for scenario-specific fields.
GET/api/co-living/analyze/{run_id}/scenariosList available scenarios and active scenario metadata.
POST/api/co-living/analyze/{run_id}/explain-metricExplain a metric for the completed deal.
PATCH/api/co-living/analyze/{run_id}/assumptionsApply dashboard-style updates through the shared v2 tool.
POST/api/co-living/analyze/{run_id}/scenariosCreate a custom scenario from a natural-language description.
POST/api/co-living/analyze/{run_id}/messagesEnqueue a follow-up chat or agent turn for the existing deal.
GET/api/co-living/analyze/{run_id}/jobs/{job_id}Fetch durable job status plus the latest deal envelope.
GET/api/co-living/analyze/{run_id}/jobs/{job_id}/eventsFetch incremental stream events. Add after_seq to resume.
POST/api/co-living/photo-assets/upload-intentsCreate signed upload URLs for photos and floor plans.
GET/api/co-living/analyze/{run_id}/image?url=...Proxy owned v2 deal/listing images through allow-list checks.
GET/api/co-living/overrides/schemaList editable v2 path families and supported operations.
PATCH/api/co-living/analyze/{run_id}/overridesApply one or many value edits with updates: [{ field_path, new_value, operation }].
DELETE/api/co-living/analyze/{run_id}/overridesClear all active v2 session and scenario overrides.
POST/api/co-living/analyze/{run_id}/scenarios/{scenario_id}/activateSwitch the active scenario.
POST/api/co-living/analyze/{run_id}/scenarios/replanReplan scenarios after room, bedroom, or bath corrections.
POST/api/co-living/analyze/{run_id}/roomsAdd rooms, optionally triggering scenario replanning.
DELETE/api/co-living/analyze/{run_id}/rooms/{room_id}Remove a room, optionally triggering scenario replanning.
GET/api/co-living/analyze/{run_id}/versionsList v2 deal versions.
GET/api/co-living/analyze/{run_id}/versions/{version_id}Fetch one version and its snapshot.
POST/api/co-living/analyze/{run_id}/versions/{version_id}/revertRestore a historical v2 version and create a new current version.
Co-living

Start Request

Use property for address and listing context, analysis_tier for Pro or Flash, inputs for media and modeling preferences, and metadata for your own reference id. Missing analysis_tier defaults to pro.

jsonRequest
{
  "property": {
    "address": "123 Main St, Atlanta, GA",
    "listing_url": "https://example.com/listing"
  },
  "analysis_tier": "pro",
  "inputs": {
    "photos": [
      {
        "url": "https://example.com/kitchen.jpg"
      }
    ],
    "floor_plan_image": null,
    "preferences": {
      "aggressiveness": "max_viable",
      "optimize_for": "revenue",
      "target_market_segment": "workforce"
    },
    "user_overrides": {},
    "buy_box": {
      "cash_flow_threshold": 500,
      "cash_on_cash_threshold": 0.07
    }
  },
  "metadata": {
    "client_reference_id": "coliving-lead-77"
  }
}
json202 response
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "analysis_tier": "pro",
  "status": "queued",
  "job_id": "job_01JZ9A2Z9V0V2K8T7D3D5E6F7G",
  "created_at": "2026-05-26T12:00:00Z",
  "api_contract_version": "2026-05-31",
  "poll_url": "/api/co-living/analyze/atlanta-main-st-coliving",
  "dashboard_url": "/reports/co-living/atlanta-main-st-coliving",
  "next_action": "Preflight is running (~2-3 min). Poll until status is review, then complete the analysis.",
  "metadata": {
    "api_contract_version": "2026-05-31",
    "session_id": "sess_01JZ9A2YQW5G9T6A6S1ZZT4K7R",
    "deal_slug": "atlanta-main-st-coliving",
    "analysis_tier": "pro",
    "dashboard_url": "/reports/co-living/atlanta-main-st-coliving",
    "client_reference_id": "coliving-lead-77"
  }
}
Co-living

Polling Responses

The co-living run moves from queued or running into review, onboarding, done, error, or not_suitable. Add ?status_only=true to omit data and overrides for lightweight status checks.

jsonReview
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "status": "review",
  "next_action": "Property mapped. Review property_summary with the user, then call the complete endpoint to run full underwriting.",
  "property": {
    "address": "123 Main St, Atlanta, GA",
    "listing_url": "https://example.com/listing"
  },
  "property_summary": {
    "bedroom_count": 3,
    "full_bathroom_count": 2,
    "rooms": []
  },
  "data": {},
  "overrides": {},
  "error": {
    "message": null,
    "code": null
  },
  "metadata": {
    "api_contract_version": "2026-05-31",
    "status_values": [
      "queued",
      "running",
      "review",
      "onboarding",
      "done",
      "error",
      "not_suitable"
    ],
    "session_id": "sess_01JZ9A2YQW5G9T6A6S1ZZT4K7R",
    "deal_slug": "atlanta-main-st-coliving",
    "dashboard_url": "/reports/co-living/atlanta-main-st-coliving",
    "client_reference_id": "coliving-lead-77",
    "created_at": "2026-05-26T12:00:00Z",
    "updated_at": "2026-05-26T12:01:00Z",
    "completed_at": null,
    "recomputed_at": null
  }
}
jsonDone
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "status": "done",
  "next_action": "Analysis complete. Use explain, assumptions, scenarios, or versions endpoints for follow-ups.",
  "property": {
    "address": "123 Main St, Atlanta, GA",
    "listing_url": "https://example.com/listing"
  },
  "data": {
    "property_summary": {},
    "scenario_set": {},
    "deal_analysis": {},
    "recommendation_summary": {},
    "v2_analysis_result": {}
  },
  "v2_analysis_result": {},
  "recommended_scenario_id": "baseline",
  "overrides": {},
  "report_version": {
    "id": "fb9d7e8c-8ec1-4b98-bf62-13f089df8a21",
    "version_number": 1,
    "created_at": "2026-05-26T12:08:00Z",
    "history_url": "/api/co-living/analyze/atlanta-main-st-coliving/versions"
  },
  "error": {
    "message": null,
    "code": null
  },
  "metadata": {
    "api_contract_version": "2026-05-31",
    "status_values": [
      "queued",
      "running",
      "review",
      "onboarding",
      "done",
      "error",
      "not_suitable"
    ],
    "session_id": "sess_01JZ9A2YQW5G9T6A6S1ZZT4K7R",
    "deal_slug": "atlanta-main-st-coliving",
    "dashboard_url": "/reports/co-living/atlanta-main-st-coliving",
    "client_reference_id": "coliving-lead-77",
    "created_at": "2026-05-26T12:00:00Z",
    "updated_at": "2026-05-26T12:08:00Z",
    "completed_at": "2026-05-26T12:08:00Z",
    "recomputed_at": null,
    "report_version_number": 1
  }
}
jsonTerminal non-success
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "status": "not_suitable",
  "property": {
    "address": "123 Main St, Atlanta, GA",
    "listing_url": "https://example.com/listing"
  },
  "data": null,
  "overrides": {},
  "error": {
    "message": "This property is not suitable for co-living conversion.",
    "code": "unsupported_property_type"
  },
  "metadata": {
    "api_contract_version": "2026-05-31",
    "status_values": [
      "queued",
      "running",
      "review",
      "onboarding",
      "done",
      "error",
      "not_suitable"
    ],
    "session_id": "sess_01JZ9A2YQW5G9T6A6S1ZZT4K7R",
    "deal_slug": "atlanta-main-st-coliving",
    "dashboard_url": "/reports/co-living/atlanta-main-st-coliving",
    "client_reference_id": "coliving-lead-77",
    "created_at": "2026-05-26T12:00:00Z",
    "updated_at": "2026-05-26T12:04:00Z",
    "completed_at": null,
    "recomputed_at": null
  }
}
The co-living public run_id is the v2 deal slug. Responses also include metadata.session_id, metadata.dashboard_url, and next_action. GET /api/co-living/analyze/{run_id}/report.pdf returns 410 Gone.
Co-living

Complete And Follow Up

These endpoints are REST aliases over the same coliving_v2 tool routes used by MCP, email, WhatsApp, and the dashboard.

jsonComplete analysis
{
  "property_summary_patches": {
    "bedroom_count": 4
  },
  "property_inputs": {
    "purchase_price": 700000,
    "insurance_annual": 1800
  },
  "target_bedroom_count": 4,
  "scenario_generation_mode": "explore_and_recommend",
  "package_selections": {},
  "financing_preferences": {},
  "operating_assumptions": {}
}
httpTool calls
GET /api/co-living/analyze/{run_id}/editable-fields?scenario_id=baseline
GET /api/co-living/analyze/{run_id}/scenarios

POST /api/co-living/analyze/{run_id}/explain-metric
{
  "metric_id": "cash_on_cash_pct",
  "scenario_id": "baseline",
  "question": "Why did this change?"
}

PATCH /api/co-living/analyze/{run_id}/assumptions
{
  "updates": [
    {
      "field_path": "operating.occupancy_rate_pct",
      "new_value": 91
    }
  ],
  "rationale": "Operator expects a stabilized lease-up."
}

POST /api/co-living/analyze/{run_id}/scenarios
{
  "description": "Convert the office into a compliant bedroom and compare yield.",
  "base_scenario_id": "baseline",
  "target_bedroom_count": 4
}
Completion, tool calls, and edits do not reserve extra report credits. /assumptions is the dashboard-style edit path; /overrides remains available for low-level path patches.
Co-living

Low-level Overrides

Co-living v2 overrides apply path-level edits without consuming report credits. Prefer /assumptions for dashboard-style updates.

jsonPatch overrides
{
  "updates": [
    {
      "field_path": "financing.purchase_price",
      "new_value": 650000,
      "operation": "set"
    },
    {
      "field_path": "operating.occupancy_rate_pct",
      "new_value": 92,
      "operation": "set"
    }
  ]
}
httpClear overrides
DELETE /api/co-living/analyze/{run_id}/overrides
jsonSchema response
{
  "override_mode": "patch",
  "schema_version": "2026-05-31",
  "supported_operations": [
    "set",
    "revert",
    "remove",
    "add_custom_line_item"
  ],
  "paths": [
    "property_inputs.*",
    "assumptions.*",
    "assumptions.financing_strategies.{strategy}.*",
    "property_summary.rooms.{room_id}.*",
    "financing.*",
    "operating.*",
    "income.per_bedroom_estimates.{room_id}.weekly_rate",
    "conversion_cost.*",
    "scenarios.{scenario_id}.*"
  ],
  "fields": [
    {
      "path": "financing.purchase_price",
      "type": "number",
      "min": 0,
      "operation": "set"
    },
    {
      "path": "operating.occupancy_rate_pct",
      "type": "number",
      "min": 0,
      "max": 100,
      "operation": "set"
    },
    {
      "path": "conversion_cost.custom_items",
      "type": "object",
      "operation": "add_custom_line_item"
    },
    {
      "path": "conversion_cost.custom_items.{item_id}.estimated_cost",
      "type": "number",
      "min": 0,
      "operation": "set"
    },
    {
      "path": "conversion_cost.custom_items.{item_id}",
      "type": "void",
      "operation": "remove"
    },
    {
      "path": "conversion_cost.per_room.{room_id}.custom_line_items.{item_id}.estimated_cost",
      "type": "number",
      "min": 0,
      "operation": "set"
    },
    {
      "path": "conversion_cost.per_room.{room_id}.custom_line_items.{item_id}",
      "type": "void",
      "operation": "remove"
    },
    {
      "path": "scenarios.{scenario_id}.conversion_cost.per_room.{room_id}.custom_line_items.{item_id}.estimated_cost",
      "type": "number",
      "min": 0,
      "operation": "set"
    },
    {
      "path": "scenarios.{scenario_id}.conversion_cost.per_room.{room_id}.custom_line_items.{item_id}",
      "type": "void",
      "operation": "remove"
    }
  ]
}
Use GET /api/co-living/overrides/schema to discover editable path families and supported operations. Send updates with operation: "set", "remove", "add_custom_line_item", or "revert".
History

Report Versions

Completed reports automatically capture an original version. Override edits and reverts create additional immutable versions.

GET/api/co-living/analyze/{run_id}/versions
GET/api/co-living/analyze/{run_id}/versions/{version_id}
POST/api/co-living/analyze/{run_id}/versions/{version_id}/revert
jsonList versions
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "current_version": {
    "id": "a9cd5a6a-6cd3-4541-9f0f-ea823fa7d319",
    "version_number": 2,
    "created_at": "2026-05-14T12:10:00Z",
    "history_url": "/api/co-living/analyze/atlanta-main-st-coliving/versions"
  },
  "versions": [
    {
      "id": "a9cd5a6a-6cd3-4541-9f0f-ea823fa7d319",
      "version_number": 2,
      "event_type": "edit",
      "created_at": "2026-05-14T12:10:00Z",
      "changed_fields": [
        {
          "path": "financing.purchase_price",
          "before": 700000,
          "after": 650000,
          "action": "changed"
        }
      ],
      "reverted_to_version_id": null,
      "is_current": true
    }
  ]
}
jsonRevert response
{
  "run_id": "atlanta-main-st-coliving",
  "strategy": "co-living",
  "reverted_to_version": {
    "id": "60ac21d0-503b-4a99-8a99-3d39919a7c80",
    "version_number": 1,
    "created_at": "2026-05-14T12:06:00Z",
    "history_url": "/api/co-living/analyze/atlanta-main-st-coliving/versions"
  },
  "current_version": {
    "id": "e9c70670-419e-407a-9dcc-44bdbd85cc38",
    "version_number": 3,
    "created_at": "2026-05-14T12:15:00Z",
    "history_url": "/api/co-living/analyze/atlanta-main-st-coliving/versions"
  },
  "result": {}
}
Reverting the current version returns 409. Unknown or inaccessible versions return 404.
Reliability

Status Codes And Billing

Report credits are reserved at start time and consumed only when the run reaches status done. Failed terminal states release the reservation.

Billable event
status = done
Not billable
polls, overrides, failed runs
Terminal states
done, error, not_suitable
json429 response
{
  "detail": "Request rate limit exceeded. Retry after 42 seconds.",
  "retry_after_seconds": 42,
  "limit": 600,
  "window": "1 minute"
}
API keys default to 600 reads per minute, 50 analysis starts per hour, and 200 analysis starts per day. Read and override endpoints share the per-minute request bucket. Analysis starts use the hourly and daily analysis buckets. If rate-limit storage is unavailable, Weston returns 503 instead of bypassing throttles.
StatusMeaning
400Invalid JSON, invalid payload, missing query parameter, or invalid override path/value.
401Missing, invalid, or revoked API key.
402No report credits remaining.
403Authenticated caller is not allowed to access the requested resource or image URL.
404Run, deal, photo asset, or version not found, including resources owned by another user.
409Stale optimistic-lock timestamp or invalid report-version revert.
410Deprecated route, including co-living v2 PDF export.
422The run state does not allow this operation, or the run predates override support.
429Request or analysis rate limit exceeded. Check Retry-After.
500 / 502Weston or upstream strategy backend failure.
503Temporary database, photo service, reporting, or rate-limit service unavailability.