Handoff — Express Project Setup (Fast-Track)
Actionable work drafted from the gaps · Onboarding · view the flow →
Backend contract · Backend agent · 18 endpoints
Backend contract — Express Project Setup (Fast-Track)
Drafted by the Dovel Team Product agent for the Backend agent from the Onboarding flow. These endpoints are required by the design but not yet confirmed in code. Review, refine, and implement.- Flow: Express Project Setup (Fast-Track) — Get a new real-estate project fully set up — property, deal numbers, build scope, and payment wallet — in a guided 4-step wizard.
- Area: Onboarding
- Endpoints: 18 unconfirmed
POST /projects
Create draft project on Fast-Track wizard entry; also creates owner membership and empty budget.
- Auth: required · Domain: projects
- Request:
name (optional, defaults 'Untitled Project'), type=fast_track - Response:
201 {id, status:'draft', owner_membership_id, budget_id, created_at} - Errors: 401 unauth; 422 invalid payload
GET /projects/{project_id}/setup-status
Return resume point and per-section completion (property, deal numbers, build scope, wallet) for wizard shell polling.
- Auth: required · Domain: projects
- Request:
project_id (path) - Response:
200 {project_id, current_step, sections:{property:'complete|incomplete|skipped', deal_details:..., build_scope:..., wallet:...}, updated_at} - Errors: 401 unauth; 403 not a member; 404 project not found
GET /properties/search
Search property records by user-entered address query; drives one-match vs multiple/no-match outcomes.
- Auth: required · Domain: properties
- Request:
q (address string, min completeness validated client-side), limit (optional) - Response:
200 {results:[{property_ref, address_line1, city, state, zip, property_type}], match_count} - Errors: 401 unauth; 400 q missing/too incomplete; 404 none found (or empty results)
PATCH /projects/{project_id}/property
Save confirmed match or manually entered/edited property details on the project.
- Auth: required · Domain: projects
- Request:
project_id (path); property_ref (if matched) OR manual fields: address_line1, address_line2, city, state, zip, property_type, year_built, sqft, lot_size - Response:
200 {project_id, property:{...saved fields}, status:'saved'} - Errors: 400 validation (missing required address fields); 401 unauth; 403 not a member; 404 project not found; 409 conflict/stale version
POST /projects/{project_id}/deal-details
Save top-level project cost screen: purchase price and setup estimates (rehab, ARV, financing assumptions).
- Auth: required · Domain: projects
- Request:
project_id (path); purchase_price, rehab_costs, arv, financing:{down_payment_pct, interest_rate, loan_term_months, loan_amount} - Response:
201 {project_id, deal_details_id, saved_at, computed:{total_project_cost}} - Errors: 400 invalid amounts/negative values; 401 unauth; 403 not a member; 404 project not found; 409 already finalized
POST /projects/{project_id}/profitability-details
Save Profitability Details screen: expected sale price and monthly interest; returns computed profitability outputs.
- Auth: required · Domain: projects
- Request:
project_id (path); expected_sale_price, monthly_interest, holding_months (optional) - Response:
201 {project_id, saved_at, computed:{net_profit, roi, margin}} - Errors: 400 invalid values; 401 unauth; 403 not a member; 404 project not found; 409 deal-details missing prerequisite
POST /projects/{project_id}/budget/initialize
Seed the project budget from a selected scope config template / selected line items
- Auth: required · Domain: financial
- Request:
project_id (path), template_id (optional), line_items[] {scope_item_id, name, category, quantity, unit_cost, total} , currency - Response:
201 {budget_id, project_id, status:'initialized', line_items[], total_budget} - Errors: 400 invalid line items/template, 401 unauth, 404 project not found, 409 budget already initialized
GET /budget/catalog
Return full scope config hierarchy for rehab-type picker and Add Item picker
- Auth: required · Domain: budget
- Request:
none (optional query: region_id, rehab_type) - Response:
200 {categories[] {id, name, children[] {id, name, line_items[] {id, name, unit, default_cost}}}} - Errors: 401 unauth, 500 catalog unavailable
GET /costs/project-estimate
Return all available scope estimates for a region to seed the budget UI
- Auth: required · Domain: costs
- Request:
query: region_id (required), project_id (optional), rehab_type (optional) - Response:
200 {region_id, estimates[] {scope_item_id, name, low, median, high, unit}, generated_at} - Errors: 400 missing/invalid region_id, 401 unauth, 404 region not found
POST /open-banking/link-token
Create an open-banking Link token to initialize the account-link flow
- Auth: required · Domain: open-banking
- Request:
project_id, user_id, redirect_uri (optional), products[] (optional) - Response:
201 {link_token, expiration, institution_count} - Errors: 401 unauth, 403 wallet not eligible, 429 rate limited
POST /open-banking/link
Exchange link flow result (public token / credentials) to link accounts to the project wallet
- Auth: required · Domain: open-banking
- Request:
project_id, public_token or institution credentials payload, account_selection[] (optional account_ids) - Response:
201 {link_id, accounts[] {account_ref, bank_name, mask, account_type, is_default}} - Errors: 400 invalid token/payload, 401 unauth, 402 link failed/institution error, 409 already linked
GET /open-banking/accounts
List connected bank accounts with default flagged for wallet selection
- Auth: required · Domain: open-banking
- Request:
query: project_id (optional filter) - Response:
200 {accounts[] {account_ref, bank_name, mask, account_type, balance, is_default, status}} - Errors: 401 unauth, 404 no accounts found
POST /wallet/setup-intent
Create a setup intent to tokenize/register a card or activate the wallet.
- Auth: required · Domain: wallet
- Request:
payment_method_type (card|bank_account), card fields if card: number, exp_month, exp_year, cvc (validated client-side) - Response:
201 {setup_intent_id, status: requires_action|succeeded, payment_method_id} - Errors: 400 invalid card fields, 401 unauth, 402 card declined, 409 wallet already active
GET /wallet/payment-methods
List activated payment methods for the account-activated confirmation screen.
- Auth: required · Domain: wallet
- Request:
none - Response:
200 {payment_methods: [{id, type, brand/last4, is_default, status: active}]} - Errors: 401 unauth, 404 wallet not found
POST /open-banking/accounts/{account_ref}/set-default
Set the selected linked account as the wallet default.
- Auth: required · Domain: open-banking
- Request:
account_ref (path) - Response:
200 {account_ref, is_default: true} - Errors: 401 unauth, 404 account not found, 409 account not linkable/inactive
GET /projects/{project_id}/setup-review
Full per-section review payload for the final Review setup screen (SCR-SETUP-07).
- Auth: required · Domain: projects
- Request:
project_id (path) - Response:
200 {property: {address, type, details}, deal_details: {purchase_price, rehab_costs, arv, financing}, profitability: {inputs, computed_outputs}, budget: {scope_line_items, total_estimate}, payment_method: {id, type, brand/last4, is_default}, sections_editable: [property, deal_details, budget, payment_method]} - Errors: 401 unauth, 404 project not found, 409 setup incomplete
GET /projects/{project_id}/deal-details
Read current deal details to prefill the project cost edit form.
- Auth: required · Domain: projects
- Request:
project_id (path) - Response:
200 {purchase_price, rehab_costs, arv, financing_assumptions: {down_payment_pct, interest_rate, loan_term, ...}} - Errors: 401 unauth, 404 project not found, 404 deal details not yet saved
GET /projects/{project_id}/profitability-details
Read profitability inputs and computed outputs to prefill the edit form.
- Auth: required · Domain: projects
- Request:
project_id (path) - Response:
200 {inputs: {...}, computed: {profit, roi, margin, ...}} - Errors: 401 unauth, 404 project not found, 404 profitability details not yet saved
*Generated 2026-10-11 · Dovel Team · dovel-team.dev.utom.dev*
Frontend build checklist · Frontend agent · 14 screens
Frontend build checklist — Express Project Setup (Fast-Track)
For Frontend agent, from the Onboarding flow. These screens are designed (and Ready for Dev) but have no Flutter page yet.- Flow: Express Project Setup (Fast-Track) — Get a new real-estate project fully set up — property, deal numbers, build scope, and payment wallet — in a guided 4-step wizard.
- Screens to build: 14
- ☐ project-setup/fast-track/step-1/unfield — wire: —
- ☐ User can choose to enter the property address manually via the unfield state, with no endpoints called until they proceed.
- ☐ User can advance to the field-entry screen; the unfield state persists no data on navigation back.
- ☐ project-setup/fast-track/step-1/field — wire: —
- ☐ User can enter a property address in the field input; system validates a minimum address completeness before enabling search.
- ☐ On submit, the app routes to the search screen and triggers GET /properties/search with the entered address.
- ☐ User can navigate back to the unfield state without saving partial input.
- ☐ project-setup/fast-track/step-1/search — wire:
GET /properties/search - ☐ On entry, the app calls GET /properties/search with the user's address query and displays matching property results.
- ☐ User can select a result and proceed to the matching outcome screen (one match found vs. multiple/no matches).
- ☐ If GET /properties/search returns no results or errors, the user sees a clear empty/error state with a retry option.
- ☐ project-setup/fast-track/step-1/one-search-found — wire: —
- ☐ When exactly one property match is returned, the user sees the single-match confirmation with the property's key details (address, type).
- ☐ User can confirm the match to continue to property data resolution, or go back to search to refine the query.
- ☐ project-setup/fast-track/step-1/all-property-data-found — wire:
PATCH /projects/{project_id}/property - ☐ When all property data is found, the screen pre-populates property details for user review.
- ☐ On confirm, the app calls PATCH /projects/{project_id}/property to save the property record and advances to Step 2.
- ☐ If PATCH /projects/{project_id}/property fails, the user sees an error and can retry without re-searching.
- ☐ project-setup/fast-track/step-1/all-property-not-found — wire:
PATCH /projects/{project_id}/property - ☐ When property data is incomplete or not found, the user can manually enter/edit the missing property fields.
- ☐ On save, the app calls PATCH /projects/{project_id}/property with the manually entered data and advances to Step 2.
- ☐ System validates required property fields (address, city, state, zip) before enabling save.
- ☐ project-setup/fast-track/step-2/P&L-capturing — wire:
POST /projects/{project_id}/deal-details,POST /projects/{project_id}/profitability-details - ☐ User can enter deal details (purchase price, rehab costs, ARV, financing assumptions); on save the app calls POST /projects/{project_id}/deal-details.
- ☐ User can enter profitability inputs; on save the app calls POST /projects/{project_id}/profitability-details and the screen reflects computed profitability outputs.
- ☐ System validates numeric fields (non-negative, required deal numbers) before enabling save and advance to Step 3.
- ☐ User can save and return later; previously saved deal and profitability details are reloaded on re-entry.
- ☐ project-setup/fast-track/step-3/build-scope — wire:
POST /projects/{project_id}/budget/initialize,GET /budget/catalog,GET /costs/project-estimate - ☐ On entry, the app calls GET /budget/catalog to display the scope catalog and GET /costs/project-estimate to show the current project cost estimate.
- ☐ User can select build scope line items; on confirm the app calls POST /projects/{project_id}/budget/initialize to create the project budget.
- ☐ The cost estimate updates to reflect selected scope items after initialization.
- ☐ User can proceed to Step 4 only after the budget is successfully initialized.
- ☐ project-setup/fast-track/step-4/link-account — wire:
POST /open-banking/link-token,POST /open-banking/link,GET /open-banking/accounts - ☐ User can link a bank account via open banking; on entry the app calls POST /open-banking/link-token to initialize the link flow.
- ☐ On successful link, the app calls POST /open-banking/link and then GET /open-banking/accounts to display linked accounts for selection.
- ☐ User can choose manual card or manual account entry instead of the open-banking flow, routing to screens 12 or 13 respectively.
- ☐ account-activated — wire:
GET /wallet/payment-methods - ☐ On entry, the app calls GET /wallet/payment-methods and displays the activated payment method(s).
- ☐ User sees confirmation that the wallet is active and can proceed to the Review setup screen.
- ☐ project-setup/fast-track/step-4/link-account/manual card — wire:
POST /wallet/setup-intent - ☐ User can manually enter card details; on submit the app calls POST /wallet/setup-intent to tokenize and register the card.
- ☐ System validates card fields (number, expiry, CVC) client-side before enabling submit.
- ☐ On success the user advances to the Review setup screen; on failure an inline error is shown with retry.
- ☐ project-setup/fast-track/step-4/link-account/manual account — wire:
POST /open-banking/link,POST /open-banking/accounts/{account_ref}/set-default - ☐ User can manually enter bank account details; on submit the app calls POST /open-banking/link to register the account.
- ☐ On successful link, the app calls POST /open-banking/accounts/{account_ref}/set-default to make the new account the wallet default.
- ☐ System validates routing and account number formats before enabling submit; on failure the user sees an inline error with retry.
- ☐ project-setup/fast-track/Review setup — wire:
GET /projects/{project_id}/setup-review - ☐ On entry, the app calls GET /projects/{project_id}/setup-review and displays a summary of property, deal numbers, build scope/budget, and linked payment method.
- ☐ User can tap any summary section to edit it, routing to the corresponding edit screen (15 for deal/cost details, 16 for linked account).
- ☐ User can complete setup from the review screen once all required sections show a completed status.
- ☐ edit/property-cost/project-cost — wire:
GET /projects/{project_id}/deal-details,POST /projects/{project_id}/deal-details,GET /projects/{project_id}/profitability-details,POST /projects/{project_id}/profitability-details - ☐ On entry, the app calls GET /projects/{project_id}/deal-details and GET /projects/{project_id}/profitability-details to pre-populate current values.
- ☐ User can edit deal and profitability inputs; on save the app calls POST /projects/{project_id}/deal-details and POST /projects/{project_id}/profitability-details.
- ☐ System validates numeric inputs before save; on success the user returns to the Review setup screen with updated values reflected.
*Generated 2026-10-11 · Dovel Team · dovel-team.dev.utom.dev*