{"components":{"parameters":{},"schemas":{"AccountServiceUnavailable":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"AddWatchedAgentRequest":{"properties":{"agentId":{"description":"Agent id to watch.","minLength":1,"type":"string"}},"required":["agentId"],"type":"object"},"AddWatchedAreaRequest":{"properties":{"lat":{"description":"Center latitude (point + radius).","maximum":90,"minimum":-90,"type":"number"},"lon":{"description":"Center longitude.","maximum":180,"minimum":-180,"type":"number"},"maxLat":{"description":"Box north edge.","maximum":90,"minimum":-90,"type":"number"},"maxLon":{"description":"Box east edge.","maximum":180,"minimum":-180,"type":"number"},"minLat":{"description":"Box south edge.","maximum":90,"minimum":-90,"type":"number"},"minLon":{"description":"Box west edge.","maximum":180,"minimum":-180,"type":"number"},"radius":{"description":"Radius around the center point.","example":10,"exclusiveMinimum":true,"minimum":0,"type":"number"},"state":{"description":"2-letter state. Ignored for zip + geo areas.","example":"CA","type":"string"},"type":{"description":"Named area (city/county/zip) or geo area (bbox = bounding box, radius = point + radius).","enum":["city","county","zip","bbox","radius"],"type":"string"},"unit":{"description":"Radius unit (default mi).","enum":["mi","km","m"],"example":"mi","type":"string"},"value":{"description":"City / county name, or 5-digit zip. Required for named areas.","example":"Los Angeles","type":"string"}},"required":["type"],"type":"object"},"AddWatchedDocumentRequest":{"properties":{"documentId":{"description":"The document id (mm_property_id / mm_loan_id / mm_sale_id).","minLength":1,"type":"string"},"documentType":{"description":"The kind of document to watch.","enum":["sale","property","loan"],"example":"property","type":"string"},"rules":{"description":"One or more rules; each fires as one alert.","items":{"properties":{"match":{"description":"How predicates combine: all (AND, default) or any (OR).","enum":["all","any"],"example":"all","type":"string"},"predicates":{"description":"One or more conditions; combined per match.","items":{"properties":{"field":{"description":"Catalog field alias (e.g. avm, current_ltv, loan_type).","example":"current_ltv","type":"string"},"op":{"description":"Comparison / change / status / guard operator.","enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"example":"lte","type":"string"},"stringValue":{"description":"Target keyword for changed_to / eq / not_eq guard.","type":"string"},"stringValues":{"description":"Keyword set for the in guard (1–20).","items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"description":"Threshold, or change amount (percent for pct_change_gte).","example":0.8,"type":"number"},"value2":{"description":"Upper bound for between.","type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"minItems":1,"type":"array"}},"required":["documentType","documentId","rules"],"type":"object"},"AdminAlertConditionsResponse":{"properties":{"data":{"properties":{"conditions":{"$ref":"#/components/schemas/AlertConditions"},"email":{"type":"string"},"emailEnabled":{"deprecated":true,"description":"Deprecated and ignored: accepted for compatibility, but not stored and no longer controls delivery (the response always reports every flag off). Email and in-app channel preferences for alerts live in Notifications settings.","properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"required":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan"],"type":"object"},"enabled":{"$ref":"#/components/schemas/AlertEnabled"},"name":{"type":"string"},"nmlsId":{"type":"string"},"orgId":{"type":"string"},"updatedAt":{"type":"string"},"userId":{"type":"string"}},"required":["userId","orgId","nmlsId","email","name","enabled","emailEnabled","conditions","updatedAt"],"type":"object"}},"required":["data"],"type":"object"},"AdminAlertDigestItem":{"allOf":[{"$ref":"#/components/schemas/AlertDigestItem"},{"properties":{"correlationId":{"description":"The detector run that produced this digest (trace to /runs).","type":"string"},"userId":{"type":"string"}},"required":["userId"],"type":"object"}]},"AdminAlertDigestResponse":{"properties":{"cursor":{"type":"string"},"items":{"items":{"$ref":"#/components/schemas/AdminAlertDigestItem"},"type":"array"}},"required":["items"],"type":"object"},"AdminAlertEmailTemplatePreviewRequest":{"properties":{"kinds":{"description":"The alert kinds to sample (and validate item tokens against). Default: the recipe's kinds, else every kind.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"recipeId":{"description":"Preview under this recipe (its copy, family and kinds). Omitted: a neutral stand-in recipe.","type":"string"},"template":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"userId":{"description":"Sample from this user's recent alerts (and greet them by name); a `u-` recipeId is looked up among this user's recipes. Omitted: static samples.","minLength":1,"type":"string"}},"required":["template"],"type":"object"},"AdminAlertLogItem":{"allOf":[{"$ref":"#/components/schemas/AlertLogItem"},{"properties":{"correlationId":{"description":"The detector run that produced this alert (trace to /runs).","type":"string"},"userId":{"type":"string"},"via":{"$ref":"#/components/schemas/AdminAlertVia"}},"required":["userId"],"type":"object"}]},"AdminAlertLogResponse":{"properties":{"cursor":{"type":"string"},"items":{"items":{"$ref":"#/components/schemas/AdminAlertLogItem"},"type":"array"}},"required":["items"],"type":"object"},"AdminAlertRawResponse":{"properties":{"data":{"additionalProperties":{"nullable":true},"type":"object"}},"required":["data"],"type":"object"},"AdminAlertRecipe":{"properties":{"category":{"maxLength":32,"minLength":1,"type":"string"},"copy":{"properties":{"headline":{"maxLength":200,"minLength":1,"type":"string"},"intro":{"maxLength":1000,"type":"string"},"plural":{"maxLength":40,"minLength":1,"type":"string"},"subject":{"maxLength":200,"minLength":1,"type":"string"}},"required":["subject","headline","intro","plural"],"type":"object"},"createdAt":{"type":"string"},"createdBy":{"type":"string"},"description":{"maxLength":500,"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"featured":{"type":"boolean"},"grants":{"properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"howItWorks":{"maxLength":2000,"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"inputs":{"items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"maxItems":4,"type":"array"},"maxItemsPerRun":{"maximum":100,"minimum":1,"type":"integer"},"sortOrder":{"maximum":999999,"minimum":0,"type":"integer"},"status":{"enum":["draft","published","archived"],"type":"string"},"subscribers":{"description":"List only: users with a subscription carrying this recipe (kinds on).","type":"integer"},"title":{"maxLength":80,"minLength":1,"type":"string"},"updatedAt":{"type":"string"},"updatedBy":{"type":"string"},"version":{"minimum":1,"type":"integer"}},"required":["id","title","description","icon","category","family","grants","inputs","copy","featured","sortOrder","status","version","createdBy","createdAt","updatedBy","updatedAt"],"type":"object"},"AdminAlertRecipeResponse":{"properties":{"data":{"$ref":"#/components/schemas/AdminAlertRecipe"}},"required":["data"],"type":"object"},"AdminAlertRecipeStatsResponse":{"properties":{"data":{"properties":{"alertsLast30d":{"description":"Alerts fired in the last 30 days whose grant came from this recipe (LOG `via.recipeIds`), across its subscribers.","type":"integer"},"lastFiredAt":{"description":"Newest such alert (ISO) in the last 30 days.","type":"string"},"subscribers":{"description":"Users with a subscription carrying the recipe (kinds on).","type":"integer"}},"required":["subscribers","alertsLast30d"],"type":"object"}},"required":["data"],"type":"object"},"AdminAlertRecipesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AdminAlertRecipe"},"type":"array"}},"required":["data"],"type":"object"},"AdminAlertRunRecord":{"properties":{"correlationId":{"type":"string"},"dryRun":{"type":"boolean"},"durationMs":{"type":"integer"},"finishedAt":{"type":"string"},"id":{"type":"string"},"perDetector":{"items":{"properties":{"deduped":{"type":"integer"},"matched":{"type":"integer"},"published":{"type":"integer"},"scanned":{"type":"integer"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"written":{"type":"integer"}},"required":["type","scanned","matched","deduped","written","published"],"type":"object"},"type":"array"},"startedAt":{"type":"string"},"totals":{"properties":{"matched":{"type":"integer"},"published":{"type":"integer"},"scanned":{"type":"integer"},"written":{"type":"integer"}},"required":["scanned","matched","written","published"],"type":"object"}},"required":["id","correlationId","startedAt","finishedAt","durationMs","dryRun","perDetector","totals"],"type":"object"},"AdminAlertRunResponse":{"properties":{"data":{"$ref":"#/components/schemas/AdminAlertRunRecord"}},"required":["data"],"type":"object"},"AdminAlertRunsResponse":{"properties":{"cursor":{"type":"string"},"items":{"items":{"$ref":"#/components/schemas/AdminAlertRunRecord"},"type":"array"}},"required":["items"],"type":"object"},"AdminAlertUserRecipe":{"properties":{"alertsLast30d":{"description":"Alerts its grant fired for the owner in the last 30 days (LOG `via.recipeIds`).","type":"integer"},"category":{"type":"string"},"copy":{"properties":{"headline":{"maxLength":200,"minLength":1,"type":"string"},"intro":{"maxLength":1000,"type":"string"},"plural":{"maxLength":40,"minLength":1,"type":"string"},"subject":{"maxLength":200,"minLength":1,"type":"string"}},"required":["subject","headline","intro","plural"],"type":"object"},"createdAt":{"type":"string"},"createdBy":{"type":"string"},"description":{"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"grants":{"properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"icon":{"type":"string"},"id":{"type":"string"},"inputs":{"items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"type":"array"},"maxItemsPerRun":{"type":"integer"},"ownerUserId":{"type":"string"},"promotedTo":{"type":"string"},"scope":{"enum":["user"],"type":"string"},"status":{"enum":["active","archived"],"type":"string"},"subscribers":{"description":"1 when the owner is subscribed to it, else 0.","type":"integer"},"title":{"type":"string"},"updatedAt":{"type":"string"},"updatedBy":{"type":"string"},"version":{"minimum":1,"type":"integer"}},"required":["id","ownerUserId","scope","title","description","icon","category","family","grants","inputs","copy","maxItemsPerRun","status","version","createdBy","createdAt","updatedBy","updatedAt","subscribers","alertsLast30d"],"type":"object"},"AdminAlertUserRecipesResponse":{"properties":{"cursor":{"type":"string"},"items":{"items":{"$ref":"#/components/schemas/AdminAlertUserRecipe"},"type":"array"}},"required":["items"],"type":"object"},"AdminAlertVia":{"description":"Why the alert fired: the matched subject, the granting recipes and the match source. Absent on rows written before it existed.","properties":{"matchSource":{"description":"Which match source routed the alert: `subscriptions` for every alert fired since the legacy source was retired; `legacy` only on older rows.","enum":["legacy","subscriptions"],"type":"string"},"parentKey":{"description":"When the match went through a derived child (an auto agent, a borrower property, a manual agent's VRE), the owning subscription's subject key.","type":"string"},"recipeIds":{"description":"The recipes whose grants enabled this alert type on the matched subscription (empty on alerts fired by the retired legacy match source).","items":{"type":"string"},"type":"array"},"subjectKey":{"description":"The watched subject key the alert matched.","type":"string"}},"required":["subjectKey","recipeIds","matchSource"],"type":"object"},"AdminBulkJob":{"properties":{"bytes":{"type":"number"},"chargedCount":{"type":"number"},"completedAt":{"type":"string"},"creditLedgerId":{"nullable":true,"type":"string"},"creditsCharged":{"type":"number"},"entityType":{"type":"string"},"error":{"type":"string"},"failed":{"type":"number"},"format":{"type":"string"},"fromCache":{"type":"number"},"jobId":{"type":"string"},"jobType":{"enum":["enrichment","bulk-delivery","crm-production-enrich","crm-import"],"type":"string"},"orgId":{"type":"string"},"processed":{"type":"number"},"startedAt":{"type":"string"},"status":{"enum":["queued","running","completed","failed","cancelled"],"type":"string"},"succeeded":{"type":"number"},"total":{"type":"number"},"userId":{"type":"string"}},"required":["jobId","orgId","userId","jobType","status","total","succeeded","failed","fromCache","chargedCount","creditsCharged","creditLedgerId"],"type":"object"},"AdminBulkJobResponse":{"properties":{"job":{"$ref":"#/components/schemas/AdminBulkJob"},"resultsUrl":{"nullable":true,"type":"string"}},"required":["job","resultsUrl"],"type":"object"},"AdminCadLinks":{"properties":{"current":{"nullable":true,"properties":{"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"startDate":{"nullable":true,"type":"string"}},"required":["companyNmlsId","companyName","startDate"],"type":"object"},"explanation":{"properties":{"activeLogic":{"type":"string"},"registrationLink":{"type":"string"},"sponsorshipLink":{"type":"string"}},"required":["sponsorshipLink","registrationLink","activeLogic"],"type":"object"},"indexGaps":{"items":{"type":"string"},"type":"array"},"isWorking":{"nullable":true,"type":"boolean"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"},"registrations":{"properties":{"active":{"type":"number"},"inactive":{"type":"number"},"rows":{"items":{"properties":{"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"endDate":{"nullable":true,"type":"string"},"isActive":{"type":"boolean"},"licenseType":{"nullable":true,"type":"string"},"locationNmlsId":{"nullable":true,"type":"string"},"regulator":{"nullable":true,"type":"string"},"source":{"enum":["sponsorship","registration",null],"nullable":true,"type":"string"},"startDate":{"nullable":true,"type":"string"}},"required":["source","companyNmlsId","companyName","startDate","endDate","isActive","regulator","licenseType","locationNmlsId"],"type":"object"},"type":"array"},"total":{"type":"number"}},"required":["total","active","inactive","rows"],"type":"object"},"sponsorships":{"properties":{"active":{"type":"number"},"inactive":{"type":"number"},"rows":{"items":{"properties":{"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"endDate":{"nullable":true,"type":"string"},"isActive":{"type":"boolean"},"licenseType":{"nullable":true,"type":"string"},"locationNmlsId":{"nullable":true,"type":"string"},"regulator":{"nullable":true,"type":"string"},"source":{"enum":["sponsorship","registration",null],"nullable":true,"type":"string"},"startDate":{"nullable":true,"type":"string"}},"required":["source","companyNmlsId","companyName","startDate","endDate","isActive","regulator","licenseType","locationNmlsId"],"type":"object"},"type":"array"},"total":{"type":"number"}},"required":["total","active","inactive","rows"],"type":"object"}},"required":["nmlsId","name","isWorking","current","sponsorships","registrations","explanation","indexGaps"],"type":"object"},"AdminCreateAlertRecipeRequest":{"description":"A recipe definition. Created as a draft; publish it to show it to users.","properties":{"category":{"maxLength":32,"minLength":1,"type":"string"},"copy":{"properties":{"headline":{"maxLength":200,"minLength":1,"type":"string"},"intro":{"maxLength":1000,"type":"string"},"plural":{"maxLength":40,"minLength":1,"type":"string"},"subject":{"maxLength":200,"minLength":1,"type":"string"}},"required":["subject","headline","intro","plural"],"type":"object"},"description":{"maxLength":500,"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"featured":{"type":"boolean"},"grants":{"properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"howItWorks":{"maxLength":2000,"type":"string"},"icon":{"description":"hugeicons component name, e.g. `UserSearch01Icon`.","type":"string"},"id":{"description":"Kebab-case slug, at most 48 characters; immutable once created.","example":"listing-watch","type":"string"},"inputs":{"items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"maxItems":4,"type":"array"},"maxItemsPerRun":{"maximum":100,"minimum":1,"type":"integer"},"sortOrder":{"maximum":999999,"minimum":0,"type":"integer"},"title":{"maxLength":80,"minLength":1,"type":"string"}},"required":["id","title","description","icon","category","family","grants","inputs","copy","featured","sortOrder"],"type":"object"},"AdminCrmApplyMiResult":{"properties":{"data":{"properties":{"applied":{"type":"number"},"results":{"items":{"properties":{"applied":{"type":"number"},"entityId":{"type":"string"},"error":{"enum":["not_found","invalid_phone"],"type":"string"}},"required":["entityId","applied"],"type":"object"},"type":"array"}},"required":["applied","results"],"type":"object"}},"required":["data"],"type":"object"},"AdminCrmLinkResult":{"properties":{"data":{"properties":{"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"linked":{"enum":[true],"type":"boolean"},"previousLink":{"$ref":"#/components/schemas/CrmLink"}},"required":["linked","entityType","previousLink"],"type":"object"}},"required":["data"],"type":"object"},"AdminCrmMatchCandidates":{"properties":{"data":{"items":{"properties":{"company":{"type":"string"},"location":{"type":"string"},"mmaId":{"type":"string"},"name":{"type":"string"},"nmlsId":{"type":"string"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["name"],"type":"object"},"type":"array"}},"required":["data"],"type":"object"},"AdminCrmMiReviewResult":{"properties":{"data":{"properties":{"failedEntityIds":{"items":{"type":"string"},"type":"array"},"mirrorRefreshed":{"type":"number"},"nextCursor":{"nullable":true,"type":"string"},"notFound":{"items":{"type":"string"},"type":"array"},"records":{"items":{"properties":{"checkedAt":{"type":"number"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"inputsChanged":{"type":"boolean"},"name":{"nullable":true,"type":"string"},"status":{"enum":["needs_review","snoozed","up_to_date"],"type":"string"},"updates":{"items":{"properties":{"action":{"enum":["add","overwrite"],"type":"string"},"current":{"nullable":true,"type":"string"},"field":{"type":"string"},"id":{"type":"string"},"incoming":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"},"linkage":{"properties":{"companyNmlsId":{"type":"string"},"office":{"$ref":"#/components/schemas/CrmOverrideOffice"}},"type":"object"},"previouslyReviewed":{"type":"boolean"},"seenKey":{"type":"string"},"store":{"enum":["override","contact"],"type":"string"}},"required":["id","field","label","store","current","incoming","action","seenKey","previouslyReviewed"],"type":"object"},"type":"array"}},"required":["entityId","entityType","name","status","inputsChanged","updates","checkedAt"],"type":"object"},"type":"array"},"scanned":{"type":"number"},"summary":{"properties":{"failed":{"type":"number"},"needsReview":{"type":"number"},"snoozed":{"type":"number"},"unavailable":{"type":"number"},"upToDate":{"type":"number"}},"required":["needsReview","snoozed","upToDate","unavailable","failed"],"type":"object"}},"required":["records","scanned","summary","failedEntityIds","notFound","mirrorRefreshed","nextCursor"],"type":"object"}},"required":["data"],"type":"object"},"AdminPreviewAlertRecipeRequest":{"properties":{"inputs":{"$ref":"#/components/schemas/AlertRecipeInputs"},"userId":{"description":"Whose saved setup to replay with the recipe overlaid.","minLength":1,"type":"string"}},"required":["userId"],"type":"object"},"AdminPromoteUserRecipeRequest":{"properties":{"id":{"description":"The new global recipe's id (kebab-case slug ≤ 48, not `u-…`).","example":"listing-watch","type":"string"}},"required":["id"],"type":"object"},"AdminPromoteUserRecipeResponse":{"properties":{"data":{"properties":{"markerWritten":{"description":"Whether `promotedTo` was recorded on the user recipe. false when the owner edited it concurrently (the draft exists either way; `userRecipe` is then the current row, without the marker).","type":"boolean"},"recipe":{"$ref":"#/components/schemas/AdminAlertRecipe"},"userRecipe":{"$ref":"#/components/schemas/AlertUserRecipe"}},"required":["recipe","userRecipe","markerWritten"],"type":"object"}},"required":["data"],"type":"object"},"AdminPushAlertRequest":{"properties":{"dedupeKey":{"description":"Dedup key; generated server-side when omitted.","type":"string"},"orgId":{"description":"Workspace id so the push also lands in the org feed.","type":"string"},"payload":{"additionalProperties":{"nullable":true},"description":"Human description + optional link + fields.","properties":{"description":{"type":"string"},"url":{"type":"string"}},"required":["description"],"type":"object"},"type":{"description":"One of the six alert types.","enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}},"required":["type","payload"],"type":"object"},"AdminPushAlertResponse":{"properties":{"data":{"properties":{"dedupeKey":{"type":"string"},"written":{"type":"boolean"}},"required":["written","dedupeKey"],"type":"object"}},"required":["data"],"type":"object"},"AdminReplaceAlertRecipeRequest":{"description":"The full definition (everything but `id`); status is kept.","properties":{"category":{"maxLength":32,"minLength":1,"type":"string"},"copy":{"properties":{"headline":{"maxLength":200,"minLength":1,"type":"string"},"intro":{"maxLength":1000,"type":"string"},"plural":{"maxLength":40,"minLength":1,"type":"string"},"subject":{"maxLength":200,"minLength":1,"type":"string"}},"required":["subject","headline","intro","plural"],"type":"object"},"description":{"maxLength":500,"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"featured":{"type":"boolean"},"grants":{"properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"howItWorks":{"maxLength":2000,"type":"string"},"icon":{"type":"string"},"inputs":{"items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"maxItems":4,"type":"array"},"maxItemsPerRun":{"maximum":100,"minimum":1,"type":"integer"},"sortOrder":{"maximum":999999,"minimum":0,"type":"integer"},"title":{"maxLength":80,"minLength":1,"type":"string"},"version":{"description":"The version you edited; a stale one answers 409 `version_conflict`.","minimum":1,"type":"integer"}},"required":["title","description","icon","category","family","grants","inputs","copy","featured","sortOrder"],"type":"object"},"AdminResyncAlertRecipeRequest":{"properties":{"rules":{"description":"Also overwrite the rules on record subscriptions carrying the recipe with its current rule templates (replaces rules users entered). Default false: only the granted kinds are rewritten.","type":"boolean"}},"type":"object"},"AdminResyncAlertRecipeResponse":{"properties":{"data":{"properties":{"deleted":{"description":"NMLS subscriptions left with nothing and removed.","type":"integer"},"matched":{"description":"Subscriptions carrying the recipe's grant.","type":"integer"},"revoked":{"description":"Grants dropped because the recipe no longer covers the subject type.","type":"integer"},"scanned":{"description":"Subscriptions read (all users).","type":"integer"},"unchanged":{"type":"integer"},"updated":{"description":"Grants (or rules) rewritten.","type":"integer"}},"required":["scanned","matched","updated","unchanged","revoked","deleted"],"type":"object"}},"required":["data"],"type":"object"},"AdminUpdateAlertConditionsRequest":{"properties":{"conditions":{"$ref":"#/components/schemas/AlertConditions"},"email":{"type":"string"},"emailEnabled":{"deprecated":true,"description":"Deprecated and ignored: accepted for compatibility, but not stored and no longer controls delivery (the response always reports every flag off). Email and in-app channel preferences for alerts live in Notifications settings.","properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"type":"object"},"enabled":{"properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"type":"object"},"name":{"type":"string"},"nmlsId":{"type":"string"},"orgId":{"description":"Workspace id stamped on the config (admin supplies it). Required — alerts are org-scoped, so a config can't exist without a workspace.","minLength":1,"type":"string"}},"required":["orgId"],"type":"object"},"AgentChartMeasure":{"default":"units","description":"Which metric each bar reports, AND what the bars are ranked by — the list is ordered by the measure you ask for, descending. Defaults to `units`, so an unqualified \"top originators\" means the busiest; pass `volume` for the biggest by dollars, or an average to rank by that average. Two things to know about the averages specifically. Buckets built from fewer than 5 documents are dropped from an average chart entirely, because a mean says nothing about how many transactions produced it and a single-transaction bucket would otherwise outrank real ones; no floor is applied to `units` or `volume`, where a lone large transaction is a legitimate top bar. And ranking a bucket list by a sub-aggregated average is approximate in the search engine — each shard contributes its own local top-N before they are merged — so treat the ordering of an average chart as indicative near the boundary rather than exact. Every bucket publishes its own `count`, so the sample size behind a value is never implicit.","enum":["volume","units","avgSalePrice"],"type":"string"},"AgentChartRequest":{"additionalProperties":false,"properties":{"id":{"type":"string"},"ids":{"items":{"type":"string"},"type":"array"},"measure":{"$ref":"#/components/schemas/AgentChartMeasure"},"period":{"$ref":"#/components/schemas/Period"},"slice":{"$ref":"#/components/schemas/AgentChartSlice"}},"required":["slice"],"type":"object"},"AgentChartSlice":{"enum":["city","county","state","zip"],"type":"string"},"AgentCountyFilterValue":{"anyOf":[{"pattern":"^\\d{5}$","type":"string"},{"description":"Match any of several counties","items":{"pattern":"^\\d{5}$","type":"string"},"type":"array"},{"nullable":true}],"description":"County, keyed by 5-digit county FIPS code (e.g. `06037` = Los Angeles, CA; `04013` = Maricopa, AZ). By default matches agents who closed transactions in this county (production alone — unlike `city`/`state`/`zip`, which an office address also satisfies); with `locationSource: \"office\"` it matches agents whose CURRENT office lies inside the county boundary. A county NAME is REJECTED with a 400 naming the expected format; resolve the name to its FIPS code first (via instantSearch), or use `city`/`state`, which do accept names. Location dimensions AND with each other, so `county` + `state` returns only agents matching both."},"AgentCrmListFilter":{"additionalProperties":false,"description":"Scope the result to the caller's CRM. Resolved against the caller's ACTIVE WORKSPACE at query time — list membership is read server-side, so the request never carries member ids. Only real-estate-agent members count; loan officers and manual (unlinked) records on the same list are ignored. `mode: \"in\"` with no matching members returns an empty page (not an unfiltered one). Errors: 400 `crm_list_requires_workspace` when the caller has no active workspace (API-key / OAuth callers must select an organization), 403 / 404 when a named list is not visible to the caller or does not exist, and 400 `crm_list_too_large` when the selected lists hold more than 50,000 agents in total — narrow the selection rather than get a silently partial answer.","properties":{"lists":{"anyOf":[{"description":"Every list in the caller's workspace that the caller can see (own, org-wide, or shared with them) and that holds this kind of record — People lists for originators and agents, Company lists for companies.","enum":["any"],"type":"string"},{"description":"Specific CRM list ids (1–50).","items":{"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"}],"description":"Which lists: `\"any\"` for every People list the caller can see, or an array of list ids. Membership is the UNION across the selected lists."},"mode":{"description":"`in` — only agents who are a member of the selected list(s). `notIn` — exclude every agent who is a member of the selected list(s); everyone else passes, including agents on none of your lists.","enum":["in","notIn"],"type":"string"}},"required":["mode","lists"],"type":"object"},"AgentDealFilters":{"additionalProperties":false,"description":"Deal filters beyond the sale `flatFilters`. Loan-side keys (`financed`, `loan`) and the loan / party sorts consider the newest 10,000 matching sales; `truncated` says when more matched.","properties":{"coListAgentName":{"description":"Co-listing agent name: every word must start a word of the name the MLS recorded.","maxLength":100,"minLength":1,"type":"string"},"financed":{"description":"`true`: deals with a purchase loan on file; `false`: none on file (cash, or not yet recorded).","type":"boolean"},"hasBuilder":{"description":"`true`: new construction — the sale or its purchase loan names a builder (or a builder seller).","type":"boolean"},"loan":{"$ref":"#/components/schemas/AgentSaleLoanFilters"},"search":{"description":"Address search: every word must start a word of the street line, city or ZIP (\"12 oak\" → 1200 Oakmont Dr).","maxLength":100,"minLength":1,"type":"string"},"statusDate":{"allOf":[{"$ref":"#/components/schemas/DateFilterValue"},{"description":"MLS status-change date range. With `mlsStatus: \"ACT\"`, `{gte}` keeps listings still active recently."}]}},"type":"object"},"AgentDetail":{"allOf":[{"$ref":"#/components/schemas/AgentSummary"},{"properties":{"licenses":{"items":{"$ref":"#/components/schemas/AgentLicense"},"nullable":true,"type":"array"},"linkedProfileCount":{"description":"Total consolidated records for this agent, before the 20-entry cap applied to `linkedProfiles`.","nullable":true,"type":"number"},"linkedProfiles":{"description":"Additional records consolidated into this agent — the SAME person as captured by different data sources, not teammates or a team roster. Useful for the alternate contact details and the transaction window each record carries. Ordered by transaction count, highest first, and capped at 20 entries; `linkedProfileCount` is the uncapped total.","items":{"$ref":"#/components/schemas/AgentLinkedProfile"},"nullable":true,"type":"array"},"scored":{"nullable":true}},"type":"object"}]},"AgentDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/AgentDetail"}},"required":["data"],"type":"object"},"AgentField":{"enum":["office","city","state","zip","volume","units","avgSalePrice","buyerVolume","buyerUnits","sellerVolume","sellerUnits","dualVolume","dualUnits","name","firstName","lastName","email","producersOnly"],"type":"string"},"AgentFootprintFilter":{"additionalProperties":false,"properties":{"avgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Mean loan size financed by this lender on the agent's deals."}]},"dimension":{"description":"Which footprint to address. Only `lender` is available for agents — it is inferred from a `lender` key, so you rarely pass this. Name it to ask the ANY-lender question (`{dimension:'lender', volume:{gte:10000000}}` = 'some single lender financed $10M of their sales'). A geographic dimension is a 400 naming the per-agent markets endpoint, which live-aggregates that answer.","enum":["zip","city","county","state","lender"],"type":"string"},"lender":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Financing lender, as an id from `listLenders` or `instantSearch`. Lender names are stored in a normalized dictionary form, so a typed name does not match — resolve it first. Several values UNION."},"not":{"description":"Invert the whole entry: match agents with NO lender relationship matching it.","type":"boolean"},"product":{"$ref":"#/components/schemas/FootprintProductFilter"},"units":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Count of the agent's transactions financed by this lender during the selected period."}]},"volume":{"$ref":"#/components/schemas/FootprintRange"}},"type":"object"},"AgentLicense":{"properties":{"expirationDate":{"nullable":true,"type":"string"},"number":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"type":{"nullable":true,"type":"string"}},"type":"object"},"AgentLicenseFilterValue":{"anyOf":[{"type":"string"},{"description":"Match any of several licenses","items":{"type":"string"},"type":"array"},{"nullable":true}],"description":"Real-estate license number, matched EXACTLY. Case and surrounding whitespace are normalized, so `EB00084246`, `eb00084246` and `\" eb00084246 \"` all behave identically — paste straight from a spreadsheet or PDF. Punctuation is NOT normalized: `52219-90` and `5221990` are treated as different licenses, because separator-insensitive matching merges distinct agents. Matches against EVERY license on the agent's record, not just the one shown as `licenseNumber` on the response row — an agent licensed in two states is found by either. Fuzzy `{match}` is rejected with a 400: a near-miss on a license number is a different person, not a typo to forgive. Present on roughly 49% of agents; the rest carry no license at all and cannot be matched by this filter."},"AgentLinkedProfile":{"properties":{"email":{"nullable":true,"type":"string"},"firstTransactionDate":{"nullable":true,"type":"string"},"lastTransactionDate":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"transactions":{"description":"Transactions observed on this record.","nullable":true,"type":"number"}},"type":"object"},"AgentListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"crmList":{"$ref":"#/components/schemas/AgentCrmListFilter"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"activeListings":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Current active listings (not period-scoped). `{gte: 1}` = has listings."}]},"avgMortgagedLoanAmount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean loan size across the agent's financed deals — the price band their buyers actually borrow in."}]},"avgSalePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"buyerUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"buyerVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"city":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"City — matches across ALL of an agent's location signals (listed city, office address, AND transaction/production markets), OR'd together. An agent can match this city while their row's displayed `city`/`state` (their primary market) is elsewhere. Cities in several states: write each as `\"City, ST\"` (`[\"Springfield, IL\", \"Austin, TX\"]`) — each binds to its own state; a bare name plus a `state` list cross-pairs."}]},"county":{"$ref":"#/components/schemas/AgentCountyFilterValue"},"currentOffice":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Brokerage/office name(s), OR'd: each a case-insensitive whole-word phrase (`\"compass\"` matches \"Compass RE\", not \"Encompass\"); end with `*` for a prefix (`\"washington fine*\"`); names with punctuation (`\"@properties\"`) match as a substring. `{match}` is a fuzzy single-name match. Matches only the agent's CURRENT office; `office` takes the same values and matches ANY office on record."}]},"currentOfficeKey":{"anyOf":[{"minLength":1,"type":"string"},{"items":{"minLength":1,"type":"string"},"minItems":1,"type":"array"}],"description":"Office roster: agents whose CURRENT office is this office id (the `id` from `listOffices` / `instantSearch`, raw or encoded). Several ids OR."},"dualUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"dualVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"email":{"$ref":"#/components/schemas/TextFilterValue"},"excludeCurrentOffice":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Drop agents whose CURRENT office matches these names."}]},"excludeOffice":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Drop agents with ANY office matching these names (same grammar as `office`)."}]},"firstName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"Deprecated: the fuzzy name filters can return the wrong agent. Resolve the agent via instantSearch (POST /v1/instant-search) and pass the returned `id` to the `id` filter for an exact match."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"hasEmail":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the row's `email` is populated."}]},"hasPhone":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the row's `phone` is populated."}]},"id":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact agent id — the `id` returned by instantSearch (same value as `modelMatchId`). Resolves the agent by its canonical ModelMatch id or any since-merged legacy id. Preferred over the fuzzy `name` filter."}]},"lastName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"Deprecated: the fuzzy name filters can return the wrong agent. Resolve the agent via instantSearch (POST /v1/instant-search) and pass the returned `id` to the `id` filter for an exact match."}]},"lastTransactionDate":{"allOf":[{"$ref":"#/components/schemas/DateFilterValue"},{"description":"Date of the agent's newest deal inside the selected period — \"recently active\". `{gte: \"2026-07-01\"}`. Only producing agents carry it."}]},"licenseNumber":{"$ref":"#/components/schemas/AgentLicenseFilterValue"},"licensedSinceDate":{"allOf":[{"$ref":"#/components/schemas/DateFilterValue"},{"description":"Original issue date of a real-estate license on the record (any license) — \"new agents\": `{gte: \"2025-10-01\"}`. Lifetime, not period-scoped; on ~26% of agents."}]},"mode":{"enum":["and","or"],"type":"string"},"modelMatchId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `id` — the agent's ModelMatch id. Exact match (canonical or since-merged legacy id)."}]},"mortgagedBuyerUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Count of the agent's buyer-side deals that were financed — the sharpest 'how many mortgage introductions can this agent make' number on the record."}]},"mortgagedBuyerVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Dollar volume of the agent's BUYER-side deals that were financed. Measured independently of `buyerVolume`, not carved out of it, so it is not guaranteed to be smaller."}]},"mortgagedDualUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Count of the agent's dual-agency deals that were financed."}]},"mortgagedDualVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Dollar volume of the agent's dual-agency deals that were financed."}]},"mortgagedSellerUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Count of the agent's seller-side (listing) deals whose buyer financed."}]},"mortgagedSellerVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Dollar volume of the agent's SELLER-side (listing) deals whose buyer financed."}]},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"Deprecated: the fuzzy name filters can return the wrong agent. Resolve the agent via instantSearch (POST /v1/instant-search) and pass the returned `id` to the `id` filter for an exact match."}]},"namePrefix":{"description":"Prefix name search: every word must start a word of the name (\"jen ro\" → Jennifer Rodriguez). No fuzzy/nickname matching; relevance-ranked unless `sort` is set. Max 100 chars / 6 words (emails, URLs, phones ignored), else 400.","minLength":1,"type":"string"},"office":{"$ref":"#/components/schemas/TextFilterValue"},"percentUnitsMortgaged":{"anyOf":[{"type":"number"},{"description":"Match any value","items":{"type":"number"},"type":"array"},{"description":"Numeric range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.","type":"boolean"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},{"nullable":true}],"description":"Share of the agent's TRANSACTIONS that were financed with a mortgage, as a 0–100 percent — the by-count twin of `percentVolumeMortgaged`, and the better one when deal size varies wildly. Same 0–100 clamp."},"percentVolumeMortgaged":{"anyOf":[{"type":"number"},{"description":"Match any value","items":{"type":"number"},"type":"array"},{"description":"Numeric range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.","type":"boolean"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},{"nullable":true}],"description":"Share of the agent's sale volume that was financed with a mortgage, as a 0–100 percent. `{gte:80}` = 'almost everything they sell is financed' (211,079 agents over the last 12 months); `{lte:20}` finds cash-heavy books. Values are clamped at 100 — a small number of records carry a computed percent above 100, and they are treated as fully financed rather than silently kept or dropped. Bounds outside 0–100 are rejected."},"producersOnly":{"$ref":"#/components/schemas/BooleanFilterValue"},"sellerUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"sellerVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"State — matches across ALL of an agent's location signals (listed state, office address, AND transaction/production markets), OR'd together. So an agent whose office is in another state still matches if they closed transactions here."}]},"totalCompaniesWorkedWith":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct mortgage COMPANIES financed this agent's deals in the selected period."}]},"totalLendersWorkedWith":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct LENDERS financed this agent's deals in the selected period."}]},"totalOriginatorsWorkedWith":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many DISTINCT loan officers financed this agent's deals in the selected period. `{lte:1}` finds agents with a single LO relationship — the displacement target; `{gte:5}` finds agents who spread their referrals around. Same number shown on the response row."}]},"units":{"$ref":"#/components/schemas/NumericFilterValue"},"volume":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"ZIP — matches across ALL of an agent's location signals, OR'd together: an office postal code, OR a ZIP they actually closed transactions in (their production market). So an agent whose office is elsewhere still matches if they sold here, and the `zip` shown on their row (their primary market) can differ from the one you searched. Supply the 5-digit form; ZIP+4 input is reduced to its 5-digit prefix. Canonical key; `zipCode` is an accepted alias."}]},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zip` — identical behavior. Kept so the `zipCode` spelling used by loans/sales works here too."}]}},"type":"object"},"footprint":{"anyOf":[{"$ref":"#/components/schemas/AgentFootprintFilter"},{"items":{"$ref":"#/components/schemas/AgentFootprintFilter"},"type":"array"}],"description":"Scoped lender filter(s). Each entry names ONE financing relationship and the metric bounds that must hold INSIDE it — `{lender:'<id>', volume:{gte:10000000}}` means '$10M of their sales were financed by that lender', not '$10M of sales and one deal with them'. Several entries AND together. Geographic market filters are not available here: use `POST /v1/agents/{id}/markets` (live-aggregated) for an agent's geography."},"lenderFilters":{"items":{"$ref":"#/components/schemas/LenderFilterEntry"},"type":"array"},"lenderMatchMode":{"$ref":"#/components/schemas/LenderMatchMode"},"locationSource":{"$ref":"#/components/schemas/AgentLocationSource"},"losOnMyTeam":{"$ref":"#/components/schemas/AgentLosOnMyTeamFilter"},"near":{"$ref":"#/components/schemas/AgentNearFilter"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"productMix":{"$ref":"#/components/schemas/AgentProductMixFilter"},"sideDominance":{"$ref":"#/components/schemas/AgentSideDominance"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/AgentField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"AgentListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/AgentSummary"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"AgentLoanMixRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"period":{"$ref":"#/components/schemas/DatedPeriod"}},"type":"object"},"AgentLoanMixResponse":{"description":"`buyer` + `listing` = `any` (dual deals are counted on `buyer`).","properties":{"any":{"$ref":"#/components/schemas/AgentLoanMixSide"},"buyer":{"$ref":"#/components/schemas/AgentLoanMixSide"},"listing":{"$ref":"#/components/schemas/AgentLoanMixSide"}},"required":["any","buyer","listing"],"type":"object"},"AgentLoanMixSide":{"properties":{"loanTypes":{"description":"Loan-type mix of `units`, most deals first. Deals with no recorded loan type are absent, so the rows can sum to less than `units`.","items":{"$ref":"#/components/schemas/AgentLoanMixType"},"type":"array"},"tpoUnits":{"description":"Of `units`, deals originated through a mortgage broker (a broker NMLS id on the loan) — third-party origination. TPO share = `tpoUnits / units`.","type":"number"},"tpoVolume":{"description":"Loan amount of the TPO deals.","type":"number"},"units":{"description":"Financed deals (recorded loans) on this side in the window.","type":"number"},"volume":{"description":"Total loan amount of those deals (out-of-range fill amounts excluded).","type":"number"}},"required":["units","volume","tpoUnits","tpoVolume","loanTypes"],"type":"object"},"AgentLoanMixType":{"properties":{"label":{"description":"Loan type (e.g. `conventional`, `fha`, `va`)","type":"string"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["label","units","volume"],"type":"object"},"AgentLoansBreakdownRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"side":{"$ref":"#/components/schemas/AgentSide"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"AgentLocationSource":{"description":"Which location signal `city`/`state`/`zip`/`county`, `geoPoint` and `near` match. `any` (default) = an office OR a market they transacted in (`geoPoint`: any office on record); `office` = their CURRENT office (a bare `state` also matches the state on their member record; `county` = the office inside the county boundary); `production` = transaction markets only.","enum":["any","office","production"],"type":"string"},"AgentLosOnMyTeamFilter":{"additionalProperties":false,"description":"Relationship with loan officers at the CALLER's company, resolved server-side from the caller's profile NMLS id and that LO's current employer; the caller's own deals never count. 400 `los_on_my_team_requires_company` when the caller has no NMLS id on their profile or it resolves to no company.","properties":{"minUnits":{"description":"Buyer-side deals with ONE colleague that count as a relationship (default 1). Under `doesNotWorkWith`, agents below it still pass.","maximum":100,"minimum":1,"type":"integer"},"relationship":{"description":"`worksWith` — the agent's buyers were financed by loan officers at the caller's company; `doesNotWorkWith` — no such relationship (prospects).","enum":["worksWith","doesNotWorkWith"],"type":"string"}},"required":["relationship"],"type":"object"},"AgentMarket":{"properties":{"avgSalePrice":{"description":"`volume ÷ units` — the mean priced sale in this market.","nullable":true,"type":"number"},"shareOfScope":{"description":"This market's share of the agent's volume ACROSS THE SCOPE REQUESTED, 0–100. It sums to 100 over the whole scope, so a page truncated by `limit` sums to less than 100 by exactly the share left out — the shares do not re-normalize to the page, because a number that moved every time you changed the page size would not be a share of anything stable. It is NOT this agent's share of the market itself, and it is not comparable across agents.","nullable":true,"type":"number"},"transactions":{"description":"Transaction records matched in this market. NOT every one of them carries a price — compare with `units`.","type":"number"},"units":{"description":"Priced transaction records — the ones that contributed to `volume`, and the divisor behind `avgSalePrice`. Typically about half of `transactions`.","nullable":true,"type":"number"},"volume":{"description":"Total sale price across the priced records.","nullable":true,"type":"number"},"zipCode":{"description":"The ZIP code this market is keyed by.","nullable":true,"type":"string"}},"required":["zipCode","transactions","units","volume","avgSalePrice","shareOfScope"],"type":"object"},"AgentMarketsCommunityLending":{"description":"The Community Lending mix of this footprint: the neighborhood characteristics of where the production landed, as percentages on a 0-100 scale. Null when nothing in scope resolved to a neighborhood — an absent block, never a row of zeroes, because 'no data' and '0%' are different answers. Read `basis` before comparing two responses. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"affordableHousingTractPct":{"description":"Share of production, 0-100, in neighborhoods carrying an affordable-housing designation. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"basis":{"description":"Which measurement produced this block, and they are NOT the same number. `entityRollup` is the neighborhood mix of the entity's own production over the whole period — the default. `marketsInScope` is the neighborhood profile of the markets the request selected, weighted by the entity's production in each, and is what any ZIP, date or filter scope returns, because a whole-period rollup cannot be re-cut to a narrower question.","enum":["entityRollup","marketsInScope"],"type":"string"},"coveredProductionPct":{"description":"`marketsInScope` only — what share of the weighted production, 0-100, sits in a market that resolved to neighborhood data. Below 100 means the mix describes part of the footprint, not all of it.","nullable":true,"type":"number"},"difficultDevelopmentAreaPct":{"description":"Share of production, 0-100, in designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"distressedTractPct":{"description":"Share of production, 0-100, in distressed or underserved nonmetropolitan middle-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"floodHazardTractPct":{"description":"Share of production, 0-100, in neighborhoods inside a special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"incomeLevelMix":{"description":"`marketsInScope` only — the full relative-income distribution of the neighborhoods, 0-100, summing to about 100. Null on `entityRollup`, which stores the predominant band but no distribution; publishing one derived from a single label would be a histogram nobody measured. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"low":{"nullable":true,"type":"number"},"middle":{"nullable":true,"type":"number"},"moderate":{"nullable":true,"type":"number"},"upper":{"nullable":true,"type":"number"}},"required":["low","moderate","middle","upper"],"type":"object"},"loansWithCommunityData":{"description":"`entityRollup` only — how many of the entity's transactions in the period resolved to a neighborhood. This is the denominator every share below is a share OF, so read it first: a 100% share over three transactions is not a footprint.","nullable":true,"type":"number"},"lowModIncomeTractPct":{"description":"Share of production, 0-100, in low- or moderate-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractPct":{"description":"Share of production, 0-100, in majority-minority neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"marketsInScope":{"description":"`marketsInScope` only — ZIP markets the mix considered, including any that carried no neighborhood data.","nullable":true,"type":"number"},"marketsWithCommunityData":{"description":"`marketsInScope` only — ZIP markets that resolved to neighborhood data.","nullable":true,"type":"number"},"opportunityZonePct":{"description":"Share of production, 0-100, in designated Opportunity Zones. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"predominantIncomeLevel":{"description":"The most common relative-income classification of the neighborhoods, on the standard four-band scale. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","enum":["low","moderate","middle","upper",null],"nullable":true,"type":"string"},"ruralTractPct":{"description":"Share of production, 0-100, in neighborhoods classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTractPct":{"description":"Share of production, 0-100, in neighborhoods eligible for USDA rural housing programs. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"}},"required":["basis","loansWithCommunityData","marketsWithCommunityData","marketsInScope","coveredProductionPct","predominantIncomeLevel","incomeLevelMix","lowModIncomeTractPct","majorityMinorityTractPct","ruralTractPct","opportunityZonePct","affordableHousingTractPct","distressedTractPct","usdaEligibleTractPct","floodHazardTractPct","difficultDevelopmentAreaPct"],"type":"object"},"AgentMarketsDateRange":{"additionalProperties":false,"description":"Narrow the footprint to transactions inside this window. Omit for the agent's whole recorded history.","properties":{"from":{"description":"Inclusive lower bound on the transaction date.","example":"2024-01-01","pattern":"^\\d{4}(-\\d{2}(-\\d{2})?)?$","type":"string"},"to":{"description":"Inclusive upper bound on the transaction date.","example":"2025-12-31","pattern":"^\\d{4}(-\\d{2}(-\\d{2})?)?$","type":"string"}},"type":"object"},"AgentMarketsReach":{"properties":{"presentInScope":{"description":"Whether this agent is present in the requested ZIP scope at all — by office location OR by any transaction on record. Null when no scope was requested. `true` with an empty `markets` array means the agent works that market but has no priced transaction there in the window, which is a different answer from `false`.","nullable":true,"type":"boolean"},"transactedInScope":{"description":"Whether the scope produced any market with recorded transactions. Null when no scope was requested.","nullable":true,"type":"boolean"},"zipCodesRequested":{"description":"The normalized ZIP scope actually applied, or null when the caller asked for the whole footprint.","items":{"type":"string"},"nullable":true,"type":"array"}},"required":["zipCodesRequested","presentInScope","transactedInScope"],"type":"object"},"AgentMarketsRequest":{"additionalProperties":false,"properties":{"dateRange":{"$ref":"#/components/schemas/AgentMarketsDateRange"},"limit":{"description":"How many markets to return, ranked by volume descending (default 50). The summary is computed over the whole footprint BEFORE this truncation, so changing it never moves the totals or the average.","maximum":500,"minimum":1,"type":"integer"},"zipCodes":{"description":"Narrow the footprint to these ZIP codes. 1–5 digits; a value that is not a ZIP is a 400 naming it, never a silently narrower result. Leading zeros may be omitted (`1001` resolves to `01001`).","example":["77316","77578"],"items":{"type":"string"},"maxItems":200,"minItems":1,"type":"array"}},"type":"object"},"AgentMarketsResponse":{"properties":{"data":{"properties":{"agentId":{"description":"The canonical agent id these markets were computed for. May differ from the id sent if that id was a pre-merge one.","type":"string"},"basis":{"description":"This is a REACH view. An agent belongs to every market they touch, so agent counts across markets over-sum and cannot be turned into a market share. See `notes`.","enum":["reach"],"type":"string"},"markets":{"items":{"$ref":"#/components/schemas/AgentMarket"},"type":"array"},"notes":{"description":"Plain-language caveats that apply to every figure above.","items":{"type":"string"},"type":"array"},"reach":{"$ref":"#/components/schemas/AgentMarketsReach"},"source":{"$ref":"#/components/schemas/AgentMarketsSource"},"summary":{"$ref":"#/components/schemas/AgentMarketsSummary"}},"required":["agentId","basis","markets","summary","reach","source","notes"],"type":"object"}},"required":["data"],"type":"object"},"AgentMarketsSource":{"properties":{"mode":{"enum":["live"],"type":"string"},"reasons":{"description":"Why the figures were computed live from transaction records rather than read from a stored rollup.","items":{"type":"string"},"type":"array"}},"required":["mode","reasons"],"type":"object"},"AgentMarketsSummary":{"properties":{"avgSalePrice":{"description":"Volume-weighted mean priced sale across the footprint. Equal to `volume ÷ units`; NOT the average of the per-market averages, which drifts with market size.","nullable":true,"type":"number"},"communityLending":{"$ref":"#/components/schemas/AgentMarketsCommunityLending"},"marketCount":{"description":"How many placed markets contributed to this summary — the whole footprint inside the considered set, not the number of rows returned.","type":"number"},"shareOfBook":{"description":"Always null on this surface. A share of an agent's whole book would need a per-agent total to divide by, and the transaction records carry none — publishing a partial sum as a total is the error this field exists to refuse.","nullable":true},"transactions":{"type":"number"},"units":{"nullable":true,"type":"number"},"unresolved":{"$ref":"#/components/schemas/AgentMarketsUnresolved"},"volume":{"nullable":true,"type":"number"}},"required":["marketCount","transactions","units","volume","avgSalePrice","shareOfBook","unresolved","communityLending"],"type":"object"},"AgentMarketsUnresolved":{"description":"Transactions whose market could not be placed. Held OUT of the summary and every ranking, and reported here so the coverage is stated rather than hidden.","properties":{"transactions":{"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"}},"required":["transactions","units","volume"],"type":"object"},"AgentMortgagedTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"side":{"$ref":"#/components/schemas/AgentSide"}},"type":"object"},"AgentNearEntry":{"additionalProperties":false,"properties":{"city":{"minLength":1,"type":"string"},"lat":{"maximum":90,"minimum":-90,"type":"number"},"lon":{"maximum":180,"minimum":-180,"type":"number"},"radius":{"example":"25mi","minLength":1,"type":"string"},"state":{"minLength":1,"type":"string"}},"required":["lat","lon","radius"],"type":"object"},"AgentNearFilter":{"description":"Radius search, entries OR'd, on the `locationSource` points (current office / transactions / either). With `city`+`state` an entry also matches addresses in that city beyond the radius.","items":{"$ref":"#/components/schemas/AgentNearEntry"},"maxItems":50,"minItems":1,"type":"array"},"AgentProductMixEntry":{"additionalProperties":false,"properties":{"minShare":{"description":"Minimum financed volume of this product through ONE mortgage company, as a percent of the agent's period sale volume. Omit for 'any deal financed with this product'.","minimum":0,"type":"number"},"product":{"description":"Loan product (case-insensitive). `government` = FHA, VA or USDA.","enum":["conventional","fha","va","usda","government","he","heloc","commercial","building","reverse"],"type":"string"}},"required":["product"],"type":"object"},"AgentProductMixFilter":{"description":"Agents whose buyers financed with these loan products in the selected period, ANDed: `[{product: \"fha\"}, {product: \"va\", minShare: 10}]`. Not a whole-book share — the index stores product mix per mortgage company only.","items":{"$ref":"#/components/schemas/AgentProductMixEntry"},"maxItems":10,"minItems":1,"type":"array"},"AgentPropertiesResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/AgentPropertySummary"},"type":"array"},"total":{"type":"number"},"truncated":{"description":"`true` when more than 10,000 sales matched and a loan-side filter or a loan / party sort considered only the newest 10,000","type":"boolean"}},"required":["data","total"],"type":"object"},"AgentPropertySummary":{"properties":{"address":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"date":{"nullable":true,"type":"string"},"id":{"type":"string"},"mmPropertyId":{"nullable":true,"type":"string"},"price":{"nullable":true,"type":"number"},"propertyType":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"AgentRelationRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"dealFilters":{"$ref":"#/components/schemas/AgentDealFilters"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/SaleFlatFilters"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"side":{"$ref":"#/components/schemas/AgentSide"},"sort":{"items":{"properties":{"field":{"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"AgentSaleLoanFilters":{"additionalProperties":false,"description":"Filters on the sale's purchase loan (the row's `loan`), with the `/v1/loans` filter semantics. Any key here keeps only financed deals whose purchase loan matches.","properties":{"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"}},"type":"object"},"AgentSaleSummary":{"properties":{"address":{"description":"Full street line — number, directionals, street name, suffix and unit (`123 w 4th st`), lowercase","nullable":true,"type":"string"},"builderName":{"description":"Builder, on a new-construction sale","nullable":true,"type":"string"},"buyer1FirstMiddle":{"description":"First buyer's first + middle name (an entity's whole name, with no last).","nullable":true,"type":"string"},"buyer1Last":{"description":"First buyer's last name.","nullable":true,"type":"string"},"buyer2FirstMiddle":{"description":"Second buyer's first + middle name.","nullable":true,"type":"string"},"buyer2Last":{"description":"Second buyer's last name.","nullable":true,"type":"string"},"buyerName":{"description":"First buyer named on the sale — from the purchase loan's document when the MLS record names none; `null` on most cash deals","nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"coListAgentId":{"description":"Co-listing agent's id (`GET /v1/agents/{id}`), when the sale's agent key resolves to one agent","nullable":true,"type":"string"},"coListAgentName":{"description":"Co-listing agent's name — the agent record's (lowercase) when `coListAgentId` resolved from the MLS keys, else as the MLS recorded it; lowercase","nullable":true,"type":"string"},"date":{"nullable":true,"type":"string"},"id":{"type":"string"},"listAgentId":{"description":"Listing agent's id (`GET /v1/agents/{id}`), when the sale's agent key resolves to one agent","nullable":true,"type":"string"},"listAgentName":{"nullable":true,"type":"string"},"listDate":{"description":"MLS listing date (`YYYY-MM-DD`); days on market = `date` − `listDate`","nullable":true,"type":"string"},"listOfficeName":{"description":"Listing agent's brokerage (office), as the MLS recorded it; `null` when not on file","nullable":true,"type":"string"},"listPrice":{"description":"Last MLS list price","nullable":true,"type":"number"},"loan":{"description":"The purchase loan recorded against this sale (matched on the sale id), or `null` when none is recorded — a cash deal, or a loan not yet on file.","nullable":true,"properties":{"amount":{"nullable":true,"type":"number"},"brokerName":{"description":"Mortgage broker as written on the loan document, when the loan was third-party originated","nullable":true,"type":"string"},"brokerNmlsId":{"description":"Mortgage broker NMLS id when the loan was third-party originated","nullable":true,"type":"string"},"companyName":{"description":"Mortgage company the loan was written under","nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"employerName":{"description":"Employer at the time of the loan (the LO's company then), as recorded. Not `companyName`, the funding company on the document.","nullable":true,"type":"string"},"employerNmlsId":{"description":"NMLS id of `employerName`.","nullable":true,"type":"string"},"id":{"description":"Loan id (`GET /v1/loans/{id}`)","type":"string"},"interestRate":{"description":"Note rate in percent (e.g. `6.25`), recorded or modeled; `null` when not on file","nullable":true,"type":"number"},"lenderId":{"description":"Normalized lender key — the value the `lender` filter accepts","nullable":true,"type":"string"},"lenderName":{"description":"Lender as written on the loan document","nullable":true,"type":"string"},"loanType":{"description":"e.g. `conventional`, `fha`, `va`","nullable":true,"type":"string"},"originatorName":{"nullable":true,"type":"string"},"originatorNmlsId":{"nullable":true,"type":"string"},"titleCompany":{"nullable":true,"type":"string"},"transactionType":{"description":"e.g. `purchase`, `refinance`","nullable":true,"type":"string"}},"required":["id","amount","loanType","transactionType","lenderName","lenderId","originatorName","originatorNmlsId","companyName","companyNmlsId","brokerNmlsId","titleCompany"],"type":"object"},"mmPropertyId":{"description":"The property's id (`GET /v1/properties/{id}`)","nullable":true,"type":"string"},"price":{"nullable":true,"type":"number"},"seller1FirstMiddle":{"description":"First seller's first + middle name.","nullable":true,"type":"string"},"seller1Last":{"description":"First seller's last name.","nullable":true,"type":"string"},"seller2FirstMiddle":{"description":"Second seller's first + middle name.","nullable":true,"type":"string"},"seller2Last":{"description":"Second seller's last name.","nullable":true,"type":"string"},"sellerName":{"description":"First seller named on the sale — from the purchase loan's document when the MLS record names none","nullable":true,"type":"string"},"side":{"description":"Which side of this deal the agent was on: `buyer`, `listing`, or `dual` (both). `null` when the sale names the agent under an id this API cannot place on a side.","enum":["buyer","listing","dual",null],"nullable":true,"type":"string"},"soldAgentId":{"description":"Buyer's (selling) agent's id (`GET /v1/agents/{id}`), when the sale's agent key resolves to one agent","nullable":true,"type":"string"},"soldAgentName":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"txType":{"description":"Property type for the transacted property (e.g. `Residential`, `Condominium`) — the same value `/v1/sales` returns as `propertyType`. Named `txType` for backwards compatibility. Present on roughly 19% of sales; the rest carry no MLS listing type and read `null`.","nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"AgentSalesBreakdownRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"side":{"$ref":"#/components/schemas/AgentSide"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"AgentSalesResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/AgentSaleSummary"},"type":"array"},"total":{"type":"number"},"truncated":{"description":"`true` when more than 10,000 sales matched and a loan-side filter or a loan / party sort considered only the newest 10,000","type":"boolean"}},"required":["data","total"],"type":"object"},"AgentScoredBreakdownRequest":{"properties":{"period":{"$ref":"#/components/schemas/Period"},"side":{"$ref":"#/components/schemas/AgentSide"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"AgentSide":{"description":"Which side of the deal the agent was on. `buyer`: the agent represented the buyer — deals where the agent was on BOTH sides (dual) count here. `listing`: the agent represented the seller only (duals are already in `buyer`). `any` (default): either side, each deal once. `buyer` + `listing` = `any`.","enum":["any","buyer","listing"],"type":"string"},"AgentSideDominance":{"description":"Which side the agent mostly represents in the selected period, OR'd: `buyer` = more buyer-side than seller-side deals, `seller` = the reverse (a tie is neither), `dual` = at least one dual-agency deal.","items":{"enum":["buyer","seller","dual"],"type":"string"},"minItems":1,"type":"array"},"AgentSummary":{"properties":{"avgSoldPrice":{"nullable":true,"type":"number"},"buyerUnits":{"nullable":true,"type":"number"},"buyerVolume":{"nullable":true,"type":"number"},"city":{"nullable":true,"type":"string"},"dualUnits":{"nullable":true,"type":"number"},"dualVolume":{"nullable":true,"type":"number"},"email":{"nullable":true,"type":"string"},"firstName":{"nullable":true,"type":"string"},"fullName":{"nullable":true,"type":"string"},"id":{"description":"Document ID","type":"string"},"lastName":{"nullable":true,"type":"string"},"licenseNumber":{"nullable":true,"type":"string"},"modelMatchId":{"nullable":true,"type":"string"},"office":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"sellerUnits":{"nullable":true,"type":"number"},"sellerVolume":{"nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"totalCompaniesWorkedWith":{"nullable":true,"type":"number"},"totalLendersWorkedWith":{"nullable":true,"type":"number"},"totalOriginatorsWorkedWith":{"nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"AgentSummaryRequest":{"additionalProperties":false,"properties":{"id":{"type":"string"},"ids":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"}},"type":"object"},"AgentTimeSeriesRequest":{"additionalProperties":false,"properties":{"id":{"type":"string"},"ids":{"items":{"type":"string"},"type":"array"},"interval":{"$ref":"#/components/schemas/Interval"},"period":{"$ref":"#/components/schemas/Period"}},"type":"object"},"AgentTitleCompanyTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"side":{"$ref":"#/components/schemas/AgentSide"}},"type":"object"},"AlertConditions":{"properties":{"epoThresholdDays":{"description":"Max days since loan close for an early-payoff alert.","example":180,"type":"integer"},"refiRateThreshold":{"description":"Minimum loan rate (%) before a refi-risk alert fires.","example":7,"type":"number"}},"type":"object"},"AlertConditionsResponse":{"properties":{"data":{"properties":{"conditions":{"$ref":"#/components/schemas/AlertConditions"},"emailEnabled":{"deprecated":true,"description":"Deprecated and ignored: accepted for compatibility, but not stored and no longer controls delivery (the response always reports every flag off). Email and in-app channel preferences for alerts live in Notifications settings.","properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"required":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan"],"type":"object"},"enabled":{"$ref":"#/components/schemas/AlertEnabled"}},"required":["enabled","emailEnabled","conditions"],"type":"object"}},"required":["data"],"type":"object"},"AlertDecision":{"properties":{"correlationId":{"type":"string"},"dedupeKey":{"type":"string"},"orgId":{"type":"string"},"payload":{"additionalProperties":{"nullable":true},"properties":{"description":{"type":"string"},"url":{"type":"string"}},"required":["description"],"type":"object"},"triggeredAt":{"type":"string"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"userId":{"type":"string"}},"required":["userId","type","dedupeKey","payload","triggeredAt"],"type":"object"},"AlertDetectorStatusResponse":{"properties":{"data":{"properties":{"running":{"type":"boolean"},"tasks":{"items":{"properties":{"arn":{"type":"string"},"startedAt":{"type":"string"},"status":{"type":"string"},"stoppedReason":{"type":"string"}},"required":["arn","status"],"type":"object"},"type":"array"}},"required":["running","tasks"],"type":"object"}},"required":["data"],"type":"object"},"AlertDigestItem":{"properties":{"count":{"description":"Total alerts rolled into this digest.","type":"integer"},"id":{"description":"Opaque digest id for mark-read.","type":"string"},"ids":{"description":"The individual alert ids — resolve full detail via the feed.","items":{"type":"string"},"type":"array"},"preview":{"description":"First few human-formatted preview lines.","items":{"type":"string"},"type":"array"},"readAt":{"type":"string"},"triggeredAt":{"type":"string"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}},"required":["id","type","count","ids","preview","triggeredAt"],"type":"object"},"AlertDigestResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/AlertDigestItem"},"type":"array"}},"required":["data"],"type":"object"},"AlertEmailTemplatePreviewRequest":{"properties":{"kinds":{"description":"The alert kinds to sample (and validate item tokens against). Default: the recipe's kinds, else every kind.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"recipeId":{"description":"Preview under this recipe (its copy, family and kinds). Omitted: a neutral stand-in recipe.","type":"string"},"template":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"}},"required":["template"],"type":"object"},"AlertEmailTemplatePreviewResponse":{"properties":{"ok":{"enum":[true],"type":"boolean"},"props":{"$ref":"#/components/schemas/AlertRecipeDigestProps"},"subjectPreview":{"description":"The email subject with the sample count filled in.","type":"string"}},"required":["ok","subjectPreview","props"],"type":"object"},"AlertEmailTokensResponse":{"properties":{"byKind":{"description":"Item tokens per alert kind, usable inside an `items` block. A token offered by ANY of a recipe's kinds is allowed; an item without a value drops that line.","properties":{"agent_sale_closed":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"area_new_listing":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"area_property":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"book_loan":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"book_property":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"borrower_listed":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"epo_risk":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"rate_term_refi_area":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"watched_agent_pending":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"watched_loan":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"watched_property":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"},"watched_sale":{"items":{"properties":{"example":{"description":"A formatted sample value.","type":"string"},"label":{"type":"string"},"token":{"description":"Use as `{token}`.","example":"price","type":"string"}},"required":["token","label","example"],"type":"object"},"type":"array"}},"required":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"object"},"run":{"description":"Tokens usable anywhere: count, recipe, appUrl, date, firstName.","items":{"type":"string"},"type":"array"}},"required":["run","byKind"],"type":"object"},"AlertEnabled":{"properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"required":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan"],"type":"object"},"AlertLogItem":{"properties":{"id":{"description":"Opaque id for mark-read.","type":"string"},"payload":{"additionalProperties":{"nullable":true},"description":"Human description + optional deep link + typed fields.","properties":{"description":{"type":"string"},"url":{"type":"string"}},"required":["description"],"type":"object"},"readAt":{"type":"string"},"triggeredAt":{"type":"string"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}},"required":["id","type","payload","triggeredAt"],"type":"object"},"AlertLogResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/AlertLogItem"},"type":"array"}},"required":["data"],"type":"object"},"AlertMyRecipeDefinition":{"description":"Your own alert recipe. The server derives its family, default inputs and digest copy.","properties":{"description":{"description":"What it watches for (also the digest intro).","maxLength":240,"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"grants":{"description":"The alert kinds per subject type (`nmls`, `agent`, `area`, or `document` rule templates). Every kind must belong to ONE notification family (else 400 `family_mismatch`).","properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"icon":{"description":"One of: Agreement02Icon, Alert02Icon, AnalyticsUpIcon, Award01Icon, BankIcon, BinocularsIcon, Bookmark02Icon, Briefcase01Icon, Building03Icon, Building06Icon, Calendar03Icon, Call02Icon, Certificate01Icon, ChartIncreaseIcon, ChartLineData01Icon, Clock01Icon, Coins01Icon, Crown02Icon, DollarCircleIcon, Exchange01Icon, File01Icon, FileValidationIcon, Fire02Icon, Flag02Icon, FlashIcon, Globe02Icon, Home01Icon, House03Icon, Idea01Icon, Invoice01Icon, Key01Icon, Location01Icon, Mail01Icon, MapPinIcon, MapsLocation01Icon, Megaphone01Icon, Money03Icon, MoneyBag02Icon, MoneyExchange01Icon, MoneyReceive02Icon, Notification03Icon, PercentCircleIcon, Radar01Icon, RealEstate01Icon, RealEstate02Icon, RefreshIcon, Rocket01Icon, RouteIcon, SaleTag02Icon, Search01Icon, Shield01Icon, SparklesIcon, StarIcon, Store01Icon, Target02Icon, TradeUpIcon, UserCheck01Icon, UserGroupIcon, UserLove01Icon, UserMultiple02Icon, UserMultipleIcon, UserSearch01Icon, UserStar01Icon, ViewIcon, Wallet01Icon. Default Notification03Icon.","type":"string"},"inputs":{"description":"What subscribing asks for. Omitted: one required input per subject type the grants use (an NMLS id comes from your alert settings).","items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"maxItems":4,"type":"array"},"title":{"description":"The alert's name (also its digest subject / headline).","maxLength":60,"minLength":1,"type":"string"}},"required":["title","grants"],"type":"object"},"AlertMyRecipePreviewRequest":{"properties":{"definition":{"$ref":"#/components/schemas/AlertMyRecipeDefinition"},"inputs":{"allOf":[{"$ref":"#/components/schemas/AlertRecipeInputs"},{"description":"Inputs to preview with (as the subscribe body)."}]}},"required":["definition"],"type":"object"},"AlertMyRecipeUpdate":{"properties":{"description":{"description":"What it watches for (also the digest intro).","maxLength":240,"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"grants":{"description":"The alert kinds per subject type (`nmls`, `agent`, `area`, or `document` rule templates). Every kind must belong to ONE notification family (else 400 `family_mismatch`).","properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"icon":{"description":"One of: Agreement02Icon, Alert02Icon, AnalyticsUpIcon, Award01Icon, BankIcon, BinocularsIcon, Bookmark02Icon, Briefcase01Icon, Building03Icon, Building06Icon, Calendar03Icon, Call02Icon, Certificate01Icon, ChartIncreaseIcon, ChartLineData01Icon, Clock01Icon, Coins01Icon, Crown02Icon, DollarCircleIcon, Exchange01Icon, File01Icon, FileValidationIcon, Fire02Icon, Flag02Icon, FlashIcon, Globe02Icon, Home01Icon, House03Icon, Idea01Icon, Invoice01Icon, Key01Icon, Location01Icon, Mail01Icon, MapPinIcon, MapsLocation01Icon, Megaphone01Icon, Money03Icon, MoneyBag02Icon, MoneyExchange01Icon, MoneyReceive02Icon, Notification03Icon, PercentCircleIcon, Radar01Icon, RealEstate01Icon, RealEstate02Icon, RefreshIcon, Rocket01Icon, RouteIcon, SaleTag02Icon, Search01Icon, Shield01Icon, SparklesIcon, StarIcon, Store01Icon, Target02Icon, TradeUpIcon, UserCheck01Icon, UserGroupIcon, UserLove01Icon, UserMultiple02Icon, UserMultipleIcon, UserSearch01Icon, UserStar01Icon, ViewIcon, Wallet01Icon. Default Notification03Icon.","type":"string"},"inputs":{"description":"What subscribing asks for. Omitted: one required input per subject type the grants use (an NMLS id comes from your alert settings).","items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"maxItems":4,"type":"array"},"title":{"description":"The alert's name (also its digest subject / headline).","maxLength":60,"minLength":1,"type":"string"},"version":{"description":"The version you edited; a stale one answers 409 `version_conflict`.","minimum":1,"type":"integer"}},"required":["title","grants"],"type":"object"},"AlertRecipe":{"properties":{"category":{"type":"string"},"description":{"type":"string"},"family":{"description":"Notification family (selects the email template).","enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"featured":{"type":"boolean"},"hasEmailTemplate":{"description":"Whether the recipe sends a custom email template (else the built-in email).","type":"boolean"},"howItWorks":{"type":"string"},"icon":{"description":"hugeicons component name; render with a fallback.","example":"UserGroupIcon","type":"string"},"id":{"type":"string"},"inputs":{"items":{"$ref":"#/components/schemas/AlertRecipeInputSpec"},"type":"array"},"inputsSchema":{"additionalProperties":{"nullable":true},"description":"JSON Schema of the inputs the recipe needs to subscribe.","type":"object"},"label":{"description":"Same as `title` (kept for compatibility).","type":"string"},"scope":{"description":"`global`: a Model Match recipe; `mine`: one of your own recipes (id `u-…`).","enum":["global","mine"],"type":"string"},"sortOrder":{"type":"integer"},"subscribed":{"description":"Whether you are subscribed: at least one of your subscriptions carries this recipe.","type":"boolean"},"title":{"type":"string"},"types":{"description":"The alert triggers this recipe turns on.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"required":["id","title","label","description","icon","category","family","types","inputs","inputsSchema","featured","sortOrder","hasEmailTemplate","subscribed","scope"],"type":"object"},"AlertRecipeDigestProps":{"description":"The notification props a run dispatches for one recipe (v3) — what the email renders from.","properties":{"appUrl":{"type":"string"},"count":{"type":"integer"},"date":{"description":"Run date, e.g. `Oct 5`.","type":"string"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"firstName":{"type":"string"},"propsVersion":{"enum":[3],"type":"number"},"recipe":{"properties":{"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"headline":{"type":"string"},"icon":{"type":"string"},"id":{"type":"string"},"intro":{"type":"string"},"plural":{"type":"string"},"subject":{"type":"string"},"title":{"type":"string"}},"required":["id","title","icon","headline","intro","plural","subject"],"type":"object"},"runId":{"type":"string"},"sections":{"items":{"properties":{"count":{"type":"integer"},"items":{"items":{"properties":{"alertId":{"type":"string"},"fields":{"additionalProperties":{"type":"string"},"description":"The formatted item tokens (only non-empty values).","type":"object"},"kind":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"summary":{"type":"string"},"title":{"type":"string"},"url":{"type":"string"}},"required":["alertId","title","kind","fields"],"type":"object"},"type":"array"},"label":{"type":"string"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}},"required":["type","label","count","items"],"type":"object"},"type":"array"},"triggeredAt":{"type":"string"}},"required":["propsVersion","recipe","family","runId","triggeredAt","count","sections","appUrl","date"],"type":"object"},"AlertRecipeEmailBlock":{"properties":{"columns":{"description":"items, table layout only: 1–5 columns (`value` is a token template).","items":{"properties":{"label":{"type":"string"},"value":{"type":"string"}},"required":["label","value"],"type":"object"},"type":"array"},"href":{"description":"button: `{appUrl}` (the alerts page).","type":"string"},"label":{"description":"button: the label (≤40).","type":"string"},"layout":{"description":"items: cards | list | table.","type":"string"},"link":{"description":"items: `{url}` (default — each entry links) or `none`.","type":"string"},"max":{"description":"items: how many to show, 1–25 (default 10).","type":"integer"},"meta":{"description":"items: up to 4 detail lines; a line whose token has no value for an entry is dropped.","items":{"type":"string"},"type":"array"},"text":{"description":"heading / text / callout: the copy (tokens allowed).","type":"string"},"title":{"description":"items: each entry's title line (item tokens allowed).","type":"string"},"tone":{"description":"callout: info | success | warning.","type":"string"},"type":{"description":"heading (`text` ≤120) · text (`text` ≤600; newlines become line breaks) · callout (`tone` info|success|warning + `text` ≤300) · items (one entry per alert: `layout` cards|list|table, `title`, optional `meta` lines, `columns` for table, `max`, `link`) · button (`label` ≤40 + `href` `{appUrl}`) · divider.","enum":["heading","text","callout","items","button","divider"],"type":"string"}},"required":["type"],"type":"object"},"AlertRecipeEmailTemplate":{"description":"The recipe's email, as blocks. Plain text only. Tokens: `{count}`, `{recipe}`, `{appUrl}`, `{date}`, `{firstName}` anywhere; `{one|many}` (resolved by count) in heading / text / callout; item tokens (GET /alerts/email-tokens, per alert kind) inside an items block. Serialized size ≤ 8 KB.","properties":{"blocks":{"description":"1–20 blocks, rendered top to bottom.","items":{"$ref":"#/components/schemas/AlertRecipeEmailBlock"},"type":"array"},"version":{"description":"Template format version.","enum":[1],"type":"number"}},"required":["version","blocks"],"type":"object"},"AlertRecipeError":{"properties":{"code":{"description":"Machine-readable reason (absent on a generic validation error).","enum":["unknown_recipe","recipe_archived","invalid_recipe","invalid_recipe_id","invalid_icon","invalid_kind","kind_not_allowed_for_subject","unknown_field","invalid_rule","rule_edge_op_on_event_kind","rule_op_not_supported_for_area","grants_empty","family_mismatch","inputs_mismatch","invalid_inputs","rules_required","recipe_exists","recipe_in_use","version_conflict","recipe_limit","no_org","invalid_title","invalid_email_template"],"type":"string"},"details":{"description":"`invalid_email_template`: every problem found (fix them all in one go).","items":{"properties":{"path":{"description":"Where, e.g. `email.blocks.2.meta.0`.","type":"string"},"reason":{"type":"string"}},"required":["path","reason"],"type":"object"},"type":"array"},"error":{"description":"Error message","type":"string"}},"required":["error"],"type":"object"},"AlertRecipeInputSpec":{"description":"One input the subscribe form asks for. `type` maps to body fields: nmls → nmlsId, agent → agents, area → areas, document → documentType + documentId + rules.","properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"AlertRecipeInputs":{"properties":{"agents":{"description":"Recipes with an `agent` input: the agents.","items":{"properties":{"agentMmaId":{"description":"Agent id.","minLength":1,"type":"string"}},"required":["agentMmaId"],"type":"object"},"maxItems":50,"type":"array"},"areas":{"description":"Recipes with an `area` input: the areas.","items":{"$ref":"#/components/schemas/AddWatchedAreaRequest"},"maxItems":25,"type":"array"},"documentId":{"description":"Recipes with a `document` input: the record id.","minLength":1,"type":"string"},"documentType":{"description":"Recipes with a `document` input: the record type.","enum":["sale","property","loan"],"example":"property","type":"string"},"nmlsId":{"description":"Recipes with an `nmls` input: the loan officer's NMLS id.","type":"string"},"rules":{"description":"Recipes with a `document` input: what change to watch for. Empty or omitted applies the recipe's rule templates for the record type.","items":{"properties":{"match":{"description":"How predicates combine: all (AND, default) or any (OR).","enum":["all","any"],"example":"all","type":"string"},"predicates":{"description":"One or more conditions; combined per match.","items":{"properties":{"field":{"description":"Catalog field alias (e.g. avm, current_ltv, loan_type).","example":"current_ltv","type":"string"},"op":{"description":"Comparison / change / status / guard operator.","enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"example":"lte","type":"string"},"stringValue":{"description":"Target keyword for changed_to / eq / not_eq guard.","type":"string"},"stringValues":{"description":"Keyword set for the in guard (1–20).","items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"description":"Threshold, or change amount (percent for pct_change_gte).","example":0.8,"type":"number"},"value2":{"description":"Upper bound for between.","type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"AlertRecipePreviewResponse":{"properties":{"data":{"properties":{"byType":{"additionalProperties":{"type":"integer"},"description":"Count per alert trigger.","type":"object"},"count":{"description":"Alerts the recipe would have fired in the window.","type":"integer"},"sample":{"description":"The newest few, as digest lines.","items":{"properties":{"description":{"type":"string"},"title":{"type":"string"},"triggeredAt":{"type":"string"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}},"required":["type","title","description","triggeredAt"],"type":"object"},"type":"array"},"since":{"description":"Window start (ISO).","type":"string"}},"required":["count","byType","sample","since"],"type":"object"}},"required":["data"],"type":"object"},"AlertRecipeResponse":{"properties":{"data":{"$ref":"#/components/schemas/AlertRecipe"}},"required":["data"],"type":"object"},"AlertRecipesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AlertRecipe"},"type":"array"}},"required":["data"],"type":"object"},"AlertSubscription":{"properties":{"createdAt":{"type":"string"},"display":{"$ref":"#/components/schemas/AlertSubscriptionDisplay"},"expiresAt":{"description":"When the subscription stops firing (ISO 8601).","type":"string"},"grants":{"items":{"$ref":"#/components/schemas/AlertSubscriptionGrant"},"type":"array"},"id":{"description":"Opaque subscription id.","type":"string"},"kinds":{"description":"The alert kinds that fire on this subject (empty = paused).","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"rules":{"items":{"$ref":"#/components/schemas/WatchedDocumentRule"},"type":"array"},"subjectType":{"enum":["agent","area","nmls","property","loan","sale","company","filter"],"type":"string"},"updatedAt":{"type":"string"}},"required":["id","subjectType","display","kinds","grants","createdAt","updatedAt"],"type":"object"},"AlertSubscriptionDisplay":{"description":"What the subscription watches, for display.","properties":{"agentMmaId":{"type":"string"},"areaType":{"enum":["city","county","zip","bbox","radius"],"type":"string"},"documentId":{"type":"string"},"documentType":{"enum":["sale","property","loan"],"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"maxLat":{"type":"number"},"maxLon":{"type":"number"},"minLat":{"type":"number"},"minLon":{"type":"number"},"name":{"type":"string"},"nmlsId":{"type":"string"},"radiusMeters":{"type":"number"},"state":{"type":"string"},"value":{"type":"string"}},"type":"object"},"AlertSubscriptionError":{"properties":{"code":{"description":"Machine-readable reason (absent on a generic validation error).","enum":["invalid_kind","kind_not_allowed_for_subject","subject_type_not_supported","rules_required","rule_edge_op_on_event_kind","unknown_field","invalid_rule","invalid_area","invalid_subject","invalid_subscription_id","nmls_mismatch"],"type":"string"},"error":{"description":"Error message","type":"string"}},"required":["error"],"type":"object"},"AlertSubscriptionGrant":{"properties":{"addedAt":{"type":"string"},"addedBy":{"description":"Who set the grant up on the user's behalf (`admin:{userId}`); absent when the user did.","type":"string"},"kinds":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"recipeId":{"description":"Why the kinds are on: a recipe id (see GET /alerts/recipes), `custom` (set directly), or `migration`.","type":"string"}},"required":["recipeId","kinds","addedAt"],"type":"object"},"AlertSubscriptionResponse":{"properties":{"data":{"$ref":"#/components/schemas/AlertSubscription"}},"required":["data"],"type":"object"},"AlertSubscriptionSubject":{"properties":{"agentMmaId":{"description":"agent: the agent id.","minLength":1,"type":"string"},"area":{"description":"Area subject: the same body as POST /watched-areas.","properties":{"lat":{"description":"Center latitude (point + radius).","maximum":90,"minimum":-90,"type":"number"},"lon":{"description":"Center longitude.","maximum":180,"minimum":-180,"type":"number"},"maxLat":{"description":"Box north edge.","maximum":90,"minimum":-90,"type":"number"},"maxLon":{"description":"Box east edge.","maximum":180,"minimum":-180,"type":"number"},"minLat":{"description":"Box south edge.","maximum":90,"minimum":-90,"type":"number"},"minLon":{"description":"Box west edge.","maximum":180,"minimum":-180,"type":"number"},"radius":{"description":"Radius around the center point.","example":10,"exclusiveMinimum":true,"minimum":0,"type":"number"},"state":{"description":"2-letter state. Ignored for zip + geo areas.","example":"CA","type":"string"},"type":{"description":"Named area (city/county/zip) or geo area (bbox = bounding box, radius = point + radius).","enum":["city","county","zip","bbox","radius"],"type":"string"},"unit":{"description":"Radius unit (default mi).","enum":["mi","km","m"],"example":"mi","type":"string"},"value":{"description":"City / county name, or 5-digit zip. Required for named areas.","example":"Los Angeles","type":"string"}},"required":["type"],"type":"object"},"documentId":{"description":"sale / property / loan: the record id.","minLength":1,"type":"string"},"nmlsId":{"description":"nmls: your NMLS id.","minLength":1,"type":"string"},"type":{"description":"agent, area, nmls (your own NMLS id), sale, property or loan. company and filter are reserved.","enum":["agent","area","nmls","property","loan","sale","company","filter"],"type":"string"}},"required":["type"],"type":"object"},"AlertSubscriptionsResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AlertSubscription"},"type":"array"}},"required":["data"],"type":"object"},"AlertUserRecipe":{"properties":{"category":{"type":"string"},"copy":{"properties":{"headline":{"maxLength":200,"minLength":1,"type":"string"},"intro":{"maxLength":1000,"type":"string"},"plural":{"maxLength":40,"minLength":1,"type":"string"},"subject":{"maxLength":200,"minLength":1,"type":"string"}},"required":["subject","headline","intro","plural"],"type":"object"},"createdAt":{"type":"string"},"createdBy":{"type":"string"},"description":{"type":"string"},"email":{"$ref":"#/components/schemas/AlertRecipeEmailTemplate"},"family":{"enum":["past-clients","agent-partners","farm-area","watch-record"],"type":"string"},"grants":{"properties":{"agent":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"area":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"areaRules":{"properties":{"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"book":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"document":{"properties":{"loan":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"property":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"sale":{"items":{"properties":{"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"properties":{"field":{"type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"}},"type":"object"},"nmls":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"icon":{"type":"string"},"id":{"type":"string"},"inputs":{"items":{"properties":{"documentType":{"enum":["sale","property","loan"],"type":"string"},"help":{"maxLength":400,"type":"string"},"label":{"maxLength":80,"type":"string"},"max":{"minimum":1,"type":"integer"},"min":{"minimum":0,"type":"integer"},"required":{"type":"boolean"},"type":{"enum":["nmls","agent","area","document"],"type":"string"}},"required":["type","required"],"type":"object"},"type":"array"},"maxItemsPerRun":{"type":"integer"},"ownerUserId":{"type":"string"},"promotedTo":{"description":"The global recipe id this was promoted to.","type":"string"},"scope":{"enum":["user"],"type":"string"},"status":{"enum":["active","archived"],"type":"string"},"subscribed":{"description":"Lists only: whether the owner is subscribed (a subscription carries it).","type":"boolean"},"title":{"type":"string"},"updatedAt":{"type":"string"},"updatedBy":{"type":"string"},"version":{"minimum":1,"type":"integer"}},"required":["id","ownerUserId","scope","title","description","icon","category","family","grants","inputs","copy","maxItemsPerRun","status","version","createdBy","createdAt","updatedBy","updatedAt"],"type":"object"},"AlertUserRecipeResponse":{"properties":{"data":{"$ref":"#/components/schemas/AlertUserRecipe"}},"required":["data"],"type":"object"},"AlertUserRecipesResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/AlertUserRecipe"},"type":"array"}},"required":["data"],"type":"object"},"AlertsOkResponse":{"properties":{"data":{"properties":{"ok":{"type":"boolean"}},"required":["ok"],"type":"object"}},"required":["data"],"type":"object"},"AnalyticsCompleteness":{"description":"Data-completeness watermark for this response. Present only when it could be measured; absence means it was not measured, NOT that the data is complete.","properties":{"through":{"description":"The last calendar date (`YYYY-MM-DD`) this query's matching records actually reach. Records arrive after the events they describe, so a period ending today is normally backed by data ending days or weeks earlier, and any bucket extending past this date is built from a partial period. Measured from THIS query's own matched set, not a global figure: the delay varies by geography and moves over time, so two requests with different filters can legitimately report different dates.","format":"date","type":"string"}},"required":["through"],"type":"object"},"AndFilter":{"properties":{"children":{"description":"Array of filter expressions (AND)","items":{"$ref":"#/components/schemas/FilterNode"},"type":"array"},"type":{"enum":["and"],"type":"string"}},"required":["type","children"],"type":"object"},"BooleanFilterValue":{"nullable":true,"type":"boolean"},"BranchChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"nmlsId":{"description":"Branch NMLS ID","minLength":1,"type":"string"},"period":{"$ref":"#/components/schemas/Period"},"segment":{"allOf":[{"$ref":"#/components/schemas/BranchSlice"},{"description":"Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."}]},"slice":{"$ref":"#/components/schemas/BranchSlice"}},"required":["nmlsId","slice"],"type":"object"},"BranchCompanyTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): BANK, CU, OTHER","enum":["BANK","CU","OTHER"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): BANK, CU, OTHER","enum":["BANK","CU","OTHER"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"BranchCrmListFilter":{"additionalProperties":false,"description":"Scope the result to the caller's CRM. Resolved against the caller's ACTIVE WORKSPACE at query time — list membership is read server-side, so the request never carries member ids. Only branch members count; people, companies, offices and manual (unlinked) records on the same list are ignored. `mode: \"in\"` with no matching members returns an empty page (not an unfiltered one). Errors: 400 `crm_list_requires_workspace` when the caller has no active workspace (API-key / OAuth callers must select an organization), 403 / 404 when a named list is not visible to the caller or does not exist, and 400 `crm_list_too_large` when the selected lists hold more than 50,000 branches in total — narrow the selection rather than get a silently partial answer.","properties":{"lists":{"anyOf":[{"description":"Every list in the caller's workspace that the caller can see (own, org-wide, or shared with them) and that holds this kind of record — People lists for originators and agents, Company lists for companies.","enum":["any"],"type":"string"},{"description":"Specific CRM list ids (1–50).","items":{"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"}],"description":"Which lists: `\"any\"` for every Company list the caller can see, or an array of list ids. Membership is the UNION across the selected lists."},"mode":{"description":"`in` — only branches who are a member of the selected list(s). `notIn` — exclude every branch who is a member of the selected list(s); everyone else passes, including branches on none of your lists.","enum":["in","notIn"],"type":"string"}},"required":["mode","lists"],"type":"object"},"BranchDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/BranchSummary"}},"required":["data"],"type":"object"},"BranchField":{"enum":["company","companyName","companyType","name","nmlsId","city","state","zip","zipCode","licensedState","isAuthorized","volume","units","avgLoanAmount","teamSize","loCount","rosterJoined","rosterLeft","producersOnly","purchaseShare","refinanceShare"],"type":"string"},"BranchFlatFilters":{"additionalProperties":false,"properties":{"affordableHousingTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in qualified affordable-housing tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"affordableHousingTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in qualified census tracts for affordable-housing programs, 0-100 (`{gte:25}` = 27,209 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgAsianPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Asian (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgBlackPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Black (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgDenialRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of mortgage applications denied in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgFamilyIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median family income of the tracts the entity lent in, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Hispanic or Latino share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median home value across the tracts the entity lent in, in whole dollars. A neighborhood statistic — not the entity's average loan size, which is `avgLoanAmount`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeownershipRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean owner-occupied share of housing units in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHouseholdIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median household income of the tracts the entity lent in, in whole dollars (e.g. `{lte:60000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean tract income relative to its metro area, where `100` is parity — `{lt:80}` is the CRA low/moderate band, and values legitimately exceed 100 (observed up to 412). NOT a 0-100 share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgLoanAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"avgLowModHouseholdPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean HUD block-group low/moderate-income HOUSEHOLD share across the tracts the entity lent in, 0-100. A finer-grained measure than `lowModIncomeTractPct`, which counts whole tracts — not a duplicate of it. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMedianAge":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median age of the population in the tracts the entity lent in, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToCollege":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToSchool":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance from the properties the entity lent on to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToWorship":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMinorityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean non-white share of the population in the tracts the entity lent in, 0-100 (`{gte:50}` = 63,370 originators). `majorityMinorityTractPct` is the per-tract-threshold form of the same question. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPopulation":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean population of the tracts the entity lent in. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPovertyRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of the population below the poverty line in the tracts the entity lent in, 0-100. Pass whole percents — `{gte:0.2}` means 0.2%. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractApplications":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage applications reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractLoanVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean mortgage dollar volume reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractOriginations":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage originations reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgWhiteNonHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean White (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"city":{"$ref":"#/components/schemas/TextFilterValue"},"company":{"$ref":"#/components/schemas/TextFilterValue"},"companyName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy company-name matching is unreliable (partial names silently return 0). Resolve via instantSearch and filter by `company` (exact company NMLS id) instead. Still functional for now."}]},"companyType":{"$ref":"#/components/schemas/BranchCompanyTypeFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Branch address COUNTY: a name (`Travis`, with `state` when ambiguous), a 5-digit FIPS (`48453`) or a dictionary county id; an array matches any. Matches when the branch's geocoded address lies inside the county boundary (no geocode = no match). Unknown county = 400."}]},"difficultDevelopmentAreaCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in HUD-designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"difficultDevelopmentAreaPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in HUD-designated difficult development areas, 0-100 (`{gte:25}` = 93,397 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in distressed-or-underserved tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in distressed-or-underserved nonmetropolitan middle-income tracts, 0-100 (`{gte:25}` = 11,773 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"floodHazardTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in a FEMA special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"floodHazardTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in a FEMA special flood hazard area, 0-100 (`{gte:25}` = 5,212 originators). `predominantFloodZone` gives the specific zone code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"isAuthorized":{"$ref":"#/components/schemas/TextFilterValue"},"licensedState":{"$ref":"#/components/schemas/TextFilterValue"},"loCount":{"$ref":"#/components/schemas/NumericFilterValue"},"loanType":{"$ref":"#/components/schemas/OriginatorLoanTypeFilterValue"},"loansWithCommunityData":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many of the entity's loans in the selected period resolved to a neighborhood — the DENOMINATOR every Community Lending share is taken over. Pair it with a share filter (`{gte:25}`, 60,399 originators) so a 100% share off two loans does not read as a 100% share off two hundred. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans that landed in a low- or moderate-income tract, as a count rather than a share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans that landed in a low- or moderate-income tract under the Community Reinvestment Act, 0-100. `{gte:50}` = 'at least half their book is LMI' (36,977 originators, 655 companies, 648 branches). Pass whole percents — `{gte:0.5}` means half of one percent and matches nearly everyone. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in majority-minority tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in majority-minority tracts, 0-100 (`{gte:50}` = 65,654 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"mode":{"enum":["and","or"],"type":"string"},"msa":{"$ref":"#/components/schemas/BranchMsaFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — matches the branch's FULL name exactly (e.g. `Movement Mortgage, LLC, Providence, RI Branch`); a partial name will not match. Use `namePrefix` for partial names, or `nmlsId` (exact branch NMLS id)."}]},"namePrefix":{"description":"Prefix name search: every word must start a word of the name (\"movement prov\" → Movement Mortgage, LLC, Providence, RI Branch; digits = branch NMLS id). No fuzzy/nickname matching; relevance-ranked unless `sort` is set. Max 100 chars / 6 words (emails, URLs, phones ignored), else 400.","minLength":1,"type":"string"},"nmlsId":{"$ref":"#/components/schemas/TextFilterValue"},"opportunityZoneCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in Opportunity Zone tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"opportunityZonePct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in federally designated Opportunity Zone tracts, 0-100 (`{gte:10}` = 33,520 originators — this is a small-share filter, a 50% floor finds almost nobody). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"predominantFloodZone":{"$ref":"#/components/schemas/EntityPredominantFloodZoneFilterValue"},"predominantIncomeLevel":{"$ref":"#/components/schemas/EntityPredominantIncomeLevelFilterValue"},"producersOnly":{"$ref":"#/components/schemas/BooleanFilterValue"},"region":{"$ref":"#/components/schemas/BranchRegionFilterValue"},"rosterJoined":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the number of loan officers who joined the branch during the selected period — individuals whose sponsorship with the branch began inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction."}]},"rosterLeft":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the number of loan officers who left the branch during the selected period — individuals whose sponsorship with the branch ended inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction."}]},"ruralGradient":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean remoteness of the tracts the entity lent in, on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). This is a code, not a percent — `{gte:7}` selects the deepest-rural books (8,886 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in rural tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in rural tracts, 0-100 (`{gte:50}` = 24,006 originators). `ruralGradient` is the finer, ordinal form. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"state":{"$ref":"#/components/schemas/TextFilterValue"},"teamSize":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the number of loan officers currently attributed to the branch. IMPORTANT — this is a CURRENT headcount snapshot, not a per-period measure. The same value is copied into effectively every period, so subtracting one period's `teamSize` from another's does not measure growth or attrition: it is zero for all but a handful of branches, and on those few it reflects a data artifact rather than a real change. Filtering and sorting on it likewise ignore the selected period. For headcount movement over a window, use `rosterJoined` / `rosterLeft`, which are genuinely per-period."}]},"transactionType":{"$ref":"#/components/schemas/OriginatorTransactionTypeFilterValue"},"units":{"$ref":"#/components/schemas/NumericFilterValue"},"usdaEligibleTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in USDA-eligible tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"usdaEligibleTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in tracts eligible for USDA rural housing programs, 0-100 (`{gte:50}` = 90,392 originators). Broader than `ruralTractPct` — eligibility reaches well past what is classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"volume":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"ZIP code. Canonical key (matches the `zip` field on the response DTO); `zipCode` is a cross-entity alias kept for parity with loans/sales."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"BranchListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"crmList":{"$ref":"#/components/schemas/BranchCrmListFilter"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/BranchFlatFilters"},"lenderFilters":{"items":{"$ref":"#/components/schemas/LenderFilterEntry"},"type":"array"},"lenderMatchMode":{"$ref":"#/components/schemas/LenderMatchMode"},"managerName":{"description":"Branch manager name. Matches ALL the words supplied, fuzzily, against the names of the branch's licensed managers. Always ANDed with the other filters. A name matching more than 5,000 branches is rejected with a 400.","minLength":1,"type":"string"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for branch production metrics (default: last12Months). Applies to `volume`, `units`, `avgLoanAmount`, `rosterJoined`, `rosterLeft` and the loan/transaction-type mix. It does NOT apply to `teamSize`, which is a current snapshot and reads the same on every period."}]},"productMix":{"$ref":"#/components/schemas/BranchProductMixFilter"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/BranchField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"},"transactionMix":{"$ref":"#/components/schemas/BranchTransactionMixFilter"}},"type":"object"},"BranchListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/BranchSummary"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"BranchManager":{"properties":{"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"}},"type":"object"},"BranchMsaFilterValue":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Branch address METRO (MSA / CBSA): 5-digit CBSA code (`12420`) or metro name (`Austin Metro`); an array matches any. The address point inside any member county. Unknown/ambiguous = 400 naming candidates."},"BranchProductMixFilter":{"description":"Loan-product share / volume bands for the selected period, ANDed: `[{product:\"fha\", minShare:30}]` = FHA is at least 30% of the branch's period volume; `[{product:\"va\", volume:{gte:5000000}}]` = at least $5M of VA. `products` lets ANY of several types satisfy one entry. Whole-book figures across all markets.","items":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100 percent. No bucket = 0% (passes).","maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","maximum":100,"minimum":0,"type":"number"},"product":{"description":"The loan product. Send this OR `products`, not both.","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},"products":{"description":"Several products, ANY of which may satisfy the bounds on its own (each type's share is read separately, never summed): `{products:[\"fha\",\"va\",\"usda\"], minShare:30}` = FHA, VA or USDA is on its own at least 30% of the book. Send this OR `product`.","items":{"enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},"maxItems":10,"minItems":1,"type":"array"},"volume":{"additionalProperties":false,"description":"Dollar volume of THIS type in the period, `{gte, lte}` — e.g. `{gte: 5000000}` = at least $5M of FHA. Evaluated inside the same type bucket as the share bounds; a branch with no loans of the type does not match.","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"type":"object"},"maxItems":10,"minItems":1,"type":"array"},"BranchRegionFilterValue":{"anyOf":[{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},{"items":{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Branch address CENSUS REGION / DIVISION (`<region>-division-<n>`, 1–9) — branches in ANY state of it. An array matches any."},"BranchRosterContact":{"nullable":true,"properties":{"cellPhone":{"nullable":true,"type":"string"},"employerAddress":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerCompany":{"nullable":true,"type":"string"},"employerCompanyId":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"employerType":{"nullable":true,"type":"string"},"employerWebsite":{"nullable":true,"type":"string"},"employerZip":{"nullable":true,"type":"string"},"facebook":{"nullable":true,"type":"string"},"linkedin":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"officePhoneExt":{"nullable":true,"type":"string"},"personalEmail":{"nullable":true,"type":"string"},"twitter":{"nullable":true,"type":"string"},"website":{"nullable":true,"type":"string"},"workEmail":{"nullable":true,"type":"string"}},"type":"object"},"BranchRosterMember":{"properties":{"city":{"nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"description":"Current employer (active sponsorship first, then active registration).","nullable":true,"type":"string"},"companyStartDate":{"nullable":true,"type":"string"},"contact":{"$ref":"#/components/schemas/BranchRosterContact"},"firstName":{"nullable":true,"type":"string"},"id":{"type":"string"},"isBranchManager":{"description":"Manages ANY branch.","nullable":true,"type":"boolean"},"isWorking":{"nullable":true,"type":"boolean"},"lastName":{"nullable":true,"type":"string"},"managesThisBranch":{"description":"Listed as a manager of THIS branch.","type":"boolean"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"tenureMonths":{"description":"Whole months at the current company, as of the weekly refresh.","nullable":true,"type":"number"},"yearsInIndustry":{"nullable":true,"type":"number"}},"required":["id","managesThisBranch"],"type":"object"},"BranchRosterRequest":{"additionalProperties":false,"properties":{"flatFilters":{"additionalProperties":false,"properties":{"isBranchManager":{"$ref":"#/components/schemas/BooleanFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan officer name. Matches ALL the words supplied, fuzzily. Scoped to this branch's roster."}]},"tenureMonths":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Whole months at the loan officer's current company."}]},"yearsInIndustry":{"$ref":"#/components/schemas/NumericFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/BranchRosterSortField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"BranchRosterResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/BranchRosterMember"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"BranchRosterSortField":{"enum":["name","tenureMonths","yearsInIndustry","state","city"],"type":"string"},"BranchSegment":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`. Time-series only: `titleCompany` groups on the title company named on the deed, with spellings of one company merged per bucket (`label` = most-used spelling across the response, `id` = normalized name — match on `id`) and \"none available\"-style placeholders excluded.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","titleCompany"],"type":"string"},"BranchSlice":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming"],"type":"string"},"BranchSummary":{"properties":{"avgLoanAmount":{"nullable":true,"type":"number"},"city":{"nullable":true,"type":"string"},"communityLending":{"$ref":"#/components/schemas/EntityCommunityLending"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"companyType":{"nullable":true,"type":"string"},"coordinates":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"id":{"type":"string"},"isAuthorized":{"nullable":true,"type":"boolean"},"licensedStates":{"description":"Licensed states (populated on the detail route only)","items":{"type":"string"},"nullable":true,"type":"array"},"loCount":{"nullable":true,"type":"number"},"managerCount":{"nullable":true,"type":"number"},"managers":{"description":"Branch managers. List rows carry NMLS ids only; the detail route adds manager names.","items":{"$ref":"#/components/schemas/BranchManager"},"nullable":true,"type":"array"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"purchasePct":{"nullable":true,"type":"number"},"purchaseShare":{"description":"Purchase share (0–100) of the period's loan COUNT — what `sort: purchaseShare` orders by. `null` = none (sorts as 0).","nullable":true,"type":"number"},"refinancePct":{"nullable":true,"type":"number"},"refinanceShare":{"description":"Refinance share (0–100) of the period's loan COUNT — what `sort: refinanceShare` orders by. `null` = none (sorts as 0).","nullable":true,"type":"number"},"rosterCount":{"description":"Loan officers on this branch's CURRENT licensing roster: registered to this branch location AND holding an active sponsorship or registration. A current snapshot (refreshed weekly), not period-scoped. Null when the roster is not on file. List rows also carry manager NAMES from the same lookup. See POST /v1/branches/{nmlsId}/roster for the people.","nullable":true,"type":"number"},"rosterJoined":{"description":"Loan officers who joined the branch during the selected period — individuals whose sponsorship with the branch began inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction.","nullable":true,"type":"number"},"rosterLeft":{"description":"Loan officers who left the branch during the selected period — individuals whose sponsorship with the branch ended inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"teamSize":{"description":"Loan officers currently attributed to this branch. IMPORTANT — this is a CURRENT headcount snapshot, not a per-period measure. The same value is copied into effectively every period, so subtracting one period's `teamSize` from another's does not measure growth or attrition: it is zero for all but a handful of branches, and on those few it reflects a data artifact rather than a real change. Filtering and sorting on it likewise ignore the selected period. For headcount movement over a window, use `rosterJoined` / `rosterLeft`, which are genuinely per-period.","nullable":true,"type":"number"},"tradenames":{"items":{"type":"string"},"nullable":true,"type":"array"},"units":{"description":"Branch-level loan units for the selected period","nullable":true,"type":"number"},"volume":{"description":"Branch-level loan volume for the selected period","nullable":true,"type":"number"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"BranchSummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"nmlsId":{"description":"Branch NMLS ID","minLength":1,"type":"string"},"period":{"$ref":"#/components/schemas/Period"}},"required":["nmlsId"],"type":"object"},"BranchTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"nmlsId":{"description":"Branch NMLS ID","minLength":1,"type":"string"},"period":{"$ref":"#/components/schemas/Period"},"segment":{"$ref":"#/components/schemas/BranchSegment"}},"required":["nmlsId"],"type":"object"},"BranchTransactionMixFilter":{"description":"Transaction-type share bands for the selected period, ANDed: `[{transactionType:\"purchase\", minShare:60}]` = purchases are at least 60% of the branch's period volume.","items":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100 percent. No bucket = 0% (passes).","maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","maximum":100,"minimum":0,"type":"number"},"transactionType":{"enum":["purchase","refinance","construction","equity","UNKNOWN"],"type":"string"},"volume":{"additionalProperties":false,"description":"Dollar volume of THIS type in the period, `{gte, lte}` — e.g. `{gte: 5000000}` = at least $5M of FHA. Evaluated inside the same type bucket as the share bounds; a branch with no loans of the type does not match.","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"required":["transactionType"],"type":"object"},"maxItems":10,"minItems":1,"type":"array"},"BreakdownItem":{"properties":{"company":{"description":"Agent and company `originators` only: the LO's employer per NMLS licensing (on agents, as of the agent profile's last refresh) — not necessarily the company on the loans, and it can trail a very recent move (`GET /v1/originators/{nmlsId}` is always current). Absent on every other breakdown; `null` leaves when no sponsorship was on file.","properties":{"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"}},"required":["name","nmlsId"],"type":"object"},"excluded":{"description":"How many of this bucket's documents the volume guard excluded — documents that carry the money field but whose value is an out-of-range fill. Compare against `units` to see what share of the bucket `volume` was actually computed over: a bucket can show many units and still sum a small fraction of them. Absent when the entity's money column is unguarded (the sales-backed agent breakdowns), where nothing can be excluded.","type":"number"},"id":{"description":"Machine value behind `label` for breakdowns whose bucket key is an id rather than a name (`lenders`, where `label` is the dictionary display name and `id` is the normalized lender key — pass `id`, not `label`, back as a `lender` filter value; agent `originators`, where `id` is the LO's NMLS id; `originatorAgents`, where `id` is the agent id most often recorded under that name; `titleCompanies`, where `id` is the normalized name the spellings were merged under). Absent on name-keyed breakdowns, where `label` is already the machine value.","type":"string"},"label":{"description":"Bucket label/key","type":"string"},"name":{"description":"Human-readable name for the bucket when `label` is an entity id (e.g. a broker NMLS id resolved to its company name). Absent when unresolved or not an id-keyed breakdown.","type":"string"},"office":{"description":"`originatorAgents` only: the agent's brokerage office — the same office `GET /v1/agents/{id}` and the agents list report as `office`, picked from the offices on the agent's profile by recency and frequency, so it can trail a very recent move and is not necessarily the office on these loans. `id` is the office id (pass it to `GET /v1/offices/{id}`); `null` when the office has none. `null` when the agent has no named office on file; absent on rows without an agent `id` and on every other breakdown.","nullable":true,"properties":{"id":{"nullable":true,"type":"string"},"name":{"type":"string"}},"required":["name","id"],"type":"object"},"pctUnits":{"description":"Percentage of total units","type":"number"},"pctVolume":{"description":"Percentage of total volume","type":"number"},"units":{"description":"Number of transactions","type":"number"},"volume":{"description":"Total dollar volume","type":"number"}},"required":["label","units","volume","pctUnits","pctVolume"],"type":"object"},"BreakdownRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"BreakdownResponse":{"properties":{"cursor":{"description":"Opaque cursor for the next page; absent when this is the last page.","type":"string"},"data":{"items":{"$ref":"#/components/schemas/BreakdownItem"},"type":"array"},"total":{"description":"Number of buckets returned","type":"number"},"totals":{"description":"Grand totals across all data","properties":{"excluded":{"description":"Documents the volume guard excluded across the whole scope — the grand-total counterpart of a bucket's `excluded`, and the same figure `/analytics/summary` reports as `current.excluded.volume` for an equivalent query. Absent when the money column is unguarded.","type":"number"},"units":{"type":"number"},"volume":{"type":"number"},"volumePlausible":{"description":"False when `volume` is a pre-summed figure this API can show is impossible — e.g. an average sale price per unit far outside any real market, or buyer-side and seller-side averages that contradict each other. `pctVolume` on every item is that figure's quotient, so when this is false those percentages are unusable and should not be rendered as shares. A MAGNITUDE check only: true means \"not obviously impossible\", NOT \"verified\". Absent on surfaces that aggregate documents live, where no such figure is read.","type":"boolean"}},"required":["units","volume"],"type":"object"},"truncated":{"description":"True when more buckets exist beyond this page. Page through with `cursor`, or sort by `label` to enumerate the full key space.","type":"boolean"}},"required":["data","total"],"type":"object"},"BreakdownSort":{"items":{"properties":{"field":{"description":"One of (case-insensitive): volume, units, label, pctVolume, pctUnits, name","enum":["volume","units","label","pctVolume","pctUnits","name"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"},"BulkDeliveryBilling":{"description":"`credits` = billed at 1 credit per delivered row. `none` = not billed (deliveries submitted from the ModelMatch web app).","enum":["credits","none"],"type":"string"},"BulkDeliveryColumn":{"additionalProperties":false,"properties":{"field":{"anyOf":[{"minLength":1,"type":"string"},{"items":{"minLength":1,"type":"string"},"maxItems":10,"minItems":1,"type":"array"}],"description":"The response DTO field this column reads — the same names `fields` takes, dotted into nested objects (`contact.linkedin`) — or a list of them, taking the first non-empty value (`[\"contact.personalEmail\", \"contact.workEmail\", \"email\"]`).","example":"volume"},"format":{"description":"`currency`, `number` and `percentWhole` round the value to a whole number (in both `csv` and `xlsx`) and, in `xlsx`, display it as `$1,234,567`, `1,234` or `62%`. `percentWhole` expects a value that is already 0–100 (it is written as `62` in `csv`; in `xlsx` the cell holds `0.62` under the standard percent format, so it displays `62%` in every spreadsheet app and calculates as a percent). `text` writes an `xlsx` text cell. `titleCase` (`dina verteramo` → `Dina Verteramo`), `lowercase`, and `phone` (US 10-digit numbers as `(469) 907-7475`; anything else as stored) reshape the text and write a text cell. Omit for the value as-is.","enum":["currency","number","percentWhole","text","titleCase","lowercase","phone"],"type":"string"},"label":{"description":"Header for the column.","example":"Total Volume","maxLength":255,"minLength":1,"type":"string"},"valueMap":{"additionalProperties":{"type":"string"},"description":"Display text per value, keyed by the value as a string (`{ \"true\": \"Branch Manager\", \"false\": \"Originator\" }`, `{ \"BANK\": \"Bank\" }`). The key `\"null\"` matches an empty value. Unmatched values are written unchanged.","type":"object"}},"required":["field","label"],"type":"object"},"BulkDeliveryColumnsError":{"description":"The `columns` request was refused: `columns_with_fields`, `columns_with_destination`, `columns_format_unsupported` (needs `csv` or `xlsx`), or `unknown_column_field`.","properties":{"error":{"enum":["columns_with_fields","columns_with_destination","columns_format_unsupported","unknown_column_field"],"type":"string"},"message":{"type":"string"}},"required":["error","message"],"type":"object"},"BulkDeliveryDestination":{"description":"Where the finished delivery goes. Omit for the default — a file you download from the status endpoint. `push-target`: when the job completes, the rows are handed to the named push target, which sends them to its configured HTTPS destination using its own field mapping and signing. The target is checked at submit (it must exist, be enabled, accept this entity, and be usable by you on your plan) — a failed check rejects the submit with the push target's error `code`. `format` is ignored (the handoff is always gzipped NDJSON), and when the target's mapping reads only some fields, only those fields (plus `id`) are delivered. Row limits, entitlements, `limit`, and billing (1 credit / row) are unchanged, except that deliveries submitted from the ModelMatch web app are not billed. Poll the job for `pushBatchId`; a handoff that cannot be completed fails the job with error `push_handoff_failed` and is not billed.","properties":{"targetId":{"description":"Id of a push target configured on the active workspace (or your own member push targets).","minLength":1,"type":"string"},"type":{"enum":["push-target"],"type":"string"}},"required":["type","targetId"],"type":"object"},"BulkDeliveryForbidden":{"properties":{"entitlementKey":{"description":"Entitlement that would lift the cap. Contact support to request a limit increase.","type":"string"},"error":{"enum":["entitlement_missing"],"type":"string"},"estimatedTotal":{"description":"Rows the query matched — what pushed it over `maxRows`.","minimum":0,"type":"integer"},"maxRows":{"description":"Row ceiling that applied to this request, i.e. the deliverable limit without the entitlement.","exclusiveMinimum":true,"minimum":0,"type":"integer"},"message":{"type":"string"}},"required":["error","entitlementKey","estimatedTotal","maxRows","message"],"type":"object"},"BulkDeliveryFormat":{"description":"Output file format for the delivered dataset. Every format contains the same rows — the entity's list/summary DTO (e.g. `LoanSummary`), one record per row. `ndjson`: gzipped newline-delimited JSON (`application/x-ndjson`, `.ndjson.gz`). `json`: a single JSON array (`application/json`, `.json`). `csv`: RFC 4180 (`text/csv`, `.csv`). `parquet`: typed columnar Apache Parquet — scalar fields keep their DTO types, nested fields are JSON-encoded strings (`application/vnd.apache.parquet`, `.parquet`). `xlsx`: a single-sheet Excel workbook with a bold, frozen header row — numbers are numeric cells, everything else (ids, zips, phones) text cells (`.xlsx`). Pair with `columns` for labelled headers and number formats. Required on submit unless `destination` is a push target, which always delivers gzipped NDJSON (a missing `format` on a file delivery is a 400 `format_required`).","enum":["ndjson","json","csv","parquet","xlsx"],"example":"parquet","type":"string"},"BulkDeliveryInsufficientCredits":{"properties":{"balance":{"description":"Remaining credit balance the charge saw.","type":"number"},"cost":{"description":"Credits the request asked for.","type":"number"},"error":{"enum":["payment_required"],"type":"string"},"message":{"description":"Human-readable explanation of the decline.","type":"string"},"reason":{"description":"Why the charge was declined, when known: `out_of_credits` (balance empty) vs. `limit_reached` (a spend cap was hit).","enum":["out_of_credits","limit_reached"],"type":"string"}},"required":["error","balance","cost"],"type":"object"},"BulkDeliveryInsufficientScope":{"properties":{"error":{"enum":["insufficient_scope"],"type":"string"},"message":{"type":"string"},"requiredScope":{"enum":["push-targets:send"],"type":"string"}},"required":["error","requiredScope","message"],"type":"object"},"BulkDeliveryPreflightExceeded":{"properties":{"error":{"enum":["delivery_exceeds_max_rows"],"type":"string"},"estimatedTotal":{"minimum":0,"type":"integer"},"maxRows":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"required":["error","estimatedTotal","maxRows"],"type":"object"},"BulkDeliveryPushTargetError":{"description":"The push-target destination was refused: `TARGET_NOT_FOUND` (404), `FORBIDDEN` (403), `PLAN_REQUIRED` (402), `TARGET_DISABLED` (409), `ENTITY_MISMATCH` (400).","properties":{"code":{"enum":["TARGET_NOT_FOUND","FORBIDDEN","PLAN_REQUIRED","TARGET_DISABLED","ENTITY_MISMATCH"],"type":"string"},"error":{"enum":["TARGET_NOT_FOUND","FORBIDDEN","PLAN_REQUIRED","TARGET_DISABLED","ENTITY_MISMATCH"],"type":"string"},"message":{"type":"string"}},"required":["error","code","message"],"type":"object"},"BulkDeliveryStatusResponse":{"properties":{"billing":{"$ref":"#/components/schemas/BulkDeliveryBilling"},"billingReason":{"description":"Why `billing` is `none`: `first_party_push_target` = a push-target delivery submitted from the ModelMatch web app; `first_party_download` = a file delivery submitted from the ModelMatch web app.","enum":["first_party_push_target","first_party_download"],"type":"string"},"bytes":{"minimum":0,"type":"integer"},"chargedCount":{"description":"Delivered-row count that was billed.","minimum":0,"type":"integer"},"completedAt":{"type":"string"},"creditLedgerId":{"description":"Credit-ledger entry id for this job's debit. Absent if billing didn't land.","type":"string"},"creditsCharged":{"description":"Credits debited for this job (1 credit / row). Absent until the job completes; absent on a failed billing call.","minimum":0,"type":"number"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"downloadUrl":{"description":"Stable, shareable download link for the completed dataset. Forces a file download (with a friendly filename) and stays valid for 7 days after completion. Present once `status` is `completed`. This is the link to hand to a user or send by email.","type":"string"},"entityType":{"type":"string"},"error":{"description":"Why the job failed. `push_handoff_failed` = the rows were exported but could not be handed to the push target (not billed).","type":"string"},"estimatedTotal":{"minimum":0,"type":"integer"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"jobId":{"type":"string"},"processed":{"minimum":0,"type":"integer"},"pushBatchId":{"description":"Push-target deliveries only: the batch the push target is sending, set once the completed file was handed off. Per-record send progress is tracked by the push target, not this job.","type":"string"},"resultsUrl":{"description":"Direct download URL for the completed dataset. Long-lived per request but changes on each poll; prefer `downloadUrl` for a stable link to share.","type":"string"},"startedAt":{"type":"string"},"status":{"enum":["queued","running","completed","failed","cancelled"],"type":"string"}},"required":["jobId","status"],"type":"object"},"BulkDeliverySubmitResponse":{"properties":{"billing":{"$ref":"#/components/schemas/BulkDeliveryBilling"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"entityType":{"type":"string"},"estimatedTotal":{"minimum":0,"type":"integer"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"jobId":{"type":"string"},"maxRows":{"exclusiveMinimum":true,"minimum":0,"type":"integer"},"status":{"enum":["queued"],"type":"string"}},"required":["jobId","status","entityType","format","estimatedTotal","maxRows"],"type":"object"},"CacheScope":{"description":"Which row kind(s) to scan. Default `both`.","enum":["internal","member","both"],"type":"string"},"ChartBucket":{"properties":{"count":{"description":"How many documents this bucket was built from — the denominator behind `value`, published whatever the measure. It is the sample size of an average, the transaction count behind a `volume` sum, and (for `measure: \"units\"`) `value` itself. Present on every bucket. Distinct from `excluded`, which reports how many of these documents a guarded measure's sentinel filter then dropped: a bucket can look well-populated here and still average over far fewer.","type":"number"},"excluded":{"description":"How many of this bucket's documents the measure's sentinel guard excluded — documents that carry the field but whose value is an out-of-range fill. Additive and optional: absent when the measure is unguarded (a document count, or a field with no fill values). Present per BUCKET because exclusion is not uniform — one period or slice can be almost entirely fill values while its neighbors are clean, and a single response-level total would hide exactly that.","type":"number"},"id":{"description":"Machine value behind `label` when the bucket key is not itself the label. `lender`: `label` is the dictionary display name and `id` the normalized lender key — pass `id`, not `label`, back as a `lender` filter value. `conforming`: `label` is `conforming` / `nonConforming` and `id` the raw `true` / `false` flag. `titleCompany` (time-series segment): `label` is the most-used spelling and `id` the normalized name every spelling was merged under — match segments across buckets on `id`. Absent on slices whose `label` is already the machine value.","type":"string"},"label":{"type":"string"},"segments":{"description":"Present only when the request named a `segment`: this bucket broken down by that second dimension, ranked by the same `measure` and capped at 25 per bucket (the rest is counted in `segmentsOmittedCount`). Documents with no value for the segment are not grouped and appear nowhere here, so segment `count`s sum to at most the bucket's `count`.","items":{"$ref":"#/components/schemas/ChartSegment"},"type":"array"},"segmentsOmittedCount":{"description":"Present only with `segments`: documents in this bucket whose segment value fell past the 25-per-bucket cap. A document COUNT, never a dollar figure. `0` means `segments` is the complete breakdown of every document that carries a segment value.","type":"number"},"unattributed":{"description":"Present and `true` on at most one bucket, which is NOT a real category: it collects the documents this breakdown could not attribute to any value of the slice, and its `label` (`\"(unknown)\"`) is prose, not an identifier. Filter on THIS field, never on the label — a consumer plotting a map or joining the label to a real code must drop this row. It is always the LAST element of `data`, appended after ranking rather than placed by value, so it is the one bucket that does not obey the ordering `measure` describes. It exists so the bars account for the same population the summary reports: a document whose slice field holds no indexed term is absent from a terms breakdown entirely rather than forming a small bucket, so without it a chart silently omits part of its own corpus. That reconciliation is exact for `units`; on an average it is not, because buckets under the five-document floor are dropped and a slice with more than 200 distinct values still truncates — neither loss is collected in this row (the truncated tail is reported response-wide as `omittedCount`; the floor is reported nowhere). Absent when there is nothing unattributed, never `false` and never a zero-valued row.","enum":[true],"type":"boolean"},"value":{"type":"number"}},"required":["label","value","count"],"type":"object"},"ChartMeasure":{"default":"units","description":"Which metric each bar reports, AND what the bars are ranked by — the list is ordered by the measure you ask for, descending. Defaults to `units`, so an unqualified \"top originators\" means the busiest; pass `volume` for the biggest by dollars, or an average to rank by that average. Two things to know about the averages specifically. Buckets built from fewer than 5 documents are dropped from an average chart entirely, because a mean says nothing about how many transactions produced it and a single-transaction bucket would otherwise outrank real ones; no floor is applied to `units` or `volume`, where a lone large transaction is a legitimate top bar. And ranking a bucket list by a sub-aggregated average is approximate in the search engine — each shard contributes its own local top-N before they are merged — so treat the ordering of an average chart as indicative near the boundary rather than exact. Every bucket publishes its own `count`, so the sample size behind a value is never implicit.","enum":["volume","units","avgSalePrice","avgListPrice"],"type":"string"},"ChartResponse":{"properties":{"completeness":{"$ref":"#/components/schemas/AnalyticsCompleteness"},"data":{"items":{"$ref":"#/components/schemas/ChartBucket"},"type":"array"},"measure":{"type":"string"},"nextCursor":{"description":"Paged party slices only (a chart request that passed `size` or `after` with `slice` `originator` / `broker` / `loanCompany`). Opaque cursor for the next page of the ranking — send it back as `after` with the same body. Absent on the last page.","type":"string"},"omittedCount":{"description":"How many documents fell outside the bars — the size of the dropped tail, not its value. A chart groups by a capped number of distinct values, so a slice with more of them than the cap returns its largest groups and drops the rest; `zip`, `city`, `lender` and `originator` are the ones that reach it. It is the documents in the groups past the size cap, and only those: documents excluded from the slice by its empty-value filter, or carrying no value for it at all, are never grouped and are not counted here either. Where the response carries an `unattributed` row that row collects them; elsewhere a small residual against `/analytics/summary` can remain on `city`, `lender`, `originator` and similar, so bars plus this count reconcile with the summary's population exactly only on a slice with no such documents. `0` means the bars ARE the complete set, and the field is absent only where the grouping cannot truncate at all — so `0` and missing are different claims. Unlike a breakdown there is no next page to fetch: narrow the filters or pick a coarser slice. It is a DOCUMENT count and never a dollar or an average — the aggregation reports how many rows it left out, not what they were worth, so a truncated volume chart cannot be completed from this figure. One exception it does not cover: the average measures drop buckets thinner than a minimum sample size, and those are not counted here — compare against the summary when a mean matters.","type":"number"},"segment":{"description":"The second dimension echoed from the request, or `null` for a one-dimensional chart (then no bucket carries `segments`).","nullable":true,"type":"string"},"slice":{"type":"string"},"total":{"description":"Paged party slices only. Distinct bucket keys (e.g. originators) in the filtered population — what a consumer paginates against. A cardinality ESTIMATE (see `totalApproximate`): near-exact below 40,000, approximate above. On an average measure it can exceed the ranked buckets, which drop keys under the 5-document floor. Use `nextCursor`, not `total`, to decide whether another page exists.","type":"integer"},"totalApproximate":{"description":"Present (always `true`) alongside `total`: the total is a cardinality estimate, not an exact count.","type":"boolean"}},"required":["measure","slice","segment","data"],"type":"object"},"ChartSegment":{"properties":{"count":{"description":"Documents in this segment of the parent bucket — the denominator behind `value`, whatever the measure.","type":"number"},"id":{"description":"Machine value behind `label` when the bucket key is not itself the label. `lender`: `label` is the dictionary display name and `id` the normalized lender key — pass `id`, not `label`, back as a `lender` filter value. `conforming`: `label` is `conforming` / `nonConforming` and `id` the raw `true` / `false` flag. `titleCompany` (time-series segment): `label` is the most-used spelling and `id` the normalized name every spelling was merged under — match segments across buckets on `id`. Absent on slices whose `label` is already the machine value.","type":"string"},"label":{"type":"string"},"value":{"description":"The requested `measure` over the documents in BOTH this segment and its parent bucket.","type":"number"}},"required":["label","value","count"],"type":"object"},"ClearAlertHistoryRequest":{"properties":{"detectors":{"description":"Limit the wipe to these alert types; all history when omitted.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"ClearAlertHistoryResponse":{"properties":{"data":{"properties":{"dedupDeleted":{"type":"integer"},"digestDeleted":{"type":"integer"},"logDeleted":{"type":"integer"}},"required":["dedupDeleted","logDeleted","digestDeleted"],"type":"object"}},"required":["data"],"type":"object"},"CompanyBranch":{"properties":{"branchNmlsId":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"id":{"type":"string"},"isAuthorized":{"nullable":true,"type":"boolean"},"licensedStates":{"items":{"type":"string"},"nullable":true,"type":"array"},"location":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"managers":{"nullable":true},"name":{"nullable":true,"type":"string"},"postalCode":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"tradeNames":{"items":{"type":"string"},"nullable":true,"type":"array"}},"required":["id"],"type":"object"},"CompanyBranchesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Branch office name. Matches ALL the words supplied, fuzzily — so \"Rocket Mortgage\" does not return every branch with \"mortgage\" in its name (39.9% of the index). Scoped to this company's branches."}]},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"sort":{"items":{"properties":{"field":{"enum":["city","state","zipCode","county","transactionType","loanType","conforming","mortgageAmount","mortgageDate","broker","loanCompany","lender","borrowerStatus","salePrice","saleDate","originator","originatorName","interestRate","equity","homeValue","ltvAtOrigination","currentBalance"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"CompanyBranchesResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/CompanyBranch"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"CompanyBreakdownRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"roleScope":{"$ref":"#/components/schemas/CompanyRoleScope"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"CompanyChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"},"roleScope":{"$ref":"#/components/schemas/CompanyRoleScope"},"segment":{"allOf":[{"$ref":"#/components/schemas/CompanySlice"},{"description":"Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."}]},"slice":{"$ref":"#/components/schemas/CompanySlice"}},"required":["slice"],"type":"object"},"CompanyCrmListFilter":{"additionalProperties":false,"description":"Scope the result to the caller's CRM. Resolved against the caller's ACTIVE WORKSPACE at query time — list membership is read server-side, so the request never carries member ids. Only company members count; people, branches, offices and manual (unlinked) records on the same list are ignored. `mode: \"in\"` with no matching members returns an empty page (not an unfiltered one). Errors: 400 `crm_list_requires_workspace` when the caller has no active workspace (API-key / OAuth callers must select an organization), 403 / 404 when a named list is not visible to the caller or does not exist, and 400 `crm_list_too_large` when the selected lists hold more than 50,000 companies in total — narrow the selection rather than get a silently partial answer.","properties":{"lists":{"anyOf":[{"description":"Every list in the caller's workspace that the caller can see (own, org-wide, or shared with them) and that holds this kind of record — People lists for originators and agents, Company lists for companies.","enum":["any"],"type":"string"},{"description":"Specific CRM list ids (1–50).","items":{"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"}],"description":"Which lists: `\"any\"` for every Company list the caller can see, or an array of list ids. Membership is the UNION across the selected lists."},"mode":{"description":"`in` — only companies who are a member of the selected list(s). `notIn` — exclude every company who is a member of the selected list(s); everyone else passes, including companies on none of your lists.","enum":["in","notIn"],"type":"string"}},"required":["mode","lists"],"type":"object"},"CompanyDetail":{"allOf":[{"$ref":"#/components/schemas/CompanySummary"},{"properties":{"builders":{"description":"Top home builders (up to 10) behind the company's period production — the builder of each sold property, ranked by loan count. Units only (no volume is recorded). Empty when none.","items":{"properties":{"name":{"type":"string"},"units":{"type":"number"}},"required":["name","units"],"type":"object"},"type":"array"},"communityLending":{"$ref":"#/components/schemas/EntityCommunityLending"},"registration":{"$ref":"#/components/schemas/CompanyRegistration"}},"type":"object"}]},"CompanyDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/CompanyDetail"}},"required":["data"],"type":"object"},"CompanyEarlyExitsResponse":{"properties":{"data":{"description":"Present only with `month`: that cohort's rows.","items":{"$ref":"#/components/schemas/EarlyExitRow"},"type":"array"},"monthlyCohorts":{"items":{"properties":{"attritionRate":{"type":"number"},"earlyDepartures":{"type":"number"},"isIncompleteCohort":{"description":"The month ends inside the trailing `withinDays`, so the cohort has not had the full horizon to exit.","type":"boolean"},"month":{"type":"string"},"newHires":{"type":"number"},"recentStarts":{"type":"number"}},"required":["month","newHires","earlyDepartures","recentStarts","attritionRate","isIncompleteCohort"],"type":"object"},"type":"array"},"summary":{"properties":{"avgDaysBeforeExit":{"type":"number"},"earlyAttritionRate":{"description":"0–100.","type":"number"},"riskLevel":{"enum":["low_sample","critical_attention","attention_needed","review_recommended","worth_reviewing","worth_monitoring","steady_retention","strong_retention","exceptional_retention"],"type":"string"},"totalEarlyDepartures":{"type":"number"},"totalNewHires":{"type":"number"}},"required":["totalNewHires","totalEarlyDepartures","earlyAttritionRate","avgDaysBeforeExit","riskLevel"],"type":"object"},"truncated":{"description":"`true` when the company has more than 100,000 loan officers in scope and only the first 100,000 (by NMLS ID) were counted. `false` means every figure covers the full population.","type":"boolean"},"window":{"$ref":"#/components/schemas/EmploymentWindow"},"withinDays":{"type":"number"}},"required":["window","withinDays","summary","monthlyCohorts","truncated"],"type":"object"},"CompanyEmployeeStatsResponse":{"properties":{"arrived":{"description":"Hires in the window. A hire is a loan officer whose earliest employment record at this company still relevant to the window (open, or ended on/after the window start) starts inside it — so someone who fully left and came back inside the window counts, and an existing employee who adds a state license does not.","properties":{"avgVolume":{"type":"number"},"count":{"type":"number"},"shareOfRoster":{"description":"Hires as a share (0–100) of the current roster.","type":"number"},"topName":{"nullable":true,"type":"string"},"topNmlsId":{"nullable":true,"type":"string"},"topVolume":{"type":"number"},"totalUnits":{"type":"number"},"totalVolume":{"type":"number"}},"required":["count","totalVolume","totalUnits","avgVolume","topNmlsId","topName","topVolume","shareOfRoster"],"type":"object"},"current":{"description":"The current roster (open employment record today). Production is each loan officer's `period` production across ALL employers.","properties":{"avgUnitsPerLO":{"type":"number"},"avgVolumePerLO":{"type":"number"},"nonProducingCount":{"type":"number"},"producingCount":{"type":"number"},"tiers":{"description":"The current roster bucketed by units closed in `period`: none (0), low (1–24), mid (25–99), top (100+).","items":{"$ref":"#/components/schemas/RosterProductionTier"},"type":"array"},"topConcentrationPct":{"description":"Share (0–100) of roster volume produced by its top 10%.","type":"number"},"totalCount":{"type":"number"},"totalUnits":{"type":"number"},"totalVolume":{"type":"number"}},"required":["totalCount","producingCount","nonProducingCount","totalVolume","totalUnits","avgVolumePerLO","avgUnitsPerLO","topConcentrationPct","tiers"],"type":"object"},"departed":{"description":"Exits in the window. An exit is a loan officer whose latest record at this company ended inside the window and who holds NO open record there — a complete departure.","properties":{"avgVolume":{"type":"number"},"count":{"type":"number"},"topName":{"nullable":true,"type":"string"},"topNmlsId":{"nullable":true,"type":"string"},"topVolume":{"type":"number"},"totalUnits":{"type":"number"},"totalVolume":{"type":"number"}},"required":["count","totalVolume","totalUnits","avgVolume","topNmlsId","topName","topVolume"],"type":"object"},"truncated":{"description":"`true` when the company has more than 100,000 loan officers in scope and only the first 100,000 (by NMLS ID) were counted. `false` means every figure covers the full population.","type":"boolean"},"window":{"$ref":"#/components/schemas/EmploymentWindow"}},"required":["window","current","arrived","departed","truncated"],"type":"object"},"CompanyEmploymentResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CompanyEmploymentRow"},"type":"array"},"limit":{"type":"number"},"page":{"type":"number"},"total":{"type":"number"},"totalPages":{"type":"number"},"truncated":{"description":"`true` when the company has more than 100,000 loan officers in scope and only the first 100,000 (by NMLS ID) were counted. `false` means every figure covers the full population.","type":"boolean"},"window":{"$ref":"#/components/schemas/EmploymentWindow"}},"required":["data","total","page","limit","totalPages","window","truncated"],"type":"object"},"CompanyEmploymentRow":{"properties":{"branchLocation":{"$ref":"#/components/schemas/EmploymentBranchLocation"},"city":{"nullable":true,"type":"string"},"companyUnits":{"description":"Loans the loan officer closed while employed here, recorded inside the window. 0 when none.","type":"number"},"companyVolume":{"description":"Dollar volume the loan officer closed WHILE EMPLOYED HERE (employer at time of loan = this company), recorded inside the window. 0 when none.","type":"number"},"contact":{"$ref":"#/components/schemas/EmploymentContact"},"currentCompanyName":{"nullable":true,"type":"string"},"currentCompanyNmlsId":{"nullable":true,"type":"string"},"entered":{"description":"Hired inside the window.","type":"boolean"},"exitDate":{"description":"Complete-departure date; null while still employed.","nullable":true,"type":"string"},"exited":{"description":"Completely departed inside the window.","type":"boolean"},"isActive":{"description":"Holds an open employment record at this company (under `asOf`: a record covering that date).","type":"boolean"},"isBranchManager":{"nullable":true,"type":"boolean"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"},"previousEmployer":{"description":"The employer whose record ended most recently on or before this loan officer's start here (the same rule `talent-flow` attributes hires by). Both null when none is on file.","properties":{"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"}},"required":["nmlsId","name"],"type":"object"},"startDate":{"description":"For current employees, the start of the earliest OPEN record here (current tenure); otherwise the earliest record relevant to the window.","nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"units":{"nullable":true,"type":"number"},"volume":{"description":"The loan officer's production in `period`, across ALL employers (not only this company). Null when they have no production profile.","nullable":true,"type":"number"}},"required":["nmlsId","name","isActive","entered","exited","startDate","exitDate","isBranchManager","branchLocation","currentCompanyNmlsId","currentCompanyName","city","state","volume","units","companyVolume","companyUnits","previousEmployer","contact"],"type":"object"},"CompanyFootprintFilter":{"additionalProperties":false,"properties":{"avgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Mean loan size funded by this lender."}]},"dimension":{"description":"Which footprint to address. Only `lender` is available for companies — it is inferred from a `lender` key, so you rarely pass this. Name it to ask the ANY-lender question (`{dimension:'lender', volume:{gte:50000000}}` = 'some single lender they sent $50M to'). A geographic dimension is a 400 naming the per-company markets endpoint, which live-aggregates that answer.","enum":["zip","city","county","state","lender"],"type":"string"},"lender":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Funding lender, as an id from `listLenders` or `instantSearch`. Lender names are stored in a normalized dictionary form, so a typed name does not match — resolve it first. Several values UNION."},"not":{"description":"Invert the whole entry: match companies with NO lender relationship matching it (e.g. 'does not send loans to this lender').","type":"boolean"},"product":{"allOf":[{"$ref":"#/components/schemas/FootprintProductFilter"},{"description":"Correlate a product INSIDE this lender relationship — '$1M of FHA through this lender'."}]},"shareOfVolume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"This lender's share of the company's total volume for the period, as a 0–100 PERCENT (not a 0–1 fraction). `{gte:50}` = 'at least half their book goes through this lender'."}]},"units":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Loan count funded by this lender during the selected period."}]},"volume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Dollar volume funded BY this lender during the selected period — evaluated inside the lender's own bucket, not against the company's total."}]}},"type":"object"},"CompanyHeadcountResponse":{"properties":{"series":{"description":"Monthly headcount, ending at the last COMPLETE month (the in-progress month always undercounts) and trimmed of trailing months with no movement yet. Counts PEOPLE, not license records: a loan officer licensed in many states counts once, and adding or dropping a state license is not a hire or an exit.","items":{"$ref":"#/components/schemas/HeadcountPoint"},"type":"array"},"summary":{"properties":{"change1y":{"description":"Hires minus exits over the last 365 days.","type":"number"},"change30d":{"description":"Hires minus exits over the last 30 days.","type":"number"},"change90d":{"description":"Hires minus exits over the last 90 days.","type":"number"},"current":{"description":"Loan officers holding an open employment record here today.","type":"number"},"entered":{"description":"Hires in the window. A hire is a loan officer whose earliest employment record at this company still relevant to the window (open, or ended on/after the window start) starts inside it — so someone who fully left and came back inside the window counts, and an existing employee who adds a state license does not.","type":"number"},"exited":{"description":"Exits in the window. An exit is a loan officer whose latest record at this company ended inside the window and who holds NO open record there — a complete departure.","type":"number"},"net":{"type":"number"}},"required":["current","change30d","change90d","change1y","entered","exited","net"],"type":"object"},"truncated":{"description":"`true` when the company has more than 100,000 loan officers in scope and only the first 100,000 (by NMLS ID) were counted. `false` means every figure covers the full population.","type":"boolean"},"window":{"$ref":"#/components/schemas/EmploymentWindow"}},"required":["window","series","summary","truncated"],"type":"object"},"CompanyLicense":{"properties":{"isAuthorized":{"nullable":true,"type":"boolean"},"issueDate":{"nullable":true,"type":"string"},"licenseId":{"nullable":true,"type":"string"},"licenseNumber":{"nullable":true,"type":"string"},"licenseType":{"nullable":true,"type":"string"},"regulator":{"description":"Issuing regulator — \"<State>\" or \"<State> - <Agency>\"; not a clean state code.","nullable":true,"type":"string"},"renewedThrough":{"nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"},"statusDate":{"nullable":true,"type":"string"}},"required":["licenseId","regulator","licenseNumber","licenseType","issueDate","status","statusDate","isAuthorized","renewedThrough"],"type":"object"},"CompanyListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"crmList":{"$ref":"#/components/schemas/CompanyCrmListFilter"},"excludeBrokerPartners":{"description":"`true`: hide the companies your workspace already partners with — a confidential partner roster your organization supplied to Model Match, attached to the workspace (today: Rocket Pro TPO partners). The roster is never returned; it is applied only as an exclusion. Errors: 400 `partner_set_requires_workspace` when the request has no active workspace, 403 `partner_set_unavailable` when the workspace has no partner roster. `false` or absent: no effect.","type":"boolean"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"affordableHousingTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in qualified affordable-housing tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"affordableHousingTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in qualified census tracts for affordable-housing programs, 0-100 (`{gte:25}` = 27,209 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgAsianPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Asian (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgBlackPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Black (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgDenialRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of mortgage applications denied in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgFamilyIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median family income of the tracts the entity lent in, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Hispanic or Latino share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median home value across the tracts the entity lent in, in whole dollars. A neighborhood statistic — not the entity's average loan size, which is `avgLoanAmount`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeownershipRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean owner-occupied share of housing units in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHouseholdIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median household income of the tracts the entity lent in, in whole dollars (e.g. `{lte:60000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean tract income relative to its metro area, where `100` is parity — `{lt:80}` is the CRA low/moderate band, and values legitimately exceed 100 (observed up to 412). NOT a 0-100 share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the company's mean loan size for the selected period, derived from TOTAL production across ALL markets — NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"avgLowModHouseholdPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean HUD block-group low/moderate-income HOUSEHOLD share across the tracts the entity lent in, 0-100. A finer-grained measure than `lowModIncomeTractPct`, which counts whole tracts — not a duplicate of it. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMedianAge":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median age of the population in the tracts the entity lent in, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToCollege":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToSchool":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance from the properties the entity lent on to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToWorship":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMinorityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean non-white share of the population in the tracts the entity lent in, 0-100 (`{gte:50}` = 63,370 originators). `majorityMinorityTractPct` is the per-tract-threshold form of the same question. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPopulation":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean population of the tracts the entity lent in. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPovertyRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of the population below the poverty line in the tracts the entity lent in, 0-100. Pass whole percents — `{gte:0.2}` means 0.2%. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractApplications":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage applications reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractLoanVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean mortgage dollar volume reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractOriginations":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage originations reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgWhiteNonHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean White (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"branchCount":{"$ref":"#/components/schemas/NumericFilterValue"},"city":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Registered business address CITY — where the company is headquartered, NOT where it produced loans. This matches companies whose registered address is in this city; a company headquartered elsewhere is excluded no matter how much it lends here, and a company headquartered here is returned even if it produced nothing here. The row's `volume`/`units`/`avgLoanAmount` remain national totals, so a city filter combined with the default `volume` sort ranks the largest national producers that happen to be headquartered in this city. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"companyType":{"$ref":"#/components/schemas/CompanyTypeFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Registered business address COUNTY — where the company is headquartered, NOT where it produced loans (same caveats as `state`; under `locationBasis: \"production\"` it selects companies that produced loans in the county instead). Accepts a county name (`Travis`, with a sibling `state` when the name exists in several states), a 5-digit FIPS code (`48453`) or a dictionary county id; an array matches any. The address carries no county of its own, so it matches when the geocoded point of the address lies inside the Census boundary of the county (a company with no geocoded address matches no county). An unrecognized county is a 400. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"difficultDevelopmentAreaCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in HUD-designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"difficultDevelopmentAreaPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in HUD-designated difficult development areas, 0-100 (`{gte:25}` = 93,397 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in distressed-or-underserved tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in distressed-or-underserved nonmetropolitan middle-income tracts, 0-100 (`{gte:25}` = 11,773 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"floodHazardTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in a FEMA special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"floodHazardTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in a FEMA special flood hazard area, 0-100 (`{gte:25}` = 5,212 originators). `predominantFloodZone` gives the specific zone code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"geoPoint":{"allOf":[{"$ref":"#/components/schemas/GeoFilterValue"},{"description":"Radius search around a point, over the company's registered business address — it finds companies HEADQUARTERED within the radius, NOT companies that produced loans there. A company headquartered outside the radius is excluded no matter how much it lends inside it, and one headquartered inside is returned even if it produced nothing there. The row's `volume`/`units`/`avgLoanAmount` remain national totals, so a radius search combined with the default `volume` sort ranks the largest national producers that happen to be headquartered nearby. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"isBroker":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"`true`: broker shops — non-bank companies that send more of the period's volume to OTHER lenders than they fund themselves. `false`: everyone else. Computed per period from each company's lender mix. Cannot be combined with `mode: \"or\"`."}]},"loCount":{"$ref":"#/components/schemas/NumericFilterValue"},"loanType":{"$ref":"#/components/schemas/OriginatorLoanTypeFilterValue"},"loansWithCommunityData":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many of the entity's loans in the selected period resolved to a neighborhood — the DENOMINATOR every Community Lending share is taken over. Pair it with a share filter (`{gte:25}`, 60,399 originators) so a 100% share off two loans does not read as a 100% share off two hundred. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans that landed in a low- or moderate-income tract, as a count rather than a share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans that landed in a low- or moderate-income tract under the Community Reinvestment Act, 0-100. `{gte:50}` = 'at least half their book is LMI' (36,977 originators, 655 companies, 648 branches). Pass whole percents — `{gte:0.5}` means half of one percent and matches nearly everyone. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in majority-minority tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in majority-minority tracts, 0-100 (`{gte:50}` = 65,654 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"mode":{"enum":["and","or"],"type":"string"},"msa":{"$ref":"#/components/schemas/CompanyMsaFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (name pollution silently returns unrelated companies). Resolve via instantSearch and filter by `nmlsId` (exact NMLS id) instead. Still functional for now."}]},"namePrefix":{"description":"Prefix name search: every word must start a word of the name (\"rock mort\" → Rocket Mortgage). No fuzzy/nickname matching; relevance-ranked unless `sort` is set. Max 100 chars / 6 words (emails, URLs, phones ignored), else 400.","minLength":1,"type":"string"},"nmlsId":{"$ref":"#/components/schemas/TextFilterValue"},"opportunityZoneCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in Opportunity Zone tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"opportunityZonePct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in federally designated Opportunity Zone tracts, 0-100 (`{gte:10}` = 33,520 originators — this is a small-share filter, a 50% floor finds almost nobody). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"predominantFloodZone":{"$ref":"#/components/schemas/EntityPredominantFloodZoneFilterValue"},"predominantIncomeLevel":{"$ref":"#/components/schemas/EntityPredominantIncomeLevelFilterValue"},"producersOnly":{"$ref":"#/components/schemas/BooleanFilterValue"},"region":{"$ref":"#/components/schemas/CompanyRegionFilterValue"},"rosterJoined":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the number of loan officers who joined the company during the selected period — individuals whose sponsorship with the company began inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction."}]},"rosterLeft":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the number of loan officers who left the company during the selected period — individuals whose sponsorship with the company ended inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction."}]},"ruralGradient":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean remoteness of the tracts the entity lent in, on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). This is a code, not a percent — `{gte:7}` selects the deepest-rural books (8,886 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in rural tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in rural tracts, 0-100 (`{gte:50}` = 24,006 originators). `ruralGradient` is the finer, ordinal form. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"state":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Registered business address STATE — where the company is headquartered, NOT where it produced loans. This matches companies whose registered address is in this state; a company headquartered elsewhere is excluded no matter how much it lends here, and a company headquartered here is returned even if it produced nothing here. The row's `volume`/`units`/`avgLoanAmount` remain national totals, so a state filter combined with the default `volume` sort ranks the largest national producers that happen to be headquartered in this state — not the largest producers in it. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"teamSize":{"$ref":"#/components/schemas/NumericFilterValue"},"transactionType":{"$ref":"#/components/schemas/OriginatorTransactionTypeFilterValue"},"units":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the company's TOTAL loan count for the selected period across ALL markets — the same national total the response `units` returns, NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request, exactly as described on the `volume` filter. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"usdaEligibleTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in USDA-eligible tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"usdaEligibleTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in tracts eligible for USDA rural housing programs, 0-100 (`{gte:50}` = 90,392 originators). Broader than `ruralTractPct` — eligibility reaches well past what is classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"volume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bound the company's TOTAL dollar production for the selected period across ALL markets — this is the same national total the response `volume` returns, and it is NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request. Combined with one of those filters it means 'national volume at least this large, AND headquartered in that place' — not 'produced this much there'. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Registered business address ZIP code — where the company is headquartered, NOT where it produced loans, with the same caveats as `state` and `city`: a company headquartered elsewhere is excluded however much it lends in this ZIP, and the row's `volume`/`units`/`avgLoanAmount` remain national totals. Canonical key (matches the response DTO); `zipCode` is an alias kept for cross-entity consistency with loans/sales. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zip`, identical behavior — the registered business address ZIP code, i.e. where the company is headquartered, NOT where it produced loans. The row's `volume`/`units`/`avgLoanAmount` remain national totals. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there."}]}},"type":"object"},"footprint":{"anyOf":[{"$ref":"#/components/schemas/CompanyFootprintFilter"},{"items":{"$ref":"#/components/schemas/CompanyFootprintFilter"},"type":"array"}],"description":"Scoped lender filter(s). Each entry names ONE lender relationship and the metric bounds that must hold INSIDE it — `{lender:'<id>', volume:{gte:50000000}}` means '$50M funded by that lender', not '$50M somewhere and one loan with them'. Several entries AND together. Geographic market filters are not available on companies: that rollup is not written for these records, so use `POST /companies/{nmlsId}/markets` (live-aggregated) for a company's geography."},"lenderFilters":{"items":{"$ref":"#/components/schemas/LenderFilterEntry"},"type":"array"},"lenderMatchMode":{"$ref":"#/components/schemas/LenderMatchMode"},"locationBasis":{"description":"What the geographic filters (`city`/`county`/`msa`/`region`/`state`/`zip`/`zipCode`/`geoPoint`) select. `registeredAddress` (the default) matches companies whose REGISTERED BUSINESS ADDRESS is in the place — a company registered elsewhere is excluded no matter how much it lends there. `production` matches companies that PRODUCED loans in the place, whatever address they are registered at, which is usually what a geographic search means. It changes only WHICH companies are returned: every non-geographic filter applies identically either way, `scopedVolume`/`scopedUnits` report in-geography production under both, and `countCompanies` honors this field, so a count and a list built from the same body always describe the same set. Measured on an 8-state Southeast search: under `registeredAddress` the largest actual producer in the region is absent at any depth, because it is registered in Michigan.","enum":["registeredAddress","production"],"type":"string"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"productMix":{"$ref":"#/components/schemas/CompanyProductMixFilter"},"sort":{"items":{"properties":{"field":{"enum":["name","nmlsId","companyType","city","state","volume","units","scopedVolume","scopedUnits","teamSize","loCount","rosterJoined","rosterLeft","producersOnly","purchaseShare","refinanceShare"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"},"transactionMix":{"$ref":"#/components/schemas/CompanyTransactionMixFilter"}},"type":"object"},"CompanyListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/CompanySummary"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"CompanyLookupRequest":{"additionalProperties":false,"properties":{"activeLoCount":{"additionalProperties":false,"description":"Bound the number of loan officers currently sponsored OR registered with the company (distinct people).","properties":{"gte":{"type":"number"},"lte":{"type":"number"}},"type":"object"},"branchCount":{"additionalProperties":false,"description":"Bound the number of registered branch offices.","properties":{"gte":{"type":"number"},"lte":{"type":"number"}},"type":"object"},"city":{"description":"Registered address city.","type":"string"},"name":{"description":"Company name — all words must match, fuzzily.","maxLength":200,"type":"string"},"nmlsIds":{"description":"Exact NMLS company ids (up to 1000). Every id registered with NMLS is returned, including companies with no production on file.","items":{"type":"string"},"maxItems":1000,"type":"array"},"pagination":{"additionalProperties":false,"description":"`limit` default 100 (max 1000); `offset + limit` may not exceed 10,000.","properties":{"limit":{"maximum":1000,"minimum":1,"type":"integer"},"offset":{"minimum":0,"type":"integer"}},"type":"object"},"regulatorCategory":{"description":"`BANK` (OCC / FDIC, or a Federal Reserve–regulated company whose name contains 'bank'), `CU` (NCUA), `OTHER` (every other company, including every state-licensed non-bank lender). Several values union.","items":{"enum":["BANK","CU","OTHER"],"type":"string"},"type":"array"},"sort":{"description":"Default: name ascending.","items":{"properties":{"field":{"enum":["name","nmlsId","branchCount","activeLoCount","avgTenureMonths"],"type":"string"},"order":{"enum":["asc","desc"],"type":"string"}},"required":["field"],"type":"object"},"type":"array"},"state":{"description":"Registered address state (2-letter code).","type":"string"}},"type":"object"},"CompanyLookupResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CompanyLookupRow"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"CompanyLookupRow":{"properties":{"activeLoCount":{"description":"Distinct loan officers currently sponsored or registered with the company.","nullable":true,"type":"number"},"avgTenureMonths":{"description":"Average months the current loan officers have been at the company, as of the last weekly registry refresh. Null when it has none.","nullable":true,"type":"number"},"branchCount":{"nullable":true,"type":"number"},"businessStructure":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"primaryFederalRegulator":{"nullable":true,"type":"string"},"registrationStatus":{"nullable":true,"type":"string"},"regulatorCategory":{"enum":["BANK","CU","OTHER",null],"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"}},"required":["nmlsId","name","city","state","businessStructure","registrationStatus","primaryFederalRegulator","regulatorCategory","branchCount","activeLoCount","avgTenureMonths"],"type":"object"},"CompanyMarketBucket":{"properties":{"avgLoanAmount":{"nullable":true,"type":"number"},"key":{"description":"Join-stable bucket identity — ZIP `\"92683\"`, city `\"orlando|fl\"`, county 5-digit FIPS `\"06037\"`, state `\"CA\"`.","nullable":true,"type":"string"},"name":{"description":"Human label, in the same form the matching `/breakdowns` route publishes: a county reads `Middlesex County (MA)`, a state `MA`, a city `Belmont, MA` (this grain is a city within one state). `key` is the identity; `name` is the only field to display.","nullable":true,"type":"string"},"shareOfBook":{"description":"Share of the entity's whole period volume as pre-stored on the entity record, 0–100. Always null for a company: the pre-aggregated market rollups are not written for companies, so this figure is computed live and has no stored share to report. Use `shareOfScope`, or divide by `totals.volume`.","nullable":true,"type":"number"},"shareOfScope":{"description":"Share of the volume of every market RANKED at this grain, 0–100 — the denominator is the whole footprint the request selected, NOT the page. It therefore sums to 100 only when `limit` covers every bucket; on a shorter page the shortfall is the tail you did not ask for. (Note the scale: 0–100, unlike the Community Lending fractions, which are 0–1.)","nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"description":"Dollar volume in this market. A ranked top-N figure is a distributed approximation and can understate slightly (measured: 1.2% on one headline market); narrowing the request to this market with `zipCodes` returns the exact figure.","nullable":true,"type":"number"}},"required":["key","name","volume","units","avgLoanAmount","shareOfScope","shareOfBook"],"type":"object"},"CompanyMarketsCommunityLending":{"description":"The Community Lending mix of this footprint: the neighborhood characteristics of where the production landed, as percentages on a 0-100 scale. Null when nothing in scope resolved to a neighborhood — an absent block, never a row of zeroes, because 'no data' and '0%' are different answers. Read `basis` before comparing two responses. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"affordableHousingTractPct":{"description":"Share of production, 0-100, in neighborhoods carrying an affordable-housing designation. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"basis":{"description":"Which measurement produced this block, and they are NOT the same number. `entityRollup` is the neighborhood mix of the entity's own production over the whole period — the default. `marketsInScope` is the neighborhood profile of the markets the request selected, weighted by the entity's production in each, and is what any ZIP, date or filter scope returns, because a whole-period rollup cannot be re-cut to a narrower question.","enum":["entityRollup","marketsInScope"],"type":"string"},"coveredProductionPct":{"description":"`marketsInScope` only — what share of the weighted production, 0-100, sits in a market that resolved to neighborhood data. Below 100 means the mix describes part of the footprint, not all of it.","nullable":true,"type":"number"},"difficultDevelopmentAreaPct":{"description":"Share of production, 0-100, in designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"distressedTractPct":{"description":"Share of production, 0-100, in distressed or underserved nonmetropolitan middle-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"floodHazardTractPct":{"description":"Share of production, 0-100, in neighborhoods inside a special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"incomeLevelMix":{"description":"`marketsInScope` only — the full relative-income distribution of the neighborhoods, 0-100, summing to about 100. Null on `entityRollup`, which stores the predominant band but no distribution; publishing one derived from a single label would be a histogram nobody measured. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"low":{"nullable":true,"type":"number"},"middle":{"nullable":true,"type":"number"},"moderate":{"nullable":true,"type":"number"},"upper":{"nullable":true,"type":"number"}},"required":["low","moderate","middle","upper"],"type":"object"},"loansWithCommunityData":{"description":"`entityRollup` only — how many of the entity's transactions in the period resolved to a neighborhood. This is the denominator every share below is a share OF, so read it first: a 100% share over three transactions is not a footprint.","nullable":true,"type":"number"},"lowModIncomeTractPct":{"description":"Share of production, 0-100, in low- or moderate-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractPct":{"description":"Share of production, 0-100, in majority-minority neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"marketsInScope":{"description":"`marketsInScope` only — ZIP markets the mix considered, including any that carried no neighborhood data.","nullable":true,"type":"number"},"marketsWithCommunityData":{"description":"`marketsInScope` only — ZIP markets that resolved to neighborhood data.","nullable":true,"type":"number"},"opportunityZonePct":{"description":"Share of production, 0-100, in designated Opportunity Zones. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"predominantIncomeLevel":{"description":"The most common relative-income classification of the neighborhoods, on the standard four-band scale. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","enum":["low","moderate","middle","upper",null],"nullable":true,"type":"string"},"ruralTractPct":{"description":"Share of production, 0-100, in neighborhoods classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTractPct":{"description":"Share of production, 0-100, in neighborhoods eligible for USDA rural housing programs. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"}},"required":["basis","loansWithCommunityData","marketsWithCommunityData","marketsInScope","coveredProductionPct","predominantIncomeLevel","incomeLevelMix","lowModIncomeTractPct","majorityMinorityTractPct","ruralTractPct","opportunityZonePct","affordableHousingTractPct","distressedTractPct","usdaEligibleTractPct","floodHazardTractPct","difficultDevelopmentAreaPct"],"type":"object"},"CompanyMarketsDateRange":{"description":"Custom window, applied IN ADDITION to `period` (the two intersect). Use it for a window the named periods cannot express.","properties":{"from":{"description":"Inclusive lower bound, `YYYY-MM-DD` (a bare `YYYY` or `YYYY-MM` expands to the start of that period).","example":"2025-01-01","type":"string"},"to":{"description":"Inclusive upper bound, `YYYY-MM-DD` (a bare `YYYY` or `YYYY-MM` expands to the END of that period).","example":"2025-12-31","type":"string"}},"type":"object"},"CompanyMarketsRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"dateRange":{"$ref":"#/components/schemas/CompanyMarketsDateRange"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"limit":{"description":"Buckets returned per grain (default 25). The summary is computed BEFORE this slice, so it describes the footprint and not the page.","maximum":200,"minimum":1,"type":"integer"},"period":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Named window over the company's recorded transactions (default `last12Months`)."}]},"zipCodes":{"description":"Narrow the footprint to these ZIP codes. Values are normalized to 5 digits, so a ZIP that lost its leading zero in a spreadsheet (`1001`) still resolves. A value that is not 1–5 digits returns 400 rather than being silently dropped.","example":["92683","92703"],"items":{"type":"string"},"maxItems":200,"type":"array"}},"type":"object"},"CompanyMarketsResponse":{"properties":{"nmlsId":{"type":"string"},"period":{"type":"string"},"rollups":{"properties":{"cities":{"items":{"$ref":"#/components/schemas/CompanyMarketBucket"},"type":"array"},"counties":{"items":{"$ref":"#/components/schemas/CompanyMarketBucket"},"type":"array"},"states":{"items":{"$ref":"#/components/schemas/CompanyMarketBucket"},"type":"array"}},"required":["cities","counties","states"],"type":"object"},"source":{"$ref":"#/components/schemas/CompanyMarketsSource"},"summary":{"$ref":"#/components/schemas/CompanyMarketsSummary"},"totals":{"description":"The whole matched book — every transaction the filters selected, including those that could not be placed in a market. The denominator for `summary.shareOfMatchedVolume`.","properties":{"avgLoanAmount":{"nullable":true,"type":"number"},"excluded":{"description":"Transactions held out of `volume` because their amount is an out-of-range fill rather than a real figure — the second kind of omission this response reports, alongside `summary.unresolved` (production that could not be placed in a market). Compare against `units` to see the share `volume` was computed over: a company whose amounts are mostly unreadable and one that is genuinely small are indistinguishable without it. Absent when the money column is unguarded.","nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"}},"required":["volume","units","avgLoanAmount"],"type":"object"},"zips":{"items":{"$ref":"#/components/schemas/CompanyMarketBucket"},"type":"array"}},"required":["nmlsId","period","source","summary","zips","rollups","totals"],"type":"object"},"CompanyMarketsSource":{"properties":{"mode":{"description":"Companies are always computed live from the recorded transactions — there is no pre-aggregated market rollup on a company record to read.","enum":["live"],"type":"string"},"reasons":{"description":"Why the live path was selected, in evaluation order (e.g. `coverage-empty`, `zip-scope`, `date-scope`).","items":{"type":"string"},"type":"array"}},"required":["mode","reasons"],"type":"object"},"CompanyMarketsSummary":{"properties":{"avgLoanAmount":{"description":"Units-weighted mean loan size — equal to `volume ÷ units`, NOT the unweighted mean of the per-market averages (which differs by several percent and flips sign with the bucket-size mix).","nullable":true,"type":"number"},"bucketCount":{"type":"number"},"communityLending":{"$ref":"#/components/schemas/CompanyMarketsCommunityLending"},"shareOfBook":{"description":"Always null for a company — see the same field on a bucket.","nullable":true,"type":"number"},"shareOfMatchedVolume":{"description":"What percent of `totals.volume` these ZIP buckets account for, 0–100. Below 100 whenever transactions could not be placed to a ZIP or fall outside the ranked depth — published so a partial sum is never mistaken for a total.","nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"unresolved":{"description":"Production the source could not place in a market, held OUT of the blend and reported here rather than ranked alongside real markets.","properties":{"bucketCount":{"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"}},"required":["bucketCount","volume","units"],"type":"object"},"volume":{"nullable":true,"type":"number"}},"required":["bucketCount","volume","units","avgLoanAmount","shareOfBook","shareOfMatchedVolume","unresolved","communityLending"],"type":"object"},"CompanyMsaFilterValue":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Registered business address METRO AREA (MSA / CBSA) — companies headquartered in ANY county of the metro (the address point inside the boundary of a member county, as for `county`); under `locationBasis: \"production\"`, companies that produced loans in it. 5-digit CBSA code (`12420`) or metro name (`Austin Metro`); an array matches any. Member counties per the OMB July-2023 delineation (Connecticut's pre-2022 counties included; `41860` San Francisco Bay Area is the nine-county Bay Area). Unknown/ambiguous names are a 400 naming candidates."},"CompanyProductMixFilter":{"description":"Loan-product share / volume bands for the selected period, ANDed: `[{product:\"fha\", minShare:30}]` = FHA is at least 30% of the company's period volume; `[{product:\"va\", volume:{gte:5000000}}]` = at least $5M of VA. `products` lets ANY of several types satisfy one entry. Whole-book figures across all markets.","items":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100 percent. No bucket = 0% (passes).","maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","maximum":100,"minimum":0,"type":"number"},"product":{"description":"The loan product. Send this OR `products`, not both.","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},"products":{"description":"Several products, ANY of which may satisfy the bounds on its own (each type's share is read separately, never summed): `{products:[\"fha\",\"va\",\"usda\"], minShare:30}` = FHA, VA or USDA is on its own at least 30% of the book. Send this OR `product`.","items":{"enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},"maxItems":10,"minItems":1,"type":"array"},"volume":{"additionalProperties":false,"description":"Dollar volume of THIS type in the period, `{gte, lte}` — e.g. `{gte: 5000000}` = at least $5M of FHA. Evaluated inside the same type bucket as the share bounds; a company with no loans of the type does not match.","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"type":"object"},"maxItems":10,"minItems":1,"type":"array"},"CompanyRegionFilterValue":{"anyOf":[{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},{"items":{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Registered business address CENSUS REGION / DIVISION (`<region>-division-<n>`, Census numbering 1–9) — companies headquartered in ANY state of it; under `locationBasis: \"production\"`, companies that produced loans in it. An array matches any."},"CompanyRegistration":{"nullable":true,"properties":{"activeLoCount":{"nullable":true,"type":"number"},"avgTenureMonths":{"description":"Average months the company's current loan officers have been there (earliest open employment record each), as of the last weekly registry refresh. Divide by 12 for years. Null when it has none.","nullable":true,"type":"number"},"branchCount":{"nullable":true,"type":"number"},"businessStructure":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"dateFormed":{"nullable":true,"type":"string"},"formedIn":{"nullable":true,"type":"string"},"hasAuthorizedLicense":{"description":"At least one of `licenses` is currently authorized. Null when no license rows are on file.","nullable":true,"type":"boolean"},"licensedStates":{"items":{"type":"string"},"nullable":true,"type":"array"},"licenses":{"description":"Every NMLS license / registration row on file for the company, authorized or not.","items":{"$ref":"#/components/schemas/CompanyLicense"},"nullable":true,"type":"array"},"location":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"postalCode":{"nullable":true,"type":"string"},"primaryFederalRegulator":{"nullable":true,"type":"string"},"registrationStatus":{"nullable":true,"type":"string"},"regulatorCategory":{"description":"`BANK` (OCC / FDIC, or a Federal Reserve–regulated company whose name contains 'bank'), `CU` (NCUA), `OTHER` (every other company).","enum":["BANK","CU","OTHER",null],"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"stockSymbol":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"tradeNames":{"items":{"type":"string"},"nullable":true,"type":"array"},"websites":{"items":{"type":"string"},"nullable":true,"type":"array"}},"type":"object"},"CompanyRoleScope":{"description":"Which of a loan's party roles make it this company's loan. `loanCompany` (default): the company named on the loan document — one company per loan. `all`: the company appears in ANY role — loan-document company, the originating LO's employer at time of loan, the LO's organization, broker, or funding lender; a loan matching several roles counts once. `employer`: the company employed the originating LO when the loan closed. `broker`: the company brokered the loan. `lender`: the company funded the loan. `tpo`: third-party origination — the company is the loan company or lender but did NOT employ the originating LO (the `channel` dimension's `tpo` bucket as a population; `employer` is its `inHouse` counterpart). Use `all` for a broker shop's full production — its loans are often recorded under the funding lender's name, so `loanCompany` undercounts it.","enum":["loanCompany","all","employer","broker","lender","tpo"],"type":"string"},"CompanySegment":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`. Time-series only: `titleCompany` groups on the title company named on the deed, with spellings of one company merged per bucket (`label` = most-used spelling across the response, `id` = normalized name — match on `id`) and \"none available\"-style placeholders excluded. `channel` (companies only) splits the company's loans into `inHouse` — the company employed the originating loan officer — and `tpo` — the company is the loan company or funding lender but did NOT employ the LO (third-party origination). The two never overlap; under `roleScope: \"all\"` they need not sum to the total (broker-only and LO-organization-only matches are in neither). Both buckets are always returned.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","broker","originator","channel","titleCompany"],"type":"string"},"CompanySlice":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`. `channel` (companies only) splits the company's loans into `inHouse` — the company employed the originating loan officer — and `tpo` — the company is the loan company or funding lender but did NOT employ the LO (third-party origination). The two never overlap; under `roleScope: \"all\"` they need not sum to the total (broker-only and LO-organization-only matches are in neither). Both buckets are always returned.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","broker","originator","channel"],"type":"string"},"CompanySponsoredIndividual":{"properties":{"activeLicenseCount":{"nullable":true,"type":"number"},"city":{"nullable":true,"type":"string"},"firstName":{"nullable":true,"type":"string"},"fullName":{"nullable":true,"type":"string"},"hasDisciplinaryAction":{"nullable":true,"type":"boolean"},"id":{"type":"string"},"isActive":{"nullable":true,"type":"boolean"},"isBranchManager":{"nullable":true,"type":"boolean"},"lastName":{"nullable":true,"type":"string"},"licensedStates":{"items":{"type":"string"},"nullable":true,"type":"array"},"nmlsId":{"nullable":true,"type":"string"},"sponsorships":{"nullable":true},"state":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"CompanySponsoredIndividualsRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"isActive":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the individual's NMLS registration is currently active. `true` and `false` partition the roster — they sum to the unfiltered total."}]},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan officer name. Matches ALL the words supplied, fuzzily, against the individual's full name — so \"John Smith\" does not return every John or every Smith. Scoped to this company's roster."}]},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"sort":{"items":{"properties":{"field":{"enum":["city","state","zipCode","county","transactionType","loanType","conforming","mortgageAmount","mortgageDate","broker","loanCompany","lender","borrowerStatus","salePrice","saleDate","originator","originatorName","interestRate","equity","homeValue","ltvAtOrigination","currentBalance"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"CompanySponsoredIndividualsResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/CompanySponsoredIndividual"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"CompanySponsorshipMovementRequest":{"properties":{"dateFrom":{"description":"Window start (ISO date, default 12 mo ago)","type":"string"},"dateTo":{"description":"Window end (ISO date, default today)","type":"string"},"direction":{"default":"both","enum":["arrivals","departures","both"],"type":"string"},"size":{"default":25,"description":"Max example individuals per direction (0–500, default 25; a fractional value is rounded down). Affects ONLY the `arrivals`/`departures` row lists — every count and breakdown covers the full population regardless.","maximum":500,"minimum":0,"type":"number"}},"type":"object"},"CompanySponsorshipMovementResponse":{"properties":{"alreadyAtCompany":{"description":"Counted in `summary.arrivals` but NOT a hire: already sponsored by this company before the window and merely added a state license.","type":"number"},"arrivalSources":{"description":"Prior employers of the `fromOtherCompany` group, by distinct individuals, over the FULL population. An attribution, not a partition: an individual who ended sponsorships at two companies inside the window is counted under both, so this may sum above `fromOtherCompany`. Complete unless `arrivalSourcesTruncated` is `true`.","items":{"properties":{"companyName":{"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"count":{"type":"number"}},"required":["companyNmlsId","companyName","count"],"type":"object"},"type":"array"},"arrivalSourcesTruncated":{"description":"`true` when more distinct employers matched than `arrivalSources` can hold (1000); the list is then the largest 1000 and no longer accounts for all of `fromOtherCompany`. `false` means the list is complete. The scalar counts are unaffected either way.","type":"boolean"},"arrivals":{"items":{"properties":{"movementKind":{"description":"Which group this arrival falls in — the row-level twin of `fromOtherCompany` / `newToIndustry` / `alreadyAtCompany`. `from_other_company`: moved here from a different employer (named in `previousCompany`). `new_to_industry`: no prior sponsorship at any company. `already_at_company`: already sponsored here before the window and merely added a state license — not a move.","enum":["from_other_company","new_to_industry","already_at_company"],"type":"string"},"name":{"type":"string"},"nmlsId":{"type":"string"},"previousCompany":{"nullable":true,"type":"string"},"previousCompanyNmlsId":{"nullable":true,"type":"string"},"startDate":{"description":"When this individual actually joined — the earliest sponsorship start at this company, not the license row that matched the window.","type":"string"}},"required":["nmlsId","name","startDate","previousCompany","previousCompanyNmlsId","movementKind"],"type":"object"},"type":"array"},"departureDests":{"description":"Onward employers of the `toOtherCompany` group, by distinct individuals, over the FULL population. Same attribution caveat as `arrivalSources`. Complete unless `departureDestsTruncated` is `true`.","items":{"properties":{"companyName":{"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"count":{"type":"number"}},"required":["companyNmlsId","companyName","count"],"type":"object"},"type":"array"},"departureDestsTruncated":{"description":"`true` when more distinct employers matched than `departureDests` can hold (1000); the list is then the largest 1000 and no longer accounts for all of `toOtherCompany`. `false` means the list is complete. The scalar counts are unaffected either way.","type":"boolean"},"departures":{"items":{"properties":{"endDate":{"type":"string"},"movementKind":{"description":"Which group this departure falls in — the row-level twin of `toOtherCompany` / `leftIndustry` / `stillAtCompany`. `to_other_company`: moved on to a different employer (named in `nextCompany`). `left_industry`: holds no open sponsorship at any company afterwards. `still_at_company`: still sponsored here; a state license lapsed — not an exit.","enum":["to_other_company","left_industry","still_at_company"],"type":"string"},"name":{"type":"string"},"nextCompany":{"nullable":true,"type":"string"},"nextCompanyNmlsId":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"}},"required":["nmlsId","name","endDate","nextCompany","nextCompanyNmlsId","movementKind"],"type":"object"},"type":"array"},"fromOtherCompany":{"description":"Arrivals who moved from a different employer. `fromOtherCompany + newToIndustry + alreadyAtCompany` equals `summary.arrivals` exactly.","type":"number"},"leftIndustry":{"description":"Departures holding no open sponsorship at any company afterwards.","type":"number"},"newToIndustry":{"description":"Arrivals with no prior sponsorship at any company — genuinely new to the industry.","type":"number"},"stillAtCompany":{"description":"Counted in `summary.departures` but NOT an exit: still holds an open sponsorship with this company; a state license lapsed.","type":"number"},"summary":{"properties":{"arrivals":{"description":"Individuals whose sponsorship with this company began inside the window. Counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate sponsorship record for every state they are licensed in, so an existing team member who adds or lapses one state license registers here even though their employment did not change. The `alreadyAtCompany` / `stillAtCompany` fields report exactly how many of this total that is — subtract them for a move-only figure.","type":"number"},"departures":{"description":"Individuals whose sponsorship with this company ended inside the window. Counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate sponsorship record for every state they are licensed in, so an existing team member who adds or lapses one state license registers here even though their employment did not change. The `alreadyAtCompany` / `stillAtCompany` fields report exactly how many of this total that is — subtract them for a move-only figure.","type":"number"},"netChange":{"type":"number"}},"required":["arrivals","departures","netChange"],"type":"object"},"toOtherCompany":{"description":"Departures who moved to a different employer. `toOtherCompany + leftIndustry + stillAtCompany` equals `summary.departures` exactly.","type":"number"}},"required":["summary","arrivalSources","arrivalSourcesTruncated","departureDests","departureDestsTruncated","fromOtherCompany","toOtherCompany","newToIndustry","leftIndustry","alreadyAtCompany","stillAtCompany","arrivals","departures"],"type":"object"},"CompanySummary":{"properties":{"avgLoanAmount":{"description":"Mean loan size for the selected period, derived from the TOTAL `volume` and `units` across ALL markets — NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there.","nullable":true,"type":"number"},"city":{"nullable":true,"type":"string"},"companyType":{"nullable":true,"type":"string"},"id":{"description":"Document ID","type":"string"},"loCount":{"nullable":true,"type":"number"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"purchaseShare":{"description":"Purchase loans as a 0–100 percent of the company's period loan COUNT — the value `sort: [{field: \"purchaseShare\"}]` orders by. `null` when it made no purchase loans in the period (sorts as 0).","nullable":true,"type":"number"},"refinanceShare":{"description":"Refinance loans as a 0–100 percent of the company's period loan COUNT — the value `sort: [{field: \"refinanceShare\"}]` orders by. `null` when none (sorts as 0).","nullable":true,"type":"number"},"rosterJoined":{"description":"Loan officers who joined the company during the selected period — individuals whose sponsorship with the company began inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction.","nullable":true,"type":"number"},"rosterLeft":{"description":"Loan officers who left the company during the selected period — individuals whose sponsorship with the company ended inside the window. IMPORTANT — this counts LICENSING EVENTS, not confirmed employer moves. A loan officer holds a separate license record for every state they are sponsored in, and this counts each individual whose sponsorship began or ended inside the window, so a single added or lapsed state license registers as an arrival or a departure even when the person's employment did not change. Measured on large lenders: 13-24% of a 12-month `rosterLeft` are still sponsored by the same employer today, and 33-50% of a 12-month `rosterJoined` were already sponsored by it before the window began. Treat both as directional indicators of movement, not as headcounts. `rosterJoined` and `rosterLeft` are measured from the same source on the same window basis, so unlike the retired `loLoss` — which had no arrivals figure computed the same way — the two can legitimately be combined into a churn rate. Both also grow with the window, so a longer period reports more than a shorter one and the periods are comparable in that direction.","nullable":true,"type":"number"},"scopedUnits":{"description":"The company's loan count INSIDE the geography this request names, on the same basis as `scopedVolume`. Sortable. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /companies/{nmlsId}/markets` for the same geography and period: both are computed from the same recorded transactions and neither excludes transactions with no identified loan officer.","nullable":true,"type":"number"},"scopedVolume":{"description":"The company's dollar production INSIDE the geography this request names — what a `city`/`state`/`zip`/`zipCode`/`geoPoint` filter was almost certainly asking for, and what the sibling `volume` is not. Sort by `scopedVolume` to rank companies by it. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /companies/{nmlsId}/markets` for the same geography and period: both are computed from the same recorded transactions and neither excludes transactions with no identified loan officer.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"teamSize":{"nullable":true,"type":"number"},"units":{"description":"The company's TOTAL loan count for the selected period across ALL markets — NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request, exactly as described on `volume`. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there.","nullable":true,"type":"number"},"volume":{"description":"The company's TOTAL dollar production for the selected period across ALL markets — NOT scoped to any geographic filter (`city`/`state`/`zip`/`zipCode`/`geoPoint`) in this request. Those filters select WHICH companies are returned, by registered business address, and never change WHAT is summed here. Since the list sorts by `volume` descending by default, a geo-filtered search ranks companies by NATIONAL production, so the top row can be many times larger than that company's production inside the filtered area. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank companies by it. There are two ways to get production for a geography: `POST /companies/{nmlsId}/markets` breaks ONE company's production out by market, and `POST /loans/analytics/chart` with `measure: \"volume\"`, `slice: \"loanCompany\"` and a geographic filter answers the reverse — the companies that actually produced in that geography, each with the volume they produced there.","nullable":true,"type":"number"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"CompanySummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"},"roleScope":{"$ref":"#/components/schemas/CompanyRoleScope"}},"type":"object"},"CompanyTalentFlowResponse":{"properties":{"arrivals":{"description":"Where this window's hires came from: each hire's employer whose record ended most recently on or before their start here. A partition — `companies[].count` + `unattributed` = `total`. A hire is a loan officer whose earliest employment record at this company still relevant to the window (open, or ended on/after the window start) starts inside it — so someone who fully left and came back inside the window counts, and an existing employee who adds a state license does not.","properties":{"companies":{"items":{"$ref":"#/components/schemas/TalentFlowCompany"},"type":"array"},"companiesTruncated":{"description":"`true` when more counterparties exist than `limit`; `companies` is then the largest `limit`. `total` and `unattributed` are unaffected.","type":"boolean"},"total":{"type":"number"},"unattributed":{"description":"Hires with no earlier employer on file that ended by their start date — typically new to the industry.","type":"number"},"units":{"description":"Loans behind `volume`.","type":"number"},"volume":{"description":"Every mover on this side's production AT THIS company (employer at time of loan = this company) recorded inside the window — volume gained (arrivals) / lost (departures). Includes unattributed movers.","type":"number"}},"required":["total","unattributed","volume","units","companies","companiesTruncated"],"type":"object"},"departures":{"description":"Where this window's exits went: each exit's earliest employer record starting on or after their departure. A partition, like `arrivals`. An exit is a loan officer whose latest record at this company ended inside the window and who holds NO open record there — a complete departure.","properties":{"companies":{"items":{"$ref":"#/components/schemas/TalentFlowCompany"},"type":"array"},"companiesTruncated":{"description":"`true` when more counterparties exist than `limit`; `companies` is then the largest `limit`. `total` and `unattributed` are unaffected.","type":"boolean"},"total":{"type":"number"},"unattributed":{"description":"Exits with no later employer on file — not re-employed yet, or left the industry.","type":"number"},"units":{"description":"Loans behind `volume`.","type":"number"},"volume":{"description":"Every mover on this side's production AT THIS company (employer at time of loan = this company) recorded inside the window — volume gained (arrivals) / lost (departures). Includes unattributed movers.","type":"number"}},"required":["total","unattributed","volume","units","companies","companiesTruncated"],"type":"object"},"truncated":{"description":"`true` when the company has more than 100,000 loan officers in scope and only the first 100,000 (by NMLS ID) were counted. `false` means every figure covers the full population.","type":"boolean"},"window":{"$ref":"#/components/schemas/EmploymentWindow"}},"required":["window","arrivals","departures","truncated"],"type":"object"},"CompanyTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"},"roleScope":{"$ref":"#/components/schemas/CompanyRoleScope"},"segment":{"$ref":"#/components/schemas/CompanySegment"}},"type":"object"},"CompanyTransactionMixFilter":{"description":"Transaction-type share bands for the selected period, ANDed: `[{transactionType:\"purchase\", minShare:60}]` = purchases are at least 60% of the company's period volume.","items":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100 percent. No bucket = 0% (passes).","maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","maximum":100,"minimum":0,"type":"number"},"transactionType":{"enum":["purchase","refinance","construction","equity","UNKNOWN"],"type":"string"},"volume":{"additionalProperties":false,"description":"Dollar volume of THIS type in the period, `{gte, lte}` — e.g. `{gte: 5000000}` = at least $5M of FHA. Evaluated inside the same type bucket as the share bounds; a company with no loans of the type does not match.","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"required":["transactionType"],"type":"object"},"maxItems":10,"minItems":1,"type":"array"},"CompanyTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): BANK, CU, OTHER","enum":["BANK","CU","OTHER"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): BANK, CU, OTHER","enum":["BANK","CU","OTHER"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"ContactCardType":{"enum":["lo","agent","cobranded",null],"nullable":true,"type":"string"},"CountResponse":{"properties":{"lenderNormalizations":{"description":"How each `lenderName` value resolved against the lender dictionary. Present when a `lenderName` filter was supplied.","items":{"$ref":"#/components/schemas/LenderNormalization"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"description":"Exact count of records matching the filters","example":48213,"minimum":0,"type":"integer"}},"required":["total"],"type":"object"},"CreateAlertSubscriptionRequest":{"properties":{"expiresAt":{"description":"Stop firing after this instant (ISO 8601).","format":"date-time","type":"string"},"kinds":{"description":"The alert kinds to turn on for this subject (replaces kinds set directly before; kinds granted by a recipe stay). Empty = paused.","items":{"type":"string"},"type":"array"},"rules":{"description":"Rules (required for sale / property / loan subjects; same shape as POST /watched-documents).","items":{"properties":{"match":{"description":"How predicates combine: all (AND, default) or any (OR).","enum":["all","any"],"example":"all","type":"string"},"predicates":{"description":"One or more conditions; combined per match.","items":{"properties":{"field":{"description":"Catalog field alias (e.g. avm, current_ltv, loan_type).","example":"current_ltv","type":"string"},"op":{"description":"Comparison / change / status / guard operator.","enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"example":"lte","type":"string"},"stringValue":{"description":"Target keyword for changed_to / eq / not_eq guard.","type":"string"},"stringValues":{"description":"Keyword set for the in guard (1–20).","items":{"minLength":1,"type":"string"},"maxItems":20,"minItems":1,"type":"array"},"value":{"description":"Threshold, or change amount (percent for pct_change_gte).","example":0.8,"type":"number"},"value2":{"description":"Upper bound for between.","type":"number"}},"required":["field","op"],"type":"object"},"minItems":1,"type":"array"}},"required":["predicates"],"type":"object"},"type":"array"},"subject":{"$ref":"#/components/schemas/AlertSubscriptionSubject"}},"required":["subject","kinds"],"type":"object"},"CreateSavedFilterRequest":{"additionalProperties":false,"properties":{"fidelity":{"description":"How much of the UI state `query` captures: `exact`; `partial` (see `unmapped`); `ui_only` — no runnable query. Defaults from whether `query` is present.","enum":["exact","partial","ui_only"],"type":"string"},"icon":{"$ref":"#/components/schemas/SavedFilterIcon"},"kind":{"description":"`filter` (default) — a saved search; `view` — a saved CRM table layout (columns / order) kept in `uiState`. Views never carry a `query` and have their own 25-per-target quota. Fixed at create.","enum":["filter","view"],"type":"string"},"name":{"maxLength":100,"minLength":1,"type":"string"},"query":{"additionalProperties":{"nullable":true},"description":"The target list operation's request body WITHOUT `pagination` (e.g. `{ flatFilters, filters, sort, period }` for listOriginators). Validated against that operation's schema; unknown filter fields are rejected. Null/omitted for a UI-only filter.","nullable":true,"type":"object"},"target":{"description":"Which list the filter runs against. Market targets run against that entity's list operation (see `operationId`, e.g. listOriginators); `crm_people` / `crm_companies` are UI-only (filtered client-side).","enum":["originators","agents","companies","branches","offices","loans","properties","sales","crm_people","crm_companies"],"type":"string"},"uiState":{"additionalProperties":{"nullable":true},"description":"Opaque client UI state used to restore a filter panel (≤16KB). Not interpreted by the API.","nullable":true,"type":"object"},"uiStateVersion":{"minimum":1,"type":"integer"},"unmapped":{"description":"UI filter keys the client could not express in `query` (set with `fidelity: partial`).","items":{"maxLength":200,"minLength":1,"type":"string"},"maxItems":100,"type":"array"}},"required":["name","target"],"type":"object"},"CreateSavedFilterResult":{"properties":{"data":{"$ref":"#/components/schemas/SavedFilter"}},"required":["data"],"type":"object"},"CrmActiveCall":{"nullable":true,"properties":{"entityId":{"type":"string"},"id":{"type":"string"},"organizationId":{"type":"string"},"recordName":{"nullable":true,"type":"string"},"toNumber":{"type":"string"}},"required":["id","organizationId","entityId","toNumber","recordName"],"type":"object"},"CrmActiveCallResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmActiveCall"}},"required":["data"],"type":"object"},"CrmActivityEntry":{"properties":{"actorEmail":{"nullable":true,"type":"string"},"actorImage":{"nullable":true,"type":"string"},"actorName":{"nullable":true,"type":"string"},"actorUserId":{"nullable":true,"type":"string"},"body":{"nullable":true,"type":"string"},"bodyHtml":{"nullable":true,"type":"string"},"createdAt":{"type":"number"},"data":{"nullable":true},"editedAt":{"nullable":true,"type":"number"},"id":{"type":"string"},"kind":{"$ref":"#/components/schemas/CrmActivityKind"},"linkedNotes":{"items":{"$ref":"#/components/schemas/CrmActivityEntry"},"type":"array"},"occurredAt":{"nullable":true,"type":"number"},"parentId":{"nullable":true,"type":"string"},"replies":{"items":{"$ref":"#/components/schemas/CrmActivityEntry"},"type":"array"},"replyCount":{"type":"number"},"subtype":{"type":"string"}},"required":["id","kind","subtype","body","bodyHtml","parentId","actorUserId","actorName","actorEmail","actorImage","createdAt","editedAt","occurredAt"],"type":"object"},"CrmActivityKind":{"enum":["note","system","automated"],"type":"string"},"CrmActivityList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmActivityEntry"},"type":"array"}},"required":["data"],"type":"object"},"CrmActivityReportResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmReportActivity"}},"required":["data"],"type":"object"},"CrmAddContactResult":{"properties":{"data":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}},"required":["data"],"type":"object"},"CrmAddListMemberResult":{"properties":{"data":{"properties":{"added":{"type":"boolean"},"member":{"$ref":"#/components/schemas/CrmListMember"}},"required":["added","member"],"type":"object"}},"required":["data"],"type":"object"},"CrmAddMembersBulkResult":{"properties":{"data":{"properties":{"added":{"type":"number"},"addedEntityIds":{"items":{"type":"string"},"type":"array"},"createdEntityIds":{"items":{"type":"string"},"type":"array"},"enrichJobId":{"type":"string"},"total":{"type":"number"}},"required":["added","total","addedEntityIds","createdEntityIds"],"type":"object"}},"required":["data"],"type":"object"},"CrmAddNoteResult":{"properties":{"data":{"properties":{"id":{"type":"string"},"parentId":{"nullable":true,"type":"string"}},"required":["id","parentId"],"type":"object"}},"required":["data"],"type":"object"},"CrmAddRecordResult":{"properties":{"data":{"properties":{"added":{"type":"boolean"},"member":{"$ref":"#/components/schemas/CrmListMember"}},"required":["added","member"],"type":"object"}},"required":["data"],"type":"object"},"CrmAddRecordsBulkResult":{"properties":{"data":{"properties":{"added":{"type":"number"},"addedEntityIds":{"items":{"type":"string"},"type":"array"},"createdEntityIds":{"items":{"type":"string"},"type":"array"},"enrichJobId":{"type":"string"},"total":{"type":"number"}},"required":["added","total","addedEntityIds","createdEntityIds"],"type":"object"}},"required":["data"],"type":"object"},"CrmApplyListMiUpdatesResult":{"properties":{"data":{"properties":{"applied":{"description":"Fields persisted in total.","type":"number"},"results":{"items":{"properties":{"applied":{"type":"number"},"entityId":{"type":"string"},"error":{"enum":["not_in_list","invalid_phone"],"type":"string"}},"required":["entityId","applied"],"type":"object"},"type":"array"}},"required":["applied","results"],"type":"object"}},"required":["data"],"type":"object"},"CrmApplyMiUpdatesResult":{"properties":{"data":{"properties":{"applied":{"type":"number"}},"required":["applied"],"type":"object"}},"required":["data"],"type":"object"},"CrmApplyTemplateBody":{"properties":{"libraryTemplateId":{"type":"string"},"templateId":{"type":"string"}},"type":"object"},"CrmApplyTemplateResult":{"properties":{"data":{"properties":{"applied":{"items":{"$ref":"#/components/schemas/CrmCustomField"},"type":"array"},"objectTypeMismatch":{"type":"boolean"},"skipped":{"items":{"type":"string"},"type":"array"}},"required":["applied","skipped"],"type":"object"}},"required":["data"],"type":"object"},"CrmCall":{"properties":{"aiActions":{"items":{"$ref":"#/components/schemas/CrmCallAiAction"},"nullable":true,"type":"array"},"aiAnalyzedAt":{"nullable":true,"type":"number"},"aiLabel":{"nullable":true,"type":"string"},"aiSentiment":{"enum":["positive","neutral","negative",null],"nullable":true,"type":"string"},"aiSummary":{"nullable":true,"type":"string"},"answeredBy":{"enum":["human","machine","fax","unknown",null],"nullable":true,"type":"string"},"createdAt":{"type":"number"},"durationSeconds":{"nullable":true,"type":"number"},"endedAt":{"nullable":true,"type":"number"},"endedBy":{"enum":["caller","remote","system",null],"nullable":true,"type":"string"},"entityId":{"type":"string"},"fromNumber":{"type":"string"},"id":{"type":"string"},"organizationId":{"type":"string"},"recordingEnabled":{"type":"boolean"},"recordingSid":{"nullable":true,"type":"string"},"startedAt":{"nullable":true,"type":"number"},"status":{"type":"string"},"toNumber":{"type":"string"},"transcript":{"items":{"$ref":"#/components/schemas/CrmTranscriptSentence"},"nullable":true,"type":"array"},"transcriptSid":{"nullable":true,"type":"string"},"transcriptStatus":{"enum":["pending","processing","completed","failed","absent","voicemail",null],"nullable":true,"type":"string"},"twilioCallSid":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["id","organizationId","entityId","userId","toNumber","fromNumber","twilioCallSid","status","durationSeconds","startedAt","endedAt","endedBy","answeredBy","recordingEnabled","recordingSid","transcriptSid","transcriptStatus","transcript","aiLabel","aiSummary","aiSentiment","aiActions","aiAnalyzedAt","createdAt"],"type":"object"},"CrmCallAiAction":{"properties":{"dueInDays":{"type":"number"},"durationMinutes":{"type":"number"},"startInDays":{"type":"number"},"title":{"type":"string"},"type":{"enum":["task","meeting"],"type":"string"}},"required":["type","title"],"type":"object"},"CrmCallAnalysisResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmCallAnalyzeResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmCallTranscribeResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmCallTranscriptResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmCallerId":{"properties":{"createdAt":{"type":"number"},"friendlyName":{"nullable":true,"type":"string"},"id":{"type":"string"},"isDefault":{"type":"boolean"},"phoneNumber":{"type":"string"},"status":{"enum":["pending","verified","failed"],"type":"string"}},"required":["id","phoneNumber","friendlyName","status","isDefault","createdAt"],"type":"object"},"CrmCallerIdActionResult":{"properties":{"data":{"properties":{"callerId":{"allOf":[{"$ref":"#/components/schemas/CrmCallerId"},{"nullable":true}]},"validationCode":{"nullable":true,"type":"string"}},"required":["callerId"],"type":"object"}},"required":["data"],"type":"object"},"CrmCallerIdList":{"properties":{"data":{"properties":{"callerIds":{"items":{"$ref":"#/components/schemas/CrmCallerId"},"type":"array"},"configured":{"type":"boolean"}},"required":["callerIds","configured"],"type":"object"}},"required":["data"],"type":"object"},"CrmContactKind":{"enum":["phone","email","social","address","website","facebook","linkedin","x","zillow","realtor","youtube","instagram"],"type":"string"},"CrmContactSeed":{"properties":{"isPrimary":{"type":"boolean"},"kind":{"enum":["phone","email","social","address","website","facebook","linkedin","x","zillow","realtor","youtube","instagram"],"type":"string"},"label":{"nullable":true,"type":"string"},"value":{"nullable":true}},"required":["kind"],"type":"object"},"CrmCreateListFieldResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCustomField"}},"required":["data"],"type":"object"},"CrmCreateObjectFieldResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCustomField"}},"required":["data"],"type":"object"},"CrmCreateRecordResult":{"properties":{"data":{"properties":{"created":{"type":"boolean"}},"required":["created"],"type":"object"}},"required":["data"],"type":"object"},"CrmCreateTemplateResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmTemplateWithFields"}},"required":["data"],"type":"object"},"CrmCustomField":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"id":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"listId":{"nullable":true,"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"options":{"items":{"$ref":"#/components/schemas/CrmCustomFieldOption"},"nullable":true,"type":"array"},"scope":{"enum":["object","list"],"type":"string"},"sortOrder":{"type":"number"},"type":{"$ref":"#/components/schemas/CrmCustomFieldType"}},"required":["id","scope","objectType","listId","key","label","type","options","config","sortOrder"],"type":"object"},"CrmCustomFieldList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmCustomField"},"type":"array"}},"required":["data"],"type":"object"},"CrmCustomFieldOption":{"properties":{"color":{"type":"string"},"id":{"type":"string"},"label":{"type":"string"},"outcome":{"description":"Reporting classification (`status` fields only). Absent = in-progress. Seed ids `won`/`lost` classify by convention when unset.","enum":["won","lost"],"type":"string"}},"required":["id","label"],"type":"object"},"CrmCustomFieldType":{"enum":["text","number","currency","date","select","multiselect","url","rating","checkbox","status","tags"],"type":"string"},"CrmCustomValue":{"properties":{"bool":{"nullable":true,"type":"boolean"},"date":{"minimum":0,"nullable":true,"type":"integer"},"multi":{"items":{"type":"string"},"nullable":true,"type":"array"},"num":{"nullable":true,"type":"number"},"text":{"nullable":true,"type":"string"}},"type":"object"},"CrmCustomValueResult":{"properties":{"data":{"anyOf":[{"additionalProperties":{"$ref":"#/components/schemas/CrmCustomValue"},"type":"object"},{"additionalProperties":{"additionalProperties":{"$ref":"#/components/schemas/CrmCustomValue"},"type":"object"},"type":"object"}]}},"required":["data"],"type":"object"},"CrmDeclineMiUpdateResult":{"properties":{"data":{"properties":{"declined":{"items":{"type":"string"},"type":"array"}},"required":["declined"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteCallerIdResult":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteListFieldResult":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteNoteResult":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteObjectFieldResult":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteRecordResult":{"properties":{"data":{"properties":{"removed":{"type":"boolean"}},"required":["removed"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteRecordsResult":{"properties":{"data":{"properties":{"removed":{"items":{"type":"string"},"type":"array"},"skipped":{"items":{"type":"string"},"type":"array"}},"required":["removed","skipped"],"type":"object"}},"required":["data"],"type":"object"},"CrmDeleteTemplateResult":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmDerivedLocation":{"properties":{"cbsaCode":{"type":"string"},"county":{"type":"string"},"countyFips":{"type":"string"}},"type":"object"},"CrmDescribeOnAddResult":{"properties":{"data":{"properties":{"needsDescriptionEntityIds":{"items":{"type":"string"},"type":"array"}},"required":["needsDescriptionEntityIds"],"type":"object"}},"required":["data"],"type":"object"},"CrmDismissListMiUpdatesResult":{"properties":{"data":{"properties":{"dismissed":{"items":{"type":"string"},"type":"array"},"notInList":{"items":{"type":"string"},"type":"array"}},"required":["dismissed","notInList"],"type":"object"}},"required":["data"],"type":"object"},"CrmDismissMiUpdatesResult":{"properties":{"data":{"properties":{"dismissed":{"type":"boolean"}},"required":["dismissed"],"type":"object"}},"required":["data"],"type":"object"},"CrmDisplay":{"properties":{"branchName":{"type":"string"},"branchNmlsId":{"type":"string"},"cbsaCode":{"type":"string"},"city":{"type":"string"},"companyName":{"type":"string"},"companyNmlsId":{"type":"string"},"contactCheckedAt":{"type":"number"},"county":{"type":"string"},"countyFips":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"state":{"type":"string"},"subtitle":{"type":"string"},"units":{"type":"number"},"volume":{"type":"number"},"zip":{"type":"string"}},"required":["name"],"type":"object"},"CrmEditLoggedActivityResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmEditNoteResult":{"properties":{"data":{"properties":{"entityId":{"nullable":true,"type":"string"},"previousBodyHtml":{"nullable":true,"type":"string"},"updated":{"type":"boolean"}},"required":["updated","entityId","previousBodyHtml"],"type":"object"}},"required":["data"],"type":"object"},"CrmEmailAttachment":{"properties":{"base64":{"type":"string"},"filename":{"type":"string"},"mimeType":{"type":"string"}},"required":["filename","mimeType","base64"],"type":"object"},"CrmEmailRecipient":{"properties":{"email":{"type":"string"},"entityId":{"type":"string"},"isPrimary":{"type":"boolean"},"label":{"nullable":true,"type":"string"},"name":{"type":"string"}},"required":["entityId","name","email","label","isPrimary"],"type":"object"},"CrmEmailRecipientArray":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmEmailRecipient"},"type":"array"}},"required":["data"],"type":"object"},"CrmEmailSendBody":{"properties":{"attachments":{"items":{"$ref":"#/components/schemas/CrmEmailAttachment"},"type":"array"},"bcc":{"items":{"type":"string"},"type":"array"},"cc":{"items":{"type":"string"},"type":"array"},"entityId":{"type":"string"},"html":{"type":"string"},"organizationId":{"type":"string"},"provider":{"$ref":"#/components/schemas/CrmMailProvider"},"subject":{"type":"string"},"text":{"type":"string"},"to":{"items":{"type":"string"},"minItems":1,"type":"array"}},"required":["entityId","to","subject","html","text"],"type":"object"},"CrmEmailSendResult":{"properties":{"provider":{"$ref":"#/components/schemas/CrmMailProvider"},"result":{"enum":["sent","needs-connect"],"type":"string"}},"required":["result","provider"],"type":"object"},"CrmEmailUpstreamError":{"properties":{"detail":{"type":"string"},"result":{"enum":["error"],"type":"string"},"status":{"type":"number"}},"required":["result","status","detail"],"type":"object"},"CrmEnrichmentContact":{"properties":{"isPrimary":{"type":"boolean"},"kind":{"$ref":"#/components/schemas/CrmContactKind"},"label":{"nullable":true,"type":"string"},"value":{"nullable":true}},"required":["kind"],"type":"object"},"CrmEnrichmentOverrideSources":{"description":"Origin of each `overrides` value: \"mm\" (ours) or \"imported\" (the customer's). An \"mm\" value the record already renders from the mirror is NOT pinned, so the record keeps tracking. Omit to pin everything.","properties":{"company":{"type":"string"},"companyType":{"type":"string"},"title":{"type":"string"}},"type":"object"},"CrmEnrichmentOverrides":{"properties":{"company":{"type":"string"},"companyType":{"type":"string"},"title":{"type":"string"}},"type":"object"},"CrmEnrichmentResult":{"properties":{"data":{"properties":{"linked":{"type":"boolean"},"seeded":{"type":"number"}},"required":["linked","seeded"],"type":"object"}},"required":["data"],"type":"object"},"CrmEntityType":{"enum":["lo","agent","company","branch"],"type":"string"},"CrmFilterMembersResult":{"properties":{"data":{"properties":{"entityIds":{"items":{"type":"string"},"type":"array"}},"required":["entityIds"],"type":"object"}},"required":["data"],"type":"object"},"CrmGenerateDescriptionResult":{"properties":{"data":{"properties":{"description":{"nullable":true,"type":"string"}},"required":["description"],"type":"object"}},"required":["data"],"type":"object"},"CrmGrantListAccessResult":{"properties":{"data":{"properties":{"granted":{"type":"boolean"}},"required":["granted"],"type":"object"}},"required":["data"],"type":"object"},"CrmGrantRecordAccessRequestResult":{"properties":{"data":{"properties":{"granted":{"type":"boolean"},"status":{"enum":["granted"],"type":"string"}},"required":["granted","status"],"type":"object"}},"required":["data"],"type":"object"},"CrmGrantRecordAccessResult":{"properties":{"data":{"properties":{"granted":{"type":"boolean"}},"required":["granted"],"type":"object"}},"required":["data"],"type":"object"},"CrmHangupCallResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmImportAccepted":{"properties":{"data":{"properties":{"jobId":{"description":"Poll GET /crm/import/{jobId} for progress + per-row errors.","type":"string"}},"required":["jobId"],"type":"object"}},"required":["data"],"type":"object"},"CrmImportErrorCode":{"description":"Failure reason on a failed row; drives friendly client copy. Absent on success.","enum":["MISSING_NAME","RECORD_NOT_FOUND","WRONG_OBJECT_TYPE","NO_ACCESS","UNKNOWN_FIELD","INVALID","INTERNAL"],"type":"string"},"CrmImportJob":{"properties":{"data":{"properties":{"completedAt":{"type":"string"},"error":{"type":"string"},"errorsUrl":{"type":"string"},"failed":{"type":"number"},"jobId":{"type":"string"},"resultsUrl":{"type":"string"},"startedAt":{"type":"string"},"status":{"enum":["queued","running","completed","failed","cancelled"],"type":"string"},"succeeded":{"type":"number"},"total":{"type":"number"}},"required":["jobId","status","total","succeeded","failed"],"type":"object"}},"required":["data"],"type":"object"},"CrmImportPhone":{"properties":{"e164":{"type":"string"},"raw":{"type":"string"}},"required":["raw","e164"],"type":"object"},"CrmImportResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmImportSummary"}},"required":["data"],"type":"object"},"CrmImportRow":{"properties":{"address":{"type":"string"},"city":{"type":"string"},"company":{"description":"Employer override for people rows; ignored on companies imports.","type":"string"},"county":{"type":"string"},"countyFips":{"type":"string"},"customValues":{"additionalProperties":{"$ref":"#/components/schemas/CrmCustomValue"},"type":"object"},"email":{"type":"string"},"emails":{"description":"Additional emails in submitted order (first non-duplicate becomes primary via oldest-wins).","items":{"type":"string"},"maxItems":5,"type":"array"},"entityId":{"description":"Set to update an existing record; omit to create one.","type":"string"},"facebook":{"type":"string"},"instagram":{"type":"string"},"link":{"allOf":[{"$ref":"#/components/schemas/CrmLink"},{"description":"Match pointer; an MM-sourced link populates the entity mirror."}]},"linkedin":{"type":"string"},"location":{"type":"string"},"name":{"type":"string"},"note":{"description":"Plain-text timeline note appended to the record's activity feed, authored by the importing user. Distinct from `notes` (the Description scalar).","maxLength":2000,"type":"string"},"notes":{"type":"string"},"ownerUserId":{"description":"Working owner (member userId) for this CREATED record; overrides the batch-level ownerUserId. Ignored on update rows (entityId set) — import never reassigns an existing record's owner. Assigning any owner other than the caller requires an org admin.","type":"string"},"phone":{"$ref":"#/components/schemas/CrmImportPhone"},"phones":{"description":"Additional phones in submitted order.","items":{"$ref":"#/components/schemas/CrmImportPhone"},"maxItems":5,"type":"array"},"realtor":{"type":"string"},"state":{"type":"string"},"status":{"type":"string"},"subtitle":{"type":"string"},"title":{"description":"Role title override for people rows (the record's Title field, column and filter) — distinct from `subtitle`, the display line under the name. Trimmed; blank reads as absent. Overwrites on update rows. Ignored on companies imports.","type":"string"},"website":{"type":"string"},"x":{"type":"string"},"youtube":{"type":"string"},"zillow":{"type":"string"},"zip":{"type":"string"}},"type":"object"},"CrmImportRowResult":{"properties":{"code":{"$ref":"#/components/schemas/CrmImportErrorCode"},"entityId":{"type":"string"},"error":{"type":"string"},"outcome":{"enum":["created","updated","failed"],"type":"string"},"row":{"type":"number"}},"required":["row","outcome"],"type":"object"},"CrmImportSummary":{"properties":{"created":{"type":"number"},"enrichJobId":{"type":"string"},"failed":{"type":"number"},"results":{"items":{"$ref":"#/components/schemas/CrmImportRowResult"},"type":"array"},"total":{"type":"number"},"updated":{"type":"number"}},"required":["total","created","updated","failed","results"],"type":"object"},"CrmLenderChannels":{"properties":{"data":{"properties":{"byLo":{"additionalProperties":{"properties":{"channel":{"enum":["Bank","Credit Union","Broker","Retail","Unknown"],"type":"string"},"companyName":{"type":"string"},"companyNmlsId":{"type":"string"}},"required":["companyNmlsId","companyName","channel"],"type":"object"},"type":"object"}},"required":["byLo"],"type":"object"}},"required":["data"],"type":"object"},"CrmLink":{"nullable":true,"properties":{"entityId":{"type":"string"},"mmaId":{"type":"string"},"nmlsId":{"type":"string"},"propertyId":{"type":"string"},"source":{"enum":["mm","manual"],"type":"string"}},"required":["source","entityId"],"type":"object"},"CrmLinkRecordResult":{"properties":{"data":{"properties":{"linked":{"type":"boolean"}},"required":["linked"],"type":"object"}},"required":["data"],"type":"object"},"CrmList":{"properties":{"canManage":{"type":"boolean"},"createdAt":{"type":"number"},"hasMember":{"type":"boolean"},"id":{"type":"string"},"memberCount":{"type":"number"},"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"visibility":{"enum":["private","organization","shared"],"type":"string"}},"required":["id","name","objectType","visibility","memberCount","createdAt"],"type":"object"},"CrmListArray":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmList"},"type":"array"}},"required":["data"],"type":"object"},"CrmListAssignee":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"CrmListAssigneeList":{"properties":{"data":{"properties":{"assignees":{"items":{"$ref":"#/components/schemas/CrmListAssignee"},"type":"array"}},"required":["assignees"],"type":"object"}},"required":["data"],"type":"object"},"CrmListCreateResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmList"}},"required":["data"],"type":"object"},"CrmListDeleteResult":{"properties":{"data":{"properties":{"ok":{"type":"boolean"}},"required":["ok"],"type":"object"}},"required":["data"],"type":"object"},"CrmListFieldsResult":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmCustomField"},"type":"array"}},"required":["data"],"type":"object"},"CrmListMember":{"nullable":true,"properties":{"addedAt":{"type":"number"},"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"lastActivityAt":{"nullable":true,"type":"number"},"overrides":{"$ref":"#/components/schemas/CrmOverlay"},"ownerUserId":{"nullable":true,"type":"string"}},"required":["entityId","entityType","addedAt","display"],"type":"object"},"CrmListMembershipEntry":{"properties":{"canManage":{"type":"boolean"},"id":{"type":"string"},"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"}},"required":["id","name","objectType","canManage"],"type":"object"},"CrmListMemberships":{"properties":{"memberships":{"additionalProperties":{"items":{"$ref":"#/components/schemas/CrmListMembershipEntry"},"type":"array"},"type":"object"}},"required":["memberships"],"type":"object"},"CrmListMembershipsResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmListMemberships"}},"required":["data"],"type":"object"},"CrmListMiUpdatesResult":{"properties":{"data":{"properties":{"failedEntityIds":{"description":"Members whose check failed transiently; retry them with `getCrmMiUpdates` or a later pass.","items":{"type":"string"},"type":"array"},"fieldSetVersion":{"type":"number"},"nextCursor":{"description":"Pass back as `cursor` for the next page; null once every member has been scanned. A page can return zero `records` and still have a `nextCursor` — keep paging until it is null.","nullable":true,"type":"string"},"records":{"items":{"properties":{"checkedAt":{"description":"Epoch ms of this check.","type":"number"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"inputsChanged":{"description":"The Market-Insights data or the record changed since the previous check (true when the record had never been checked).","type":"boolean"},"name":{"nullable":true,"type":"string"},"status":{"description":"`needs_review`: at least one proposal the user has not reviewed. `snoozed`: every proposal was already reviewed within the check window (only returned with `includeSnoozed: true`).","enum":["needs_review","snoozed"],"type":"string"},"updates":{"items":{"properties":{"action":{"enum":["add","overwrite"],"type":"string"},"current":{"nullable":true,"type":"string"},"field":{"type":"string"},"id":{"type":"string"},"incoming":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"},"linkage":{"properties":{"companyNmlsId":{"type":"string"},"office":{"$ref":"#/components/schemas/CrmOverrideOffice"}},"type":"object"},"previouslyReviewed":{"description":"True when the user already reviewed (applied around or dismissed) this exact proposal inside the 31-day check window. A record is returned only when at least one of its proposals is new, unless `includeSnoozed` is set.","type":"boolean"},"seenKey":{"type":"string"},"store":{"enum":["override","contact"],"type":"string"}},"required":["id","field","label","store","current","incoming","action","seenKey","previouslyReviewed"],"type":"object"},"type":"array"}},"required":["entityId","entityType","name","status","inputsChanged","updates","checkedAt"],"type":"object"},"type":"array"},"scanned":{"description":"List members evaluated by this page.","type":"number"},"summary":{"description":"Tally over every member this page scanned.","properties":{"failed":{"type":"number"},"needsReview":{"type":"number"},"snoozed":{"type":"number"},"unavailable":{"description":"Members with no Market-Insights data to compare against (manual / unmatched records).","type":"number"},"upToDate":{"type":"number"}},"required":["needsReview","snoozed","upToDate","unavailable","failed"],"type":"object"}},"required":["records","scanned","summary","failedEntityIds","nextCursor","fieldSetVersion"],"type":"object"}},"required":["data"],"type":"object"},"CrmListShare":{"properties":{"createdAt":{"type":"number"},"email":{"nullable":true,"type":"string"},"id":{"type":"string"},"image":{"nullable":true,"type":"string"},"invitedByName":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"permission":{"enum":["owner","editor","viewer"],"type":"string"},"userId":{"type":"string"}},"required":["id","userId","name","email","image","permission","invitedByName","createdAt"],"type":"object"},"CrmListSharing":{"nullable":true,"properties":{"canManageSharing":{"type":"boolean"},"orgWidePermission":{"enum":["viewer","editor"],"type":"string"},"owner":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"ownerUserId":{"type":"string"},"shares":{"items":{"$ref":"#/components/schemas/CrmListShare"},"type":"array"},"visibility":{"enum":["private","organization","shared"],"type":"string"}},"required":["visibility","ownerUserId","owner","canManageSharing","orgWidePermission","shares"],"type":"object"},"CrmListSharingResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmListSharing"}},"required":["data"],"type":"object"},"CrmListUpdateBody":{"properties":{"name":{"type":"string"},"orgWidePermission":{"enum":["viewer","editor"],"type":"string"},"visibility":{"enum":["private","organization","shared"],"type":"string"}},"type":"object"},"CrmListUpdateResult":{"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/CrmList"},{"nullable":true}]}},"required":["data"],"type":"object"},"CrmListWithMembers":{"properties":{"data":{"nullable":true,"properties":{"list":{"$ref":"#/components/schemas/CrmList"},"members":{"items":{"$ref":"#/components/schemas/CrmListMember"},"type":"array"}},"required":["list","members"],"type":"object"}},"required":["data"],"type":"object"},"CrmLoLoanMix":{"properties":{"data":{"properties":{"mix":{"items":{"properties":{"percentage":{"type":"number"},"type":{"type":"string"}},"required":["type","percentage"],"type":"object"},"type":"array"},"top":{"nullable":true,"type":"string"}},"required":["mix","top"],"type":"object"}},"required":["data"],"type":"object"},"CrmLoMomentum":{"properties":{"data":{"additionalProperties":{"properties":{"priorUnits":{"type":"number"},"recentUnits":{"type":"number"}},"required":["recentUnits","priorUnits"],"type":"object"},"type":"object"}},"required":["data"],"type":"object"},"CrmLoSponsorLocation":{"properties":{"data":{"additionalProperties":{"properties":{"location":{"type":"string"},"sponsored":{"type":"boolean"}},"required":["sponsored"],"type":"object"},"type":"object"}},"required":["data"],"type":"object"},"CrmLogActivityResult":{"properties":{"data":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}},"required":["data"],"type":"object"},"CrmLoggedActivityType":{"enum":["call","meeting","email","task"],"type":"string"},"CrmMailProvider":{"enum":["google","microsoft",null],"nullable":true,"type":"string"},"CrmManualRecordResult":{"properties":{"data":{"properties":{"added":{"type":"boolean"},"entityId":{"type":"string"}},"required":["entityId","added"],"type":"object"}},"required":["data"],"type":"object"},"CrmMatchCandidate":{"properties":{"company":{"type":"string"},"location":{"type":"string"},"mmaId":{"type":"string"},"name":{"type":"string"},"nmlsId":{"type":"string"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["name"],"type":"object"},"CrmMatchCandidates":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmMatchCandidate"},"type":"array"}},"required":["data"],"type":"object"},"CrmMeeting":{"properties":{"attendees":{"items":{"$ref":"#/components/schemas/CrmMeetingAttendee"},"type":"array"},"calendarEventId":{"nullable":true,"type":"string"},"calendarHtmlLink":{"nullable":true,"type":"string"},"calendarId":{"nullable":true,"type":"string"},"calendarProvider":{"$ref":"#/components/schemas/CrmMeetingProvider"},"calendarSyncedAt":{"nullable":true,"type":"number"},"cancelReason":{"$ref":"#/components/schemas/CrmMeetingCancelReason"},"cancelledAt":{"nullable":true,"type":"number"},"completedAt":{"nullable":true,"type":"number"},"completedBy":{"$ref":"#/components/schemas/CrmMeetingCompletedBy"},"createdAt":{"type":"number"},"createdByUserId":{"type":"string"},"description":{"nullable":true,"type":"string"},"endAt":{"type":"number"},"entityId":{"type":"string"},"icalUid":{"nullable":true,"type":"string"},"id":{"type":"string"},"listId":{"nullable":true,"type":"string"},"location":{"nullable":true,"type":"string"},"startAt":{"type":"number"},"status":{"$ref":"#/components/schemas/CrmMeetingStatus"},"timezone":{"nullable":true,"type":"string"},"title":{"type":"string"}},"required":["id","entityId","createdByUserId","title","description","startAt","endAt","timezone","location","status","listId","calendarProvider","calendarId","calendarEventId","icalUid","calendarHtmlLink","calendarSyncedAt","completedAt","completedBy","cancelledAt","cancelReason","createdAt","attendees"],"type":"object"},"CrmMeetingAttendee":{"properties":{"email":{"type":"string"},"id":{"type":"string"},"isOrganizer":{"type":"boolean"},"kind":{"enum":["record","teammate","external"],"type":"string"},"name":{"nullable":true,"type":"string"},"responseStatus":{"enum":["needsAction","accepted","declined","tentative"],"type":"string"},"userId":{"nullable":true,"type":"string"}},"required":["id","kind","userId","email","name","responseStatus","isOrganizer"],"type":"object"},"CrmMeetingCancelReason":{"enum":["cancelled","no_show",null],"nullable":true,"type":"string"},"CrmMeetingCompletedBy":{"enum":["user","system",null],"nullable":true,"type":"string"},"CrmMeetingCreated":{"properties":{"data":{"$ref":"#/components/schemas/CrmMeeting"},"needsConnect":{"$ref":"#/components/schemas/CrmMeetingProvider"}},"required":["data"],"type":"object"},"CrmMeetingDeleted":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmMeetingList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmMeeting"},"type":"array"}},"required":["data"],"type":"object"},"CrmMeetingProvider":{"enum":["google","microsoft",null],"nullable":true,"type":"string"},"CrmMeetingReconcileResult":{"properties":{"data":{"properties":{"applied":{"type":"number"}},"required":["applied"],"type":"object"}},"required":["data"],"type":"object"},"CrmMeetingStatus":{"enum":["scheduled","cancelled","completed"],"type":"string"},"CrmMeetingUpdateResult":{"properties":{"needsConnect":{"$ref":"#/components/schemas/CrmMeetingProvider"},"updated":{"type":"boolean"}},"required":["updated"],"type":"object"},"CrmMeetingUpdated":{"properties":{"data":{"$ref":"#/components/schemas/CrmMeetingUpdateResult"}},"required":["data"],"type":"object"},"CrmMemberFilter":{"properties":{"companyNmlsId":{"items":{"type":"string"},"type":"array"},"entityType":{"items":{"$ref":"#/components/schemas/CrmEntityType"},"type":"array"},"state":{"items":{"type":"string"},"type":"array"},"units":{"properties":{"gte":{"type":"number"},"lte":{"type":"number"}},"type":"object"},"volume":{"properties":{"gte":{"type":"number"},"lte":{"type":"number"}},"type":"object"}},"type":"object"},"CrmMemberIdsResult":{"properties":{"data":{"properties":{"entityIds":{"items":{"type":"string"},"type":"array"},"truncated":{"type":"boolean"}},"required":["entityIds","truncated"],"type":"object"}},"required":["data"],"type":"object"},"CrmMembersList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmListMember"},"type":"array"}},"required":["data"],"type":"object"},"CrmMentionRecord":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"location":{"nullable":true,"type":"string"},"name":{"type":"string"},"subtitle":{"nullable":true,"type":"string"}},"required":["entityId","entityType","name","subtitle","location"],"type":"object"},"CrmMentionSearch":{"properties":{"data":{"properties":{"results":{"items":{"$ref":"#/components/schemas/CrmMentionRecord"},"type":"array"}},"required":["results"],"type":"object"}},"required":["data"],"type":"object"},"CrmMiUpdatesResult":{"properties":{"data":{"properties":{"checkedAt":{"nullable":true,"type":"number"},"updates":{"items":{"properties":{"action":{"enum":["add","overwrite"],"type":"string"},"current":{"nullable":true,"type":"string"},"field":{"type":"string"},"id":{"type":"string"},"incoming":{"type":"string"},"kind":{"type":"string"},"label":{"type":"string"},"linkage":{"properties":{"companyNmlsId":{"type":"string"},"office":{"$ref":"#/components/schemas/CrmOverrideOffice"}},"type":"object"},"seenKey":{"type":"string"},"store":{"enum":["override","contact"],"type":"string"}},"required":["id","field","label","store","current","incoming","action","seenKey"],"type":"object"},"type":"array"}},"required":["updates","checkedAt"],"type":"object"}},"required":["data"],"type":"object"},"CrmObjectType":{"enum":["people","companies"],"type":"string"},"CrmOrgMember":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"CrmOrgMemberList":{"properties":{"data":{"properties":{"members":{"items":{"$ref":"#/components/schemas/CrmOrgMember"},"type":"array"}},"required":["members"],"type":"object"}},"required":["data"],"type":"object"},"CrmOutcomesReportResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmReportOutcomes"}},"required":["data"],"type":"object"},"CrmOverlay":{"additionalProperties":{"type":"string"},"properties":{"office":{"$ref":"#/components/schemas/CrmOverrideOffice"}},"type":"object"},"CrmOverrideField":{"enum":["status","notes","title","company","companyType","firstName","lastName","location","city","state","zip","companyNmlsId","office"],"type":"string"},"CrmOverrideOffice":{"properties":{"city":{"type":"string"},"key":{"minLength":1,"type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"name":{"type":"string"},"state":{"type":"string"}},"required":["key"],"type":"object"},"CrmOverridesMap":{"properties":{"data":{"additionalProperties":{"$ref":"#/components/schemas/CrmOverlay"},"type":"object"}},"required":["data"],"type":"object"},"CrmPatchContactBody":{"oneOf":[{"properties":{"id":{"type":"string"},"isPrimary":{"type":"boolean"},"label":{"nullable":true,"type":"string"},"op":{"enum":["update"],"type":"string"},"value":{"nullable":true}},"required":["op","id"],"type":"object"},{"properties":{"entityId":{"type":"string"},"kind":{"$ref":"#/components/schemas/CrmContactKind"},"mmKey":{"type":"string"},"op":{"enum":["suppress"],"type":"string"}},"required":["op","entityId","kind","mmKey"],"type":"object"}]},"CrmPatchContactResult":{"properties":{"data":{"properties":{"id":{"type":"string"},"updated":{"type":"boolean"}},"type":"object"}},"required":["data"],"type":"object"},"CrmPlaceCallResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmPollCallResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmCall"}},"required":["data"],"type":"object"},"CrmProductionEnrichJob":{"properties":{"data":{"properties":{"completedAt":{"type":"string"},"error":{"type":"string"},"failed":{"type":"number"},"jobId":{"type":"string"},"startedAt":{"type":"string"},"status":{"enum":["queued","running","completed","failed","cancelled"],"type":"string"},"succeeded":{"type":"number"},"total":{"type":"number"}},"required":["jobId","status","total","succeeded","failed"],"type":"object"}},"required":["data"],"type":"object"},"CrmProfile":{"properties":{"data":{"nullable":true}},"type":"object"},"CrmRecordAccessFacts":{"properties":{"data":{"properties":{"accessibleUserIds":{"items":{"type":"string"},"type":"array"},"canManageShares":{"type":"boolean"},"everyone":{"type":"boolean"}},"required":["canManageShares","everyone","accessibleUserIds"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordAccessRequestInfo":{"properties":{"data":{"properties":{"alreadyHasAccess":{"type":"boolean"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"recordName":{"type":"string"},"requesterName":{"nullable":true,"type":"string"},"status":{"enum":["pending","granted","dismissed"],"type":"string"}},"required":["requesterName","recordName","entityType","status","alreadyHasAccess"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordConnections":{"properties":{"data":{"properties":{"colleagues":{"items":{"$ref":"#/components/schemas/CrmRelatedRecord"},"type":"array"},"inCrm":{"items":{"type":"string"},"type":"array"}},"required":["inCrm","colleagues"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordRef":{"properties":{"data":{"nullable":true,"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"}},"required":["entityId","entityType"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordRequestAccessResult":{"properties":{"data":{"properties":{"ownerName":{"nullable":true,"type":"string"},"status":{"enum":["requested","already_requested","already_has_access"],"type":"string"}},"required":["status","ownerName"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordSearchResult":{"properties":{"data":{"properties":{"ids":{"items":{"type":"string"},"type":"array"}},"required":["ids"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordShare":{"properties":{"createdAt":{"type":"number"},"email":{"nullable":true,"type":"string"},"grantedByName":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"source":{"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image","source","grantedByName","createdAt"],"type":"object"},"CrmRecordShareList":{"properties":{"data":{"properties":{"canManageShares":{"type":"boolean"},"shares":{"items":{"$ref":"#/components/schemas/CrmRecordShare"},"type":"array"}},"required":["canManageShares","shares"],"type":"object"}},"required":["data"],"type":"object"},"CrmRecordShareableMember":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"CrmRecordShareableMemberList":{"properties":{"data":{"properties":{"members":{"items":{"$ref":"#/components/schemas/CrmRecordShareableMember"},"type":"array"}},"required":["members"],"type":"object"}},"required":["data"],"type":"object"},"CrmReferencedActivityEntry":{"allOf":[{"$ref":"#/components/schemas/CrmActivityEntry"},{"properties":{"sourceAccessible":{"type":"boolean"},"sourceEntityId":{"type":"string"},"sourceEntityType":{"$ref":"#/components/schemas/CrmEntityType"},"sourceHref":{"type":"string"},"sourceName":{"type":"string"}},"required":["sourceEntityId","sourceEntityType","sourceName","sourceHref","sourceAccessible"],"type":"object"}]},"CrmReferencedActivityList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmReferencedActivityEntry"},"type":"array"}},"required":["data"],"type":"object"},"CrmRefreshMirrorResult":{"properties":{"data":{"properties":{"display":{"allOf":[{"$ref":"#/components/schemas/CrmDisplay"},{"description":"The record's mirrored display after the attempt.","nullable":true}]},"refreshed":{"description":"Whether the mirrored row actually CHANGED. `false` when it was already current, when the record has no resolvable MM link, or when the refresh could not run — all of which are normal and none of which are errors.","type":"boolean"}},"required":["refreshed","display"],"type":"object"}},"required":["data"],"type":"object"},"CrmRelatedRecord":{"properties":{"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"listNames":{"items":{"type":"string"},"type":"array"}},"required":["entityId","entityType","display","listNames"],"type":"object"},"CrmRemoveContactResult":{"properties":{"data":{"properties":{"removed":{"type":"boolean"}},"required":["removed"],"type":"object"}},"required":["data"],"type":"object"},"CrmRemoveListMemberResult":{"properties":{"data":{"properties":{"removed":{"type":"boolean"}},"required":["removed"],"type":"object"}},"required":["data"],"type":"object"},"CrmReportActivity":{"properties":{"from":{"type":"number"},"to":{"type":"number"},"users":{"items":{"$ref":"#/components/schemas/CrmReportActivityUser"},"type":"array"}},"required":["from","to","users"],"type":"object"},"CrmReportActivityDay":{"properties":{"calls":{"minimum":0,"type":"integer"},"callsConnected":{"minimum":0,"type":"integer"},"date":{"type":"string"},"emails":{"minimum":0,"type":"integer"},"meetingsCancelled":{"minimum":0,"type":"integer"},"meetingsCompleted":{"minimum":0,"type":"integer"},"meetingsNoShow":{"minimum":0,"type":"integer"},"meetingsScheduled":{"minimum":0,"type":"integer"},"notes":{"minimum":0,"type":"integer"},"recordsAdded":{"minimum":0,"type":"integer"},"recordsLost":{"minimum":0,"type":"integer"},"recordsWon":{"minimum":0,"type":"integer"},"talkTimeSeconds":{"minimum":0,"type":"integer"},"tasksCompleted":{"minimum":0,"type":"integer"},"tasksCreated":{"minimum":0,"type":"integer"},"voicemails":{"minimum":0,"type":"integer"}},"required":["date","calls","callsConnected","talkTimeSeconds","voicemails","notes","emails","tasksCreated","tasksCompleted","meetingsScheduled","meetingsCompleted","meetingsNoShow","meetingsCancelled","recordsAdded","recordsWon","recordsLost"],"type":"object"},"CrmReportActivityTotals":{"properties":{"calls":{"minimum":0,"type":"integer"},"callsConnected":{"minimum":0,"type":"integer"},"emails":{"minimum":0,"type":"integer"},"meetingsCancelled":{"minimum":0,"type":"integer"},"meetingsCompleted":{"minimum":0,"type":"integer"},"meetingsNoShow":{"minimum":0,"type":"integer"},"meetingsScheduled":{"minimum":0,"type":"integer"},"notes":{"minimum":0,"type":"integer"},"recordsAdded":{"minimum":0,"type":"integer"},"recordsLost":{"minimum":0,"type":"integer"},"recordsWon":{"minimum":0,"type":"integer"},"talkTimeSeconds":{"minimum":0,"type":"integer"},"tasksCompleted":{"minimum":0,"type":"integer"},"tasksCreated":{"minimum":0,"type":"integer"},"voicemails":{"minimum":0,"type":"integer"}},"required":["calls","callsConnected","talkTimeSeconds","voicemails","notes","emails","tasksCreated","tasksCompleted","meetingsScheduled","meetingsCompleted","meetingsNoShow","meetingsCancelled","recordsAdded","recordsWon","recordsLost"],"type":"object"},"CrmReportActivityUser":{"properties":{"days":{"description":"Ascending by date; all-zero days omitted (fill gaps client-side).","items":{"$ref":"#/components/schemas/CrmReportActivityDay"},"type":"array"},"previousTotals":{"properties":{"calls":{"minimum":0,"type":"integer"},"callsConnected":{"minimum":0,"type":"integer"},"emails":{"minimum":0,"type":"integer"},"meetingsCancelled":{"minimum":0,"type":"integer"},"meetingsCompleted":{"minimum":0,"type":"integer"},"meetingsNoShow":{"minimum":0,"type":"integer"},"meetingsScheduled":{"minimum":0,"type":"integer"},"notes":{"minimum":0,"type":"integer"},"recordsAdded":{"minimum":0,"type":"integer"},"recordsContacted":{"minimum":0,"type":"integer"},"recordsLost":{"minimum":0,"type":"integer"},"recordsWon":{"minimum":0,"type":"integer"},"talkTimeSeconds":{"minimum":0,"type":"integer"},"tasksCompleted":{"minimum":0,"type":"integer"},"tasksCreated":{"minimum":0,"type":"integer"},"voicemails":{"minimum":0,"type":"integer"}},"required":["calls","callsConnected","talkTimeSeconds","voicemails","notes","emails","tasksCreated","tasksCompleted","meetingsScheduled","meetingsCompleted","meetingsNoShow","meetingsCancelled","recordsAdded","recordsWon","recordsLost","recordsContacted"],"type":"object"},"recordsContacted":{"description":"Distinct records with ≥1 outreach touch in the period. Totals-only — never per day (distincts don't sum).","minimum":0,"type":"integer"},"totals":{"$ref":"#/components/schemas/CrmReportActivityTotals"},"userId":{"type":"string"}},"required":["userId","totals","recordsContacted","previousTotals","days"],"type":"object"},"CrmReportEffortPerWin":{"properties":{"avgCalls":{"nullable":true,"type":"number"},"avgDaysToWin":{"nullable":true,"type":"number"},"avgEmails":{"nullable":true,"type":"number"},"avgMeetings":{"nullable":true,"type":"number"},"avgTouches":{"nullable":true,"type":"number"},"wins":{"minimum":0,"type":"integer"}},"required":["wins","avgTouches","avgCalls","avgEmails","avgMeetings","avgDaysToWin"],"type":"object"},"CrmReportMilestones":{"properties":{"timeToConnect":{"properties":{"avgDays":{"nullable":true,"type":"number"},"medianDays":{"nullable":true,"type":"number"},"records":{"minimum":0,"type":"integer"}},"required":["records","medianDays","avgDays"],"type":"object"},"timeToFirstMeeting":{"properties":{"avgDays":{"nullable":true,"type":"number"},"medianDays":{"nullable":true,"type":"number"},"records":{"minimum":0,"type":"integer"}},"required":["records","medianDays","avgDays"],"type":"object"},"timeToFirstTouch":{"properties":{"avgDays":{"nullable":true,"type":"number"},"medianDays":{"nullable":true,"type":"number"},"records":{"minimum":0,"type":"integer"}},"required":["records","medianDays","avgDays"],"type":"object"},"timeToWin":{"properties":{"avgDays":{"nullable":true,"type":"number"},"medianDays":{"nullable":true,"type":"number"},"records":{"minimum":0,"type":"integer"}},"required":["records","medianDays","avgDays"],"type":"object"}},"required":["timeToFirstTouch","timeToConnect","timeToFirstMeeting","timeToWin"],"type":"object"},"CrmReportOutcomes":{"properties":{"from":{"type":"number"},"pipeline":{"description":"CURRENT snapshot of records by status (ignores from/to and userId).","items":{"$ref":"#/components/schemas/CrmReportPipelineBucket"},"type":"array"},"to":{"type":"number"},"users":{"items":{"$ref":"#/components/schemas/CrmReportOutcomesUser"},"type":"array"}},"required":["from","to","users","pipeline"],"type":"object"},"CrmReportOutcomesUser":{"properties":{"effortPerWin":{"$ref":"#/components/schemas/CrmReportEffortPerWin"},"losses":{"properties":{"records":{"minimum":0,"type":"integer"},"transitions":{"minimum":0,"type":"integer"}},"required":["transitions","records"],"type":"object"},"milestones":{"$ref":"#/components/schemas/CrmReportMilestones"},"previous":{"properties":{"effortPerWin":{"$ref":"#/components/schemas/CrmReportEffortPerWin"},"losses":{"properties":{"records":{"minimum":0,"type":"integer"},"transitions":{"minimum":0,"type":"integer"}},"required":["transitions","records"],"type":"object"},"milestones":{"$ref":"#/components/schemas/CrmReportMilestones"},"volumeOnboarded":{"$ref":"#/components/schemas/CrmReportVolumeOnboarded"},"wins":{"properties":{"records":{"minimum":0,"type":"integer"},"transitions":{"minimum":0,"type":"integer"}},"required":["transitions","records"],"type":"object"},"winsByStatus":{"items":{"properties":{"label":{"type":"string"},"records":{"minimum":0,"type":"integer"},"statusId":{"type":"string"}},"required":["statusId","label","records"],"type":"object"},"type":"array"}},"required":["wins","losses","winsByStatus","volumeOnboarded","milestones","effortPerWin"],"type":"object"},"userId":{"type":"string"},"volumeOnboarded":{"$ref":"#/components/schemas/CrmReportVolumeOnboarded"},"wins":{"properties":{"records":{"minimum":0,"type":"integer"},"transitions":{"minimum":0,"type":"integer"}},"required":["transitions","records"],"type":"object"},"winsByStatus":{"items":{"properties":{"label":{"type":"string"},"records":{"minimum":0,"type":"integer"},"statusId":{"type":"string"}},"required":["statusId","label","records"],"type":"object"},"type":"array"}},"required":["userId","wins","losses","winsByStatus","volumeOnboarded","milestones","effortPerWin","previous"],"type":"object"},"CrmReportPipelineBucket":{"properties":{"label":{"type":"string"},"outcome":{"enum":["won","lost",null],"nullable":true,"type":"string"},"records":{"minimum":0,"type":"integer"},"statusId":{"nullable":true,"type":"string"}},"required":["statusId","label","outcome","records"],"type":"object"},"CrmReportVolumeOnboarded":{"properties":{"buyerSideUnits":{"nullable":true,"type":"number"},"buyerSideVolume":{"nullable":true,"type":"number"},"records":{"minimum":0,"type":"integer"},"windows":{"properties":{"r12":{"nullable":true,"properties":{"records":{"minimum":0,"type":"integer"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units","records"],"type":"object"},"r14":{"nullable":true,"properties":{"records":{"minimum":0,"type":"integer"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units","records"],"type":"object"},"r6":{"nullable":true,"properties":{"records":{"minimum":0,"type":"integer"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units","records"],"type":"object"}},"required":["r6","r12","r14"],"type":"object"},"withProduction":{"minimum":0,"type":"integer"}},"required":["records","withProduction","windows","buyerSideVolume","buyerSideUnits"],"type":"object"},"CrmRequestAccessResult":{"properties":{"data":{"properties":{"status":{"enum":["sent","already_requested"],"type":"string"}},"required":["status"],"type":"object"}},"required":["data"],"type":"object"},"CrmRevokeListAccessResult":{"properties":{"data":{"properties":{"revoked":{"type":"boolean"}},"required":["revoked"],"type":"object"}},"required":["data"],"type":"object"},"CrmRevokeRecordAccessResult":{"properties":{"data":{"properties":{"revoked":{"type":"boolean"}},"required":["revoked"],"type":"object"}},"required":["data"],"type":"object"},"CrmSetCustomValueResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmSetDefaultCallerIdResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmSetOverrideResult":{"properties":{"data":{"$ref":"#/components/schemas/CrmOverlay"},"derived":{"$ref":"#/components/schemas/CrmDerivedLocation"}},"required":["data"],"type":"object"},"CrmSetOwnerResult":{"properties":{"data":{"properties":{"canShare":{"type":"boolean"},"needsShare":{"type":"boolean"},"ownerUserId":{"type":"string"}},"required":["ownerUserId"],"type":"object"}},"required":["data"],"type":"object"},"CrmShareTemplateResult":{"properties":{"data":{"properties":{"granted":{"type":"boolean"}},"required":["granted"],"type":"object"}},"required":["data"],"type":"object"},"CrmShareableMember":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"CrmShareableMemberList":{"properties":{"data":{"properties":{"members":{"items":{"$ref":"#/components/schemas/CrmShareableMember"},"type":"array"}},"required":["members"],"type":"object"}},"required":["data"],"type":"object"},"CrmSimilarOriginators":{"properties":{"data":{"properties":{"results":{"items":{"properties":{"components":{"properties":{"loan":{"nullable":true,"type":"number"},"size":{"type":"number"},"tx":{"nullable":true,"type":"number"}},"required":["tx","loan","size"],"type":"object"},"highlight":{"nullable":true,"properties":{"partnerPct":{"type":"number"},"type":{"type":"string"}},"required":["type","partnerPct"],"type":"object"},"nmls":{"type":"string"},"score":{"type":"number"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["nmls","score","components","volume","units","highlight"],"type":"object"},"type":"array"}},"required":["results"],"type":"object"}},"required":["data"],"type":"object"},"CrmTask":{"properties":{"allDay":{"type":"boolean"},"assigneeUserId":{"type":"string"},"body":{"nullable":true,"type":"string"},"calendarEventId":{"nullable":true,"type":"string"},"calendarProvider":{"enum":["google","microsoft",null],"nullable":true,"type":"string"},"cancelledAt":{"nullable":true,"type":"number"},"completedAt":{"nullable":true,"type":"number"},"createdAt":{"type":"number"},"createdByUserId":{"type":"string"},"dueAt":{"nullable":true,"type":"number"},"entityId":{"type":"string"},"id":{"type":"string"},"listId":{"nullable":true,"type":"string"},"status":{"$ref":"#/components/schemas/CrmTaskStatus"},"title":{"type":"string"}},"required":["id","entityId","title","body","dueAt","allDay","status","assigneeUserId","createdByUserId","completedAt","cancelledAt","calendarProvider","calendarEventId","createdAt","listId"],"type":"object"},"CrmTaskCreated":{"properties":{"data":{"anyOf":[{"$ref":"#/components/schemas/CrmTask"},{"properties":{"canShare":{"type":"boolean"},"created":{"type":"boolean"},"needsShare":{"enum":[true],"type":"boolean"},"updated":{"type":"boolean"}},"required":["needsShare","canShare"],"type":"object"}]}},"required":["data"],"type":"object"},"CrmTaskDeleted":{"properties":{"data":{"properties":{"deleted":{"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"CrmTaskList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmTask"},"type":"array"}},"required":["data"],"type":"object"},"CrmTaskStatus":{"enum":["open","completed","cancelled"],"type":"string"},"CrmTaskUpdated":{"properties":{"data":{"anyOf":[{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"},{"properties":{"canShare":{"type":"boolean"},"created":{"type":"boolean"},"needsShare":{"enum":[true],"type":"boolean"},"updated":{"type":"boolean"}},"required":["needsShare","canShare"],"type":"object"},{"properties":{"needsConnect":{"enum":["google","microsoft"],"type":"string"},"task":{"$ref":"#/components/schemas/CrmTask"}},"required":["task"],"type":"object"}]}},"required":["data"],"type":"object"},"CrmTemplate":{"properties":{"data":{"allOf":[{"$ref":"#/components/schemas/CrmTemplateWithFields"},{"nullable":true}]}},"required":["data"],"type":"object"},"CrmTemplateField":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"id":{"type":"string"},"key":{"type":"string"},"label":{"type":"string"},"options":{"items":{"properties":{"color":{"type":"string"},"id":{"type":"string"},"label":{"type":"string"}},"required":["id","label"],"type":"object"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"},"type":{"enum":["text","number","currency","date","select","multiselect","url","rating","checkbox","status","tags"],"type":"string"}},"required":["id","key","label","type","options","config","sortOrder"],"type":"object"},"CrmTemplateList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmTemplateSummary"},"type":"array"}},"required":["data"],"type":"object"},"CrmTemplateShareList":{"properties":{"data":{"$ref":"#/components/schemas/CrmTemplateShares"}},"required":["data"],"type":"object"},"CrmTemplateShares":{"properties":{"canManage":{"type":"boolean"},"owner":{"properties":{"email":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image"],"type":"object"},"ownerUserId":{"type":"string"},"shares":{"items":{"properties":{"createdAt":{"type":"number"},"email":{"nullable":true,"type":"string"},"grantedByName":{"nullable":true,"type":"string"},"image":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"userId":{"type":"string"}},"required":["userId","name","email","image","grantedByName","createdAt"],"type":"object"},"type":"array"}},"required":["ownerUserId","owner","canManage","shares"],"type":"object"},"CrmTemplateSummary":{"properties":{"canManage":{"type":"boolean"},"createdAt":{"type":"number"},"fieldCount":{"type":"number"},"id":{"type":"string"},"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"ownerName":{"nullable":true,"type":"string"},"ownerUserId":{"type":"string"},"sharedCount":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","objectType","ownerUserId","sharedCount","fieldCount","createdAt","updatedAt","ownerName","canManage"],"type":"object"},"CrmTemplateWithFields":{"properties":{"createdAt":{"type":"number"},"fieldCount":{"type":"number"},"fields":{"items":{"$ref":"#/components/schemas/CrmTemplateField"},"type":"array"},"id":{"type":"string"},"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"ownerUserId":{"type":"string"},"sharedCount":{"type":"number"},"updatedAt":{"type":"number"}},"required":["id","name","objectType","ownerUserId","sharedCount","fieldCount","createdAt","updatedAt","fields"],"type":"object"},"CrmTranscriptSentence":{"properties":{"speaker":{"enum":["user","contact"],"type":"string"},"text":{"type":"string"}},"required":["speaker","text"],"type":"object"},"CrmTransferListOwnershipResult":{"properties":{"data":{"properties":{"transferred":{"type":"boolean"}},"required":["transferred"],"type":"object"}},"required":["data"],"type":"object"},"CrmUnshareTemplateResult":{"properties":{"data":{"properties":{"revoked":{"type":"boolean"}},"required":["revoked"],"type":"object"}},"required":["data"],"type":"object"},"CrmUpdateListFieldResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmUpdateObjectFieldResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmUpdateTemplateResult":{"properties":{"data":{"properties":{"updated":{"type":"boolean"}},"required":["updated"],"type":"object"}},"required":["data"],"type":"object"},"CrmWorkspaceMeeting":{"allOf":[{"$ref":"#/components/schemas/CrmMeeting"},{"properties":{"canManage":{"type":"boolean"},"display":{"allOf":[{"$ref":"#/components/schemas/CrmDisplay"},{"nullable":true}]},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"overrides":{"$ref":"#/components/schemas/CrmOverlay"},"recordName":{"type":"string"},"recordSubtitle":{"nullable":true,"type":"string"}},"required":["entityType","recordName","recordSubtitle","display","canManage"],"type":"object"}]},"CrmWorkspaceMeetingList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmWorkspaceMeeting"},"type":"array"}},"required":["data"],"type":"object"},"CrmWorkspaceTask":{"allOf":[{"$ref":"#/components/schemas/CrmTask"},{"properties":{"canDelete":{"type":"boolean"},"display":{"allOf":[{"$ref":"#/components/schemas/CrmDisplay"},{"nullable":true}]},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"overrides":{"$ref":"#/components/schemas/CrmOverlay"},"recordName":{"type":"string"},"recordSubtitle":{"nullable":true,"type":"string"}},"required":["entityType","recordName","recordSubtitle","display","canDelete"],"type":"object"}]},"CrmWorkspaceTaskList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/CrmWorkspaceTask"},"type":"array"}},"required":["data"],"type":"object"},"DateFilterValue":{"anyOf":[{"description":"Exact date","example":"2024-01-01","type":"string"},{"description":"Date range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them. Bounds accept `YYYY`, `YYYY-MM`, `YYYY-MM-DD` or a full ISO datetime. A partial bound denotes the whole period and expands to the edge that preserves the operator: `gte`/`lt` take the period START, `gt`/`lte` take the period END — so `{gte: \"2024\"}` means on/after 2024-01-01 and `{lte: \"2024\"}` means through 2024-12-31.","example":{"gte":"2024-01-01","lte":"2024-12-31"},"properties":{"gt":{"type":"string"},"gte":{"type":"string"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires a bound.","type":"boolean"},"lt":{"type":"string"},"lte":{"type":"string"}},"type":"object"},{"nullable":true}]},"DatedPeriod":{"description":"Date window for loans / sales / market endpoints. Accepts every `Period` value plus rolling windows: `last30Days` / `last60Days` / `last90Days` (today minus 30 / 60 / 90 days through today), `previousMonth` (the last complete calendar month) and `currentMonth` (the 1st of this month through today). All windows are resolved in UTC with inclusive calendar-date bounds. Rolling windows are only accepted by the loans, sales and market endpoints (list, count, breakdowns, analytics summary / time-series / chart); originators / companies / branches / agents / offices endpoints return 400 for them.","enum":["2017","2018","2019","2020","2021","2022","2023","2024","2025","2026","last3Months","last6Months","last12Months","last14Months","last16Months","last18Months","last24Months","yearToDate","allTime","last30Days","last60Days","last90Days","previousMonth","currentMonth"],"type":"string"},"DeleteSavedFilterResult":{"properties":{"data":{"properties":{"deleted":{"enum":[true],"type":"boolean"}},"required":["deleted"],"type":"object"}},"required":["data"],"type":"object"},"EarlyExitCounterparty":{"properties":{"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"}},"required":["nmlsId","name"],"type":"object"},"EarlyExitRow":{"properties":{"city":{"nullable":true,"type":"string"},"daysAtCompany":{"nullable":true,"type":"number"},"daysSinceStart":{"type":"number"},"endDate":{"nullable":true,"type":"string"},"kind":{"enum":["early_departure","recent_start"],"type":"string"},"name":{"nullable":true,"type":"string"},"nextEmployer":{"$ref":"#/components/schemas/EarlyExitCounterparty"},"nmlsId":{"type":"string"},"previousEmployer":{"$ref":"#/components/schemas/EarlyExitCounterparty"},"startDate":{"type":"string"},"state":{"nullable":true,"type":"string"},"trailingUnits":{"type":"number"},"trailingVolume":{"description":"Trailing-12-month production across all employers (0 when none on file).","type":"number"}},"required":["nmlsId","name","kind","city","state","startDate","endDate","daysAtCompany","daysSinceStart","previousEmployer","nextEmployer","trailingVolume","trailingUnits"],"type":"object"},"EmploymentBranchLocation":{"nullable":true,"properties":{"city":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"}},"required":["nmlsId","name","city","state"],"type":"object"},"EmploymentContact":{"nullable":true,"properties":{"cellPhone":{"nullable":true,"type":"string"},"employerAddress":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerCompany":{"nullable":true,"type":"string"},"employerCompanyId":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"employerType":{"nullable":true,"type":"string"},"employerWebsite":{"nullable":true,"type":"string"},"employerZip":{"nullable":true,"type":"string"},"facebook":{"nullable":true,"type":"string"},"linkedin":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"officePhoneExt":{"nullable":true,"type":"string"},"personalEmail":{"nullable":true,"type":"string"},"twitter":{"nullable":true,"type":"string"},"website":{"nullable":true,"type":"string"},"workEmail":{"nullable":true,"type":"string"}},"required":["cellPhone","officePhone","officePhoneExt","workEmail","personalEmail","linkedin","facebook","twitter","website","employerCompany","employerCompanyId","employerAddress","employerCity","employerState","employerZip","employerWebsite","employerType"],"type":"object"},"EmploymentWindow":{"properties":{"from":{"type":"string"},"to":{"type":"string"}},"required":["from","to"],"type":"object"},"EnrichAmbiguousRef":{"properties":{"alternates":{"description":"Sibling document `id`s — pass one back as `/{id}/enrich` to enrich that exact unit.","items":{"type":"string"},"type":"array"},"error":{"type":"string"}},"required":["error","alternates"],"type":"object"},"EnrichBatchItem":{"properties":{"alternates":{"description":"Sibling document `id`s. Present only on `ambiguous_ref` — pass one as a precise id to enrich that exact unit.","items":{"type":"string"},"type":"array"},"balance":{"description":"Remaining credit balance. Present only on insufficient_credits.","type":"number"},"cached":{"description":"Served from cache (member entitlement or internal). ok items only.","type":"boolean"},"charged":{"description":"True when this id resulted in a credit debit. ok items only.","type":"boolean"},"code":{"$ref":"#/components/schemas/EnrichBatchItemErrorCode"},"data":{"$ref":"#/components/schemas/PropertyEnrichment"},"property":{"description":"The parcel behind this enrichment. ok items only; `null` when the id resolved to more than one parcel.","nullable":true,"properties":{"communityLending":{"$ref":"#/components/schemas/PropertyCommunityLending"},"parties":{"$ref":"#/components/schemas/PropertyParties"}},"required":["communityLending","parties"],"type":"object"},"propertyId":{"type":"string"},"reason":{"$ref":"#/components/schemas/EnrichmentReason"},"result":{"$ref":"#/components/schemas/EnrichmentResultMeta"},"status":{"enum":["ok","error"],"type":"string"}},"required":["propertyId","status"],"type":"object"},"EnrichBatchItemErrorCode":{"description":"Failure reason. error items only.","enum":["not_found","ambiguous_ref","no_address","provider_error","insufficient_credits","rate_limited","daily_limit_exceeded","permission_denied","member_not_found","bad_request","billing_unavailable"],"type":"string"},"EnrichBatchRequest":{"properties":{"propertyIds":{"description":"Property ids to enrich in one request. 1–50; larger sets must use the async bulk job. Use the `id`/`mmPropertyId` from a property search or a loan/sale record (e.g. `mm_<fips><apn>`) — bare APNs, fips+apn, or `loan_…` ids will not resolve.","items":{"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"},"refresh":{"description":"When true, bypass both caches for every id, force a fresh skip-trace, and re-charge per match.","type":"boolean"}},"required":["propertyIds"],"type":"object"},"EnrichBatchResponse":{"properties":{"results":{"items":{"$ref":"#/components/schemas/EnrichBatchItem"},"type":"array"},"summary":{"$ref":"#/components/schemas/EnrichBatchSummary"}},"required":["results","summary"],"type":"object"},"EnrichBatchSummary":{"properties":{"charged":{"description":"Items that resulted in a credit debit (one per match).","type":"integer"},"failed":{"description":"Items with status error.","type":"integer"},"requested":{"type":"integer"},"succeeded":{"description":"Items with status ok (cache hits + fresh, matched or empty).","type":"integer"}},"required":["requested","succeeded","charged","failed"],"type":"object"},"EnrichBulkJobResponse":{"properties":{"billingStatus":{"description":"Outcome of the job's single finalize debit: `charged`, `capped` (member balance/daily cap hit — customer constraint), `billing_error` (5xx/auth — recoverable revenue to reconcile), or `none` (nothing matched). Absent on older rows.","enum":["charged","capped","billing_error","none"],"type":"string"},"chargedCount":{"description":"Intended charge — matched rows tallied during the run. NOT necessarily what was billed; read `creditsCharged` for the actual debit and `billingStatus` for why they differ.","type":"integer"},"completedAt":{"type":"string"},"creditsCharged":{"description":"Credits ACTUALLY debited (0 when the finalize debit was rejected/failed). Absent only on rows written before the field existed, where enrichment billed 1 credit per match and `chargedCount` was the credit amount.","type":"integer"},"downloadUrl":{"description":"Stable, shareable download link for the completed results. Forces a file download (with a friendly filename) and stays valid for 7 days after completion. Present once `status` is `completed`. This is the link to hand to a user or send by email.","type":"string"},"error":{"type":"string"},"failed":{"type":"integer"},"fromCache":{"type":"integer"},"jobId":{"type":"string"},"resultsUrl":{"description":"Direct download URL for the completed results. Long-lived per request but changes on each poll; prefer `downloadUrl` for a stable link to share.","type":"string"},"startedAt":{"type":"string"},"status":{"enum":["queued","running","completed","failed","cancelled"],"type":"string"},"succeeded":{"type":"integer"},"total":{"type":"integer"}},"required":["jobId","status","total","succeeded","failed","fromCache","chargedCount"],"type":"object"},"EnrichBulkRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode","description":"Filter-driven mode: an advanced boolean filter tree, AND-merged with `flatFilters` (same semantics as `POST /properties`)."},"filters":{"$ref":"#/components/schemas/FilterNode","description":"Legacy alias for `advancedFilters`."},"flatFilters":{"allOf":[{"$ref":"#/components/schemas/PropertyFlatFilters"},{"description":"Filter-driven mode: the same flat filters as `POST /properties` (including the loan-slot filters). The job enriches every matching property up to `limit` (or the hard cap). Provide filters OR propertyIds, not both."}]},"limit":{"description":"Filter-driven mode only: cap the number of matching properties enriched (and billed). Omitted → enrich every match up to the 50000 hard cap.","maximum":50000,"minimum":1,"type":"integer"},"propertyIds":{"description":"Property IDs to enrich (id-driven mode). Hard cap 50000. Use the `id`/`mmPropertyId` from a property search or a loan/sale record (e.g. `mm_<fips><apn>`) — bare APNs, fips+apn, or `loan_…` ids will not resolve. Provide this OR filters, not both.","items":{"minLength":1,"type":"string"},"maxItems":50000,"minItems":1,"type":"array"},"refresh":{"description":"When true, the ECS task bypasses both caches for every property and re-charges credits. Idempotency key picks up an epoch-minute discriminator.","type":"boolean"}},"type":"object"},"EnrichBulkResponse":{"properties":{"estimatedCost":{"description":"Worst-case credit cost (10 / property). Actual debit is per match — properties with no skip-trace contacts and cached no-match rows don't charge. The post-completion `creditsCharged` on the job row is the precise debited total; `chargedCount` is the match COUNT, which is a different unit.","type":"integer"},"jobId":{"type":"string"},"propertyCount":{"type":"integer"},"status":{"enum":["queued"],"type":"string"}},"required":["jobId","status","propertyCount","estimatedCost"],"type":"object"},"EnrichPropertyContext":{"description":"The parcel behind the enrichment: its Community Lending neighborhood profile and the mortgage parties attributed to it. Identical to the `communityLending` and `parties` blocks on `GET /v1/properties/{id}` — returned here so a skip-trace does not need a second call to answer 'what kind of neighborhood is this' and 'who already has a relationship with this parcel'.","nullable":true,"properties":{"communityLending":{"$ref":"#/components/schemas/PropertyCommunityLending"},"parties":{"$ref":"#/components/schemas/PropertyParties"}},"required":["communityLending","parties"],"type":"object"},"EnrichPropertyResponse":{"properties":{"cached":{"description":"Whether the result was served from cache","type":"boolean"},"charged":{"description":"True when this call resulted in a credit debit. False on cache hits AND on `fresh_skip_trace_empty` (no-match calls don't charge).","type":"boolean"},"data":{"$ref":"#/components/schemas/PropertyEnrichment"},"property":{"$ref":"#/components/schemas/EnrichPropertyContext"},"reason":{"$ref":"#/components/schemas/EnrichmentReason"},"result":{"$ref":"#/components/schemas/EnrichmentResultMeta"}},"required":["data","cached","charged","reason","result"],"type":"object"},"EnrichmentCacheBustRequest":{"properties":{"rows":{"description":"Explicit list of cache rows to delete. Mix internal and member keys freely. Max 500 per call; the helper batches into 25-item DDB `BatchWriteItem` chunks under the hood.","items":{"$ref":"#/components/schemas/EnrichmentCacheRowKey"},"maxItems":500,"minItems":1,"type":"array"}},"required":["rows"],"type":"object"},"EnrichmentCacheBustResponse":{"properties":{"deleted":{"minimum":0,"type":"integer"},"unprocessed":{"items":{"$ref":"#/components/schemas/EnrichmentCacheRowKey"},"type":"array"}},"required":["deleted","unprocessed"],"type":"object"},"EnrichmentCacheDeleteResponse":{"properties":{"deleted":{"enum":[true],"type":"boolean"}},"required":["deleted"],"type":"object"},"EnrichmentCacheGetResponse":{"properties":{"data":{"$ref":"#/components/schemas/EnrichmentCacheRow"}},"required":["data"],"type":"object"},"EnrichmentCachePropertyChildrenResponse":{"properties":{"internal":{"allOf":[{"$ref":"#/components/schemas/EnrichmentCacheRow"},{"description":"The internal property cache row, or `null` if the property has no cached enrichment.","nullable":true}]},"members":{"description":"Every member entitlement row tied to this property. Empty when no member has enriched it.","items":{"$ref":"#/components/schemas/EnrichmentCacheRow"},"type":"array"}},"required":["internal","members"],"type":"object"},"EnrichmentCacheRow":{"properties":{"data":{"description":"Parsed `PropertyEnrichment` payload, or `null` if the row failed schema parse (drift). Admin-view exposes both.","nullable":true},"enrichedAt":{"nullable":true,"type":"string"},"expired":{"type":"boolean"},"expiresAt":{"nullable":true,"type":"number"},"key":{"$ref":"#/components/schemas/EnrichmentCacheRowKey"},"personCount":{"description":"Number of skip-trace persons cached in this row. `0` usually means the provider had no contact match — but rows from the May 2026 parser-drift incident also surface here.","minimum":0,"type":"integer"},"source":{"nullable":true,"type":"string"}},"required":["key","personCount","enrichedAt","source","expiresAt","expired"],"type":"object"},"EnrichmentCacheRowKey":{"oneOf":[{"properties":{"kind":{"enum":["internal"],"type":"string"},"propertyId":{"type":"string"}},"required":["kind","propertyId"],"type":"object"},{"properties":{"kind":{"enum":["member"],"type":"string"},"orgId":{"type":"string"},"propertyId":{"type":"string"},"userId":{"type":"string"}},"required":["kind","orgId","userId","propertyId"],"type":"object"}]},"EnrichmentCacheScanResponse":{"properties":{"cursor":{"description":"Pagination cursor. Pass back unchanged on the next call.","type":"string"},"items":{"items":{"$ref":"#/components/schemas/EnrichmentCacheRow"},"type":"array"}},"required":["items"],"type":"object"},"EnrichmentCacheStats":{"properties":{"computedAt":{"description":"ISO 8601 timestamp","type":"string"},"costUsd":{"description":"`total × unitCostUsd` — upstream spend behind the live table.","minimum":0,"type":"number"},"empty":{"description":"Unexpired rows where the provider returned no persons.","minimum":0,"type":"integer"},"expired":{"minimum":0,"type":"integer"},"healthy":{"description":"Unexpired rows with at least one person.","minimum":0,"type":"integer"},"memberRows":{"description":"Member entitlement rows across every workspace.","minimum":0,"type":"integer"},"partial":{"description":"True when the scan hit its page/time budget; counts are a lower bound.","type":"boolean"},"savedLookups":{"description":"Member entitlements served from the internal cache rather than a fresh BatchData call (every member beyond the first per property).","minimum":0,"type":"integer"},"savingsUsd":{"description":"`savedLookups × unitCostUsd`.","minimum":0,"type":"number"},"total":{"description":"Internal property cache rows — one per enriched property.","minimum":0,"type":"integer"},"unitCostUsd":{"minimum":0,"type":"number"}},"required":["total","expired","empty","healthy","memberRows","savedLookups","costUsd","savingsUsd","unitCostUsd","partial","computedAt"],"type":"object"},"EnrichmentCharge":{"properties":{"at":{"description":"ISO 8601 time of the debit","type":"string"},"credits":{"type":"number"},"refresh":{"description":"True when this charge came from a forced re-run","type":"boolean"}},"required":["at","credits","refresh"],"type":"object"},"EnrichmentListItem":{"properties":{"charged":{"description":"Whether the call that produced the current result debited credits. `null` for results stored before charges were recorded.","nullable":true,"type":"boolean"},"charges":{"description":"Every recorded debit for this property, oldest first. More than one means it was paid for more than once (a `refresh` re-run). `null` when not recorded.","items":{"$ref":"#/components/schemas/EnrichmentCharge"},"nullable":true,"type":"array"},"creditsCharged":{"description":"Total credits debited for this property across every recorded run, including forced re-runs. `null` when not recorded.","nullable":true,"type":"number"},"emailCount":{"description":"Email addresses found across every matched person.","type":"number"},"enrichedAt":{"type":"string"},"personCount":{"type":"number"},"phoneCount":{"description":"Phone numbers found across every matched person. A matched person can have none.","type":"number"},"propertyId":{"type":"string"},"source":{"type":"string"}},"required":["propertyId","enrichedAt","source","personCount","phoneCount","emailCount","charged","creditsCharged","charges"],"type":"object"},"EnrichmentListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/EnrichmentListItem"},"type":"array"}},"required":["data"],"type":"object"},"EnrichmentReason":{"description":"Pipeline path used to produce this enrichment. Pair with `charged` to drive billing UX; pair with `data.persons` to drive the empty-state UX.","enum":["member_cache_hit","internal_cache_hit","internal_cache_hit_empty","fresh_skip_trace","fresh_skip_trace_empty"],"type":"string"},"EnrichmentResultMeta":{"description":"Per-batch counts BatchData echoed back (or all-zero on cache hits). `matched` > 0 implies a fresh hit; `noMatch` > 0 with `matched: 0` implies a genuine no-match.","properties":{"error":{"minimum":0,"type":"integer"},"matched":{"minimum":0,"type":"integer"},"noMatch":{"minimum":0,"type":"integer"},"requested":{"minimum":0,"type":"integer"}},"required":["requested","matched","noMatch","error"],"type":"object"},"EntityCommunityLending":{"description":"Community Lending — the neighborhood (U.S. Census tract) mix of the loans this entity produced in the selected period: program shares and counts, the averaged neighborhood profile, and the local mortgage market. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100. Every share is taken over `loansWithCommunityData`, NOT over the entity's total production. Two fields are deliberately not 0-100: `avgIncomeVsMetroPct` is a ratio where 100 means parity with the metro (it exceeds 100), and `ruralGradient` is an ordinal 1-10 code. `null` — not an all-null object — when the entity had no tract-resolved loans in the window. Returned by the entity DETAIL routes only (`getOriginator` / `getCompany` / `getBranch`); list rows omit the block. Every key here is also a filter key on the matching list route.","nullable":true,"properties":{"affordableHousingTractCount":{"description":"Loans in qualified affordable-housing neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"affordableHousingTractPct":{"description":"Share of the entity's tract-resolved loans in qualified neighborhoods for affordable-housing programs, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgAsianPct":{"description":"Mean Asian (non-Hispanic) share of the population in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgBlackPct":{"description":"Mean Black (non-Hispanic) share of the population in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgDenialRate":{"description":"Mean share of mortgage applications denied in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgFamilyIncome":{"description":"Mean median family income of those neighborhoods, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgHispanicPct":{"description":"Mean Hispanic or Latino share of the population in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgHomeValue":{"description":"Mean median home value across those neighborhoods, in whole dollars — a neighborhood statistic, not the entity's average loan size (`avgLoanAmount`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgHomeownershipRate":{"description":"Mean owner-occupied share of housing units in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgHouseholdIncome":{"description":"Mean median household income of those neighborhoods, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgIncomeVsMetroPct":{"description":"Mean neighborhood income relative to its metro area, where 100 is parity. Legitimately exceeds 100 — a ratio, not a share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgLowModHouseholdPct":{"description":"Mean HUD block-group low/moderate-income HOUSEHOLD share across those neighborhoods, 0-100 — a finer measure than `lowModIncomeTractPct`, which counts whole neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgMedianAge":{"description":"Mean median age of the population in those neighborhoods, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgMilesToCollege":{"description":"Mean straight-line distance to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgMilesToSchool":{"description":"Mean straight-line distance to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgMilesToWorship":{"description":"Mean straight-line distance to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgMinorityPct":{"description":"Mean non-white share of the population in those neighborhoods, 0-100. `majorityMinorityTractPct` is the per-neighborhood-threshold form of the same question. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgPopulation":{"description":"Mean population of those neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgPovertyRate":{"description":"Mean share of the population below the poverty line in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgTractApplications":{"description":"Mean number of mortgage applications reported in those neighborhoods, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgTractLoanVolume":{"description":"Mean mortgage dollar volume reported in those neighborhoods, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgTractOriginations":{"description":"Mean number of mortgage originations reported in those neighborhoods, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgWhiteNonHispanicPct":{"description":"Mean White (non-Hispanic) share of the population in those neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"difficultDevelopmentAreaCount":{"description":"Loans in HUD-designated difficult development areas, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"difficultDevelopmentAreaPct":{"description":"Share of the entity's tract-resolved loans in HUD-designated difficult development areas, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"distressedTractCount":{"description":"Loans in distressed-or-underserved neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"distressedTractPct":{"description":"Share of the entity's tract-resolved loans in distressed-or-underserved nonmetropolitan middle-income neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"floodHazardTractCount":{"description":"Loans in a FEMA special flood hazard area, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"floodHazardTractPct":{"description":"Share of the entity's tract-resolved loans in a FEMA special flood hazard area, 0-100. `predominantFloodZone` names the specific zone. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"loansWithCommunityData":{"description":"How many of the entity's loans in the selected period resolved to a neighborhood — the DENOMINATOR every share in this block is taken over. Read it first: a 100% share off two loans is not a 100% share off two hundred. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"lowModIncomeTractCount":{"description":"Loans in low- or moderate-income neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"lowModIncomeTractPct":{"description":"Share of the entity's tract-resolved loans in low- or moderate-income neighborhoods under the Community Reinvestment Act, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractCount":{"description":"Loans in majority-minority neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractPct":{"description":"Share of the entity's tract-resolved loans in majority-minority neighborhoods, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"opportunityZoneCount":{"description":"Loans in Opportunity Zones, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"opportunityZonePct":{"description":"Share of the entity's tract-resolved loans in federally designated Opportunity Zones, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"predominantFloodZone":{"description":"FEMA flood-zone code most common across those neighborhoods (e.g. `AE`). Null means no special flood hazard area on file. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"string"},"predominantIncomeLevel":{"description":"The relative-income classification most of the entity's loans landed in: low, moderate, middle or upper. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","enum":["low","moderate","middle","upper",null],"nullable":true,"type":"string"},"ruralGradient":{"description":"Mean remoteness of those neighborhoods on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). A code, not a percent. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"ruralTractCount":{"description":"Loans in rural neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"ruralTractPct":{"description":"Share of the entity's tract-resolved loans in rural neighborhoods, 0-100. `ruralGradient` is the finer, ordinal form. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTractCount":{"description":"Loans in USDA-eligible neighborhoods, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTractPct":{"description":"Share of the entity's tract-resolved loans in neighborhoods eligible for USDA rural housing programs, 0-100. Broader than `ruralTractPct`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"}},"required":["loansWithCommunityData","lowModIncomeTractPct","lowModIncomeTractCount","majorityMinorityTractPct","majorityMinorityTractCount","ruralTractPct","ruralTractCount","opportunityZonePct","opportunityZoneCount","affordableHousingTractPct","affordableHousingTractCount","floodHazardTractPct","floodHazardTractCount","usdaEligibleTractPct","usdaEligibleTractCount","distressedTractPct","distressedTractCount","difficultDevelopmentAreaPct","difficultDevelopmentAreaCount","predominantIncomeLevel","predominantFloodZone","avgHouseholdIncome","avgFamilyIncome","avgHomeValue","avgMedianAge","avgPopulation","avgMinorityPct","avgIncomeVsMetroPct","avgDenialRate","avgHomeownershipRate","avgPovertyRate","avgLowModHouseholdPct","avgWhiteNonHispanicPct","avgBlackPct","avgAsianPct","avgHispanicPct","avgTractOriginations","avgTractApplications","avgTractLoanVolume","ruralGradient","avgMilesToSchool","avgMilesToCollege","avgMilesToWorship"],"type":"object"},"EntityPredominantFloodZoneFilterValue":{"anyOf":[{"description":"One of (case-insensitive): A, AE, AH, AO, A99, V, VE","enum":["A","AE","AH","AO","A99","V","VE"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): A, AE, AH, AO, A99, V, VE","enum":["A","AE","AH","AO","A99","V","VE"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"EntityPredominantIncomeLevelFilterValue":{"anyOf":[{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"ErrorResponse":{"properties":{"error":{"description":"Error message","type":"string"}},"required":["error"],"type":"object"},"FieldCondition":{"properties":{"field":{"type":"string"},"op":{"$ref":"#/components/schemas/FilterOp"},"type":{"enum":["filter"],"type":"string"},"value":{"description":"Comparison value","nullable":true}},"required":["type","field","op"],"type":"object"},"FilterNode":{"anyOf":[{"$ref":"#/components/schemas/AndFilter"},{"$ref":"#/components/schemas/OrFilter"},{"$ref":"#/components/schemas/NotFilter"},{"$ref":"#/components/schemas/FieldCondition"}]},"FilterOp":{"description":"Comparison operator. `exists` means the field has a REAL value: on fields whose source records an unknown as an in-domain value (e.g. `beds`, `squareFeet`, `lotSquareFeet`, where an unrecorded measurement is stored as `0`), those docs count as NOT existing. `neq` keeps docs with no value — it removes only what is known to equal the value, matching the reading of an exclusion.","enum":["eq","neq","gt","gte","lt","lte","between","in","match","geoDistance","exists"],"type":"string"},"FootprintProductFilter":{"additionalProperties":false,"description":"Correlate a product INSIDE this lender relationship — 'FHA business through this lender'.","properties":{"avgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Mean loan size of this product INSIDE the named market."}]},"key":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Product key(s), lowercase — e.g. `fha`, `conventional`, `va` for `loanType`; `purchase`, `refinance` for `transactionType`."},"mix":{"description":"Which product breakdown inside the market — loan type (fha, conventional, va, …) or transaction type (purchase, refinance, …).","enum":["loanType","transactionType"],"type":"string"},"shareOfUnits":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"This product's share of the market's loan count, as a 0–100 PERCENT (not a 0–1 fraction)."}]},"shareOfVolume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"This product's share of the market's dollar volume, as a 0–100 PERCENT (not a 0–1 fraction)."}]},"units":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Loan count of this product INSIDE the named market."}]},"volume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Dollar volume of this product INSIDE the named market, for the selected period."}]}},"type":"object"},"FootprintRange":{"additionalProperties":false,"description":"Dollar volume of the agent's sales financed BY this lender during the selected period — evaluated inside that lender's own bucket, not against the agent's total.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},"ForecastError":{"properties":{"code":{"enum":["forecast_interval","forecast_measure","forecast_history","forecast_unavailable"],"type":"string"},"error":{"description":"Error message","type":"string"}},"required":["error"],"type":"object"},"ForecastPoint":{"properties":{"date":{"description":"First day of the forecast month, `yyyy-MM-dd`.","type":"string"},"p10":{"type":"number"},"p50":{"description":"Median forecast.","type":"number"},"p90":{"type":"number"}},"required":["date","p10","p50","p90"],"type":"object"},"ForecastRequest":{"description":"Append a zero-shot forecast (Amazon Chronos-2) to the time series. Monthly interval only. The history in `current` is returned unchanged; the forecast starts the month after `forecast.asOf`.","properties":{"horizon":{"default":6,"description":"Months ahead to forecast, counted from `asOf` (1–12).","maximum":12,"minimum":1,"type":"integer"},"scenario":{"default":{"rate30y":"hold"},"description":"Known-future covariates the forecast conditions on. Omit for `hold`.","properties":{"rate30y":{"anyOf":[{"enum":["hold","fall","rise"],"type":"string"},{"items":{"maximum":25,"minimum":0,"type":"number"},"maxItems":12,"minItems":1,"type":"array"}],"default":"hold","description":"Path of the 30-year fixed mortgage rate over the forecast horizon, one value per month, as a plain percent (6.5 = 6.5%). Presets: `hold` keeps the latest weekly Freddie Mac PMMS reading flat; `fall` glides it down 1.0 point linearly over the horizon; `rise` glides it up 1.0 point. An explicit array must have exactly `horizon` entries. The rate is an INPUT the model conditions on, never something it predicts."}},"type":"object"}},"type":"object"},"ForecastResponse":{"description":"Present only when the request carried `forecast`. History above is unchanged; the forecast starts the month after `forecast.asOf`.","properties":{"asOf":{"description":"First day of the last month of history the model saw (`yyyy-MM-dd`). The forecast begins the following month.","type":"string"},"cached":{"description":"True when served from cache (same request, same data version).","type":"boolean"},"confidence":{"description":"Support tier: `high` ≥ 100/month, `medium` ≥ 20/month, `low` below. Below 20/month the series is mostly noise and the band is wide; treat `low` as a shape, not a number.","enum":["high","medium","low"],"type":"string"},"horizon":{"type":"integer"},"interval":{"enum":["monthly"],"type":"string"},"model":{"description":"Model id that produced the quantiles.","type":"string"},"points":{"items":{"$ref":"#/components/schemas/ForecastPoint"},"type":"array"},"scenario":{"description":"The resolved covariate path the forecast conditioned on, one value per horizon month. `null` when the rate series was unavailable and the forecast ran without it.","nullable":true,"properties":{"rate30y":{"items":{"type":"number"},"type":"array"}},"required":["rate30y"],"type":"object"},"segments":{"description":"Per-segment forecasts when the request carried `segment`, one per label (top 12 by history total). Independent forecasts — they are not reconciled to sum to the total.","items":{"$ref":"#/components/schemas/ForecastSegment"},"type":"array"},"support":{"description":"Mean monthly value of the forecast target over the last 12 months of history the model saw. The number behind `confidence`.","type":"number"},"trimmedMonths":{"description":"Trailing months dropped from history before forecasting because they are still filling in (ingest lag on application months; closing lag on originated measures).","type":"integer"}},"required":["model","asOf","trimmedMonths","horizon","interval","scenario","support","confidence","points","cached"],"type":"object"},"ForecastSegment":{"properties":{"confidence":{"description":"Support tier: `high` ≥ 100/month, `medium` ≥ 20/month, `low` below. Below 20/month the series is mostly noise and the band is wide; treat `low` as a shape, not a number.","enum":["high","medium","low"],"type":"string"},"label":{"type":"string"},"points":{"items":{"$ref":"#/components/schemas/ForecastPoint"},"type":"array"},"support":{"description":"Mean monthly value of the forecast target over the last 12 months of history the model saw. The number behind `confidence`.","type":"number"}},"required":["label","support","confidence","points"],"type":"object"},"GeoFilterValue":{"description":"Radius search — `{ lat, lon, radius }` (e.g. radius \"15mi\" or \"24km\") — around any office on the agent's record; with `locationSource` `office` the CURRENT office, `production` their transactions.","nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"},"radius":{"example":"25mi","type":"string"}},"required":["lat","lon","radius"],"type":"object"},"GetSavedFilterResult":{"properties":{"data":{"$ref":"#/components/schemas/SavedFilter"}},"required":["data"],"type":"object"},"HeadcountPoint":{"properties":{"active":{"description":"Distinct loan officers with any employment record here overlapping the month.","type":"number"},"entered":{"description":"Hires in the month.","type":"number"},"exited":{"description":"Complete departures in the month.","type":"number"},"net":{"type":"number"},"period":{"description":"Month, `YYYY-MM`.","type":"string"}},"required":["period","active","entered","exited","net"],"type":"object"},"HubspotError":{"properties":{"code":{"description":"Stable reason code. `not_connected` means run the HubSpot connect flow; `portal_mismatch` means the connected account is not the one the workspace's mapping was built for; the rest describe a setup problem to fix before retrying.","type":"string"},"details":{"additionalProperties":{"nullable":true},"type":"object"},"error":{"description":"Human-readable explanation.","type":"string"}},"required":["error","code"],"type":"object"},"HubspotObjectStatus":{"properties":{"code":{"type":"string"},"entity":{"description":"The kind of Model Match record the ids refer to — `originator` for loan officers, `agent` for real estate agents. Required, and checked against what your workspace configured: if they disagree the request is refused rather than writing records built from the wrong mapping.","enum":["agent","originator"],"type":"string"},"mappedFieldCount":{"type":"number"},"matchOn":{"description":"The HubSpot field used to match existing records.","type":"string"},"object":{"description":"Which kind of HubSpot record to write. Your workspace decides which Model Match records feed each one.","enum":["contact","company"],"type":"string"},"ready":{"type":"boolean"},"reason":{"type":"string"}},"required":["object","ready"],"type":"object"},"HubspotPaymentRequired":{"properties":{"balance":{"description":"Credits available.","type":"number"},"cost":{"description":"Credits this push would cost at most.","type":"number"},"error":{"type":"string"}},"required":["error","balance","cost"],"type":"object"},"HubspotPushRecordResult":{"properties":{"crmRecordId":{"description":"The record's id in your HubSpot account, when written.","type":"string"},"id":{"type":"string"},"message":{"type":"string"},"preserved":{"description":"Fields left untouched because your HubSpot record already had a value and the mapping says not to overwrite.","items":{"type":"string"},"type":"array"},"reason":{"enum":["not_found","missing_dedupe_value","duplicate_dedupe_value","rejected"],"type":"string"},"status":{"enum":["created","updated","skipped","failed","would_create","would_update"],"type":"string"}},"required":["id","status"],"type":"object"},"HubspotPushRequest":{"properties":{"dryRun":{"default":false,"description":"Resolve the records, apply the mapping and report exactly what would be written — without writing anything. There is no undo on a real push; use this first.","type":"boolean"},"entity":{"description":"The kind of Model Match record the ids refer to — `originator` for loan officers, `agent` for real estate agents. Required, and checked against what your workspace configured: if they disagree the request is refused rather than writing records built from the wrong mapping.","enum":["agent","originator"],"type":"string"},"ids":{"description":"Record ids to send, at most 100 per request. Loan officers are identified by NMLS id, agents by their Model Match id. Duplicates are collapsed.","items":{"minLength":1,"type":"string"},"maxItems":100,"minItems":1,"type":"array"},"object":{"description":"Which kind of HubSpot record to write. Your workspace decides which Model Match records feed each one.","enum":["contact","company"],"type":"string"}},"required":["object","entity","ids"],"type":"object"},"HubspotPushResponse":{"properties":{"billing":{"properties":{"charged":{"nullable":true,"type":"number"},"note":{"type":"string"}},"required":["charged"],"type":"object"},"dryRun":{"type":"boolean"},"entity":{"description":"The kind of Model Match record the ids refer to — `originator` for loan officers, `agent` for real estate agents. Required, and checked against what your workspace configured: if they disagree the request is refused rather than writing records built from the wrong mapping.","enum":["agent","originator"],"type":"string"},"object":{"description":"Which kind of HubSpot record to write. Your workspace decides which Model Match records feed each one.","enum":["contact","company"],"type":"string"},"portalId":{"description":"The HubSpot account these records were written to.","type":"string"},"portalRecorded":{"description":"Whether your workspace's setup records which HubSpot account it was built for. When false, consider saving it so a member on a different account can be warned before sending.","type":"boolean"},"results":{"items":{"$ref":"#/components/schemas/HubspotPushRecordResult"},"type":"array"},"summary":{"properties":{"created":{"type":"number"},"failed":{"type":"number"},"requested":{"type":"number"},"skipped":{"type":"number"},"updated":{"type":"number"}},"required":["requested","created","updated","skipped","failed"],"type":"object"}},"required":["object","entity","dryRun","portalId","portalRecorded","summary","results","billing"],"type":"object"},"HubspotStatusResponse":{"properties":{"configuredPortalId":{"description":"The HubSpot account your workspace's setup was built for. When this differs from `portalId`, pushes are refused.","nullable":true,"type":"string"},"connected":{"type":"boolean"},"maxRecordsPerPush":{"type":"number"},"objects":{"items":{"$ref":"#/components/schemas/HubspotObjectStatus"},"type":"array"},"portalId":{"description":"The HubSpot account you have connected, when known.","nullable":true,"type":"string"},"portalMismatch":{"type":"boolean"}},"required":["connected","portalId","configuredPortalId","portalMismatch","maxRecordsPerPush","objects"],"type":"object"},"InstantSearchRequest":{"properties":{"entities":{"description":"Entity types to search (default: all)","items":{"type":"string"},"type":"array"},"filters":{"additionalProperties":{"type":"string"},"description":"Per-entity filter strings","type":"object"},"limit":{"description":"Max results per entity (default: 5)","maximum":50,"minimum":1,"type":"integer"},"query":{"description":"Search query","minLength":1,"type":"string"}},"required":["query"],"type":"object"},"InstantSearchResponse":{"properties":{"results":{"additionalProperties":{"items":{"nullable":true},"type":"array"},"type":"object"}},"required":["results"],"type":"object"},"Interval":{"enum":["weekly","monthly","quarterly","yearly"],"type":"string"},"LenderDetail":{"allOf":[{"$ref":"#/components/schemas/LenderSummary"},{"properties":{},"type":"object"}]},"LenderDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/LenderDetail"}},"required":["data"],"type":"object"},"LenderFilterEntry":{"properties":{"canonical":{"description":"Canonical lender name (the `value` from lender autocomplete). Resolved to a lender id server-side; pass `id` instead when you have one.","type":"string"},"displayName":{"description":"Label / typed search string","type":"string"},"id":{"description":"Lender-dictionary id — the `id` from instantSearch / listLenders (e.g. \"mortgage_rocket\" or \"mortgage rocket\"), and the same value the `lender` filter takes. PREFERRED: matched directly against the stored lender key with no name resolution. `canonical` is still accepted and resolved server-side.","type":"string"},"mode":{"enum":["include","exclude"],"type":"string"},"percentMin":{"description":"Minimum percent_of_volume (0–100); 0/undefined = > 0%","maximum":100,"minimum":0,"type":"number"},"type":{"enum":["canonical","freetext"],"type":"string"}},"required":["displayName"],"type":"object"},"LenderListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"mode":{"enum":["and","or"],"type":"string"},"name":{"$ref":"#/components/schemas/TextFilterValue"},"totalDocuments":{"$ref":"#/components/schemas/NumericFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"sort":{"items":{"properties":{"field":{"enum":["name","totalDocuments"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"LenderListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/LenderSummary"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"LenderMatchMode":{"enum":["and","or"],"type":"string"},"LenderNormalization":{"properties":{"aliasCount":{"description":"Stored lender-name variants this id expands to","minimum":0,"type":"integer"},"displayName":{"nullable":true,"type":"string"},"id":{"description":"Canonical lender-dictionary id, or null","nullable":true,"type":"string"},"matchedVia":{"description":"`id` = the value already WAS a canonical key; `alias` = a stored lender name; `name` = matched the display/canonical name; `unresolved` = fell back to raw text match; `degraded` = the dictionary could not be consulted.","enum":["id","alias","name","unresolved","degraded"],"type":"string"},"original":{"description":"The value the caller sent","type":"string"},"totalDocuments":{"description":"Loans the dictionary attributes to this id. A small number next to a well-known lender name means the name matched a minor entry.","minimum":0,"type":"integer"}},"required":["original","id","displayName","matchedVia","aliasCount","totalDocuments"],"type":"object"},"LenderSummary":{"properties":{"canonicalName":{"nullable":true,"type":"string"},"displayName":{"nullable":true,"type":"string"},"id":{"type":"string"},"totalDocuments":{"nullable":true,"type":"number"}},"required":["id"],"type":"object"},"LoanBorrowerStatusFilterValue":{"anyOf":[{"description":"One of (case-insensitive): Current, PSALE, PWNLO, PWCLO, C_PWNLO, C_PWCLO, R_CWNLO, R_CWCLO, E_CWNLO, E_CWCLO, REO_CWNLO, REO_CWCLO, UNK_NOORIG, UNK_PWNLO, UNK_PWCLO","enum":["Current","PSALE","PWNLO","PWCLO","C_PWNLO","C_PWCLO","R_CWNLO","R_CWCLO","E_CWNLO","E_CWCLO","REO_CWNLO","REO_CWCLO","UNK_NOORIG","UNK_PWNLO","UNK_PWCLO"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): Current, PSALE, PWNLO, PWCLO, C_PWNLO, C_PWCLO, R_CWNLO, R_CWCLO, E_CWNLO, E_CWCLO, REO_CWNLO, REO_CWCLO, UNK_NOORIG, UNK_PWNLO, UNK_PWCLO","enum":["Current","PSALE","PWNLO","PWCLO","C_PWNLO","C_PWCLO","R_CWNLO","R_CWCLO","E_CWNLO","E_CWCLO","REO_CWNLO","REO_CWCLO","UNK_NOORIG","UNK_PWNLO","UNK_PWCLO"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}],"description":"ModelMatch-derived loan position: whether the borrower on THIS loan is still the property's current owner. Codes read as [purpose_](C|P)W(N|C)LO — CW = current owner, PW = previous owner; NLO = a different originator than the prior loan, CLO = the same one (the retention signal).\n\nCURRENT OWNER — `Current` (no newer loan), `R_CWCLO`/`R_CWNLO` (refinanced), `E_CWCLO`/`E_CWNLO` (took equity). For \"past clients still in the home\" pass ALL FIVE: `\"Current\"` on its own silently drops ~5M loans whose borrower is still there but has since refinanced or tapped equity.\n\nPREVIOUS OWNER — `PSALE` (home sold), `PWCLO`/`PWNLO` (purchase loan), `C_PWCLO`/`C_PWNLO` (construction loan).\n\nUNKNOWN — `UNK_NOORIG` (the property's most recent loan had no originator; ~64% of all populated values), `UNK_PWCLO`/`UNK_PWNLO` (most recent loan was not a purchase). `REO_CWNLO`/`REO_CWCLO` exist but are vanishingly rare (<300 loans total) and are not classified in the source glossary.\n\nOnly ~69% of loans carry any status, so an absent value means unknown — not \"not current\"."},"LoanChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"after":{"description":"PARTY slices only. Opaque cursor from a previous page's `nextCursor`; send the same body otherwise. A cursor is bound to the `slice` and `measure` it was issued for (400 if they change). It is an offset into the ranking, so a rolling `period` re-resolved on a later UTC day ranks a shifted window.","minLength":1,"type":"string"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"segment":{"allOf":[{"$ref":"#/components/schemas/LoanSlice"},{"description":"Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."}]},"size":{"description":"PARTY slices only (`originator`, `broker`, `loanCompany`; 400 on any other slice). Page size for the ranking, 1–1000. Passing `size` (or `after`) turns on paging: the response gains `total` / `totalApproximate` and, when more buckets remain, `nextCursor`, and drops `omittedCount`. Buckets stay ranked by `measure` descending (ties broken by key), and bucket labels stay NMLS ids. Default when only `after` is sent: 200, the fixed chart's bucket count. Paging reaches the top 10,000 ranked buckets.","maximum":1000,"minimum":1,"type":"integer"},"slice":{"$ref":"#/components/schemas/LoanSlice"}},"required":["slice"],"type":"object"},"LoanDetail":{"allOf":[{"$ref":"#/components/schemas/LoanSummary"},{"properties":{"buyers":{"items":{"nullable":true},"nullable":true,"type":"array"},"downPayment":{"nullable":true},"employersAtTimeOfLoan":{"items":{"type":"string"},"nullable":true,"type":"array"},"equity":{"nullable":true,"type":"number"},"estimatedPayment":{"nullable":true,"type":"number"},"homeValue":{"nullable":true,"type":"number"},"listAgent":{"nullable":true},"ltv":{"nullable":true,"type":"number"},"mmSaleId":{"nullable":true,"type":"string"},"propertyUseCode":{"nullable":true,"type":"string"},"recordingDate":{"nullable":true,"type":"string"},"sellers":{"items":{"nullable":true},"nullable":true,"type":"array"},"soldAgent":{"nullable":true},"titleCompany":{"nullable":true}},"type":"object"}]},"LoanDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/LoanDetail"}},"required":["data"],"type":"object"},"LoanListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"agentId":{"description":"Loans crediting this agent (`GET /v1/agents/{id}`) — the rows' `*AgentId`; see `agentRole`. ≤ 10,000 candidate loans in scope (else 400).","minLength":1,"type":"string"},"agentRole":{"description":"`agentId`'s role: `sold`, `list`, `coList`, `listing` (list or co-list), `any` (default).","enum":["any","sold","list","coList","listing"],"type":"string"},"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"coListAgentName":{"description":"Co-listing agent name.","maxLength":100,"minLength":1,"type":"string"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"hasAgent":{"description":"Roles that must have an agent: `sold` (buyer's), `list`, `coList`; `any` = at least one.","items":{"enum":["any","sold","list","coList"],"type":"string"},"minItems":1,"type":"array"},"hasBuilder":{"description":"`true`: new construction — a sale of the property names a builder, or the loan names a builder or a builder seller of record. `false`: the rest. Needs a scope of ≤ 50,000 loans (else 400).","type":"boolean"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"listAgentName":{"description":"Listing agent name.","maxLength":100,"minLength":1,"type":"string"},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"search":{"description":"Every word starts a word of the address (street, city, state, ZIP), the lender name or an agent name (\"12 oak\", \"jane sm\").","maxLength":100,"minLength":1,"type":"string"},"soldAgentName":{"description":"Buyer's agent: every word starts a word of the MLS name or the linked agent's name. Likewise `listAgentName`, `coListAgentName`.","maxLength":100,"minLength":1,"type":"string"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"sort":{"items":{"properties":{"field":{"enum":["city","state","zipCode","county","transactionType","loanType","conforming","mortgageAmount","mortgageDate","broker","loanCompany","lender","borrowerStatus","salePrice","saleDate","originator","originatorName","interestRate","equity","homeValue","ltvAtOrigination","currentBalance","streetAddress","listPrice","employerName","brokerName","soldAgentName","listAgentName","coListAgentName"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"LoanListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/LoanSummary"},"type":"array"},"lenderNormalizations":{"description":"How each `lenderName` value resolved against the lender dictionary. Present when a `lenderName` filter was supplied.","items":{"$ref":"#/components/schemas/LenderNormalization"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"},"truncated":{"description":"Row sorts only: more than 10,000 loans matched; the newest 10,000 were sorted and `total` counts them.","type":"boolean"}},"required":["data","total"],"type":"object"},"LoanSegment":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`. Time-series only: `titleCompany` groups on the title company named on the deed, with spellings of one company merged per bucket (`label` = most-used spelling across the response, `id` = normalized name — match on `id`) and \"none available\"-style placeholders excluded.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","broker","loanCompany","originator","titleCompany"],"type":"string"},"LoanSlice":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","broker","loanCompany","originator"],"type":"string"},"LoanSummary":{"properties":{"apn":{"nullable":true,"type":"string"},"borrowerName":{"nullable":true,"type":"string"},"borrowerStatus":{"enum":["Current","PSALE","PWNLO","PWCLO","C_PWNLO","C_PWCLO","R_CWNLO","R_CWCLO","E_CWNLO","E_CWCLO","REO_CWNLO","REO_CWCLO","UNK_NOORIG","UNK_PWNLO","UNK_PWCLO",null],"nullable":true,"type":"string"},"brokerName":{"description":"Mortgage broker as written on the loan document, when third-party originated.","nullable":true,"type":"string"},"brokerNmlsId":{"nullable":true,"type":"string"},"builderName":{"description":"Builder named on a sale of this property (new construction); the `hasBuilder` predicate.","nullable":true,"type":"string"},"buyer1FirstMiddle":{"description":"First buyer's first + middle name (an entity's whole name, with no last).","nullable":true,"type":"string"},"buyer1Last":{"description":"First buyer's last name.","nullable":true,"type":"string"},"buyer2FirstMiddle":{"description":"Second buyer's first + middle name.","nullable":true,"type":"string"},"buyer2Last":{"description":"Second buyer's last name.","nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"coListAgentId":{"description":"Co-listing agent id, same rule.","nullable":true,"type":"string"},"coListAgentName":{"description":"Co-listing agent: the agent record's name when the MLS keys resolve to one agent, else as the MLS recorded it.","nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"conforming":{"nullable":true,"type":"boolean"},"coordinates":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"employerName":{"description":"Employer at the time of the loan (the LO's company then), as recorded. Not `companyName`, the funding company on the document.","nullable":true,"type":"string"},"employerNmlsId":{"description":"NMLS id of `employerName`.","nullable":true,"type":"string"},"fips":{"nullable":true,"type":"string"},"id":{"type":"string"},"interestRate":{"nullable":true,"type":"number"},"lenderId":{"description":"Normalized lender id — the value the `lender` filter takes.","nullable":true,"type":"string"},"lenderName":{"nullable":true,"type":"string"},"listAgentId":{"description":"Listing agent id, same rule.","nullable":true,"type":"string"},"listAgentName":{"description":"Listing agent: the agent record's name when the MLS keys resolve to one agent, else as the MLS recorded it.","nullable":true,"type":"string"},"listPrice":{"nullable":true,"type":"number"},"loanTermMonths":{"nullable":true,"type":"number"},"loanType":{"nullable":true,"type":"string"},"mmPropertyId":{"nullable":true,"type":"string"},"mortgageAmount":{"nullable":true,"type":"number"},"mortgageDate":{"nullable":true,"type":"string"},"originatorEmail":{"deprecated":true,"description":"DEPRECATED — ALWAYS NULL. Loan records carry no originator email field, so this is null on every loan; it is retained only for response-shape compatibility. To get a loan officer's email, take `originatorNmlsId` from this response and fetch the originator (`GET /v1/originators/{nmlsId}`), whose `email` field carries it — available for roughly 14% of loan officers.","nullable":true,"type":"string"},"originatorName":{"nullable":true,"type":"string"},"originatorNmlsId":{"nullable":true,"type":"string"},"salePrice":{"nullable":true,"type":"number"},"seller1FirstMiddle":{"description":"First seller's first + middle name.","nullable":true,"type":"string"},"seller1Last":{"description":"First seller's last name.","nullable":true,"type":"string"},"seller2FirstMiddle":{"description":"Second seller's first + middle name.","nullable":true,"type":"string"},"seller2Last":{"description":"Second seller's last name.","nullable":true,"type":"string"},"sellerName":{"nullable":true,"type":"string"},"soldAgentId":{"description":"Buyer's agent id (`GET /v1/agents/{id}`) when the MLS keys resolve to one agent.","nullable":true,"type":"string"},"soldAgentName":{"description":"Buyer's agent: the agent record's name when the loan's MLS agent keys resolve to one agent, else as the MLS recorded it; lowercase.","nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"streetAddress":{"nullable":true,"type":"string"},"titleCompanyName":{"description":"Title company name.","nullable":true,"type":"string"},"transactionDate":{"nullable":true,"type":"string"},"transactionType":{"nullable":true,"type":"string"},"zipCode":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"LoanSummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"period":{"$ref":"#/components/schemas/DatedPeriod"}},"type":"object"},"LoanTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"segment":{"$ref":"#/components/schemas/LoanSegment"}},"type":"object"},"LoanTransactionTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): purchase, refinance, construction, equity, reo","enum":["purchase","refinance","construction","equity","reo"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): purchase, refinance, construction, equity, reo","enum":["purchase","refinance","construction","equity","reo"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"LoanTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): conventional, fha, va, usda, he, heloc, building, balloon, commercial, reverse, sba, assumption, stand_alone_refi, stand_alone_second, aggregate, closed_end, negative_amortization, land_contract, modification, trade, other, unknown","enum":["conventional","fha","va","usda","he","heloc","building","balloon","commercial","reverse","sba","assumption","stand_alone_refi","stand_alone_second","aggregate","closed_end","negative_amortization","land_contract","modification","trade","other","unknown"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): conventional, fha, va, usda, he, heloc, building, balloon, commercial, reverse, sba, assumption, stand_alone_refi, stand_alone_second, aggregate, closed_end, negative_amortization, land_contract, modification, trade, other, unknown","enum":["conventional","fha","va","usda","he","heloc","building","balloon","commercial","reverse","sba","assumption","stand_alone_refi","stand_alone_second","aggregate","closed_end","negative_amortization","land_contract","modification","trade","other","unknown"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"LocationNormalization":{"properties":{"candidates":{"description":"Location ids matching an ambiguous name, ranked. Use `instantSearch` or `suggestLocations` to pick one.","items":{"type":"string"},"type":"array"},"confidence":{"description":"\"exact\" — matched a dictionary entry as written. \"normalized\" — resolved to a different spelling or merged several candidates. \"fallback\" — NOT resolved; the raw value was passed through, so a zero result means the name was not recognized rather than empty.","enum":["exact","normalized","fallback"],"example":"normalized","type":"string"},"displayName":{"example":"Saint Louis, MO","type":"string"},"field":{"description":"The filter key this applies to","example":"city","type":"string"},"id":{"description":"Resolved location id — pass this back for an exact filter","example":"city_mo_saint-louis","type":"string"},"normalized":{"example":"Saint Louis","type":"string"},"original":{"example":"St. Louis","type":"string"},"variants":{"description":"Spellings actually queried against the index","items":{"type":"string"},"type":"array"}},"required":["field","original","normalized","displayName","confidence"],"type":"object"},"LocationRetrieveResponse":{"properties":{"location":{"$ref":"#/components/schemas/NormalizedLocation"}},"required":["location"],"type":"object"},"LocationSuggestResponse":{"properties":{"suggestions":{"items":{"$ref":"#/components/schemas/MapboxSuggestion"},"type":"array"}},"required":["suggestions"],"type":"object"},"MapboxSuggestion":{"properties":{"feature_type":{"type":"string"},"full_address":{"type":"string"},"id":{"description":"Location dictionary id (e.g. `city_mo_saint-louis`). Pass this to a city / county filter. Absent on Mapbox address suggestions.","type":"string"},"mapbox_id":{"description":"Pass to `retrieveLocation`. On a dictionary suggestion this is the location `id`; on a Mapbox suggestion it is the Mapbox feature id.","type":"string"},"name":{"type":"string"},"place_formatted":{"type":"string"},"source":{"description":"Where the suggestion came from. `dictionary` suggestions carry an `id` that filters accept; `mapbox` suggestions are addresses and coordinates only.","enum":["dictionary","mapbox"],"type":"string"},"state":{"type":"string"},"totalCount":{"description":"Records across all entities at this location — a popularity signal for ranking, not a filter result count.","type":"number"},"type":{"description":"Location type — `city` or `county`.","type":"string"}},"required":["mapbox_id","name","feature_type"],"type":"object"},"MarketChartMeasure":{"default":"units","description":"Which metric to compute. Every field-backed measure is sentinel-guarded: the source encodes unknown values as an out-of-range fill, so values outside the measure's plausible range are dropped before it is aggregated. Ranges: `volume` 0–100,000,000; `avgRate` 0–25; `avgLoanAmount` 0–100,000,000; `avgCreditScore` 300–850; `avgLTV` 0–999; `avgDTI` 0–999; `avgIncome` 0–100,000,000; `avgAppraisedValue` 0–100,000,000; `avgPurchasePrice` 0–100,000,000; `avgDtiFront` 0–999; `avgCombinedLtv` 0–999; `avgLoanTerm` 0–1,200; `originatedVolume` 0–100,000,000; `originatedAvgDti` 0–100. `units` and `originatedUnits` are document counts and are not guarded. Each response reports how many documents its guard excluded, so a mean taken over 98% of the data can be told apart from one taken over 60%. NOTE on population: `units` and `volume` cover loan APPLICATIONS of every outcome — denials, withdrawals and secondary-market purchases included — and so does `avgDTI`, while `originatedUnits`, `originatedVolume` and `originatedAvgDti` cover originations only. Which metric each bar reports, AND what the bars are ranked by — the list is ordered by the measure you ask for, descending. Defaults to `units`, so an unqualified \"top originators\" means the busiest; pass `volume` for the biggest by dollars, or an average to rank by that average. Two things to know about the averages specifically. Buckets built from fewer than 5 documents are dropped from an average chart entirely, because a mean says nothing about how many transactions produced it and a single-transaction bucket would otherwise outrank real ones; no floor is applied to `units` or `volume`, where a lone large transaction is a legitimate top bar. And ranking a bucket list by a sub-aggregated average is approximate in the search engine — each shard contributes its own local top-N before they are merged — so treat the ordering of an average chart as indicative near the boundary rather than exact. Every bucket publishes its own `count`, so the sample size behind a value is never implicit.","enum":["volume","units","avgRate","avgLoanAmount","avgCreditScore","avgLTV","avgDTI","avgIncome","avgAppraisedValue","avgPurchasePrice","avgDtiFront","avgCombinedLtv","avgLoanTerm","originatedUnits","originatedVolume","originatedAvgDti"],"type":"string"},"MarketChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/MarketFlatFilters"},"measure":{"$ref":"#/components/schemas/MarketChartMeasure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"slice":{"$ref":"#/components/schemas/MarketSliceDimension"}},"required":["slice"],"type":"object"},"MarketCommunityBucket":{"properties":{"avgMinorityTractPct":{"description":"Average non-white share (0-100) of the neighborhood population across originations that carry it. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgTractIncomeVsMetroPct":{"description":"Average neighborhood median family income as a percent of its metro area's — 100 is parity, and it legitimately exceeds 100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"craEligibleCoverage":{"description":"Originations carrying a CRA-eligibility determination — the denominator of `craEligibleSharePct`. Effectively the whole population: the determination is loan-level and is present on every record.","type":"number"},"craEligibleOriginations":{"type":"number"},"craEligibleSharePct":{"description":"Share (0-100) of `craEligibleCoverage` that is CRA-eligible — a low- or moderate-income neighborhood OR a low- or moderate-income borrower. Null when nothing in scope carries the determination.","nullable":true,"type":"number"},"incomeBandCoverage":{"description":"Originations whose neighborhood carries an income band — the denominator of `lowModIncomeTractSharePct`, `middleIncomeTractSharePct` and every `incomeBands[].sharePct`. READ THIS FIRST: roughly a fifth of records carry a band, and a share taken over the full population instead is about 4.5x too low.","type":"number"},"incomeBands":{"items":{"$ref":"#/components/schemas/MarketCommunityIncomeBand"},"type":"array"},"key":{"description":"The dimension value this bucket covers — a metro (CBSA) code for `metro`, a state code for `state`, and so on.","type":"string"},"lowModIncomeTractOriginations":{"type":"number"},"lowModIncomeTractSharePct":{"description":"Share (0-100) of `incomeBandCoverage` originated in a low- or moderate-income neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractOriginations":{"type":"number"},"majorityMinorityTractSharePct":{"description":"Share (0-100) of `minorityTractCoverage` originated in a majority-minority neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"middleIncomeTractOriginations":{"type":"number"},"middleIncomeTractSharePct":{"description":"Share (0-100) of `incomeBandCoverage` originated in a middle-income neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"minorityTractCoverage":{"description":"Originations whose neighborhood carries the majority-minority determination — the denominator of `majorityMinorityTractSharePct` and the population behind `avgMinorityTractPct`. About half of all records; it is a different denominator from `incomeBandCoverage`.","type":"number"},"originations":{"description":"Originations matched by the filters in this scope.","type":"number"}},"required":["key","originations","craEligibleOriginations","craEligibleCoverage","craEligibleSharePct","incomeBandCoverage","lowModIncomeTractOriginations","lowModIncomeTractSharePct","middleIncomeTractOriginations","middleIncomeTractSharePct","incomeBands","majorityMinorityTractOriginations","minorityTractCoverage","majorityMinorityTractSharePct","avgMinorityTractPct","avgTractIncomeVsMetroPct"],"type":"object"},"MarketCommunityIncomeBand":{"description":"One FFIEC tract income band and its share (0-100) of `incomeBandCoverage`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","properties":{"level":{"enum":["low","moderate","middle","upper"],"type":"string"},"originations":{"type":"number"},"sharePct":{"nullable":true,"type":"number"}},"required":["level","originations","sharePct"],"type":"object"},"MarketCommunityIncomeLevel":{"anyOf":[{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}],"description":"FFIEC income classification of the neighborhood the property sits in. A tract-level aggregate statistic describing the neighborhood, never an individual, household or applicant attribute. Carried on roughly a fifth of originations, so this filter narrows sharply."},"MarketCommunityLendingRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/MarketFlatFilters"},"limit":{"description":"Maximum buckets when `slice` is supplied (default 25, max 200).","maximum":200,"minimum":1,"type":"integer"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"slice":{"description":"Break the mix down by a market dimension — `metro` for the metro (CBSA) grain, `state` / `county` / `zip` for geography, or any product dimension. Each bucket reports its OWN denominators, so bucket shares are comparable to each other and to the overall mix. Omit for the overall mix only.","enum":["state","county","metro","zip","loanPurpose","loanType","propertyType","occupancyType","amortizationType","channel","borrowerGeneration","firstTimeHomebuyer","veteranIndicator","hmdaActionTaken","selfEmployed","currentHomeOwner"],"type":"string"}},"type":"object"},"MarketCommunityLendingResponse":{"properties":{"overall":{"$ref":"#/components/schemas/MarketCommunityMix"},"slice":{"properties":{"buckets":{"items":{"$ref":"#/components/schemas/MarketCommunityBucket"},"type":"array"},"dimension":{"type":"string"}},"required":["dimension","buckets"],"type":"object"}},"required":["overall"],"type":"object"},"MarketCommunityMix":{"properties":{"avgMinorityTractPct":{"description":"Average non-white share (0-100) of the neighborhood population across originations that carry it. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"avgTractIncomeVsMetroPct":{"description":"Average neighborhood median family income as a percent of its metro area's — 100 is parity, and it legitimately exceeds 100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"craEligibleCoverage":{"description":"Originations carrying a CRA-eligibility determination — the denominator of `craEligibleSharePct`. Effectively the whole population: the determination is loan-level and is present on every record.","type":"number"},"craEligibleOriginations":{"type":"number"},"craEligibleSharePct":{"description":"Share (0-100) of `craEligibleCoverage` that is CRA-eligible — a low- or moderate-income neighborhood OR a low- or moderate-income borrower. Null when nothing in scope carries the determination.","nullable":true,"type":"number"},"incomeBandCoverage":{"description":"Originations whose neighborhood carries an income band — the denominator of `lowModIncomeTractSharePct`, `middleIncomeTractSharePct` and every `incomeBands[].sharePct`. READ THIS FIRST: roughly a fifth of records carry a band, and a share taken over the full population instead is about 4.5x too low.","type":"number"},"incomeBands":{"items":{"$ref":"#/components/schemas/MarketCommunityIncomeBand"},"type":"array"},"lowModIncomeTractOriginations":{"type":"number"},"lowModIncomeTractSharePct":{"description":"Share (0-100) of `incomeBandCoverage` originated in a low- or moderate-income neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractOriginations":{"type":"number"},"majorityMinorityTractSharePct":{"description":"Share (0-100) of `minorityTractCoverage` originated in a majority-minority neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"middleIncomeTractOriginations":{"type":"number"},"middleIncomeTractSharePct":{"description":"Share (0-100) of `incomeBandCoverage` originated in a middle-income neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"minorityTractCoverage":{"description":"Originations whose neighborhood carries the majority-minority determination — the denominator of `majorityMinorityTractSharePct` and the population behind `avgMinorityTractPct`. About half of all records; it is a different denominator from `incomeBandCoverage`.","type":"number"},"originations":{"description":"Originations matched by the filters in this scope.","type":"number"}},"required":["originations","craEligibleOriginations","craEligibleCoverage","craEligibleSharePct","incomeBandCoverage","lowModIncomeTractOriginations","lowModIncomeTractSharePct","middleIncomeTractOriginations","middleIncomeTractSharePct","incomeBands","majorityMinorityTractOriginations","minorityTractCoverage","majorityMinorityTractSharePct","avgMinorityTractPct","avgTractIncomeVsMetroPct"],"type":"object"},"MarketConcentrationFilterValue":{"additionalProperties":false,"description":"Share of the originator's period volume held by their SINGLE LARGEST city, as a 0–100 percent. `{gte:50}` = 'at least half their book is in one city'. LOWER BOUNDS ONLY (`gte`/`gt`): an upper bound on this reads as 'some market is small', which is true of almost everyone — to find diversified producers use `marketCount` instead.","properties":{"gt":{"maximum":100,"minimum":0,"type":"number"},"gte":{"maximum":100,"minimum":0,"type":"number"},"lt":{"maximum":100,"minimum":0,"type":"number"},"lte":{"maximum":100,"minimum":0,"type":"number"}},"type":"object"},"MarketExcludedCounts":{"description":"Per-measure count of documents this query's sentinel guard excluded — documents that carry the measure's field but whose value is an out-of-range fill. Compare against `units` to see what share of the matched population each average was actually computed over. Absent for `units` (a document count, not a guarded metric).","properties":{"avgAppraisedValue":{"type":"number"},"avgCombinedLtv":{"type":"number"},"avgCreditScore":{"type":"number"},"avgDTI":{"type":"number"},"avgDtiFront":{"type":"number"},"avgIncome":{"type":"number"},"avgLTV":{"type":"number"},"avgLoanAmount":{"type":"number"},"avgLoanTerm":{"type":"number"},"avgPurchasePrice":{"type":"number"},"avgRate":{"type":"number"},"originatedAvgDti":{"type":"number"},"originatedVolume":{"type":"number"},"volume":{"type":"number"}},"type":"object"},"MarketField":{"enum":["state","county","zip","closingDate","loanPurpose","loanType","propertyType","occupancyType","amortizationType","channel","noteRate","loanAmount","creditScore","ltv","dti","income","appraisedValue","purchasePrice","combinedLtv","dtifront","loanTerm","hmdaActionTaken","loanApplicationDate"],"type":"string"},"MarketFlatFilters":{"additionalProperties":false,"properties":{"amortizationType":{"$ref":"#/components/schemas/TextFilterValue"},"appraisedValue":{"$ref":"#/components/schemas/NumericFilterValue"},"channel":{"$ref":"#/components/schemas/TextFilterValue"},"closingDate":{"$ref":"#/components/schemas/DateFilterValue"},"combinedLtv":{"$ref":"#/components/schemas/NumericFilterValue"},"communityIncomeLevel":{"$ref":"#/components/schemas/MarketCommunityIncomeLevel"},"county":{"$ref":"#/components/schemas/TextFilterValue"},"countyCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"3-digit county code (the county segment of a FIPS, e.g. Philadelphia = \"101\"). Pair it with `state` — the code is not unique across states. `county` accepts a county NAME or 5-digit FIPS and resolves to this code for you."}]},"craEligible":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Only CRA-eligible originations (a low- or moderate-income neighborhood OR a low- or moderate-income borrower). Determined on every origination."}]},"creditScore":{"$ref":"#/components/schemas/NumericFilterValue"},"dti":{"$ref":"#/components/schemas/NumericFilterValue"},"dtifront":{"$ref":"#/components/schemas/NumericFilterValue"},"hmdaActionTaken":{"$ref":"#/components/schemas/TextFilterValue"},"income":{"$ref":"#/components/schemas/NumericFilterValue"},"loanAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"loanApplicationDate":{"$ref":"#/components/schemas/DateFilterValue"},"loanPurpose":{"$ref":"#/components/schemas/TextFilterValue"},"loanTerm":{"$ref":"#/components/schemas/NumericFilterValue"},"loanType":{"$ref":"#/components/schemas/TextFilterValue"},"lowModIncomeTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Only originations in a low- or moderate-income neighborhood. This describes the U.S. Census tract (neighborhood) as a whole — a tract-level aggregate statistic, never an individual, household or applicant attribute. `false` also matches originations whose neighborhood carries no income classification; pair with `communityIncomeLevel` when you need the classified population only."}]},"ltv":{"$ref":"#/components/schemas/NumericFilterValue"},"majorityMinorityTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Only originations in a majority-minority neighborhood. This describes the U.S. Census tract (neighborhood) as a whole — a tract-level aggregate statistic, never an individual, household or applicant attribute. Carried on about half of originations."}]},"metro":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Metro area code (5-digit federal CBSA code, e.g. Los Angeles = \"31084\"). Roughly half of originations sit outside any metro area and carry no code, so a metro filter is a narrowing one."}]},"middleIncomeTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Only originations in a middle-income neighborhood. Tract-level aggregate, never an individual attribute. Same caveat on `false` as `lowModIncomeTract`."}]},"minorityTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Non-white share (0-100) of the neighborhood's population. Tract-level aggregate, never an individual attribute."}]},"mode":{"enum":["and","or"],"type":"string"},"noteRate":{"$ref":"#/components/schemas/NumericFilterValue"},"occupancyType":{"$ref":"#/components/schemas/TextFilterValue"},"propertyType":{"$ref":"#/components/schemas/TextFilterValue"},"purchasePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"tractIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Neighborhood median family income as a percent of its metro area's — 100 is parity, and it legitimately exceeds 100. Tract-level aggregate, never an individual attribute."}]},"zip":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"MarketListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/MarketFlatFilters"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/MarketField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"MarketListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/MarketRecord"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"MarketMeasure":{"description":"Which metric to compute. Every field-backed measure is sentinel-guarded: the source encodes unknown values as an out-of-range fill, so values outside the measure's plausible range are dropped before it is aggregated. Ranges: `volume` 0–100,000,000; `avgRate` 0–25; `avgLoanAmount` 0–100,000,000; `avgCreditScore` 300–850; `avgLTV` 0–999; `avgDTI` 0–999; `avgIncome` 0–100,000,000; `avgAppraisedValue` 0–100,000,000; `avgPurchasePrice` 0–100,000,000; `avgDtiFront` 0–999; `avgCombinedLtv` 0–999; `avgLoanTerm` 0–1,200; `originatedVolume` 0–100,000,000; `originatedAvgDti` 0–100. `units` and `originatedUnits` are document counts and are not guarded. Each response reports how many documents its guard excluded, so a mean taken over 98% of the data can be told apart from one taken over 60%. NOTE on population: `units` and `volume` cover loan APPLICATIONS of every outcome — denials, withdrawals and secondary-market purchases included — and so does `avgDTI`, while `originatedUnits`, `originatedVolume` and `originatedAvgDti` cover originations only.","enum":["volume","units","avgRate","avgLoanAmount","avgCreditScore","avgLTV","avgDTI","avgIncome","avgAppraisedValue","avgPurchasePrice","avgDtiFront","avgCombinedLtv","avgLoanTerm","originatedUnits","originatedVolume","originatedAvgDti"],"type":"string"},"MarketMetrics":{"properties":{"avgAppraisedValue":{"description":"Average appraised property value. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"avgCombinedLtv":{"description":"Average combined LTV (including subordinate liens). Excludes values outside 0–999 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"avgCreditScore":{"description":"Average credit score. Excludes values outside 300–850 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgDTI":{"description":"Average back-end DTI ratio across loan APPLICATIONS matching the filters — every outcome, on the same population as `units`. A denied application carries a much higher ratio than a funded loan, often above 100, so this figure sits several points above what closed borrowers actually carry. For originations use `originatedAvgDti`. Excludes values outside 0–999 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgDtiFront":{"description":"Average front-end DTI ratio. Excludes values outside 0–999 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"avgIncome":{"description":"Average household annual income. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgLTV":{"description":"Average LTV ratio. Excludes values outside 0–999 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgLoanAmount":{"description":"Average loan amount. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgLoanTerm":{"description":"Average loan term in months. Excludes values outside 0–1,200 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"avgPurchasePrice":{"description":"Average purchase price. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"avgRate":{"description":"Average note rate. Excludes values outside 0–25 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"excluded":{"$ref":"#/components/schemas/MarketExcludedCounts"},"originatedAvgDti":{"description":"Average back-end DTI ratio across ORIGINATED loans only — the subset of applications whose `hmdaActionTaken` is \"loan originated\". Prefer this over `avgDTI` for any question about what borrowers who actually got a loan are carrying. `avgDTI` averages applications of EVERY outcome, and a denied application legitimately carries a far higher ratio — often above 100 — because that is frequently why it was denied, so the two figures differ by several points on the same filters and neither is a correction of the other. `null` when the matched set contains no originations. Excludes values outside 0–100 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"originatedUnits":{"description":"Loans ORIGINATED — the subset of `units` whose `hmdaActionTaken` is \"loan originated\". This is the count most callers mean by \"number of loans\"","type":"number"},"originatedVolume":{"description":"Total dollar volume of ORIGINATED loans — the subset of `volume` whose `hmdaActionTaken` is \"loan originated\". Pair with `originatedUnits` for an originated average loan size. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"outcomes":{"description":"How the matched applications split by outcome — a complete PARTITION of `units` and `volume`, so the two headline numbers can be reconciled against their parts without a second query. Roughly half of all rows are not originated loans and the share varies widely by geography, so no fixed correction ratio exists. Summary only: on the chart use `slice: \"hmdaActionTaken\"`, on the time-series `segment: \"hmdaActionTaken\"`.","items":{"$ref":"#/components/schemas/MarketOutcomeBucket"},"type":"array"},"units":{"description":"Loan APPLICATIONS matching the filters — every outcome, not just originations. Withdrawn, denied, closed-for-incompleteness and secondary-market purchases are all counted here; roughly half of all rows are not originated loans, and the originated share varies enough by geography that no fixed correction ratio exists. For originations use `originatedUnits`; `outcomes` reports the full breakdown, and `hmdaActionTaken` filters on it","type":"number"},"volume":{"description":"Total dollar volume of loan APPLICATIONS matching the filters — every outcome, on the same population as `units`, not just originations. For originated dollars use `originatedVolume`. `volume` ÷ `units` is an application average, not an originated average. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"}},"required":["volume","units","avgRate","avgLoanAmount","avgCreditScore","avgLTV","avgDTI","avgIncome","avgAppraisedValue","avgPurchasePrice","avgDtiFront","avgCombinedLtv","avgLoanTerm","originatedUnits","originatedVolume","originatedAvgDti"],"type":"object"},"MarketOutcomeBucket":{"properties":{"outcome":{"description":"The application outcome, exactly as stored — the same vocabulary the `hmdaActionTaken` filter accepts, so any bucket here can be reproduced as a filter. The empty-string bucket carries rows with no outcome recorded. One value is a leaked source header row and is not a real outcome.","type":"string"},"units":{"description":"Applications with this outcome. These sum to `units`.","type":"number"},"volume":{"description":"Dollar volume for this outcome. These sum to `volume`.","type":"number"}},"required":["outcome","units","volume"],"type":"object"},"MarketRecord":{"properties":{"amortizationType":{"nullable":true,"type":"string"},"appraisedValue":{"nullable":true,"type":"number"},"borrowerGeneration":{"nullable":true,"type":"string"},"channel":{"nullable":true,"type":"string"},"closingDate":{"nullable":true,"type":"string"},"combinedLtv":{"nullable":true,"type":"number"},"county":{"nullable":true,"type":"string"},"creditScore":{"nullable":true,"type":"number"},"currentHomeOwner":{"nullable":true,"type":"boolean"},"dti":{"nullable":true,"type":"number"},"dtifront":{"nullable":true,"type":"number"},"firstTimeHomebuyer":{"nullable":true,"type":"boolean"},"fundingDate":{"nullable":true,"type":"string"},"hmdaActionTaken":{"nullable":true,"type":"string"},"id":{"description":"Document ID","type":"string"},"income":{"nullable":true,"type":"number"},"loanAmount":{"nullable":true,"type":"number"},"loanApplicationDate":{"nullable":true,"type":"string"},"loanPurpose":{"nullable":true,"type":"string"},"loanTerm":{"nullable":true,"type":"number"},"loanType":{"nullable":true,"type":"string"},"ltv":{"nullable":true,"type":"number"},"noteRate":{"nullable":true,"type":"number"},"occupancyType":{"nullable":true,"type":"string"},"propertyType":{"nullable":true,"type":"string"},"purchasePrice":{"nullable":true,"type":"number"},"selfEmployed":{"nullable":true,"type":"boolean"},"state":{"nullable":true,"type":"string"},"veteranIndicator":{"nullable":true,"type":"boolean"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"MarketSliceDimension":{"enum":["state","county","metro","zip","loanPurpose","loanType","propertyType","occupancyType","amortizationType","channel","borrowerGeneration","firstTimeHomebuyer","veteranIndicator","hmdaActionTaken","selfEmployed","currentHomeOwner"],"type":"string"},"MarketSummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/MarketFlatFilters"},"period":{"$ref":"#/components/schemas/DatedPeriod"}},"type":"object"},"MarketSummaryResponse":{"properties":{"completeness":{"$ref":"#/components/schemas/AnalyticsCompleteness"},"current":{"$ref":"#/components/schemas/MarketMetrics"},"previous":{"allOf":[{"$ref":"#/components/schemas/MarketMetrics"},{"nullable":true}]}},"required":["current","previous"],"type":"object"},"MarketTimeSeriesBucket":{"properties":{"complete":{"description":"Whether this bucket's whole period is backed by data. `false` means the bucket extends past `completeness.through`, so it is built from a partial period and MUST NOT be compared against its neighbours or the same bucket a year earlier. Absent whenever `completeness` itself is absent; the two are emitted together or not at all.","type":"boolean"},"date":{"type":"string"},"excluded":{"description":"How many of this bucket's documents the requested measure's sentinel guard excluded — documents carrying the field whose value is an out-of-range fill. Compare against `units` to see the share the value was computed over. Present per BUCKET because exclusion is not uniform over time: one period can be almost entirely fill values while its neighbors are clean, and a single response-level total would hide exactly that. Absent for `units`, which is a document count and cannot be guarded.","type":"number"},"measureValue":{"description":"This bucket's value for the requested `measure` (`volume` when none was supplied). Null when the bucket has no in-bounds document for the measure's field — sentinel-filtered rows do not contribute, so an empty bucket reports null rather than 0.","nullable":true,"type":"number"},"segments":{"items":{"$ref":"#/components/schemas/MarketTimeSeriesSegment"},"type":"array"},"units":{"description":"Number of loans","type":"number"},"volume":{"description":"Total loan volume in dollars","type":"number"}},"required":["date","volume","units","measureValue"],"type":"object"},"MarketTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/MarketFlatFilters"},"forecast":{"$ref":"#/components/schemas/ForecastRequest"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/MarketMeasure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"segment":{"$ref":"#/components/schemas/MarketSliceDimension"}},"type":"object"},"MarketTimeSeriesResponse":{"properties":{"completeness":{"$ref":"#/components/schemas/AnalyticsCompleteness"},"current":{"items":{"$ref":"#/components/schemas/MarketTimeSeriesBucket"},"type":"array"},"forecast":{"$ref":"#/components/schemas/ForecastResponse"},"measure":{"description":"Echo of the measure `measureValue` reports, so a caller never has to infer which metric it is plotting.","type":"string"},"previous":{"items":{"$ref":"#/components/schemas/MarketTimeSeriesBucket"},"nullable":true,"type":"array"}},"required":["measure","current","previous"],"type":"object"},"MarketTimeSeriesSegment":{"properties":{"label":{"type":"string"},"measureValue":{"description":"This segment's value for the requested `measure`. Null when the segment has no in-bounds document for the measure's field.","nullable":true,"type":"number"},"unattributed":{"description":"Present and `true` on at most one segment PER DATE BUCKET, which is not a real category: it collects the documents that bucket could not attribute to any value of the requested `segment`, and its `label` (\"(unknown)\") is prose, not an identifier. Filter on THIS field, never on the label — a consumer joining a segment label to a real code must drop it. It is always the LAST entry of its bucket's `segments`, appended after ranking rather than placed by value, so it is the one segment that does not obey the ordering `measure` describes. It exists so a period's segments account for the same documents that period's own `units` counts: a document whose segment field holds no indexed term is absent from a terms breakdown entirely rather than forming a small segment, so without it a stacked series silently omits part of every bar. That reconciliation is exact for `units`; on an average it is not, because segments under the five-document floor are dropped and a segment field with more than 200 distinct values still truncates — neither loss is collected here. Reported per bucket rather than once per response because what cannot be attributed is not uniform over time. Absent when there is nothing unattributed, never `false` and never a zero-valued segment.","enum":[true],"type":"boolean"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["label","volume","units","measureValue"],"type":"object"},"MeAuth":{"properties":{"clientId":{"description":"OAuth client that minted the token, when applicable","nullable":true,"type":"string"},"method":{"description":"Which credential the API resolved this caller from","enum":["api-key","bearer","session","internal"],"type":"string"},"profileResolved":{"description":"Always true on a successful read; retained for compatibility now that every caller type resolves the full profile","type":"boolean"},"role":{"description":"Global user role","type":"string"},"scopes":{"description":"OAuth scopes on the bearer token; null for API-key / session callers","items":{"type":"string"},"nullable":true,"type":"array"}},"required":["method","role","profileResolved"],"type":"object"},"MeCreditAllowance":{"properties":{"perCycle":{"description":"Credits granted to each member per billing cycle","type":"number"},"unitPriceCents":{"description":"Price of one on-demand credit, in cents","type":"number"}},"required":["perCycle","unitPriceCents"],"type":"object"},"MeCreditBalance":{"properties":{"cycle":{"description":"Credits from the current subscription cycle allowance","type":"number"},"onDemand":{"description":"Purchased credits that do not expire with the cycle","type":"number"},"personal":{"description":"The user's personal (non-workspace) credit balance","type":"number"},"total":{"type":"number"}},"required":["cycle","onDemand","personal","total"],"type":"object"},"MeCreditUsage":{"properties":{"granted":{"type":"number"},"purchased":{"type":"number"},"spent":{"type":"number"},"spentByCategory":{"properties":{"ai_agent":{"type":"number"},"ai_chat":{"type":"number"},"api":{"type":"number"},"enrichment":{"type":"number"}},"required":["api","enrichment","ai_chat","ai_agent"],"type":"object"},"window":{"properties":{"endDate":{"description":"ISO-8601, inclusive","type":"string"},"startDate":{"description":"ISO-8601, inclusive","type":"string"}},"required":["startDate","endDate"],"type":"object"}},"required":["window","granted","purchased","spent","spentByCategory"],"type":"object"},"MeCreditsResponse":{"properties":{"allowance":{"$ref":"#/components/schemas/MeCreditAllowance"},"balance":{"$ref":"#/components/schemas/MeCreditBalance"},"organizationId":{"type":"string"},"usage":{"$ref":"#/components/schemas/MeCreditUsage"}},"required":["organizationId","balance","allowance","usage"],"type":"object"},"MeOrganization":{"nullable":true,"properties":{"id":{"type":"string"},"role":{"description":"The caller's MEMBERSHIP role in this org (owner/admin/member)","nullable":true,"type":"string"}},"required":["id"],"type":"object"},"MePlan":{"nullable":true,"properties":{"displayName":{"nullable":true,"type":"string"},"group":{"nullable":true,"type":"string"},"id":{"type":"string"},"limits":{"additionalProperties":{"nullable":true},"description":"Plan limit map as configured in auth (free-form)","type":"object"},"name":{"type":"string"}},"required":["id","name","limits"],"type":"object"},"MePlanGrants":{"properties":{"organization":{"items":{"properties":{"additive":{"nullable":true,"type":"boolean"},"planId":{"type":"string"}},"required":["planId"],"type":"object"},"type":"array"},"user":{"items":{"properties":{"planId":{"type":"string"}},"required":["planId"],"type":"object"},"type":"array"}},"required":["organization","user"],"type":"object"},"MePlanResponse":{"properties":{"grants":{"$ref":"#/components/schemas/MePlanGrants"},"organizationId":{"type":"string"},"plan":{"$ref":"#/components/schemas/MePlan"},"subscription":{"$ref":"#/components/schemas/MeSubscription"}},"required":["organizationId","plan","subscription","grants"],"type":"object"},"MeResponse":{"properties":{"auth":{"$ref":"#/components/schemas/MeAuth"},"organization":{"$ref":"#/components/schemas/MeOrganization"},"user":{"$ref":"#/components/schemas/MeUser"}},"required":["user","organization","auth"],"type":"object"},"MeSubscription":{"nullable":true,"properties":{"planName":{"nullable":true,"type":"string"},"status":{"description":"active | trialing | past_due","type":"string"}},"required":["status"],"type":"object"},"MeTheme":{"enum":["light","dark","system"],"type":"string"},"MeUpdateRequest":{"additionalProperties":false,"properties":{"addressLine1":{"maxLength":255,"nullable":true,"type":"string"},"agentPhotoUrl":{"maxLength":4096,"nullable":true,"type":"string"},"city":{"maxLength":255,"nullable":true,"type":"string"},"contactCardType":{"$ref":"#/components/schemas/ContactCardType"},"contactPhone":{"maxLength":64,"nullable":true,"type":"string"},"headline":{"maxLength":255,"nullable":true,"type":"string"},"image":{"maxLength":4096,"nullable":true,"type":"string"},"jobRole":{"maxLength":255,"nullable":true,"type":"string"},"name":{"maxLength":255,"minLength":1,"type":"string"},"nmlsId":{"maxLength":64,"nullable":true,"type":"string"},"postalCode":{"maxLength":10,"nullable":true,"type":"string"},"qrBaseUrl":{"maxLength":4096,"nullable":true,"type":"string"},"reLicenseNumber":{"maxLength":64,"nullable":true,"type":"string"},"reLicenseState":{"maxLength":2,"nullable":true,"type":"string"},"sendNewLoginEmail":{"type":"boolean"},"signatureImage":{"maxLength":4096,"nullable":true,"type":"string"},"state":{"maxLength":2,"nullable":true,"type":"string"},"tagline":{"maxLength":255,"nullable":true,"type":"string"},"theme":{"$ref":"#/components/schemas/MeTheme"}},"type":"object"},"MeUser":{"properties":{"addressLine1":{"nullable":true,"type":"string"},"agentPhotoUrl":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"contactCardType":{"nullable":true,"type":"string"},"contactPhone":{"nullable":true,"type":"string"},"createdAt":{"nullable":true,"type":"string"},"email":{"nullable":true,"type":"string"},"emailVerified":{"nullable":true,"type":"boolean"},"headline":{"nullable":true,"type":"string"},"id":{"description":"Auth user id","type":"string"},"image":{"nullable":true,"type":"string"},"jobRole":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"postalCode":{"nullable":true,"type":"string"},"qrBaseUrl":{"nullable":true,"type":"string"},"reLicenseNumber":{"nullable":true,"type":"string"},"reLicenseState":{"nullable":true,"type":"string"},"sendNewLoginEmail":{"nullable":true,"type":"boolean"},"signatureImage":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"tagline":{"nullable":true,"type":"string"},"theme":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"Measure":{"enum":["volume","units","avgSalePrice","avgListPrice"],"type":"string"},"MeiliUnavailable":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"MlsStatus":{"enum":["SLD","ACT","PND","Cancelled","WDN","EXP","CNT","OFF","UNK","RNTD","RNT","LSE","RNT-SLD","RNT-ACT","RNT-PND","RNT-WDN","RNT-EXP","RNT-LSE","RNT-RNTD"],"type":"string"},"MovementActivity":{"properties":{"chartData":{"items":{"$ref":"#/components/schemas/MovementActivityPoint"},"type":"array"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","chartData"],"type":"object"},"MovementActivityPoint":{"properties":{"activeLos":{"description":"Loan officers with an open employment record at month end.","type":"number"},"becameInactive":{"description":"Always null: license-authorization history is not available on this surface.","nullable":true,"type":"number"},"leftIndustry":{"description":"Loan officers with no open employment whose last employment ended this month. NOT the same as license inactivation.","type":"number"},"month":{"example":"Jan 2026","type":"string"},"monthEnd":{"type":"string"},"monthStart":{"type":"string"},"newlyLicensed":{"type":"number"}},"required":["month","monthStart","monthEnd","newlyLicensed","activeLos","leftIndustry","becameInactive"],"type":"object"},"MovementByState":{"properties":{"cities":{"items":{"$ref":"#/components/schemas/MovementCityRow"},"type":"array"},"data":{"description":"Loan officers who changed companies in the window, by their current state.","items":{"$ref":"#/components/schemas/MovementStateRow"},"type":"array"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","data","cities"],"type":"object"},"MovementCityRow":{"properties":{"city":{"type":"string"},"losChanged":{"type":"number"},"state":{"nullable":true,"type":"string"},"topGainingCompany":{"nullable":true,"properties":{"gainedCount":{"type":"number"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"}},"required":["nmlsId","name","gainedCount"],"type":"object"}},"required":["city","state","losChanged","topGainingCompany"],"type":"object"},"MovementCohortPayoff":{"properties":{"caveats":{"properties":{"floorMonths":{"type":"number"},"totalMoversAnalyzed":{"type":"number"},"totalMoversExcluded":{"type":"number"},"totalMoversInRange":{"type":"number"},"truncated":{"description":"Always false: every mover in the window is analyzed. Kept for compatibility.","type":"boolean"}},"required":["floorMonths","totalMoversInRange","totalMoversAnalyzed","totalMoversExcluded","truncated"],"type":"object"},"tiers":{"items":{"$ref":"#/components/schemas/MovementCohortTier"},"type":"array"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","tiers","caveats"],"type":"object"},"MovementCohortTier":{"properties":{"delta":{"properties":{"unitsChangePct":{"type":"number"},"volumeChangePct":{"type":"number"}},"required":["unitsChangePct","volumeChangePct"],"type":"object"},"moverCount":{"type":"number"},"postMove":{"properties":{"meanUnits":{"type":"number"},"meanVolume":{"type":"number"},"medianUnits":{"type":"number"},"medianVolume":{"type":"number"}},"required":["meanUnits","medianUnits","meanVolume","medianVolume"],"type":"object"},"preMove":{"properties":{"meanUnits":{"type":"number"},"meanVolume":{"type":"number"},"medianUnits":{"type":"number"},"medianVolume":{"type":"number"}},"required":["meanUnits","medianUnits","meanVolume","medianVolume"],"type":"object"},"tierKey":{"enum":["low","mid","high"],"type":"string"},"tierLabel":{"type":"string"}},"required":["tierKey","tierLabel","moverCount","preMove","postMove","delta"],"type":"object"},"MovementCompanies":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MovementCompanyRow"},"type":"array"},"truncated":{"description":"Only for `rankBy=net`: more companies moved than the ranking scans, so the tail is not ranked.","type":"boolean"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","data","truncated"],"type":"object"},"MovementCompanyRow":{"properties":{"avgLoanSize":{"type":"number"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"type":"string"},"gained":{"description":"Loan officers who started at the company in the window.","type":"number"},"lost":{"description":"Loan officers who completely left the company in the window.","type":"number"},"net":{"type":"number"},"units":{"type":"number"},"volume":{"description":"Trailing 14-month origination volume of the loan officers counted on the ranked side (gained for most-gained, lost for most-lost).","type":"number"},"volumeTruncated":{"description":"Always false: `volume`/`units` cover every loan officer on the ranked side. Kept for compatibility.","type":"boolean"}},"required":["companyNmlsId","companyName","gained","lost","net","volume","units","avgLoanSize","volumeTruncated"],"type":"object"},"MovementComputing":{"description":"The result is not ready within the response budget (25 s). The computation continues and is cached when done — repeat the identical request after `retryAfterMs` until it answers 200. Identical concurrent requests share one computation.","properties":{"retryAfterMs":{"description":"Suggested wait before repeating the SAME request (also sent as `Retry-After`, in seconds).","example":5000,"type":"integer"},"status":{"enum":["computing"],"type":"string"}},"required":["status","retryAfterMs"],"type":"object"},"MovementMover":{"properties":{"city":{"nullable":true,"type":"string"},"fromCompanyName":{"nullable":true,"type":"string"},"fromCompanyNmlsId":{"nullable":true,"type":"string"},"moveDate":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"},"previousUnits":{"nullable":true,"type":"number"},"previousVolume":{"description":"Trailing 14-month volume originated under the previous company.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"toCompanyName":{"nullable":true,"type":"string"},"toCompanyNmlsId":{"type":"string"},"units":{"nullable":true,"type":"number"},"volume":{"description":"Trailing 14-month volume, all employers.","nullable":true,"type":"number"}},"required":["nmlsId","name","fromCompanyNmlsId","fromCompanyName","toCompanyNmlsId","toCompanyName","moveDate","state","city","volume","units","previousVolume","previousUnits"],"type":"object"},"MovementMovers":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MovementMover"},"type":"array"},"limit":{"type":"number"},"page":{"type":"number"},"total":{"description":"Rows matching the request (moves for `sort=date`, loan officers for `sort=volume`).","nullable":true,"type":"number"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","data","total","page","limit"],"type":"object"},"MovementRankingRow":{"properties":{"avgLoanSize":{"type":"number"},"city":{"nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"loType":{"description":"Broker when the scored profile says so; else Retail (state-licensed) or Banker (federally registered) from the current employment.","enum":["Broker","Retail","Banker",null],"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"},"purchasePct":{"nullable":true,"type":"number"},"rank":{"type":"number"},"refinancePct":{"nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"typeUnits":{"nullable":true,"type":"number"},"typeVolume":{"nullable":true,"type":"number"},"unitShare":{"description":"Percent of the top-100's units (type-specific units for product rankings).","type":"number"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["rank","nmlsId","name","city","state","companyName","companyNmlsId","volume","units","avgLoanSize","unitShare","loType","typeVolume","typeUnits","purchasePct","refinancePct"],"type":"object"},"MovementRankings":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MovementRankingRow"},"type":"array"},"page":{"type":"number"},"pageSize":{"type":"number"},"subcategory":{"enum":["total_volume","most_units","top_fha","top_va","top_purchase","top_refinance"],"type":"string"},"total":{"type":"number"},"totalPages":{"type":"number"},"year":{"type":"string"}},"required":["year","subcategory","data","total","page","pageSize","totalPages"],"type":"object"},"MovementStateRow":{"properties":{"losChanged":{"type":"number"},"state":{"type":"string"},"topGainingCompany":{"nullable":true,"properties":{"gainedCount":{"type":"number"},"name":{"nullable":true,"type":"string"},"nmlsId":{"type":"string"}},"required":["nmlsId","name","gainedCount"],"type":"object"}},"required":["state","losChanged","topGainingCompany"],"type":"object"},"MovementStats":{"properties":{"activeAtEnd":{"description":"Loan officers with an open employment record on the last day of the window.","type":"number"},"activeAtStart":{"description":"Loan officers with an open employment record on the day before the window starts.","type":"number"},"companyDepartures":{"description":"Loan officers whose every record at a company ended in the window (a complete departure from that company). Approximate distinct count.","type":"number"},"industryExits":{"description":"Loan officers with no open employment anywhere whose last employment ended in the window.","type":"number"},"joins":{"description":"Loan officers who started at a company in the window (first record at that company), new entrants included. Approximate distinct count (±~1%).","type":"number"},"moversScanned":{"description":"How many moving loan officers the volume figures cover (each counted once, at their latest move in the window).","type":"number"},"moversTruncated":{"description":"Always false: every mover in the window is covered. Kept for compatibility.","type":"boolean"},"net":{"description":"`activeAtEnd − activeAtStart` — the change in working loan officers over the window.","type":"number"},"newlyLicensed":{"description":"Loan officers first licensed or registered in the window (each counted once, ever).","type":"number"},"transitions":{"description":"Loan officers who started at a company in the window after a previous employer — company-to-company moves. Approximate distinct count.","type":"number"},"unitsTransferred":{"type":"number"},"volumeTransferred":{"description":"Trailing 14-month origination volume of the loan officers counted in `transitions` (see `moversScanned`), as of the last weekly refresh.","type":"number"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","joins","transitions","companyDepartures","industryExits","newlyLicensed","activeAtStart","activeAtEnd","net","volumeTransferred","unitsTransferred","moversScanned","moversTruncated"],"type":"object"},"MovementTransitionFlow":{"properties":{"fromCompanyName":{"nullable":true,"type":"string"},"fromCompanyNmlsId":{"type":"string"},"los":{"description":"Loan officers who made this move in the window.","type":"number"},"toCompanyName":{"nullable":true,"type":"string"},"toCompanyNmlsId":{"type":"string"}},"required":["fromCompanyNmlsId","fromCompanyName","toCompanyNmlsId","toCompanyName","los"],"type":"object"},"MovementTransitions":{"properties":{"data":{"items":{"$ref":"#/components/schemas/MovementTransitionFlow"},"type":"array"},"truncated":{"description":"True when flows beyond the scanned destination/source companies exist.","type":"boolean"},"window":{"$ref":"#/components/schemas/MovementWindow"}},"required":["window","data","truncated"],"type":"object"},"MovementWindow":{"description":"The resolved reporting window (inclusive dates).","properties":{"endDate":{"type":"string"},"months":{"type":"number"},"startDate":{"type":"string"}},"required":["startDate","endDate","months"],"type":"object"},"NormalizedLocation":{"nullable":true,"properties":{"city":{"type":"string"},"county":{"type":"string"},"displayName":{"type":"string"},"id":{"description":"Location dictionary id, when this location is one of ours. Pass it to a city / county filter instead of the free-text name.","type":"string"},"lat":{"type":"number"},"lon":{"type":"number"},"placeType":{"type":"string"},"state":{"type":"string"},"zip":{"type":"string"}},"required":["placeType","displayName"],"type":"object"},"NotFilter":{"properties":{"child":{"$ref":"#/components/schemas/FilterNode"},"type":{"enum":["not"],"type":"string"}},"required":["type","child"],"type":"object"},"NumericFilterValue":{"anyOf":[{"type":"number"},{"description":"Match any value","items":{"type":"number"},"type":"array"},{"description":"Numeric range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.","type":"boolean"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},{"nullable":true}]},"OfficeAgentsRequest":{"additionalProperties":false,"properties":{"city":{"description":"Narrow agent matches to this city (exact, lowercase).","type":"string"},"companyName":{"description":"Office name to match against `ModelMatch.AgentOffices.OfficeName` (fuzzy). Required when `officeId` is omitted.","type":"string"},"officeId":{"description":"Office key (mm_office_key). When set, the office is fetched first to resolve its name / city / state.","type":"string"},"pagination":{"$ref":"#/components/schemas/Pagination"},"sort":{"items":{"properties":{"field":{"enum":["name","volume","units"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"},"state":{"description":"Narrow agent matches to this state (exact, lowercase).","type":"string"}},"type":"object"},"OfficeDetail":{"allOf":[{"$ref":"#/components/schemas/OfficeSummary"},{"properties":{"email":{"nullable":true,"type":"string"},"fullAddress":{"nullable":true,"type":"string"},"number":{"nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"totalListPriceActive":{"description":"Total list price of active listings at this office","nullable":true,"type":"number"}},"type":"object"}]},"OfficeDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/OfficeDetail"}},"required":["data"],"type":"object"},"OfficeField":{"enum":["company","city","state","zip","agentCount","activeListings","volume","units","buyerVolume","buyerUnits","sellerVolume","sellerUnits","dualVolume","dualUnits","avgSalePrice","avgListPrice","teamSize"],"type":"string"},"OfficeFlatFilters":{"additionalProperties":false,"properties":{"activeListings":{"$ref":"#/components/schemas/NumericFilterValue"},"agentCount":{"$ref":"#/components/schemas/NumericFilterValue"},"avgListPrice":{"$ref":"#/components/schemas/NumericFilterValue"},"avgSalePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"buyerUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"buyerVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"company":{"$ref":"#/components/schemas/TextFilterValue"},"dualUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"dualVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"mode":{"enum":["and","or"],"type":"string"},"sellerUnits":{"$ref":"#/components/schemas/NumericFilterValue"},"sellerVolume":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"teamSize":{"$ref":"#/components/schemas/NumericFilterValue"},"units":{"$ref":"#/components/schemas/NumericFilterValue"},"volume":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"$ref":"#/components/schemas/TextFilterValue"},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"OfficeListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/OfficeFlatFilters"},"lenderFilters":{"items":{"$ref":"#/components/schemas/LenderFilterEntry"},"type":"array"},"lenderMatchMode":{"$ref":"#/components/schemas/LenderMatchMode"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/OfficeField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"OfficeListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/OfficeSummary"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"OfficeSummary":{"properties":{"activeListings":{"nullable":true,"type":"number"},"agentCount":{"description":"Number of agents at this office","nullable":true,"type":"number"},"avgListPrice":{"nullable":true,"type":"number"},"avgSalePrice":{"nullable":true,"type":"number"},"buyerUnits":{"nullable":true,"type":"number"},"buyerVolume":{"nullable":true,"type":"number"},"city":{"description":"City (stored lowercase on the source index)","nullable":true,"type":"string"},"company":{"nullable":true,"type":"string"},"coordinates":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"country":{"nullable":true,"type":"string"},"dualUnits":{"nullable":true,"type":"number"},"dualVolume":{"nullable":true,"type":"number"},"id":{"description":"Office key (mm_office_key)","type":"string"},"lastCountedAt":{"nullable":true,"type":"string"},"locationType":{"nullable":true,"type":"string"},"sellerUnits":{"nullable":true,"type":"number"},"sellerVolume":{"nullable":true,"type":"number"},"state":{"description":"State abbreviation (stored lowercase on the source index)","nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"teamSize":{"nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"OrFilter":{"properties":{"children":{"description":"Array of filter expressions (OR)","items":{"$ref":"#/components/schemas/FilterNode"},"type":"array"},"type":{"enum":["or"],"type":"string"}},"required":["type","children"],"type":"object"},"OriginatorAgentSide":{"description":"Which agent on the LO's loans to rank. `buyer` (default): the buyer's (selling) agent — the agent who brought the borrower. `listing`: the seller's listing and co-listing agents.","enum":["buyer","listing"],"type":"string"},"OriginatorAgentsBreakdownRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"side":{"$ref":"#/components/schemas/OriginatorAgentSide"},"sort":{"$ref":"#/components/schemas/BreakdownSort"}},"type":"object"},"OriginatorBranchLocation":{"description":"The NMLS branch the originator is currently registered at. Null when they have no branch location on file.","nullable":true,"properties":{"city":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"description":"Branch NMLS ID.","nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"}},"type":"object"},"OriginatorChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"},"segment":{"allOf":[{"$ref":"#/components/schemas/OriginatorSlice"},{"description":"Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."}]},"slice":{"$ref":"#/components/schemas/OriginatorSlice"}},"required":["slice"],"type":"object"},"OriginatorCompanyCategoryFilterValue":{"anyOf":[{"description":"One of (case-insensitive): BANK, CU, OTHER, BUILDER","enum":["BANK","CU","OTHER","BUILDER"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): BANK, CU, OTHER, BUILDER","enum":["BANK","CU","OTHER","BUILDER"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}],"description":"Employer category. `BANK` / `CU` / `OTHER` are the stored NMLS categories; `BUILDER` is a virtual category matching the mortgage arms of home builders (Lennar Mortgage, DHI Mortgage, Pulte Mortgage, …), which NMLS registers as `OTHER`. Pass an array to match any of several — `[\"BANK\", \"BUILDER\"]` is banks OR builder lenders. Rows never carry `BUILDER` back; read `companyNmlsId` instead."},"OriginatorContact":{"nullable":true,"properties":{"cellPhone":{"nullable":true,"type":"string"},"employerAddress":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerCompany":{"nullable":true,"type":"string"},"employerCompanyId":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"employerType":{"nullable":true,"type":"string"},"employerWebsite":{"nullable":true,"type":"string"},"employerZip":{"nullable":true,"type":"string"},"facebook":{"nullable":true,"type":"string"},"linkedin":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"officePhoneExt":{"nullable":true,"type":"string"},"personalEmail":{"nullable":true,"type":"string"},"twitter":{"nullable":true,"type":"string"},"website":{"nullable":true,"type":"string"},"workEmail":{"nullable":true,"type":"string"}},"type":"object"},"OriginatorCountResponse":{"properties":{"lenderNormalizations":{"description":"How each `lenderName` value resolved against the lender dictionary. Present when a `lenderName` filter was supplied.","items":{"$ref":"#/components/schemas/LenderNormalization"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"previousTotal":{"description":"How many of the originators in this result set also produced at least one loan in the 12 months BEFORE the `last12Months` window — i.e. months 13-24 back. With no filters, or identity-only filters (`nmlsId`, name, company), that is the full prior-year active originator population, and `total` against `previousTotal` is a true trailing year-over-year change in it. It is NOT `countOriginators(last24Months) - countOriginators(last12Months)`: the 24-month window CONTAINS the 12-month one, so that subtraction returns only the originators who produced in the prior year and then stopped (46,525) rather than all who were active in it (220,836) — it drops everyone who produced in both years and understates by about 79%. There is no way to derive this figure from the published totals, which is why it is returned here. UNDER A PRODUCTION OR GEOGRAPHY FILTER IT IS A RETENTION COUNT, NOT A PRIOR-YEAR POPULATION. Every such filter (`state`, `city`, `county`, `zip`, `volume`, `units`, `loanType`, the market-count filters, `footprint`, …) is read from the CURRENT window in both passes: `state: \"CA\"` selects originators whose last-12-month production includes California, then counts how many of THOSE were also producing a year earlier (45,024 → 38,269). `previousTotal` is then a subset of `total` — it is never larger, `total - previousTotal` is the members of the current set who were not active a year ago, and `total / previousTotal` is a retention ratio, not the growth of the California market. An originator who produced in California a year ago but has since stopped or moved markets is not counted, because there is no per-market breakdown of the prior window to filter on. ABSENT rather than zero when it cannot be computed: on any `period` other than `last12Months` (no other window has a measured containing block), and when `producersOnly: false` is set (that opts the zero-production tail into `total`, so the two figures would no longer describe comparable populations).","example":220836,"minimum":0,"type":"integer"},"total":{"description":"Exact count of records matching the filters","example":48213,"minimum":0,"type":"integer"},"totalIsLowerBound":{"description":"Present (always `true`) only under `timeAtCompanyMonths` when the other filters match more than 200,000 originators: `total` then counts the tenure matches among the first 200,000 of them (in sort order) and the true count may be higher. Absent means `total` is exact.","enum":[true],"type":"boolean"}},"required":["total"],"type":"object"},"OriginatorCrmListFilter":{"additionalProperties":false,"description":"Scope the result to the caller's CRM. Resolved against the caller's ACTIVE WORKSPACE at query time — list membership is read server-side, so the request never carries member ids. Only loan-officer members count; agents and manual (unlinked) records on the same list are ignored. `mode: \"in\"` with no matching members returns an empty page (not an unfiltered one). Errors: 400 `crm_list_requires_workspace` when the caller has no active workspace (API-key / OAuth callers must select an organization), 403 / 404 when a named list is not visible to the caller or does not exist, and 400 `crm_list_too_large` when the selected lists hold more than 50,000 loan officers in total — narrow the selection rather than get a silently partial answer.","properties":{"lists":{"anyOf":[{"description":"Every list in the caller's workspace that the caller can see (own, org-wide, or shared with them) and that holds this kind of record — People lists for originators and agents, Company lists for companies.","enum":["any"],"type":"string"},{"description":"Specific CRM list ids (1–50).","items":{"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"}],"description":"Which lists: `\"any\"` for every People list the caller can see, or an array of list ids. Membership is the UNION across the selected lists."},"mode":{"description":"`in` — only originators who are a member of the selected list(s). `notIn` — exclude every originator who is a member of the selected list(s); everyone else passes, including originators on none of your lists.","enum":["in","notIn"],"type":"string"}},"required":["mode","lists"],"type":"object"},"OriginatorDetail":{"allOf":[{"$ref":"#/components/schemas/OriginatorSummary"},{"properties":{"careerHistory":{"nullable":true,"properties":{"employerCount":{"description":"Number of employers on the origination record. May be lower than `employers.length`, which also counts companies known only from the NMLS sponsorship record.","nullable":true,"type":"number"},"employers":{"description":"Employer history, current employer(s) first, then most recent activity.","items":{"properties":{"address":{"description":"The employer's NMLS-registered main office. Null when the company has no registration record on file.","nullable":true,"properties":{"city":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"type":"object"},"avgLoanAmount":{"nullable":true,"type":"number"},"cityCount":{"nullable":true,"type":"number"},"countyCount":{"nullable":true,"type":"number"},"isCurrent":{"description":"True when the originator is still with this employer. Taken from the NMLS sponsorship record when there is one (it is maintained independently of loan closings, so an originator who has not closed recently still reads as current), otherwise from an open production window.","type":"boolean"},"name":{"nullable":true,"type":"string"},"nmlsId":{"description":"The employer's NMLS company ID.","nullable":true,"type":"string"},"producedFrom":{"description":"First loan origination seen under this employer. Null when the originator never closed a loan here.","nullable":true,"type":"string"},"producedTo":{"description":"Most recent loan origination seen under this employer. Null means production was still open at the last scoring run — it does NOT mean no production.","nullable":true,"type":"string"},"registeredFrom":{"description":"Start of the NMLS company sponsorship. Null when this employer appears only in the origination record.","nullable":true,"type":"string"},"registeredTo":{"description":"End of the NMLS company sponsorship. Null when the sponsorship is still open.","nullable":true,"type":"string"},"sources":{"description":"Which record this employer came from. `production` only = they closed loans here but the sponsorship record does not carry the company; `registration` only = sponsored here with no closed loans on file.","items":{"enum":["production","registration"],"type":"string"},"type":"array"},"stateCount":{"description":"Distinct states originated in under this employer.","nullable":true,"type":"number"},"topStates":{"description":"The employer's three largest states by volume. The full footprint is available from the originator breakdown endpoints.","items":{"properties":{"percentOfVolume":{"description":"Share of this employer's volume originated in this state, 0–100.","nullable":true,"type":"number"},"state":{"description":"Two-letter state code.","nullable":true,"type":"string"},"stateName":{"nullable":true,"type":"string"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"}},"type":"object"},"type":"array"},"units":{"nullable":true,"type":"number"},"volume":{"description":"All-time origination volume under this employer (not period-scoped). Zero is a real answer — a registered stint with no closed loans.","nullable":true,"type":"number"},"zipCount":{"nullable":true,"type":"number"}},"required":["isCurrent","topStates","sources"],"type":"object"},"type":"array"},"records":{"description":"Every NMLS employment record — company sponsorships AND federal registrations — newest start first, each with the company's registered address. Empty until the registration record carries them.","items":{"properties":{"address":{"nullable":true,"properties":{"city":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"type":"object"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"endDate":{"description":"Null while the record is open.","nullable":true,"type":"string"},"isActive":{"type":"boolean"},"licenseType":{"nullable":true,"type":"string"},"locationNmlsId":{"description":"Branch the originator is registered at, on the ACTIVE record at that branch's company only (no location history is kept).","nullable":true,"type":"string"},"regulator":{"description":"State regulator on a sponsorship; primary federal regulator on a registration.","nullable":true,"type":"string"},"source":{"description":"`sponsorship` = a state-licensed company sponsorship (one per license); `registration` = a federal registration (banks, credit unions).","enum":["sponsorship","registration",null],"nullable":true,"type":"string"},"startDate":{"nullable":true,"type":"string"}},"required":["isActive"],"type":"object"},"type":"array"},"summary":{"description":"Counts over `records` and the state licenses. Null when the originator has no registration record.","nullable":true,"properties":{"activeEmployers":{"type":"number"},"activeLicenses":{"description":"State licenses currently authorizing origination.","type":"number"},"avgTenurePerEmployerYears":{"description":"Mean years per employer, earliest start to latest end (open records run to today), to 0.1.","nullable":true,"type":"number"},"careerYears":{"description":"Years since the earliest employer start on `records`, to 0.1 — the career length the recruiting signal is judged on. Null when no record carries a start date.","nullable":true,"type":"number"},"currentTenureYears":{"description":"Years at the current employer (the first employer with an active record), from its earliest record start to today, to 0.1. Null when no employer is active or its start date is unknown. A 365-day year, matching the profile's recruiting signal.","nullable":true,"type":"number"},"employerChanges":{"nullable":true,"type":"number"},"licenseRegulators":{"items":{"type":"string"},"type":"array"},"recruitingSignal":{"description":"One-line read of this career for recruiting, rule-based over `records` (employers grouped by company NMLS id): no records → `none`; over half the employers missing a start date → `incompleteData`; under 2 career years with one employer → `limitedHistory`; one employer for 2+ years → `singleEmployerCareer`; 5+ years at the current employer with ≤3 employers → `longTermStability`; 3+ employers at ≥0.6 per career year → `highMobility`; under 1 year at the current employer with >1 employer → `recentMove`; 3-4 employers over 5+ years → `multiSponsorships`; otherwise `establishedAtCurrent`. First matching rule wins. `label`/`subtext` are display copy.","properties":{"code":{"enum":["singleEmployerCareer","longTermStability","establishedAtCurrent","recentMove","highMobility","multiSponsorships","limitedHistory","incompleteData","none"],"type":"string"},"label":{"type":"string"},"subtext":{"type":"string"}},"required":["code","label","subtext"],"type":"object"},"totalEmployers":{"type":"number"},"totalLicenses":{"type":"number"}},"required":["totalEmployers","activeEmployers","totalLicenses","activeLicenses","licenseRegulators"],"type":"object"}},"required":["employers"],"type":"object"},"communityLending":{"$ref":"#/components/schemas/EntityCommunityLending"},"contact":{"$ref":"#/components/schemas/OriginatorContact"},"hasScoredData":{"description":"`false` on an originator who is in the NMLS registry but has no production record — typically newly licensed. Their production fields (`volume`, `units`, the mix and share fields, `lastTransactionDate`) are `null` because none exists, not because it is zero: label the row (e.g. \"no transactions yet\") rather than rendering zeros. ABSENT on every originator with a production record. Such rows appear on the list only for an identity search (`nmlsId`, `name` or `namePrefix`) sent with `producersOnly: false`, after the rows that have production.","type":"boolean"},"licenses":{"nullable":true},"locations":{"nullable":true},"managedBranches":{"description":"NMLS branches that list this originator as a manager of record. Empty when they manage none.","items":{"$ref":"#/components/schemas/OriginatorManagedBranch"},"nullable":true,"type":"array"},"profileInsights":{"$ref":"#/components/schemas/OriginatorProfileInsights"},"registration":{"$ref":"#/components/schemas/OriginatorRegistration"},"registrations":{"nullable":true},"scored":{"nullable":true},"sponsorships":{"nullable":true},"stateLicenses":{"description":"Every state license on the originator's NMLS record, active and historical, as typed rows. The untyped `licenses` array carries the same rows verbatim.","items":{"$ref":"#/components/schemas/OriginatorStateLicense"},"nullable":true,"type":"array"},"title":{"nullable":true,"type":"string"}},"type":"object"}]},"OriginatorDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/OriginatorDetail"}},"required":["data"],"type":"object"},"OriginatorFootprintFilter":{"additionalProperties":false,"properties":{"avgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Mean loan size INSIDE this market."}]},"city":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Production city — a name (`Orlando`, best paired with `state`) or a location id from `instantSearch` / `suggestLocations`. An unrecognized name is a 400, never a silent zero."},"county":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Production county — a 5-digit FIPS code (`06037`) or a county name (`Riverside`, best paired with `state`)."},"dimension":{"description":"Which footprint to address. Normally inferred from the location key you pass; name it explicitly to ask the ANY-market question (`{dimension:'city', volume:{gte:15000000}}` = 'some single city where they did $15M').","enum":["zip","city","county","state","lender"],"type":"string"},"lender":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Funding lender, as an id from `listLenders` or `instantSearch`. Lender names are stored in a normalized dictionary form, so a typed name does not match — resolve it first."},"not":{"description":"Invert the whole entry: match producers with NO market matching it (e.g. 'does not send loans to this lender').","type":"boolean"},"product":{"allOf":[{"$ref":"#/components/schemas/FootprintProductFilter"},{"description":"Correlate a product INSIDE this market — '$1M of FHA in Orlando'."}]},"shareOfVolume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"This market's share of the originator's total volume for the period, as a 0–100 PERCENT (not a 0–1 fraction). `{gte:50}` = 'this market is at least half their book'."}]},"state":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Two-letter state code or full state name. Alongside `city` or `county` it DISAMBIGUATES that place rather than adding a second predicate; on its own it selects the state footprint."},"units":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Loan count INSIDE this market during the selected period."}]},"volume":{"allOf":[{"$ref":"#/components/schemas/FootprintRange"},{"description":"Dollar volume originated INSIDE this market during the selected period."}]},"zip":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"type":"array"}],"description":"Production 5-digit zip code."}},"type":"object"},"OriginatorListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"crmList":{"$ref":"#/components/schemas/OriginatorCrmListFilter"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"affordableHousingTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in qualified affordable-housing tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"affordableHousingTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in qualified census tracts for affordable-housing programs, 0-100 (`{gte:25}` = 27,209 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgAsianPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Asian (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgBlackPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Black (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgDenialRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of mortgage applications denied in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgFamilyIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median family income of the tracts the entity lent in, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean Hispanic or Latino share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median home value across the tracts the entity lent in, in whole dollars. A neighborhood statistic — not the entity's average loan size, which is `avgLoanAmount`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHomeownershipRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean owner-occupied share of housing units in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgHouseholdIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median household income of the tracts the entity lent in, in whole dollars (e.g. `{lte:60000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean tract income relative to its metro area, where `100` is parity — `{lt:80}` is the CRA low/moderate band, and values legitimately exceed 100 (observed up to 412). NOT a 0-100 share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgLoanAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"avgLowModHouseholdPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean HUD block-group low/moderate-income HOUSEHOLD share across the tracts the entity lent in, 0-100. A finer-grained measure than `lowModIncomeTractPct`, which counts whole tracts — not a duplicate of it. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMedianAge":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean median age of the population in the tracts the entity lent in, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToCollege":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToSchool":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance from the properties the entity lent on to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMilesToWorship":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean straight-line distance to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgMinorityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean non-white share of the population in the tracts the entity lent in, 0-100 (`{gte:50}` = 63,370 originators). `majorityMinorityTractPct` is the per-tract-threshold form of the same question. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPopulation":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean population of the tracts the entity lent in. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgPovertyRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean share of the population below the poverty line in the tracts the entity lent in, 0-100. Pass whole percents — `{gte:0.2}` means 0.2%. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractApplications":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage applications reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractLoanVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean mortgage dollar volume reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgTractOriginations":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean number of mortgage originations reported in the tracts the entity lent in, over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"avgWhiteNonHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean White (non-Hispanic) share of the population in the tracts the entity lent in, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"city":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Production city — matches originators who originated loans in this city during the selected period (NOT office/employer location). An LO can match this city while their row's displayed `city`/`state` is a different, higher-volume market."}]},"companyCategory":{"$ref":"#/components/schemas/OriginatorCompanyCategoryFilterValue"},"companyName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (one name can match many different people; partial names can silently return 0). Resolve the company via instantSearch and filter by `companyNmlsId` (exact NMLS id) instead. Still functional for now."}]},"companyNamePrefix":{"description":"Current company name prefix search: each word starts a word of it (\"guild mort\"); not fuzzy. Digits = company NMLS id.","minLength":1,"type":"string"},"companyNmlsId":{"$ref":"#/components/schemas/TextFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `countyFips`, identical behavior — production county by 5-digit FIPS code (e.g. `06037` = Los Angeles, CA) or by county name (`Riverside`, optionally with a sibling `state`). Pass an array to match any of several counties."}]},"countyCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct counties the originator produced in during the selected period."}]},"countyFips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Production county. Accepts a 5-digit FIPS code (e.g. `04013` = Maricopa, AZ; `06037` = Los Angeles, CA) or a county name (`Riverside`, optionally with a sibling `state`) — names are resolved to a FIPS by the location dictionary. Matches originators who originated loans in this county during the selected period (NOT office/employer location). An ambiguous name returns candidates; an unrecognized one is a 400 naming `instantSearch`. Pass an array to match any of several counties."}]},"difficultDevelopmentAreaCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in HUD-designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"difficultDevelopmentAreaPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in HUD-designated difficult development areas, 0-100 (`{gte:25}` = 93,397 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in distressed-or-underserved tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in distressed-or-underserved nonmetropolitan middle-income tracts, 0-100 (`{gte:25}` = 11,773 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"firstName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (one name can match many different people; partial names can silently return 0). Note: firstName maps to the FULL analyzed `name` field, not a dedicated first-name leaf, so it also matches middle names. Resolve the originator via instantSearch and filter by `nmlsId` (exact NMLS id) instead. Still functional for now."}]},"floodHazardTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in a FEMA special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"floodHazardTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in a FEMA special flood hazard area, 0-100 (`{gte:25}` = 5,212 originators). `predominantFloodZone` gives the specific zone code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"hasEmail":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the originator's profile carries at least one email address (101,566 do). Same `true`-is-a-guarantee / `false`-means-'none on the profile' caveat as `hasPhone`."}]},"hasPhone":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the originator's profile carries at least one phone number (250,077 do). `true` is a guarantee — those records have a number. `false` means 'none on the profile', not 'no number exists': the detail response also draws on a broader contact source, so a small share of `false` records still show a phone when fetched individually."}]},"hasSocial":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Whether the originator's profile carries a social profile link — LinkedIn, Facebook or X/Twitter. Deliberately excludes a plain company website, which is tracked separately and is not a social presence."}]},"isBranchManager":{"$ref":"#/components/schemas/BooleanFilterValue"},"isBroker":{"$ref":"#/components/schemas/BooleanFilterValue"},"isWorking":{"$ref":"#/components/schemas/BooleanFilterValue"},"lastName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (one name can match many different people; partial names can silently return 0). Note: lastName maps to the FULL analyzed `name` field, not a dedicated last-name leaf, so it also matches middle names. Resolve the originator via instantSearch and filter by `nmlsId` (exact NMLS id) instead. Still functional for now."}]},"lastTransactionDate":{"allOf":[{"$ref":"#/components/schemas/DateFilterValue"},{"description":"Date of the originator's most recent loan INSIDE the selected period — the 'recently active' axis. `{gte: \"2026-07-01\"}` keeps originators who closed a loan on or after that day; under the default `last12Months` the period's newest loan is the originator's newest loan, so this reads as 'last active since'. Present on every producing record (100% of served rows), so a bound drops no one for lack of a date. Bounds accept `YYYY`, `YYYY-MM`, `YYYY-MM-DD` or an ISO datetime (see `DateFilterValue`). Sortable: `sort: [{field: \"lastTransactionDate\", order: \"desc\"}]` = most recently active first."}]},"lenderCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct lenders the originator sent loans to during the selected period. `{lte:1}` finds single-outlet producers."}]},"licenseCount":{"$ref":"#/components/schemas/NumericFilterValue"},"licensedSinceDate":{"allOf":[{"$ref":"#/components/schemas/DateFilterValue"},{"description":"Date the originator's NMLS registration began — 'licensed since'. Lifetime, NOT scoped by `period`. `{gte: \"2025-10-01\"}` finds originators who entered the industry on or after that day (newly licensed); `{lte: \"2015-01-01\"}` finds ten-year veterans by registration rather than by `yearsInIndustry`. On file for 99.7% of producing originators (59% of the whole index, so pair with `producersOnly: false` cautiously — unregistered rows have no date and are dropped by any bound unless `includeNulls: true`). Bounds accept `YYYY`, `YYYY-MM`, `YYYY-MM-DD` or an ISO datetime. Sortable: `desc` = newest registrations first."}]},"loanType":{"$ref":"#/components/schemas/OriginatorLoanTypeFilterValue"},"loansWithCommunityData":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many of the entity's loans in the selected period resolved to a neighborhood — the DENOMINATOR every Community Lending share is taken over. Pair it with a share filter (`{gte:25}`, 60,399 originators) so a 100% share off two loans does not read as a 100% share off two hundred. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans that landed in a low- or moderate-income tract, as a count rather than a share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"lowModIncomeTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans that landed in a low- or moderate-income tract under the Community Reinvestment Act, 0-100. `{gte:50}` = 'at least half their book is LMI' (36,977 originators, 655 companies, 648 branches). Pass whole percents — `{gte:0.5}` means half of one percent and matches nearly everyone. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in majority-minority tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in majority-minority tracts, 0-100 (`{gte:50}` = 65,654 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"marketConcentration":{"$ref":"#/components/schemas/MarketConcentrationFilterValue"},"marketCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct CITIES the originator produced in during the selected period. `{gte:10}` = a broad, multi-market book; `{lte:2}` = concentrated. Counts markets, not loans."}]},"mode":{"enum":["and","or"],"type":"string"},"msa":{"$ref":"#/components/schemas/OriginatorMsaFilterValue"},"name":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (one name can match many different people; partial names can silently return 0). Resolve the originator via instantSearch and filter by `nmlsId` (exact NMLS id) instead. Still functional for now."}]},"namePrefix":{"description":"Prefix name search: every word must start a word of the name (\"jen ro\" → Jennifer Rodriguez). No fuzzy/nickname matching; relevance-ranked unless `sort` is set. Max 100 chars / 6 words (emails, URLs, phones ignored), else 400.","minLength":1,"type":"string"},"nmlsId":{"$ref":"#/components/schemas/TextFilterValue"},"officeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Office city — matches originators whose NMLS-registered office is in this city (NOT where they produced loans; that is `city`). Resolved through the location dictionary, so spelling variants match (`Saint Louis` = `St. Louis`); pair it with `officeState` to pick one of several same-named cities (a sibling production `state` does NOT disambiguate it), or pass a dictionary city id. An unrecognized city is a 400 naming `instantSearch`. Pass an array to match any of several."}]},"officeCounty":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Office county — matches originators whose NMLS-registered office zip lies in this county. Accepts a county name (`Orleans`, with a sibling `officeState` when the name exists in several states), a 5-digit FIPS code (`22071`) or a dictionary county id. The office address carries no county of its own, so it is derived from the office zip: each zip is assigned to the ONE county holding most of its parcels, which makes the counties of a state partition its offices but attributes an office in a zip that straddles a county line to the zip's main county. An unrecognized county is a 400."}]},"officeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Office state — matches originators whose NMLS-registered office is in this state (NOT where they produced loans; that is `state`). A 2-letter code or full name (`LA` or `Louisiana`), any case; pass an array to match any of several. Period-independent. Originators with no office address on file never match."}]},"officeZip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Office zip code — matches originators whose NMLS-registered office is in this 5-digit zip (ZIP+4 office addresses match their 5-digit prefix). Pass an array to match any of several."}]},"opportunityZoneCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in Opportunity Zone tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"opportunityZonePct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in federally designated Opportunity Zone tracts, 0-100 (`{gte:10}` = 33,520 originators — this is a small-share filter, a 50% floor finds almost nobody). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"peakMonthUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"The originator's BEST single month of loan COUNT inside the selected period. `{gte:20}` = 'they closed 20+ loans in some month' (7,295 originators over the last 12 months). Same peak semantics as `peakMonthVolume`."}]},"peakMonthVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"The originator's BEST single month of volume inside the selected period. `{gte:10000000}` = 'they had at least one $10M month' (4,803 originators over the last 12 months); `{lte:X}` means no month exceeded X, so it is a true ceiling on their best month. There is no way to ask about a SPECIFIC month here — the per-month buckets are not individually addressable — so use `POST /v1/originators/analytics/time-series` (filtered to the originator) for a month-by-month series."}]},"predominantFloodZone":{"$ref":"#/components/schemas/EntityPredominantFloodZoneFilterValue"},"predominantIncomeLevel":{"$ref":"#/components/schemas/EntityPredominantIncomeLevelFilterValue"},"producersOnly":{"$ref":"#/components/schemas/BooleanFilterValue"},"region":{"$ref":"#/components/schemas/OriginatorRegionFilterValue"},"regulators":{"$ref":"#/components/schemas/TextFilterValue"},"ruralGradient":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean remoteness of the tracts the entity lent in, on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). This is a code, not a percent — `{gte:7}` selects the deepest-rural books (8,886 originators). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in rural tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ruralTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in rural tracts, 0-100 (`{gte:50}` = 24,006 originators). `ruralGradient` is the finer, ordinal form. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"sponsoredAvgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean loan size on the originator's sponsored-employer production."}]},"sponsoredShare":{"anyOf":[{"type":"number"},{"description":"Match any value","items":{"type":"number"},"type":"array"},{"description":"Numeric range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.","type":"boolean"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},{"nullable":true}],"description":"Share of the originator's period volume originated under their SPONSORING employer, as a 0–100 percent. The retail counterpart of `thirdPartyShare`; same denominator, same exclusion of zero-volume records, and the two do not sum to 100."},"sponsoredUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan count the originator produced under their sponsoring employer during the selected period."}]},"sponsoredVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Dollar volume the originator produced under their sponsoring employer during the selected period."}]},"state":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Production state — matches originators who originated loans in this state during the selected period (NOT office/employer location). Multi-state LOs match any state they produced in; each row's `state` shows only their primary (highest-volume) market."}]},"stateCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct states the originator produced in during the selected period. `{gte:2}` finds multi-state producers."}]},"thirdPartyAvgLoanAmount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mean loan size on the originator's third-party (broker) production."}]},"thirdPartyShare":{"anyOf":[{"type":"number"},{"description":"Match any value","items":{"type":"number"},"type":"array"},{"description":"Numeric range. Excludes null/missing-field docs by default; add `includeNulls: true` to keep them.","properties":{"gt":{"type":"number"},"gte":{"type":"number"},"includeNulls":{"description":"Also keep docs where the field is null/missing (a range filter drops them by default). Requires at least one of gte/lte/gt/lt.","type":"boolean"},"lt":{"type":"number"},"lte":{"type":"number"}},"type":"object"},{"nullable":true}],"description":"Share of the originator's period volume submitted through a THIRD-PARTY (broker) relationship, as a 0–100 percent. `{gte:50}` = 'most of their book is wholesale' (52,507 originators over the last 12 months). Computed against their total period volume; an originator with no volume in the period has no share and is excluded rather than counted as zero. This and `sponsoredShare` do not sum to 100 — the remainder is retail."},"thirdPartyUnits":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan count the originator submitted through third-party (broker) relationships during the selected period."}]},"thirdPartyVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Dollar volume the originator submitted through third-party (broker) relationships during the selected period."}]},"timeAtCompanyMonths":{"description":"Whole months at the CURRENT employer (`tenureMonths` on each row), from the NMLS registration record as of the last weekly refresh. `{gte:24}` = at their company two years or more; `{lte:6}` = recent movers. Only originators currently working at a company have a value. Not sortable — sort by `yearsInIndustry` or production instead. Applied after the rest of the request: the other filters are matched first, in the request's sort order, and each match is checked against the registration record, so it works at any result size up to 200,000 matches of the OTHER filters. Past that, `total` counts only the tenure matches among the first 200,000 scanned and the response carries `totalIsLowerBound: true`; a page beyond what was found answers 400 with `code: \"TIME_AT_COMPANY_SCOPE\"` — add a geography, production or company filter to narrow. Pages use an opaque offset cursor; pass `cursor` back unchanged. Flat filters only, and not inside `mode: \"or\"`.","nullable":true,"properties":{"gt":{"minimum":0,"type":"integer"},"gte":{"minimum":0,"type":"integer"},"lt":{"minimum":0,"type":"integer"},"lte":{"minimum":0,"type":"integer"}},"type":"object"},"totalLicenses":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many licenses appear on the originator's record in total, including expired and superseded ones. Distinct from `licenseCount`, which is the CURRENT registration snapshot and runs lower (it is also only on file for about 60% of originators, where this is on all of them). Use `totalLicenses` for career breadth, `licenseCount` for who is licensed right now."}]},"totalLoans":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Lifetime originated loan count across every period on record. Not scoped by `period` — use `units` for the selected period."}]},"transactionType":{"$ref":"#/components/schemas/OriginatorTransactionTypeFilterValue"},"units":{"$ref":"#/components/schemas/NumericFilterValue"},"usdaEligibleTractCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Number of the entity's loans in USDA-eligible tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"usdaEligibleTractPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the entity's tract-resolved loans in tracts eligible for USDA rural housing programs, 0-100 (`{gte:50}` = 90,392 originators). Broader than `ruralTractPct` — eligibility reaches well past what is classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"volume":{"$ref":"#/components/schemas/NumericFilterValue"},"yearsInIndustry":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Years of recorded industry tenure. Lifetime, NOT scoped by `period`. `{gte:10}` finds established originators (246,091 today); `{lte:2}` finds new entrants."}]},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Production zip code — matches originators who originated loans in this 5-digit zip during the selected period (NOT office/employer location). Pass an array to match any of several zips."}]},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zip` — production zip code (5-digit). Identical behavior; kept for callers using the loans/sales spelling."}]},"zipCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"How many distinct 5-digit zip codes the originator produced in during the selected period."}]}},"type":"object"},"footprint":{"anyOf":[{"$ref":"#/components/schemas/OriginatorFootprintFilter"},{"items":{"$ref":"#/components/schemas/OriginatorFootprintFilter"},"type":"array"}],"description":"Scoped market filter(s). Each entry names ONE market (city / county / state / zip / lender) and the metric bounds that must hold INSIDE it — `{city:'Orlando', state:'FL', volume:{gte:15000000}}` means '$15M of production in Orlando', not '$15M somewhere and a loan in Orlando'. Several entries AND together."},"lenderFilters":{"items":{"$ref":"#/components/schemas/LenderFilterEntry"},"type":"array"},"lenderMatchMode":{"$ref":"#/components/schemas/LenderMatchMode"},"officeGeoPoint":{"$ref":"#/components/schemas/OriginatorOfficeGeoPoint"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/Period"},"productMix":{"$ref":"#/components/schemas/OriginatorProductMixFilter"},"productionGeoPoint":{"$ref":"#/components/schemas/OriginatorProductionGeoPoint"},"sort":{"items":{"properties":{"field":{"enum":["nmlsId","name","firstName","lastName","volume","units","scopedVolume","scopedUnits","state","city","countyFips","producersOnly","yearsInIndustry","officeState","officeCity","licensedSinceDate","lastTransactionDate","purchaseShare","refinanceShare"],"type":"string"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"},"transactionMix":{"$ref":"#/components/schemas/OriginatorTransactionMixFilter"}},"type":"object"},"OriginatorListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/OriginatorListRow"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"},"totalIsLowerBound":{"description":"Present (always `true`) only under `timeAtCompanyMonths` when the other filters match more than 200,000 originators: `total` then counts the tenure matches among the first 200,000 of them (in sort order) and the true count may be higher. Absent means `total` is exact.","enum":[true],"type":"boolean"}},"required":["data","total"],"type":"object"},"OriginatorListRow":{"properties":{"avgLoanAmount":{"description":"Mean loan size for the selected period, derived from the TOTAL `volume` and `units` across ALL markets — NOT scoped to any geographic filter in this request. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"branchLocation":{"$ref":"#/components/schemas/OriginatorBranchLocation"},"city":{"nullable":true,"type":"string"},"companyCategory":{"description":"Category of the current employer: `BANK`, `CU` (credit union) or `OTHER`.","nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"description":"NMLS ID of the originator's current employer (the same value the `companyNmlsId` filter matches). Null when they are not currently registered with a company.","nullable":true,"type":"string"},"companyStartDate":{"description":"Date (YYYY-MM-DD) the originator started at their current employer: the earliest ACTIVE sponsorship or registration start at that company. Null when not currently working.","nullable":true,"type":"string"},"contact":{"description":"Collected contact block — the same object `getOriginator` returns. Null when no contact record is on file.","nullable":true,"properties":{"cellPhone":{"nullable":true,"type":"string"},"employerAddress":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerCompany":{"nullable":true,"type":"string"},"employerCompanyId":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"employerType":{"nullable":true,"type":"string"},"employerWebsite":{"nullable":true,"type":"string"},"employerZip":{"nullable":true,"type":"string"},"facebook":{"nullable":true,"type":"string"},"linkedin":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"officePhoneExt":{"nullable":true,"type":"string"},"personalEmail":{"nullable":true,"type":"string"},"twitter":{"nullable":true,"type":"string"},"website":{"nullable":true,"type":"string"},"workEmail":{"nullable":true,"type":"string"}},"type":"object"},"conventionalPct":{"nullable":true,"type":"number"},"email":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"fhaPct":{"nullable":true,"type":"number"},"firstName":{"nullable":true,"type":"string"},"hasScoredData":{"description":"`false` on an originator who is in the NMLS registry but has no production record — typically newly licensed. Their production fields (`volume`, `units`, the mix and share fields, `lastTransactionDate`) are `null` because none exists, not because it is zero: label the row (e.g. \"no transactions yet\") rather than rendering zeros. ABSENT on every originator with a production record. Such rows appear on the list only for an identity search (`nmlsId`, `name` or `namePrefix`) sent with `producersOnly: false`, after the rows that have production.","type":"boolean"},"id":{"description":"Document ID","type":"string"},"isBranchManager":{"description":"True when the originator is a manager of record on any NMLS branch.","nullable":true,"type":"boolean"},"isWorking":{"description":"True when the originator holds an active company sponsorship or registration.","nullable":true,"type":"boolean"},"lastName":{"nullable":true,"type":"string"},"lastTransactionDate":{"description":"ISO datetime of the originator's most recent loan INSIDE the selected period — the value the `lastTransactionDate` filter and sort use. Under the default `last12Months` this is the originator's most recent loan overall. Null when the period bucket carries no production.","nullable":true,"type":"string"},"licenseCount":{"description":"Current NMLS registration license count — the value the `licenseCount` filter matches.","nullable":true,"type":"number"},"licensedSinceDate":{"description":"Date (YYYY-MM-DD) the originator's NMLS registration began — the value the `licensedSinceDate` filter and sort use. Lifetime, not scoped by `period`. Null when no registration record is on file.","nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"officeCity":{"description":"City of the originator's NMLS-registered office — the value the `officeCity` filter matches. Null when no office address is on file.","nullable":true,"type":"string"},"officeState":{"description":"2-letter state of the originator's NMLS-registered office — the value the `officeState` filter matches.","nullable":true,"type":"string"},"officeZip":{"description":"Zip of the originator's NMLS-registered office as stored (5-digit, occasionally ZIP+4) — the value the `officeZip` filter matches.","nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"previousUnits":{"description":"The originator's TOTAL loan count in the 12 months BEFORE the `last12Months` window — months 13-24 back — with the same availability and geography caveats as `previousVolume` (NMLS 7206: 1,295 → 550). For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"previousVolume":{"description":"The originator's TOTAL dollar production in the 12 months BEFORE the `last12Months` window — i.e. months 13-24 back. Pair it with `volume` for a true trailing year-over-year change (NMLS 7206: $855,758,492 → $440,740,230, −48.5%). Substituting calendar years answers a DIFFERENT question and disagrees materially — 2024 vs 2025 for the same originator reads −39.6%, nine points off — because a calendar year is not a trailing window and the current one is only partly elapsed. ABSENT, not zero, on any `period` other than `last12Months`: no other window has a containing block measured in the index, and a zero would read as 'produced nothing' rather than 'not available here'. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"purchaseShare":{"description":"Purchase loans as a 0–100 percent of the originator's period loan COUNT — the value `sort: [{field: \"purchaseShare\"}]` orders by. `null` when the originator wrote no purchase loans in the period (sorts as 0).","example":72.5,"nullable":true,"type":"number"},"purchaseUnits":{"nullable":true,"type":"number"},"purchaseVolume":{"nullable":true,"type":"number"},"refinanceShare":{"description":"Refinance loans as a 0–100 percent of the originator's period loan COUNT — the value `sort: [{field: \"refinanceShare\"}]` orders by. `null` when none (sorts as 0).","example":18.2,"nullable":true,"type":"number"},"refinanceUnits":{"nullable":true,"type":"number"},"refinanceVolume":{"nullable":true,"type":"number"},"regulators":{"description":"Distinct state regulators across the originator's sponsorships, historical included.","items":{"type":"string"},"nullable":true,"type":"array"},"scopedUnits":{"description":"The originator's loan count INSIDE the geography this request names, on the same basis as `scopedVolume`. Sortable. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /v1/originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.","nullable":true,"type":"number"},"scopedVolume":{"description":"The originator's dollar production INSIDE the geography this request names — what a `state`/`city`/`county`/`zip` filter was almost certainly asking for, and what the sibling `volume` is not. Sort by `scopedVolume` to rank originators by it. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /v1/originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"tenureMonths":{"description":"Whole months at the current employer, from `companyStartDate`, as of the last weekly registration refresh. The value the `timeAtCompanyMonths` filter matches.","nullable":true,"type":"number"},"units":{"description":"The originator's TOTAL loan count for the selected period across ALL markets — NOT scoped to any geographic filter in this request, exactly as described on `volume`. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"vaPct":{"nullable":true,"type":"number"},"volume":{"description":"The originator's TOTAL dollar production for the selected period across ALL markets — NOT scoped to any geographic filter (`state`/`city`/`county`/`countyFips`/`zip`/`zipCode`) in this request. Those filters select WHICH originators are returned — they produced at least one loan there — and never change WHAT is summed here. Since the list sorts by `volume` descending by default, a geo-filtered search ranks originators by NATIONAL production, so the top row can be many times larger than that originator's production inside the filtered area. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"yearsInIndustry":{"description":"Years of recorded industry tenure — the value the `yearsInIndustry` filter and sort use. Lifetime, not scoped by `period`.","nullable":true,"type":"number"}},"required":["id"],"type":"object"},"OriginatorLoanTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): conventional, fha, va, he, heloc, building, commercial, stand_alone_refi, closed_end, reverse, usda, stand_alone_second, aggregate, seller_take_back, sba_participation_trust_deed, balloon, opened_end, assumption, negative_amortization, land_contract, trade, modification, unknown","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): conventional, fha, va, he, heloc, building, commercial, stand_alone_refi, closed_end, reverse, usda, stand_alone_second, aggregate, seller_take_back, sba_participation_trust_deed, balloon, opened_end, assumption, negative_amortization, land_contract, trade, modification, unknown","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"OriginatorManagedBranch":{"properties":{"city":{"nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"rosterCount":{"description":"Originators actively registered at the branch.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"}},"type":"object"},"OriginatorMarketBucket":{"properties":{"avgLoanAmount":{"description":"Mean loan size in this market.","nullable":true,"type":"number"},"key":{"description":"The market's key as the source stores it. Form varies with `source` (a rollup city is `city|state`, a live city is the city name) — use `name` for display and grouping.","nullable":true,"type":"string"},"name":{"description":"Display label for the market, in the same form the matching `/breakdowns` route publishes: a county reads `Middlesex County (MA)`, a state `MA`, a city `Belmont` (with a `, MA` qualifier when the market is a city within one state). Identical for a given market whichever `source` served the request, so labels can be compared across surfaces; `key` is the source-native identity and is not.","nullable":true,"type":"string"},"shareOfBook":{"description":"Share of the LO's whole period volume, 0–100. Null on live transaction data, which carries no stored share.","nullable":true,"type":"number"},"shareOfScope":{"description":"Share of the volume of the markets RETURNED, 0–100. Sums to 100 across the grain — this is the one a chart should render.","nullable":true,"type":"number"},"units":{"description":"Loans in this market.","nullable":true,"type":"number"},"volume":{"description":"Dollar volume originated in this market.","nullable":true,"type":"number"}},"required":["key","name","volume","units","avgLoanAmount","shareOfScope","shareOfBook"],"type":"object"},"OriginatorMarketsCommunityLending":{"description":"The Community Lending mix of this footprint: the neighborhood characteristics of where the production landed, as percentages on a 0-100 scale. Null when nothing in scope resolved to a neighborhood — an absent block, never a row of zeroes, because 'no data' and '0%' are different answers. Read `basis` before comparing two responses. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"affordableHousingTractPct":{"description":"Share of production, 0-100, in neighborhoods carrying an affordable-housing designation. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"basis":{"description":"Which measurement produced this block, and they are NOT the same number. `entityRollup` is the neighborhood mix of the entity's own production over the whole period — the default. `marketsInScope` is the neighborhood profile of the markets the request selected, weighted by the entity's production in each, and is what any ZIP, date or filter scope returns, because a whole-period rollup cannot be re-cut to a narrower question.","enum":["entityRollup","marketsInScope"],"type":"string"},"coveredProductionPct":{"description":"`marketsInScope` only — what share of the weighted production, 0-100, sits in a market that resolved to neighborhood data. Below 100 means the mix describes part of the footprint, not all of it.","nullable":true,"type":"number"},"difficultDevelopmentAreaPct":{"description":"Share of production, 0-100, in designated difficult development areas. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"distressedTractPct":{"description":"Share of production, 0-100, in distressed or underserved nonmetropolitan middle-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"floodHazardTractPct":{"description":"Share of production, 0-100, in neighborhoods inside a special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"incomeLevelMix":{"description":"`marketsInScope` only — the full relative-income distribution of the neighborhoods, 0-100, summing to about 100. Null on `entityRollup`, which stores the predominant band but no distribution; publishing one derived from a single label would be a histogram nobody measured. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"properties":{"low":{"nullable":true,"type":"number"},"middle":{"nullable":true,"type":"number"},"moderate":{"nullable":true,"type":"number"},"upper":{"nullable":true,"type":"number"}},"required":["low","moderate","middle","upper"],"type":"object"},"loansWithCommunityData":{"description":"`entityRollup` only — how many of the entity's transactions in the period resolved to a neighborhood. This is the denominator every share below is a share OF, so read it first: a 100% share over three transactions is not a footprint.","nullable":true,"type":"number"},"lowModIncomeTractPct":{"description":"Share of production, 0-100, in low- or moderate-income neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"majorityMinorityTractPct":{"description":"Share of production, 0-100, in majority-minority neighborhoods. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"marketsInScope":{"description":"`marketsInScope` only — ZIP markets the mix considered, including any that carried no neighborhood data.","nullable":true,"type":"number"},"marketsWithCommunityData":{"description":"`marketsInScope` only — ZIP markets that resolved to neighborhood data.","nullable":true,"type":"number"},"opportunityZonePct":{"description":"Share of production, 0-100, in designated Opportunity Zones. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"predominantIncomeLevel":{"description":"The most common relative-income classification of the neighborhoods, on the standard four-band scale. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","enum":["low","moderate","middle","upper",null],"nullable":true,"type":"string"},"ruralTractPct":{"description":"Share of production, 0-100, in neighborhoods classified rural. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTractPct":{"description":"Share of production, 0-100, in neighborhoods eligible for USDA rural housing programs. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"}},"required":["basis","loansWithCommunityData","marketsWithCommunityData","marketsInScope","coveredProductionPct","predominantIncomeLevel","incomeLevelMix","lowModIncomeTractPct","majorityMinorityTractPct","ruralTractPct","opportunityZonePct","affordableHousingTractPct","distressedTractPct","usdaEligibleTractPct","floodHazardTractPct","difficultDevelopmentAreaPct"],"type":"object"},"OriginatorMarketsRequest":{"additionalProperties":false,"properties":{"dateRange":{"description":"Custom window. A period is a fixed pre-aggregated window and cannot be re-cut, so any bound here switches the response to live transaction data.","properties":{"from":{"pattern":"^\\d{4}(?:-\\d{2}(?:-\\d{2})?)?$","type":"string"},"to":{"pattern":"^\\d{4}(?:-\\d{2}(?:-\\d{2})?)?$","type":"string"}},"type":"object"},"limit":{"description":"Markets returned per grain (default 100). The summary is computed over the whole footprint FIRST and is not affected by this.","maximum":500,"minimum":1,"type":"integer"},"period":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Production period the markets are read from (default last12Months)."}]},"zipCodes":{"description":"Narrow the footprint to these ZIP codes. 5-digit; ZIP+4 and zero-stripped forms are accepted and normalized. A value that is not 1–5 digits returns 400 naming it rather than being ignored. Any value here switches the response to live transaction data.","example":["92683","92703"],"items":{"type":"string"},"maxItems":200,"type":"array"}},"type":"object"},"OriginatorMarketsResponse":{"properties":{"nmlsId":{"type":"string"},"notes":{"description":"Plain-language caveats that apply to this response.","items":{"type":"string"},"type":"array"},"period":{"type":"string"},"rollups":{"$ref":"#/components/schemas/OriginatorMarketsRollups"},"scope":{"description":"The scope as applied, after normalization — echo it back to see what the request actually asked.","properties":{"dateRange":{"nullable":true,"properties":{"from":{"nullable":true,"type":"string"},"to":{"nullable":true,"type":"string"}},"required":["from","to"],"type":"object"},"zipCodes":{"items":{"type":"string"},"nullable":true,"type":"array"}},"required":["zipCodes","dateRange"],"type":"object"},"source":{"description":"Where the markets were read from. `documentRollup` is the LO's pre-aggregated footprint; `liveTransactions` aggregates the LO's loans directly, which is what any scope requires.","enum":["documentRollup","liveTransactions"],"type":"string"},"sourceReasons":{"description":"Why that source was chosen.","items":{"enum":["doc-rollup","coverage-empty","zip-scope","date-scope","live-only-metric"],"type":"string"},"type":"array"},"summary":{"$ref":"#/components/schemas/OriginatorMarketsSummary"},"totals":{"$ref":"#/components/schemas/OriginatorMarketsTotals"},"zips":{"description":"The ZIP-level footprint, largest volume first.","items":{"$ref":"#/components/schemas/OriginatorMarketBucket"},"type":"array"}},"required":["nmlsId","period","source","sourceReasons","scope","summary","zips","rollups","totals","notes"],"type":"object"},"OriginatorMarketsRollups":{"description":"Coarser views of the same scope. Each grain is its own pre-aggregation, not a re-cut of the ZIPs, so grains need not sum to each other.","properties":{"cities":{"items":{"$ref":"#/components/schemas/OriginatorMarketBucket"},"type":"array"},"counties":{"items":{"$ref":"#/components/schemas/OriginatorMarketBucket"},"type":"array"},"states":{"items":{"$ref":"#/components/schemas/OriginatorMarketBucket"},"type":"array"}},"required":["cities","counties","states"],"type":"object"},"OriginatorMarketsSummary":{"properties":{"avgLoanAmount":{"description":"Volume-weighted mean loan size — Σ volume ÷ Σ units, never an unweighted mean of the per-market averages.","nullable":true,"type":"number"},"communityLending":{"$ref":"#/components/schemas/OriginatorMarketsCommunityLending"},"markets":{"description":"Placed markets the summary covers.","type":"number"},"shareOfBook":{"description":"How much of the LO's whole period book the ZIP markets are, 0–100. Read it as COVERAGE, and expect it below 100 even with no filter: part of the gap is production that could not be placed at all (reported in `unresolved`) and part is production carrying no ZIP. The coarser grains in `rollups` are separate pre-aggregations with their own — usually higher — coverage, so they can legitimately add up to more than this. Null on live transaction data.","nullable":true,"type":"number"},"truncatedMarkets":{"description":"True when the source returned only the largest markets, so the summary covers those and not the full tail.","type":"boolean"},"units":{"description":"Σ loans of those markets.","nullable":true,"type":"number"},"unresolved":{"$ref":"#/components/schemas/OriginatorMarketsUnresolved"},"volume":{"description":"Σ volume of the markets in scope — NOT the LO's period total, which is `totals.volume`.","nullable":true,"type":"number"}},"required":["markets","volume","units","avgLoanAmount","shareOfBook","truncatedMarkets","unresolved","communityLending"],"type":"object"},"OriginatorMarketsTotals":{"properties":{"avgLoanAmount":{"description":"The LO's mean loan size for the period.","nullable":true,"type":"number"},"footprintCoverage":{"description":"What share of `volume` the returned ZIP markets account for, 0–100. Null on live transaction data, where the window and the period block are not the same denominator.","nullable":true,"type":"number"},"units":{"description":"The LO's whole loan count for the period.","nullable":true,"type":"number"},"volume":{"description":"The LO's whole volume for the period.","nullable":true,"type":"number"}},"required":["volume","units","avgLoanAmount","footprintCoverage"],"type":"object"},"OriginatorMarketsUnresolved":{"description":"Production the source could not attribute to a place, held OUT of the summary and the market lists and reported on its own.","properties":{"markets":{"description":"Buckets the source could not attribute to a place.","type":"number"},"shareOfBook":{"nullable":true,"type":"number"},"units":{"nullable":true,"type":"number"},"volume":{"nullable":true,"type":"number"}},"required":["markets","volume","units","shareOfBook"],"type":"object"},"OriginatorMsaFilterValue":{"anyOf":[{"type":"string"},{"items":{"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Production METRO AREA (MSA / CBSA): originators who originated loans in ANY county of the metro during the selected period (not office). 5-digit CBSA code (`12420`) or metro name (`Austin Metro`); an array matches any. Member counties per the OMB July-2023 delineation (Connecticut's pre-2022 counties included; `41860` San Francisco Bay Area is the nine-county Bay Area). Unknown/ambiguous names are a 400 naming candidates."},"OriginatorOfficeGeoPoint":{"additionalProperties":false,"description":"Originators whose NMLS-registered OFFICE is within `radiusMiles` of an anchor — the radius form of `officeState` / `officeCity` / `officeZip`, NOT production geography (that is `state` / `city` / `county` / `zip` / `footprint`). Anchor on a coordinate (`{lat, lon, radiusMiles}`) or on another originator's office (`{nmlsId: \"7206\", radiusMiles: 25}` — 'LOs near this LO'; that originator is excluded). Originators with no geocoded office never match. 400 when neither anchor form is complete or both are given; 404 `office_geo_anchor_not_found` for an unknown `nmlsId`; 400 `office_geo_anchor_unlocated` when that originator has no geocoded office.","properties":{"lat":{"description":"Anchor latitude; pair with `lon`.","example":33.4484,"maximum":90,"minimum":-90,"type":"number"},"lon":{"description":"Anchor longitude; pair with `lat`.","example":-112.074,"maximum":180,"minimum":-180,"type":"number"},"nmlsId":{"description":"Anchor on another originator's office instead: their NMLS id (resolved server-side; they are excluded from the result). Exclusive with `lat`/`lon`.","example":"7206","minLength":1,"type":"string"},"radiusMiles":{"description":"Radius in miles, > 0 and ≤ 1000.","example":50,"exclusiveMinimum":true,"maximum":1000,"minimum":0,"type":"number"}},"required":["radiusMiles"],"type":"object"},"OriginatorProductMixEntry":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100. No bucket = 0% (passes).","example":60,"maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","example":25,"maximum":100,"minimum":0,"type":"number"},"product":{"description":"Loan product (case-insensitive).","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"example":"fha","type":"string"},"products":{"description":"Any-of instead of `product`: `[\"fha\",\"va\",\"usda\"]` = one of them on its own meets the bounds (shares never summed).","items":{"description":"Loan product (case-insensitive).","enum":["conventional","fha","va","he","heloc","building","commercial","stand_alone_refi","closed_end","reverse","usda","stand_alone_second","aggregate","seller_take_back","sba_participation_trust_deed","balloon","opened_end","assumption","negative_amortization","land_contract","trade","modification","unknown"],"example":"fha","type":"string"},"maxItems":10,"minItems":1,"type":"array"},"volume":{"additionalProperties":false,"description":"Dollar volume of this type in the period, `{gte, lte}`. Needs the bucket (no loans of the type fails).","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"type":"object"},"OriginatorProductMixFilter":{"description":"Whole-book product-share / volume bands for the selected period, ANDed: `[{product: \"fha\", minShare: 30}, {product: \"va\", maxShare: 10}]` = FHA ≥ 30% of period volume AND VA ≤ 10%; `{product:\"fha\", volume:{gte:10000000}}` = ≥ $10M of FHA. Shares are 0–100 percents of TOTAL period production across all markets (not geography-scoped), as the row's `fhaPct` / `vaPct` / `conventionalPct`. No bucket = 0% (fails `minShare` > 0, passes `maxShare`). Pair with `units: {gte: N}` so a 100% share off two loans is not a specialty.","items":{"$ref":"#/components/schemas/OriginatorProductMixEntry"},"maxItems":10,"minItems":1,"type":"array"},"OriginatorProductionGeoPoint":{"additionalProperties":false,"description":"Production RADIUS (statute miles, 0 < r ≤ 500): originators who originated loans within the radius of the point during the selected period — where they PRODUCE, not their office. COUNTY-LEVEL APPROXIMATION: counties whose Census centroid lies within the radius (always including the nearest) are in with all their loans; a large county whose centroid is outside is out even where its border is close. Coarser than a true radius, especially under ~25 mi. Pair with `sort: [{ field: \"scopedVolume\" }]` to rank by production inside those counties.","properties":{"lat":{"maximum":90,"minimum":-90,"type":"number"},"lon":{"maximum":180,"minimum":-180,"type":"number"},"radiusMiles":{"exclusiveMinimum":true,"maximum":500,"minimum":0,"type":"number"}},"required":["lat","lon","radiusMiles"],"type":"object"},"OriginatorProfileInsights":{"description":"Profile read-outs computed server-side from the LO's production in the requested `period` (default `last12Months`) — the same `volume` / `units` this response reports. Labels and descriptions are display copy; branch on the enum fields.","properties":{"producerTier":{"description":"From the period's units and volume, first match wins: `topProducer` ≥ 60 units OR ≥ $25M; `strongProducer` ≥ 36 units OR ≥ $12M; `midTier` ≥ 18 units OR ≥ $5M; else `lowVolume`.","properties":{"description":{"type":"string"},"label":{"type":"string"},"tier":{"enum":["topProducer","strongProducer","midTier","lowVolume"],"type":"string"}},"required":["tier","label","description"],"type":"object"}},"required":["producerTier"],"type":"object"},"OriginatorRegionFilterValue":{"anyOf":[{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},{"items":{"enum":["northeast","northeast-division-1","northeast-division-2","midwest","midwest-division-3","midwest-division-4","south","south-division-5","south-division-6","south-division-7","west","west-division-8","west-division-9"],"type":"string"},"maxItems":50,"minItems":1,"type":"array"},{"nullable":true}],"description":"Production CENSUS REGION / DIVISION (`<region>-division-<n>`, Census numbering 1–9): originators who originated loans in ANY state of it during the selected period (not office). An array matches any."},"OriginatorRegistration":{"nullable":true,"properties":{"address":{"nullable":true},"city":{"nullable":true,"type":"string"},"companyCategory":{"nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"hasDisciplinaryAction":{"nullable":true,"type":"boolean"},"isBranchManager":{"nullable":true,"type":"boolean"},"isWorking":{"nullable":true,"type":"boolean"},"licenseCount":{"nullable":true,"type":"number"},"licensedSinceDate":{"nullable":true,"type":"string"},"licensedStates":{"items":{"type":"string"},"nullable":true,"type":"array"},"licenses":{"nullable":true},"otherNames":{"nullable":true},"regulators":{"items":{"type":"string"},"nullable":true,"type":"array"},"sponsorships":{"nullable":true},"state":{"nullable":true,"type":"string"}},"type":"object"},"OriginatorSegment":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`. Time-series only: `titleCompany` groups on the title company named on the deed, with spellings of one company merged per bucket (`label` = most-used spelling across the response, `id` = normalized name — match on `id`) and \"none available\"-style placeholders excluded.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming","titleCompany"],"type":"string"},"OriginatorSlice":{"description":"Dimension to group by. Most are the loan's own field (`loanType`, `transactionType`, `state`, …). `lender` groups on the normalized lender (label = display name, `id` = filter key). `propertyType` is the recorder's land-use code of the collateral (`SFR` single-family, `PUD` planned unit development, `CND` condo, `RES` residential-other, `MFD` multi-family dwelling, `2ND` second home, `MFG` manufactured, `TWN` townhouse, `LAN` land, `COM` commercial, …); loans with no code are not grouped (≈20% of recent loans). `conforming` splits on the conforming-loan-limit flag: `conforming` vs `nonConforming` (above the county conforming limit — i.e. jumbo, not Non-QM), raw `true`/`false` on `id`.","enum":["transactionType","loanType","city","county","state","zip","lender","propertyType","conforming"],"type":"string"},"OriginatorStateLicense":{"properties":{"isAuthorized":{"description":"True when the license currently authorizes origination.","nullable":true,"type":"boolean"},"issueDate":{"nullable":true,"type":"string"},"licenseId":{"nullable":true,"type":"string"},"licenseNumber":{"nullable":true,"type":"string"},"licenseType":{"nullable":true,"type":"string"},"regulator":{"description":"Issuing regulator — a state name or \"<State> - <Agency>\"; not a normalized state code.","nullable":true,"type":"string"},"status":{"nullable":true,"type":"string"}},"type":"object"},"OriginatorSummary":{"properties":{"avgLoanAmount":{"description":"Mean loan size for the selected period, derived from the TOTAL `volume` and `units` across ALL markets — NOT scoped to any geographic filter in this request. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"branchLocation":{"$ref":"#/components/schemas/OriginatorBranchLocation"},"city":{"nullable":true,"type":"string"},"companyCategory":{"description":"Category of the current employer: `BANK`, `CU` (credit union) or `OTHER`.","nullable":true,"type":"string"},"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"description":"NMLS ID of the originator's current employer (the same value the `companyNmlsId` filter matches). Null when they are not currently registered with a company.","nullable":true,"type":"string"},"companyStartDate":{"description":"Date (YYYY-MM-DD) the originator started at their current employer: the earliest ACTIVE sponsorship or registration start at that company. Null when not currently working.","nullable":true,"type":"string"},"contact":{"description":"Collected contact block — the same object `getOriginator` returns. Null when no contact record is on file.","nullable":true,"properties":{"cellPhone":{"nullable":true,"type":"string"},"employerAddress":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerCompany":{"nullable":true,"type":"string"},"employerCompanyId":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"employerType":{"nullable":true,"type":"string"},"employerWebsite":{"nullable":true,"type":"string"},"employerZip":{"nullable":true,"type":"string"},"facebook":{"nullable":true,"type":"string"},"linkedin":{"nullable":true,"type":"string"},"officePhone":{"nullable":true,"type":"string"},"officePhoneExt":{"nullable":true,"type":"string"},"personalEmail":{"nullable":true,"type":"string"},"twitter":{"nullable":true,"type":"string"},"website":{"nullable":true,"type":"string"},"workEmail":{"nullable":true,"type":"string"}},"type":"object"},"conventionalPct":{"nullable":true,"type":"number"},"email":{"nullable":true,"type":"string"},"employerCity":{"nullable":true,"type":"string"},"employerState":{"nullable":true,"type":"string"},"fhaPct":{"nullable":true,"type":"number"},"firstName":{"nullable":true,"type":"string"},"id":{"description":"Document ID","type":"string"},"isBranchManager":{"description":"True when the originator is a manager of record on any NMLS branch.","nullable":true,"type":"boolean"},"isWorking":{"description":"True when the originator holds an active company sponsorship or registration.","nullable":true,"type":"boolean"},"lastName":{"nullable":true,"type":"string"},"lastTransactionDate":{"description":"ISO datetime of the originator's most recent loan INSIDE the selected period — the value the `lastTransactionDate` filter and sort use. Under the default `last12Months` this is the originator's most recent loan overall. Null when the period bucket carries no production.","nullable":true,"type":"string"},"licenseCount":{"description":"Current NMLS registration license count — the value the `licenseCount` filter matches.","nullable":true,"type":"number"},"licensedSinceDate":{"description":"Date (YYYY-MM-DD) the originator's NMLS registration began — the value the `licensedSinceDate` filter and sort use. Lifetime, not scoped by `period`. Null when no registration record is on file.","nullable":true,"type":"string"},"name":{"nullable":true,"type":"string"},"nmlsId":{"nullable":true,"type":"string"},"officeCity":{"description":"City of the originator's NMLS-registered office — the value the `officeCity` filter matches. Null when no office address is on file.","nullable":true,"type":"string"},"officeState":{"description":"2-letter state of the originator's NMLS-registered office — the value the `officeState` filter matches.","nullable":true,"type":"string"},"officeZip":{"description":"Zip of the originator's NMLS-registered office as stored (5-digit, occasionally ZIP+4) — the value the `officeZip` filter matches.","nullable":true,"type":"string"},"phone":{"nullable":true,"type":"string"},"previousUnits":{"description":"The originator's TOTAL loan count in the 12 months BEFORE the `last12Months` window — months 13-24 back — with the same availability and geography caveats as `previousVolume` (NMLS 7206: 1,295 → 550). For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"previousVolume":{"description":"The originator's TOTAL dollar production in the 12 months BEFORE the `last12Months` window — i.e. months 13-24 back. Pair it with `volume` for a true trailing year-over-year change (NMLS 7206: $855,758,492 → $440,740,230, −48.5%). Substituting calendar years answers a DIFFERENT question and disagrees materially — 2024 vs 2025 for the same originator reads −39.6%, nine points off — because a calendar year is not a trailing window and the current one is only partly elapsed. ABSENT, not zero, on any `period` other than `last12Months`: no other window has a containing block measured in the index, and a zero would read as 'produced nothing' rather than 'not available here'. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"purchaseShare":{"description":"Purchase loans as a 0–100 percent of the originator's period loan COUNT — the value `sort: [{field: \"purchaseShare\"}]` orders by. `null` when the originator wrote no purchase loans in the period (sorts as 0).","example":72.5,"nullable":true,"type":"number"},"purchaseUnits":{"nullable":true,"type":"number"},"purchaseVolume":{"nullable":true,"type":"number"},"refinanceShare":{"description":"Refinance loans as a 0–100 percent of the originator's period loan COUNT — the value `sort: [{field: \"refinanceShare\"}]` orders by. `null` when none (sorts as 0).","example":18.2,"nullable":true,"type":"number"},"refinanceUnits":{"nullable":true,"type":"number"},"refinanceVolume":{"nullable":true,"type":"number"},"regulators":{"description":"Distinct state regulators across the originator's sponsorships, historical included.","items":{"type":"string"},"nullable":true,"type":"array"},"scopedUnits":{"description":"The originator's loan count INSIDE the geography this request names, on the same basis as `scopedVolume`. Sortable. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /v1/originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.","nullable":true,"type":"number"},"scopedVolume":{"description":"The originator's dollar production INSIDE the geography this request names — what a `state`/`city`/`county`/`zip` filter was almost certainly asking for, and what the sibling `volume` is not. Sort by `scopedVolume` to rank originators by it. When the request names no geography — or names one only inside an `or` group or a negation — the scope is everywhere, and this is identical to the unscoped figure beside it. Reconciles with `POST /v1/originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"tenureMonths":{"description":"Whole months at the current employer, from `companyStartDate`, as of the last weekly registration refresh. The value the `timeAtCompanyMonths` filter matches.","nullable":true,"type":"number"},"units":{"description":"The originator's TOTAL loan count for the selected period across ALL markets — NOT scoped to any geographic filter in this request, exactly as described on `volume`. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"vaPct":{"nullable":true,"type":"number"},"volume":{"description":"The originator's TOTAL dollar production for the selected period across ALL markets — NOT scoped to any geographic filter (`state`/`city`/`county`/`countyFips`/`zip`/`zipCode`) in this request. Those filters select WHICH originators are returned — they produced at least one loan there — and never change WHAT is summed here. Since the list sorts by `volume` descending by default, a geo-filtered search ranks originators by NATIONAL production, so the top row can be many times larger than that originator's production inside the filtered area. For production INSIDE the geography this request names, read `scopedVolume`/`scopedUnits` on the same row, and sort by them to rank originators by it. `POST /v1/originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.","nullable":true,"type":"number"},"yearsInIndustry":{"description":"Years of recorded industry tenure — the value the `yearsInIndustry` filter and sort use. Lifetime, not scoped by `period`.","nullable":true,"type":"number"}},"required":["id"],"type":"object"},"OriginatorSummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"}},"type":"object"},"OriginatorTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"additionalProperties":false,"properties":{"borrowerStatus":{"$ref":"#/components/schemas/LoanBorrowerStatusFilterValue"},"broker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Broker shop NMLS id (digits only). A broker is a company — resolve a broker name to its NMLS id via instantSearch (or listCompanies)."}]},"buyerEntityType":{"$ref":"#/components/schemas/BooleanFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"conforming":{"$ref":"#/components/schemas/BooleanFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County name (e.g. \"Broward\") or 5-digit FIPS code. Names resolve to FIPS server-side; include a `state` filter to disambiguate."}]},"currentBalance":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated remaining principal balance (~19% populated). Approximate current equity as `homeValue` (AVM) minus this."}]},"employer":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Employer/company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Point-in-time equity recorded on the loan (sparse, ~10%). NOT a live current-equity figure. For HELOC/cash-out targeting on up-to-date equity, use properties search (listProperties) instead — its equity is far better populated and current."}]},"excludeBroker":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans brokered by this broker-shop NMLS id (digits only) — the inverse of `broker`."}]},"excludeCity":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this city — the inverse of `city`."}]},"excludeLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans from this lender ID (\"everyone but X\") — the inverse of `lender`, same id contract (resolve via instantSearch/listLenders). Loans with no lender stay in the results."}]},"excludeLoanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans funded by this company NMLS id (digits only) — the inverse of `loanCompany`."}]},"excludeOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans with this originator NMLS id (digits only) — the inverse of `originator`. Common for 'everyone but my own shop' lists."}]},"excludeState":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this state (2-letter code, e.g. \"CA\") — the inverse of `state`. For \"everywhere but this state\" lists."}]},"excludeZipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exclude loans in this ZIP code — the inverse of `zipCode`."}]},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Exact 5-digit county FIPS code (no name resolution) — the code-only escape hatch alongside `county`."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"homeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"AVM (automated valuation) at the linked property (~26%, MLS-linked). Pair with `currentBalance` to approximate current equity."}]},"includeUnknownOriginator":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Include loans that have no originator NMLS id. Omitted/false (default): such loans are excluded — the vast majority are pre-2016 public records with no linkable originator. true: include them. Note that the default scopes results to loans with a known originator (~2016+ recordings)."}]},"interestRate":{"$ref":"#/components/schemas/NumericFilterValue"},"lender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID — the normalized lender-dictionary key, NOT a fuzzy name match. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"). Underscores and letter case are normalized, so either id surface works. A stored normalized lender name (what the `slice: \"lender\"` chart buckets emit) is also accepted, so a chart bucket key filters directly. A value that is neither returns 400 rather than silently matching nothing — to search by lender NAME, use `lenderName`."}]},"lenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender name as recorded on the loan document — fuzzy, all-terms match (e.g. \"Fifth Third\"). The name counterpart to the exact-id `lender` filter; use `lender` when you have a resolved id, and this when you only have a name."}]},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Funding/loan company NMLS id (digits only). Resolve a company name to its NMLS id via instantSearch."}]},"loanType":{"$ref":"#/components/schemas/LoanTypeFilterValue"},"ltvAtOrigination":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value at ORIGINATION (sparse), as a PERCENT on a 0-100 scale (`80` = 80% LTV; values above 100 are real underwater loans). This is not a current LTV — there is no stored current-LTV field on loans."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"mortgageDate":{"$ref":"#/components/schemas/DateFilterValue"},"originator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Loan originator NMLS id (digits only). To search by name use `originatorName`, or resolve a name to its id via instantSearch."}]},"originatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `originator` (exact NMLS id) instead. Still functional for now."}]},"propertyId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Parcel id — returns every loan recorded against one property. Pass the same string this endpoint returns as `mmPropertyId` on a loan row, or the `mmPropertyId` of a property record.\n\nThis is the parcel's FULL recorded loan history, which is deliberately wider than the loans embedded on a property record: that embed is a snapshot of what is still owed (up to five currently-active loans), so paid-off mortgages are absent from it and present here.\n\nMulti-unit caveat: loans carry a unit-blind parcel id, so for one unit of a multi-unit building this selects every unit in the building, not that unit alone."}]},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"transactionType":{"$ref":"#/components/schemas/LoanTransactionTypeFilterValue"},"zip":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Alias of `zipCode` — same ZIP filter, accepted for cross-entity key parity."}]},"zipCode":{"$ref":"#/components/schemas/TextFilterValue"}},"type":"object"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"nmlsId":{"type":"string"},"nmlsIds":{"items":{"type":"string"},"type":"array"},"period":{"$ref":"#/components/schemas/Period"},"segment":{"$ref":"#/components/schemas/OriginatorSegment"}},"type":"object"},"OriginatorTransactionMixFilter":{"description":"Transaction-type bands, same rules as `productMix`: `[{transactionType:\"purchase\", minShare:60}]` = purchases ≥ 60% of period volume.","items":{"additionalProperties":false,"properties":{"basis":{"description":"`volume` (default) or `units` (loan count).","enum":["volume","units"],"type":"string"},"maxShare":{"description":"Upper bound, 0–100. No bucket = 0% (passes).","example":60,"maximum":100,"minimum":0,"type":"number"},"minShare":{"description":"Lower bound, 0–100 percent of the period book.","example":25,"maximum":100,"minimum":0,"type":"number"},"transactionType":{"enum":["purchase","refinance","construction","equity","UNKNOWN"],"type":"string"},"volume":{"additionalProperties":false,"description":"Dollar volume of this type in the period, `{gte, lte}`. Needs the bucket (no loans of the type fails).","properties":{"gte":{"minimum":0,"type":"number"},"lte":{"minimum":0,"type":"number"}},"type":"object"}},"required":["transactionType"],"type":"object"},"maxItems":10,"minItems":1,"type":"array"},"OriginatorTransactionTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): purchase, refinance, construction, equity, UNKNOWN","enum":["purchase","refinance","construction","equity","UNKNOWN"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): purchase, refinance, construction, equity, UNKNOWN","enum":["purchase","refinance","construction","equity","UNKNOWN"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"Pagination":{"properties":{"cursor":{"description":"Opaque cursor from previous response for next page","type":"string"},"size":{"description":"Page size (1-100, default 25)","example":25,"maximum":100,"minimum":1,"type":"integer"}},"type":"object"},"PayloadTooLarge":{"properties":{"error":{"type":"string"},"limit":{"type":"number"},"size":{"type":"number"}},"required":["error","size","limit"],"type":"object"},"Period":{"description":"Pre-aggregated period block. Rolling windows (last30Days, last60Days, last90Days, previousMonth, currentMonth) are NOT accepted here and return 400; they are supported on the loans, sales and market endpoints (list, count, breakdowns, analytics summary / time-series / chart) (see `DatedPeriod`).","enum":["2017","2018","2019","2020","2021","2022","2023","2024","2025","2026","last3Months","last6Months","last12Months","last14Months","last16Months","last18Months","last24Months","yearToDate","allTime"],"type":"string"},"PreviewAlertsRequest":{"properties":{"detectors":{"description":"Limit to specific triggers; all six when omitted.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"}},"type":"object"},"PropertyAnalyticsFlatFilters":{"additionalProperties":false,"properties":{"activeLoanCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgages believed to still be outstanding (e.g. `{lte: 0}` for parcels with none). `{lte: 0}` alone is NOT a free-and-clear filter: it also matches recently-sold parcels whose new mortgage has not been recorded yet. Pair it with `preSaleLoanCount: {lte: 0}` for parcels we can actually verify."}]},"address":{"$ref":"#/components/schemas/TextFilterValue"},"affordableHousingTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a qualified census tract for affordable-housing programs (17,603,810 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"agentUid":{"$ref":"#/components/schemas/TextFilterValue"},"apn":{"$ref":"#/components/schemas/TextFilterValue"},"avmConfidence":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Confidence in the value estimate, as a 50–100 score (e.g. `{gte: 90}` for high-confidence estimates only). NOT a fraction — `{gte: 0.9}` matches every scored parcel, not the top decile."}]},"avmValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Automated value estimate for the parcel, in whole dollars (e.g. `{gte: 500000}`). ~77% coverage. Matches the `avm.mid` value on the response."}]},"beds":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bedroom count (e.g. `{lte: 2}` for starter homes). ~46% coverage — on the rest the bedroom count was never recorded, which is NOT the same as a parcel with no bedrooms and NOT the same as a parcel with no assessor record: 15.6M of them do carry a recorded bath count and floor area. Unrecorded parcels are EXCLUDED by default; pass `includeNulls: true` to add them back. `beds: 0` matches nothing (an unrecorded count is not a count of zero, and a genuine studio is indistinguishable from it), and the response returns `null` rather than `0`."}]},"borrowerStatus":{"$ref":"#/components/schemas/PropertyBorrowerStatusFilterValue"},"brokerNmls":{"$ref":"#/components/schemas/TextFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"companyNmls":{"$ref":"#/components/schemas/TextFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County, as a 5-digit FIPS code (e.g. `06037`). Canonical key for the county dimension; `fips` is the exact-code alias kept for back-compat."}]},"difficultDevelopmentArea":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a HUD-designated difficult development area (30,643,419 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a distressed-or-underserved nonmetropolitan middle-income tract (13,289,914 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated equity, in whole dollars (e.g. `{gte: 250000}`). Negative values are genuine underwater parcels. Derived from the value estimate minus outstanding loan balances, so it inherits their coverage (~77%) AND their gaps: on a parcel whose mortgage is missing from the record there is nothing to subtract, so this returns the full value estimate. Pair a high-equity range with `preSaleLoanCount: {lte: 0}` to drop those."}]},"equityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated equity as a FRACTION of the value estimate, where `1` = the whole value and `0.5` = half. Pass `{gte: 0.5}` for 50%-or-more equity — `{gte: 50}` is not a synonym and matches ZERO parcels, since no value exceeds 1. Negative values are genuine underwater parcels. Note the contrast with `loanLtv`, which takes whole percents. CAUTION: `1` is not proof a parcel is owned free and clear — it is also what a recently-sold parcel returns when the buyer's new mortgage has not been recorded yet, because the calculation subtracts nothing. Add `preSaleLoanCount: {lte: 0}` to restrict to parcels whose position we can actually verify."}]},"fips":{"$ref":"#/components/schemas/TextFilterValue"},"floodHazardTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a FEMA special flood hazard area (4,675,160 parcels). `tractFloodZone` gives the specific zone code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"foreclosureStatus":{"$ref":"#/components/schemas/PropertyForeclosureStatusFilterValue"},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"lastSalePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"lenderNmls":{"$ref":"#/components/schemas/TextFilterValue"},"loNmls":{"$ref":"#/components/schemas/TextFilterValue"},"loanCount":{"$ref":"#/components/schemas/NumericFilterValue"},"lotSquareFeet":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Lot size in square feet (e.g. `{gte: 5000}`). ~85% coverage; unmeasured parcels are excluded by default — pass `includeNulls: true` to add them back. `lotSquareFeet: 0` matches nothing (the response returns `null`)."}]},"lowModIncomeTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a low- or moderate-income tract under the Community Reinvestment Act (34,010,153 parcels). `tractIncomeLevel` is the four-way form of the same classification. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a majority-minority tract (38,745,783 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToCollege":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToSchool":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToWorship":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageBalance":{"$ref":"#/components/schemas/NumericFilterValue"},"opportunityZone":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a federally designated Opportunity Zone tract (10,277,168 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ownerName":{"$ref":"#/components/schemas/TextFilterValue"},"preSaleLoanCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgages excluded from `activeLoanCount` because the parcel sold after they were recorded — the seller's loan, assumed paid off at closing. Use it to separate the two meanings of `activeLoanCount: 0`: `{activeLoanCount: {lte: 0}, preSaleLoanCount: {lte: 0}}` returns parcels where nothing was excluded, so the zero is backed by the record; `{activeLoanCount: {lte: 0}, preSaleLoanCount: {gte: 1}}` returns the parcels where it is not. On its own a non-zero value is unremarkable — most recently-sold parcels have one and also carry a current mortgage."}]},"ruralTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a rural tract (29,289,319 parcels). Thinner coverage than the other flags — stamped on 111.9M of 161.1M parcels, and a parcel with no value is dropped by either `true` or `false`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"saleCount":{"$ref":"#/components/schemas/NumericFilterValue"},"salePropensity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Likelihood the parcel sells in the near term, as a 0–100 score (e.g. `{gte: 80}` for the most likely to sell). NOT a fraction — `{gte: 0.8}` matches nearly every scored parcel. `salePropensityCategory` is the bucketed form of the same signal."}]},"salePropensityCategory":{"$ref":"#/components/schemas/PropertySalePropensityCategoryFilterValue"},"squareFeet":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Building area in square feet (e.g. `{gte: 1500}`). ~68% coverage; unmeasured parcels are excluded by default — pass `includeNulls: true` to add them back. `squareFeet: 0` matches nothing (the response returns `null`)."}]},"state":{"$ref":"#/components/schemas/TextFilterValue"},"tractApplications":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage applications reported in the tract over the year, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractAsianPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Asian (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractBlackPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Black (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractCountyCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Three-digit county FIPS code of the tract (county-within-state, NOT the 5-digit `county`/`fips` key). Pass with `tractStateCode` and `tractId` to pin one neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractDenialRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the tract's mortgage applications that were denied, 0-100 (e.g. `{gte: 25}` for 25%+). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractFamilyIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median family income of the tract, in whole dollars (e.g. `{lte: 60000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractFloodZone":{"$ref":"#/components/schemas/PropertyTractFloodZoneFilterValue"},"tractHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Hispanic or Latino share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractHomeownershipRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Owner-occupied share of the tract's housing units, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractHouseholdIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median household income of the tract, in whole dollars (e.g. `{gte: 120000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Six-digit tract code. A tract code REPEATS in every state and county, so this only identifies a neighborhood when passed ALONGSIDE `tractStateCode` and `tractCountyCode` — on its own it matches roughly 75× too many parcels. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractIncomeLevel":{"$ref":"#/components/schemas/PropertyTractIncomeLevelFilterValue"},"tractIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Tract income relative to its metro area, where `100` is parity — `{lt: 80}` is the CRA low/moderate band and values legitimately exceed 100 (observed up to 412). NOT a 0-100 share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractLoanVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage dollar volume reported in the tract over the year, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMedianAge":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median age of the tract's population, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMedianHomeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median home value across the tract, in whole dollars. A neighborhood statistic — the parcel's own value estimate is `avmValue`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMinorityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Non-white share of the tract's population, 0-100 (e.g. `{gte: 50}` for majority-minority; `majorityMinorityTract` is the flag form). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractOriginations":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage originations reported in the tract over the year, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractPopulation":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Total population of the tract. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractPovertyRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the tract's population below the poverty line, 0-100 (e.g. `{gte: 20}` for 20%+). Pass whole percents — `{gte: 0.2}` means 0.2% and matches almost every tract. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractRuralGradient":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Remoteness of the tract on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). This is a code, not a percent — `{gte: 7}` selects the most remote tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractStateCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Two-digit state FIPS code of the tract. Pass with `tractCountyCode` and `tractId` to pin one neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractWhiteNonHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"White (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"usdaEligibleTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a tract eligible for USDA rural housing programs (70,637,816 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"yearBuilt":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"$ref":"#/components/schemas/TextFilterValue"},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"ZIP code. Canonical key (matches loans `zipCode` and the response DTO); `zip` is a legacy alias kept for back-compat."}]}},"type":"object"},"PropertyAnalyticsResponse":{"properties":{"avgAvmValue":{"description":"Average AVM value","nullable":true,"type":"number"},"avgEquity":{"description":"Average estimated equity. Excludes values outside -2,000,000 to 50,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","nullable":true,"type":"number"},"excluded":{"description":"Per-measure count of parcels this query's sentinel guard excluded — parcels that carry the field but whose value is an out-of-range fill. Compare against `totalCount` to see what share of the matched population the figure was computed over. Absent for `avgAvmValue`, which is unguarded.","properties":{"avgEquity":{"type":"number"}},"type":"object"},"pctInForeclosure":{"nullable":true,"type":"number"},"totalCount":{"type":"number"}},"required":["totalCount","avgAvmValue","avgEquity","pctInForeclosure"],"type":"object"},"PropertyAvm":{"nullable":true,"properties":{"confidence":{"description":"0–100","nullable":true,"type":"number"},"high":{"nullable":true,"type":"number"},"low":{"nullable":true,"type":"number"},"mid":{"nullable":true,"type":"number"}},"required":["low","mid","high","confidence"],"type":"object"},"PropertyBorrowerStatusFilterValue":{"anyOf":[{"description":"One of (case-insensitive): no_active_loans, Current, Current_via_ALI","enum":["no_active_loans","Current","Current_via_ALI"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): no_active_loans, Current, Current_via_ALI","enum":["no_active_loans","Current","Current_via_ALI"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/PropertyAnalyticsFlatFilters"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"slice":{"$ref":"#/components/schemas/PropertyChartSlice"}},"required":["slice"],"type":"object"},"PropertyChartSlice":{"enum":["city","county","state","zipCode","zip","foreclosureStatus","borrowerStatus","salePropensityCategory"],"type":"string"},"PropertyCommunityLending":{"description":"Community Lending — the profile of the neighborhood (U.S. Census tract) this parcel sits in: program designations, income and affordability, the population profile, the local mortgage market, remoteness and proximity. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100. Two fields are deliberately NOT 0-100: `tractIncomeVsMetroPct` is a ratio where 100 means parity with the metro (it exceeds 100), and `tractRuralGradient` is an ordinal 1-10 code. `null` — not an all-null object — for the roughly 6% of parcels that resolve to no neighborhood. Every field here is also a filter key on `POST /properties`.","nullable":true,"properties":{"affordableHousingTract":{"description":"A qualified neighborhood for affordable-housing programs. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"difficultDevelopmentArea":{"description":"A HUD-designated difficult development area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"distressedTract":{"description":"A distressed-or-underserved nonmetropolitan middle-income neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"floodHazardTract":{"description":"In a FEMA special flood hazard area. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"lowModIncomeTract":{"description":"A low- or moderate-income neighborhood under the Community Reinvestment Act. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"majorityMinorityTract":{"description":"A majority-minority neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"milesToCollege":{"description":"Distance to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"milesToSchool":{"description":"Distance to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"milesToWorship":{"description":"Distance to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"opportunityZone":{"description":"In a federally designated Opportunity Zone. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"ruralTract":{"description":"A rural neighborhood. Thinner coverage than the other designations, so null is common. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"},"tractApplications":{"description":"Mortgage applications reported over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractAsianPct":{"description":"Asian (non-Hispanic) share of the population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractBlackPct":{"description":"Black (non-Hispanic) share of the population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractCountyCode":{"description":"Public three-digit county-within-state code (not the five-digit `fips`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"string"},"tractDenialRate":{"description":"Share of mortgage applications that were denied. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractFamilyIncome":{"description":"Median family income, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractFloodZone":{"description":"FEMA flood-zone code (e.g. `AE`). Null means no special flood hazard area on file. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"string"},"tractHispanicPct":{"description":"Hispanic or Latino share of the population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractHomeownershipRate":{"description":"Owner-occupied share of housing units. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractHouseholdIncome":{"description":"Median household income, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractId":{"description":"Public six-digit neighborhood code. It repeats in every state and county, so it identifies a neighborhood only together with `tractStateCode` and `tractCountyCode`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"string"},"tractIncomeLevel":{"description":"Relative-income classification of the neighborhood: low, moderate, middle or upper. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","enum":["low","moderate","middle","upper",null],"nullable":true,"type":"string"},"tractIncomeVsMetroPct":{"description":"Neighborhood income relative to its metro area, where 100 is parity. Legitimately exceeds 100 — this is a ratio, not a share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractLoanVolume":{"description":"Mortgage dollar volume reported over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractMedianAge":{"description":"Median age, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractMedianHomeValue":{"description":"Median home value across the neighborhood, in whole dollars — a neighborhood statistic, not this parcel's value estimate (see `avm`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractMinorityPct":{"description":"Non-white share of the population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractOriginations":{"description":"Mortgage originations reported over the year. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractPopulation":{"description":"Total population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractPovertyRate":{"description":"Share of the population below the poverty line. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractRuralGradient":{"description":"Remoteness on an ordinal 1-10 scale (1 = metropolitan core, 10 = most remote). A code, not a percent. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"tractStateCode":{"description":"Public two-digit state code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"string"},"tractWhiteNonHispanicPct":{"description":"White (non-Hispanic) share of the population. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"number"},"usdaEligibleTract":{"description":"Eligible for USDA rural housing programs. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.","nullable":true,"type":"boolean"}},"required":["opportunityZone","majorityMinorityTract","lowModIncomeTract","distressedTract","usdaEligibleTract","ruralTract","difficultDevelopmentArea","affordableHousingTract","floodHazardTract","tractIncomeLevel","tractFamilyIncome","tractHouseholdIncome","tractIncomeVsMetroPct","tractPovertyRate","tractMinorityPct","tractPopulation","tractMedianAge","tractMedianHomeValue","tractHomeownershipRate","tractHispanicPct","tractBlackPct","tractAsianPct","tractWhiteNonHispanicPct","tractOriginations","tractApplications","tractLoanVolume","tractDenialRate","tractRuralGradient","tractFloodZone","milesToSchool","milesToCollege","milesToWorship","tractId","tractStateCode","tractCountyCode"],"type":"object"},"PropertyDetail":{"allOf":[{"$ref":"#/components/schemas/PropertySummary"},{"properties":{"communityLending":{"$ref":"#/components/schemas/PropertyCommunityLending"},"enrichment":{"description":"Owner contact enrichment data (included if previously enriched by the authenticated user)","nullable":true,"properties":{"enrichedAt":{"description":"ISO 8601 timestamp","type":"string"},"persons":{"items":{"$ref":"#/components/schemas/SkipTracePerson"},"type":"array"},"source":{"description":"Data source identifier","type":"string"}},"required":["persons","enrichedAt","source"],"type":"object"},"foreclosureDetail":{"nullable":true,"properties":{"beneficiaryLender":{"nullable":true,"type":"string"},"count":{"nullable":true,"type":"number"},"latestCode":{"nullable":true,"type":"string"},"latestDate":{"nullable":true,"type":"string"},"trusteeSaleNumber":{"nullable":true,"type":"string"},"unpaidBalance":{"nullable":true,"type":"number"}},"required":["count","latestCode","latestDate","beneficiaryLender","trusteeSaleNumber","unpaidBalance"],"type":"object"},"ownerMailingAddress":{"nullable":true,"properties":{"city":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"}},"required":["street","city","state","zip"],"type":"object"},"owners":{"description":"Every owner of record — `owners[0]` is the same person the flat `ownerName`/`ownerFirstName`/`ownerLastName` fields describe, and the rest are co-owners/co-borrowers. Additive: those three fields are unchanged. `null` (never `[]`) when the parcel has no readable owner.","items":{"$ref":"#/components/schemas/PropertyOwner"},"nullable":true,"type":"array"},"parties":{"$ref":"#/components/schemas/PropertyParties"},"position":{"properties":{"activeOverFive":{"nullable":true,"type":"boolean"},"loanCountActive":{"nullable":true,"type":"number"},"loanCountAll":{"nullable":true,"type":"number"},"loanCountPaidOff":{"nullable":true,"type":"number"},"loanCountPreSale":{"description":"Mortgages excluded because the parcel sold after they were recorded. Same value as the summary's `preSaleLoanCount`. These four counts partition `loanCountAll`.","nullable":true,"type":"number"},"loanCountReleased":{"description":"Mortgages with a recorded release — documented evidence of a payoff, unlike `loanCountPreSale`.","nullable":true,"type":"number"},"sumOutstanding":{"nullable":true,"type":"number"}},"required":["loanCountAll","loanCountActive","loanCountPaidOff","loanCountReleased","loanCountPreSale","sumOutstanding","activeOverFive"],"type":"object"},"relationships":{"$ref":"#/components/schemas/PropertyRelationships"}},"type":"object"}]},"PropertyDetailResponse":{"properties":{"alternates":{"description":"Sibling document `id`s when `ambiguousRef` is true — pass one back as `/{id}` to fetch that exact unit. Absent on an unambiguous lookup.","items":{"type":"string"},"type":"array"},"ambiguousRef":{"description":"`true` only when the id you passed resolved to more than one parcel (a non-unique `mm_property_id` colliding across units). `data` is a deterministic pick (the base parcel); use `alternates` to re-request a specific sibling by its exact `id`. Absent on an unambiguous lookup.","type":"boolean"},"data":{"$ref":"#/components/schemas/PropertyDetail"}},"required":["data"],"type":"object"},"PropertyEnrichment":{"properties":{"enrichedAt":{"description":"ISO 8601 timestamp","type":"string"},"persons":{"items":{"$ref":"#/components/schemas/SkipTracePerson"},"type":"array"},"source":{"description":"Data source identifier","type":"string"}},"required":["persons","enrichedAt","source"],"type":"object"},"PropertyEquity":{"nullable":true,"properties":{"pct":{"description":"Equity as a FRACTION of the value estimate — `1` is the whole value, `0.5` is half. A `1` alongside `activeLoanCountKnown: false` is arithmetic on a missing mortgage, not a free-and-clear parcel.","nullable":true,"type":"number"},"value":{"description":"Estimated equity in whole dollars — the value estimate minus the outstanding balance of the mortgages we know about. It inherits their completeness: when `activeLoanCountKnown` is `false` there is no known balance to subtract, so this equals the full value estimate and should NOT be read as equity.","nullable":true,"type":"number"}},"required":["value","pct"],"type":"object"},"PropertyField":{"enum":["address","city","state","zipCode","zip","apn","fips","ownerName","beds","squareFeet","lotSquareFeet","yearBuilt","avmValue","avmConfidence","equity","equityPct","salePropensity","salePropensityCategory","foreclosureStatus","borrowerStatus","loanCount","activeLoanCount","mortgageBalance","saleCount","lastSalePrice","loNmls","lenderNmls","companyNmls","brokerNmls","agentUid"],"type":"string"},"PropertyFlatFilters":{"additionalProperties":false,"properties":{"activeLoanCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgages believed to still be outstanding (e.g. `{lte: 0}` for parcels with none). `{lte: 0}` alone is NOT a free-and-clear filter: it also matches recently-sold parcels whose new mortgage has not been recorded yet. Pair it with `preSaleLoanCount: {lte: 0}` for parcels we can actually verify."}]},"address":{"$ref":"#/components/schemas/TextFilterValue"},"affordableHousingTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a qualified census tract for affordable-housing programs (17,603,810 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"agentUid":{"$ref":"#/components/schemas/TextFilterValue"},"apn":{"$ref":"#/components/schemas/TextFilterValue"},"avmConfidence":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Confidence in the value estimate, as a 50–100 score (e.g. `{gte: 90}` for high-confidence estimates only). NOT a fraction — `{gte: 0.9}` matches every scored parcel, not the top decile."}]},"avmValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Automated value estimate for the parcel, in whole dollars (e.g. `{gte: 500000}`). ~77% coverage. Matches the `avm.mid` value on the response."}]},"beds":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Bedroom count (e.g. `{lte: 2}` for starter homes). ~46% coverage — on the rest the bedroom count was never recorded, which is NOT the same as a parcel with no bedrooms and NOT the same as a parcel with no assessor record: 15.6M of them do carry a recorded bath count and floor area. Unrecorded parcels are EXCLUDED by default; pass `includeNulls: true` to add them back. `beds: 0` matches nothing (an unrecorded count is not a count of zero, and a genuine studio is indistinguishable from it), and the response returns `null` rather than `0`."}]},"borrowerStatus":{"$ref":"#/components/schemas/PropertyBorrowerStatusFilterValue"},"brokerNmls":{"$ref":"#/components/schemas/TextFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"companyNmls":{"$ref":"#/components/schemas/TextFilterValue"},"county":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"County, as a 5-digit FIPS code (e.g. `06037`). Canonical key for the county dimension; `fips` is the exact-code alias kept for back-compat."}]},"difficultDevelopmentArea":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a HUD-designated difficult development area (30,643,419 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"distressedTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a distressed-or-underserved nonmetropolitan middle-income tract (13,289,914 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"equity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated equity, in whole dollars (e.g. `{gte: 250000}`). Negative values are genuine underwater parcels. Derived from the value estimate minus outstanding loan balances, so it inherits their coverage (~77%) AND their gaps: on a parcel whose mortgage is missing from the record there is nothing to subtract, so this returns the full value estimate. Pair a high-equity range with `preSaleLoanCount: {lte: 0}` to drop those."}]},"equityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Estimated equity as a FRACTION of the value estimate, where `1` = the whole value and `0.5` = half. Pass `{gte: 0.5}` for 50%-or-more equity — `{gte: 50}` is not a synonym and matches ZERO parcels, since no value exceeds 1. Negative values are genuine underwater parcels. Note the contrast with `loanLtv`, which takes whole percents. CAUTION: `1` is not proof a parcel is owned free and clear — it is also what a recently-sold parcel returns when the buyer's new mortgage has not been recorded yet, because the calculation subtracts nothing. Add `preSaleLoanCount: {lte: 0}` to restrict to parcels whose position we can actually verify."}]},"fips":{"$ref":"#/components/schemas/TextFilterValue"},"floodHazardTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a FEMA special flood hazard area (4,675,160 parcels). `tractFloodZone` gives the specific zone code. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"foreclosureStatus":{"$ref":"#/components/schemas/PropertyForeclosureStatusFilterValue"},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"id":{"description":"Exact parcel ids (up to 50,000, any-of). A property `id` from the list/search rows (`mm_<fips><apn>|<fips>-<apn>|<unit>`, exactly that parcel) or an `mmPropertyId` (`mm_<fips><apn>`, every unit of the parcel). Must start with `mm_`. ANDed with the other filters, even under `mode: \"or\"`.","items":{"pattern":"^mm_\\S","type":"string"},"maxItems":50000,"minItems":1,"type":"array"},"lastSalePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"lenderNmls":{"$ref":"#/components/schemas/TextFilterValue"},"loNmls":{"$ref":"#/components/schemas/TextFilterValue"},"loanAmount":{"$ref":"#/components/schemas/NumericFilterValue"},"loanBalance":{"$ref":"#/components/schemas/NumericFilterValue"},"loanBorrowerStatus":{"$ref":"#/components/schemas/PropertyLoanBorrowerStatusFilterValue"},"loanCompany":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Per-loan funding-company NMLS id (digits only) on the parcel's loans."}]},"loanCount":{"$ref":"#/components/schemas/NumericFilterValue"},"loanInterestRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Deprecated alias of `loanModeledInterestRate` — a low-biased ModelMatch model that caps near 7%. For the genuine recorded note rate use `recordedInterestRate`."}]},"loanLender":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender ID on the parcel's loans — the normalized lender-dictionary key, NOT the lender name the response shows. Resolve a lender via instantSearch (or listLenders) and pass the `id` it returns (e.g. \"mortgage_rocket\" or \"mortgage rocket\"); the `lenderId` on a parcel's `loans[]` is the same value, so a lender read off a result round-trips here directly. Underscores and letter case are normalized, and the id expands to every stored variant the lender is recorded under. A value that is neither an id nor a stored lender name returns 400 with the closest matches, rather than silently matching nothing — to filter by the lender NAME shown on the parcel, use `loanLenderName`."}]},"loanLenderName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Lender NAME on the parcel's loans — the counterpart to the exact-id `loanLender`, and the filter that accepts the `lenderName` a parcel's `loans[]` displays (e.g. \"UNION HOME MORTGAGE CORP\"). Case-insensitive, matched against the name recorded on the loan. When the name is one the lender dictionary knows, it also expands to that lender's whole recorded-name family, so a brand name (\"union home mortgage\") selects far more than the one literal string. Never 400s: a name it cannot resolve simply matches the recorded string. The response reports how each value resolved as `lenderNormalizations`."}]},"loanLtv":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Loan-to-value on the parcel's active loan(s), as WHOLE PERCENTS — `{gte: 40, lte: 50}` means 40%–50% LTV. A fractional range (`{gte: 0.4, lte: 0.5}`) is not a synonym and matches ZERO parcels. ~7% coverage. Careful: the response DTO reports the same measurement as a fraction (`loans[].ltv` of `0.4238` is 42.38% LTV), so a value read off a result must be multiplied by 100 before it can be used here. `equityPct`, by contrast, takes the fraction. Two further limits of the stored value. It SATURATES at 10 and 199 — no parcel stores a ratio outside that range, so `{gte: 200}` matches nothing at all, and the extremes are dominated by parcels whose true ratio was merely clipped to the bound; the response returns those as `null`, but this filter still selects them. And the underlying value is not a dependable per-loan ratio — two thirds of parcels with several mortgages store an identical figure across loans of very different amounts (see `loans[].ltv`, deprecated). For selecting on borrower position prefer `equityPct`, which has neither limitation."}]},"loanMatchMode":{"description":"How the loan-slot filters combine across a parcel's 5 cached loans. `correlated` (default): ONE loan (any slot) must satisfy ALL loan-slot conditions. `most_recent`: only the newest loan (loan_1). `any`: each condition may be satisfied by a different loan. `none`: ignore loan-slot filters. Honored on list, bulk-delivery, and bulk-enrich.","enum":["correlated","most_recent","any","none"],"type":"string"},"loanModeledInterestRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Per-loan MODELED rate (`loan_N.modeled_interest_rate`). Low-biased, effectively caps near 7% — not a note rate. Use `recordedInterestRate` for the recorded rate."}]},"loanOriginator":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Per-loan originator NMLS id (digits only) on the parcel's loans. For all-time attribution across the parcel use `loNmls`."}]},"loanOriginatorName":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"deprecated":true,"description":"DEPRECATED — fuzzy name matching is unreliable (same originator can return wildly different counts by name string). Resolve the loan officer via instantSearch and filter by `loanOriginator` (exact NMLS id) instead. Still functional for now."}]},"loanRecordedDate":{"$ref":"#/components/schemas/DateFilterValue"},"loanTransactionType":{"$ref":"#/components/schemas/PropertyLoanTransactionTypeFilterValue"},"loanType":{"$ref":"#/components/schemas/PropertyLoanTypeFilterValue"},"lotSquareFeet":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Lot size in square feet (e.g. `{gte: 5000}`). ~85% coverage; unmeasured parcels are excluded by default — pass `includeNulls: true` to add them back. `lotSquareFeet: 0` matches nothing (the response returns `null`)."}]},"lowModIncomeTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a low- or moderate-income tract under the Community Reinvestment Act (34,010,153 parcels). `tractIncomeLevel` is the four-way form of the same classification. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"majorityMinorityTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a majority-minority tract (38,745,783 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToCollege":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest college, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToSchool":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest school, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"milesToWorship":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Straight-line distance from the parcel to the nearest place of worship, in miles. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"mode":{"enum":["and","or"],"type":"string"},"mortgageBalance":{"$ref":"#/components/schemas/NumericFilterValue"},"opportunityZone":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a federally designated Opportunity Zone tract (10,277,168 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"ownerName":{"$ref":"#/components/schemas/TextFilterValue"},"preSaleLoanCount":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgages excluded from `activeLoanCount` because the parcel sold after they were recorded — the seller's loan, assumed paid off at closing. Use it to separate the two meanings of `activeLoanCount: 0`: `{activeLoanCount: {lte: 0}, preSaleLoanCount: {lte: 0}}` returns parcels where nothing was excluded, so the zero is backed by the record; `{activeLoanCount: {lte: 0}, preSaleLoanCount: {gte: 1}}` returns the parcels where it is not. On its own a non-zero value is unremarkable — most recently-sold parcels have one and also carry a current mortgage."}]},"programEligibility":{"description":"Restrict to parcels whose value estimate falls within this loan program's county price limit — an eligibility band (value ceiling). Pair with `fips` to resolve the county's limit; with no county context the national baseline applies. Parcels without a value estimate are excluded. This is a price band only — no borrower income, payment, or DTI is considered.","enum":["fha","conforming"],"type":"string"},"recordedInterestRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Genuine RECORDED note rate from the parcel's active loan(s) (~7% coverage, concentrated on the most-recent loan). Percent input (e.g. 7 means 7%)."}]},"ruralTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a rural tract (29,289,319 parcels). Thinner coverage than the other flags — stamped on 111.9M of 161.1M parcels, and a parcel with no value is dropped by either `true` or `false`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"saleCount":{"$ref":"#/components/schemas/NumericFilterValue"},"salePropensity":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Likelihood the parcel sells in the near term, as a 0–100 score (e.g. `{gte: 80}` for the most likely to sell). NOT a fraction — `{gte: 0.8}` matches nearly every scored parcel. `salePropensityCategory` is the bucketed form of the same signal."}]},"salePropensityCategory":{"$ref":"#/components/schemas/PropertySalePropensityCategoryFilterValue"},"squareFeet":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Building area in square feet (e.g. `{gte: 1500}`). ~68% coverage; unmeasured parcels are excluded by default — pass `includeNulls: true` to add them back. `squareFeet: 0` matches nothing (the response returns `null`)."}]},"state":{"$ref":"#/components/schemas/TextFilterValue"},"tractApplications":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage applications reported in the tract over the year, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractAsianPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Asian (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractBlackPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Black (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractCountyCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Three-digit county FIPS code of the tract (county-within-state, NOT the 5-digit `county`/`fips` key). Pass with `tractStateCode` and `tractId` to pin one neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractDenialRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the tract's mortgage applications that were denied, 0-100 (e.g. `{gte: 25}` for 25%+). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractFamilyIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median family income of the tract, in whole dollars (e.g. `{lte: 60000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractFloodZone":{"$ref":"#/components/schemas/PropertyTractFloodZoneFilterValue"},"tractHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Hispanic or Latino share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractHomeownershipRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Owner-occupied share of the tract's housing units, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractHouseholdIncome":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median household income of the tract, in whole dollars (e.g. `{gte: 120000}`). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractId":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Six-digit tract code. A tract code REPEATS in every state and county, so this only identifies a neighborhood when passed ALONGSIDE `tractStateCode` and `tractCountyCode` — on its own it matches roughly 75× too many parcels. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractIncomeLevel":{"$ref":"#/components/schemas/PropertyTractIncomeLevelFilterValue"},"tractIncomeVsMetroPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Tract income relative to its metro area, where `100` is parity — `{lt: 80}` is the CRA low/moderate band and values legitimately exceed 100 (observed up to 412). NOT a 0-100 share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractLoanVolume":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage dollar volume reported in the tract over the year, in whole dollars. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMedianAge":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median age of the tract's population, in years. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMedianHomeValue":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Median home value across the tract, in whole dollars. A neighborhood statistic — the parcel's own value estimate is `avmValue`. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractMinorityPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Non-white share of the tract's population, 0-100 (e.g. `{gte: 50}` for majority-minority; `majorityMinorityTract` is the flag form). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractOriginations":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Mortgage originations reported in the tract over the year, as a count. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractPopulation":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Total population of the tract. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractPovertyRate":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Share of the tract's population below the poverty line, 0-100 (e.g. `{gte: 20}` for 20%+). Pass whole percents — `{gte: 0.2}` means 0.2% and matches almost every tract. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractRuralGradient":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"Remoteness of the tract on an ORDINAL 1-10 scale (1 = metropolitan core, 10 = most remote). This is a code, not a percent — `{gte: 7}` selects the most remote tracts. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractStateCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"Two-digit state FIPS code of the tract. Pass with `tractCountyCode` and `tractId` to pin one neighborhood. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"tractWhiteNonHispanicPct":{"allOf":[{"$ref":"#/components/schemas/NumericFilterValue"},{"description":"White (non-Hispanic) share of the tract's population, 0-100. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"usdaEligibleTract":{"allOf":[{"$ref":"#/components/schemas/BooleanFilterValue"},{"description":"Parcel sits in a tract eligible for USDA rural housing programs (70,637,816 parcels). Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100."}]},"yearBuilt":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"$ref":"#/components/schemas/TextFilterValue"},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"ZIP code. Canonical key (matches loans `zipCode` and the response DTO); `zip` is a legacy alias kept for back-compat."}]}},"type":"object"},"PropertyForeclosure":{"properties":{"matched":{"type":"boolean"},"scheduledAuctionDate":{"nullable":true,"type":"string"},"status":{"description":"e.g. \"in_foreclosure\" or \"unknown\"","nullable":true,"type":"string"}},"required":["matched","status","scheduledAuctionDate"],"type":"object"},"PropertyForeclosureStatusFilterValue":{"anyOf":[{"description":"One of (case-insensitive): unknown, in_foreclosure","enum":["unknown","in_foreclosure"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): unknown, in_foreclosure","enum":["unknown","in_foreclosure"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyLastPartyRoster":{"description":"The most recent loan's originator(s). Deliberately originator-only — see the parent description.","properties":{"originators":{"items":{"type":"string"},"type":"array"}},"required":["originators"],"type":"object"},"PropertyListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/PropertyFlatFilters"},"pagination":{"$ref":"#/components/schemas/Pagination"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/PropertyField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"PropertyListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/PropertySummary"},"type":"array"},"lenderNormalizations":{"description":"How each `loanLenderName` value resolved against the lender dictionary. Present when a `loanLenderName` filter was supplied. A `matchedVia` of `unresolved` means only the recorded lender string was matched, not the lender's whole name family.","items":{"$ref":"#/components/schemas/LenderNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"PropertyLoan":{"properties":{"amount":{"nullable":true,"type":"number"},"amountPlausible":{"description":"`false` when `amount` is outside the range our mortgage metrics treat as possible, so aggregate totals exclude this loan while this row still shows it. Usually an institutional blanket loan — one note recorded against every parcel in a pool — which is a real record but not this property's debt. This judges SIZE only, so `true` means the amount is a believable one, not that it is the right one.","type":"boolean"},"borrowerStatus":{"nullable":true,"type":"string"},"brokerNmls":{"nullable":true,"type":"string"},"companyNmls":{"nullable":true,"type":"string"},"currentBalance":{"nullable":true,"type":"number"},"interestRate":{"nullable":true,"type":"number"},"lenderId":{"description":"Lender id for this loan — pass it back as `loanLender` to select every parcel financed by the same lender, exactly as a chart bucket's `id` round-trips. `null` when this loan carries no lender id; use `lenderName` with `loanLenderName` in that case.","nullable":true,"type":"string"},"lenderName":{"description":"Lender name as recorded on the loan document — the same value `/v1/loans` returns as `lenderName` for this loan. To filter parcels by it, pass it as `loanLenderName`; `lenderId` is the exact-id route.","nullable":true,"type":"string"},"lenderNmls":{"nullable":true,"type":"string"},"loanType":{"nullable":true,"type":"string"},"ltv":{"description":"DEPRECATED — do not use; will be removed in a future major. This is not a reliable loan-to-value ratio. It is NOT per-loan: two thirds of parcels carrying several mortgages report an identical figure across loans of very different amounts, so per-loan equity computed from it is wrong. Nor does it consistently track the parcel's combined position, so it cannot be read as a whole-parcel ratio either. `null` when unknown — the stored value is clipped to a fixed range and both ends mean \"clipped\" rather than a real ratio, so they are returned as `null` rather than as a plausible-looking number. For a dependable measure of borrower position use `equity` on the parcel.","nullable":true,"type":"number"},"originatorName":{"nullable":true,"type":"string"},"originatorNmls":{"nullable":true,"type":"string"},"recordedInterestRate":{"nullable":true,"type":"number"},"recordingDate":{"nullable":true,"type":"string"},"transactionType":{"nullable":true,"type":"string"}},"required":["amount","currentBalance","interestRate","recordedInterestRate","loanType","transactionType","ltv","recordingDate","borrowerStatus","lenderNmls","lenderName","lenderId","originatorNmls","originatorName","brokerNmls","companyNmls"],"type":"object"},"PropertyLoanBorrowerStatusFilterValue":{"anyOf":[{"description":"One of (case-insensitive): Current, Current_via_ALI","enum":["Current","Current_via_ALI"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): Current, Current_via_ALI","enum":["Current","Current_via_ALI"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyLoanTransactionTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): purchase, refinance, equity, construction","enum":["purchase","refinance","equity","construction"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): purchase, refinance, equity, construction","enum":["purchase","refinance","equity","construction"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyLoanTypeFilterValue":{"anyOf":[{"description":"One of (case-insensitive): va, fha, conventional","enum":["va","fha","conventional"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): va, fha, conventional","enum":["va","fha","conventional"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyOwner":{"properties":{"firstName":{"nullable":true,"type":"string"},"fullName":{"description":"Per-owner composed display name; null when the record came from the assessment slots, which have no composed form.","nullable":true,"type":"string"},"lastName":{"nullable":true,"type":"string"},"middleName":{"nullable":true,"type":"string"}},"required":["firstName","middleName","lastName","fullName"],"type":"object"},"PropertyParties":{"description":"Mortgage parties attributed to the parcel, split by scope: `alltime` (everyone on record, a strict superset of the rest), `active` (parties on loans still outstanding), `matched` (the subset whose loan resolved to a known NMLS entity) and `last` (the most recent loan). Real estate agents are not part of this block — reach parcels from an agent through `POST /v1/agents/{id}/properties`.","properties":{"active":{"$ref":"#/components/schemas/PropertyPartyRoster"},"alltime":{"$ref":"#/components/schemas/PropertyPartyRoster"},"last":{"$ref":"#/components/schemas/PropertyLastPartyRoster"},"matched":{"$ref":"#/components/schemas/PropertyPartyRoster"}},"required":["alltime","active","matched","last"],"type":"object"},"PropertyPartyRoster":{"description":"NMLS ids of the mortgage parties attributed to the parcel under one scope. Each id resolves through the originator, lender and company detail endpoints.","properties":{"brokers":{"items":{"type":"string"},"type":"array"},"companies":{"items":{"type":"string"},"type":"array"},"lenders":{"items":{"type":"string"},"type":"array"},"originators":{"items":{"type":"string"},"type":"array"}},"required":["originators","lenders","companies","brokers"],"type":"object"},"PropertyRelationships":{"properties":{"agents":{"items":{"type":"string"},"type":"array"},"brokers":{"items":{"type":"string"},"type":"array"},"companies":{"items":{"type":"string"},"type":"array"},"lenders":{"items":{"type":"string"},"type":"array"},"originators":{"items":{"type":"string"},"type":"array"}},"required":["originators","lenders","companies","brokers","agents"],"type":"object"},"PropertyResolveRequest":{"properties":{"addresses":{"items":{"properties":{"address":{"description":"Street line, e.g. \"123 N Main St Apt 4\".","maxLength":300,"type":"string"},"city":{"maxLength":100,"type":"string"},"line":{"description":"The whole address as one line (\"123 Main St, Springfield, IL 62701\"). Used for any part the fields leave empty.","maxLength":500,"type":"string"},"ref":{"description":"Your row key, echoed back. Defaults to the row's 0-based position.","maxLength":200,"type":"string"},"state":{"maxLength":50,"type":"string"},"zip":{"maxLength":20,"type":"string"}},"type":"object"},"maxItems":2000,"minItems":1,"type":"array"}},"required":["addresses"],"type":"object"},"PropertyResolveResponse":{"properties":{"results":{"items":{"properties":{"address":{"description":"The matched parcel's address as stored.","type":"string"},"candidates":{"description":"Up to 5 competing parcels on an `ambiguous` row.","items":{"properties":{"address":{"type":"string"},"id":{"type":"string"},"mmPropertyId":{"nullable":true,"type":"string"},"score":{"type":"number"}},"required":["id","mmPropertyId","address","score"],"type":"object"},"type":"array"},"id":{"description":"The parcel document id (pass to `propertyIds` / `flatFilters.id`). Absent when a multi-unit parcel matched without a unit — use `mmPropertyId`, which selects every unit.","type":"string"},"matchedBy":{"enum":["exact_key","search"],"type":"string"},"mmPropertyId":{"type":"string"},"reason":{"enum":["unit_required","duplicate_parcels","multiple_parcels","no_parcel_at_number","low_confidence","no_house_number","no_street","no_location","search_failed","search_budget_exhausted"],"type":"string"},"ref":{"type":"string"},"score":{"description":"Match confidence 0–1: 1 for an exact key match, street-name similarity for a search match.","type":"number"},"status":{"enum":["matched","ambiguous","not_found"],"type":"string"}},"required":["ref","status"],"type":"object"},"type":"array"},"summary":{"properties":{"ambiguous":{"type":"integer"},"matched":{"type":"integer"},"notFound":{"type":"integer"}},"required":["matched","ambiguous","notFound"],"type":"object"}},"required":["results","summary"],"type":"object"},"PropertySalePropensity":{"nullable":true,"properties":{"category":{"description":"Low/Medium/High","nullable":true,"type":"string"},"score":{"description":"0–100","nullable":true,"type":"number"}},"required":["score","category"],"type":"object"},"PropertySalePropensityCategoryFilterValue":{"anyOf":[{"description":"One of (case-insensitive): High, Medium, Low","enum":["High","Medium","Low"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): High, Medium, Low","enum":["High","Medium","Low"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertySales":{"properties":{"count":{"nullable":true,"type":"number"},"firstDate":{"nullable":true,"type":"string"},"lastDate":{"nullable":true,"type":"string"},"lastPrice":{"nullable":true,"type":"number"}},"required":["count","lastPrice","lastDate","firstDate"],"type":"object"},"PropertySearchRequest":{"properties":{"limit":{"description":"Max results to return (default 12).","maximum":50,"minimum":1,"type":"integer"},"query":{"description":"Free-text search — an address (full or partial), an owner name, or a place. Ranked by relevance; tolerates typos, missing parts, and reordered directionals.","maxLength":200,"minLength":1,"type":"string"}},"required":["query"],"type":"object"},"PropertySummary":{"properties":{"activeLoanCount":{"description":"Mortgages believed to still be outstanding. IMPORTANT: `0` does not always mean the parcel is paid off — on a recently-sold parcel it usually means the buyer's new mortgage has not reached the public record yet, so the honest reading is UNKNOWN. Check `activeLoanCountKnown` before treating a `0` as fact, and do not infer 100% `equity` from it.","nullable":true,"type":"number"},"activeLoanCountKnown":{"description":"`false` when `activeLoanCount` reflects a gap in the record rather than a measurement — the parcel sold, its prior mortgage was excluded, and no replacement has been recorded yet. On those parcels `activeLoanCount: 0`, `mortgageBalance: 0` and an `equity` of 100% are all consequences of the same missing document, not independent findings. To exclude them, filter `preSaleLoanCount: {lte: 0}` alongside `activeLoanCount: {lte: 0}`.","type":"boolean"},"address":{"nullable":true,"type":"string"},"apn":{"description":"Assessor parcel number (cleaned)","nullable":true,"type":"string"},"avm":{"$ref":"#/components/schemas/PropertyAvm"},"baths":{"nullable":true,"type":"number"},"beds":{"nullable":true,"type":"number"},"borrowerStatus":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"coordinates":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"equity":{"$ref":"#/components/schemas/PropertyEquity"},"equityPlausible":{"description":"`false` when `equity` is outside the range our equity metrics treat as possible, so aggregate equity figures exclude this parcel while this row still shows it — both are correct, they are answering different questions. Applies to `pct` as well, since that is `value` divided by the value estimate. Read alongside `activeLoanCountKnown`, which is the opposite failure: that one flags equity computed against a MISSING mortgage (so equity looks too GOOD), where this one flags equity distorted by an oversized one (equity looks too BAD).","type":"boolean"},"fips":{"description":"FIPS county code","nullable":true,"type":"string"},"foreclosure":{"$ref":"#/components/schemas/PropertyForeclosure"},"id":{"description":"Document ID","type":"string"},"loanCount":{"description":"Every mortgage on record for this parcel, current or not. Splits into `activeLoanCount` + `preSaleLoanCount` + the paid-off and released counts on the detail `position` block.","nullable":true,"type":"number"},"loanType":{"nullable":true,"type":"string"},"loans":{"description":"The parcel's cached top-5 loans (may be fewer than `loanCount`; full history is on the loans index).","items":{"$ref":"#/components/schemas/PropertyLoan"},"type":"array"},"lotSquareFeet":{"nullable":true,"type":"number"},"mmPropertyId":{"nullable":true,"type":"string"},"mortgageBalance":{"nullable":true,"type":"number"},"mortgageBalancePlausible":{"description":"`false` when `mortgageBalance` is outside the range our mortgage metrics treat as possible — typically a parcel carrying an institutional blanket loan, where one securitization note is recorded against every property in the pool. Sorting by `mortgageBalance` puts these first, so check this flag before reading the top of that list as the most heavily mortgaged homes.","type":"boolean"},"ownerFirstName":{"nullable":true,"type":"string"},"ownerLastName":{"nullable":true,"type":"string"},"ownerName":{"nullable":true,"type":"string"},"partialBaths":{"nullable":true,"type":"number"},"preSaleLoanCount":{"description":"Mortgages excluded from `activeLoanCount` because the parcel sold after they were recorded — the seller's loan, assumed paid off at closing. Read this NEXT TO `activeLoanCount`, never alone: a non-zero value on a parcel that still has an active loan is the normal post-sale state and means the replacement mortgage was recorded. It is only a warning when `activeLoanCount` is `0`, which is what `activeLoanCountKnown` reports.","nullable":true,"type":"number"},"recordedInterestRate":{"description":"Genuine recorded note rate from the most-recent loan (sparse, ~7%). See `loans[]` for per-loan detail.","nullable":true,"type":"number"},"saleCount":{"nullable":true,"type":"number"},"salePropensity":{"$ref":"#/components/schemas/PropertySalePropensity"},"sales":{"$ref":"#/components/schemas/PropertySales"},"scoredAt":{"nullable":true,"type":"string"},"squareFeet":{"nullable":true,"type":"number"},"state":{"description":"Two-letter state abbreviation, uppercased (stored lowercase in OS)","nullable":true,"type":"string"},"stories":{"nullable":true,"type":"number"},"yearBuilt":{"nullable":true,"type":"number"},"zip":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"PropertySummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/PropertyAnalyticsFlatFilters"}},"type":"object"},"PropertyTractFloodZoneFilterValue":{"anyOf":[{"description":"One of (case-insensitive): A, AE, AH, AO, A99, V, VE","enum":["A","AE","AH","AO","A99","V","VE"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): A, AE, AH, AO, A99, V, VE","enum":["A","AE","AH","AO","A99","V","VE"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"PropertyTractIncomeLevelFilterValue":{"anyOf":[{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},{"description":"Match any of these values","items":{"description":"One of (case-insensitive): low, moderate, middle, upper","enum":["low","moderate","middle","upper"],"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"RealtimeConfigResponse":{"properties":{"app":{"description":"Topic app segment (e.g. `mm`)","type":"string"},"authorizerName":{"description":"IoT custom authorizer name used to build the WSS URL","type":"string"},"endpoint":{"description":"IoT realtime endpoint host","type":"string"},"stage":{"description":"Deployed stage segment (e.g. `prod`)","type":"string"},"userId":{"description":"The authenticated caller's user id (their MQTT topic key)","type":"string"}},"required":["endpoint","authorizerName","app","stage","userId"],"type":"object"},"RealtimeConfigUnavailable":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"RelatedResponse":{"properties":{"data":{"description":"Ids of the linked records (unordered)","items":{"properties":{"id":{"description":"Id of the linked record, on the `to` entity","type":"string"}},"required":["id"],"type":"object"},"type":"array"},"from":{"description":"Type of the starting record","type":"string"},"linkQuality":{"description":"How the link was established. `primary` = the canonical identifier for this pair. `secondary` = a weaker but real alternate identifier, used only because the record carried nothing better. `null` = the record carries no linking identifier at all, so nothing was searched.","enum":["primary","secondary",null],"nullable":true,"type":"string"},"to":{"description":"Type of the linked records","type":"string"},"total":{"description":"Total linked records, before the `limit` page","type":"number"}},"required":["data","total","from","to","linkQuality"],"type":"object"},"ReplayRequest":{"properties":{"asOf":{"description":"The subscribe day (yyyy-MM-dd). Step 0 replays the backfill window a real subscribe would deliver on this date.","pattern":"^\\d{4}-\\d{2}-\\d{2}","type":"string"},"backfillDays":{"description":"Step-0 backfill lookback (days). Omit for the same 90-day window a real subscribe replays.","exclusiveMinimum":true,"minimum":0,"type":"integer"},"detectors":{"description":"Limit to specific triggers; all when omitted.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"steps":{"description":"Later dates (yyyy-MM-dd) to advance to. Each shows only what is NEW since the previous date — the forward delta the cron would have delivered. Sorted + de-duplicated; capped at 12 dates total.","items":{"pattern":"^\\d{4}-\\d{2}-\\d{2}","type":"string"},"type":"array"}},"required":["asOf"],"type":"object"},"ReplayResponse":{"properties":{"data":{"properties":{"capped":{"description":"True if the requested date list was truncated to the cap.","type":"boolean"},"steps":{"items":{"$ref":"#/components/schemas/ReplayStep"},"type":"array"}},"required":["steps","capped"],"type":"object"}},"required":["data"],"type":"object"},"ReplayStep":{"properties":{"counts":{"properties":{"matched":{"type":"integer"},"new":{"type":"integer"},"scanned":{"type":"integer"}},"required":["scanned","matched","new"],"type":"object"},"date":{"description":"The step's yyyy-MM-dd date.","type":"string"},"new":{"description":"Alerts new at this step (deduped against all prior steps).","items":{"$ref":"#/components/schemas/AlertDecision"},"type":"array"}},"required":["date","new","counts"],"type":"object"},"RosterProductionTier":{"properties":{"count":{"type":"number"},"label":{"type":"string"},"maxUnits":{"nullable":true,"type":"number"},"minUnits":{"type":"number"},"tier":{"enum":["none","low","mid","top"],"type":"string"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["tier","label","minUnits","maxUnits","count","volume","units"],"type":"object"},"RunUserDetectorRequest":{"properties":{"backfillDays":{"description":"Ingest-axis lookback (days) the run replays past the global watermark. Omit to use the same 90-day window a real subscribe backfills, so the preview matches what the user receives on add.","exclusiveMinimum":true,"minimum":0,"type":"integer"},"detectors":{"description":"Limit to specific triggers; all six when omitted.","items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"dryRun":{"description":"Preview only (default true): compute what would fire without writing the feed, publishing events, or sending email. Set false to actually fire — persists a run record + delivers like the cron.","type":"boolean"}},"type":"object"},"RunUserDetectorResponse":{"properties":{"data":{"properties":{"correlationId":{"type":"string"},"dryRun":{"type":"boolean"},"perDetector":{"items":{"properties":{"decisions":{"description":"The alerts that fired for this detector (dry-run only).","items":{"$ref":"#/components/schemas/AlertDecision"},"type":"array"},"deduped":{"type":"integer"},"matched":{"type":"integer"},"published":{"type":"integer"},"scanned":{"type":"integer"},"type":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"written":{"type":"integer"}},"required":["type","scanned","matched","deduped","written","published"],"type":"object"},"type":"array"}},"required":["correlationId","dryRun","perDetector"],"type":"object"}},"required":["data"],"type":"object"},"SaleChartRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/SaleFlatFilters"},"measure":{"$ref":"#/components/schemas/ChartMeasure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"slice":{"$ref":"#/components/schemas/SaleChartSlice"}},"required":["slice"],"type":"object"},"SaleChartSlice":{"enum":["city","county","state","zip"],"type":"string"},"SaleDetail":{"allOf":[{"$ref":"#/components/schemas/SaleSummary"},{"properties":{"buyerNames":{"nullable":true},"documentType":{"nullable":true,"type":"string"},"listAgent":{"nullable":true},"mlsBoards":{"nullable":true},"mlsListDate":{"nullable":true},"mlsPendingDate":{"nullable":true},"mlsSoldDate":{"nullable":true},"mmPropertyId":{"nullable":true,"type":"string"},"mmSaleId":{"nullable":true,"type":"string"},"sellerNames":{"nullable":true},"soldAgent":{"nullable":true}},"type":"object"}]},"SaleDetailResponse":{"properties":{"data":{"$ref":"#/components/schemas/SaleDetail"}},"required":["data"],"type":"object"},"SaleField":{"enum":["city","state","zipCode","county","salePrice","saleDate","listPrice","soldPrice","listingAgent","soldAgent","mlsStatus","beds","baths","sqft","yearBuilt","propertyType"],"type":"string"},"SaleFlatFilters":{"additionalProperties":false,"properties":{"baths":{"$ref":"#/components/schemas/NumericFilterValue"},"beds":{"$ref":"#/components/schemas/NumericFilterValue"},"city":{"$ref":"#/components/schemas/TextFilterValue"},"county":{"$ref":"#/components/schemas/TextFilterValue"},"fips":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"5-digit county FIPS code — the exact-code escape hatch for `county` (which also accepts a county name)."}]},"geoPoint":{"$ref":"#/components/schemas/GeoFilterValue"},"listPrice":{"$ref":"#/components/schemas/NumericFilterValue"},"listingAgent":{"$ref":"#/components/schemas/TextFilterValue"},"mlsStatus":{"$ref":"#/components/schemas/SaleMlsStatusFilterValue"},"mode":{"enum":["and","or"],"type":"string"},"propertyType":{"$ref":"#/components/schemas/TextFilterValue"},"saleDate":{"$ref":"#/components/schemas/DateFilterValue"},"salePrice":{"$ref":"#/components/schemas/NumericFilterValue"},"soldAgent":{"$ref":"#/components/schemas/TextFilterValue"},"soldPrice":{"$ref":"#/components/schemas/NumericFilterValue"},"sqft":{"$ref":"#/components/schemas/NumericFilterValue"},"state":{"$ref":"#/components/schemas/TextFilterValue"},"yearBuilt":{"$ref":"#/components/schemas/NumericFilterValue"},"zip":{"$ref":"#/components/schemas/TextFilterValue"},"zipCode":{"allOf":[{"$ref":"#/components/schemas/TextFilterValue"},{"description":"ZIP code. Canonical key on sales (matches loans `zipCode` and the response DTO); `zip` is an alias kept for cross-entity parity."}]}},"type":"object"},"SaleListRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/SaleFlatFilters"},"pagination":{"$ref":"#/components/schemas/Pagination"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"sort":{"items":{"properties":{"field":{"$ref":"#/components/schemas/SaleField"},"order":{"$ref":"#/components/schemas/SortOrder"}},"required":["field"],"type":"object"},"type":"array"}},"type":"object"},"SaleListResponse":{"properties":{"cursor":{"type":"string"},"data":{"items":{"$ref":"#/components/schemas/SaleSummary"},"type":"array"},"locationNormalizations":{"description":"How each location filter value resolved. Present when a `city`/`county`/`state`/`zip` filter was supplied.","items":{"$ref":"#/components/schemas/LocationNormalization"},"type":"array"},"total":{"type":"number"}},"required":["data","total"],"type":"object"},"SaleMlsStatusFilterValue":{"anyOf":[{"$ref":"#/components/schemas/MlsStatus"},{"description":"Match any MLS status","items":{"$ref":"#/components/schemas/MlsStatus"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"SaleSummary":{"properties":{"apn":{"nullable":true,"type":"string"},"baths":{"description":"Number of full bathrooms","nullable":true,"type":"number"},"beds":{"description":"Number of bedrooms","nullable":true,"type":"number"},"buyerName":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"coordinates":{"nullable":true,"properties":{"lat":{"type":"number"},"lon":{"type":"number"}},"required":["lat","lon"],"type":"object"},"daysOnMarket":{"nullable":true,"type":"number"},"fips":{"nullable":true,"type":"string"},"id":{"description":"Document ID","type":"string"},"listPrice":{"description":"MLS list price in dollars","nullable":true,"type":"number"},"listingAgentId":{"description":"ModelMatch agent ID for the listing agent","nullable":true,"type":"string"},"listingAgentName":{"nullable":true,"type":"string"},"mlsStatus":{"description":"MLS listing status code","enum":["SLD","ACT","PND","Cancelled","WDN","EXP","CNT","OFF","UNK","RNTD","RNT","LSE","RNT-SLD","RNT-ACT","RNT-PND","RNT-WDN","RNT-EXP","RNT-LSE","RNT-RNTD",null],"nullable":true,"type":"string"},"originalListPrice":{"description":"Original MLS list price in dollars","nullable":true,"type":"number"},"propertyType":{"description":"Listing property type (e.g. Residential, Condo)","nullable":true,"type":"string"},"recordingDate":{"nullable":true,"type":"string"},"salePrice":{"description":"Transaction price in dollars","nullable":true,"type":"number"},"sellerName":{"nullable":true,"type":"string"},"soldAgentId":{"description":"ModelMatch agent ID for the sold/buying agent","nullable":true,"type":"string"},"soldAgentName":{"nullable":true,"type":"string"},"soldPrice":{"description":"MLS sold price in dollars","nullable":true,"type":"number"},"sqft":{"description":"Living area in square feet","nullable":true,"type":"number"},"state":{"nullable":true,"type":"string"},"streetAddress":{"nullable":true,"type":"string"},"transactionDate":{"nullable":true,"type":"string"},"yearBuilt":{"description":"Year the property was built","nullable":true,"type":"number"},"zipCode":{"nullable":true,"type":"string"}},"required":["id"],"type":"object"},"SaleSummaryRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/SaleFlatFilters"},"period":{"$ref":"#/components/schemas/DatedPeriod"}},"type":"object"},"SaleTimeSeriesRequest":{"additionalProperties":false,"properties":{"advancedFilters":{"$ref":"#/components/schemas/FilterNode"},"filters":{"$ref":"#/components/schemas/FilterNode"},"flatFilters":{"$ref":"#/components/schemas/SaleFlatFilters"},"interval":{"$ref":"#/components/schemas/Interval"},"measure":{"$ref":"#/components/schemas/Measure"},"period":{"$ref":"#/components/schemas/DatedPeriod"},"segment":{"$ref":"#/components/schemas/SegmentDimension"}},"type":"object"},"SalesTimeSeriesBucket":{"properties":{"buyer":{"$ref":"#/components/schemas/SalesTimeSeriesSideMetrics"},"date":{"type":"string"},"dual":{"$ref":"#/components/schemas/SalesTimeSeriesSideMetrics"},"seller":{"$ref":"#/components/schemas/SalesTimeSeriesSideMetrics"},"total":{"$ref":"#/components/schemas/SalesTimeSeriesSideMetrics"}},"required":["date","total","buyer","seller","dual"],"type":"object"},"SalesTimeSeriesResponse":{"properties":{"current":{"items":{"$ref":"#/components/schemas/SalesTimeSeriesBucket"},"type":"array"},"measure":{"description":"Echo of the measure `measureValue` reports, so a caller never has to infer which metric it is plotting.","type":"string"},"previous":{"items":{"$ref":"#/components/schemas/SalesTimeSeriesBucket"},"nullable":true,"type":"array"}},"required":["measure","current","previous"],"type":"object"},"SalesTimeSeriesSideMetrics":{"properties":{"measureValue":{"description":"This side's value for the requested `measure` (`volume` when none was supplied). Null when this side has no in-bounds document for the measure's field — sentinel-filtered rows do not contribute, so an empty side reports null rather than 0.","nullable":true,"type":"number"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units","measureValue"],"type":"object"},"SavedFilter":{"properties":{"createdAt":{"format":"date-time","type":"string"},"fidelity":{"description":"How much of the UI state `query` captures: `exact`; `partial` (see `unmapped`); `ui_only` — no runnable query. Defaults from whether `query` is present.","enum":["exact","partial","ui_only"],"type":"string"},"icon":{"$ref":"#/components/schemas/SavedFilterIcon"},"id":{"type":"string"},"kind":{"description":"`filter` (default) — a saved search; `view` — a saved CRM table layout (columns / order) kept in `uiState`. Views never carry a `query` and have their own 25-per-target quota. Fixed at create.","enum":["filter","view"],"type":"string"},"name":{"type":"string"},"operationId":{"description":"The operation to run `query` against (e.g. `listOriginators`); null for UI-only targets.","nullable":true,"type":"string"},"query":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"queryVersion":{"type":"integer"},"stale":{"description":"True when the stored `query` no longer validates against the operation (its contract changed). Re-save or adjust before running.","type":"boolean"},"staleIssues":{"items":{"properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["path","message"],"type":"object"},"type":"array"},"target":{"description":"Which list the filter runs against. Market targets run against that entity's list operation (see `operationId`, e.g. listOriginators); `crm_people` / `crm_companies` are UI-only (filtered client-side).","enum":["originators","agents","companies","branches","offices","loans","properties","sales","crm_people","crm_companies"],"type":"string"},"uiState":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"uiStateVersion":{"type":"integer"},"unmapped":{"items":{"type":"string"},"type":"array"},"updatedAt":{"format":"date-time","type":"string"},"visibility":{"description":"Always `private` in v1.","enum":["private","organization","shared"],"type":"string"}},"required":["id","name","target","kind","icon","query","queryVersion","uiState","uiStateVersion","fidelity","unmapped","visibility","operationId","stale","staleIssues","createdAt","updatedAt"],"type":"object"},"SavedFilterError":{"properties":{"code":{"description":"`QUOTA_EXCEEDED` (409, 25 per target + kind).","type":"string"},"error":{"type":"string"},"issues":{"items":{"properties":{"message":{"type":"string"},"path":{"type":"string"}},"required":["path","message"],"type":"object"},"type":"array"}},"required":["error"],"type":"object"},"SavedFilterIcon":{"description":"Optional marker: a color dot, a tinted icon, or an emoji.","oneOf":[{"properties":{"color":{"pattern":"^#[0-9a-fA-F]{6}$","type":"string"},"type":{"enum":["color"],"type":"string"}},"required":["type","color"],"type":"object"},{"properties":{"color":{"pattern":"^#[0-9a-fA-F]{6}$","type":"string"},"icon":{"pattern":"^[A-Za-z][A-Za-z0-9]{0,63}$","type":"string"},"type":{"enum":["icon"],"type":"string"}},"required":["type","icon","color"],"type":"object"},{"properties":{"emoji":{"maxLength":16,"minLength":1,"type":"string"},"type":{"enum":["emoji"],"type":"string"}},"required":["type","emoji"],"type":"object"},{"nullable":true}]},"SavedFilterList":{"properties":{"data":{"items":{"$ref":"#/components/schemas/SavedFilter"},"type":"array"}},"required":["data"],"type":"object"},"SearchTokenResponse":{"properties":{"expiresAt":{"description":"ISO-8601 expiry","type":"string"},"host":{"description":"Search host to query directly","type":"string"},"indexes":{"description":"Index names the token may search","items":{"type":"string"},"type":"array"},"token":{"description":"Scoped search token","type":"string"}},"required":["token","host","indexes","expiresAt"],"type":"object"},"SearchTokenUnavailable":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"},"SegmentDimension":{"enum":["side","transactionType"],"type":"string"},"SideMetrics":{"properties":{"avgListPrice":{"type":"number"},"avgSalePrice":{"type":"number"},"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units","avgSalePrice","avgListPrice"],"type":"object"},"SidedSummaryResponse":{"properties":{"current":{"$ref":"#/components/schemas/SummaryPeriod"},"previous":{"allOf":[{"$ref":"#/components/schemas/SummaryPeriod"},{"nullable":true}]}},"required":["current","previous"],"type":"object"},"SidedTimeSeriesBucket":{"properties":{"buyer":{"properties":{"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units"],"type":"object"},"date":{"type":"string"},"dual":{"properties":{"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units"],"type":"object"},"seller":{"properties":{"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units"],"type":"object"},"total":{"properties":{"units":{"type":"number"},"volume":{"type":"number"}},"required":["volume","units"],"type":"object"}},"required":["date","total","buyer","seller","dual"],"type":"object"},"SidedTimeSeriesResponse":{"properties":{"current":{"items":{"$ref":"#/components/schemas/SidedTimeSeriesBucket"},"type":"array"},"previous":{"items":{"$ref":"#/components/schemas/SidedTimeSeriesBucket"},"nullable":true,"type":"array"}},"required":["current","previous"],"type":"object"},"SimpleExcludedCounts":{"description":"Per-measure count of documents this query's sentinel guard excluded — documents that carry the measure's field but whose value is an out-of-range fill. Compare against `units` to see what share of the matched population each figure was computed over. Empty when the entity's measures are unguarded.","properties":{"avgListPrice":{"type":"number"},"avgPrice":{"type":"number"},"volume":{"type":"number"}},"type":"object"},"SimpleMetrics":{"properties":{"avgListPrice":{"description":"Average list price. Omitted entirely for entities with no list-price column — absence means 'not available here', not zero. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"avgPrice":{"description":"Average sale price. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"},"excluded":{"$ref":"#/components/schemas/SimpleExcludedCounts"},"units":{"description":"Number of transactions","type":"number"},"volume":{"description":"Total volume in dollars. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"}},"required":["volume","units","avgPrice"],"type":"object"},"SimpleSummaryResponse":{"properties":{"completeness":{"$ref":"#/components/schemas/AnalyticsCompleteness"},"current":{"$ref":"#/components/schemas/SimpleMetrics"},"previous":{"allOf":[{"$ref":"#/components/schemas/SimpleMetrics"},{"nullable":true}]}},"required":["current","previous"],"type":"object"},"SimpleTimeSeriesBucket":{"properties":{"complete":{"description":"Whether this bucket's whole period is backed by data. `false` means the bucket extends past `completeness.through`, so it is built from a partial period and MUST NOT be compared against its neighbours or the same bucket a year earlier — a trailing bucket holding a few days of a month reads as a collapse. Absent on every bucket whenever `completeness` itself is absent; the two are emitted together or not at all.","type":"boolean"},"date":{"type":"string"},"excluded":{"description":"How many of this bucket's documents the measure's sentinel guard excluded — documents that carry the field but whose value is an out-of-range fill. Additive and optional: absent when the measure is unguarded (a document count, or a field with no fill values). Present per BUCKET because exclusion is not uniform — one period or slice can be almost entirely fill values while its neighbors are clean, and a single response-level total would hide exactly that.","type":"number"},"measureValue":{"description":"This bucket's value for the requested `measure` (`volume` when none was supplied). Null when the bucket has no in-bounds document for the measure's field — sentinel-filtered rows do not contribute, so an empty bucket reports null rather than 0.","nullable":true,"type":"number"},"segments":{"items":{"$ref":"#/components/schemas/SimpleTimeSeriesSegment"},"type":"array"},"units":{"description":"Number of transactions","type":"number"},"volume":{"description":"This bucket's volume in dollars. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"}},"required":["date","volume","units","measureValue"],"type":"object"},"SimpleTimeSeriesResponse":{"properties":{"completeness":{"$ref":"#/components/schemas/AnalyticsCompleteness"},"current":{"items":{"$ref":"#/components/schemas/SimpleTimeSeriesBucket"},"type":"array"},"measure":{"description":"Echo of the measure `measureValue` reports, so a caller never has to infer which metric it is plotting.","type":"string"},"previous":{"items":{"$ref":"#/components/schemas/SimpleTimeSeriesBucket"},"nullable":true,"type":"array"}},"required":["measure","current","previous"],"type":"object"},"SimpleTimeSeriesSegment":{"properties":{"id":{"description":"Machine value behind `label` when the bucket key is not itself the label. `lender`: `label` is the dictionary display name and `id` the normalized lender key — pass `id`, not `label`, back as a `lender` filter value. `conforming`: `label` is `conforming` / `nonConforming` and `id` the raw `true` / `false` flag. `titleCompany` (time-series segment): `label` is the most-used spelling and `id` the normalized name every spelling was merged under — match segments across buckets on `id`. Absent on slices whose `label` is already the machine value.","type":"string"},"label":{"type":"string"},"measureValue":{"description":"This segment's value for the requested `measure`. Null when the segment has no in-bounds document for the measure's field.","nullable":true,"type":"number"},"units":{"description":"Number of transactions","type":"number"},"volume":{"description":"This segment's volume in dollars. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly.","type":"number"}},"required":["label","volume","units","measureValue"],"type":"object"},"SkipTraceAddress":{"additionalProperties":{"nullable":true},"nullable":true,"properties":{"addressValidity":{"nullable":true,"type":"string"},"city":{"nullable":true,"type":"string"},"county":{"nullable":true,"type":"string"},"formattedStreet":{"nullable":true,"type":"string"},"hash":{"nullable":true,"type":"string"},"houseNumber":{"nullable":true,"type":"string"},"state":{"nullable":true,"type":"string"},"street":{"nullable":true,"type":"string"},"streetNoUnit":{"nullable":true,"type":"string"},"zip":{"nullable":true,"type":"string"},"zipPlus4":{"nullable":true,"type":"string"}},"type":"object"},"SkipTraceEmail":{"properties":{"email":{"nullable":true,"type":"string"},"tested":{"anyOf":[{"type":"boolean"},{"type":"string"},{"nullable":true}]}},"type":"object"},"SkipTraceName":{"nullable":true,"properties":{"first":{"nullable":true,"type":"string"},"full":{"nullable":true,"type":"string"},"last":{"nullable":true,"type":"string"},"middle":{"nullable":true,"type":"string"}},"type":"object"},"SkipTracePerson":{"additionalProperties":{"nullable":true},"properties":{"death":{"additionalProperties":{"nullable":true},"nullable":true,"properties":{"deceased":{"nullable":true,"type":"boolean"}},"type":"object"},"dnc":{"additionalProperties":{"nullable":true},"nullable":true,"properties":{"tcpa":{"nullable":true,"type":"boolean"}},"type":"object"},"emails":{"items":{"$ref":"#/components/schemas/SkipTraceEmail"},"nullable":true,"type":"array"},"litigator":{"nullable":true,"type":"boolean"},"mailingAddress":{"$ref":"#/components/schemas/SkipTraceAddress"},"meta":{"additionalProperties":{"nullable":true},"nullable":true,"properties":{"error":{"anyOf":[{"type":"string"},{"type":"boolean"},{"nullable":true}]},"matched":{"nullable":true,"type":"boolean"}},"type":"object"},"name":{"$ref":"#/components/schemas/SkipTraceName"},"phoneNumbers":{"items":{"$ref":"#/components/schemas/SkipTracePhone"},"nullable":true,"type":"array"},"propertyAddress":{"$ref":"#/components/schemas/SkipTraceAddress"}},"type":"object"},"SkipTracePhone":{"properties":{"carrier":{"nullable":true,"type":"string"},"dnc":{"nullable":true,"type":"boolean"},"lastReportedDate":{"nullable":true,"type":"string"},"number":{"nullable":true,"type":"string"},"reachable":{"nullable":true,"type":"boolean"},"score":{"nullable":true,"type":"number"},"tested":{"anyOf":[{"type":"boolean"},{"type":"string"},{"nullable":true}]},"type":{"nullable":true,"type":"string"}},"type":"object"},"SortOrder":{"enum":["asc","desc"],"type":"string"},"StartAlertDetectorRequest":{"properties":{"detectors":{"items":{"enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"},"type":"array"},"dryRun":{"type":"boolean"},"limitPerDetector":{"exclusiveMinimum":true,"minimum":0,"type":"integer"},"userIds":{"items":{"type":"string"},"type":"array"}},"type":"object"},"StartAlertDetectorResponse":{"properties":{"data":{"properties":{"arn":{"type":"string"},"started":{"type":"boolean"}},"required":["arn","started"],"type":"object"}},"required":["data"],"type":"object"},"StopAlertDetectorRequest":{"properties":{"taskArn":{"minLength":1,"type":"string"}},"required":["taskArn"],"type":"object"},"StopAlertDetectorResponse":{"properties":{"data":{"properties":{"arn":{"type":"string"},"stopped":{"type":"boolean"}},"required":["arn","stopped"],"type":"object"}},"required":["data"],"type":"object"},"SummaryPeriod":{"properties":{"buyer":{"$ref":"#/components/schemas/SideMetrics"},"buyerPct":{"type":"number"},"dual":{"$ref":"#/components/schemas/SideMetrics"},"dualPct":{"type":"number"},"seller":{"$ref":"#/components/schemas/SideMetrics"},"sellerPct":{"type":"number"},"total":{"$ref":"#/components/schemas/SideMetrics"}},"required":["total","buyer","seller","dual","buyerPct","sellerPct","dualPct"],"type":"object"},"TalentFlowCompany":{"properties":{"companyName":{"nullable":true,"type":"string"},"companyNmlsId":{"nullable":true,"type":"string"},"count":{"description":"Loan officers attributed.","type":"number"},"units":{"description":"Loans behind `volume`.","type":"number"},"volume":{"description":"Those loan officers' production AT THIS company (employer at time of loan = this company) recorded inside the window.","type":"number"}},"required":["companyNmlsId","companyName","count","volume","units"],"type":"object"},"TextFilterValue":{"anyOf":[{"type":"string"},{"description":"Match any value","items":{"type":"string"},"type":"array"},{"description":"Fuzzy text match","properties":{"match":{"type":"string"}},"required":["match"],"type":"object"},{"nullable":true}]},"UnreadCountResponse":{"properties":{"data":{"properties":{"count":{"type":"integer"}},"required":["count"],"type":"object"}},"required":["data"],"type":"object"},"UpdateAlertConditionsRequest":{"properties":{"conditions":{"$ref":"#/components/schemas/AlertConditions"},"email":{"description":"Contact email stored for the alert digest.","type":"string"},"emailEnabled":{"deprecated":true,"description":"Deprecated and ignored: accepted for compatibility, but not stored and no longer controls delivery (the response always reports every flag off). Email and in-app channel preferences for alerts live in Notifications settings.","properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"type":"object"},"enabled":{"deprecated":true,"description":"Deprecated: use the alert recipes (POST/DELETE /recipes/{id}) or /subscriptions instead. Still honoured: `true` turns the trigger on for every watched subject that supports it (and for your NMLS id when one is on file); `false` turns it off everywhere. Omitted triggers are unchanged. A trigger with nothing watched that supports it stays off.","properties":{"agent_sale_closed":{"type":"boolean"},"area_new_listing":{"type":"boolean"},"borrower_listed":{"type":"boolean"},"epo_risk":{"type":"boolean"},"rate_term_refi_area":{"type":"boolean"},"watched_agent_pending":{"type":"boolean"},"watched_loan":{"type":"boolean"},"watched_property":{"type":"boolean"},"watched_sale":{"type":"boolean"}},"type":"object"},"name":{"description":"Display name.","type":"string"},"nmlsId":{"description":"The loan officer's NMLS id. Required to enable the borrower-centric triggers (borrower_listed, epo_risk); the agent + area triggers work without it.","type":"string"}},"type":"object"},"UpdateSavedFilterRequest":{"additionalProperties":false,"properties":{"fidelity":{"description":"How much of the UI state `query` captures: `exact`; `partial` (see `unmapped`); `ui_only` — no runnable query. Defaults from whether `query` is present.","enum":["exact","partial","ui_only"],"type":"string"},"icon":{"$ref":"#/components/schemas/SavedFilterIcon"},"name":{"maxLength":100,"minLength":1,"type":"string"},"query":{"additionalProperties":{"nullable":true},"description":"The target list operation's request body WITHOUT `pagination` (e.g. `{ flatFilters, filters, sort, period }` for listOriginators). Validated against that operation's schema; unknown filter fields are rejected. Null/omitted for a UI-only filter.","nullable":true,"type":"object"},"uiState":{"additionalProperties":{"nullable":true},"description":"Opaque client UI state used to restore a filter panel (≤16KB). Not interpreted by the API.","nullable":true,"type":"object"},"uiStateVersion":{"minimum":1,"type":"integer"},"unmapped":{"description":"UI filter keys the client could not express in `query` (set with `fidelity: partial`).","items":{"maxLength":200,"minLength":1,"type":"string"},"maxItems":100,"type":"array"}},"type":"object"},"UpdateSavedFilterResult":{"properties":{"data":{"$ref":"#/components/schemas/SavedFilter"}},"required":["data"],"type":"object"},"WatchedAgent":{"properties":{"addedAt":{"type":"string"},"agentId":{"description":"Agent id.","type":"string"},"name":{"type":"string"},"source":{"description":"How the agent entered the watchlist — added by hand or auto-derived from recent buyer-side deals.","enum":["manual","auto_buyer_24mo"],"type":"string"}},"required":["agentId","source","addedAt"],"type":"object"},"WatchedAgentsResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WatchedAgent"},"type":"array"}},"required":["data"],"type":"object"},"WatchedArea":{"properties":{"addedAt":{"type":"string"},"id":{"description":"Opaque id used to remove the area.","type":"string"},"lat":{"description":"Radius center latitude.","type":"number"},"lon":{"description":"Radius center longitude.","type":"number"},"maxLat":{"description":"Box north edge.","type":"number"},"maxLon":{"description":"Box east edge.","type":"number"},"minLat":{"description":"Box south edge.","type":"number"},"minLon":{"description":"Box west edge.","type":"number"},"radiusMeters":{"description":"Radius in meters (canonical unit).","type":"number"},"state":{"description":"2-letter state ('' for zip + geo areas).","type":"string"},"type":{"enum":["city","county","zip","bbox","radius"],"type":"string"},"value":{"type":"string"}},"required":["id","type","value","state","addedAt"],"type":"object"},"WatchedAreasResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WatchedArea"},"type":"array"}},"required":["data"],"type":"object"},"WatchedDocument":{"properties":{"addedAt":{"type":"string"},"documentId":{"type":"string"},"documentType":{"enum":["sale","property","loan"],"type":"string"},"rules":{"items":{"$ref":"#/components/schemas/WatchedDocumentRule"},"type":"array"}},"required":["documentType","documentId","rules","addedAt"],"type":"object"},"WatchedDocumentPredicate":{"properties":{"field":{"description":"Catalog field alias.","type":"string"},"id":{"description":"Stable predicate id.","type":"string"},"op":{"enum":["gt","gte","lt","lte","eq","between","pct_change_gte","abs_change_gte","changed","changed_to","not_eq","in"],"type":"string"},"stringValue":{"type":"string"},"stringValues":{"items":{"type":"string"},"type":"array"},"value":{"type":"number"},"value2":{"type":"number"}},"required":["id","field","op"],"type":"object"},"WatchedDocumentRule":{"properties":{"id":{"description":"Stable rule id.","type":"string"},"match":{"enum":["all","any"],"type":"string"},"predicates":{"items":{"$ref":"#/components/schemas/WatchedDocumentPredicate"},"type":"array"}},"required":["id","match","predicates"],"type":"object"},"WatchedDocumentsResponse":{"properties":{"data":{"items":{"$ref":"#/components/schemas/WatchedDocument"},"type":"array"}},"required":["data"],"type":"object"}},"securitySchemes":{"apiKeyAuth":{"in":"header","name":"x-api-key","type":"apiKey"},"bearerAuth":{"bearerFormat":"JWT","scheme":"bearer","type":"http"}}},"info":{"description":"ModelMatch API — mortgage and real-estate market data.\n\n## Bulk delivery limits\n\nThe `POST /{entity}/bulk-delivery` endpoints export a full result set to\nS3 as NDJSON, JSON, CSV, or Parquet.\n\n- **Up to 5,000 rows per delivery: no entitlement required.** Available to\n  every authenticated caller.\n- **Above 5,000 rows: requires the entity's `bulk-delivery.{entity}`\n  entitlement** (e.g. `bulk-delivery.loans`). The grant's scope sets your\n  row ceiling and may also restrict which rows and fields you receive.\n\nA delivery that would exceed the limit available to you is rejected with\n`403 entitlement_missing`, reporting the matched row count and the ceiling\nthat applied. To stay under the limit, pass `limit` — the job then delivers\n(and bills for) only the first `limit` rows of a broader query.\n\n**Need a higher limit?** Email support@modelmatch.com to request the\nentitlement. Limits are raised per organization and per entity.\n\nBulk delivery is billed at 1 credit per delivered row whether or not\nan entitlement is held.\n\nInstead of a download, a delivery can be sent to a push target configured\non your workspace: pass `destination: { type: \"push-target\", targetId }`.\nThe same limits and billing apply.","title":"ModelMatch API","version":"3.94.0"},"openapi":"3.1.0","paths":{"/v1/admin/alerts/email-templates/preview":{"post":{"description":"Validates an email template and returns the notification props a run would send with it — any recipe (drafts too), sampled from a user's recent alerts when `userId` is given, else static samples.","operationId":"adminPreviewAlertEmailTemplate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertEmailTemplatePreviewRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEmailTemplatePreviewResponse"}}},"description":"Valid — the props the email renders from"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Preview an alert email template (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes":{"get":{"description":"Every alert recipe in any status (draft, published, archived), in sort order, each with its subscriber count. Seeds the four built-in recipes on first read.","operationId":"adminListAlertRecipes","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipesResponse"}}},"description":"Recipes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"List alert recipes (admin)","tags":["Admin"]},"post":{"description":"Creates a draft recipe. Validated: kinds allowed per subject, rule templates against the field catalog, inputs covering the grants.","operationId":"adminCreateAlertRecipe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCreateAlertRecipeRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeResponse"}}},"description":"Recipe"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Create an alert recipe (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}":{"delete":{"description":"Deletes a recipe no subscription carries (409 `recipe_in_use` otherwise — archive it instead).","operationId":"adminDeleteAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Delete an alert recipe (admin)","tags":["Admin"]},"get":{"operationId":"adminGetAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeResponse"}}},"description":"Recipe"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Get an alert recipe (admin)","tags":["Admin"]},"put":{"description":"Replaces the definition (the id and status stay; `version` bumps). Existing subscriptions keep their grants until you resync.","operationId":"adminReplaceAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminReplaceAlertRecipeRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeResponse"}}},"description":"Recipe"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Replace an alert recipe (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}/archive":{"post":{"operationId":"adminArchiveAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeResponse"}}},"description":"Recipe"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Archive an alert recipe (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}/preview":{"post":{"description":"Dry-runs the recipe over the last 30 days for `userId`, with the given inputs applied on top of the user's saved setup. Works on drafts. Writes nothing.","operationId":"adminPreviewAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPreviewAlertRecipeRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipePreviewResponse"}}},"description":"What the recipe would have fired"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Preview an alert recipe for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}/publish":{"post":{"operationId":"adminPublishAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeResponse"}}},"description":"Recipe"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Publish an alert recipe (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}/resync":{"post":{"description":"Narrows the recipe's grant on every subscription that carries it to the kinds the recipe still grants (it never adds a kind a user turned off; a subject type the recipe no longer covers loses the grant). With `rules: true` record subscriptions also get the current rule templates. Scans every subscription (10 writes in flight): seconds per ten thousand rows. Idempotent and resumable — after a timeout, call it again to finish the rest. Returns counts.","operationId":"adminResyncAlertRecipe","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminResyncAlertRecipeRequest"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminResyncAlertRecipeResponse"}}},"description":"Counts"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Resync an alert recipe's subscriptions (admin)","tags":["Admin"]}},"/v1/admin/alerts/recipes/{id}/stats":{"get":{"description":"How many users subscribe to the recipe, how many alerts its grants fired in the last 30 days, and when it last fired in that window. Scans every subscription, then reads each subscriber's last 30 days of feed (10 in flight): expect seconds on a large table.","operationId":"adminGetAlertRecipeStats","parameters":[{"description":"Recipe id.","in":"path","name":"id","required":true,"schema":{"description":"Recipe id.","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRecipeStatsResponse"}}},"description":"Stats"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Alert recipe stats (admin)","tags":["Admin"]}},"/v1/admin/alerts/runs":{"get":{"description":"Run history, newest first. One record per non-dry-run.","operationId":"adminListAlertRuns","parameters":[{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRunsResponse"}}},"description":"Paginated run history"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List detector runs (admin)","tags":["Admin"]}},"/v1/admin/alerts/runs/{id}":{"get":{"operationId":"adminGetAlertRun","parameters":[{"description":"Opaque run id (from the run list).","in":"path","name":"id","required":true,"schema":{"description":"Opaque run id (from the run list).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRunResponse"}}},"description":"The run record"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Run not found"}},"summary":"Get one detector run (admin)","tags":["Admin"]}},"/v1/admin/alerts/task/start":{"post":{"operationId":"adminStartAlertDetector","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAlertDetectorRequest"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StartAlertDetectorResponse"}}},"description":"The launched task arn"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Start an on-demand detector run (admin)","tags":["Admin"]}},"/v1/admin/alerts/task/status":{"get":{"operationId":"adminGetAlertDetectorStatus","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertDetectorStatusResponse"}}},"description":"Running flag + any running tasks"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Is the detector running right now? (admin)","tags":["Admin"]}},"/v1/admin/alerts/task/stop":{"post":{"operationId":"adminStopAlertDetector","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopAlertDetectorRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/StopAlertDetectorResponse"}}},"description":"The stopped task arn"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Stop a running detector task (admin)","tags":["Admin"]}},"/v1/admin/alerts/user-recipes":{"get":{"description":"User recipes across all users (owner, then id), each with whether its owner subscribes and how many alerts it fired in the last 30 days. Paged by `cursor`.","operationId":"adminListAllUserRecipes","parameters":[{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertUserRecipesResponse"}}},"description":"User recipes"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List every user's own alert recipes (admin)","tags":["Admin"]}},"/v1/admin/alerts/user-recipes/{ownerUserId}/{userRecipeId}/promote":{"post":{"description":"Copies the user recipe into a DRAFT global recipe with the given id (validated like any recipe: 400 `invalid_recipe_id` for a bad or `u-` id, 409 `recipe_exists` for a taken one) and records it on the user recipe's `promotedTo`. Edit and publish the draft as usual; the user's own recipe and subscription are untouched.","operationId":"adminPromoteUserRecipe","parameters":[{"description":"The recipe's owner.","in":"path","name":"ownerUserId","required":true,"schema":{"description":"The recipe's owner.","type":"string"}},{"description":"The user recipe id (`u-…`).","in":"path","name":"userRecipeId","required":true,"schema":{"description":"The user recipe id (`u-…`).","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPromoteUserRecipeRequest"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPromoteUserRecipeResponse"}}},"description":"Promoted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Conflict: `recipe_exists`, `recipe_in_use` or `version_conflict`"}},"summary":"Promote a user's alert recipe to the catalog (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/conditions":{"get":{"operationId":"adminGetUserAlertConditions","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertConditionsResponse"}}},"description":"The user's settings + identity (defaults if none saved)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Get a user's alert settings (admin)","tags":["Admin"]},"put":{"operationId":"adminUpdateUserAlertConditions","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminUpdateAlertConditionsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertConditionsResponse"}}},"description":"The saved settings"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"An NMLS id is required to enable the borrower-centric triggers"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Set a user's alert settings on their behalf (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/digests":{"get":{"operationId":"adminListUserAlertDigests","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertDigestResponse"}}},"description":"Paginated digest feed (newest first)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's alert digests (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/history/clear":{"post":{"description":"Deletes the user's fire-once dedupe markers + their feed (LOG) rows (and digest rows) so the detector can re-fire the same alerts — a debug aid for testing the pipeline end-to-end. Optionally scope to specific alert types; a full clear also resets the unread counter. Leaves the user's alert settings and watchlists untouched.","operationId":"adminClearUserAlertHistory","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearAlertHistoryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ClearAlertHistoryResponse"}}},"description":"Counts of deleted dedupe / log / digest rows"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Clear a user's fired-alert history (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/log":{"get":{"operationId":"adminListUserAlertLog","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertLogResponse"}}},"description":"Paginated feed (newest first)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's alert feed (admin)","tags":["Admin"]},"post":{"operationId":"adminPushUserAlert","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPushAlertRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminPushAlertResponse"}}},"description":"Whether it was written (false = deduped)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Push a one-off alert into a user's feed (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/log/mark-all-read":{"post":{"operationId":"adminMarkAllUserAlertsRead","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Unread count reset to 0"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Clear a user's unread badge (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/log/{id}":{"get":{"description":"The raw DynamoDB document for one alert — the drill-in behind a global alert row. 404 when it was never written (e.g. a deduped / dry-run decision) or the id is malformed.","operationId":"adminGetUserAlertLogItem","parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"description":"Alert id (from the feed).","in":"path","name":"id","required":true,"schema":{"description":"Alert id (from the feed).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertRawResponse"}}},"description":"The raw stored alert item"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No stored alert for that id"}},"summary":"Get the raw stored item for one alert (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/log/{id}/read":{"post":{"operationId":"adminMarkUserAlertRead","parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"description":"Alert id (from the feed).","in":"path","name":"id","required":true,"schema":{"description":"Alert id (from the feed).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Marked read (idempotent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Mark one of a user's alerts read (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/my-recipes":{"get":{"description":"The recipes the user created (any status), with whether they are subscribed — the rows they see on GET /alerts/my-recipes.","operationId":"adminListUserOwnedRecipes","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertUserRecipesResponse"}}},"description":"The user's recipes"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's own alert recipes (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/recipes":{"get":{"description":"The alert recipe catalog with whether the user is subscribed to each — the same rows the user sees on GET /alerts/recipes.","operationId":"adminListUserAlertRecipes","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipesResponse"}}},"description":"Recipes"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's alert recipes (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/recipes/{id}":{"delete":{"operationId":"adminUnsubscribeUserAlertRecipe","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeResponse"}}},"description":"Unsubscribed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`no_org`: the user has no alert-settings org to stamp the setup with"}},"summary":"Unsubscribe a user from an alert recipe (admin)","tags":["Admin"]},"post":{"description":"Subscribes the user exactly as POST /alerts/recipes/{id} would (same body), on their behalf: grants are stamped `addedBy: admin:{you}`, rows with the user's alert-settings org (409 `no_org` when they have none). `{id}` may be one of the user's own recipes.","operationId":"adminSubscribeUserAlertRecipe","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeInputs"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeResponse"}}},"description":"Subscribed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`no_org`: the user has no alert-settings org to stamp the setup with"}},"summary":"Subscribe a user to an alert recipe (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/recipes/{id}/preview":{"post":{"description":"POST /alerts/recipes/{id}/preview for the user: a 30-day dry replay with the given inputs over their saved setup. Works for the user's own recipes too. Writes nothing.","operationId":"adminPreviewUserAlertRecipe","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeInputs"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipePreviewResponse"}}},"description":"What the recipe would have fired"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"No such recipe"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`no_org`: the user has no alert-settings org to stamp the setup with"}},"summary":"Preview an alert recipe for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/replay":{"post":{"description":"Backtest: run the detector as-of `asOf` (the subscribe day) and each later `step` date, returning a timeline of what's NEW at each step. Always a dry-run — writes nothing, sends no email. A reconstruction from the current index filtered to each date, not a perfect snapshot.","operationId":"adminReplayUserAlerts","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ReplayResponse"}}},"description":"Per-step timeline of newly-firing alerts"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Replay a user's alerts over time (admin, dry-run)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/run":{"post":{"description":"Runs all six detectors scoped to this user, in-process and synchronously. Defaults to a dry-run preview that returns the alerts that WOULD fire (per detector, with the decision payloads) without writing the feed, publishing events, or sending email. Set `dryRun: false` to actually fire.","operationId":"adminRunUserAlertDetector","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunUserDetectorRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunUserDetectorResponse"}}},"description":"Per-detector run summary (fired decisions on a dry-run)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Run the alert detector for one user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/subscriptions":{"get":{"operationId":"adminListUserAlertSubscriptions","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Only subscriptions of this subject type.","in":"query","name":"subjectType","required":false,"schema":{"description":"Only subscriptions of this subject type.","enum":["agent","area","nmls","property","loan","sale","company","filter"],"type":"string"}},{"description":"Only subscriptions carrying this alert kind.","in":"query","name":"kind","required":false,"schema":{"description":"Only subscriptions carrying this alert kind.","enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionsResponse"}}},"description":"Subscriptions"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's alert subscriptions (admin)","tags":["Admin"]},"post":{"operationId":"adminCreateUserAlertSubscription","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertSubscriptionRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionResponse"}}},"description":"The subscription as saved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionError"}}},"description":"Invalid subscription (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Subscribe a user to alerts on a subject (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/subscriptions/{id}":{"delete":{"operationId":"adminDeleteUserAlertSubscription","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}},{"description":"Opaque subscription id.","in":"path","name":"id","required":true,"schema":{"description":"Opaque subscription id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Removed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionError"}}},"description":"Invalid subscription (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Remove a user's alert subscription (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/unread-count":{"get":{"operationId":"adminGetUserUnreadCount","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnreadCountResponse"}}},"description":"Unread count for the user's bell"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Get a user's unread alert count (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-agents":{"get":{"operationId":"adminListUserWatchedAgents","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAgentsResponse"}}},"description":"Watched agents"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's watched agents (admin)","tags":["Admin"]},"post":{"operationId":"adminAddUserWatchedAgent","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedAgentRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Added (idempotent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Add a watched agent for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-agents/{id}":{"delete":{"operationId":"adminRemoveUserWatchedAgent","parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"description":"Agent id to remove.","in":"path","name":"id","required":true,"schema":{"description":"Agent id to remove.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Removed (idempotent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Remove a watched agent for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-areas":{"get":{"operationId":"adminListUserWatchedAreas","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAreasResponse"}}},"description":"Watched areas"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's watched areas (admin)","tags":["Admin"]},"post":{"operationId":"adminAddUserWatchedArea","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedAreaRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAreasResponse"}}},"description":"The updated list"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Add a watched area for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-areas/{id}":{"delete":{"operationId":"adminRemoveUserWatchedArea","parameters":[{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"description":"Area id to remove.","in":"path","name":"id","required":true,"schema":{"description":"Area id to remove.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Removed (idempotent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Remove a watched area for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-documents":{"get":{"operationId":"adminListUserWatchedDocuments","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedDocumentsResponse"}}},"description":"Watched documents"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a user's watched documents (admin)","tags":["Admin"]},"post":{"operationId":"adminAddUserWatchedDocument","parameters":[{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedDocumentRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedDocumentsResponse"}}},"description":"The updated list of watched documents"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Add a watched document (property/sale/loan) for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/users/{userId}/watched-documents/{documentType}/{documentId}":{"delete":{"operationId":"adminRemoveUserWatchedDocument","parameters":[{"description":"The document kind.","in":"path","name":"documentType","required":true,"schema":{"description":"The document kind.","enum":["sale","property","loan"],"type":"string"}},{"description":"The document id.","in":"path","name":"documentId","required":true,"schema":{"description":"The document id.","type":"string"}},{"description":"Target user id.","in":"path","name":"userId","required":true,"schema":{"description":"Target user id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Removed (idempotent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Remove a watched document for a user (admin)","tags":["Admin"]}},"/v1/admin/alerts/workspaces/{orgId}/log":{"get":{"description":"Every alert fired for any user in the workspace, newest first. Only alerts fired after the org was captured on each user's config appear.","operationId":"adminListWorkspaceAlertLog","parameters":[{"description":"Workspace / org id.","in":"path","name":"orgId","required":true,"schema":{"description":"Workspace / org id.","type":"string"}},{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminAlertLogResponse"}}},"description":"Paginated workspace feed"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List a whole workspace's alert feed (admin)","tags":["Admin"]}},"/v1/admin/cad/links/{nmlsId}":{"get":{"description":"Diagnostic: the LO's indexed employment union (sponsorships + registrations), split by source with active counts. `indexGaps` lists what the former database diagnostic showed that the index does not carry.","operationId":"adminGetCadLinks","parameters":[{"description":"Individual NMLS id.","in":"path","name":"nmlsId","required":true,"schema":{"description":"Individual NMLS id.","example":"3352","pattern":"^\\d+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCadLinks"}}},"description":"Links"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not authenticated"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No individual with that NMLS id"}},"summary":"An LO's sponsorship / registration links (admin)","tags":["Admin: NMLS"]}},"/v1/admin/crm/match-candidates":{"post":{"operationId":"adminSearchCrmMatchCandidates","requestBody":{"content":{"application/json":{"schema":{"properties":{"city":{"maxLength":100,"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"name":{"maxLength":200,"minLength":1,"type":"string"},"state":{"maxLength":50,"type":"string"}},"required":["entityType","name"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCrmMatchCandidates"}}},"description":"Ranked candidates (best first)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Find Market-Insights entities a CRM record could link to (admin)","tags":["Admin"]}},"/v1/admin/crm/orgs/{orgId}/apply-mi-updates":{"post":{"description":"`applyCrmMiUpdates` per record for any org: persists ONLY the listed updates (copy `store`, `field`/`kind` and `incoming` as `value` from the review). Sequential, in request order. Free.","operationId":"adminApplyCrmMiUpdates","parameters":[{"description":"The customer's organization id (auth org).","in":"path","name":"orgId","required":true,"schema":{"description":"The customer's organization id (auth org).","maxLength":128,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"actor":{"description":"Who is acting, as the caller names it (`charles`, an admin user id). Writes are stamped `admin:<actor>` on the record.","maxLength":128,"minLength":1,"type":"string"},"reason":{"description":"Why (ticket / support request id + one line). Logged.","maxLength":500,"minLength":3,"type":"string"},"records":{"items":{"properties":{"entityId":{"maxLength":128,"minLength":1,"type":"string"},"updates":{"items":{"oneOf":[{"properties":{"field":{"enum":["title","company","location","city","state","zip"],"type":"string"},"store":{"enum":["override"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","field","value"],"type":"object"},{"properties":{"kind":{"enum":["email","phone","linkedin","facebook","x","instagram","youtube","zillow","realtor","website"],"type":"string"},"store":{"enum":["contact"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","kind","value"],"type":"object"}]},"maxItems":20,"minItems":1,"type":"array"}},"required":["entityId","updates"],"type":"object"},"maxItems":25,"minItems":1,"type":"array"}},"required":["records","actor","reason"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCrmApplyMiResult"}}},"description":"Per-record outcome, in request order."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Apply accepted Market-Insights updates to a customer's records (admin)","tags":["Admin"]}},"/v1/admin/crm/orgs/{orgId}/link":{"post":{"description":"`linkCrmRecord` for any org, after verifying the MM entity resolves: writes `crm_record.link`, logs the record's `linked` activity, lands the mirror row and enriches production inline. 422 `mm_entity_not_found` when the link points at nothing.","operationId":"adminLinkCrmRecord","parameters":[{"description":"The customer's organization id (auth org).","in":"path","name":"orgId","required":true,"schema":{"description":"The customer's organization id (auth org).","maxLength":128,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"actor":{"description":"Who is acting, as the caller names it (`charles`, an admin user id). Writes are stamped `admin:<actor>` on the record.","maxLength":128,"minLength":1,"type":"string"},"entityId":{"description":"The record to connect (often a `manual:` id).","maxLength":128,"minLength":1,"type":"string"},"link":{"$ref":"#/components/schemas/CrmLink"},"reason":{"description":"Why (ticket / support request id + one line). Logged.","maxLength":500,"minLength":3,"type":"string"}},"required":["entityId","link","actor","reason"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCrmLinkResult"}}},"description":"Linked; `previousLink` is what the record pointed at before."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"422":{"content":{"application/json":{"schema":{"properties":{"code":{"enum":["mm_entity_not_found"],"type":"string"},"error":{"type":"string"}},"required":["error","code"],"type":"object"}}},"description":"The link does not resolve to a Market-Insights entity of the record's type."}},"summary":"Connect a customer's CRM record to Market Insights (admin)","tags":["Admin"]}},"/v1/admin/crm/orgs/{orgId}/mi-review":{"post":{"description":"The list-level MI read (`getCrmListMiUpdates`) for any org, on explicit records or one page of a list. Does NOT restart the customer's 31-day review clock or touch their seen-ledger; records the review state only. Free.","operationId":"adminReviewCrmMiUpdates","parameters":[{"description":"The customer's organization id (auth org).","in":"path","name":"orgId","required":true,"schema":{"description":"The customer's organization id (auth org).","maxLength":128,"minLength":1,"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"actor":{"description":"Who is acting, as the caller names it (`charles`, an admin user id). Writes are stamped `admin:<actor>` on the record.","maxLength":128,"minLength":1,"type":"string"},"cursor":{"description":"List paging: `nextCursor` of the previous page.","maxLength":256,"type":"string"},"entityIds":{"description":"Explicit records to check.","items":{"maxLength":128,"minLength":1,"type":"string"},"maxItems":50,"minItems":1,"type":"array"},"limit":{"default":25,"maximum":50,"minimum":1,"type":"integer"},"listId":{"description":"Or: check one page of this list's members.","maxLength":128,"minLength":1,"type":"string"},"reason":{"description":"Why (ticket / support request id + one line). Logged.","maxLength":500,"minLength":3,"type":"string"},"refreshMirror":{"default":true,"description":"Freshen each record's mirrored Market-Insights row before the diff (what opening the record does).","type":"boolean"}},"required":["actor","reason"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminCrmMiReviewResult"}}},"description":"Records with proposals (needs_review + snoozed) and the tally."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Check a customer's CRM records against Market Insights (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache":{"get":{"description":"Returns one page of rows from the DDB enrichment cache table. Optional `empty=true` filters server-side to rows the May 2026 parser-drift incident produced. **Cost note**: DDB Scan reads the whole table boundary regardless of the filter — admin-only.","operationId":"adminScanEnrichmentCache","parameters":[{"description":"Which row kind(s) to scan. Default `both`.","in":"query","name":"scope","required":false,"schema":{"$ref":"#/components/schemas/CacheScope"}},{"description":"When `true`, server-side filter to rows with `size(persons) = 0` — the shape produced by the May 2026 parser-drift incident.","in":"query","name":"empty","required":false,"schema":{"description":"When `true`, server-side filter to rows with `size(persons) = 0` — the shape produced by the May 2026 parser-drift incident.","enum":["true","false"],"type":"string"}},{"in":"query","name":"cursor","required":false,"schema":{"type":"string"}},{"description":"Page size (1-200, default 50).","in":"query","name":"limit","required":false,"schema":{"description":"Page size (1-200, default 50).","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheScanResponse"}}},"description":"One page of cache rows"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Paginated scan of the enrichment cache (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache/bust":{"post":{"description":"Pass full row keys (as returned by `GET /v1/admin/enrichments/cache`). Mix internal and member keys in one call. Returns the count deleted and any keys DDB left in `UnprocessedItems` for the caller to retry.","operationId":"adminBustEnrichmentCacheRows","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheBustRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheBustResponse"}}},"description":"Delete summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Batch-delete a list of enrichment cache rows (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache/internal/{propertyId}":{"delete":{"description":"Idempotent — deleting a missing key is a success. Does NOT bust any `MEMBER#` rows that already cached a copy of this enrichment; use the batch `POST /v1/admin/enrichments/cache/bust` for that.","operationId":"adminDeleteInternalCacheRow","parameters":[{"in":"path","name":"propertyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheDeleteResponse"}}},"description":"Row deleted (or was already absent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Bust a single internal cache row (admin)","tags":["Admin"]},"get":{"operationId":"adminGetInternalCacheRow","parameters":[{"in":"path","name":"propertyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheGetResponse"}}},"description":"The internal cache row (raw, including expired entries)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Row not found"}},"summary":"Inspect a single internal cache row (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache/member/{orgId}/{userId}/{propertyId}":{"delete":{"description":"Idempotent. Does NOT refund the original credit — the user's purchase remains on their account ledger; this just drops the cache row so the next enrich call re-fetches.","operationId":"adminDeleteMemberCacheRow","parameters":[{"in":"path","name":"orgId","required":true,"schema":{"type":"string"}},{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"in":"path","name":"propertyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheDeleteResponse"}}},"description":"Row deleted (or was already absent)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Bust a single member entitlement row (admin)","tags":["Admin"]},"get":{"operationId":"adminGetMemberCacheRow","parameters":[{"in":"path","name":"orgId","required":true,"schema":{"type":"string"}},{"in":"path","name":"userId","required":true,"schema":{"type":"string"}},{"in":"path","name":"propertyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheGetResponse"}}},"description":"The member entitlement row (raw, including expired)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Row not found"}},"summary":"Inspect a single member entitlement row (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache/property/{propertyId}":{"get":{"description":"Returns the internal property cache row and every member entitlement derived from it. Backed by the `byProperty` GSI — single Query, not a table scan. Rows written before the GSI shipped (no `propertyId` attribute) won't appear here until they next refresh.","operationId":"adminGetPropertyCacheChildren","parameters":[{"in":"path","name":"propertyId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCachePropertyChildrenResponse"}}},"description":"Internal row + every member entitlement for this property"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"List every cache row tied to a property (admin)","tags":["Admin"]}},"/v1/admin/enrichments/cache/stats":{"get":{"description":"Counts internal cache rows by health and prices them at the BatchData per-lookup rate, plus the lookups the internal cache saved. Full-table Scan, memoized for 5 minutes per instance; `fresh=true` rescans.","operationId":"adminGetEnrichmentCacheStats","parameters":[{"description":"When `true`, bypass the 5-minute memo and rescan the table.","in":"query","name":"fresh","required":false,"schema":{"description":"When `true`, bypass the 5-minute memo and rescan the table.","enum":["true","false"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentCacheStats"}}},"description":"Cache KPI rollup"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"System admin role required"}},"summary":"Whole-table enrichment cache KPIs (admin)","tags":["Admin"]}},"/v1/admin/jobs/{jobId}":{"get":{"description":"Returns any org's bulk job (delivery or enrichment) with a freshly signed download URL for its result file. Cross-org: signs against the job's own stored org. `resultsUrl` is null until the job is completed.","operationId":"adminGetBulkJob","parameters":[{"description":"Bulk job id (delivery or enrichment).","in":"path","name":"jobId","required":true,"schema":{"description":"Bulk job id (delivery or enrichment).","example":"job_01h...","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AdminBulkJobResponse"}}},"description":"The job"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not authenticated"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Admin role required"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No job with that id (or it has aged past its TTL)"}},"summary":"Get a bulk job and a signed download URL (admin)","tags":["Admin: Jobs"]}},"/v1/agents":{"post":{"description":"Search and list individual real-estate agents with filters — one row per agent. Filter by name, location (state, city, zip), brokerage/office, and production metrics (sales volume, transaction units, price range), with sorting and cursor pagination. LOCATION SEMANTICS: the state/city/zip filters match ANY of an agent's location signals — their listed city/state, their office address(es), AND the markets where they actually closed transactions (production) — combined with OR. So an agent matches a searched location if their office OR their production is there (set `locationSource` to `office` or `production` to use one signal). A search for city \"Long Beach\" can therefore return agents whose office or displayed primary market is in a different city/state, because they transacted in Long Beach. The `state`/`city` returned on each row reflect the agent's primary market and may differ from the searched location. (Use the `office` filter to match by brokerage/office name — one or several names, each a case-insensitive whole-word phrase, `name*` for a prefix; `currentOffice` restricts to the agent's current office — and the per-agent city/county/state breakdown endpoints to rank an agent's volume within a specific market.) RANKING BY DEAL SIDE: combine a location filter with `sort` on `buyerVolume`/`buyerUnits` (or `sellerVolume`/`sellerUnits`, `dualVolume`/`dualUnits`) to rank agents by how active they are representing buyers vs. sellers in that market — e.g. sort `buyerVolume` descending for the most active buyer-side agents in a state or city. This is the per-agent record search: use it to find specific real-estate agents or build a filtered agent list. (For a single agent by ID use the agent detail endpoint.) If you only need how many agents match and not the records themselves, send the same request body to `countAgents`.","operationId":"listAgents","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListResponse"}}},"description":"Paginated list of agents"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Location dictionary temporarily unavailable. Only returned for a NEGATED location filter (`neq`, or `not`), which cannot be honoured without resolving the excluded value — answering anyway would return the records you asked to exclude. Positive location filters are unaffected. Retry shortly; the filter value itself was not rejected."}},"summary":"Search agents with filters","tags":["Agents"]}},"/v1/agents/analytics/chart":{"post":{"operationId":"agentAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart (measure × slice) over the agent's sales","tags":["Agents"]}},"/v1/agents/analytics/summary":{"post":{"operationId":"agentAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SidedSummaryResponse"}}},"description":"Sided summary with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Production summary with buyer/seller/dual split + previous period","tags":["Agents"]}},"/v1/agents/analytics/time-series":{"post":{"operationId":"agentAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SidedTimeSeriesResponse"}}},"description":"Time-series with side splits + previous period"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Agent volume/units over time with buyer/seller/dual split","tags":["Agents"]}},"/v1/agents/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching agents document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/agents/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.agents` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitAgentsBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/AgentListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.agents` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for agents","tags":["Agents"]}},"/v1/agents/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running agents delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/agents/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelAgentsBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/agents/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/agents/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for agents","tags":["Agents"]},"get":{"operationId":"getAgentsBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/agents/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/agents/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for agents","tags":["Agents"]}},"/v1/agents/count":{"post":{"description":"Return the exact number of agents matching the given filters. Accepts the same request body as `listAgents` (pagination and sort are ignored). Use this when you only need a total; to get the matching agents themselves, send the same request body to `listAgents`.","operationId":"countAgents","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching agents"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Location dictionary temporarily unavailable. Only returned for a NEGATED location filter (`neq`, or `not`), which cannot be honoured without resolving the excluded value — answering anyway would return the records you asked to exclude. Positive location filters are unaffected. Retry shortly; the filter value itself was not rejected."}},"summary":"Count agents matching filters","tags":["Agents"],"x-mm-records-via":"listAgents"}},"/v1/agents/{id}":{"get":{"operationId":"getAgent","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}},{"description":"Period for volume/units (default: last12Months)","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for volume/units (default: last12Months)"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentDetailResponse"}}},"description":"Agent detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Agent not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get agent by ID","tags":["Agents"]}},"/v1/agents/{id}/analytics/loan-mix":{"post":{"description":"Scoped to the agent's FINANCED deals: recorded loans on which the agent is the buyer's agent or the listing / co-listing agent, matched through the agent's MLS ids. Cash deals carry no loan and are not counted. The date window is the loan's recording date. Returns, for each side at once (`any`, `buyer`, `listing` — duals on `buyer`): the financed deal count and loan volume, how many were brokered (third-party origination), and the loan-type mix. For the prior period, call again with that period.","operationId":"agentLoanMix","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentLoanMixRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentLoanMixResponse"}}},"description":"Per-side financing profile"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Financing profile of the agent's deals, per side","tags":["Agents"]}},"/v1/agents/{id}/analytics/mortgaged-time-series":{"post":{"description":"Scoped to the agent's FINANCED deals: recorded loans on which the agent is the buyer's agent or the listing / co-listing agent, matched through the agent's MLS ids. Cash deals carry no loan and are not counted. The date window is the loan's recording date. One bucket per `interval` (default monthly): `units` = financed deals recorded in the bucket, `volume` = their total loan amount (out-of-range fill amounts excluded and counted in `excluded`). `previous` is the same series for the prior window. `side` defaults to `any`; `buyer` + `listing` = `any` per bucket. Pair with `agentAnalyticsTimeSeries` (closed sales by sale date) for a mortgaged-vs-total chart — the two use different date axes (loan recording vs sale close), so a deal can land a month apart.","operationId":"agentMortgagedTimeSeries","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentMortgagedTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Financed deals and loan volume per bucket"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"The agent's financed deals and loan volume, over time","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/builders":{"post":{"description":"New-construction builders named on the agent's deals in the period, ranked by units. The pre-aggregated builder list carries a deal COUNT only, so every row's `volume` and `pctVolume` are 0 — rank and share by `units` / `pctUnits` (a share of ALL the agent's deals in the period, so the rows sum to the builder-sold share, not to 1). It carries no buyer/listing split either: `side` must be `any` (or omitted); `buyer`/`listing` return 400.","operationId":"agentBuilders","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScoredBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Pre-aggregated builders breakdown from the agent's scored doc"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Home builders on the agent's deals (pre-aggregated)","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/cities":{"post":{"description":"Ranks the agent's CLOSED sales (MLS status sold, a real sale price — rentals and lease listings excluded, duplicate MLS records of one sale counted once) by this dimension. The same population `POST /v1/agents/{id}/sales` returns with `flatFilters.mlsStatus: \"SLD\"` and the agent analytics routes count. `side` narrows to the deals the agent was on that side of (`buyer` includes deals on both sides; `buyer` + `listing` = `any`).","operationId":"agentCities","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's sales by cities"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"City volume breakdown across the agent's sales","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/companies":{"post":{"operationId":"agentCompanies","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScoredBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Pre-aggregated companies breakdown from the agent's scored doc"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Mortgage companies the agent dealt with (pre-aggregated)","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/counties":{"post":{"description":"Ranks the agent's CLOSED sales (MLS status sold, a real sale price — rentals and lease listings excluded, duplicate MLS records of one sale counted once) by this dimension. The same population `POST /v1/agents/{id}/sales` returns with `flatFilters.mlsStatus: \"SLD\"` and the agent analytics routes count. `side` narrows to the deals the agent was on that side of (`buyer` includes deals on both sides; `buyer` + `listing` = `any`).","operationId":"agentCounties","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's sales by counties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"County (FIPS) volume breakdown","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/lenders":{"post":{"operationId":"agentLenders","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScoredBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Pre-aggregated lenders breakdown from the agent's scored doc"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Raw-name lenders encountered (pre-aggregated)","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/offices":{"post":{"description":"Ranks the agent's CLOSED sales (MLS status sold, a real sale price — rentals and lease listings excluded, duplicate MLS records of one sale counted once) by this dimension. The same population `POST /v1/agents/{id}/sales` returns with `flatFilters.mlsStatus: \"SLD\"` and the agent analytics routes count. `side` narrows to the deals the agent was on that side of (`buyer` includes deals on both sides; `buyer` + `listing` = `any`).","operationId":"agentOffices","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's sales by offices"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Listing offices the agent has closed through","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/originators":{"post":{"operationId":"agentOriginators","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentScoredBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Pre-aggregated originators breakdown from the agent's scored doc"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers the agent worked with (pre-aggregated)","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/states":{"post":{"description":"Ranks the agent's CLOSED sales (MLS status sold, a real sale price — rentals and lease listings excluded, duplicate MLS records of one sale counted once) by this dimension. The same population `POST /v1/agents/{id}/sales` returns with `flatFilters.mlsStatus: \"SLD\"` and the agent analytics routes count. `side` narrows to the deals the agent was on that side of (`buyer` includes deals on both sides; `buyer` + `listing` = `any`).","operationId":"agentStates","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's sales by states"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"State volume breakdown","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/title-companies":{"post":{"description":"Scoped to the agent's FINANCED deals: recorded loans on which the agent is the buyer's agent or the listing / co-listing agent, matched through the agent's MLS ids. Cash deals carry no loan and are not counted. The date window is the loan's recording date. Ranks the title companies named on those loans. Spellings of one company are MERGED: `label` is its most-used spelling, `id` the normalized name every spelling was grouped under. \"None available\"-style placeholders and names shorter than 3 characters are excluded. `pctUnits` / `pctVolume` are shares of ALL the side's financed deals in the window, including those with no title company, so they do not sum to 1. `side` defaults to `any`; title company is usually picked on the buyer side, so `buyer` is the view that reads as \"who this agent's buyers close with\".","operationId":"agentTitleCompanies","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentLoansBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's financed deals by title company"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Title companies on the agent's financed deals (spellings merged)","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/title-companies/time-series":{"post":{"description":"Scoped to the agent's FINANCED deals: recorded loans on which the agent is the buyer's agent or the listing / co-listing agent, matched through the agent's MLS ids. Cash deals carry no loan and are not counted. The date window is the loan's recording date. One bucket per `interval` (default monthly), each segmented by title company with spellings merged per bucket: `segments[].label` is the company's most-used spelling across the whole response and `segments[].id` the normalized name — match a company across buckets on `id`. `previous` is the same series for the prior window. `side` defaults to `any`.","operationId":"agentTitleCompaniesTimeSeries","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentTitleCompanyTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Title-company-segmented time series"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Title companies on the agent's financed deals, over time","tags":["Agents"]}},"/v1/agents/{id}/breakdowns/zip-codes":{"post":{"description":"Ranks the agent's CLOSED sales (MLS status sold, a real sale price — rentals and lease listings excluded, duplicate MLS records of one sale counted once) by this dimension. The same population `POST /v1/agents/{id}/sales` returns with `flatFilters.mlsStatus: \"SLD\"` and the agent analytics routes count. `side` narrows to the deals the agent was on that side of (`buyer` includes deals on both sides; `buyer` + `listing` = `any`).","operationId":"agentZipCodes","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the agent's sales by zip-codes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Zip-code volume breakdown","tags":["Agents"]}},"/v1/agents/{id}/markets":{"post":{"description":"Rank the ZIP markets one real-estate agent works, with volume, transaction counts and mean sale price per market, plus a weighted summary across the whole footprint. Optionally narrow to a ZIP list or a date window. REACH, NOT MARKET SHARE: an agent belongs to every market they touch — where their office is AND everywhere they have transacted — so one agent is counted in several markets at once. Per-market agent counts therefore over-sum: they cannot be added together, and dividing one into a total does not produce a market share. The only percentage returned, `shareOfScope`, is each market's share of this agent's volume across the scope requested and sums to 100 over that scope; there is no share-of-whole-book figure, because the transaction records carry no per-agent total to divide by. TWO COUNTS, ON PURPOSE: `transactions` counts transaction records; `units` counts the ones carrying a price, which are the records behind `volume` and `avgSalePrice`. Roughly half of an agent's records are priced, so dividing volume by `transactions` understates the average by about 2×. Figures are computed live from the agent's transaction records — an agent record carries no stored market rollup — and are ranked across their busiest ZIP markets. When a ZIP scope returns no markets, `reach.presentInScope` distinguishes 'works there, nothing closed in the window' from 'not present at all'. The summary also carries a Community Lending mix: what kind of neighborhood these markets are, weighted by the agent's activity in each. These are U.S. Census tract-level aggregates describing whole neighborhoods — never an individual, household or client attribute — and on this surface the basis is always the markets in scope, since an agent record carries no stored neighborhood rollup.","operationId":"agentMarkets","parameters":[{"description":"Agent ID","in":"path","name":"id","required":true,"schema":{"description":"Agent ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentMarketsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentMarketsResponse"}}},"description":"The agent's blended market footprint"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"The ZIP markets this agent works, blended","tags":["Agents"]}},"/v1/agents/{id}/properties":{"post":{"operationId":"agentProperties","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRelationRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentPropertiesResponse"}}},"description":"Paginated list of properties for this agent"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Properties this agent has transacted on","tags":["Agents"]}},"/v1/agents/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"agentRelated","parameters":[{"description":"Agent id","in":"path","name":"id","required":true,"schema":{"description":"Agent id","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["loans","sales"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/agents/{id}/sales":{"post":{"description":"The agent's deals, newest first: every sale on which the agent is the buyer's agent or the listing / co-listing agent. `side` narrows to one half (`buyer` includes deals where the agent was on both sides; `listing` excludes them). Each row says which `side` the agent was on and carries the sale's recorded purchase `loan` — lender, loan officer, loan type, amount, title company — or `null` for a cash deal or a loan not yet on file. Pass `flatFilters.mlsStatus: \"SLD\"` for closed deals only. `dealFilters` adds an address `search`, the co-listing agent, builder / status-date filters and loan-side filters (`financed`, `loan.*` on the purchase loan). Sorts: the `/v1/sales` names plus `listDate`, `builder`, `coListAgent`, and the loan / party columns `loanAmount`, `loanType`, `loanTransactionType`, `interestRate`, `lenderName`, `originatorName`, `companyName`, `brokerName`, `titleCompany`, `buyerName`, `sellerName`, `downPayment` (one at a time; blanks last). `listingAgent` / `soldAgent` / `coListAgent` order by the name the row shows.","operationId":"agentSales","parameters":[{"description":"Agent document ID","in":"path","name":"id","required":true,"schema":{"description":"Agent document ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentRelationRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentSalesResponse"}}},"description":"Paginated list of sales for this agent"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Sales transactions where this agent was listing or selling side","tags":["Agents"]}},"/v1/alerts/conditions":{"get":{"operationId":"getAlertConditions","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertConditionsResponse"}}},"description":"Per-trigger flags + tunables (defaults if none saved)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get your alert settings","tags":["Alerts"]},"put":{"description":"Saves your NMLS id, contact identity and tunables. The per-trigger `enabled` flags are deprecated: subscribe to alert recipes or manage subscriptions instead. While still accepted, `enabled[type]: true` turns the trigger on for every watched subject that supports it, and `false` turns it off everywhere.","operationId":"updateAlertConditions","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateAlertConditionsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertConditionsResponse"}}},"description":"The saved settings"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update your alert settings","tags":["Alerts"]}},"/v1/alerts/digests":{"get":{"operationId":"listAlertDigests","parameters":[{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertDigestResponse"}}},"description":"Paginated digest feed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List your alert digests (newest first)","tags":["Alerts"]}},"/v1/alerts/digests/{id}/read":{"post":{"operationId":"markAlertDigestRead","parameters":[{"description":"Digest id (from the feed).","in":"path","name":"id","required":true,"schema":{"description":"Digest id (from the feed).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Marked read (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Mark one digest read","tags":["Alerts"]}},"/v1/alerts/email-templates/preview":{"post":{"description":"Validates an email template and returns the notification props a run would send with it, filled with sample items for the given kinds — your recent alerts of those kinds when you have any, else samples. Writes nothing. Pass `recipeId` to preview under one of your recipes (or a published one).","operationId":"previewAlertEmailTemplate","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEmailTemplatePreviewRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEmailTemplatePreviewResponse"}}},"description":"Valid — the props the email renders from"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`invalid_email_template` (with `details`: every problem's path and reason) or `unknown_recipe`"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Preview an alert email template","tags":["Alerts"]}},"/v1/alerts/email-tokens":{"get":{"description":"The tokens a recipe email template can use: run-level tokens (anywhere) and the item tokens each alert kind offers (inside an `items` block), each with a label and a formatted example.","operationId":"getAlertEmailTokens","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertEmailTokensResponse"}}},"description":"Token catalog"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the alert email template tokens","tags":["Alerts"]}},"/v1/alerts/log":{"get":{"operationId":"listAlertLog","parameters":[{"description":"Max items to return (default 25).","in":"query","name":"limit","required":false,"schema":{"description":"Max items to return (default 25).","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response.","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertLogResponse"}}},"description":"Paginated alert feed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List your alerts (newest first)","tags":["Alerts"]}},"/v1/alerts/log/mark-all-read":{"post":{"operationId":"markAllAlertsRead","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Unread count reset to 0"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Clear the unread badge","tags":["Alerts"]}},"/v1/alerts/log/{id}/read":{"post":{"operationId":"markAlertRead","parameters":[{"description":"Alert id (from the feed).","in":"path","name":"id","required":true,"schema":{"description":"Alert id (from the feed).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Marked read (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Mark one alert read","tags":["Alerts"]}},"/v1/alerts/my-recipes":{"get":{"description":"The alert recipes you created (any status), with whether you are subscribed to each. Active ones also appear on GET /alerts/recipes with `scope: \"mine\"`.","operationId":"listMyAlertRecipes","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertUserRecipesResponse"}}},"description":"Your recipes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List your own alert recipes","tags":["Alerts"]},"post":{"description":"Creates an alert recipe only you can see and subscribe to (at most 10). Give a title, the alert kinds per subject type (`grants`), and optionally a description, icon and inputs; the notification family, default inputs and digest copy are derived. Subscribe to it with POST /alerts/recipes/{id}.","operationId":"createMyAlertRecipe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertMyRecipeDefinition"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertUserRecipeResponse"}}},"description":"Created"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`: `family_mismatch`, `grants_empty`, `invalid_icon`, `invalid_kind`, `kind_not_allowed_for_subject`, `unknown_field`, `invalid_rule`, `rule_edge_op_on_event_kind`, `inputs_mismatch`, `invalid_inputs`, `invalid_email_template` with `details`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"You have no such recipe (`unknown_recipe`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`recipe_limit` (at most 10) or `version_conflict`"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create your own alert recipe","tags":["Alerts"]}},"/v1/alerts/my-recipes/preview":{"post":{"description":"Dry-runs a recipe definition (not saved) over the last 30 days for you, with the given inputs applied on top of your saved setup. Writes nothing.","operationId":"previewMyAlertRecipe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertMyRecipePreviewRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipePreviewResponse"}}},"description":"What the recipe would have fired"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`: `family_mismatch`, `grants_empty`, `invalid_icon`, `invalid_kind`, `kind_not_allowed_for_subject`, `unknown_field`, `invalid_rule`, `rule_edge_op_on_event_kind`, `inputs_mismatch`, `invalid_inputs`, `invalid_email_template` with `details`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"You have no such recipe (`unknown_recipe`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`recipe_limit` (at most 10) or `version_conflict`"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Preview an unsaved alert recipe","tags":["Alerts"]}},"/v1/alerts/my-recipes/{id}":{"delete":{"description":"Deletes the recipe and unsubscribes you from it. Saved agents, areas and records stay.","operationId":"deleteMyAlertRecipe","parameters":[{"description":"Your recipe's id (`u-…`).","in":"path","name":"id","required":true,"schema":{"description":"Your recipe's id (`u-…`).","example":"u-k3j9x0a1bq","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Deleted"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`: `family_mismatch`, `grants_empty`, `invalid_icon`, `invalid_kind`, `kind_not_allowed_for_subject`, `unknown_field`, `invalid_rule`, `rule_edge_op_on_event_kind`, `inputs_mismatch`, `invalid_inputs`, `invalid_email_template` with `details`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"You have no such recipe (`unknown_recipe`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`recipe_limit` (at most 10) or `version_conflict`"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete your own alert recipe","tags":["Alerts"]},"put":{"description":"Replaces the definition (`version` bumps). Your existing subscription to it narrows to the kinds it still grants.","operationId":"updateMyAlertRecipe","parameters":[{"description":"Your recipe's id (`u-…`).","in":"path","name":"id","required":true,"schema":{"description":"Your recipe's id (`u-…`).","example":"u-k3j9x0a1bq","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertMyRecipeUpdate"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertUserRecipeResponse"}}},"description":"Updated"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid recipe (see `code`: `family_mismatch`, `grants_empty`, `invalid_icon`, `invalid_kind`, `kind_not_allowed_for_subject`, `unknown_field`, `invalid_rule`, `rule_edge_op_on_event_kind`, `inputs_mismatch`, `invalid_inputs`, `invalid_email_template` with `details`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"You have no such recipe (`unknown_recipe`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"`recipe_limit` (at most 10) or `version_conflict`"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update your own alert recipe","tags":["Alerts"]}},"/v1/alerts/preview":{"post":{"description":"Runs all six detectors scoped to your own token, in-process and synchronously, as a dry-run: returns the alerts that WOULD fire (per detector, with the decision payloads) without writing the feed, publishing events, or sending email.","operationId":"previewAlerts","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PreviewAlertsRequest"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RunUserDetectorResponse"}}},"description":"Per-detector dry-run summary (the decisions that would fire)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Preview the alerts that would fire for you","tags":["Alerts"]}},"/v1/alerts/recipes":{"get":{"description":"The published alert recipes — named bundles of alert triggers — with the inputs each needs and whether you are subscribed, followed by your own recipes (`scope: \"mine\"`).","operationId":"listAlertRecipes","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipesResponse"}}},"description":"Recipes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List alert recipes","tags":["Alerts"]}},"/v1/alerts/recipes/{id}":{"delete":{"description":"Turns the recipe's alert triggers off. Saved agents, areas and records stay; remove them with the watch-list endpoints.","operationId":"unsubscribeAlertRecipe","parameters":[{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeResponse"}}},"description":"Unsubscribed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid request (see `code`: `unknown_recipe`, `recipe_archived`, `invalid_inputs`, `rules_required`, `unknown_field`, `invalid_rule`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Unsubscribe from an alert recipe","tags":["Alerts"]},"post":{"description":"Turns on the recipe's alert triggers, saves its inputs (NMLS id, agents, areas or a record — see the recipe's `inputs`), and backfills recent matches. For a record input, empty rules apply the recipe's rule templates for the record type.","operationId":"subscribeAlertRecipe","parameters":[{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeInputs"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeResponse"}}},"description":"Subscribed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid request (see `code`: `unknown_recipe`, `recipe_archived`, `invalid_inputs`, `rules_required`, `unknown_field`, `invalid_rule`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Subscribe to an alert recipe","tags":["Alerts"]}},"/v1/alerts/recipes/{id}/preview":{"post":{"description":"Dry-run the recipe over the last 30 days for you, with the given inputs applied on top of your saved ones. Writes nothing.","operationId":"previewAlertRecipe","parameters":[{"description":"Recipe id (from GET /alerts/recipes).","in":"path","name":"id","required":true,"schema":{"description":"Recipe id (from GET /alerts/recipes).","example":"farm-area","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeInputs"}}},"required":false},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipePreviewResponse"}}},"description":"What the recipe would have fired"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertRecipeError"}}},"description":"Invalid request (see `code`: `unknown_recipe`, `recipe_archived`, `invalid_inputs`, `rules_required`, `unknown_field`, `invalid_rule`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Preview an alert recipe","tags":["Alerts"]}},"/v1/alerts/subscriptions":{"get":{"description":"Every subject you watch — agents, areas, your NMLS id, records — with the alert kinds that fire on it and the recipes that turned them on.","operationId":"listAlertSubscriptions","parameters":[{"description":"Only subscriptions of this subject type.","in":"query","name":"subjectType","required":false,"schema":{"description":"Only subscriptions of this subject type.","enum":["agent","area","nmls","property","loan","sale","company","filter"],"type":"string"}},{"description":"Only subscriptions carrying this alert kind.","in":"query","name":"kind","required":false,"schema":{"description":"Only subscriptions carrying this alert kind.","enum":["area_new_listing","watched_agent_pending","borrower_listed","epo_risk","agent_sale_closed","rate_term_refi_area","watched_sale","watched_property","watched_loan","book_property","book_loan","area_property"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionsResponse"}}},"description":"Subscriptions"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List your alert subscriptions","tags":["Alerts"]},"post":{"description":"Watch a subject (an agent, an area, your NMLS id, or a sale / property / loan with rules) for the given alert kinds. Re-posting the same subject replaces the kinds you set directly; kinds a recipe turned on stay. Recent matches are backfilled when kinds are added.","operationId":"createAlertSubscription","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateAlertSubscriptionRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionResponse"}}},"description":"The subscription as saved"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionError"}}},"description":"Invalid subscription (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Subscribe to alerts on a subject","tags":["Alerts"]}},"/v1/alerts/subscriptions/{id}":{"delete":{"description":"Stops watching the subject (idempotent). For a record watch this also forgets its baseline, so watching it again starts fresh.","operationId":"deleteAlertSubscription","parameters":[{"description":"Opaque subscription id.","in":"path","name":"id","required":true,"schema":{"description":"Opaque subscription id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Removed"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertSubscriptionError"}}},"description":"Invalid subscription (see `code`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove an alert subscription","tags":["Alerts"]}},"/v1/alerts/unread-count":{"get":{"operationId":"getAlertUnreadCount","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UnreadCountResponse"}}},"description":"Unread count for the bell"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get your unread alert count","tags":["Alerts"]}},"/v1/alerts/watched-agents":{"get":{"operationId":"listWatchedAgents","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAgentsResponse"}}},"description":"Watched agents (hand-added + auto-derived)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the agents you watch","tags":["Alerts"]},"post":{"operationId":"addWatchedAgent","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedAgentRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Agent added (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Watch an agent","tags":["Alerts"]}},"/v1/alerts/watched-agents/{id}":{"delete":{"operationId":"removeWatchedAgent","parameters":[{"description":"Agent id to remove (a hand-added agent; auto-derived agents follow your NMLS id).","in":"path","name":"id","required":true,"schema":{"description":"Agent id to remove (a hand-added agent; auto-derived agents follow your NMLS id).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Agent removed (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Stop watching an agent","tags":["Alerts"]}},"/v1/alerts/watched-areas":{"get":{"operationId":"listWatchedAreas","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAreasResponse"}}},"description":"Watched areas"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the areas you watch","tags":["Alerts"]},"post":{"operationId":"addWatchedArea","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedAreaRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedAreasResponse"}}},"description":"The updated list of watched areas"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Watch an area","tags":["Alerts"]}},"/v1/alerts/watched-areas/{id}":{"delete":{"operationId":"removeWatchedArea","parameters":[{"description":"Area id (from the list).","in":"path","name":"id","required":true,"schema":{"description":"Area id (from the list).","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Area removed (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Stop watching an area","tags":["Alerts"]}},"/v1/alerts/watched-documents":{"get":{"operationId":"listWatchedDocuments","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedDocumentsResponse"}}},"description":"Watched documents"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the documents you watch","tags":["Alerts"]},"post":{"operationId":"addWatchedDocument","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AddWatchedDocumentRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/WatchedDocumentsResponse"}}},"description":"The updated list of watched documents"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Watch a document","tags":["Alerts"]}},"/v1/alerts/watched-documents/{documentType}/{documentId}":{"delete":{"operationId":"removeWatchedDocument","parameters":[{"description":"The document kind.","in":"path","name":"documentType","required":true,"schema":{"description":"The document kind.","enum":["sale","property","loan"],"type":"string"}},{"description":"The document id.","in":"path","name":"documentId","required":true,"schema":{"description":"The document id.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AlertsOkResponse"}}},"description":"Document removed (idempotent)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Stop watching a document","tags":["Alerts"]}},"/v1/branches":{"post":{"description":"Search NMLS-registered mortgage company branch offices (not MLS real estate offices — use listOffices for those). Returns branch name, address, parent company, managers, and NMLS ID. Each row carries branch-level production metrics for the selected period. If you only need how many branches match and not the records themselves, send the same request body to `countBranches`.","operationId":"listBranches","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListResponse"}}},"description":"Paginated list of branches"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search branches with filters","tags":["Branches"]}},"/v1/branches/analytics/chart":{"post":{"description":"Scoped to loans written by the loan officers on this branch's CURRENT licensing roster (wherever they wrote them), matching the branch profile. For loans public record attributes to the branch itself, use the branch breakdown endpoints.","operationId":"branchAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data. Money measures (`volume`, `avgSalePrice`, `avgListPrice`) are sentinel-guarded. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart (measure × slice) over a branch roster's loans","tags":["Branches"]}},"/v1/branches/analytics/summary":{"post":{"description":"Scoped to loans written by the loan officers on this branch's CURRENT licensing roster (wherever they wrote them), matching the branch profile. For loans public record attributes to the branch itself, use the branch breakdown endpoints.","operationId":"branchAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleSummaryResponse"}}},"description":"Current + previous-period summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Branch roster production summary with previous-period comparison","tags":["Branches"]}},"/v1/branches/analytics/time-series":{"post":{"description":"Scoped to loans written by the loan officers on this branch's CURRENT licensing roster (wherever they wrote them), matching the branch profile. For loans public record attributes to the branch itself, use the branch breakdown endpoints.","operationId":"branchAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Time-series with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Branch roster volume / units over time","tags":["Branches"]}},"/v1/branches/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching branches document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/branches/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.branches` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitBranchesBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/BranchListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.branches` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for branches","tags":["Branches"]}},"/v1/branches/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running branches delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/branches/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelBranchesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/branches/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/branches/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for branches","tags":["Branches"]},"get":{"operationId":"getBranchesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/branches/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/branches/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for branches","tags":["Branches"]}},"/v1/branches/count":{"post":{"description":"Return the exact number of branches matching the given filters. Accepts the same request body as `listBranches` (pagination and sort are ignored). Use this when you only need a total; to get the matching branches themselves, send the same request body to `listBranches`.","operationId":"countBranches","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching branches"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count branches matching filters","tags":["Branches"],"x-mm-records-via":"listBranches"}},"/v1/branches/{nmlsId}":{"get":{"description":"Retrieve full details for a single NMLS mortgage branch including name, address, parent company, managers, trade names, licensing, and branch-level production for the selected period.","operationId":"getBranch","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}},{"description":"Period for production metrics (default: last12Months). Does NOT apply to `teamSize`, which is a current snapshot and reads the same on every period.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for production metrics (default: last12Months). Does NOT apply to `teamSize`, which is a current snapshot and reads the same on every period."}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchDetailResponse"}}},"description":"Branch detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Branch not found"}},"summary":"Get branch by NMLS ID","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/cities":{"post":{"description":"Ranks the cities this branch's loans were secured in, by volume — the branch's real lending footprint rather than its parent company's. Labels are Title Case so they match the city breakdowns on every other entity.","operationId":"branchCities","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this branch's loans by cities"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"City volume breakdown across this branch's loans","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/counties":{"post":{"description":"Ranks the counties this branch's loans were secured in, by volume. Labels are county codes on this surface — the same axis every other county breakdown uses, so the two are directly comparable.","operationId":"branchCounties","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this branch's loans by counties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"County volume breakdown across this branch's loans","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/lenders":{"post":{"description":"Ranks the lenders this branch's loans funded through, by volume. Pass an item's `id` — not its `label` — back as a `lender` filter value; `label` is the display name.","operationId":"branchLenders","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this branch's loans by lenders"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Lenders this branch originated through","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/originators":{"post":{"description":"Ranks the loan officers whose loans public record attributes to this branch, by volume. Each label is the LO's NMLS ID, so it chains straight into `GET /v1/originators/{nmlsId}`. This is the branch's RECORDED roster, not its licensing roster: it answers who actually wrote loans here in the period, which is narrower than everyone registered to the branch and can include someone who has since moved. For the licensed managers on file, read `managers` on `GET /v1/branches/{nmlsId}`.","operationId":"branchOriginators","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this branch's loans by originators"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers who wrote this branch's loans","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/states":{"post":{"description":"Ranks the states this branch's loans were secured in, by volume. Labels are two-letter state abbreviations. This is where the branch actually transacted, which is narrower than where it is licensed — licensed states are returned by `GET /v1/branches/{nmlsId}`.","operationId":"branchStates","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this branch's loans by states"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"State volume breakdown across this branch's loans","tags":["Branches"]}},"/v1/branches/{nmlsId}/breakdowns/title-companies":{"post":{"description":"Ranks the title companies on this entity's loans (recorded deeds, `recording_date` window — the same population and period axis as every other loans breakdown). Spellings of one company are MERGED: `label` is its most-used spelling, `id` the normalized name every spelling was grouped under (legal-form and filler words such as `inc`, `llc`, `co`, `company`, `title`, `escrow` removed; `natl` → `national`). Placeholder entries meaning \"no title company recorded\" (`none available` and its misspellings, `unknown`, `n/a`, …) and names shorter than 3 characters are excluded rather than ranked. `attorney` and `accommodation` are kept: they say who closed. `pctUnits` / `pctVolume` are shares of the entity's WHOLE loan population in the window, including loans with no title company, so they do not sum to 100 across the page. Pages of up to 100 via `pagination`.","operationId":"branchTitleCompanies","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the entity's loans by title company"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Title companies on this branch's loans (spellings merged)","tags":["Branches"]}},"/v1/branches/{nmlsId}/loans":{"post":{"description":"Returns the individual loans attributed to this branch office — the branch's own book, not its parent company's. Accepts the same filters, sorts and pagination as the main loan search. Attribution comes from public record, so this is the branch's recorded footprint and can be smaller than the production totals on `GET /v1/branches/{nmlsId}`.","operationId":"branchLoans","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListResponse"}}},"description":"Paginated list of loans written by this branch"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loans written by this branch","tags":["Branches"]}},"/v1/branches/{nmlsId}/roster":{"post":{"description":"The loan officers currently registered to this branch location who hold an active sponsorship or registration — one row per person, with current employer, tenure, years in the industry, manager flags and collected contact info. This is the LICENSING roster; for the loan officers whose loans public record attributes to the branch, use `branchOriginators`.","operationId":"branchRoster","parameters":[{"description":"Branch NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Branch NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchRosterRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BranchRosterResponse"}}},"description":"Paginated roster"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Branch not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers on this branch's current roster","tags":["Branches"]}},"/v1/companies":{"post":{"description":"Search and list individual mortgage companies with filters — one row per company. Filter by name, NMLS ID, location (state, county, city, zip), and production metrics (loan volume, units, market share) by period and geography, with sorting and cursor pagination. This is the per-company record search: use it to find specific mortgage lenders/companies or build a filtered company list. (For a single company by ID use the company detail endpoint.) If you only need how many companies match and not the records themselves, send the same request body to `countCompanies`.","operationId":"listCompanies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListResponse"}}},"description":"Paginated list of companies"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search companies with filters","tags":["Companies"]}},"/v1/companies/analytics/chart":{"post":{"operationId":"companyAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data. Money measures (`volume`, `avgSalePrice`, `avgListPrice`) are sentinel-guarded. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart (measure × slice) over company's loans","tags":["Companies"]}},"/v1/companies/analytics/summary":{"post":{"operationId":"companyAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanySummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleSummaryResponse"}}},"description":"Current + previous-period summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Production summary with previous-period comparison","tags":["Companies"]}},"/v1/companies/analytics/time-series":{"post":{"operationId":"companyAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Time-series with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Company volume / units over time","tags":["Companies"]}},"/v1/companies/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching companies document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/companies/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.companies` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitCompaniesBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/CompanyListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.companies` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for companies","tags":["Companies"]}},"/v1/companies/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running companies delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/companies/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelCompaniesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/companies/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/companies/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for companies","tags":["Companies"]},"get":{"operationId":"getCompaniesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/companies/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/companies/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for companies","tags":["Companies"]}},"/v1/companies/count":{"post":{"description":"Return the exact number of companies matching the given filters. Accepts the same request body as `listCompanies` (pagination and sort are ignored). Use this when you only need a total; to get the matching companies themselves, send the same request body to `listCompanies`.","operationId":"countCompanies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching companies"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count companies matching filters","tags":["Companies"],"x-mm-records-via":"listCompanies"}},"/v1/companies/lookup":{"post":{"description":"Search the NMLS company registry by id, name, registered address, regulator category and size — one row per registered company, INCLUDING companies with no production on file (which `listCompanies` does not return). Use it to resolve canonical company names for a list of NMLS ids, or to filter/sort companies by `regulatorCategory`, `branchCount`, `activeLoCount` or `avgTenureMonths`. For production metrics use `listCompanies`.","operationId":"lookupCompanies","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyLookupRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyLookupResponse"}}},"description":"Registered companies"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Look up companies in the NMLS registry","tags":["Companies"]}},"/v1/companies/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"companyRelated","parameters":[{"description":"Company NMLS ID","in":"path","name":"id","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["loans","originators","properties"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/companies/{nmlsId}":{"get":{"operationId":"getCompany","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Period for production metrics (default: last12Months)","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for production metrics (default: last12Months)"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyDetailResponse"}}},"description":"Company detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Company not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get company by NMLS ID","tags":["Companies"]}},"/v1/companies/{nmlsId}/branches":{"post":{"operationId":"companyBranches","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBranchesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBranchesResponse"}}},"description":"Paginated list of branches"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Branch locations for this company","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/agents":{"post":{"description":"Ranks the real-estate agents on the selling side of this company's loans, by volume. Buckets whose name is an MLS placeholder for \"no selling agent recorded\" (`non member`, `non listed agent`, and ~140 board-specific spellings) are excluded rather than ranked as agents — they are not people and cannot be resolved with `GET /v1/agents/{id}`. Percentages are shares of the company's whole loan population, so they do not sum to 100 across the page.","operationId":"companyAgents","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by agents"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Real-estate agents who co-closed with this company's LOs","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/brokers":{"post":{"operationId":"companyBrokers","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by brokers"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Broker shops that originated loans funding through this company. For a wholesale/TPO lender this is its top broker partners.","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/cities":{"post":{"operationId":"companyCities","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by cities"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"City volume breakdown across this company's loans","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/counties":{"post":{"operationId":"companyCounties","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by counties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"County (FIPS) volume breakdown across this company's loans","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/lenders":{"post":{"operationId":"companyLenders","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by lenders"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Lenders this company originated through","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/offices":{"post":{"operationId":"companyOffices","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by offices"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Broker offices this company originated through","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/originators":{"post":{"description":"Ranks the loan officers on this company's loans (scope with `roleScope` — `tpo` for its third-party originators). `label` is the LO's NMLS id; `name` and `company` (the LO's CURRENT employer per NMLS licensing, not necessarily the company on the loans) are resolved server-side, and are absent for an id with no originator profile. `sort: [{field: \"name\"}]` orders by that resolved name across the top 10,000 originators by volume (`truncated` says when there are more).","operationId":"companyOriginators","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by originators"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers who originated through this company","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/states":{"post":{"operationId":"companyStates","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by states"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"State volume breakdown across this company's loans","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/title-companies":{"post":{"description":"Ranks the title companies on this entity's loans (recorded deeds, `recording_date` window — the same population and period axis as every other loans breakdown). Spellings of one company are MERGED: `label` is its most-used spelling, `id` the normalized name every spelling was grouped under (legal-form and filler words such as `inc`, `llc`, `co`, `company`, `title`, `escrow` removed; `natl` → `national`). Placeholder entries meaning \"no title company recorded\" (`none available` and its misspellings, `unknown`, `n/a`, …) and names shorter than 3 characters are excluded rather than ranked. `attorney` and `accommodation` are kept: they say who closed. `pctUnits` / `pctVolume` are shares of the entity's WHOLE loan population in the window, including loans with no title company, so they do not sum to 100 across the page. Pages of up to 100 via `pagination`.","operationId":"companyTitleCompanies","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the entity's loans by title company"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Title companies on this company's loans (spellings merged)","tags":["Companies"]}},"/v1/companies/{nmlsId}/breakdowns/zip-codes":{"post":{"operationId":"companyZipCodes","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the company's loans by zip-codes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Zip-code volume breakdown across this company's loans","tags":["Companies"]}},"/v1/companies/{nmlsId}/early-exits":{"get":{"operationId":"companyEarlyExits","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units."}]}},{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"from","required":false,"schema":{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"to","required":false,"schema":{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Drill into one hire cohort (`YYYY-MM`): `data` then lists its early departures and recent starts.","in":"query","name":"month","required":false,"schema":{"description":"Drill into one hire cohort (`YYYY-MM`): `data` then lists its early departures and recent starts.","pattern":"^\\d{4}-\\d{2}$","type":"string"}},{"description":"An exit within this many days of the start is EARLY (default 90). Also the 'recent start' and incomplete-cohort horizon.","in":"query","name":"withinDays","required":false,"schema":{"description":"An exit within this many days of the start is EARLY (default 90). Also the 'recent start' and incomplete-cohort horizon.","maximum":730,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyEarlyExitsResponse"}}},"description":"Early-exit cohorts"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Hire cohorts and how many left within N days","tags":["Companies"]}},"/v1/companies/{nmlsId}/employee-stats":{"get":{"operationId":"companyEmployeeStats","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units."}]}},{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"from","required":false,"schema":{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"to","required":false,"schema":{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyEmployeeStatsResponse"}}},"description":"Roster and mover statistics"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Roster size by production tier, plus hire and exit production","tags":["Companies"]}},"/v1/companies/{nmlsId}/employment":{"get":{"description":"Loan officers employed by (sponsored or registered with) this company, one row per person, from NMLS employment records. `status` picks the current roster, the window's hires, the window's complete departures, or everyone; `asOf` gives the roster on a past date. Rows carry tenure dates, branch-manager status, branch location, current employer, contact details and period production.","operationId":"companyEmployment","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"`active` (default): currently employed — any open employment record. `entered`: hired inside the window. `exited`: completely departed inside the window. `all`: everyone with a record relevant to the window. A hire is a loan officer whose earliest employment record at this company still relevant to the window (open, or ended on/after the window start) starts inside it — so someone who fully left and came back inside the window counts, and an existing employee who adds a state license does not. An exit is a loan officer whose latest record at this company ended inside the window and who holds NO open record there — a complete departure.","in":"query","name":"status","required":false,"schema":{"description":"`active` (default): currently employed — any open employment record. `entered`: hired inside the window. `exited`: completely departed inside the window. `all`: everyone with a record relevant to the window. A hire is a loan officer whose earliest employment record at this company still relevant to the window (open, or ended on/after the window start) starts inside it — so someone who fully left and came back inside the window counts, and an existing employee who adds a state license does not. An exit is a loan officer whose latest record at this company ended inside the window and who holds NO open record there — a complete departure.","enum":["active","entered","exited","all"],"type":"string"}},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units."}]}},{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"from","required":false,"schema":{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"to","required":false,"schema":{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Roster AS OF this date (YYYY-MM-DD): loan officers with a record covering it. Replaces the window; `status` must be `active` or omitted.","in":"query","name":"asOf","required":false,"schema":{"description":"Roster AS OF this date (YYYY-MM-DD): loan officers with a record covering it. Replaces the window; `status` must be `active` or omitted.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Loan officer name (all words, fuzzy) or an exact NMLS ID when numeric.","in":"query","name":"search","required":false,"schema":{"description":"Loan officer name (all words, fuzzy) or an exact NMLS ID when numeric.","maxLength":200,"type":"string"}},{"description":"1-based page (default 1).","in":"query","name":"page","required":false,"schema":{"description":"1-based page (default 1).","minimum":1,"type":"integer"}},{"description":"Rows per page (default 25, max 500).","in":"query","name":"limit","required":false,"schema":{"description":"Rows per page (default 25, max 500).","maximum":500,"minimum":1,"type":"integer"}},{"description":"Sort key (default `name`). `volume`/`units` rank by the loan officer's production in `period` across all employers; `companyVolume`/`companyUnits` by their production AT this company inside the window.","in":"query","name":"sort","required":false,"schema":{"description":"Sort key (default `name`). `volume`/`units` rank by the loan officer's production in `period` across all employers; `companyVolume`/`companyUnits` by their production AT this company inside the window.","enum":["name","nmlsId","startDate","exitDate","volume","units","companyVolume","companyUnits"],"type":"string"}},{"description":"Default `asc` for text/date keys, `desc` for the production keys.","in":"query","name":"order","required":false,"schema":{"description":"Default `asc` for text/date keys, `desc` for the production keys.","enum":["asc","desc"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyEmploymentResponse"}}},"description":"Employment rows"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List a company's loan officers: current roster, hires, or exits","tags":["Companies"]}},"/v1/companies/{nmlsId}/headcount":{"get":{"operationId":"companyHeadcount","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units."}]}},{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"from","required":false,"schema":{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"to","required":false,"schema":{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Series granularity. Only `month` is supported.","in":"query","name":"interval","required":false,"schema":{"description":"Series granularity. Only `month` is supported.","enum":["month"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyHeadcountResponse"}}},"description":"Headcount series and summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Monthly loan officer headcount, hires and exits for a company","tags":["Companies"]}},"/v1/companies/{nmlsId}/markets":{"post":{"description":"The company's market footprint for a period: a units-weighted summary, the ZIP-level markets, and the city / county / state rollups, computed from the company's recorded transactions. Optionally narrow to a set of ZIP codes and/or a custom date window. Shares are percentages on a 0–100 scale. The summary also carries a Community Lending mix — what kind of neighborhood the book lands in, as U.S. Census tract-level aggregates describing whole neighborhoods, never individual or applicant attributes. Unfiltered, it is the company's own whole-period mix; any ZIP, date or transaction filter recomputes it over the markets in scope, and `summary.communityLending.basis` says which you got.","operationId":"companyMarkets","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyMarketsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyMarketsResponse"}}},"description":"Blended market footprint"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Where a company lends — blended market footprint","tags":["Companies"]}},"/v1/companies/{nmlsId}/sponsored-individuals":{"post":{"operationId":"companySponsoredIndividuals","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanySponsoredIndividualsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanySponsoredIndividualsResponse"}}},"description":"Paginated list of sponsored individuals"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan originators sponsored by this company","tags":["Companies"]}},"/v1/companies/{nmlsId}/sponsorship-movement":{"post":{"operationId":"companySponsorshipMovement","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanySponsorshipMovementRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanySponsorshipMovementResponse"}}},"description":"Movement analysis"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Analyze LO arrivals and departures for a company","tags":["Companies"]}},"/v1/companies/{nmlsId}/talent-flow":{"get":{"operationId":"companyTalentFlow","parameters":[{"description":"Company NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Company NMLS ID","type":"string"}},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units.","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Preset window when `from`/`to` are not given (default `last12Months`). Rolling periods start on the FIRST day of the month N months back and end today; a year is Jan 1 – Dec 31; `allTime` starts 2017-01-01, the earliest reliable registration data. Also selects the production period for volume/units."}]}},{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"from","required":false,"schema":{"description":"Window start, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","in":"query","name":"to","required":false,"schema":{"description":"Window end, inclusive (YYYY-MM-DD). Overrides `period`.","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Counterparty companies per side (default 50, max 1000).","in":"query","name":"limit","required":false,"schema":{"description":"Counterparty companies per side (default 50, max 1000).","maximum":1000,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CompanyTalentFlowResponse"}}},"description":"Hires by prior employer, exits by next employer"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Where a company's hires came from and where its exits went","tags":["Companies"]}},"/v1/crm/activity":{"delete":{"operationId":"deleteCrmNote","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"minLength":1,"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteNoteResult"}}},"description":"Whether the note was soft-deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Soft-delete a note","tags":["CRM"]},"get":{"operationId":"listCrmActivity","parameters":[{"description":"The CRM record id whose timeline to read.","in":"query","name":"entityId","required":true,"schema":{"description":"The CRM record id whose timeline to read.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmActivityList"}}},"description":"The record's timeline entries, newest first."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List a record's activity timeline (newest first)","tags":["CRM"]},"patch":{"operationId":"editCrmNote","requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"id":{"minLength":1,"type":"string"},"listId":{"nullable":true,"type":"string"},"recordName":{"type":"string"},"recordUrl":{"deprecated":true,"description":"Ignored — the record link is server-built.","type":"string"}},"required":["id","body"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEditNoteResult"}}},"description":"Whether the note was updated, plus its record + prior body."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Edit a note's body","tags":["CRM"]},"post":{"operationId":"addCrmNote","requestBody":{"content":{"application/json":{"schema":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"},"callId":{"nullable":true,"type":"string"},"entityId":{"minLength":1,"type":"string"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"listId":{"nullable":true,"type":"string"},"parentId":{"nullable":true,"type":"string"},"recordName":{"type":"string"},"recordUrl":{"deprecated":true,"description":"Ignored — the record link is server-built.","type":"string"}},"required":["entityId","body"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddNoteResult"}}},"description":"The new note's id + its resolved thread root (null if top-level)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Append a note to a record's timeline","tags":["CRM"]}},"/v1/crm/activity/log":{"patch":{"operationId":"editCrmLoggedActivity","requestBody":{"content":{"application/json":{"schema":{"properties":{"activityType":{"$ref":"#/components/schemas/CrmLoggedActivityType"},"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"},"direction":{"description":"call + email only.","enum":["inbound","outbound",null],"nullable":true,"type":"string"},"durationMinutes":{"description":"call + meeting only, in minutes.","maximum":1440,"minimum":0,"nullable":true,"type":"integer"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"id":{"minLength":1,"type":"string"},"listId":{"nullable":true,"type":"string"},"occurredAt":{"description":"Epoch ms the activity actually happened. Must be ≤ now + 5 minutes.","exclusiveMinimum":true,"minimum":0,"type":"integer"},"outcome":{"description":"call: connected | voicemail | no_answer | busy. meeting: held | no_show. Not allowed for email/task.","nullable":true,"type":"string"},"recordName":{"type":"string"},"title":{"description":"Meeting title / email subject / task title. Not allowed for a call; required for a task.","maxLength":200,"nullable":true,"type":"string"}},"required":["id","activityType","occurredAt","body"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEditLoggedActivityResult"}}},"description":"Whether the logged entry was updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No live logged entry with that id — either it doesn't exist, was deleted, or isn't a logged entry (this route can't edit a plain note)."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Edit a logged activity entry","tags":["CRM"]},"post":{"operationId":"logCrmActivity","requestBody":{"content":{"application/json":{"schema":{"properties":{"activityType":{"$ref":"#/components/schemas/CrmLoggedActivityType"},"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"},"direction":{"description":"call + email only.","enum":["inbound","outbound",null],"nullable":true,"type":"string"},"durationMinutes":{"description":"call + meeting only, in minutes.","maximum":1440,"minimum":0,"nullable":true,"type":"integer"},"entityId":{"minLength":1,"type":"string"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"listId":{"nullable":true,"type":"string"},"occurredAt":{"description":"Epoch ms the activity actually happened. Must be ≤ now + 5 minutes.","exclusiveMinimum":true,"minimum":0,"type":"integer"},"outcome":{"description":"call: connected | voicemail | no_answer | busy. meeting: held | no_show. Not allowed for email/task.","nullable":true,"type":"string"},"recordName":{"type":"string"},"title":{"description":"Meeting title / email subject / task title. Not allowed for a call; required for a task.","maxLength":200,"nullable":true,"type":"string"}},"required":["entityId","activityType","occurredAt","body"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLogActivityResult"}}},"description":"The new logged entry's id."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Log a Call/Meeting/Email/Task that happened outside Model Match","tags":["CRM"]}},"/v1/crm/activity/referenced":{"get":{"operationId":"listCrmReferencedActivity","parameters":[{"description":"The CRM record whose referenced (trickled-up) activity to read.","in":"query","name":"entityId","required":true,"schema":{"description":"The CRM record whose referenced (trickled-up) activity to read.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmReferencedActivityList"}}},"description":"Notes authored on other records that reference this record, newest first."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List notes from other records that reference this one (trickled up)","tags":["CRM"]}},"/v1/crm/caller-ids":{"delete":{"operationId":"deleteCrmCallerId","parameters":[{"in":"query","name":"id","required":true,"schema":{"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteCallerIdResult"}}},"description":"Whether the caller ID was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove a caller ID from the registry","tags":["CRM"]},"get":{"operationId":"listCrmCallerIds","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallerIdList"}}},"description":"The user's caller IDs + whether Twilio is configured."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the current user's caller IDs","tags":["CRM"]},"patch":{"operationId":"setDefaultCrmCallerId","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"maxLength":128,"minLength":1,"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmSetDefaultCallerIdResult"}}},"description":"Whether the default was set."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Make a verified caller ID the default","tags":["CRM"]},"post":{"operationId":"actionCrmCallerId","requestBody":{"content":{"application/json":{"schema":{"oneOf":[{"properties":{"action":{"enum":["start"],"type":"string"},"friendlyName":{"maxLength":64,"type":"string"},"phoneNumber":{"maxLength":32,"minLength":7,"type":"string"}},"required":["action","phoneNumber"],"type":"object"},{"properties":{"action":{"enum":["check"],"type":"string"},"id":{"maxLength":128,"minLength":1,"type":"string"}},"required":["action","id"],"type":"object"}]}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallerIdActionResult"}}},"description":"The caller-ID row (+ the verification code on start)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Start caller-ID verification or re-check its outcome","tags":["CRM"]}},"/v1/crm/calls":{"get":{"operationId":"getCrmCall","parameters":[{"in":"query","name":"id","required":true,"schema":{"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPollCallResult"}}},"description":"The call row."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Poll one call's status (syncs + finalizes on terminal)","tags":["CRM"]},"patch":{"operationId":"hangupCrmCall","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"maxLength":128,"minLength":1,"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmHangupCallResult"}}},"description":"The call row."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Hang up an in-flight call","tags":["CRM"]},"post":{"operationId":"placeCrmCall","requestBody":{"content":{"application/json":{"schema":{"properties":{"callerIdId":{"maxLength":128,"minLength":1,"type":"string"},"entityId":{"maxLength":128,"minLength":1,"type":"string"},"record":{"type":"boolean"},"toNumber":{"maxLength":32,"minLength":7,"type":"string"}},"required":["entityId","toNumber","callerIdId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPlaceCallResult"}}},"description":"The call row."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Place an outbound bridge call","tags":["CRM"]}},"/v1/crm/calls/active":{"get":{"operationId":"getCrmActiveCall","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmActiveCallResult"}}},"description":"The live call to resume, or null."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"The current user's still-live call (for reload resume)","tags":["CRM"]}},"/v1/crm/calls/analysis":{"post":{"operationId":"setCrmCallAnalysis","requestBody":{"content":{"application/json":{"schema":{"properties":{"actions":{"items":{"oneOf":[{"properties":{"dueInDays":{"maximum":365,"minimum":0,"type":"integer"},"title":{"maxLength":300,"minLength":1,"type":"string"},"type":{"enum":["task"],"type":"string"}},"required":["type","title","dueInDays"],"type":"object"},{"properties":{"durationMinutes":{"maximum":480,"minimum":5,"type":"integer"},"startInDays":{"maximum":365,"minimum":0,"type":"integer"},"title":{"maxLength":300,"minLength":1,"type":"string"},"type":{"enum":["meeting"],"type":"string"}},"required":["type","title","startInDays"],"type":"object"}]},"maxItems":4,"type":"array"},"id":{"maxLength":128,"minLength":1,"type":"string"},"label":{"enum":["interested","ready_to_move","callback_requested","follow_up_needed","objection_raised","not_interested","not_a_fit",null],"nullable":true,"type":"string"},"sentiment":{"enum":["positive","neutral","negative"],"type":"string"},"summary":{"maxLength":4000,"minLength":1,"type":"string"}},"required":["id","label","summary","sentiment","actions"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallAnalysisResult"}}},"description":"The call row with the analysis persisted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Persist an AI analysis of a recorded call","tags":["CRM"]}},"/v1/crm/calls/analyze":{"post":{"operationId":"analyzeCrmCall","requestBody":{"content":{"application/json":{"schema":{"properties":{"contactName":{"maxLength":200,"type":"string"},"id":{"maxLength":128,"minLength":1,"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallAnalyzeResult"}}},"description":"The call row with the analysis persisted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The call's transcript isn't completed yet."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The model didn't return a usable analysis."}},"summary":"Analyze a recorded call's transcript with AI and persist it","tags":["CRM"]}},"/v1/crm/calls/transcript":{"get":{"operationId":"getCrmCallTranscript","parameters":[{"in":"query","name":"id","required":true,"schema":{"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallTranscriptResult"}}},"description":"The call row with the transcript pipeline advanced."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Poll a recorded call's transcript (advances the pipeline)","tags":["CRM"]},"post":{"operationId":"transcribeCrmCall","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"maxLength":128,"minLength":1,"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCallTranscribeResult"}}},"description":"The call row with transcription started."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The call wasn't skipped as voicemail, or its recording isn't ready yet."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Transcribe a recorded call that was skipped as voicemail","tags":["CRM"]}},"/v1/crm/contacts":{"delete":{"operationId":"removeCrmContactMethod","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRemoveContactResult"}}},"description":"Whether a contact was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove a user-added contact method","tags":["CRM"]},"patch":{"operationId":"updateCrmContactMethod","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPatchContactBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmPatchContactResult"}}},"description":"The update flag, or the id of the suppression tombstone."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update or suppress a contact method","tags":["CRM"]},"post":{"operationId":"addCrmContactMethod","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"isPrimary":{"type":"boolean"},"kind":{"$ref":"#/components/schemas/CrmContactKind"},"label":{"nullable":true,"type":"string"},"mmKey":{"nullable":true,"type":"string"},"value":{"nullable":true}},"required":["entityId","kind"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddContactResult"}}},"description":"The id of the newly added contact method."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Add a contact method to a record","tags":["CRM"]}},"/v1/crm/custom-values":{"get":{"operationId":"getCrmCustomValues","parameters":[{"in":"query","name":"entityId","required":false,"schema":{"type":"string"}},{"in":"query","name":"entityIds","required":false,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCustomValueResult"}}},"description":"Single: values keyed by field id. Bulk: keyed by entity id then field id."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get custom-field values for one or many records","tags":["CRM"]},"patch":{"operationId":"setCrmCustomValue","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"fieldId":{"type":"string"},"value":{"$ref":"#/components/schemas/CrmCustomValue"}},"required":["entityId","fieldId","value"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmSetCustomValueResult"}}},"description":"Acknowledgement that the value was written."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Set a record's value for one custom field","tags":["CRM"]}},"/v1/crm/email/send":{"post":{"operationId":"sendCrmEmail","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEmailSendBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEmailSendResult"}}},"description":"Sent, or needs-connect when no send connector is available."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEmailUpstreamError"}}},"description":"Upstream provider error."}},"summary":"Send an outbound email via the user's connected Gmail or Outlook","tags":["CRM"]}},"/v1/crm/enrich/apply":{"post":{"operationId":"applyCrmEnrichment","requestBody":{"content":{"application/json":{"schema":{"properties":{"contacts":{"items":{"$ref":"#/components/schemas/CrmEnrichmentContact"},"type":"array"},"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"link":{"allOf":[{"$ref":"#/components/schemas/CrmLink"},{"description":"Set to accept the match; omit to leave unlinked."}]},"overrideSources":{"$ref":"#/components/schemas/CrmEnrichmentOverrideSources"},"overrides":{"$ref":"#/components/schemas/CrmEnrichmentOverrides"}},"required":["entityId","entityType"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEnrichmentResult"}}},"description":"Whether a match was linked + the count of seeded contacts."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Apply a match to an imported record (link + seed contacts)","tags":["CRM"]}},"/v1/crm/fields":{"delete":{"operationId":"deleteCrmObjectField","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteObjectFieldResult"}}},"description":"Whether a field was deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete an object-scoped custom field (values cascade)","tags":["CRM"]},"get":{"operationId":"listCrmCustomFields","parameters":[{"in":"query","name":"objectType","required":true,"schema":{"$ref":"#/components/schemas/CrmObjectType"}},{"description":"Also include this list's list-scoped fields.","in":"query","name":"listId","required":false,"schema":{"description":"Also include this list's list-scoped fields.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCustomFieldList"}}},"description":"Object-scoped fields plus any requested list-scoped fields."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List custom fields applicable to a view","tags":["CRM"]},"patch":{"operationId":"updateCrmObjectField","requestBody":{"content":{"application/json":{"schema":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"id":{"type":"string"},"label":{"type":"string"},"options":{"items":{"$ref":"#/components/schemas/CrmCustomFieldOption"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmUpdateObjectFieldResult"}}},"description":"Whether a field was updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update an object-scoped custom field (label / options / config / order)","tags":["CRM"]},"post":{"operationId":"createCrmObjectField","requestBody":{"content":{"application/json":{"schema":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"key":{"type":"string"},"label":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"options":{"items":{"$ref":"#/components/schemas/CrmCustomFieldOption"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"},"type":{"$ref":"#/components/schemas/CrmCustomFieldType"}},"required":["objectType","label","type"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCreateObjectFieldResult"}}},"description":"The created field."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"properties":{"error":{"type":"string"}},"required":["error"],"type":"object"}}},"description":"A field with that key already exists for the object type."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create an object-scoped (workspace-wide) custom field","tags":["CRM"]}},"/v1/crm/import":{"post":{"operationId":"importCrmRecords","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityType":{"allOf":[{"$ref":"#/components/schemas/CrmEntityType"},{"description":"Entity type for created rows (default per object)."}]},"listId":{"nullable":true,"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"ownerUserId":{"description":"Default working owner (member userId) for created rows; a row's own ownerUserId overrides it. Both fall back to the caller. Assigning an owner other than the caller requires an org admin.","type":"string"},"rows":{"items":{"$ref":"#/components/schemas/CrmImportRow"},"type":"array"}},"required":["objectType","rows"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmImportResult"}}},"description":"Small batch: per-row outcomes plus the batch tally."},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmImportAccepted"}}},"description":"Large batch accepted for asynchronous processing; returns a job handle."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable (owner-assignment member lookup failed)."}},"summary":"Bulk import records (create or update), optionally into a list","tags":["CRM"]}},"/v1/crm/import/{jobId}":{"get":{"operationId":"getCrmImportJob","parameters":[{"description":"Job id from a 202 import.","in":"path","name":"jobId","required":true,"schema":{"description":"Job id from a 202 import.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmImportJob"}}},"description":"Job status (queued / running / completed / failed / cancelled)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get an async import job's status (progress + per-row errors)","tags":["CRM"]}},"/v1/crm/lender-channels":{"post":{"operationId":"crmLenderChannels","requestBody":{"content":{"application/json":{"schema":{"properties":{"loNmlsIds":{"description":"Bare LO NMLS ids (deduped, capped at 500).","items":{"type":"string"},"type":"array"}},"required":["loNmlsIds"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLenderChannels"}}},"description":"Per-LO current sponsor company + classified lender channel."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Bank / Credit Union / Broker / Retail channel per LO (by NMLS)","tags":["CRM"]}},"/v1/crm/lists":{"get":{"operationId":"listCrmLists","parameters":[{"in":"query","name":"objectType","required":false,"schema":{"$ref":"#/components/schemas/CrmObjectType"}},{"in":"query","name":"entityId","required":false,"schema":{"minLength":1,"type":"string"}},{"in":"query","name":"scope","required":false,"schema":{"enum":["visible","all"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListArray"}}},"description":"Visible lists (own + org-wide + shared-with-me); scope=all returns every workspace list for admins."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the caller's lists (picker mode with ?entityId adds hasMember)","tags":["CRM"]},"post":{"operationId":"createCrmList","requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"}},"required":["name","objectType"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListCreateResult"}}},"description":"The created list."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a list","tags":["CRM"]}},"/v1/crm/lists/memberships":{"get":{"operationId":"listCrmListMemberships","parameters":[{"in":"query","name":"objectType","required":false,"schema":{"$ref":"#/components/schemas/CrmObjectType"}},{"in":"query","name":"entityIds","required":true,"schema":{"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListMembershipsResult"}}},"description":"Each requested entityId mapped to the visible lists it's on ([] = none)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Batched list-membership lookup for many entities","tags":["CRM"]}},"/v1/crm/lists/{id}":{"delete":{"operationId":"deleteCrmList","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListDeleteResult"}}},"description":"Deleted (soft)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a list","tags":["CRM"]},"get":{"operationId":"getCrmList","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListWithMembers"}}},"description":"The list + members, or null when not found / not visible."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get a list with its members","tags":["CRM"]},"patch":{"operationId":"updateCrmList","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListUpdateBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListUpdateResult"}}},"description":"The updated list (null when only a sub-op with no rename ran)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update a list's name, visibility, or whole-org role","tags":["CRM"]}},"/v1/crm/lists/{id}/apply-mi-updates":{"post":{"description":"Bulk form of `applyCrmMiUpdates` for records in one CRM list: for each record, persist ONLY the updates listed for it (copy them from `getCrmListMiUpdates` — `store`, `field` or `kind`, and the `incoming` value as `value`). Never send updates the user did not accept. Proposals on a record that were not accepted count as reviewed. Records not in the list are reported, not applied.","operationId":"applyCrmListMiUpdates","parameters":[{"description":"The CRM list id.","in":"path","name":"id","required":true,"schema":{"description":"The CRM list id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"records":{"items":{"properties":{"entityId":{"maxLength":128,"minLength":1,"type":"string"},"updates":{"items":{"oneOf":[{"properties":{"field":{"enum":["title","company","location","city","state","zip"],"type":"string"},"store":{"enum":["override"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","field","value"],"type":"object"},{"properties":{"kind":{"enum":["email","phone","linkedin","facebook","x","instagram","youtube","zillow","realtor","website"],"type":"string"},"store":{"enum":["contact"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","kind","value"],"type":"object"}]},"maxItems":20,"minItems":1,"type":"array"}},"required":["entityId","updates"],"type":"object"},"maxItems":25,"minItems":1,"type":"array"}},"required":["records"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmApplyListMiUpdatesResult"}}},"description":"Per-record outcome, in request order."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Apply accepted Market-Insights updates to several list records","tags":["CRM"]}},"/v1/crm/lists/{id}/assignees":{"get":{"operationId":"listCrmListAssignees","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListAssigneeList"}}},"description":"Members who can access the list."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"List not found."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List who can be assigned on a list (access-filtered by visibility)","tags":["CRM"]}},"/v1/crm/lists/{id}/dismiss-mi-updates":{"post":{"description":"Bulk form of `dismissCrmMiUpdates` for records in one CRM list: marks the updates last shown for each record as reviewed for the 31-day check window, so `getCrmListMiUpdates` stops returning them. Nothing is written to the records. A proposal that was not shown yet (new Market-Insights data) still comes back.","operationId":"dismissCrmListMiUpdates","parameters":[{"description":"The CRM list id.","in":"path","name":"id","required":true,"schema":{"description":"The CRM list id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"entityIds":{"items":{"maxLength":128,"minLength":1,"type":"string"},"maxItems":100,"minItems":1,"type":"array"}},"required":["entityIds"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDismissListMiUpdatesResult"}}},"description":"Which records were snoozed, and which are not in the list."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Snooze Market-Insights updates on several list records","tags":["CRM"]}},"/v1/crm/lists/{id}/filter-members":{"post":{"operationId":"filterCrmListMembers","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"filter":{"$ref":"#/components/schemas/CrmMemberFilter"},"limit":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"required":["filter"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmFilterMembersResult"}}},"description":"Matching member entity ids (resolved in Postgres)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Filter a list's members by entity attributes (read)","tags":["CRM"]}},"/v1/crm/lists/{id}/member-ids":{"get":{"operationId":"getCrmListMemberIds","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMemberIdsResult"}}},"description":"Every member entity id of the list, all entity types."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List a CRM list's member entity ids (ids only)","tags":["CRM"]}},"/v1/crm/lists/{id}/members":{"delete":{"operationId":"removeCrmListMember","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"}},"required":["entityId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRemoveListMemberResult"}}},"description":"Whether a membership was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove a member from a list","tags":["CRM"]},"post":{"operationId":"addCrmListMember","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"link":{"$ref":"#/components/schemas/CrmLink"},"note":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"}},"required":["body"],"type":"object"},"ownerUserId":{"type":"string"},"status":{"type":"string"}},"required":["entityType","entityId","link","display"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddListMemberResult"}}},"description":"Whether the member was newly added + the member row."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Add a member to a list","tags":["CRM"]}},"/v1/crm/lists/{id}/members/bulk":{"post":{"operationId":"addCrmListMembersBulk","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"members":{"items":{"properties":{"company":{"type":"string"},"companyType":{"type":"string"},"contacts":{"items":{"$ref":"#/components/schemas/CrmContactSeed"},"type":"array"},"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"link":{"$ref":"#/components/schemas/CrmLink"},"title":{"type":"string"}},"required":["entityType","entityId","display"],"type":"object"},"minItems":1,"type":"array"},"note":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"}},"required":["body"],"type":"object"},"ownerUserId":{"type":"string"},"status":{"type":"string"}},"required":["members"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddMembersBulkResult"}}},"description":"Counts + the ids newly added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Add many members to a list","tags":["CRM"]}},"/v1/crm/lists/{id}/mi-updates":{"post":{"description":"Checks a CRM list's members against current Market-Insights data and returns ONLY the records that need attention, each with its proposed updates. Use this instead of calling `getCrmRecordProfile` + `getCrmMiUpdates` for every member: one call covers a page of up to 50 members, and records the user already reviewed (applied or dismissed) with nothing new since are left out. Page with `cursor` until `nextCursor` is null; a page may return no records and still have more to scan. Act on the results with `applyCrmListMiUpdates` (explicit per-record accepted updates) and `dismissCrmListMiUpdates` (snooze the rest). Each scan counts as a check of those records, exactly like `getCrmMiUpdates`.","operationId":"getCrmListMiUpdates","parameters":[{"description":"The CRM list id.","in":"path","name":"id","required":true,"schema":{"description":"The CRM list id.","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"cursor":{"description":"`nextCursor` of the previous page.","maxLength":256,"type":"string"},"entityTypes":{"description":"Only these entity types.","items":{"$ref":"#/components/schemas/CrmEntityType"},"maxItems":4,"type":"array"},"includeSnoozed":{"default":false,"description":"Also return records whose proposals were all already reviewed.","type":"boolean"},"limit":{"default":25,"description":"Members evaluated per page (max 50), not records returned.","maximum":50,"minimum":1,"type":"integer"}},"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListMiUpdatesResult"}}},"description":"The records on this page that need Market-Insights review, with their proposed updates."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Find the records in a CRM list that have Market-Insights updates to review","tags":["CRM"]}},"/v1/crm/lists/{id}/shareable-members":{"get":{"operationId":"listCrmListShareableMembers","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmShareableMemberList"}}},"description":"The org roster for the list's sharing picker (all members)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List the org members a list can be shared with (manage-gated)","tags":["CRM"]}},"/v1/crm/lists/{id}/shares":{"delete":{"operationId":"revokeCrmListAccess","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"userId":{"type":"string"}},"required":["userId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRevokeListAccessResult"}}},"description":"Whether a grant was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Revoke a member's access to a list","tags":["CRM"]},"get":{"operationId":"getCrmListShares","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListSharingResult"}}},"description":"Visibility + owner display + enriched grants, or null."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"Get a list's sharing state (+ owner display, canManageSharing)","tags":["CRM"]},"patch":{"operationId":"transferCrmListOwnership","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"newOwnerUserId":{"type":"string"}},"required":["newOwnerUserId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTransferListOwnershipResult"}}},"description":"Whether ownership moved (false when the target is already the owner)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Transfer a list's ownership to another member","tags":["CRM"]},"post":{"operationId":"grantCrmListAccess","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"permission":{"enum":["editor","viewer"],"type":"string"},"userId":{"type":"string"}},"required":["userId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmGrantListAccessResult"}}},"description":"Whether a new grant was created."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Grant a member access to a list","tags":["CRM"]}},"/v1/crm/lists/{listId}/apply-template":{"post":{"operationId":"applyCrmListTemplate","parameters":[{"in":"path","name":"listId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmApplyTemplateBody"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmApplyTemplateResult"}}},"description":"Fields that landed vs. were skipped (additive, idempotent)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Replay a template's fields onto a list","tags":["CRM"]}},"/v1/crm/lists/{listId}/fields":{"delete":{"operationId":"deleteCrmListField","parameters":[{"in":"path","name":"listId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteListFieldResult"}}},"description":"Whether the field was deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a custom field","tags":["CRM"]},"get":{"operationId":"listCrmListFields","parameters":[{"in":"path","name":"listId","required":true,"schema":{"type":"string"}},{"in":"query","name":"objectType","required":false,"schema":{"$ref":"#/components/schemas/CrmObjectType"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmListFieldsResult"}}},"description":"Object-scoped fields plus this list's list-scoped fields."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the custom fields applicable to a list","tags":["CRM"]},"patch":{"operationId":"updateCrmListField","parameters":[{"in":"path","name":"listId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"id":{"type":"string"},"label":{"type":"string"},"options":{"items":{"$ref":"#/components/schemas/CrmCustomFieldOption"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmUpdateListFieldResult"}}},"description":"Whether the field was updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update a custom field's mutable props","tags":["CRM"]},"post":{"operationId":"createCrmListField","parameters":[{"in":"path","name":"listId","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"key":{"type":"string"},"label":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"options":{"items":{"$ref":"#/components/schemas/CrmCustomFieldOption"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"},"type":{"$ref":"#/components/schemas/CrmCustomFieldType"}},"required":["label","type"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCreateListFieldResult"}}},"description":"The created custom field."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a list-scoped custom field","tags":["CRM"]}},"/v1/crm/lo-loan-mix":{"post":{"operationId":"crmLoLoanMix","requestBody":{"content":{"application/json":{"schema":{"properties":{"dateRange":{"description":"Period key (default: last_14_months).","type":"string"},"nmls":{"description":"Bare NMLS id.","type":"string"}},"required":["nmls"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLoLoanMix"}}},"description":"Loan-type percentage breakdown + the top loan type (or null)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan-type mix (percentage + top type) for a single LO (by NMLS)","tags":["CRM"]}},"/v1/crm/lo-momentum":{"post":{"operationId":"crmLoMomentum","requestBody":{"content":{"application/json":{"schema":{"properties":{"nmls":{"description":"Bare NMLS ids (deduped, capped at 50).","items":{"type":"string"},"type":"array"}},"required":["nmls"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLoMomentum"}}},"description":"Per-NMLS recent (last 3mo) vs prior (3mo) closed-loan units."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Recent-vs-prior 3-month closed-loan units for a set of LOs (by NMLS)","tags":["CRM"]}},"/v1/crm/lo-sponsor-location":{"post":{"operationId":"crmLoSponsorLocation","requestBody":{"content":{"application/json":{"schema":{"properties":{"nmlsIds":{"description":"Bare NMLS ids (deduped, empties dropped, capped 2000).","items":{"type":"string"},"type":"array"}},"required":["nmlsIds"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLoSponsorLocation"}}},"description":"Per-NMLS current-sponsor office location (optional) + sponsored flag. Ids not on file are omitted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Current-sponsor office location + sponsored flag for a set of LOs","tags":["CRM"]}},"/v1/crm/match":{"patch":{"operationId":"linkCrmRecord","requestBody":{"content":{"application/json":{"schema":{"properties":{"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"link":{"$ref":"#/components/schemas/CrmLink"}},"required":["entityId","link"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmLinkRecordResult"}}},"description":"Whether the record was linked."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Link a record to a chosen candidate","tags":["CRM"]},"post":{"operationId":"searchCrmMatchCandidates","requestBody":{"content":{"application/json":{"schema":{"properties":{"city":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"name":{"minLength":1,"type":"string"},"state":{"type":"string"}},"required":["entityType","name"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMatchCandidates"}}},"description":"Ranked candidates (best first)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Find candidate entities to link an unmatched record to","tags":["CRM"]}},"/v1/crm/meetings":{"delete":{"operationId":"deleteCrmMeeting","parameters":[{"in":"query","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMeetingDeleted"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a meeting (and its provider event)","tags":["CRM"]},"get":{"operationId":"listCrmMeetings","parameters":[{"in":"query","name":"entityId","required":true,"schema":{"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/CrmMeetingStatus"}},{"in":"query","name":"upcoming","required":false,"schema":{"enum":["0","1"],"type":"string"}},{"in":"query","name":"reconcile","required":false,"schema":{"enum":["0","1"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMeetingList"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List meetings for a record","tags":["CRM"]},"patch":{"operationId":"updateCrmMeeting","requestBody":{"content":{"application/json":{"schema":{"properties":{"action":{"enum":["update","cancel","complete","sync"],"type":"string"},"description":{"nullable":true,"type":"string"},"endAt":{"type":"number"},"id":{"type":"string"},"inviteeEmail":{"nullable":true,"type":"string"},"inviteeName":{"nullable":true,"type":"string"},"location":{"nullable":true,"type":"string"},"provider":{"$ref":"#/components/schemas/CrmMeetingProvider"},"reason":{"$ref":"#/components/schemas/CrmMeetingCancelReason"},"recordName":{"type":"string"},"recordUrl":{"type":"string"},"startAt":{"type":"number"},"teammateUserIds":{"items":{"type":"string"},"type":"array"},"timezone":{"nullable":true,"type":"string"},"title":{"type":"string"}},"required":["id","action"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMeetingUpdated"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update, cancel, complete, or re-sync a meeting","tags":["CRM"]},"post":{"operationId":"createCrmMeeting","requestBody":{"content":{"application/json":{"schema":{"properties":{"description":{"nullable":true,"type":"string"},"endAt":{"type":"number"},"entityId":{"type":"string"},"inviteeEmail":{"nullable":true,"type":"string"},"inviteeName":{"nullable":true,"type":"string"},"listId":{"maxLength":128,"minLength":1,"type":"string"},"location":{"nullable":true,"type":"string"},"provider":{"$ref":"#/components/schemas/CrmMeetingProvider"},"recordName":{"type":"string"},"recordUrl":{"type":"string"},"startAt":{"type":"number"},"teammateUserIds":{"items":{"type":"string"},"type":"array"},"timezone":{"nullable":true,"type":"string"},"title":{"minLength":1,"type":"string"}},"required":["entityId","title","startAt","endAt"],"type":"object"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMeetingCreated"}}},"description":"Created."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a meeting (optionally syncing it to a calendar provider)","tags":["CRM"]}},"/v1/crm/meetings/reconcile":{"post":{"operationId":"reconcileCrmMeetings","requestBody":{"content":{"application/json":{"schema":{"anyOf":[{"properties":{"entityId":{"type":"string"}},"required":["entityId"],"type":"object"},{"properties":{"scope":{"enum":["user"],"type":"string"}},"required":["scope"],"type":"object"}]}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMeetingReconcileResult"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Pull calendar changes and apply them (one record, or user-wide)","tags":["CRM"]}},"/v1/crm/meetings/workspace":{"get":{"operationId":"listCrmWorkspaceMeetings","parameters":[{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/CrmMeetingStatus"}},{"description":"Restrict to one organizer; omit for anyone on my records.","in":"query","name":"organizer","required":false,"schema":{"description":"Restrict to one organizer; omit for anyone on my records.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmWorkspaceMeetingList"}}},"description":"Meetings on visible records, soonest first."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Cross-record meeting inbox for the caller's visible records","tags":["CRM"]}},"/v1/crm/members":{"get":{"operationId":"listCrmMembers","parameters":[{"in":"query","name":"objectType","required":true,"schema":{"$ref":"#/components/schemas/CrmObjectType"}},{"description":"`me` scopes to the caller's records; omit for everyone.","in":"query","name":"owner","required":false,"schema":{"description":"`me` scopes to the caller's records; omit for everyone.","enum":["me"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMembersList"}}},"description":"The visible records of the object type, newest first."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List curated CRM records of an object type","tags":["CRM"]}},"/v1/crm/org-members":{"get":{"operationId":"listCrmOrgMembers","parameters":[{"in":"query","name":"search","required":false,"schema":{"type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmOrgMemberList"}}},"description":"The active org's members (optionally searched)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List the active org's members","tags":["CRM"]}},"/v1/crm/overrides":{"get":{"operationId":"getCrmOverrides","parameters":[{"description":"Comma-separated record ids.","in":"query","name":"entityIds","required":true,"schema":{"description":"Comma-separated record ids.","example":"lo:1,lo:2","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmOverridesMap"}}},"description":"The overlay per entity id."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Batch-read record overrides","tags":["CRM"]},"patch":{"operationId":"setCrmOverride","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"field":{"$ref":"#/components/schemas/CrmOverrideField"},"value":{"anyOf":[{"type":"string"},{"$ref":"#/components/schemas/CrmOverrideOffice"}]}},"required":["entityId","entityType","field","value"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmSetOverrideResult"}}},"description":"The record's updated overlay (+ re-derived location facets)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Set a single override field on a record","tags":["CRM"]}},"/v1/crm/production-enrich/{jobId}":{"get":{"operationId":"getCrmProductionEnrichJob","parameters":[{"description":"Job id from a bulk/import add.","in":"path","name":"jobId","required":true,"schema":{"description":"Job id from a bulk/import add.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmProductionEnrichJob"}}},"description":"Job status (queued / running / completed / failed / cancelled)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get an add-time production-enrich job's status","tags":["CRM"]}},"/v1/crm/profile":{"get":{"operationId":"getCrmRecordProfile","parameters":[{"description":"The CRM record id to read.","in":"query","name":"entityId","required":true,"schema":{"description":"The CRM record id to read.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmProfile"}}},"description":"The record's aggregate profile payload."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Aggregate profile read for a CRM record","tags":["CRM"]}},"/v1/crm/recipients":{"get":{"operationId":"searchCrmEmailRecipients","parameters":[{"description":"Name or address fragment.","in":"query","name":"q","required":true,"schema":{"description":"Name or address fragment.","type":"string"}},{"in":"query","name":"limit","required":false,"schema":{"exclusiveMinimum":true,"minimum":0,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmEmailRecipientArray"}}},"description":"Matching records with a stored email address."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Typeahead search for email recipients the caller can see","tags":["CRM"]}},"/v1/crm/record-access":{"get":{"operationId":"getCrmRecordAccess","parameters":[{"description":"The record's entity id.","in":"query","name":"entityId","required":true,"schema":{"description":"The record's entity id.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordAccessFacts"}}},"description":"The resolved accessible-user set + the caller's manage capability."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found / not accessible to the caller."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"Who can access a record, and whether the caller may manage shares","tags":["CRM"]}},"/v1/crm/record-shareable-members":{"get":{"operationId":"listCrmRecordShareableMembers","parameters":[{"description":"The record's entity id.","in":"query","name":"entityId","required":true,"schema":{"description":"The record's entity id.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordShareableMemberList"}}},"description":"The org roster for the record's share picker (all members)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List the org members a record can be shared with (manage-gated)","tags":["CRM"]}},"/v1/crm/record-shares":{"delete":{"operationId":"revokeCrmRecordAccess","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"userId":{"type":"string"}},"required":["entityId","userId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRevokeRecordAccessResult"}}},"description":"Whether a share was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable (roster needed for the gate)."}},"summary":"Revoke a user's access to a record","tags":["CRM"]},"get":{"operationId":"listCrmRecordShares","parameters":[{"description":"The record's entity id.","in":"query","name":"entityId","required":true,"schema":{"description":"The record's entity id.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordShareList"}}},"description":"The per-user share grants on the record, with display."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List the direct shares on a record (+ display, canManageShares)","tags":["CRM"]},"post":{"operationId":"grantCrmRecordAccess","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"listId":{"type":"string"},"source":{"enum":["mention","manual"],"type":"string"},"userId":{"type":"string"}},"required":["entityId","userId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmGrantRecordAccessResult"}}},"description":"Whether a new share was created (idempotent)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable (roster needed for the gate)."}},"summary":"Grant a user access to a record","tags":["CRM"]}},"/v1/crm/records":{"delete":{"operationId":"deleteCrmRecord","parameters":[{"description":"The record id.","in":"query","name":"entityId","required":true,"schema":{"description":"The record id.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteRecordResult"}}},"description":"Whether a record was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove a record from the workspace CRM","tags":["CRM"]},"patch":{"operationId":"setCrmRecordOwner","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"grantAccess":{"type":"boolean"},"ownerUserId":{"nullable":true,"type":"string"}},"required":["entityId","entityType","ownerUserId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmSetOwnerResult"}}},"description":"The record's owner after the call; `needsShare` is set instead when the assignee can't see the record and the write was held."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"(Re)assign a record's working owner","tags":["CRM"]},"post":{"operationId":"createCrmRecord","requestBody":{"content":{"application/json":{"schema":{"properties":{"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"link":{"$ref":"#/components/schemas/CrmLink"},"ownerUserId":{"type":"string"}},"required":["entityId","entityType","link","display"],"type":"object"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCreateRecordResult"}}},"description":"Whether the record was newly created (vs. refreshed)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create (or refresh) a canonical record from a match","tags":["CRM"]}},"/v1/crm/records/access-request":{"get":{"operationId":"getCrmRecordAccessRequest","parameters":[{"in":"query","name":"requestId","required":true,"schema":{"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordAccessRequestInfo"}}},"description":"The pending ask, for the confirm prompt."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable (roster needed for the gate)."}},"summary":"Resolve a record access request for the owner's grant-confirm screen","tags":["CRM"]}},"/v1/crm/records/add":{"post":{"operationId":"addCrmRecord","requestBody":{"content":{"application/json":{"schema":{"properties":{"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"link":{"$ref":"#/components/schemas/CrmLink"},"listId":{"type":"string"},"note":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"}},"required":["body"],"type":"object"},"ownerUserId":{"type":"string"},"status":{"type":"string"}},"required":["entityType","entityId","link","display"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddRecordResult"}}},"description":"Whether the record was newly added + the member row."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Add a record to the CRM (and optionally a list)","tags":["CRM"]}},"/v1/crm/records/add/bulk":{"post":{"operationId":"addCrmRecordsBulk","requestBody":{"content":{"application/json":{"schema":{"properties":{"grantRecordAccessUserIds":{"items":{"type":"string"},"type":"array"},"members":{"items":{"properties":{"company":{"type":"string"},"companyType":{"type":"string"},"contacts":{"items":{"$ref":"#/components/schemas/CrmContactSeed"},"type":"array"},"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"link":{"$ref":"#/components/schemas/CrmLink"},"title":{"type":"string"}},"required":["entityType","entityId","display"],"type":"object"},"minItems":1,"type":"array"},"note":{"properties":{"body":{"type":"string"},"bodyHtml":{"nullable":true,"type":"string"}},"required":["body"],"type":"object"},"ownerUserId":{"type":"string"},"status":{"type":"string"}},"required":["members"],"type":"object"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmAddRecordsBulkResult"}}},"description":"Counts + the ids newly added."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Bulk add records to the canonical CRM (listless)","tags":["CRM"]}},"/v1/crm/records/apply-mi-updates":{"post":{"operationId":"applyCrmMiUpdates","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"updates":{"items":{"oneOf":[{"properties":{"field":{"enum":["title","company","location","city","state","zip"],"type":"string"},"store":{"enum":["override"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","field","value"],"type":"object"},{"properties":{"kind":{"enum":["email","phone","linkedin","facebook","x","instagram","youtube","zillow","realtor","website"],"type":"string"},"store":{"enum":["contact"],"type":"string"},"value":{"maxLength":2000,"minLength":1,"type":"string"}},"required":["store","kind","value"],"type":"object"}]},"minItems":1,"type":"array"}},"required":["entityId","entityType","updates"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmApplyMiUpdatesResult"}}},"description":"How many accepted fields were persisted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Apply the Market-Insights updates the user accepted","tags":["CRM"]}},"/v1/crm/records/by-nmls":{"get":{"operationId":"findCrmRecordByNmls","parameters":[{"description":"Bare NMLS id.","in":"query","name":"nmlsId","required":true,"schema":{"description":"Bare NMLS id.","minLength":1,"type":"string"}},{"description":"Comma-separated entity types to match (default: all).","in":"query","name":"entityTypes","required":false,"schema":{"description":"Comma-separated entity types to match (default: all).","example":"lo,company","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordRef"}}},"description":"The matching record ref, or null when none exists."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Find an existing CRM record by NMLS id","tags":["CRM"]}},"/v1/crm/records/connections":{"post":{"operationId":"getCrmRecordConnections","requestBody":{"content":{"application/json":{"schema":{"properties":{"branchName":{"type":"string"},"branchNmlsId":{"type":"string"},"companyName":{"type":"string"},"companyNmlsId":{"type":"string"},"entityId":{"minLength":1,"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"officeKey":{"type":"string"},"officeName":{"type":"string"},"partnerEntityIds":{"items":{"type":"string"},"type":"array"}},"required":["entityId","entityType"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordConnections"}}},"description":"In-CRM partner ids + colleagues tagged with their list names."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Relationship cross-reference for a record (in-CRM partners + colleagues)","tags":["CRM"]}},"/v1/crm/records/create":{"post":{"operationId":"createCrmManualRecord","requestBody":{"content":{"application/json":{"schema":{"properties":{"contacts":{"items":{"$ref":"#/components/schemas/CrmContactSeed"},"maxItems":30,"type":"array"},"customValues":{"additionalProperties":{"$ref":"#/components/schemas/CrmCustomValue"},"type":"object"},"display":{"$ref":"#/components/schemas/CrmDisplay"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"listId":{"type":"string"},"overrides":{"properties":{"city":{"type":"string"},"company":{"type":"string"},"companyNmlsId":{"type":"string"},"companyType":{"type":"string"},"firstName":{"type":"string"},"lastName":{"type":"string"},"location":{"type":"string"},"notes":{"type":"string"},"office":{"type":"string"},"state":{"type":"string"},"status":{"type":"string"},"title":{"type":"string"},"zip":{"type":"string"}},"type":"object"},"ownerUserId":{"type":"string"}},"required":["entityType","display"],"type":"object"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmManualRecordResult"}}},"description":"The new record's id + whether it joined the given list."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a manual (unmatched) CRM record","tags":["CRM"]}},"/v1/crm/records/decline-mi-update":{"post":{"operationId":"declineCrmMiUpdate","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"fields":{"description":"The diverging override fields to keep, e.g. `[\"company\", \"location\"]`. Batched because the review dialog can select several rows at once. Only the fields the server still sees diverging are suppressed.","items":{"maxLength":64,"minLength":1,"type":"string"},"maxItems":16,"minItems":1,"type":"array"}},"required":["entityId","entityType","fields"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeclineMiUpdateResult"}}},"description":"The subset of the requested fields that actually diverged and are now suppressed. A field absent from this list no longer disagrees with MI, so there was nothing to decline."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Keep the pinned values — suppress divergence proposals","tags":["CRM"]}},"/v1/crm/records/delete":{"post":{"operationId":"deleteCrmRecords","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityIds":{"items":{"type":"string"},"minItems":1,"type":"array"}},"required":["entityIds"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteRecordsResult"}}},"description":"Ids actually removed vs. skipped (not owned / not found)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Remove one or more records from the CRM","tags":["CRM"]}},"/v1/crm/records/describe-on-add":{"post":{"operationId":"describeCrmRecordsOnAdd","requestBody":{"content":{"application/json":{"schema":{"properties":{"created":{"items":{"properties":{"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"}},"required":["entityId","entityType"],"type":"object"},"maxItems":500,"minItems":1,"type":"array"}},"required":["created"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDescribeOnAddResult"}}},"description":"The created entity ids that need a generate-description run (cache misses this caller claimed)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Resolve descriptions for just-created records (cache-first)","tags":["CRM"]}},"/v1/crm/records/dismiss-mi-updates":{"post":{"operationId":"dismissCrmMiUpdates","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"type":"string"},"seen":{"additionalProperties":{"items":{"maxLength":512,"type":"string"},"maxItems":50,"type":"array"},"type":"object"}},"required":["entityId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDismissMiUpdatesResult"}}},"description":"Confirmation the check window was restarted. The seen-ledger is untouched."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Snooze surfaced MI updates for the check window","tags":["CRM"]}},"/v1/crm/records/generate-description":{"post":{"operationId":"generateCrmRecordDescription","requestBody":{"content":{"application/json":{"schema":{"properties":{"company":{"type":"string"},"entityId":{"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"},"location":{"type":"string"},"name":{"type":"string"},"title":{"type":"string"}},"required":["entityId","entityType"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmGenerateDescriptionResult"}}},"description":"The generated description, or null when no usable source was found."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Auto-generate a record's description from the web","tags":["CRM"]}},"/v1/crm/records/grant-access":{"post":{"operationId":"grantCrmRecordAccessRequest","requestBody":{"content":{"application/json":{"schema":{"properties":{"requestId":{"minLength":1,"type":"string"}},"required":["requestId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmGrantRecordAccessRequestResult"}}},"description":"The requester was granted access (idempotent) and the ask closed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable (roster needed for the gate)."}},"summary":"Grant a pending record access request (owner/admin, one tap)","tags":["CRM"]}},"/v1/crm/records/member-ids":{"get":{"operationId":"getCrmRecordMemberIds","parameters":[{"in":"query","name":"objectType","required":true,"schema":{"$ref":"#/components/schemas/CrmObjectType"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMemberIdsResult"}}},"description":"Every workspace record id of the object type."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List the workspace's record entity ids of an object type (ids only)","tags":["CRM"]}},"/v1/crm/records/mention-search":{"post":{"operationId":"searchCrmMentionRecords","requestBody":{"content":{"application/json":{"schema":{"properties":{"q":{"default":"","type":"string"}},"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMentionSearch"}}},"description":"The viewer-visible records matching the query (or recent)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Name-first search over visible CRM records for the mention picker","tags":["CRM"]}},"/v1/crm/records/mi-updates":{"post":{"operationId":"getCrmMiUpdates","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"maxLength":128,"minLength":1,"type":"string"},"entityType":{"$ref":"#/components/schemas/CrmEntityType"}},"required":["entityId","entityType"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmMiUpdatesResult"}}},"description":"The available per-field updates + the check timestamp (null when skipped)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Compute which Market-Insights fields differ from a record snapshot","tags":["CRM"]}},"/v1/crm/records/refresh-mirror":{"post":{"operationId":"refreshCrmRecordMirror","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"maxLength":128,"minLength":1,"type":"string"}},"required":["entityId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRefreshMirrorResult"}}},"description":"Whether the mirror moved, and the display after the attempt. Never errors on a record that cannot be refreshed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Freshen a record's mirrored Market-Insights row on demand","tags":["CRM"]}},"/v1/crm/records/request-access":{"post":{"operationId":"requestCrmRecordAccess","requestBody":{"content":{"application/json":{"schema":{"properties":{"entityId":{"minLength":1,"type":"string"},"organizationId":{"minLength":1,"type":"string"}},"required":["organizationId","entityId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordRequestAccessResult"}}},"description":"The owner was emailed, a recent request still stands, or the caller already has access."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The record has no owner/admin to notify."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Owner-roster lookup or email send failed — safe to retry."}},"summary":"Ask a record's owner to share it (membership-gated, notify-only)","tags":["CRM"]}},"/v1/crm/records/search":{"post":{"operationId":"searchCrmRecords","requestBody":{"content":{"application/json":{"schema":{"properties":{"listId":{"description":"Scope to one list's members; omit for the full CRM.","type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"},"q":{"description":"Free-text query.","type":"string"}},"required":["objectType","q"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRecordSearchResult"}}},"description":"The matching namespaced entity ids."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Free-text search over CRM records","tags":["CRM"]}},"/v1/crm/reports/activity":{"get":{"description":"Human actions only, attributed to the actor (never the record owner). `previousTotals` covers the equal-length period immediately before `from`. Ratios (connect rate, show rate, win rate) are client-side divisions.","operationId":"getCrmActivityReport","parameters":[{"description":"Inclusive start of the range (epoch ms).","in":"query","name":"from","required":false,"schema":{"description":"Inclusive start of the range (epoch ms).","minimum":0,"nullable":true,"type":"integer"}},{"description":"Exclusive end of the range (epoch ms).","in":"query","name":"to","required":false,"schema":{"description":"Exclusive end of the range (epoch ms).","minimum":0,"nullable":true,"type":"integer"}},{"description":"Omit = the caller's own metrics. `team` = one entry per workspace member (owner/admin only). A member id = that member (owner/admin only).","in":"query","name":"userId","required":false,"schema":{"description":"Omit = the caller's own metrics. `team` = one entry per workspace member (owner/admin only). A member id = that member (owner/admin only).","type":"string"}},{"description":"IANA zone the day buckets are cut in (default America/New_York).","in":"query","name":"tz","required":false,"schema":{"description":"IANA zone the day buckets are cut in (default America/New_York).","type":"string"}},{"description":"Scope every metric to that list's members and vocabulary. A 1-element alias for `listIds` — do not pass both.","in":"query","name":"listId","required":false,"schema":{"description":"Scope every metric to that list's members and vocabulary. A 1-element alias for `listIds` — do not pass both.","type":"string"}},{"description":"CSV of list ids to scope to (union, not intersection — a record that's a member of more than one selected list is still counted once in every distinct-record metric and once per day-bucket). A list id the caller can't see is silently dropped, not an error. Do not pass alongside `listId`.","in":"query","name":"listIds","required":false,"schema":{"description":"CSV of list ids to scope to (union, not intersection — a record that's a member of more than one selected list is still counted once in every distinct-record metric and once per day-bucket). A list id the caller can't see is silently dropped, not an error. Do not pass alongside `listId`.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmActivityReportResult"}}},"description":"The activity report."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Per-user, per-day activity counts with previous-period totals","tags":["CRM"]}},"/v1/crm/reports/outcomes":{"get":{"description":"Cohort = records that hit the event in [from, to). Win/loss resolves through each status option's `outcome` (seed ids `won`/`lost` by convention). `pipeline` is a current snapshot and ignores the range.","operationId":"getCrmOutcomesReport","parameters":[{"description":"Inclusive start of the range (epoch ms).","in":"query","name":"from","required":false,"schema":{"description":"Inclusive start of the range (epoch ms).","minimum":0,"nullable":true,"type":"integer"}},{"description":"Exclusive end of the range (epoch ms).","in":"query","name":"to","required":false,"schema":{"description":"Exclusive end of the range (epoch ms).","minimum":0,"nullable":true,"type":"integer"}},{"description":"Omit = the caller's own metrics. `team` = one entry per workspace member (owner/admin only). A member id = that member (owner/admin only).","in":"query","name":"userId","required":false,"schema":{"description":"Omit = the caller's own metrics. `team` = one entry per workspace member (owner/admin only). A member id = that member (owner/admin only).","type":"string"}},{"description":"IANA zone the day buckets are cut in (default America/New_York).","in":"query","name":"tz","required":false,"schema":{"description":"IANA zone the day buckets are cut in (default America/New_York).","type":"string"}},{"description":"Scope every metric to that list's members and vocabulary. A 1-element alias for `listIds` — do not pass both.","in":"query","name":"listId","required":false,"schema":{"description":"Scope every metric to that list's members and vocabulary. A 1-element alias for `listIds` — do not pass both.","type":"string"}},{"description":"CSV of list ids to scope to (union, not intersection — a record that's a member of more than one selected list is still counted once in every distinct-record metric and once per day-bucket). A list id the caller can't see is silently dropped, not an error. Do not pass alongside `listId`.","in":"query","name":"listIds","required":false,"schema":{"description":"CSV of list ids to scope to (union, not intersection — a record that's a member of more than one selected list is still counted once in every distinct-record metric and once per day-bucket). A list id the caller can't see is silently dropped, not an error. Do not pass alongside `listId`.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmOutcomesReportResult"}}},"description":"The outcomes report."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Cohort outcomes: wins/losses, volume onboarded, milestones, effort per win, pipeline","tags":["CRM"]}},"/v1/crm/request-access":{"post":{"operationId":"requestCrmAccess","requestBody":{"content":{"application/json":{"schema":{"properties":{"organizationId":{"minLength":1,"type":"string"}},"required":["organizationId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmRequestAccessResult"}}},"description":"The owner(s) were emailed, or a recent request still stands."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"422":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"The org has no billing owner to notify."},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Owner-roster lookup or email send failed — safe to retry."}},"summary":"Ask the org owner(s) to enable the CRM (membership-gated)","tags":["CRM"]}},"/v1/crm/similar-originators":{"post":{"operationId":"crmSimilarOriginators","requestBody":{"content":{"application/json":{"schema":{"properties":{"dateRange":{"description":"Period key (default: last_14_months).","type":"string"},"partnerNmlsIds":{"description":"Partner LO NMLS ids to rank (deduped, self-excluded, capped at 200).","items":{"type":"string"},"type":"array"},"top":{"description":"Max scored rows to return (1–50, default 25).","type":"number"},"viewerNmls":{"description":"The viewing LO's bare NMLS id.","type":"string"},"weights":{"description":"Live tuning overrides for the tx/loan/size blend (clamped to ≥ 0).","properties":{"loan":{"type":"number"},"size":{"type":"number"},"tx":{"type":"number"}},"type":"object"}},"required":["viewerNmls","partnerNmlsIds"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmSimilarOriginators"}}},"description":"Scored + sorted partner LOs (score, per-component similarity, shared highlight)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Rank an agent's LO partners by product-mix + size similarity to a viewing LO","tags":["CRM"]}},"/v1/crm/tasks":{"delete":{"operationId":"deleteCrmTask","requestBody":{"content":{"application/json":{"schema":{"properties":{"id":{"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTaskDeleted"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a task","tags":["CRM"]},"get":{"operationId":"listCrmTasks","parameters":[{"in":"query","name":"entityId","required":false,"schema":{"type":"string"}},{"in":"query","name":"assigneeUserId","required":false,"schema":{"type":"string"}},{"in":"query","name":"owner","required":false,"schema":{"enum":["me"],"type":"string"}},{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/CrmTaskStatus"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTaskList"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List tasks for a record or for an assignee","tags":["CRM"]},"patch":{"operationId":"updateCrmTask","requestBody":{"content":{"application/json":{"schema":{"properties":{"action":{"enum":["calendar"],"type":"string"},"allDay":{"type":"boolean"},"assigneeUserId":{"type":"string"},"body":{"nullable":true,"type":"string"},"dueAt":{"nullable":true,"type":"number"},"grantAccess":{"type":"boolean"},"id":{"type":"string"},"provider":{"enum":["google","microsoft",null],"nullable":true,"type":"string"},"recordName":{"type":"string"},"recordUrl":{"type":"string"},"status":{"enum":["completed","cancelled"],"type":"string"},"title":{"type":"string"}},"required":["id"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTaskUpdated"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Edit a task, or transition it to completed/cancelled","tags":["CRM"]},"post":{"operationId":"createCrmTask","requestBody":{"content":{"application/json":{"schema":{"properties":{"allDay":{"type":"boolean"},"assigneeUserId":{"type":"string"},"body":{"nullable":true,"type":"string"},"dueAt":{"nullable":true,"type":"number"},"entityId":{"type":"string"},"grantAccess":{"type":"boolean"},"listId":{"maxLength":128,"minLength":1,"type":"string"},"title":{"minLength":1,"type":"string"}},"required":["entityId","title"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTaskCreated"}}},"description":"Success."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a task on a record","tags":["CRM"]}},"/v1/crm/tasks/workspace":{"get":{"operationId":"listCrmWorkspaceTasks","parameters":[{"in":"query","name":"status","required":false,"schema":{"$ref":"#/components/schemas/CrmTaskStatus"}},{"description":"Restrict to one assignee; omit for anyone on my records.","in":"query","name":"assignee","required":false,"schema":{"description":"Restrict to one assignee; omit for anyone on my records.","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmWorkspaceTaskList"}}},"description":"Tasks on visible records, due-soonest first."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Cross-record task inbox for the caller's visible records","tags":["CRM"]}},"/v1/crm/templates":{"get":{"operationId":"listCrmTemplates","parameters":[{"in":"query","name":"objectType","required":false,"schema":{"$ref":"#/components/schemas/CrmObjectType"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTemplateList"}}},"description":"Templates owned by or shared with the caller (+ owner display)."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"List attribute templates the caller can load","tags":["CRM"]},"post":{"operationId":"createCrmTemplate","requestBody":{"content":{"application/json":{"schema":{"properties":{"fields":{"items":{"properties":{"config":{"additionalProperties":{"nullable":true},"nullable":true,"type":"object"},"key":{"type":"string"},"label":{"type":"string"},"options":{"items":{"properties":{"color":{"type":"string"},"id":{"type":"string"},"label":{"type":"string"}},"required":["id","label"],"type":"object"},"nullable":true,"type":"array"},"sortOrder":{"type":"number"},"type":{"enum":["text","number","currency","date","select","multiselect","url","rating","checkbox","status","tags"],"type":"string"}},"required":["key","label","type"],"type":"object"},"type":"array"},"fromListId":{"type":"string"},"name":{"type":"string"},"objectType":{"$ref":"#/components/schemas/CrmObjectType"}},"required":["name"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmCreateTemplateResult"}}},"description":"The created template with its captured fields."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Create a template (optionally captured from a list)","tags":["CRM"]}},"/v1/crm/templates/{id}":{"delete":{"operationId":"deleteCrmTemplate","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmDeleteTemplateResult"}}},"description":"Whether the template row was deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a template (its fields + shares cascade)","tags":["CRM"]},"get":{"operationId":"getCrmTemplate","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTemplate"}}},"description":"The template, or null when missing / not accessible."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Load one template with its fields","tags":["CRM"]},"patch":{"operationId":"updateCrmTemplate","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"name":{"type":"string"}},"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmUpdateTemplateResult"}}},"description":"Whether the template row was updated."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Rename a template","tags":["CRM"]}},"/v1/crm/templates/{id}/shares":{"delete":{"operationId":"unshareCrmTemplate","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}},{"in":"query","name":"userId","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmUnshareTemplateResult"}}},"description":"Whether a grant was removed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Revoke a teammate's template grant","tags":["CRM"]},"get":{"operationId":"getCrmTemplateShares","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmTemplateShareList"}}},"description":"Owner display + caller canManage + enriched grantees."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Template not found / not accessible to the caller."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Auth service unavailable."}},"summary":"A template's share panel (owner display, canManage, grantees)","tags":["CRM"]},"post":{"operationId":"shareCrmTemplate","parameters":[{"in":"path","name":"id","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"properties":{"userId":{"type":"string"}},"required":["userId"],"type":"object"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CrmShareTemplateResult"}}},"description":"Whether a new grant was created."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Grant a teammate load access to a template","tags":["CRM"]}},"/v1/instant-search":{"post":{"description":"Fast typeahead/autocomplete search across agents, originators, companies, and offices. Returns top matches per entity type. A bare NMLS ID resolves directly to its originator, company, or branch — including an originator who is in the NMLS registry with no production record yet (returned with `hasScoredData: false`). Use this for quick name lookups, not for filtered searches (use the entity-specific list endpoints for those). If you already have an entity ID, prefer getOriginator / getCompany / getBranch.","operationId":"instantSearch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstantSearchRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/InstantSearchResponse"}}},"description":"Search results grouped by entity"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeiliUnavailable"}}},"description":"Search backend not configured"}},"summary":"Instant multi-entity typeahead search","tags":["Search"]}},"/v1/integrations/hubspot/push":{"post":{"description":"Sends the given Model Match records into the HubSpot account you have connected, using the field mapping your workspace configured. Existing records are matched and updated rather than duplicated, so sending the same list twice does not create it twice. Every id you send comes back with an outcome — some records failing is normal and does not fail the rest. At most 100 records per request; send larger lists in batches. There is no undo: use `dryRun` first to see exactly what would be written. Charged per record actually written, at the same rate as fetching that record.","operationId":"pushToHubspot","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotPushRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotPushResponse"}}},"description":"Per-record outcome. Check `summary` for what landed."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotError"}}},"description":"Validation or setup mismatch"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"402":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotPaymentRequired"}}},"description":"Not enough credits to send this many records"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"No active workspace"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotError"}}},"description":"Refused before writing anything — not connected, wrong HubSpot account, or a mapping that cannot be applied safely"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotError"}}},"description":"HubSpot or billing could not be reached. Nothing was sent."}},"summary":"Send records to your HubSpot account","tags":["Integrations"]}},"/v1/integrations/hubspot/status":{"get":{"description":"Reports whether your HubSpot account is connected, which record types your workspace has set up to send, and whether the connected account is the one that setup was built for. Read-only — call it before offering to send anything.","operationId":"getHubspotPushStatus","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/HubspotStatusResponse"}}},"description":"Readiness per record type"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Check whether records can be sent to HubSpot","tags":["Integrations"]}},"/v1/lenders":{"post":{"description":"Search and list normalized lender names/identities with filters — resolves raw or variant lender names to canonical lender records. Use it to look up a lender by name or reconcile lender-name variants to a single canonical entity. If you only need how many lenders match and not the records themselves, send the same request body to `countLenders`.","operationId":"listLenders","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LenderListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LenderListResponse"}}},"description":"Paginated list of lenders"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search lenders with filters","tags":["Lenders"]}},"/v1/lenders/count":{"post":{"description":"Return the exact number of lenders matching the given filters. Accepts the same request body as `listLenders` (pagination and sort are ignored). Use this when you only need a total; to get the matching lenders themselves, send the same request body to `listLenders`.","operationId":"countLenders","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LenderListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching lenders"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count lenders matching filters","tags":["Lenders"],"x-mm-records-via":"listLenders"}},"/v1/lenders/{id}":{"get":{"operationId":"getLender","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LenderDetailResponse"}}},"description":"Lender detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Lender not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get lender by ID","tags":["Lenders"]}},"/v1/lenders/{id}/breakdowns/cities":{"post":{"description":"Ranks the cities this lender's loans were secured in, by volume. Labels are Title Case so they match the city breakdowns on every other entity.","operationId":"lenderCities","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this lender's loans by cities"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"City volume breakdown across this lender's loans","tags":["Lenders"]}},"/v1/lenders/{id}/breakdowns/companies":{"post":{"description":"Ranks the mortgage companies whose loans funded through this lender, by volume. Each label is the company's NMLS ID (with the company name resolved alongside it where available), so it chains straight into `GET /v1/companies/{nmlsId}`. Loans with no identified company are excluded.","operationId":"lenderCompanies","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this lender's loans by companies"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Mortgage companies that send business to this lender","tags":["Lenders"]}},"/v1/lenders/{id}/breakdowns/counties":{"post":{"description":"Ranks the counties this lender's loans were secured in, by volume. Labels are county codes on this surface — the same axis every other county breakdown uses, so the two are directly comparable.","operationId":"lenderCounties","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this lender's loans by counties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"County volume breakdown across this lender's loans","tags":["Lenders"]}},"/v1/lenders/{id}/breakdowns/originators":{"post":{"description":"Ranks the loan officers whose loans funded through this lender, by volume. Each label is the loan officer's NMLS ID, so it chains straight into `GET /v1/originators/{nmlsId}`. Loans with no identified loan officer are excluded rather than collapsed into one unnavigable bucket.","operationId":"lenderOriginators","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this lender's loans by originators"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers who send business to this lender","tags":["Lenders"]}},"/v1/lenders/{id}/breakdowns/states":{"post":{"description":"Ranks the states this lender's loans were secured in, by volume. Labels are two-letter state abbreviations.","operationId":"lenderStates","parameters":[{"description":"Lender canonical-name ID","in":"path","name":"id","required":true,"schema":{"description":"Lender canonical-name ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of this lender's loans by states"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"State volume breakdown across this lender's loans","tags":["Lenders"]}},"/v1/loans":{"post":{"description":"Search and list individual public-record mortgage and deed loan records — one row per loan (purchase, refinance, origination). Filter by geography (state, county, city, zip), lender, originator, loan amount, interest rate, loan type/purpose, and recording date, with sorting and cursor pagination. This is the discrete per-loan record search: use it to find specific loans or build a filtered loan list. Each row carries the property address, loan terms, the originating loan officer, and `borrowerStatus` — so this is also how you pull a loan officer's own funded production (\"my closed loans\", \"my past clients\", \"my book of business\"): filter by `originator` (their NMLS id), and add `borrowerStatus` for borrowers still in the home — that is the five current-owner codes (`Current`, `R_CWCLO`, `R_CWNLO`, `E_CWCLO`, `E_CWNLO`), NOT `\"Current\"` alone, which omits everyone who has since refinanced. That is market data, not CRM data — it does not require the loan officer to have added anything to a CRM workspace. (For aggregate market rates and volumes use the market search; for one loan by its ID use the loan detail endpoint.) If you only need how many loans match and not the records themselves, send the same request body to `countLoans`.","operationId":"listLoans","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListResponse"}}},"description":"Paginated list of loans"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search individual loan records with filters","tags":["Loans"]}},"/v1/loans/analytics/chart":{"post":{"description":"Buckets the filtered loans by `slice` and ranks them by `measure`, descending. Party slices (`originator`, `broker`, `loanCompany`) are pageable: send `size` (1–1000) and follow `nextCursor` via `after` to walk the whole ranking, with `total` giving the (approximate) number of distinct parties. Other slices return their fixed top-N. `period` accepts rolling windows (`last30Days`, `last60Days`, `last90Days`, `previousMonth`, `currentMonth`) resolved in UTC; `/loans/analytics/summary` with the same filters and period returns the matching population totals.","operationId":"loansAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data. Money measures (`volume`, `avgSalePrice`, `avgListPrice`) are sentinel-guarded. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart data (measure × slice)","tags":["Loans"]}},"/v1/loans/analytics/summary":{"post":{"operationId":"loansAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleSummaryResponse"}}},"description":"Current + previous-period summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Market summary with previous-period comparison","tags":["Loans"]}},"/v1/loans/analytics/time-series":{"post":{"operationId":"loansAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Time-series with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Volume / units over time","tags":["Loans"]}},"/v1/loans/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching loans document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/loans/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.loans` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitLoansBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/LoanListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.loans` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for loans","tags":["Loans"]}},"/v1/loans/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running loans delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/loans/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelLoansBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/loans/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/loans/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for loans","tags":["Loans"]},"get":{"operationId":"getLoansBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/loans/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/loans/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for loans","tags":["Loans"]}},"/v1/loans/count":{"post":{"description":"Return the exact number of loans matching the given filters. Accepts the same request body as `listLoans` (pagination and sort are ignored). Use this when you only need a total; to get the matching loans themselves, send the same request body to `listLoans`.","operationId":"countLoans","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching loans"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count loans matching filters","tags":["Loans"],"x-mm-records-via":"listLoans"}},"/v1/loans/{id}":{"get":{"operationId":"getLoan","parameters":[{"description":"Loan ID","in":"path","name":"id","required":true,"schema":{"description":"Loan ID","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanDetailResponse"}}},"description":"Loan detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Loan not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get loan by ID","tags":["Loans"]}},"/v1/loans/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"loanRelated","parameters":[{"description":"Loan id","in":"path","name":"id","required":true,"schema":{"description":"Loan id","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["agents","companies","originators","properties","sales"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/locations/retrieve/{mapboxId}":{"get":{"description":"Retrieve normalized location details (city, state, county, zip, coordinates) for a suggestion ID from `suggestLocations`. A location dictionary id resolves from Model Match's own data and echoes back its `id`; any other id resolves through Mapbox.","operationId":"retrieveLocation","parameters":[{"description":"Mapbox suggestion ID","in":"path","name":"mapboxId","required":true,"schema":{"description":"Mapbox suggestion ID","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationRetrieveResponse"}}},"description":"Normalized location details"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Retrieve normalized location details","tags":["Locations"]}},"/v1/locations/suggest":{"get":{"description":"Autocomplete location search. Cities and counties come from Model Match's own location dictionary and carry an `id` (e.g. `city_mo_saint-louis`) that city / county filters accept — including for places our data spells differently than a mapping provider does. Street addresses come from Mapbox. Use the `mapbox_id` from any suggestion with `retrieveLocation` to get normalized geographic details and coordinates.","operationId":"suggestLocations","parameters":[{"description":"Search text","in":"query","name":"q","required":true,"schema":{"description":"Search text","minLength":1,"type":"string"}},{"description":"Max results (1-10, default 5)","in":"query","name":"limit","required":false,"schema":{"default":5,"description":"Max results (1-10, default 5)","maximum":10,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LocationSuggestResponse"}}},"description":"Location suggestions"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Autocomplete location search","tags":["Locations"]}},"/v1/market":{"post":{"description":"Search aggregated loan origination market data. Filterable dimensions cover geography (state, county, zip), product (loan purpose / type / amortization), borrower demographics, and loan numerics.","operationId":"listMarket","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketListResponse"}}},"description":"Paginated list of market records"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search aggregated market data with filters","tags":["Market"]}},"/v1/market/analytics/chart":{"post":{"operationId":"marketAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data with measure/slice breakdown"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Market measure by dimension breakdown","tags":["Market"]}},"/v1/market/analytics/summary":{"post":{"operationId":"marketAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketSummaryResponse"}}},"description":"16 market metrics + previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Market summary (volume, units, rate, loan amount, credit score, LTV, DTI, income, etc.) with previous-period comparison","tags":["Market"]}},"/v1/market/analytics/time-series":{"post":{"operationId":"marketAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketTimeSeriesResponse"}}},"description":"Time series with previous-period comparison. Each bucket carries `volume`, `units`, and `measureValue` for the requested `measure`. With `forecast` in the request, a `forecast` block is appended."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastError"}}},"description":"Validation error. With `forecast`, `code` says which rule tripped: non-monthly interval, an average measure, or under 24 months of history."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ForecastError"}}},"description":"Only with `forecast`: the forecast service is unreachable or not configured for this stage. The history itself is fine — retry without `forecast` for an immediate answer."}},"summary":"Market metrics over time","tags":["Market"]}},"/v1/market/community-lending":{"post":{"description":"The aggregate Community Lending profile of the originations matching your filters: the share that landed in low- or moderate-income neighborhoods, the CRA-eligible share, the distribution across the four neighborhood income bands, and the majority-minority neighborhood share. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100. This is a MARKET-LEVEL view only — the underlying origination data carries no lender, loan officer or borrower identity, and no figure here is attributable to one. Every share is reported next to the count it is a share of, because the three designations have three different coverage levels; read the denominator before comparing markets.","operationId":"marketCommunityLending","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketCommunityLendingRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MarketCommunityLendingResponse"}}},"description":"Community Lending mix, optionally sliced by dimension"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Community Lending mix of a market's originations","tags":["Market"]}},"/v1/market/movement/activity":{"get":{"description":"Monthly series of newly licensed loan officers, loan officers with an open employment at month end, and loan officers who left the industry (no open employment; last one ended that month). `becameInactive` (license authorization lapses) is not available and is always null. `all_time` charts the last 60 months. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementActivity","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementActivity"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Monthly NMLS activity: newly licensed, active, leaving","tags":["Market"]}},"/v1/market/movement/by-state":{"get":{"description":"Loan officers who changed companies in the window, grouped by state (all states) and city (top `limit`), each with the company that gained the most of them. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementByState","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"City rows to return (default 25, max 100). All states are always returned.","in":"query","name":"limit","required":false,"schema":{"description":"City rows to return (default 25, max 100). All states are always returned.","maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementByState"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officer movement by state and city","tags":["Market"]}},"/v1/market/movement/cohort-payoff":{"get":{"description":"For loan officers who moved in the window (default last 24 months), annualized production at the previous employer vs the new one, bucketed by pre-move tier (Low <25, Mid 25–99, High 100+ units/yr). Each side is annualized over the months actually spent there inside a trailing 24-month production window; movers with fewer than `windowMonths` months on either side are excluded. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementCohortPayoff","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"Minimum months a mover must have on EACH side of the move inside the 24-month production window (default 3).","in":"query","name":"windowMonths","required":false,"schema":{"description":"Minimum months a mover must have on EACH side of the move inside the 24-month production window (default 3).","enum":["3","6","12"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementCohortPayoff"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Did the move pay off? Production before vs after moving","tags":["Market"]}},"/v1/market/movement/most-gained":{"get":{"description":"Companies ranked by loan officers gained in the window (or by net = gained − lost with `rankBy=net`). Each row carries gained, lost and net, plus the trailing-14-month production of the loan officers on the ranked side. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementMostGained","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"`count` (default) ranks by LOs gained (most-gained) or lost (most-lost); `net` ranks by gained − lost (descending for most-gained, ascending for most-lost).","in":"query","name":"rankBy","required":false,"schema":{"description":"`count` (default) ranks by LOs gained (most-gained) or lost (most-lost); `net` ranks by gained − lost (descending for most-gained, ascending for most-lost).","enum":["count","net"],"type":"string"}},{"description":"Rows to return (default 10, max 100).","in":"query","name":"limit","required":false,"schema":{"description":"Rows to return (default 10, max 100).","maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementCompanies"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Companies that gained the most loan officers","tags":["Market"]}},"/v1/market/movement/most-lost":{"get":{"description":"Companies ranked by loan officers lost in the window (or by net = gained − lost with `rankBy=net`). Each row carries gained, lost and net, plus the trailing-14-month production of the loan officers on the ranked side. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementMostLost","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"`count` (default) ranks by LOs gained (most-gained) or lost (most-lost); `net` ranks by gained − lost (descending for most-gained, ascending for most-lost).","in":"query","name":"rankBy","required":false,"schema":{"description":"`count` (default) ranks by LOs gained (most-gained) or lost (most-lost); `net` ranks by gained − lost (descending for most-gained, ascending for most-lost).","enum":["count","net"],"type":"string"}},{"description":"Rows to return (default 10, max 100).","in":"query","name":"limit","required":false,"schema":{"description":"Rows to return (default 10, max 100).","maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementCompanies"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Companies that lost the most loan officers","tags":["Market"]}},"/v1/market/movement/movers":{"get":{"description":"The loan officers who moved to a new company in the window, with previous and new employer, move date, current location and production. `sort=volume` returns the highest producers who moved (notable moves); `sort=date` pages every move newest first. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementMovers","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"Destination company.","in":"query","name":"companyNmlsId","required":false,"schema":{"description":"Destination company.","type":"string"}},{"description":"Previous company.","in":"query","name":"fromCompanyNmlsId","required":false,"schema":{"description":"Previous company.","type":"string"}},{"description":"`date` (default): most recent moves first, one row per move. `volume`: the highest-producing movers first (trailing 14 months), one row per loan officer — scans the top producers, so `total` is null.","in":"query","name":"sort","required":false,"schema":{"description":"`date` (default): most recent moves first, one row per move. `volume`: the highest-producing movers first (trailing 14 months), one row per loan officer — scans the top producers, so `total` is null.","enum":["date","volume"],"type":"string"}},{"in":"query","name":"page","required":false,"schema":{"maximum":100,"minimum":1,"type":"integer"}},{"description":"Rows to return (default 25, max 100).","in":"query","name":"limit","required":false,"schema":{"description":"Rows to return (default 25, max 100).","maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementMovers"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officers who changed companies","tags":["Market"]}},"/v1/market/movement/rankings":{"get":{"description":"The top 100 loan officers for a calendar year by total volume, units, or FHA / VA / purchase / refinance volume, with current employer and retail / banker / broker type. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementRankings","parameters":[{"description":"Ranking metric (default `total_volume`).","in":"query","name":"subcategory","required":false,"schema":{"description":"Ranking metric (default `total_volume`).","enum":["total_volume","most_units","top_fha","top_va","top_purchase","top_refinance"],"type":"string"}},{"description":"Calendar year to rank (default: last year).","in":"query","name":"year","required":false,"schema":{"description":"Calendar year to rank (default: last year).","pattern":"^\\d{4}$","type":"string"}},{"in":"query","name":"page","required":false,"schema":{"maximum":4,"minimum":1,"type":"integer"}},{"description":"Rows to return (default 25, max 100).","in":"query","name":"limit","required":false,"schema":{"description":"Rows to return (default 25, max 100).","maximum":100,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementRankings"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Top-100 loan officer rankings for a year","tags":["Market"]}},"/v1/market/movement/stats":{"get":{"description":"Period totals of loan-officer movement: company joins, company-to-company transitions, complete company departures, industry exits, newly licensed loan officers, the working head-count at both ends of the window and its net change, plus the trailing-14-month production of the loan officers who moved. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementStats","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementStats"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loan officer movement totals for a period","tags":["Market"]}},"/v1/market/movement/transitions":{"get":{"description":"The largest company-to-company flows in the window: how many loan officers moved from each previous employer to each new one. Filter to one company (either side) with `companyNmlsId`. A move is dated by the loan officer's FIRST record at the new company; a loan officer licensed in several states counts once per company. Location filters use the loan officer's CURRENT NMLS location. Results refresh weekly. A response not ready within 25 s answers `202` (`MovementComputing`): repeat the same request after `retryAfterMs`.","operationId":"marketMovementTransitions","parameters":[{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","in":"query","name":"dateRange","required":false,"schema":{"description":"Reporting window. `last_N_months` = the N most recent COMPLETED calendar months (the current month is excluded); `year_to_date` = Jan 1 through the end of last month; `YYYY` (or `fy_YYYY`) = that calendar year; `all_time`. Default `last_12_months`.","example":"last_12_months","pattern":"^(?:last_\\d{1,3}_months|year_to_date|all_time|(?:fy_|fiscal_)?\\d{4})$","type":"string"}},{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","in":"query","name":"state","required":false,"schema":{"description":"Two-letter state. Matches the loan officer's CURRENT NMLS location, not where they were when they moved.","example":"TX","pattern":"^[A-Za-z]{2}$","type":"string"}},{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","in":"query","name":"states","required":false,"schema":{"description":"Comma-separated two-letter states (e.g. a region). ORed; combined with `state` when both are sent.","example":"WA,OR,ID","pattern":"^[A-Za-z]{2}(?:,[A-Za-z]{2})*$","type":"string"}},{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","in":"query","name":"city","required":false,"schema":{"description":"Exact city name of the loan officer's current NMLS location. Pair with `state`.","maxLength":100,"minLength":1,"type":"string"}},{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","in":"query","name":"companyCategory","required":false,"schema":{"description":"Comma-separated company categories (`BANK`, `CU`, `OTHER`) applied to the company whose roster changed — the destination for arrivals, the company left for departures.","example":"BANK,CU","pattern":"^(?:BANK|CU|OTHER)(?:,(?:BANK|CU|OTHER))*$","type":"string"}},{"description":"Only flows into or out of this company.","in":"query","name":"companyNmlsId","required":false,"schema":{"description":"Only flows into or out of this company.","type":"string"}},{"description":"Rows to return (default 25, max 200).","in":"query","name":"limit","required":false,"schema":{"description":"Rows to return (default 25, max 200).","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementTransitions"}}},"description":"OK"},"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MovementComputing"}}},"description":"Still computing — poll the same request after `retryAfterMs`. See `MovementComputing`.","headers":{"Retry-After":{"description":"Seconds to wait before retrying.","required":true,"schema":{"description":"Seconds to wait before retrying.","example":"5","type":"string"}}}},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Company-to-company loan officer flows","tags":["Market"]}},"/v1/me":{"get":{"description":"Identity, active organization + membership role, and how the caller authenticated.\n\nExtended profile fields (`nmlsId`, `jobRole`, the contact-card block) are resolved for every caller type — session-cookie, API-key, and OAuth-bearer alike. `auth.profileResolved` is `true` on any successful read; it is retained for compatibility and no longer varies by the credential the caller presented.","operationId":"getMe","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}},"description":"The caller's account"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountServiceUnavailable"}}},"description":"Account service unavailable"}},"summary":"Get the current caller's account","tags":["Me"]},"patch":{"description":"Partial update — send only the fields that change; `null` clears one. Returns the account in the same shape as `GET /v1/me`.\n\n`email` is NOT updatable here: changing it runs a verification flow. Sending it is a 400, not a silent no-op.","operationId":"updateMe","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeUpdateRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeResponse"}}},"description":"The updated account"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountServiceUnavailable"}}},"description":"Account service unavailable"}},"summary":"Update the current caller's profile","tags":["Me"]}},"/v1/me/credits":{"get":{"description":"Balance split by bucket (cycle allowance, purchased on-demand, personal), the per-cycle allowance and on-demand unit price, and ledger totals over a window.\n\nThe window defaults to the current calendar month to date (UTC). Figures are for the caller's own membership in their active organization — the same organization the API meters requests against.","operationId":"getMeCredits","parameters":[{"description":"Usage window start (YYYY-MM-DD, inclusive)","in":"query","name":"startDate","required":false,"schema":{"description":"Usage window start (YYYY-MM-DD, inclusive)","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}},{"description":"Usage window end (YYYY-MM-DD, inclusive)","in":"query","name":"endDate","required":false,"schema":{"description":"Usage window end (YYYY-MM-DD, inclusive)","pattern":"^\\d{4}-\\d{2}-\\d{2}$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MeCreditsResponse"}}},"description":"Credit balance and usage"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountServiceUnavailable"}}},"description":"Account service unavailable"}},"summary":"Get the caller's credit balance and usage","tags":["Me"]}},"/v1/me/plan":{"get":{"description":"The active organization's resolved plan (with its limit map), the subscription status backing it, and the plan grants attached to the organization and to the user.\n\n`plan` is null when the workspace has no active, trialing, or past-due subscription. No billing details (invoices, payment methods) are exposed.","operationId":"getMePlan","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/MePlanResponse"}}},"description":"The caller's plan"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AccountServiceUnavailable"}}},"description":"Account service unavailable"}},"summary":"Get the caller's current plan","tags":["Me"]}},"/v1/offices":{"post":{"description":"NOT NMLS mortgage branches — use `/branches` for those. Returns office name, address, agent count, coordinates, and office-level production for the selected period. Default sort is by agent count descending. If you only need how many offices match and not the records themselves, send the same request body to `countOffices`.","operationId":"listOffices","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfficeListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfficeListResponse"}}},"description":"Paginated list of offices"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search real-estate offices with filters","tags":["Offices"]}},"/v1/offices/agents":{"post":{"operationId":"officeAgents","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfficeAgentsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/AgentListResponse"}}},"description":"Paginated list of agents at the office"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Agents at an office","tags":["Offices"]}},"/v1/offices/count":{"post":{"description":"Return the exact number of offices matching the given filters. Accepts the same request body as `listOffices` (pagination and sort are ignored). Use this when you only need a total; to get the matching offices themselves, send the same request body to `listOffices`.","operationId":"countOffices","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfficeListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching offices"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count offices matching filters","tags":["Offices"],"x-mm-records-via":"listOffices"}},"/v1/offices/{id}":{"get":{"operationId":"getOffice","parameters":[{"description":"Office key (mm_office_key)","in":"path","name":"id","required":true,"schema":{"description":"Office key (mm_office_key)","type":"string"}},{"description":"Period for production metrics (default: last12Months)","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for production metrics (default: last12Months)"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OfficeDetailResponse"}}},"description":"Office detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Office not found"}},"summary":"Get office by key with office-level production","tags":["Offices"]}},"/v1/originators":{"post":{"description":"Search and list individual loan originators (LOs — NMLS-registered mortgage loan officers) with filters — one row per originator. Filter by name, NMLS ID, location (state, city), employer/company, and production metrics (loan volume, units, product mix), with sorting and cursor pagination. LOCATION SEMANTICS: the state/city filters match an originator's PRODUCTION GEOGRAPHY — the markets where they actually originated loans in the selected period — not where their office or employer sits. An LO who lends across several markets matches a filter for ANY of those markets, while the `state`/`city` returned on each row reflect only their PRIMARY (highest-volume) market. So a search for city \"Long Beach\" can return an LO whose displayed location is a different city/state (e.g. their top market is in Arizona) — they still originated loans in Long Beach, it just isn't their #1 market. To rank originators by their volume within a specific market, sort by volume after filtering, or use the per-originator city/county/state breakdown endpoints. NEWLY LICENSED / NO PRODUCTION: an originator who is in the NMLS registry but has no production record is returned only by an identity search — `nmlsId`, `name` or `namePrefix` as the ONLY filter — sent with `producersOnly: false`. Those rows come after the rows that have production, carry `hasScoredData: false`, and have `null` production fields. Under any other filter, or without `producersOnly: false`, they are not returned (use `getOriginator` for one by NMLS id). This is the per-originator record search: use it to find specific loan officers or build a filtered LO list. (For a single originator by NMLS ID use the originator detail endpoint.) If you only need how many originators match and not the records themselves, send the same request body to `countOriginators`.","operationId":"listOriginators","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorListResponse"}}},"description":"Paginated list of originators"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value. Also returned with `code: \"TIME_AT_COMPANY_SCOPE\"` when `timeAtCompanyMonths` is set, the other filters match more than 200,000 originators, and the requested page lies past the tenure matches found among the first 200,000 — narrow the request."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search originators with filters","tags":["Originators"]}},"/v1/originators/analytics/chart":{"post":{"operationId":"originatorAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data. Money measures (`volume`, `avgSalePrice`, `avgListPrice`) are sentinel-guarded. Excludes values outside 0–100,000,000 — the source encodes unknown values as an out-of-range fill, and averaging them raw is wrong by orders of magnitude. The bound is applied before the metric and is not part of the public filter surface, so an equivalent range filter will not reproduce this figure exactly."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart (measure × slice) over one LO's loans","tags":["Originators"]}},"/v1/originators/analytics/summary":{"post":{"operationId":"originatorAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleSummaryResponse"}}},"description":"Current + previous-period summary"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Production summary with previous-period comparison","tags":["Originators"]}},"/v1/originators/analytics/time-series":{"post":{"operationId":"originatorAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SimpleTimeSeriesResponse"}}},"description":"Time-series with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Originator volume / units over time","tags":["Originators"]}},"/v1/originators/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching originators document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/originators/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.originators` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitOriginatorsBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/OriginatorListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.originators` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for originators","tags":["Originators"]}},"/v1/originators/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running originators delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/originators/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelOriginatorsBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/originators/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/originators/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for originators","tags":["Originators"]},"get":{"operationId":"getOriginatorsBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/originators/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/originators/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for originators","tags":["Originators"]}},"/v1/originators/count":{"post":{"description":"Return the exact number of originators matching the given filters. Accepts the same request body as `listOriginators` (pagination and sort are ignored). Use this when you only need a total; to get the matching originators themselves, send the same request body to `listOriginators`.","operationId":"countOriginators","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorCountResponse"}}},"description":"Exact count of matching originators"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count originators matching filters","tags":["Originators"],"x-mm-records-via":"listOriginators"}},"/v1/originators/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"originatorRelated","parameters":[{"description":"Originator NMLS ID","in":"path","name":"id","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["companies","loans","properties"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/originators/{nmlsId}":{"get":{"operationId":"getOriginator","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}},{"description":"Period for volume/units (default: last12Months)","in":"query","name":"period","required":false,"schema":{"allOf":[{"$ref":"#/components/schemas/Period"},{"description":"Period for volume/units (default: last12Months)"}]}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorDetailResponse"}}},"description":"Originator detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Originator not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get originator by NMLS ID","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/agents":{"post":{"description":"Ranks the real-estate agents on this LO's loans, by volume — the buyer's agent by default, the listing and co-listing agents with `side: \"listing\"`. Each loan is credited to the agent its MLS agent keys resolve to (a key naming several different people credits only the confirmed one), so `units` counts distinct loans per agent. `id` is that agent's id (pass it to `GET /v1/agents/{id}`); absent when the loan's key matches no agent profile, in which case `label` is the name the MLS recorded. Names that are an MLS placeholder for \"no agent recorded\" (`non member`, `non listed agent`, and ~140 board-specific spellings) are excluded — they are not people. Percentages are shares of the LO's whole loan population, so they do not sum to 100 across the page.","operationId":"originatorAgents","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorAgentsBreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by real-estate agent"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Real-estate agents this LO co-closed with","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/branches":{"post":{"operationId":"originatorBranches","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by branches"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Branch (broker) history for this LO","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/brokers":{"post":{"operationId":"originatorBrokers","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by brokers"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Broker shops this LO originated loans through (name-resolved)","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/cities":{"post":{"operationId":"originatorCitiesBreakdown","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by cities"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"City volume breakdown across this LO's loans","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/companies":{"post":{"operationId":"originatorCompanies","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by companies"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Funding companies (employer history) for this LO","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/counties":{"post":{"operationId":"originatorCountiesBreakdown","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by counties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"County (FIPS) volume breakdown across this LO's loans","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/lenders":{"post":{"operationId":"originatorLenders","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by lenders"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Lenders this LO has originated through","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/offices":{"post":{"operationId":"originatorOffices","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by broker (office)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Real-estate offices this LO closed through (with sponsoring company)","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/states":{"post":{"operationId":"originatorStatesBreakdown","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by states"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"State volume breakdown across this LO's loans","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/title-companies":{"post":{"description":"Ranks the title companies on this entity's loans (recorded deeds, `recording_date` window — the same population and period axis as every other loans breakdown). Spellings of one company are MERGED: `label` is its most-used spelling, `id` the normalized name every spelling was grouped under (legal-form and filler words such as `inc`, `llc`, `co`, `company`, `title`, `escrow` removed; `natl` → `national`). Placeholder entries meaning \"no title company recorded\" (`none available` and its misspellings, `unknown`, `n/a`, …) and names shorter than 3 characters are excluded rather than ranked. `attorney` and `accommodation` are kept: they say who closed. `pctUnits` / `pctVolume` are shares of the entity's WHOLE loan population in the window, including loans with no title company, so they do not sum to 100 across the page. Pages of up to 100 via `pagination`.","operationId":"originatorTitleCompanies","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the entity's loans by title company"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Title companies on this LO's loans (spellings merged)","tags":["Originators"]}},"/v1/originators/{nmlsId}/breakdowns/zip-codes":{"post":{"operationId":"originatorZipCodes","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BreakdownResponse"}}},"description":"Breakdown of the LO's loans by zip-codes"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Zip-code volume breakdown","tags":["Originators"]}},"/v1/originators/{nmlsId}/loans":{"post":{"operationId":"originatorLoans","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/LoanListResponse"}}},"description":"Paginated list of loans originated by this LO"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Loans originated by this LO","tags":["Originators"]}},"/v1/originators/{nmlsId}/markets":{"post":{"description":"One blended view of a loan officer's lending footprint: the ZIP codes they originated in, city / county / state rollups of the same scope, and the period totals those markets are a share of. AVERAGES ARE VOLUME-WEIGHTED: the summary loan size is Σ volume ÷ Σ units, not an unweighted mean of the per-market averages (on a real footprint the two differ by thousands of dollars). Sending `zipCodes` narrows every grain to those ZIPs; sending a `dateRange` re-cuts the window. Either switches the response from the LO's pre-aggregated footprint to a live aggregation of their loans — `source` and `sourceReasons` say which was used, and bucket `key` forms differ between them (use `name` for display). All shares on this response are 0–100 percentages. A summary can cover less than the whole book: production that could not be attributed to a place is held out and reported in `summary.unresolved` rather than being folded in or silently dropped. The summary also carries a Community Lending mix — what kind of neighborhood this book lands in. These are U.S. Census tract-level aggregates describing whole neighborhoods, never individual, household or applicant attributes. Unscoped it is the LO's own whole-period mix; a ZIP or date scope recomputes it over the markets in scope, and `summary.communityLending.basis` says which you got.","operationId":"originatorMarkets","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorMarketsRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/OriginatorMarketsResponse"}}},"description":"The LO's blended market footprint"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Originator not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"The markets this LO lends in","tags":["Originators"]}},"/v1/originators/{nmlsId}/properties":{"post":{"description":"Returns the parcels this loan officer is attributed to in public record — the reverse of the `parties` block on `GET /v1/properties/{id}`. Accepts the same filters, sorts and pagination as the main property search, so a caller can ask 'this LO's parcels in Travis County built after 2015' in one request. Attribution is ALL-TIME: a parcel stays in this LO's set after the loan is paid off, because the question is career reach rather than current book. An LO with no attributed parcels returns an empty page, not a 404 — the LO may be real and simply have nothing in the public record yet.","operationId":"originatorProperties","parameters":[{"description":"Originator NMLS ID","in":"path","name":"nmlsId","required":true,"schema":{"description":"Originator NMLS ID","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListResponse"}}},"description":"Paginated list of parcels attributed to this LO"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Properties this loan officer has touched","tags":["Originators"]}},"/v1/properties":{"post":{"description":"Search and list individual properties/parcels with filters — one row per parcel. Filter by location (state, county, city, zip, address), owner name, property characteristics (beds, baths, square footage, year built, property type), value, and ownership or transaction history, with sorting and cursor pagination. This is the discrete per-property record search: use it to find specific properties or build a filtered property list. (For a single property by its ID use the property detail endpoint.) If you only need how many properties match and not the records themselves, send the same request body to `countProperties`.","operationId":"listProperties","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListResponse"}}},"description":"Paginated list of properties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search properties with filters","tags":["Properties"]}},"/v1/properties/analytics/chart":{"post":{"operationId":"propertiesAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data with measure/slice breakdown"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart data (measure × slice)","tags":["Properties"]}},"/v1/properties/analytics/summary":{"post":{"operationId":"propertiesAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertySummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyAnalyticsResponse"}}},"description":"Property count and average AVM value"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Property count and average AVM","tags":["Properties"]}},"/v1/properties/bulk-delivery":{"post":{"description":"Queues an ECS task that dumps every matching properties document to S3 in the requested format. Returns 202 with a jobId; poll `GET /v1/properties/bulk-delivery/{jobId}` for status + the signed download URL.\n\n**Row limit.** Deliveries of up to 5,000 rows need no entitlement. Above that, the org's `bulk-delivery.properties` entitlement is required and its scope (row ceiling, row filters, allowed fields) governs the delivery; without it the request is rejected with 403 `entitlement_missing`. Pass `limit` at or below the ceiling to deliver a capped subset of a broader query. Email support@modelmatch.com to request a limit increase.\n\nDelivery is billed at 1 credit per row regardless of entitlement (deliveries submitted from the ModelMatch web app are not billed).\n\n**Push-target destination.** Pass `destination: { type: \"push-target\", targetId }` to have the finished rows sent to a configured push target instead of downloaded. The target is checked before anything is queued; a refusal returns the push target's status and `code` (`TARGET_NOT_FOUND` 404, `FORBIDDEN` 403, `PLAN_REQUIRED` 402, `TARGET_DISABLED` 409, `ENTITY_MISMATCH` 400). Limits and billing are the same as a file delivery.","operationId":"submitPropertiesBulkDelivery","requestBody":{"content":{"application/json":{"schema":{"allOf":[{"$ref":"#/components/schemas/PropertyListRequest"},{"additionalProperties":false,"properties":{"columns":{"description":"A FORMATTED file: its columns, in order, with header labels and number formats — for `format` `csv` or `xlsx` only, and not combined with `fields` or a push-target `destination` (400 `columns_format_unsupported` / `columns_with_fields` / `columns_with_destination`). Every field a column reads is gated by the entitlement exactly as if it were listed in `fields`: a withheld field drops out of a column's fallback list, and a column with nothing left is omitted. An unknown field is a 400 `unknown_column_field`. No `id` column is added. A formatted `csv` starts with a UTF-8 byte-order mark and uses CRLF line endings, so Excel opens it with accented names intact. Columns may read any DTO field and any opt-in column `fields` documents, including the computed `governmentPct`, `branchCount` and `managerName` / `managerNmlsId`.","items":{"$ref":"#/components/schemas/BulkDeliveryColumn"},"maxItems":200,"minItems":1,"type":"array"},"destination":{"$ref":"#/components/schemas/BulkDeliveryDestination"},"fields":{"description":"Optional output column projection, named by the response DTO fields (the same camelCase fields the list endpoint returns, e.g. `city`, `interestRate`). Intersected with the entitlement scope's allowedFields and the entity's full column set. If empty after intersection, falls back to all columns. It also SELECTS the opt-in columns, which are not part of the list DTO and are never delivered unless named here: `communityLending` (properties, originators, companies, branches) — the Community Lending neighborhood profile, identical to the block on the entity's detail endpoint; `parties` (properties) — the mortgage parties attributed to the parcel, by attribution scope; `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on; and the computed `governmentPct` (originators: FHA + VA percent of loans, 0–100), `branchCount` (companies: NMLS branch count) and `managerName` / `managerNmlsId` (branches: the first branch manager). Agents also offer `email2` / `phone2` (the best-ranked email / phone distinct from `email` / `phone`, admitted by the `email` / `phone` entitlement field), `bestEmail` / `bestEmail2` and `bestPhone` / `bestPhone2` (the best and runner-up contact over every email / phone on the record, `email` / `phone` included — the pair the ModelMatch web app's agent export shows; same entitlement fields), `officePhone` (admitted by `phone`), `activeListings` (current active listings; null when unknown), and the profile-link columns `facebook`, `instagram`, `linkedin`, `twitter`, `youtube`, `tiktok`, `zillow`, `otherLinks` (a `; `-joined list of profile URLs on no known platform) — all admitted by the `links` entitlement field. Loans offer the list row's transaction-export fields (`employerName`, `employerNmlsId`, `brokerName`, `titleCompanyName`, `soldAgentName`, `listAgentName`, `coListAgentName`, `buyer1FirstMiddle` … `seller2Last`). In `csv` and `parquet` the two block columns are JSON-encoded cells; in `json` and `ndjson` they are nested objects. Windowed production (originators, agents, companies, branches): name `<field>_<n>mo` for n in 3, 6, 12, 14, 18, 24 to get a production field for that trailing window regardless of `period` — e.g. `volume_3mo`, `units_6mo`, `purchaseVolume_24mo`. Available for originators `volume`, `units`, `avgLoanAmount`, `purchaseVolume`, `purchaseUnits`, `refinanceVolume`, `refinanceUnits`, `conventionalPct`, `fhaPct`, `vaPct`; agents `volume`, `units`, `avgSoldPrice`, `buyerVolume`, `buyerUnits`, `sellerVolume`, `sellerUnits`, `totalOriginatorsWorkedWith`, `totalCompaniesWorkedWith`, `totalLendersWorkedWith`; companies `volume`, `units`, `avgLoanAmount`, `loCount`; branches `volume`, `units`, `avgLoanAmount`, `purchasePct`, `refinancePct`, `loCount`. Numbers (null when the window has no data); an entitlement that allows a field allows every window of it.","items":{"minLength":1,"type":"string"},"type":"array"},"format":{"$ref":"#/components/schemas/BulkDeliveryFormat"},"limit":{"description":"Optional hard cap on the number of rows delivered — and therefore billed (1 credit / row). The job delivers the first `limit` rows in sort order (default newest-first) and bills only for those. If the query matches fewer than `limit`, all matches are delivered. Distinct from the page-size `size` field, which is ignored on this endpoint. The row ceiling still applies — 5,000 without the entity's bulk-delivery entitlement, or the entitlement's `maxRows` with it. A `limit` above the ceiling is rejected, but a `limit` at or below it lets you export a capped top-N even when the full match exceeds the ceiling — which is the intended way to run a broad query under the 5,000-row allowance.","example":5000,"exclusiveMinimum":true,"minimum":0,"type":"integer"},"propertyIds":{"description":"Deliver exactly these parcels (up to 50,000; the ids `enrich-bulk` takes): a list/search row `id` (that parcel) or an `mmPropertyId` (every unit). Must start with `mm_`. ANDed with the filters. Unmatched ids are skipped (`estimatedTotal` = matched parcels); rows come in sort order, not id order — join on `id`. Limits and billing unchanged.","items":{"pattern":"^mm_\\S","type":"string"},"maxItems":50000,"minItems":1,"type":"array"}},"type":"object"}]}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliverySubmitResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/ErrorResponse"},{"$ref":"#/components/schemas/BulkDeliveryPreflightExceeded"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryColumnsError"}]}}},"description":"Validation failure (incl. `format_required`: a file delivery needs `format`; a refused `columns` request), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryInsufficientCredits"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}]}}},"description":"Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"},"403":{"content":{"application/json":{"schema":{"anyOf":[{"$ref":"#/components/schemas/BulkDeliveryForbidden"},{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"},{"$ref":"#/components/schemas/BulkDeliveryInsufficientScope"}]}}},"description":"Delivery exceeds the 5,000-row limit available without the `bulk-delivery.properties` entitlement (lower `limit`, narrow the filters, or contact support for a limit increase), OR you may not use the push target (`FORBIDDEN`), OR a scoped token named a push-target destination without `push-targets:send` (`insufficient_scope`)."},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target not found (`TARGET_NOT_FOUND`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryPushTargetError"}}},"description":"Push target is disabled (`TARGET_DISABLED`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"}},"summary":"Submit a bulk-delivery job for properties","tags":["Properties"]}},"/v1/properties/bulk-delivery/{jobId}":{"delete":{"description":"Cancels a queued or running properties delivery job.\n\nThe job is marked `cancelled` immediately; the container running it notices on its next page boundary and stops. Because a delivery is billed once, at the end, **a cancelled job is never charged** — no credits are debited and there is nothing to refund. No partial file is written.\n\nIdempotent-ish: cancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing. Poll `GET /v1/properties/bulk-delivery/{jobId}` for the settled state.","operationId":"cancelPropertiesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/properties/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/properties/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk-delivery job for properties","tags":["Properties"]},"get":{"operationId":"getPropertiesBulkDeliveryJob","parameters":[{"description":"Job ID returned by `POST /v1/properties/bulk-delivery`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID returned by `POST /v1/properties/bulk-delivery`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/BulkDeliveryStatusResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk-delivery job status for properties","tags":["Properties"]}},"/v1/properties/count":{"post":{"description":"Return the exact number of properties matching the given filters. Accepts the same request body as `listProperties` (pagination and sort are ignored). Use this when you only need a total; to get the matching properties themselves, send the same request body to `listProperties`.","operationId":"countProperties","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching properties"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count properties matching filters","tags":["Properties"],"x-mm-records-via":"listProperties"}},"/v1/properties/enrich":{"post":{"description":"Looks up owner contact information for up to 50 properties in a single synchronous request. Each id is resolved independently and returned in the `results` array with its own status — a bad id never fails the batch. Each match debits 10 credits; cache hits and no-matches are free. Every ok item also carries `property` — the parcel's Community Lending neighborhood profile and mortgage party rosters. For larger sets use the asynchronous bulk job.","operationId":"enrichPropertiesBatch","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBatchRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBatchResponse"}}},"description":"Per-item results (each cached, fresh, or errored)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid request (Zod validation failure)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"}},"summary":"Enrich several properties with owner contact info in one request","tags":["Properties"]}},"/v1/properties/enrich-bulk":{"post":{"description":"Queues an ECS task that enriches up to 50000 properties. Returns 202 with a jobId; poll `GET /v1/properties/enrich-bulk/{jobId}` or subscribe to the `enrichment.bulk.*` EventBridge / webhook events for completion.","operationId":"enrichPropertiesBulk","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBulkRequest"}}}},"responses":{"202":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBulkResponse"}}},"description":"Job queued; ECS task launched"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Invalid request (Zod validation failure)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"properties":{"balance":{"description":"Remaining credit balance the charge saw.","type":"number"},"cost":{"description":"Credits the request asked for.","type":"number"},"error":{"enum":["payment_required"],"type":"string"},"message":{"description":"Human-readable explanation of the decline.","type":"string"},"reason":{"description":"Why the charge was declined, when known: `out_of_credits` (balance empty) vs. `limit_reached` (a spend cap was hit).","enum":["out_of_credits","limit_reached"],"type":"string"}},"required":["error","balance","cost"],"type":"object"}}},"description":"Insufficient credits (balance < the job's worst-case cost in credits)"},"429":{"content":{"application/json":{"schema":{"properties":{"category":{"enum":["enrichment"],"type":"string"},"error":{"enum":["daily_limit_exceeded"],"type":"string"},"limit":{"description":"The daily cap.","type":"number"},"message":{"type":"string"},"requested":{"description":"Upper bound of this job's charge, in credits (not a count of ids).","type":"number"},"used":{"description":"Credits already used against today's cap.","type":"number"}},"required":["error","category","used","limit","requested","message"],"type":"object"}}},"description":"Job's max charge (one per targeted property) would exceed the member's daily enrichment cap (`daily_limit_exceeded`)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Failed to launch task or stage inputs"}},"summary":"Submit a bulk skip-trace job","tags":["Properties"]}},"/v1/properties/enrich-bulk/{jobId}":{"delete":{"description":"Cancels a queued or running bulk enrichment job.\n\nThe job is marked `cancelled` immediately; the container running it notices at its next progress tick and stops. Enrichment is billed once, at the end, so **a cancelled job is never charged** — no credits are debited and there is nothing to refund. Properties already enriched stay in the cache, so re-running later is cheaper.\n\nCancelling a job that has already finished (or was already cancelled) returns 409 and changes nothing.","operationId":"cancelEnrichBulkJob","parameters":[{"description":"Job ID from `POST /v1/properties/enrich-bulk`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID from `POST /v1/properties/enrich-bulk`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBulkJobResponse"}}},"description":"Job cancelled; body is its settled status"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job already finished — nothing to cancel"}},"summary":"Cancel a bulk enrichment job","tags":["Properties"]},"get":{"operationId":"getEnrichBulkJob","parameters":[{"description":"Job ID from `POST /v1/properties/enrich-bulk`","in":"path","name":"jobId","required":true,"schema":{"description":"Job ID from `POST /v1/properties/enrich-bulk`","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichBulkJobResponse"}}},"description":"Job status (resultsUrl re-signed if completed)"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller does not own this job"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Job not found (or expired past 30d TTL)"}},"summary":"Get bulk enrichment job status","tags":["Properties"]}},"/v1/properties/enrichments":{"get":{"operationId":"listEnrichments","parameters":[{"description":"Maximum number of items to return (default 25)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum number of items to return (default 25)","maximum":100,"minimum":1,"type":"integer"}},{"description":"Pagination cursor from a previous response","in":"query","name":"cursor","required":false,"schema":{"description":"Pagination cursor from a previous response","type":"string"}},{"description":"Return only this property's enrichment (zero or one item). The id is the one in the credit ledger's `enrich:<propertyId>` reason.","in":"query","name":"propertyId","required":false,"schema":{"description":"Return only this property's enrichment (zero or one item). The id is the one in the credit ledger's `enrich:<propertyId>` reason.","minLength":1,"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichmentListResponse"}}},"description":"Paginated list of enriched properties"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"}},"summary":"List enriched properties for the current user","tags":["Properties"]}},"/v1/properties/resolve":{"post":{"description":"Resolve up to 2,000 postal addresses to property ids in one call — e.g. a mailing list before a bulk delivery. Free. Returns one result per input, in order, keyed by your `ref`. `matched` carries the parcel `id` and `mmPropertyId` — pass them to bulk delivery `propertyIds` or the list `flatFilters.id`, then join the rows back on `ref`. Each address is first matched on the normalized number + street + unit + zip key (suffix, directional, punctuation and case insensitive); misses fall back to a ranked search that only accepts a hit with the same house number, the same zip or city, and a near-identical street name. `ambiguous` lists `candidates`: `unit_required` (a building whose units are separate parcels — resend with the unit), `duplicate_parcels` (one address on several parcel records; usually safe to take them all), `multiple_parcels`. `not_found` gives a `reason`: `no_parcel_at_number` (no parcel at that house number in that zip/city), `low_confidence`, or an input problem (`no_house_number`, `no_street`, `no_location`).","operationId":"resolveProperties","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyResolveRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyResolveResponse"}}},"description":"One result per input address, in order"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Resolve a batch of addresses to property ids","tags":["Properties"]}},"/v1/properties/search":{"post":{"description":"Find properties by a single free-text query — a full or partial address, an owner name, or a place. Results are ranked by relevance and tolerate typos, missing components, and reordered street directionals (e.g. \"112 5th ave nw\" and \"112 nw 5th ave\" both match). Returns the same property summary rows as the list endpoint. Use this for a search box; use the list endpoint for structured filtering.","operationId":"searchProperties","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertySearchRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyListResponse"}}},"description":"Relevance-ranked property matches"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Free-text property search","tags":["Properties"]}},"/v1/properties/{id}":{"get":{"operationId":"getProperty","parameters":[{"description":"Property document ID","in":"path","name":"id","required":true,"schema":{"description":"Property document ID","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PropertyDetailResponse"}}},"description":"Property detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Property not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get property by ID (with mm_property_id fallback)","tags":["Properties"]}},"/v1/properties/{id}/enrich":{"post":{"description":"Looks up owner contact information via skip-trace. Uses the canonical address first; falls back to an associated loan or sale record address if the canonical is missing. The response also carries `property` — the parcel's Community Lending neighborhood profile and its mortgage party rosters, the same blocks `GET /v1/properties/{id}` returns — so the two questions that follow a skip-trace do not need a second call. `property` is `null` when the id resolves to more than one parcel and the request was served from cache (a fresh lookup 409s instead, rather than bill for a guess).","operationId":"enrichProperty","parameters":[{"description":"Property document ID. Use the `id` or `mmPropertyId` returned by a property search/detail, or the `mmPropertyId` on a loan/sale record (e.g. `mm_37035375304734463`). Do NOT pass a bare APN, a fips+apn string, or a `loan_…` id — those will not resolve.","in":"path","name":"id","required":true,"schema":{"description":"Property document ID. Use the `id` or `mmPropertyId` returned by a property search/detail, or the `mmPropertyId` on a loan/sale record (e.g. `mm_37035375304734463`). Do NOT pass a bare APN, a fips+apn string, or a `loan_…` id — those will not resolve.","type":"string"}},{"description":"When 'true', bypass both the per-member entitlement and the internal property cache, force a fresh skip-trace, and re-charge the user. Default: 'false'.","in":"query","name":"refresh","required":false,"schema":{"description":"When 'true', bypass both the per-member entitlement and the internal property cache, force a fresh skip-trace, and re-charge the user. Default: 'false'.","enum":["true","false"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichPropertyResponse"}}},"description":"Enrichment data (cached or fresh)"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Property has no usable address on the parcel or any associated record"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Authentication required"},"402":{"content":{"application/json":{"schema":{"properties":{"balance":{"description":"Remaining credit balance the charge saw.","type":"number"},"cost":{"description":"Credits the request asked for.","type":"number"},"error":{"enum":["payment_required"],"type":"string"},"message":{"description":"Human-readable explanation of the decline.","type":"string"},"reason":{"description":"Why the charge was declined, when known: `out_of_credits` (balance empty) vs. `limit_reached` (a spend cap was hit).","enum":["out_of_credits","limit_reached"],"type":"string"}},"required":["error","balance","cost"],"type":"object"}}},"description":"Insufficient credits"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Caller lacks permission to charge credits (`permission_denied`)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Property not found, or the caller is not a member of the org (`member_not_found`)"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/EnrichAmbiguousRef"}}},"description":"The id resolved to more than one parcel (a non-unique `mm_property_id` colliding across units). Pass one of `alternates` (an exact `id`) to enrich a specific unit. NOT charged."},"429":{"content":{"application/json":{"schema":{"properties":{"category":{"description":"Usage category that was capped, when reported.","type":"string"},"error":{"enum":["rate_limited","daily_limit_exceeded"],"type":"string"},"limit":{"description":"The cap, when known.","type":"number"},"message":{"description":"Human-readable explanation of the throttle.","type":"string"},"requested":{"description":"Credits this request asked for, when known.","type":"number"},"used":{"description":"Credits already used in the window, when known.","type":"number"}},"required":["error"],"type":"object"}}},"description":"Throttled — `daily_limit_exceeded` (daily category cap) or `rate_limited` (generic limiter)"},"502":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Enrichment provider error"}},"summary":"Enrich a property with owner contact info","tags":["Properties"]}},"/v1/properties/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"propertyRelated","parameters":[{"description":"Property id","in":"path","name":"id","required":true,"schema":{"description":"Property id","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["companies","loans","originators","sales"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/realtime/config":{"get":{"description":"Returns the realtime/notifications connection info (endpoint, authorizer, app, stage) merged with the caller's userId, so a trusted client can connect to its per-user IoT MQTT topic.","operationId":"getRealtimeConfig","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeConfigResponse"}}},"description":"Realtime connection config"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RealtimeConfigUnavailable"}}},"description":"Realtime backend not configured"}},"summary":"Get realtime connection config","tags":["Realtime"]}},"/v1/sales":{"post":{"description":"Search and list individual real-estate sale transactions and active listings with filters — one row per sale/listing. Filter by location (state, county, city, zip), sale price, sale or listing date, property characteristics (beds, baths, square footage, property type), and listing status, with sorting and cursor pagination. This is the discrete per-transaction sales-record search: use it to find specific sales or build a filtered list of sold/active listings. If you only need how many sales match and not the records themselves, send the same request body to `countSales`.","operationId":"listSales","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleListResponse"}}},"description":"Paginated list of sales"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error. Includes unresolvable location filters: a `city`/`county`/`state`/`zip` value that does not match a recognized location returns 400 rather than an empty result set. Resolve the name with `instantSearch` (use an id from its `results.locations[]`) or `suggestLocations` (use the `id` of a `source: \"dictionary\"` result), then pass that id back as the filter value."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Search sales with filters","tags":["Sales"]}},"/v1/sales/analytics/chart":{"post":{"operationId":"salesAnalyticsChart","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleChartRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ChartResponse"}}},"description":"Chart data"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Configurable chart (measure × slice) over the market","tags":["Sales"]}},"/v1/sales/analytics/summary":{"post":{"operationId":"salesAnalyticsSummary","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleSummaryRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SidedSummaryResponse"}}},"description":"Sided market summary with previous-period comparison"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Market summary with buyer/seller/dual split + previous period","tags":["Sales"]}},"/v1/sales/analytics/time-series":{"post":{"operationId":"salesAnalyticsTimeSeries","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleTimeSeriesRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SalesTimeSeriesResponse"}}},"description":"Time-series with side splits + previous period. Every side carries `volume`, `units`, and `measureValue` for the requested `measure`."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Volume/units over time with buyer/seller/dual split","tags":["Sales"]}},"/v1/sales/count":{"post":{"description":"Return the exact number of sales matching the given filters. Accepts the same request body as `listSales` (pagination and sort are ignored). Use this when you only need a total; to get the matching sales themselves, send the same request body to `listSales`.","operationId":"countSales","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleListRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CountResponse"}}},"description":"Exact count of matching sales"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Count sales matching filters","tags":["Sales"],"x-mm-records-via":"listSales"}},"/v1/sales/{id}":{"get":{"operationId":"getSale","parameters":[{"description":"Sale document ID","in":"path","name":"id","required":true,"schema":{"description":"Sale document ID","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SaleDetailResponse"}}},"description":"Sale detail"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Sale not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large"}},"summary":"Get sale by ID","tags":["Sales"]}},"/v1/sales/{id}/related":{"get":{"description":"Return the ids of records of another type that are linked to this record. Links resolve by identifier, strongest identifier first, and equally-trusted identifiers are combined — a company's linked loans cover every role it holds on a loan, not just the first one found. The response reports which strength was used: `primary` is the canonical identifier for that pair, `secondary` is a real but weaker alternate used only when the record carries nothing better. This is a lightweight index: it returns ids and a count, not full records. For filtering, sorting, pagination and full detail, use the named endpoint for the pair (for example the originator loans endpoint) and fetch records by id.","operationId":"saleRelated","parameters":[{"description":"Sale id","in":"path","name":"id","required":true,"schema":{"description":"Sale id","type":"string"}},{"description":"Type of record to link to","in":"query","name":"to","required":true,"schema":{"description":"Type of record to link to","enum":["agents","loans","properties"],"type":"string"}},{"description":"Maximum ids to return (default 25, max 200)","in":"query","name":"limit","required":false,"schema":{"description":"Maximum ids to return (default 25, max 200)","maximum":200,"minimum":1,"type":"integer"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/RelatedResponse"}}},"description":"Linked record ids"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Record not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Records linked to this one","tags":["Related"]}},"/v1/saved-filters":{"get":{"description":"The caller's saved filters (and saved CRM views) in the active organization, oldest first, optionally narrowed by target and kind.","operationId":"listSavedFilters","parameters":[{"description":"Which list the filter runs against. Market targets run against that entity's list operation (see `operationId`, e.g. listOriginators); `crm_people` / `crm_companies` are UI-only (filtered client-side).","in":"query","name":"target","required":false,"schema":{"description":"Which list the filter runs against. Market targets run against that entity's list operation (see `operationId`, e.g. listOriginators); `crm_people` / `crm_companies` are UI-only (filtered client-side).","enum":["originators","agents","companies","branches","offices","loans","properties","sales","crm_people","crm_companies"],"type":"string"}},{"description":"`filter` (default) — a saved search; `view` — a saved CRM table layout (columns / order) kept in `uiState`. Views never carry a `query` and have their own 25-per-target quota. Fixed at create.","in":"query","name":"kind","required":false,"schema":{"description":"`filter` (default) — a saved search; `view` — a saved CRM table layout (columns / order) kept in `uiState`. Views never carry a `query` and have their own 25-per-target quota. Fixed at create.","enum":["filter","view"],"type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterList"}}},"description":"Saved filters."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"List your saved filters","tags":["Saved Filters"]},"post":{"description":"Save a named filter for a list target. For a market target, `query` is the target operation's request body without `pagination` (e.g. the body you would send to listOriginators) and is validated against it. Limit: 25 per target.","operationId":"createSavedFilter","requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSavedFilterRequest"}}}},"responses":{"201":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/CreateSavedFilterResult"}}},"description":"The saved filter."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"Validation error — including a `query` that is not a valid request for the target's operation (`issues` lists each problem)."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"409":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"`QUOTA_EXCEEDED` — 25 saved filters for this target already; update or delete one."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Save a filter","tags":["Saved Filters"]}},"/v1/saved-filters/{id}":{"delete":{"operationId":"deleteSavedFilter","parameters":[{"description":"Saved-filter id (nanoid).","in":"path","name":"id","required":true,"schema":{"description":"Saved-filter id (nanoid).","example":"V1StGXR8_Z5jdHi6B-myT","maxLength":32,"minLength":1,"pattern":"^[\\w-]+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/DeleteSavedFilterResult"}}},"description":"Deleted."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"No saved filter with that id belongs to the caller."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Delete a saved filter","tags":["Saved Filters"]},"get":{"description":"Returns the saved `query` and the `operationId` to run it with. Check `fidelity` (`partial` → `unmapped` lists what the query omits; `ui_only` → nothing to run) and `stale` (the query no longer validates) before running.","operationId":"getSavedFilter","parameters":[{"description":"Saved-filter id (nanoid).","in":"path","name":"id","required":true,"schema":{"description":"Saved-filter id (nanoid).","example":"V1StGXR8_Z5jdHi6B-myT","maxLength":32,"minLength":1,"pattern":"^[\\w-]+$","type":"string"}}],"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/GetSavedFilterResult"}}},"description":"The saved filter."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"No saved filter with that id belongs to the caller."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Get a saved filter (with the operation to run it)","tags":["Saved Filters"]},"patch":{"description":"Rename, re-icon, or replace the query / UI state. The target is fixed. A new `query` is validated like on create.","operationId":"updateSavedFilter","parameters":[{"description":"Saved-filter id (nanoid).","in":"path","name":"id","required":true,"schema":{"description":"Saved-filter id (nanoid).","example":"V1StGXR8_Z5jdHi6B-myT","maxLength":32,"minLength":1,"pattern":"^[\\w-]+$","type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSavedFilterRequest"}}}},"responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/UpdateSavedFilterResult"}}},"description":"The updated filter."},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"Validation error — including a `query` that is not a valid request for the target's operation (`issues` lists each problem)."},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SavedFilterError"}}},"description":"No saved filter with that id belongs to the caller."},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"}},"summary":"Update a saved filter","tags":["Saved Filters"]}},"/v1/search-token":{"get":{"description":"Returns a short-lived scoped search token plus the host to query, so a trusted client can search the entity indexes directly with per-query controls (e.g. attributesToSearchOn for name-only matching).","operationId":"getSearchToken","responses":{"200":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchTokenResponse"}}},"description":"Scoped search token"},"400":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Validation error"},"401":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Unauthorized"},"403":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Forbidden (authenticated, but missing required context — e.g. no active organization)"},"404":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/ErrorResponse"}}},"description":"Not found"},"413":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/PayloadTooLarge"}}},"description":"Response payload too large — detail endpoint capped to fit Lambda response limits"},"503":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/SearchTokenUnavailable"}}},"description":"Search backend not configured"}},"summary":"Mint a scoped search token","tags":["Search"]}}},"security":[{"apiKeyAuth":[]},{"bearerAuth":[]}],"tags":[{"description":"Internal admin endpoints (admin role only)","name":"Admin"},{"description":"Real estate agents","name":"Agents"},{"description":"Per-user alert settings, watchlists, and feed","name":"Alerts"},{"description":"NMLS-registered company branch offices","name":"Branches"},{"description":"NMLS-registered mortgage companies","name":"Companies"},{"description":"CRM records, lists, contacts, activity, tasks, meetings, and calls","name":"CRM"},{"description":"Send Model Match records into systems you own, such as your CRM","name":"Integrations"},{"description":"Lender name normalization dictionary","name":"Lenders"},{"description":"Public-record mortgage / deed transactions","name":"Loans"},{"description":"Location autocomplete and resolution","name":"Locations"},{"description":"Aggregated mortgage origination market data (geography, product, borrower numerics)","name":"Market"},{"description":"The current caller's account — profile, credit balance, and plan","name":"Me"},{"description":"Real-estate office records","name":"Offices"},{"description":"Loan originators (NMLS LOs)","name":"Originators"},{"description":"Properties with owners and history","name":"Properties"},{"description":"Realtime/notifications connection config","name":"Realtime"},{"description":"Records linked to a given record, across entity types","name":"Related"},{"description":"Real-estate sales transactions","name":"Sales"},{"description":"Your saved list filters — store a query once, re-run it against its list operation","name":"Saved Filters"},{"description":"Instant multi-entity search","name":"Search"}]}