@model-match/api 3.18.0 → 3.19.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/openapi.json CHANGED
@@ -1716,7 +1716,7 @@
1716
1716
  "type": "array"
1717
1717
  }
1718
1718
  ],
1719
- "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 /agents/{id}/markets` (live-aggregated) for an agent's geography."
1719
+ "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."
1720
1720
  },
1721
1721
  "lenderFilters": {
1722
1722
  "items": {
@@ -19838,7 +19838,7 @@
19838
19838
  },
19839
19839
  "originatorEmail": {
19840
19840
  "deprecated": true,
19841
- "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 /originators/{nmlsId}`), whose `email` field carries it — available for roughly 14% of loan officers.",
19841
+ "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.",
19842
19842
  "nullable": true,
19843
19843
  "type": "string"
19844
19844
  },
@@ -24108,22 +24108,24 @@
24108
24108
  "OriginatorCompanyCategoryFilterValue": {
24109
24109
  "anyOf": [
24110
24110
  {
24111
- "description": "One of (case-insensitive): BANK, CU, OTHER",
24111
+ "description": "One of (case-insensitive): BANK, CU, OTHER, BUILDER",
24112
24112
  "enum": [
24113
24113
  "BANK",
24114
24114
  "CU",
24115
- "OTHER"
24115
+ "OTHER",
24116
+ "BUILDER"
24116
24117
  ],
24117
24118
  "type": "string"
24118
24119
  },
24119
24120
  {
24120
24121
  "description": "Match any of these values",
24121
24122
  "items": {
24122
- "description": "One of (case-insensitive): BANK, CU, OTHER",
24123
+ "description": "One of (case-insensitive): BANK, CU, OTHER, BUILDER",
24123
24124
  "enum": [
24124
24125
  "BANK",
24125
24126
  "CU",
24126
- "OTHER"
24127
+ "OTHER",
24128
+ "BUILDER"
24127
24129
  ],
24128
24130
  "type": "string"
24129
24131
  },
@@ -24144,7 +24146,8 @@
24144
24146
  {
24145
24147
  "nullable": true
24146
24148
  }
24147
- ]
24149
+ ],
24150
+ "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."
24148
24151
  },
24149
24152
  "OriginatorContact": {
24150
24153
  "nullable": true,
@@ -24261,6 +24264,47 @@
24261
24264
  ],
24262
24265
  "type": "object"
24263
24266
  },
24267
+ "OriginatorCrmListFilter": {
24268
+ "additionalProperties": false,
24269
+ "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.",
24270
+ "properties": {
24271
+ "lists": {
24272
+ "anyOf": [
24273
+ {
24274
+ "description": "Every People list in the caller's workspace that the caller can see (own, org-wide, or shared with them).",
24275
+ "enum": [
24276
+ "any"
24277
+ ],
24278
+ "type": "string"
24279
+ },
24280
+ {
24281
+ "description": "Specific CRM list ids (1–50).",
24282
+ "items": {
24283
+ "minLength": 1,
24284
+ "type": "string"
24285
+ },
24286
+ "maxItems": 50,
24287
+ "minItems": 1,
24288
+ "type": "array"
24289
+ }
24290
+ ],
24291
+ "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."
24292
+ },
24293
+ "mode": {
24294
+ "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.",
24295
+ "enum": [
24296
+ "in",
24297
+ "notIn"
24298
+ ],
24299
+ "type": "string"
24300
+ }
24301
+ },
24302
+ "required": [
24303
+ "mode",
24304
+ "lists"
24305
+ ],
24306
+ "type": "object"
24307
+ },
24264
24308
  "OriginatorDetail": {
24265
24309
  "allOf": [
24266
24310
  {
@@ -24795,6 +24839,9 @@
24795
24839
  "advancedFilters": {
24796
24840
  "$ref": "#/components/schemas/FilterNode"
24797
24841
  },
24842
+ "crmList": {
24843
+ "$ref": "#/components/schemas/OriginatorCrmListFilter"
24844
+ },
24798
24845
  "filters": {
24799
24846
  "$ref": "#/components/schemas/FilterNode"
24800
24847
  },
@@ -25212,6 +25259,16 @@
25212
25259
  }
25213
25260
  ]
25214
25261
  },
25262
+ "lastTransactionDate": {
25263
+ "allOf": [
25264
+ {
25265
+ "$ref": "#/components/schemas/DateFilterValue"
25266
+ },
25267
+ {
25268
+ "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."
25269
+ }
25270
+ ]
25271
+ },
25215
25272
  "lenderCount": {
25216
25273
  "allOf": [
25217
25274
  {
@@ -25225,6 +25282,16 @@
25225
25282
  "licenseCount": {
25226
25283
  "$ref": "#/components/schemas/NumericFilterValue"
25227
25284
  },
25285
+ "licensedSinceDate": {
25286
+ "allOf": [
25287
+ {
25288
+ "$ref": "#/components/schemas/DateFilterValue"
25289
+ },
25290
+ {
25291
+ "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."
25292
+ }
25293
+ ]
25294
+ },
25228
25295
  "loanType": {
25229
25296
  "$ref": "#/components/schemas/OriginatorLoanTypeFilterValue"
25230
25297
  },
@@ -25388,7 +25455,7 @@
25388
25455
  "$ref": "#/components/schemas/NumericFilterValue"
25389
25456
  },
25390
25457
  {
25391
- "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 /originators/{nmlsId}/analytics/time-series` for a month-by-month series."
25458
+ "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."
25392
25459
  }
25393
25460
  ]
25394
25461
  },
@@ -25757,7 +25824,9 @@
25757
25824
  "producersOnly",
25758
25825
  "yearsInIndustry",
25759
25826
  "officeState",
25760
- "officeCity"
25827
+ "officeCity",
25828
+ "licensedSinceDate",
25829
+ "lastTransactionDate"
25761
25830
  ],
25762
25831
  "type": "string"
25763
25832
  },
@@ -26577,7 +26646,7 @@
26577
26646
  "OriginatorSummary": {
26578
26647
  "properties": {
26579
26648
  "avgLoanAmount": {
26580
- "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 /originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.",
26649
+ "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.",
26581
26650
  "nullable": true,
26582
26651
  "type": "number"
26583
26652
  },
@@ -26724,11 +26793,21 @@
26724
26793
  "nullable": true,
26725
26794
  "type": "string"
26726
26795
  },
26796
+ "lastTransactionDate": {
26797
+ "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.",
26798
+ "nullable": true,
26799
+ "type": "string"
26800
+ },
26727
26801
  "licenseCount": {
26728
26802
  "description": "Current NMLS registration license count — the value the `licenseCount` filter matches.",
26729
26803
  "nullable": true,
26730
26804
  "type": "number"
26731
26805
  },
26806
+ "licensedSinceDate": {
26807
+ "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.",
26808
+ "nullable": true,
26809
+ "type": "string"
26810
+ },
26732
26811
  "name": {
26733
26812
  "nullable": true,
26734
26813
  "type": "string"
@@ -26757,12 +26836,12 @@
26757
26836
  "type": "string"
26758
26837
  },
26759
26838
  "previousUnits": {
26760
- "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 /originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.",
26839
+ "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.",
26761
26840
  "nullable": true,
26762
26841
  "type": "number"
26763
26842
  },
26764
26843
  "previousVolume": {
26765
- "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 /originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.",
26844
+ "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.",
26766
26845
  "nullable": true,
26767
26846
  "type": "number"
26768
26847
  },
@@ -26791,12 +26870,12 @@
26791
26870
  "type": "array"
26792
26871
  },
26793
26872
  "scopedUnits": {
26794
- "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 /originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.",
26873
+ "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.",
26795
26874
  "nullable": true,
26796
26875
  "type": "number"
26797
26876
  },
26798
26877
  "scopedVolume": {
26799
- "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 /originators/{nmlsId}/markets` for the same geography and period: both are read from the same per-market rollup on the same record.",
26878
+ "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.",
26800
26879
  "nullable": true,
26801
26880
  "type": "number"
26802
26881
  },
@@ -26810,7 +26889,7 @@
26810
26889
  "type": "number"
26811
26890
  },
26812
26891
  "units": {
26813
- "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 /originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.",
26892
+ "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.",
26814
26893
  "nullable": true,
26815
26894
  "type": "number"
26816
26895
  },
@@ -26819,7 +26898,7 @@
26819
26898
  "type": "number"
26820
26899
  },
26821
26900
  "volume": {
26822
- "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 /originators/{nmlsId}/breakdowns/counties` (or `/cities`, `/states`, `/zip-codes`) breaks ONE originator's production out by market.",
26901
+ "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.",
26823
26902
  "nullable": true,
26824
26903
  "type": "number"
26825
26904
  },
@@ -29803,7 +29882,7 @@
29803
29882
  "type": "object"
29804
29883
  },
29805
29884
  "PropertyParties": {
29806
- "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 /agents/{id}/properties`.",
29885
+ "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`.",
29807
29886
  "properties": {
29808
29887
  "active": {
29809
29888
  "$ref": "#/components/schemas/PropertyPartyRoster"
@@ -32688,3867 +32767,10 @@
32688
32767
  "info": {
32689
32768
  "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.",
32690
32769
  "title": "ModelMatch API",
32691
- "version": "3.64.0"
32770
+ "version": "3.67.0"
32692
32771
  },
32693
32772
  "openapi": "3.1.0",
32694
32773
  "paths": {
32695
- "/agents": {
32696
- "post": {
32697
- "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. 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, 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`.",
32698
- "operationId": "listAgents",
32699
- "requestBody": {
32700
- "content": {
32701
- "application/json": {
32702
- "schema": {
32703
- "$ref": "#/components/schemas/AgentListRequest"
32704
- }
32705
- }
32706
- }
32707
- },
32708
- "responses": {
32709
- "200": {
32710
- "content": {
32711
- "application/json": {
32712
- "schema": {
32713
- "$ref": "#/components/schemas/AgentListResponse"
32714
- }
32715
- }
32716
- },
32717
- "description": "Paginated list of agents"
32718
- },
32719
- "400": {
32720
- "content": {
32721
- "application/json": {
32722
- "schema": {
32723
- "$ref": "#/components/schemas/ErrorResponse"
32724
- }
32725
- }
32726
- },
32727
- "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."
32728
- },
32729
- "401": {
32730
- "content": {
32731
- "application/json": {
32732
- "schema": {
32733
- "$ref": "#/components/schemas/ErrorResponse"
32734
- }
32735
- }
32736
- },
32737
- "description": "Unauthorized"
32738
- },
32739
- "403": {
32740
- "content": {
32741
- "application/json": {
32742
- "schema": {
32743
- "$ref": "#/components/schemas/ErrorResponse"
32744
- }
32745
- }
32746
- },
32747
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
32748
- },
32749
- "404": {
32750
- "content": {
32751
- "application/json": {
32752
- "schema": {
32753
- "$ref": "#/components/schemas/ErrorResponse"
32754
- }
32755
- }
32756
- },
32757
- "description": "Not found"
32758
- },
32759
- "413": {
32760
- "content": {
32761
- "application/json": {
32762
- "schema": {
32763
- "$ref": "#/components/schemas/PayloadTooLarge"
32764
- }
32765
- }
32766
- },
32767
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
32768
- },
32769
- "503": {
32770
- "content": {
32771
- "application/json": {
32772
- "schema": {
32773
- "$ref": "#/components/schemas/ErrorResponse"
32774
- }
32775
- }
32776
- },
32777
- "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."
32778
- }
32779
- },
32780
- "summary": "Search agents with filters",
32781
- "tags": [
32782
- "Agents"
32783
- ]
32784
- }
32785
- },
32786
- "/agents/analytics/chart": {
32787
- "post": {
32788
- "operationId": "agentAnalyticsChart",
32789
- "requestBody": {
32790
- "content": {
32791
- "application/json": {
32792
- "schema": {
32793
- "$ref": "#/components/schemas/AgentChartRequest"
32794
- }
32795
- }
32796
- }
32797
- },
32798
- "responses": {
32799
- "200": {
32800
- "content": {
32801
- "application/json": {
32802
- "schema": {
32803
- "$ref": "#/components/schemas/ChartResponse"
32804
- }
32805
- }
32806
- },
32807
- "description": "Chart data"
32808
- },
32809
- "400": {
32810
- "content": {
32811
- "application/json": {
32812
- "schema": {
32813
- "$ref": "#/components/schemas/ErrorResponse"
32814
- }
32815
- }
32816
- },
32817
- "description": "Validation error"
32818
- },
32819
- "401": {
32820
- "content": {
32821
- "application/json": {
32822
- "schema": {
32823
- "$ref": "#/components/schemas/ErrorResponse"
32824
- }
32825
- }
32826
- },
32827
- "description": "Unauthorized"
32828
- },
32829
- "403": {
32830
- "content": {
32831
- "application/json": {
32832
- "schema": {
32833
- "$ref": "#/components/schemas/ErrorResponse"
32834
- }
32835
- }
32836
- },
32837
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
32838
- },
32839
- "404": {
32840
- "content": {
32841
- "application/json": {
32842
- "schema": {
32843
- "$ref": "#/components/schemas/ErrorResponse"
32844
- }
32845
- }
32846
- },
32847
- "description": "Not found"
32848
- },
32849
- "413": {
32850
- "content": {
32851
- "application/json": {
32852
- "schema": {
32853
- "$ref": "#/components/schemas/PayloadTooLarge"
32854
- }
32855
- }
32856
- },
32857
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
32858
- }
32859
- },
32860
- "summary": "Configurable chart (measure × slice) over the agent's sales",
32861
- "tags": [
32862
- "Agents"
32863
- ]
32864
- }
32865
- },
32866
- "/agents/analytics/summary": {
32867
- "post": {
32868
- "operationId": "agentAnalyticsSummary",
32869
- "requestBody": {
32870
- "content": {
32871
- "application/json": {
32872
- "schema": {
32873
- "$ref": "#/components/schemas/AgentSummaryRequest"
32874
- }
32875
- }
32876
- }
32877
- },
32878
- "responses": {
32879
- "200": {
32880
- "content": {
32881
- "application/json": {
32882
- "schema": {
32883
- "$ref": "#/components/schemas/SidedSummaryResponse"
32884
- }
32885
- }
32886
- },
32887
- "description": "Sided summary with previous-period comparison"
32888
- },
32889
- "400": {
32890
- "content": {
32891
- "application/json": {
32892
- "schema": {
32893
- "$ref": "#/components/schemas/ErrorResponse"
32894
- }
32895
- }
32896
- },
32897
- "description": "Validation error"
32898
- },
32899
- "401": {
32900
- "content": {
32901
- "application/json": {
32902
- "schema": {
32903
- "$ref": "#/components/schemas/ErrorResponse"
32904
- }
32905
- }
32906
- },
32907
- "description": "Unauthorized"
32908
- },
32909
- "403": {
32910
- "content": {
32911
- "application/json": {
32912
- "schema": {
32913
- "$ref": "#/components/schemas/ErrorResponse"
32914
- }
32915
- }
32916
- },
32917
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
32918
- },
32919
- "404": {
32920
- "content": {
32921
- "application/json": {
32922
- "schema": {
32923
- "$ref": "#/components/schemas/ErrorResponse"
32924
- }
32925
- }
32926
- },
32927
- "description": "Not found"
32928
- },
32929
- "413": {
32930
- "content": {
32931
- "application/json": {
32932
- "schema": {
32933
- "$ref": "#/components/schemas/PayloadTooLarge"
32934
- }
32935
- }
32936
- },
32937
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
32938
- }
32939
- },
32940
- "summary": "Production summary with buyer/seller/dual split + previous period",
32941
- "tags": [
32942
- "Agents"
32943
- ]
32944
- }
32945
- },
32946
- "/agents/analytics/time-series": {
32947
- "post": {
32948
- "operationId": "agentAnalyticsTimeSeries",
32949
- "requestBody": {
32950
- "content": {
32951
- "application/json": {
32952
- "schema": {
32953
- "$ref": "#/components/schemas/AgentTimeSeriesRequest"
32954
- }
32955
- }
32956
- }
32957
- },
32958
- "responses": {
32959
- "200": {
32960
- "content": {
32961
- "application/json": {
32962
- "schema": {
32963
- "$ref": "#/components/schemas/SidedTimeSeriesResponse"
32964
- }
32965
- }
32966
- },
32967
- "description": "Time-series with side splits + previous period"
32968
- },
32969
- "400": {
32970
- "content": {
32971
- "application/json": {
32972
- "schema": {
32973
- "$ref": "#/components/schemas/ErrorResponse"
32974
- }
32975
- }
32976
- },
32977
- "description": "Validation error"
32978
- },
32979
- "401": {
32980
- "content": {
32981
- "application/json": {
32982
- "schema": {
32983
- "$ref": "#/components/schemas/ErrorResponse"
32984
- }
32985
- }
32986
- },
32987
- "description": "Unauthorized"
32988
- },
32989
- "403": {
32990
- "content": {
32991
- "application/json": {
32992
- "schema": {
32993
- "$ref": "#/components/schemas/ErrorResponse"
32994
- }
32995
- }
32996
- },
32997
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
32998
- },
32999
- "404": {
33000
- "content": {
33001
- "application/json": {
33002
- "schema": {
33003
- "$ref": "#/components/schemas/ErrorResponse"
33004
- }
33005
- }
33006
- },
33007
- "description": "Not found"
33008
- },
33009
- "413": {
33010
- "content": {
33011
- "application/json": {
33012
- "schema": {
33013
- "$ref": "#/components/schemas/PayloadTooLarge"
33014
- }
33015
- }
33016
- },
33017
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33018
- }
33019
- },
33020
- "summary": "Agent volume/units over time with buyer/seller/dual split",
33021
- "tags": [
33022
- "Agents"
33023
- ]
33024
- }
33025
- },
33026
- "/agents/bulk-delivery": {
33027
- "post": {
33028
- "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.\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, except that push-target deliveries from the ModelMatch web app are not billed.",
33029
- "operationId": "submitAgentsBulkDelivery",
33030
- "requestBody": {
33031
- "content": {
33032
- "application/json": {
33033
- "schema": {
33034
- "allOf": [
33035
- {
33036
- "$ref": "#/components/schemas/AgentListRequest"
33037
- },
33038
- {
33039
- "additionalProperties": false,
33040
- "properties": {
33041
- "destination": {
33042
- "$ref": "#/components/schemas/BulkDeliveryDestination"
33043
- },
33044
- "fields": {
33045
- "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; and `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on. 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.",
33046
- "items": {
33047
- "minLength": 1,
33048
- "type": "string"
33049
- },
33050
- "type": "array"
33051
- },
33052
- "format": {
33053
- "$ref": "#/components/schemas/BulkDeliveryFormat"
33054
- },
33055
- "limit": {
33056
- "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.",
33057
- "example": 5000,
33058
- "exclusiveMinimum": true,
33059
- "minimum": 0,
33060
- "type": "integer"
33061
- }
33062
- },
33063
- "type": "object"
33064
- }
33065
- ]
33066
- }
33067
- }
33068
- }
33069
- },
33070
- "responses": {
33071
- "202": {
33072
- "content": {
33073
- "application/json": {
33074
- "schema": {
33075
- "$ref": "#/components/schemas/BulkDeliverySubmitResponse"
33076
- }
33077
- }
33078
- },
33079
- "description": "Job queued; ECS task launched"
33080
- },
33081
- "400": {
33082
- "content": {
33083
- "application/json": {
33084
- "schema": {
33085
- "anyOf": [
33086
- {
33087
- "$ref": "#/components/schemas/ErrorResponse"
33088
- },
33089
- {
33090
- "$ref": "#/components/schemas/BulkDeliveryPreflightExceeded"
33091
- },
33092
- {
33093
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
33094
- }
33095
- ]
33096
- }
33097
- }
33098
- },
33099
- "description": "Validation failure (incl. `format_required`: a file delivery needs `format`), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"
33100
- },
33101
- "401": {
33102
- "content": {
33103
- "application/json": {
33104
- "schema": {
33105
- "$ref": "#/components/schemas/ErrorResponse"
33106
- }
33107
- }
33108
- },
33109
- "description": "Authentication required"
33110
- },
33111
- "402": {
33112
- "content": {
33113
- "application/json": {
33114
- "schema": {
33115
- "anyOf": [
33116
- {
33117
- "$ref": "#/components/schemas/BulkDeliveryInsufficientCredits"
33118
- },
33119
- {
33120
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
33121
- }
33122
- ]
33123
- }
33124
- }
33125
- },
33126
- "description": "Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"
33127
- },
33128
- "403": {
33129
- "content": {
33130
- "application/json": {
33131
- "schema": {
33132
- "anyOf": [
33133
- {
33134
- "$ref": "#/components/schemas/BulkDeliveryForbidden"
33135
- },
33136
- {
33137
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
33138
- },
33139
- {
33140
- "$ref": "#/components/schemas/BulkDeliveryInsufficientScope"
33141
- }
33142
- ]
33143
- }
33144
- }
33145
- },
33146
- "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`)."
33147
- },
33148
- "404": {
33149
- "content": {
33150
- "application/json": {
33151
- "schema": {
33152
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
33153
- }
33154
- }
33155
- },
33156
- "description": "Push target not found (`TARGET_NOT_FOUND`)"
33157
- },
33158
- "409": {
33159
- "content": {
33160
- "application/json": {
33161
- "schema": {
33162
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
33163
- }
33164
- }
33165
- },
33166
- "description": "Push target is disabled (`TARGET_DISABLED`)"
33167
- },
33168
- "502": {
33169
- "content": {
33170
- "application/json": {
33171
- "schema": {
33172
- "$ref": "#/components/schemas/ErrorResponse"
33173
- }
33174
- }
33175
- },
33176
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
33177
- }
33178
- },
33179
- "summary": "Submit a bulk-delivery job for agents",
33180
- "tags": [
33181
- "Agents"
33182
- ]
33183
- }
33184
- },
33185
- "/agents/bulk-delivery/{jobId}": {
33186
- "delete": {
33187
- "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.",
33188
- "operationId": "cancelAgentsBulkDeliveryJob",
33189
- "parameters": [
33190
- {
33191
- "description": "Job ID returned by `POST /v1/agents/bulk-delivery`",
33192
- "in": "path",
33193
- "name": "jobId",
33194
- "required": true,
33195
- "schema": {
33196
- "description": "Job ID returned by `POST /v1/agents/bulk-delivery`",
33197
- "type": "string"
33198
- }
33199
- }
33200
- ],
33201
- "responses": {
33202
- "200": {
33203
- "content": {
33204
- "application/json": {
33205
- "schema": {
33206
- "$ref": "#/components/schemas/BulkDeliveryStatusResponse"
33207
- }
33208
- }
33209
- },
33210
- "description": "Job cancelled; body is its settled status"
33211
- },
33212
- "401": {
33213
- "content": {
33214
- "application/json": {
33215
- "schema": {
33216
- "$ref": "#/components/schemas/ErrorResponse"
33217
- }
33218
- }
33219
- },
33220
- "description": "Authentication required"
33221
- },
33222
- "403": {
33223
- "content": {
33224
- "application/json": {
33225
- "schema": {
33226
- "$ref": "#/components/schemas/ErrorResponse"
33227
- }
33228
- }
33229
- },
33230
- "description": "Caller does not own this job"
33231
- },
33232
- "404": {
33233
- "content": {
33234
- "application/json": {
33235
- "schema": {
33236
- "$ref": "#/components/schemas/ErrorResponse"
33237
- }
33238
- }
33239
- },
33240
- "description": "Job not found (or expired past 30d TTL)"
33241
- },
33242
- "409": {
33243
- "content": {
33244
- "application/json": {
33245
- "schema": {
33246
- "$ref": "#/components/schemas/ErrorResponse"
33247
- }
33248
- }
33249
- },
33250
- "description": "Job already finished — nothing to cancel"
33251
- }
33252
- },
33253
- "summary": "Cancel a bulk-delivery job for agents",
33254
- "tags": [
33255
- "Agents"
33256
- ]
33257
- },
33258
- "get": {
33259
- "operationId": "getAgentsBulkDeliveryJob",
33260
- "parameters": [
33261
- {
33262
- "description": "Job ID returned by `POST /v1/agents/bulk-delivery`",
33263
- "in": "path",
33264
- "name": "jobId",
33265
- "required": true,
33266
- "schema": {
33267
- "description": "Job ID returned by `POST /v1/agents/bulk-delivery`",
33268
- "type": "string"
33269
- }
33270
- }
33271
- ],
33272
- "responses": {
33273
- "200": {
33274
- "content": {
33275
- "application/json": {
33276
- "schema": {
33277
- "$ref": "#/components/schemas/BulkDeliveryStatusResponse"
33278
- }
33279
- }
33280
- },
33281
- "description": "Job status (resultsUrl re-signed if completed)"
33282
- },
33283
- "401": {
33284
- "content": {
33285
- "application/json": {
33286
- "schema": {
33287
- "$ref": "#/components/schemas/ErrorResponse"
33288
- }
33289
- }
33290
- },
33291
- "description": "Authentication required"
33292
- },
33293
- "403": {
33294
- "content": {
33295
- "application/json": {
33296
- "schema": {
33297
- "$ref": "#/components/schemas/ErrorResponse"
33298
- }
33299
- }
33300
- },
33301
- "description": "Caller does not own this job"
33302
- },
33303
- "404": {
33304
- "content": {
33305
- "application/json": {
33306
- "schema": {
33307
- "$ref": "#/components/schemas/ErrorResponse"
33308
- }
33309
- }
33310
- },
33311
- "description": "Job not found (or expired past 30d TTL)"
33312
- }
33313
- },
33314
- "summary": "Get bulk-delivery job status for agents",
33315
- "tags": [
33316
- "Agents"
33317
- ]
33318
- }
33319
- },
33320
- "/agents/count": {
33321
- "post": {
33322
- "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`.",
33323
- "operationId": "countAgents",
33324
- "requestBody": {
33325
- "content": {
33326
- "application/json": {
33327
- "schema": {
33328
- "$ref": "#/components/schemas/AgentListRequest"
33329
- }
33330
- }
33331
- }
33332
- },
33333
- "responses": {
33334
- "200": {
33335
- "content": {
33336
- "application/json": {
33337
- "schema": {
33338
- "$ref": "#/components/schemas/CountResponse"
33339
- }
33340
- }
33341
- },
33342
- "description": "Exact count of matching agents"
33343
- },
33344
- "400": {
33345
- "content": {
33346
- "application/json": {
33347
- "schema": {
33348
- "$ref": "#/components/schemas/ErrorResponse"
33349
- }
33350
- }
33351
- },
33352
- "description": "Validation error"
33353
- },
33354
- "401": {
33355
- "content": {
33356
- "application/json": {
33357
- "schema": {
33358
- "$ref": "#/components/schemas/ErrorResponse"
33359
- }
33360
- }
33361
- },
33362
- "description": "Unauthorized"
33363
- },
33364
- "403": {
33365
- "content": {
33366
- "application/json": {
33367
- "schema": {
33368
- "$ref": "#/components/schemas/ErrorResponse"
33369
- }
33370
- }
33371
- },
33372
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33373
- },
33374
- "404": {
33375
- "content": {
33376
- "application/json": {
33377
- "schema": {
33378
- "$ref": "#/components/schemas/ErrorResponse"
33379
- }
33380
- }
33381
- },
33382
- "description": "Not found"
33383
- },
33384
- "413": {
33385
- "content": {
33386
- "application/json": {
33387
- "schema": {
33388
- "$ref": "#/components/schemas/PayloadTooLarge"
33389
- }
33390
- }
33391
- },
33392
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33393
- },
33394
- "503": {
33395
- "content": {
33396
- "application/json": {
33397
- "schema": {
33398
- "$ref": "#/components/schemas/ErrorResponse"
33399
- }
33400
- }
33401
- },
33402
- "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."
33403
- }
33404
- },
33405
- "summary": "Count agents matching filters",
33406
- "tags": [
33407
- "Agents"
33408
- ],
33409
- "x-mm-records-via": "listAgents"
33410
- }
33411
- },
33412
- "/agents/{id}": {
33413
- "get": {
33414
- "operationId": "getAgent",
33415
- "parameters": [
33416
- {
33417
- "description": "Agent document ID",
33418
- "in": "path",
33419
- "name": "id",
33420
- "required": true,
33421
- "schema": {
33422
- "description": "Agent document ID",
33423
- "type": "string"
33424
- }
33425
- },
33426
- {
33427
- "description": "Period for volume/units (default: last12Months)",
33428
- "in": "query",
33429
- "name": "period",
33430
- "required": false,
33431
- "schema": {
33432
- "allOf": [
33433
- {
33434
- "$ref": "#/components/schemas/Period"
33435
- },
33436
- {
33437
- "description": "Period for volume/units (default: last12Months)"
33438
- }
33439
- ]
33440
- }
33441
- }
33442
- ],
33443
- "responses": {
33444
- "200": {
33445
- "content": {
33446
- "application/json": {
33447
- "schema": {
33448
- "$ref": "#/components/schemas/AgentDetailResponse"
33449
- }
33450
- }
33451
- },
33452
- "description": "Agent detail"
33453
- },
33454
- "404": {
33455
- "content": {
33456
- "application/json": {
33457
- "schema": {
33458
- "$ref": "#/components/schemas/ErrorResponse"
33459
- }
33460
- }
33461
- },
33462
- "description": "Agent not found"
33463
- },
33464
- "413": {
33465
- "content": {
33466
- "application/json": {
33467
- "schema": {
33468
- "$ref": "#/components/schemas/PayloadTooLarge"
33469
- }
33470
- }
33471
- },
33472
- "description": "Response payload too large"
33473
- }
33474
- },
33475
- "summary": "Get agent by ID",
33476
- "tags": [
33477
- "Agents"
33478
- ]
33479
- }
33480
- },
33481
- "/agents/{id}/breakdowns/cities": {
33482
- "post": {
33483
- "operationId": "agentCities",
33484
- "parameters": [
33485
- {
33486
- "description": "Agent document ID",
33487
- "in": "path",
33488
- "name": "id",
33489
- "required": true,
33490
- "schema": {
33491
- "description": "Agent document ID",
33492
- "type": "string"
33493
- }
33494
- }
33495
- ],
33496
- "requestBody": {
33497
- "content": {
33498
- "application/json": {
33499
- "schema": {
33500
- "$ref": "#/components/schemas/BreakdownRequest"
33501
- }
33502
- }
33503
- }
33504
- },
33505
- "responses": {
33506
- "200": {
33507
- "content": {
33508
- "application/json": {
33509
- "schema": {
33510
- "$ref": "#/components/schemas/BreakdownResponse"
33511
- }
33512
- }
33513
- },
33514
- "description": "Breakdown of the agent's sales by cities"
33515
- },
33516
- "400": {
33517
- "content": {
33518
- "application/json": {
33519
- "schema": {
33520
- "$ref": "#/components/schemas/ErrorResponse"
33521
- }
33522
- }
33523
- },
33524
- "description": "Validation error"
33525
- },
33526
- "401": {
33527
- "content": {
33528
- "application/json": {
33529
- "schema": {
33530
- "$ref": "#/components/schemas/ErrorResponse"
33531
- }
33532
- }
33533
- },
33534
- "description": "Unauthorized"
33535
- },
33536
- "403": {
33537
- "content": {
33538
- "application/json": {
33539
- "schema": {
33540
- "$ref": "#/components/schemas/ErrorResponse"
33541
- }
33542
- }
33543
- },
33544
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33545
- },
33546
- "404": {
33547
- "content": {
33548
- "application/json": {
33549
- "schema": {
33550
- "$ref": "#/components/schemas/ErrorResponse"
33551
- }
33552
- }
33553
- },
33554
- "description": "Not found"
33555
- },
33556
- "413": {
33557
- "content": {
33558
- "application/json": {
33559
- "schema": {
33560
- "$ref": "#/components/schemas/PayloadTooLarge"
33561
- }
33562
- }
33563
- },
33564
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33565
- }
33566
- },
33567
- "summary": "City volume breakdown across the agent's sales",
33568
- "tags": [
33569
- "Agents"
33570
- ]
33571
- }
33572
- },
33573
- "/agents/{id}/breakdowns/companies": {
33574
- "post": {
33575
- "operationId": "agentCompanies",
33576
- "parameters": [
33577
- {
33578
- "description": "Agent document ID",
33579
- "in": "path",
33580
- "name": "id",
33581
- "required": true,
33582
- "schema": {
33583
- "description": "Agent document ID",
33584
- "type": "string"
33585
- }
33586
- }
33587
- ],
33588
- "requestBody": {
33589
- "content": {
33590
- "application/json": {
33591
- "schema": {
33592
- "$ref": "#/components/schemas/ScoredBreakdownRequest"
33593
- }
33594
- }
33595
- }
33596
- },
33597
- "responses": {
33598
- "200": {
33599
- "content": {
33600
- "application/json": {
33601
- "schema": {
33602
- "$ref": "#/components/schemas/BreakdownResponse"
33603
- }
33604
- }
33605
- },
33606
- "description": "Pre-aggregated companies breakdown from the agent's scored doc"
33607
- },
33608
- "400": {
33609
- "content": {
33610
- "application/json": {
33611
- "schema": {
33612
- "$ref": "#/components/schemas/ErrorResponse"
33613
- }
33614
- }
33615
- },
33616
- "description": "Validation error"
33617
- },
33618
- "401": {
33619
- "content": {
33620
- "application/json": {
33621
- "schema": {
33622
- "$ref": "#/components/schemas/ErrorResponse"
33623
- }
33624
- }
33625
- },
33626
- "description": "Unauthorized"
33627
- },
33628
- "403": {
33629
- "content": {
33630
- "application/json": {
33631
- "schema": {
33632
- "$ref": "#/components/schemas/ErrorResponse"
33633
- }
33634
- }
33635
- },
33636
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33637
- },
33638
- "404": {
33639
- "content": {
33640
- "application/json": {
33641
- "schema": {
33642
- "$ref": "#/components/schemas/ErrorResponse"
33643
- }
33644
- }
33645
- },
33646
- "description": "Not found"
33647
- },
33648
- "413": {
33649
- "content": {
33650
- "application/json": {
33651
- "schema": {
33652
- "$ref": "#/components/schemas/PayloadTooLarge"
33653
- }
33654
- }
33655
- },
33656
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33657
- }
33658
- },
33659
- "summary": "Mortgage companies the agent dealt with (pre-aggregated)",
33660
- "tags": [
33661
- "Agents"
33662
- ]
33663
- }
33664
- },
33665
- "/agents/{id}/breakdowns/counties": {
33666
- "post": {
33667
- "operationId": "agentCounties",
33668
- "parameters": [
33669
- {
33670
- "description": "Agent document ID",
33671
- "in": "path",
33672
- "name": "id",
33673
- "required": true,
33674
- "schema": {
33675
- "description": "Agent document ID",
33676
- "type": "string"
33677
- }
33678
- }
33679
- ],
33680
- "requestBody": {
33681
- "content": {
33682
- "application/json": {
33683
- "schema": {
33684
- "$ref": "#/components/schemas/BreakdownRequest"
33685
- }
33686
- }
33687
- }
33688
- },
33689
- "responses": {
33690
- "200": {
33691
- "content": {
33692
- "application/json": {
33693
- "schema": {
33694
- "$ref": "#/components/schemas/BreakdownResponse"
33695
- }
33696
- }
33697
- },
33698
- "description": "Breakdown of the agent's sales by counties"
33699
- },
33700
- "400": {
33701
- "content": {
33702
- "application/json": {
33703
- "schema": {
33704
- "$ref": "#/components/schemas/ErrorResponse"
33705
- }
33706
- }
33707
- },
33708
- "description": "Validation error"
33709
- },
33710
- "401": {
33711
- "content": {
33712
- "application/json": {
33713
- "schema": {
33714
- "$ref": "#/components/schemas/ErrorResponse"
33715
- }
33716
- }
33717
- },
33718
- "description": "Unauthorized"
33719
- },
33720
- "403": {
33721
- "content": {
33722
- "application/json": {
33723
- "schema": {
33724
- "$ref": "#/components/schemas/ErrorResponse"
33725
- }
33726
- }
33727
- },
33728
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33729
- },
33730
- "404": {
33731
- "content": {
33732
- "application/json": {
33733
- "schema": {
33734
- "$ref": "#/components/schemas/ErrorResponse"
33735
- }
33736
- }
33737
- },
33738
- "description": "Not found"
33739
- },
33740
- "413": {
33741
- "content": {
33742
- "application/json": {
33743
- "schema": {
33744
- "$ref": "#/components/schemas/PayloadTooLarge"
33745
- }
33746
- }
33747
- },
33748
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33749
- }
33750
- },
33751
- "summary": "County (FIPS) volume breakdown",
33752
- "tags": [
33753
- "Agents"
33754
- ]
33755
- }
33756
- },
33757
- "/agents/{id}/breakdowns/lenders": {
33758
- "post": {
33759
- "operationId": "agentLenders",
33760
- "parameters": [
33761
- {
33762
- "description": "Agent document ID",
33763
- "in": "path",
33764
- "name": "id",
33765
- "required": true,
33766
- "schema": {
33767
- "description": "Agent document ID",
33768
- "type": "string"
33769
- }
33770
- }
33771
- ],
33772
- "requestBody": {
33773
- "content": {
33774
- "application/json": {
33775
- "schema": {
33776
- "$ref": "#/components/schemas/ScoredBreakdownRequest"
33777
- }
33778
- }
33779
- }
33780
- },
33781
- "responses": {
33782
- "200": {
33783
- "content": {
33784
- "application/json": {
33785
- "schema": {
33786
- "$ref": "#/components/schemas/BreakdownResponse"
33787
- }
33788
- }
33789
- },
33790
- "description": "Pre-aggregated lenders breakdown from the agent's scored doc"
33791
- },
33792
- "400": {
33793
- "content": {
33794
- "application/json": {
33795
- "schema": {
33796
- "$ref": "#/components/schemas/ErrorResponse"
33797
- }
33798
- }
33799
- },
33800
- "description": "Validation error"
33801
- },
33802
- "401": {
33803
- "content": {
33804
- "application/json": {
33805
- "schema": {
33806
- "$ref": "#/components/schemas/ErrorResponse"
33807
- }
33808
- }
33809
- },
33810
- "description": "Unauthorized"
33811
- },
33812
- "403": {
33813
- "content": {
33814
- "application/json": {
33815
- "schema": {
33816
- "$ref": "#/components/schemas/ErrorResponse"
33817
- }
33818
- }
33819
- },
33820
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33821
- },
33822
- "404": {
33823
- "content": {
33824
- "application/json": {
33825
- "schema": {
33826
- "$ref": "#/components/schemas/ErrorResponse"
33827
- }
33828
- }
33829
- },
33830
- "description": "Not found"
33831
- },
33832
- "413": {
33833
- "content": {
33834
- "application/json": {
33835
- "schema": {
33836
- "$ref": "#/components/schemas/PayloadTooLarge"
33837
- }
33838
- }
33839
- },
33840
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33841
- }
33842
- },
33843
- "summary": "Raw-name lenders encountered (pre-aggregated)",
33844
- "tags": [
33845
- "Agents"
33846
- ]
33847
- }
33848
- },
33849
- "/agents/{id}/breakdowns/offices": {
33850
- "post": {
33851
- "operationId": "agentOffices",
33852
- "parameters": [
33853
- {
33854
- "description": "Agent document ID",
33855
- "in": "path",
33856
- "name": "id",
33857
- "required": true,
33858
- "schema": {
33859
- "description": "Agent document ID",
33860
- "type": "string"
33861
- }
33862
- }
33863
- ],
33864
- "requestBody": {
33865
- "content": {
33866
- "application/json": {
33867
- "schema": {
33868
- "$ref": "#/components/schemas/BreakdownRequest"
33869
- }
33870
- }
33871
- }
33872
- },
33873
- "responses": {
33874
- "200": {
33875
- "content": {
33876
- "application/json": {
33877
- "schema": {
33878
- "$ref": "#/components/schemas/BreakdownResponse"
33879
- }
33880
- }
33881
- },
33882
- "description": "Breakdown of the agent's sales by offices"
33883
- },
33884
- "400": {
33885
- "content": {
33886
- "application/json": {
33887
- "schema": {
33888
- "$ref": "#/components/schemas/ErrorResponse"
33889
- }
33890
- }
33891
- },
33892
- "description": "Validation error"
33893
- },
33894
- "401": {
33895
- "content": {
33896
- "application/json": {
33897
- "schema": {
33898
- "$ref": "#/components/schemas/ErrorResponse"
33899
- }
33900
- }
33901
- },
33902
- "description": "Unauthorized"
33903
- },
33904
- "403": {
33905
- "content": {
33906
- "application/json": {
33907
- "schema": {
33908
- "$ref": "#/components/schemas/ErrorResponse"
33909
- }
33910
- }
33911
- },
33912
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
33913
- },
33914
- "404": {
33915
- "content": {
33916
- "application/json": {
33917
- "schema": {
33918
- "$ref": "#/components/schemas/ErrorResponse"
33919
- }
33920
- }
33921
- },
33922
- "description": "Not found"
33923
- },
33924
- "413": {
33925
- "content": {
33926
- "application/json": {
33927
- "schema": {
33928
- "$ref": "#/components/schemas/PayloadTooLarge"
33929
- }
33930
- }
33931
- },
33932
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
33933
- }
33934
- },
33935
- "summary": "Listing offices the agent has closed through",
33936
- "tags": [
33937
- "Agents"
33938
- ]
33939
- }
33940
- },
33941
- "/agents/{id}/breakdowns/originators": {
33942
- "post": {
33943
- "operationId": "agentOriginators",
33944
- "parameters": [
33945
- {
33946
- "description": "Agent document ID",
33947
- "in": "path",
33948
- "name": "id",
33949
- "required": true,
33950
- "schema": {
33951
- "description": "Agent document ID",
33952
- "type": "string"
33953
- }
33954
- }
33955
- ],
33956
- "requestBody": {
33957
- "content": {
33958
- "application/json": {
33959
- "schema": {
33960
- "$ref": "#/components/schemas/ScoredBreakdownRequest"
33961
- }
33962
- }
33963
- }
33964
- },
33965
- "responses": {
33966
- "200": {
33967
- "content": {
33968
- "application/json": {
33969
- "schema": {
33970
- "$ref": "#/components/schemas/BreakdownResponse"
33971
- }
33972
- }
33973
- },
33974
- "description": "Pre-aggregated originators breakdown from the agent's scored doc"
33975
- },
33976
- "400": {
33977
- "content": {
33978
- "application/json": {
33979
- "schema": {
33980
- "$ref": "#/components/schemas/ErrorResponse"
33981
- }
33982
- }
33983
- },
33984
- "description": "Validation error"
33985
- },
33986
- "401": {
33987
- "content": {
33988
- "application/json": {
33989
- "schema": {
33990
- "$ref": "#/components/schemas/ErrorResponse"
33991
- }
33992
- }
33993
- },
33994
- "description": "Unauthorized"
33995
- },
33996
- "403": {
33997
- "content": {
33998
- "application/json": {
33999
- "schema": {
34000
- "$ref": "#/components/schemas/ErrorResponse"
34001
- }
34002
- }
34003
- },
34004
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34005
- },
34006
- "404": {
34007
- "content": {
34008
- "application/json": {
34009
- "schema": {
34010
- "$ref": "#/components/schemas/ErrorResponse"
34011
- }
34012
- }
34013
- },
34014
- "description": "Not found"
34015
- },
34016
- "413": {
34017
- "content": {
34018
- "application/json": {
34019
- "schema": {
34020
- "$ref": "#/components/schemas/PayloadTooLarge"
34021
- }
34022
- }
34023
- },
34024
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34025
- }
34026
- },
34027
- "summary": "Loan officers the agent worked with (pre-aggregated)",
34028
- "tags": [
34029
- "Agents"
34030
- ]
34031
- }
34032
- },
34033
- "/agents/{id}/breakdowns/states": {
34034
- "post": {
34035
- "operationId": "agentStates",
34036
- "parameters": [
34037
- {
34038
- "description": "Agent document ID",
34039
- "in": "path",
34040
- "name": "id",
34041
- "required": true,
34042
- "schema": {
34043
- "description": "Agent document ID",
34044
- "type": "string"
34045
- }
34046
- }
34047
- ],
34048
- "requestBody": {
34049
- "content": {
34050
- "application/json": {
34051
- "schema": {
34052
- "$ref": "#/components/schemas/BreakdownRequest"
34053
- }
34054
- }
34055
- }
34056
- },
34057
- "responses": {
34058
- "200": {
34059
- "content": {
34060
- "application/json": {
34061
- "schema": {
34062
- "$ref": "#/components/schemas/BreakdownResponse"
34063
- }
34064
- }
34065
- },
34066
- "description": "Breakdown of the agent's sales by states"
34067
- },
34068
- "400": {
34069
- "content": {
34070
- "application/json": {
34071
- "schema": {
34072
- "$ref": "#/components/schemas/ErrorResponse"
34073
- }
34074
- }
34075
- },
34076
- "description": "Validation error"
34077
- },
34078
- "401": {
34079
- "content": {
34080
- "application/json": {
34081
- "schema": {
34082
- "$ref": "#/components/schemas/ErrorResponse"
34083
- }
34084
- }
34085
- },
34086
- "description": "Unauthorized"
34087
- },
34088
- "403": {
34089
- "content": {
34090
- "application/json": {
34091
- "schema": {
34092
- "$ref": "#/components/schemas/ErrorResponse"
34093
- }
34094
- }
34095
- },
34096
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34097
- },
34098
- "404": {
34099
- "content": {
34100
- "application/json": {
34101
- "schema": {
34102
- "$ref": "#/components/schemas/ErrorResponse"
34103
- }
34104
- }
34105
- },
34106
- "description": "Not found"
34107
- },
34108
- "413": {
34109
- "content": {
34110
- "application/json": {
34111
- "schema": {
34112
- "$ref": "#/components/schemas/PayloadTooLarge"
34113
- }
34114
- }
34115
- },
34116
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34117
- }
34118
- },
34119
- "summary": "State volume breakdown",
34120
- "tags": [
34121
- "Agents"
34122
- ]
34123
- }
34124
- },
34125
- "/agents/{id}/breakdowns/zip-codes": {
34126
- "post": {
34127
- "operationId": "agentZipCodes",
34128
- "parameters": [
34129
- {
34130
- "description": "Agent document ID",
34131
- "in": "path",
34132
- "name": "id",
34133
- "required": true,
34134
- "schema": {
34135
- "description": "Agent document ID",
34136
- "type": "string"
34137
- }
34138
- }
34139
- ],
34140
- "requestBody": {
34141
- "content": {
34142
- "application/json": {
34143
- "schema": {
34144
- "$ref": "#/components/schemas/BreakdownRequest"
34145
- }
34146
- }
34147
- }
34148
- },
34149
- "responses": {
34150
- "200": {
34151
- "content": {
34152
- "application/json": {
34153
- "schema": {
34154
- "$ref": "#/components/schemas/BreakdownResponse"
34155
- }
34156
- }
34157
- },
34158
- "description": "Breakdown of the agent's sales by zip-codes"
34159
- },
34160
- "400": {
34161
- "content": {
34162
- "application/json": {
34163
- "schema": {
34164
- "$ref": "#/components/schemas/ErrorResponse"
34165
- }
34166
- }
34167
- },
34168
- "description": "Validation error"
34169
- },
34170
- "401": {
34171
- "content": {
34172
- "application/json": {
34173
- "schema": {
34174
- "$ref": "#/components/schemas/ErrorResponse"
34175
- }
34176
- }
34177
- },
34178
- "description": "Unauthorized"
34179
- },
34180
- "403": {
34181
- "content": {
34182
- "application/json": {
34183
- "schema": {
34184
- "$ref": "#/components/schemas/ErrorResponse"
34185
- }
34186
- }
34187
- },
34188
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34189
- },
34190
- "404": {
34191
- "content": {
34192
- "application/json": {
34193
- "schema": {
34194
- "$ref": "#/components/schemas/ErrorResponse"
34195
- }
34196
- }
34197
- },
34198
- "description": "Not found"
34199
- },
34200
- "413": {
34201
- "content": {
34202
- "application/json": {
34203
- "schema": {
34204
- "$ref": "#/components/schemas/PayloadTooLarge"
34205
- }
34206
- }
34207
- },
34208
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34209
- }
34210
- },
34211
- "summary": "Zip-code volume breakdown",
34212
- "tags": [
34213
- "Agents"
34214
- ]
34215
- }
34216
- },
34217
- "/agents/{id}/markets": {
34218
- "post": {
34219
- "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.",
34220
- "operationId": "agentMarkets",
34221
- "parameters": [
34222
- {
34223
- "description": "Agent ID",
34224
- "in": "path",
34225
- "name": "id",
34226
- "required": true,
34227
- "schema": {
34228
- "description": "Agent ID",
34229
- "type": "string"
34230
- }
34231
- }
34232
- ],
34233
- "requestBody": {
34234
- "content": {
34235
- "application/json": {
34236
- "schema": {
34237
- "$ref": "#/components/schemas/AgentMarketsRequest"
34238
- }
34239
- }
34240
- }
34241
- },
34242
- "responses": {
34243
- "200": {
34244
- "content": {
34245
- "application/json": {
34246
- "schema": {
34247
- "$ref": "#/components/schemas/AgentMarketsResponse"
34248
- }
34249
- }
34250
- },
34251
- "description": "The agent's blended market footprint"
34252
- },
34253
- "400": {
34254
- "content": {
34255
- "application/json": {
34256
- "schema": {
34257
- "$ref": "#/components/schemas/ErrorResponse"
34258
- }
34259
- }
34260
- },
34261
- "description": "Validation error"
34262
- },
34263
- "401": {
34264
- "content": {
34265
- "application/json": {
34266
- "schema": {
34267
- "$ref": "#/components/schemas/ErrorResponse"
34268
- }
34269
- }
34270
- },
34271
- "description": "Unauthorized"
34272
- },
34273
- "403": {
34274
- "content": {
34275
- "application/json": {
34276
- "schema": {
34277
- "$ref": "#/components/schemas/ErrorResponse"
34278
- }
34279
- }
34280
- },
34281
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34282
- },
34283
- "404": {
34284
- "content": {
34285
- "application/json": {
34286
- "schema": {
34287
- "$ref": "#/components/schemas/ErrorResponse"
34288
- }
34289
- }
34290
- },
34291
- "description": "Not found"
34292
- },
34293
- "413": {
34294
- "content": {
34295
- "application/json": {
34296
- "schema": {
34297
- "$ref": "#/components/schemas/PayloadTooLarge"
34298
- }
34299
- }
34300
- },
34301
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34302
- }
34303
- },
34304
- "summary": "The ZIP markets this agent works, blended",
34305
- "tags": [
34306
- "Agents"
34307
- ]
34308
- }
34309
- },
34310
- "/agents/{id}/properties": {
34311
- "post": {
34312
- "operationId": "agentProperties",
34313
- "parameters": [
34314
- {
34315
- "description": "Agent document ID",
34316
- "in": "path",
34317
- "name": "id",
34318
- "required": true,
34319
- "schema": {
34320
- "description": "Agent document ID",
34321
- "type": "string"
34322
- }
34323
- }
34324
- ],
34325
- "requestBody": {
34326
- "content": {
34327
- "application/json": {
34328
- "schema": {
34329
- "$ref": "#/components/schemas/AgentRelationRequest"
34330
- }
34331
- }
34332
- }
34333
- },
34334
- "responses": {
34335
- "200": {
34336
- "content": {
34337
- "application/json": {
34338
- "schema": {
34339
- "$ref": "#/components/schemas/AgentPropertiesResponse"
34340
- }
34341
- }
34342
- },
34343
- "description": "Paginated list of properties for this agent"
34344
- },
34345
- "400": {
34346
- "content": {
34347
- "application/json": {
34348
- "schema": {
34349
- "$ref": "#/components/schemas/ErrorResponse"
34350
- }
34351
- }
34352
- },
34353
- "description": "Validation error"
34354
- },
34355
- "401": {
34356
- "content": {
34357
- "application/json": {
34358
- "schema": {
34359
- "$ref": "#/components/schemas/ErrorResponse"
34360
- }
34361
- }
34362
- },
34363
- "description": "Unauthorized"
34364
- },
34365
- "403": {
34366
- "content": {
34367
- "application/json": {
34368
- "schema": {
34369
- "$ref": "#/components/schemas/ErrorResponse"
34370
- }
34371
- }
34372
- },
34373
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34374
- },
34375
- "404": {
34376
- "content": {
34377
- "application/json": {
34378
- "schema": {
34379
- "$ref": "#/components/schemas/ErrorResponse"
34380
- }
34381
- }
34382
- },
34383
- "description": "Not found"
34384
- },
34385
- "413": {
34386
- "content": {
34387
- "application/json": {
34388
- "schema": {
34389
- "$ref": "#/components/schemas/PayloadTooLarge"
34390
- }
34391
- }
34392
- },
34393
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34394
- }
34395
- },
34396
- "summary": "Properties this agent has transacted on",
34397
- "tags": [
34398
- "Agents"
34399
- ]
34400
- }
34401
- },
34402
- "/agents/{id}/sales": {
34403
- "post": {
34404
- "operationId": "agentSales",
34405
- "parameters": [
34406
- {
34407
- "description": "Agent document ID",
34408
- "in": "path",
34409
- "name": "id",
34410
- "required": true,
34411
- "schema": {
34412
- "description": "Agent document ID",
34413
- "type": "string"
34414
- }
34415
- }
34416
- ],
34417
- "requestBody": {
34418
- "content": {
34419
- "application/json": {
34420
- "schema": {
34421
- "$ref": "#/components/schemas/AgentRelationRequest"
34422
- }
34423
- }
34424
- }
34425
- },
34426
- "responses": {
34427
- "200": {
34428
- "content": {
34429
- "application/json": {
34430
- "schema": {
34431
- "$ref": "#/components/schemas/AgentSalesResponse"
34432
- }
34433
- }
34434
- },
34435
- "description": "Paginated list of sales for this agent"
34436
- },
34437
- "400": {
34438
- "content": {
34439
- "application/json": {
34440
- "schema": {
34441
- "$ref": "#/components/schemas/ErrorResponse"
34442
- }
34443
- }
34444
- },
34445
- "description": "Validation error"
34446
- },
34447
- "401": {
34448
- "content": {
34449
- "application/json": {
34450
- "schema": {
34451
- "$ref": "#/components/schemas/ErrorResponse"
34452
- }
34453
- }
34454
- },
34455
- "description": "Unauthorized"
34456
- },
34457
- "403": {
34458
- "content": {
34459
- "application/json": {
34460
- "schema": {
34461
- "$ref": "#/components/schemas/ErrorResponse"
34462
- }
34463
- }
34464
- },
34465
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34466
- },
34467
- "404": {
34468
- "content": {
34469
- "application/json": {
34470
- "schema": {
34471
- "$ref": "#/components/schemas/ErrorResponse"
34472
- }
34473
- }
34474
- },
34475
- "description": "Not found"
34476
- },
34477
- "413": {
34478
- "content": {
34479
- "application/json": {
34480
- "schema": {
34481
- "$ref": "#/components/schemas/PayloadTooLarge"
34482
- }
34483
- }
34484
- },
34485
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34486
- }
34487
- },
34488
- "summary": "Sales transactions where this agent was listing or selling side",
34489
- "tags": [
34490
- "Agents"
34491
- ]
34492
- }
34493
- },
34494
- "/originators": {
34495
- "post": {
34496
- "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. 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`.",
34497
- "operationId": "listOriginators",
34498
- "requestBody": {
34499
- "content": {
34500
- "application/json": {
34501
- "schema": {
34502
- "$ref": "#/components/schemas/OriginatorListRequest"
34503
- }
34504
- }
34505
- }
34506
- },
34507
- "responses": {
34508
- "200": {
34509
- "content": {
34510
- "application/json": {
34511
- "schema": {
34512
- "$ref": "#/components/schemas/OriginatorListResponse"
34513
- }
34514
- }
34515
- },
34516
- "description": "Paginated list of originators"
34517
- },
34518
- "400": {
34519
- "content": {
34520
- "application/json": {
34521
- "schema": {
34522
- "$ref": "#/components/schemas/ErrorResponse"
34523
- }
34524
- }
34525
- },
34526
- "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."
34527
- },
34528
- "401": {
34529
- "content": {
34530
- "application/json": {
34531
- "schema": {
34532
- "$ref": "#/components/schemas/ErrorResponse"
34533
- }
34534
- }
34535
- },
34536
- "description": "Unauthorized"
34537
- },
34538
- "403": {
34539
- "content": {
34540
- "application/json": {
34541
- "schema": {
34542
- "$ref": "#/components/schemas/ErrorResponse"
34543
- }
34544
- }
34545
- },
34546
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34547
- },
34548
- "404": {
34549
- "content": {
34550
- "application/json": {
34551
- "schema": {
34552
- "$ref": "#/components/schemas/ErrorResponse"
34553
- }
34554
- }
34555
- },
34556
- "description": "Not found"
34557
- },
34558
- "413": {
34559
- "content": {
34560
- "application/json": {
34561
- "schema": {
34562
- "$ref": "#/components/schemas/PayloadTooLarge"
34563
- }
34564
- }
34565
- },
34566
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34567
- }
34568
- },
34569
- "summary": "Search originators with filters",
34570
- "tags": [
34571
- "Originators"
34572
- ]
34573
- }
34574
- },
34575
- "/originators/analytics/chart": {
34576
- "post": {
34577
- "operationId": "originatorAnalyticsChart",
34578
- "requestBody": {
34579
- "content": {
34580
- "application/json": {
34581
- "schema": {
34582
- "$ref": "#/components/schemas/OriginatorChartRequest"
34583
- }
34584
- }
34585
- }
34586
- },
34587
- "responses": {
34588
- "200": {
34589
- "content": {
34590
- "application/json": {
34591
- "schema": {
34592
- "$ref": "#/components/schemas/ChartResponse"
34593
- }
34594
- }
34595
- },
34596
- "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."
34597
- },
34598
- "400": {
34599
- "content": {
34600
- "application/json": {
34601
- "schema": {
34602
- "$ref": "#/components/schemas/ErrorResponse"
34603
- }
34604
- }
34605
- },
34606
- "description": "Validation error"
34607
- },
34608
- "401": {
34609
- "content": {
34610
- "application/json": {
34611
- "schema": {
34612
- "$ref": "#/components/schemas/ErrorResponse"
34613
- }
34614
- }
34615
- },
34616
- "description": "Unauthorized"
34617
- },
34618
- "403": {
34619
- "content": {
34620
- "application/json": {
34621
- "schema": {
34622
- "$ref": "#/components/schemas/ErrorResponse"
34623
- }
34624
- }
34625
- },
34626
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34627
- },
34628
- "404": {
34629
- "content": {
34630
- "application/json": {
34631
- "schema": {
34632
- "$ref": "#/components/schemas/ErrorResponse"
34633
- }
34634
- }
34635
- },
34636
- "description": "Not found"
34637
- },
34638
- "413": {
34639
- "content": {
34640
- "application/json": {
34641
- "schema": {
34642
- "$ref": "#/components/schemas/PayloadTooLarge"
34643
- }
34644
- }
34645
- },
34646
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34647
- }
34648
- },
34649
- "summary": "Configurable chart (measure × slice) over one LO's loans",
34650
- "tags": [
34651
- "Originators"
34652
- ]
34653
- }
34654
- },
34655
- "/originators/analytics/summary": {
34656
- "post": {
34657
- "operationId": "originatorAnalyticsSummary",
34658
- "requestBody": {
34659
- "content": {
34660
- "application/json": {
34661
- "schema": {
34662
- "$ref": "#/components/schemas/OriginatorSummaryRequest"
34663
- }
34664
- }
34665
- }
34666
- },
34667
- "responses": {
34668
- "200": {
34669
- "content": {
34670
- "application/json": {
34671
- "schema": {
34672
- "$ref": "#/components/schemas/SimpleSummaryResponse"
34673
- }
34674
- }
34675
- },
34676
- "description": "Current + previous-period summary"
34677
- },
34678
- "400": {
34679
- "content": {
34680
- "application/json": {
34681
- "schema": {
34682
- "$ref": "#/components/schemas/ErrorResponse"
34683
- }
34684
- }
34685
- },
34686
- "description": "Validation error"
34687
- },
34688
- "401": {
34689
- "content": {
34690
- "application/json": {
34691
- "schema": {
34692
- "$ref": "#/components/schemas/ErrorResponse"
34693
- }
34694
- }
34695
- },
34696
- "description": "Unauthorized"
34697
- },
34698
- "403": {
34699
- "content": {
34700
- "application/json": {
34701
- "schema": {
34702
- "$ref": "#/components/schemas/ErrorResponse"
34703
- }
34704
- }
34705
- },
34706
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34707
- },
34708
- "404": {
34709
- "content": {
34710
- "application/json": {
34711
- "schema": {
34712
- "$ref": "#/components/schemas/ErrorResponse"
34713
- }
34714
- }
34715
- },
34716
- "description": "Not found"
34717
- },
34718
- "413": {
34719
- "content": {
34720
- "application/json": {
34721
- "schema": {
34722
- "$ref": "#/components/schemas/PayloadTooLarge"
34723
- }
34724
- }
34725
- },
34726
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34727
- }
34728
- },
34729
- "summary": "Production summary with previous-period comparison",
34730
- "tags": [
34731
- "Originators"
34732
- ]
34733
- }
34734
- },
34735
- "/originators/analytics/time-series": {
34736
- "post": {
34737
- "operationId": "originatorAnalyticsTimeSeries",
34738
- "requestBody": {
34739
- "content": {
34740
- "application/json": {
34741
- "schema": {
34742
- "$ref": "#/components/schemas/OriginatorTimeSeriesRequest"
34743
- }
34744
- }
34745
- }
34746
- },
34747
- "responses": {
34748
- "200": {
34749
- "content": {
34750
- "application/json": {
34751
- "schema": {
34752
- "$ref": "#/components/schemas/SimpleTimeSeriesResponse"
34753
- }
34754
- }
34755
- },
34756
- "description": "Time-series with previous-period comparison"
34757
- },
34758
- "400": {
34759
- "content": {
34760
- "application/json": {
34761
- "schema": {
34762
- "$ref": "#/components/schemas/ErrorResponse"
34763
- }
34764
- }
34765
- },
34766
- "description": "Validation error"
34767
- },
34768
- "401": {
34769
- "content": {
34770
- "application/json": {
34771
- "schema": {
34772
- "$ref": "#/components/schemas/ErrorResponse"
34773
- }
34774
- }
34775
- },
34776
- "description": "Unauthorized"
34777
- },
34778
- "403": {
34779
- "content": {
34780
- "application/json": {
34781
- "schema": {
34782
- "$ref": "#/components/schemas/ErrorResponse"
34783
- }
34784
- }
34785
- },
34786
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
34787
- },
34788
- "404": {
34789
- "content": {
34790
- "application/json": {
34791
- "schema": {
34792
- "$ref": "#/components/schemas/ErrorResponse"
34793
- }
34794
- }
34795
- },
34796
- "description": "Not found"
34797
- },
34798
- "413": {
34799
- "content": {
34800
- "application/json": {
34801
- "schema": {
34802
- "$ref": "#/components/schemas/PayloadTooLarge"
34803
- }
34804
- }
34805
- },
34806
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
34807
- }
34808
- },
34809
- "summary": "Originator volume / units over time",
34810
- "tags": [
34811
- "Originators"
34812
- ]
34813
- }
34814
- },
34815
- "/originators/bulk-delivery": {
34816
- "post": {
34817
- "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.\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, except that push-target deliveries from the ModelMatch web app are not billed.",
34818
- "operationId": "submitOriginatorsBulkDelivery",
34819
- "requestBody": {
34820
- "content": {
34821
- "application/json": {
34822
- "schema": {
34823
- "allOf": [
34824
- {
34825
- "$ref": "#/components/schemas/OriginatorListRequest"
34826
- },
34827
- {
34828
- "additionalProperties": false,
34829
- "properties": {
34830
- "destination": {
34831
- "$ref": "#/components/schemas/BulkDeliveryDestination"
34832
- },
34833
- "fields": {
34834
- "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; and `marketCount` / `countyCount` / `stateCount` / `zipCount` / `lenderCount` (originators) — the market-breadth rollups you can already filter on. 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.",
34835
- "items": {
34836
- "minLength": 1,
34837
- "type": "string"
34838
- },
34839
- "type": "array"
34840
- },
34841
- "format": {
34842
- "$ref": "#/components/schemas/BulkDeliveryFormat"
34843
- },
34844
- "limit": {
34845
- "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.",
34846
- "example": 5000,
34847
- "exclusiveMinimum": true,
34848
- "minimum": 0,
34849
- "type": "integer"
34850
- }
34851
- },
34852
- "type": "object"
34853
- }
34854
- ]
34855
- }
34856
- }
34857
- }
34858
- },
34859
- "responses": {
34860
- "202": {
34861
- "content": {
34862
- "application/json": {
34863
- "schema": {
34864
- "$ref": "#/components/schemas/BulkDeliverySubmitResponse"
34865
- }
34866
- }
34867
- },
34868
- "description": "Job queued; ECS task launched"
34869
- },
34870
- "400": {
34871
- "content": {
34872
- "application/json": {
34873
- "schema": {
34874
- "anyOf": [
34875
- {
34876
- "$ref": "#/components/schemas/ErrorResponse"
34877
- },
34878
- {
34879
- "$ref": "#/components/schemas/BulkDeliveryPreflightExceeded"
34880
- },
34881
- {
34882
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
34883
- }
34884
- ]
34885
- }
34886
- }
34887
- },
34888
- "description": "Validation failure (incl. `format_required`: a file delivery needs `format`), delivery would exceed the entitlement's maxRows, OR the push target does not accept this entity (`ENTITY_MISMATCH`)"
34889
- },
34890
- "401": {
34891
- "content": {
34892
- "application/json": {
34893
- "schema": {
34894
- "$ref": "#/components/schemas/ErrorResponse"
34895
- }
34896
- }
34897
- },
34898
- "description": "Authentication required"
34899
- },
34900
- "402": {
34901
- "content": {
34902
- "application/json": {
34903
- "schema": {
34904
- "anyOf": [
34905
- {
34906
- "$ref": "#/components/schemas/BulkDeliveryInsufficientCredits"
34907
- },
34908
- {
34909
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
34910
- }
34911
- ]
34912
- }
34913
- }
34914
- },
34915
- "description": "Insufficient credits (balance < estimatedTotal, at 1 credit per row), OR the plan does not include push targets (`PLAN_REQUIRED`)"
34916
- },
34917
- "403": {
34918
- "content": {
34919
- "application/json": {
34920
- "schema": {
34921
- "anyOf": [
34922
- {
34923
- "$ref": "#/components/schemas/BulkDeliveryForbidden"
34924
- },
34925
- {
34926
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
34927
- },
34928
- {
34929
- "$ref": "#/components/schemas/BulkDeliveryInsufficientScope"
34930
- }
34931
- ]
34932
- }
34933
- }
34934
- },
34935
- "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`)."
34936
- },
34937
- "404": {
34938
- "content": {
34939
- "application/json": {
34940
- "schema": {
34941
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
34942
- }
34943
- }
34944
- },
34945
- "description": "Push target not found (`TARGET_NOT_FOUND`)"
34946
- },
34947
- "409": {
34948
- "content": {
34949
- "application/json": {
34950
- "schema": {
34951
- "$ref": "#/components/schemas/BulkDeliveryPushTargetError"
34952
- }
34953
- }
34954
- },
34955
- "description": "Push target is disabled (`TARGET_DISABLED`)"
34956
- },
34957
- "502": {
34958
- "content": {
34959
- "application/json": {
34960
- "schema": {
34961
- "$ref": "#/components/schemas/ErrorResponse"
34962
- }
34963
- }
34964
- },
34965
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
34966
- }
34967
- },
34968
- "summary": "Submit a bulk-delivery job for originators",
34969
- "tags": [
34970
- "Originators"
34971
- ]
34972
- }
34973
- },
34974
- "/originators/bulk-delivery/{jobId}": {
34975
- "delete": {
34976
- "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.",
34977
- "operationId": "cancelOriginatorsBulkDeliveryJob",
34978
- "parameters": [
34979
- {
34980
- "description": "Job ID returned by `POST /v1/originators/bulk-delivery`",
34981
- "in": "path",
34982
- "name": "jobId",
34983
- "required": true,
34984
- "schema": {
34985
- "description": "Job ID returned by `POST /v1/originators/bulk-delivery`",
34986
- "type": "string"
34987
- }
34988
- }
34989
- ],
34990
- "responses": {
34991
- "200": {
34992
- "content": {
34993
- "application/json": {
34994
- "schema": {
34995
- "$ref": "#/components/schemas/BulkDeliveryStatusResponse"
34996
- }
34997
- }
34998
- },
34999
- "description": "Job cancelled; body is its settled status"
35000
- },
35001
- "401": {
35002
- "content": {
35003
- "application/json": {
35004
- "schema": {
35005
- "$ref": "#/components/schemas/ErrorResponse"
35006
- }
35007
- }
35008
- },
35009
- "description": "Authentication required"
35010
- },
35011
- "403": {
35012
- "content": {
35013
- "application/json": {
35014
- "schema": {
35015
- "$ref": "#/components/schemas/ErrorResponse"
35016
- }
35017
- }
35018
- },
35019
- "description": "Caller does not own this job"
35020
- },
35021
- "404": {
35022
- "content": {
35023
- "application/json": {
35024
- "schema": {
35025
- "$ref": "#/components/schemas/ErrorResponse"
35026
- }
35027
- }
35028
- },
35029
- "description": "Job not found (or expired past 30d TTL)"
35030
- },
35031
- "409": {
35032
- "content": {
35033
- "application/json": {
35034
- "schema": {
35035
- "$ref": "#/components/schemas/ErrorResponse"
35036
- }
35037
- }
35038
- },
35039
- "description": "Job already finished — nothing to cancel"
35040
- }
35041
- },
35042
- "summary": "Cancel a bulk-delivery job for originators",
35043
- "tags": [
35044
- "Originators"
35045
- ]
35046
- },
35047
- "get": {
35048
- "operationId": "getOriginatorsBulkDeliveryJob",
35049
- "parameters": [
35050
- {
35051
- "description": "Job ID returned by `POST /v1/originators/bulk-delivery`",
35052
- "in": "path",
35053
- "name": "jobId",
35054
- "required": true,
35055
- "schema": {
35056
- "description": "Job ID returned by `POST /v1/originators/bulk-delivery`",
35057
- "type": "string"
35058
- }
35059
- }
35060
- ],
35061
- "responses": {
35062
- "200": {
35063
- "content": {
35064
- "application/json": {
35065
- "schema": {
35066
- "$ref": "#/components/schemas/BulkDeliveryStatusResponse"
35067
- }
35068
- }
35069
- },
35070
- "description": "Job status (resultsUrl re-signed if completed)"
35071
- },
35072
- "401": {
35073
- "content": {
35074
- "application/json": {
35075
- "schema": {
35076
- "$ref": "#/components/schemas/ErrorResponse"
35077
- }
35078
- }
35079
- },
35080
- "description": "Authentication required"
35081
- },
35082
- "403": {
35083
- "content": {
35084
- "application/json": {
35085
- "schema": {
35086
- "$ref": "#/components/schemas/ErrorResponse"
35087
- }
35088
- }
35089
- },
35090
- "description": "Caller does not own this job"
35091
- },
35092
- "404": {
35093
- "content": {
35094
- "application/json": {
35095
- "schema": {
35096
- "$ref": "#/components/schemas/ErrorResponse"
35097
- }
35098
- }
35099
- },
35100
- "description": "Job not found (or expired past 30d TTL)"
35101
- }
35102
- },
35103
- "summary": "Get bulk-delivery job status for originators",
35104
- "tags": [
35105
- "Originators"
35106
- ]
35107
- }
35108
- },
35109
- "/originators/count": {
35110
- "post": {
35111
- "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`.",
35112
- "operationId": "countOriginators",
35113
- "requestBody": {
35114
- "content": {
35115
- "application/json": {
35116
- "schema": {
35117
- "$ref": "#/components/schemas/OriginatorListRequest"
35118
- }
35119
- }
35120
- }
35121
- },
35122
- "responses": {
35123
- "200": {
35124
- "content": {
35125
- "application/json": {
35126
- "schema": {
35127
- "$ref": "#/components/schemas/OriginatorCountResponse"
35128
- }
35129
- }
35130
- },
35131
- "description": "Exact count of matching originators"
35132
- },
35133
- "400": {
35134
- "content": {
35135
- "application/json": {
35136
- "schema": {
35137
- "$ref": "#/components/schemas/ErrorResponse"
35138
- }
35139
- }
35140
- },
35141
- "description": "Validation error"
35142
- },
35143
- "401": {
35144
- "content": {
35145
- "application/json": {
35146
- "schema": {
35147
- "$ref": "#/components/schemas/ErrorResponse"
35148
- }
35149
- }
35150
- },
35151
- "description": "Unauthorized"
35152
- },
35153
- "403": {
35154
- "content": {
35155
- "application/json": {
35156
- "schema": {
35157
- "$ref": "#/components/schemas/ErrorResponse"
35158
- }
35159
- }
35160
- },
35161
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35162
- },
35163
- "404": {
35164
- "content": {
35165
- "application/json": {
35166
- "schema": {
35167
- "$ref": "#/components/schemas/ErrorResponse"
35168
- }
35169
- }
35170
- },
35171
- "description": "Not found"
35172
- },
35173
- "413": {
35174
- "content": {
35175
- "application/json": {
35176
- "schema": {
35177
- "$ref": "#/components/schemas/PayloadTooLarge"
35178
- }
35179
- }
35180
- },
35181
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35182
- }
35183
- },
35184
- "summary": "Count originators matching filters",
35185
- "tags": [
35186
- "Originators"
35187
- ],
35188
- "x-mm-records-via": "listOriginators"
35189
- }
35190
- },
35191
- "/originators/{nmlsId}": {
35192
- "get": {
35193
- "operationId": "getOriginator",
35194
- "parameters": [
35195
- {
35196
- "description": "Originator NMLS ID",
35197
- "in": "path",
35198
- "name": "nmlsId",
35199
- "required": true,
35200
- "schema": {
35201
- "description": "Originator NMLS ID",
35202
- "type": "string"
35203
- }
35204
- },
35205
- {
35206
- "description": "Period for volume/units (default: last12Months)",
35207
- "in": "query",
35208
- "name": "period",
35209
- "required": false,
35210
- "schema": {
35211
- "allOf": [
35212
- {
35213
- "$ref": "#/components/schemas/Period"
35214
- },
35215
- {
35216
- "description": "Period for volume/units (default: last12Months)"
35217
- }
35218
- ]
35219
- }
35220
- }
35221
- ],
35222
- "responses": {
35223
- "200": {
35224
- "content": {
35225
- "application/json": {
35226
- "schema": {
35227
- "$ref": "#/components/schemas/OriginatorDetailResponse"
35228
- }
35229
- }
35230
- },
35231
- "description": "Originator detail"
35232
- },
35233
- "404": {
35234
- "content": {
35235
- "application/json": {
35236
- "schema": {
35237
- "$ref": "#/components/schemas/ErrorResponse"
35238
- }
35239
- }
35240
- },
35241
- "description": "Originator not found"
35242
- },
35243
- "413": {
35244
- "content": {
35245
- "application/json": {
35246
- "schema": {
35247
- "$ref": "#/components/schemas/PayloadTooLarge"
35248
- }
35249
- }
35250
- },
35251
- "description": "Response payload too large"
35252
- }
35253
- },
35254
- "summary": "Get originator by NMLS ID",
35255
- "tags": [
35256
- "Originators"
35257
- ]
35258
- }
35259
- },
35260
- "/originators/{nmlsId}/breakdowns/agents": {
35261
- "post": {
35262
- "description": "Ranks the real-estate agents on the selling side of this LO'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 LO's whole loan population, so they do not sum to 100 across the page.",
35263
- "operationId": "originatorAgents",
35264
- "parameters": [
35265
- {
35266
- "description": "Originator NMLS ID",
35267
- "in": "path",
35268
- "name": "nmlsId",
35269
- "required": true,
35270
- "schema": {
35271
- "description": "Originator NMLS ID",
35272
- "type": "string"
35273
- }
35274
- }
35275
- ],
35276
- "requestBody": {
35277
- "content": {
35278
- "application/json": {
35279
- "schema": {
35280
- "$ref": "#/components/schemas/BreakdownRequest"
35281
- }
35282
- }
35283
- }
35284
- },
35285
- "responses": {
35286
- "200": {
35287
- "content": {
35288
- "application/json": {
35289
- "schema": {
35290
- "$ref": "#/components/schemas/BreakdownResponse"
35291
- }
35292
- }
35293
- },
35294
- "description": "Breakdown of the LO's loans by agents"
35295
- },
35296
- "400": {
35297
- "content": {
35298
- "application/json": {
35299
- "schema": {
35300
- "$ref": "#/components/schemas/ErrorResponse"
35301
- }
35302
- }
35303
- },
35304
- "description": "Validation error"
35305
- },
35306
- "401": {
35307
- "content": {
35308
- "application/json": {
35309
- "schema": {
35310
- "$ref": "#/components/schemas/ErrorResponse"
35311
- }
35312
- }
35313
- },
35314
- "description": "Unauthorized"
35315
- },
35316
- "403": {
35317
- "content": {
35318
- "application/json": {
35319
- "schema": {
35320
- "$ref": "#/components/schemas/ErrorResponse"
35321
- }
35322
- }
35323
- },
35324
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35325
- },
35326
- "404": {
35327
- "content": {
35328
- "application/json": {
35329
- "schema": {
35330
- "$ref": "#/components/schemas/ErrorResponse"
35331
- }
35332
- }
35333
- },
35334
- "description": "Not found"
35335
- },
35336
- "413": {
35337
- "content": {
35338
- "application/json": {
35339
- "schema": {
35340
- "$ref": "#/components/schemas/PayloadTooLarge"
35341
- }
35342
- }
35343
- },
35344
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35345
- }
35346
- },
35347
- "summary": "Real-estate agents this LO co-closed with",
35348
- "tags": [
35349
- "Originators"
35350
- ]
35351
- }
35352
- },
35353
- "/originators/{nmlsId}/breakdowns/branches": {
35354
- "post": {
35355
- "operationId": "originatorBranches",
35356
- "parameters": [
35357
- {
35358
- "description": "Originator NMLS ID",
35359
- "in": "path",
35360
- "name": "nmlsId",
35361
- "required": true,
35362
- "schema": {
35363
- "description": "Originator NMLS ID",
35364
- "type": "string"
35365
- }
35366
- }
35367
- ],
35368
- "requestBody": {
35369
- "content": {
35370
- "application/json": {
35371
- "schema": {
35372
- "$ref": "#/components/schemas/BreakdownRequest"
35373
- }
35374
- }
35375
- }
35376
- },
35377
- "responses": {
35378
- "200": {
35379
- "content": {
35380
- "application/json": {
35381
- "schema": {
35382
- "$ref": "#/components/schemas/BreakdownResponse"
35383
- }
35384
- }
35385
- },
35386
- "description": "Breakdown of the LO's loans by branches"
35387
- },
35388
- "400": {
35389
- "content": {
35390
- "application/json": {
35391
- "schema": {
35392
- "$ref": "#/components/schemas/ErrorResponse"
35393
- }
35394
- }
35395
- },
35396
- "description": "Validation error"
35397
- },
35398
- "401": {
35399
- "content": {
35400
- "application/json": {
35401
- "schema": {
35402
- "$ref": "#/components/schemas/ErrorResponse"
35403
- }
35404
- }
35405
- },
35406
- "description": "Unauthorized"
35407
- },
35408
- "403": {
35409
- "content": {
35410
- "application/json": {
35411
- "schema": {
35412
- "$ref": "#/components/schemas/ErrorResponse"
35413
- }
35414
- }
35415
- },
35416
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35417
- },
35418
- "404": {
35419
- "content": {
35420
- "application/json": {
35421
- "schema": {
35422
- "$ref": "#/components/schemas/ErrorResponse"
35423
- }
35424
- }
35425
- },
35426
- "description": "Not found"
35427
- },
35428
- "413": {
35429
- "content": {
35430
- "application/json": {
35431
- "schema": {
35432
- "$ref": "#/components/schemas/PayloadTooLarge"
35433
- }
35434
- }
35435
- },
35436
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35437
- }
35438
- },
35439
- "summary": "Branch (broker) history for this LO",
35440
- "tags": [
35441
- "Originators"
35442
- ]
35443
- }
35444
- },
35445
- "/originators/{nmlsId}/breakdowns/brokers": {
35446
- "post": {
35447
- "operationId": "originatorBrokers",
35448
- "parameters": [
35449
- {
35450
- "description": "Originator NMLS ID",
35451
- "in": "path",
35452
- "name": "nmlsId",
35453
- "required": true,
35454
- "schema": {
35455
- "description": "Originator NMLS ID",
35456
- "type": "string"
35457
- }
35458
- }
35459
- ],
35460
- "requestBody": {
35461
- "content": {
35462
- "application/json": {
35463
- "schema": {
35464
- "$ref": "#/components/schemas/BreakdownRequest"
35465
- }
35466
- }
35467
- }
35468
- },
35469
- "responses": {
35470
- "200": {
35471
- "content": {
35472
- "application/json": {
35473
- "schema": {
35474
- "$ref": "#/components/schemas/BreakdownResponse"
35475
- }
35476
- }
35477
- },
35478
- "description": "Breakdown of the LO's loans by brokers"
35479
- },
35480
- "400": {
35481
- "content": {
35482
- "application/json": {
35483
- "schema": {
35484
- "$ref": "#/components/schemas/ErrorResponse"
35485
- }
35486
- }
35487
- },
35488
- "description": "Validation error"
35489
- },
35490
- "401": {
35491
- "content": {
35492
- "application/json": {
35493
- "schema": {
35494
- "$ref": "#/components/schemas/ErrorResponse"
35495
- }
35496
- }
35497
- },
35498
- "description": "Unauthorized"
35499
- },
35500
- "403": {
35501
- "content": {
35502
- "application/json": {
35503
- "schema": {
35504
- "$ref": "#/components/schemas/ErrorResponse"
35505
- }
35506
- }
35507
- },
35508
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35509
- },
35510
- "404": {
35511
- "content": {
35512
- "application/json": {
35513
- "schema": {
35514
- "$ref": "#/components/schemas/ErrorResponse"
35515
- }
35516
- }
35517
- },
35518
- "description": "Not found"
35519
- },
35520
- "413": {
35521
- "content": {
35522
- "application/json": {
35523
- "schema": {
35524
- "$ref": "#/components/schemas/PayloadTooLarge"
35525
- }
35526
- }
35527
- },
35528
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35529
- }
35530
- },
35531
- "summary": "Broker shops this LO originated loans through (name-resolved)",
35532
- "tags": [
35533
- "Originators"
35534
- ]
35535
- }
35536
- },
35537
- "/originators/{nmlsId}/breakdowns/cities": {
35538
- "post": {
35539
- "operationId": "originatorCitiesBreakdown",
35540
- "parameters": [
35541
- {
35542
- "description": "Originator NMLS ID",
35543
- "in": "path",
35544
- "name": "nmlsId",
35545
- "required": true,
35546
- "schema": {
35547
- "description": "Originator NMLS ID",
35548
- "type": "string"
35549
- }
35550
- }
35551
- ],
35552
- "requestBody": {
35553
- "content": {
35554
- "application/json": {
35555
- "schema": {
35556
- "$ref": "#/components/schemas/BreakdownRequest"
35557
- }
35558
- }
35559
- }
35560
- },
35561
- "responses": {
35562
- "200": {
35563
- "content": {
35564
- "application/json": {
35565
- "schema": {
35566
- "$ref": "#/components/schemas/BreakdownResponse"
35567
- }
35568
- }
35569
- },
35570
- "description": "Breakdown of the LO's loans by cities"
35571
- },
35572
- "400": {
35573
- "content": {
35574
- "application/json": {
35575
- "schema": {
35576
- "$ref": "#/components/schemas/ErrorResponse"
35577
- }
35578
- }
35579
- },
35580
- "description": "Validation error"
35581
- },
35582
- "401": {
35583
- "content": {
35584
- "application/json": {
35585
- "schema": {
35586
- "$ref": "#/components/schemas/ErrorResponse"
35587
- }
35588
- }
35589
- },
35590
- "description": "Unauthorized"
35591
- },
35592
- "403": {
35593
- "content": {
35594
- "application/json": {
35595
- "schema": {
35596
- "$ref": "#/components/schemas/ErrorResponse"
35597
- }
35598
- }
35599
- },
35600
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35601
- },
35602
- "404": {
35603
- "content": {
35604
- "application/json": {
35605
- "schema": {
35606
- "$ref": "#/components/schemas/ErrorResponse"
35607
- }
35608
- }
35609
- },
35610
- "description": "Not found"
35611
- },
35612
- "413": {
35613
- "content": {
35614
- "application/json": {
35615
- "schema": {
35616
- "$ref": "#/components/schemas/PayloadTooLarge"
35617
- }
35618
- }
35619
- },
35620
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35621
- }
35622
- },
35623
- "summary": "City volume breakdown across this LO's loans",
35624
- "tags": [
35625
- "Originators"
35626
- ]
35627
- }
35628
- },
35629
- "/originators/{nmlsId}/breakdowns/companies": {
35630
- "post": {
35631
- "operationId": "originatorCompanies",
35632
- "parameters": [
35633
- {
35634
- "description": "Originator NMLS ID",
35635
- "in": "path",
35636
- "name": "nmlsId",
35637
- "required": true,
35638
- "schema": {
35639
- "description": "Originator NMLS ID",
35640
- "type": "string"
35641
- }
35642
- }
35643
- ],
35644
- "requestBody": {
35645
- "content": {
35646
- "application/json": {
35647
- "schema": {
35648
- "$ref": "#/components/schemas/BreakdownRequest"
35649
- }
35650
- }
35651
- }
35652
- },
35653
- "responses": {
35654
- "200": {
35655
- "content": {
35656
- "application/json": {
35657
- "schema": {
35658
- "$ref": "#/components/schemas/BreakdownResponse"
35659
- }
35660
- }
35661
- },
35662
- "description": "Breakdown of the LO's loans by companies"
35663
- },
35664
- "400": {
35665
- "content": {
35666
- "application/json": {
35667
- "schema": {
35668
- "$ref": "#/components/schemas/ErrorResponse"
35669
- }
35670
- }
35671
- },
35672
- "description": "Validation error"
35673
- },
35674
- "401": {
35675
- "content": {
35676
- "application/json": {
35677
- "schema": {
35678
- "$ref": "#/components/schemas/ErrorResponse"
35679
- }
35680
- }
35681
- },
35682
- "description": "Unauthorized"
35683
- },
35684
- "403": {
35685
- "content": {
35686
- "application/json": {
35687
- "schema": {
35688
- "$ref": "#/components/schemas/ErrorResponse"
35689
- }
35690
- }
35691
- },
35692
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35693
- },
35694
- "404": {
35695
- "content": {
35696
- "application/json": {
35697
- "schema": {
35698
- "$ref": "#/components/schemas/ErrorResponse"
35699
- }
35700
- }
35701
- },
35702
- "description": "Not found"
35703
- },
35704
- "413": {
35705
- "content": {
35706
- "application/json": {
35707
- "schema": {
35708
- "$ref": "#/components/schemas/PayloadTooLarge"
35709
- }
35710
- }
35711
- },
35712
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35713
- }
35714
- },
35715
- "summary": "Funding companies (employer history) for this LO",
35716
- "tags": [
35717
- "Originators"
35718
- ]
35719
- }
35720
- },
35721
- "/originators/{nmlsId}/breakdowns/counties": {
35722
- "post": {
35723
- "operationId": "originatorCountiesBreakdown",
35724
- "parameters": [
35725
- {
35726
- "description": "Originator NMLS ID",
35727
- "in": "path",
35728
- "name": "nmlsId",
35729
- "required": true,
35730
- "schema": {
35731
- "description": "Originator NMLS ID",
35732
- "type": "string"
35733
- }
35734
- }
35735
- ],
35736
- "requestBody": {
35737
- "content": {
35738
- "application/json": {
35739
- "schema": {
35740
- "$ref": "#/components/schemas/BreakdownRequest"
35741
- }
35742
- }
35743
- }
35744
- },
35745
- "responses": {
35746
- "200": {
35747
- "content": {
35748
- "application/json": {
35749
- "schema": {
35750
- "$ref": "#/components/schemas/BreakdownResponse"
35751
- }
35752
- }
35753
- },
35754
- "description": "Breakdown of the LO's loans by counties"
35755
- },
35756
- "400": {
35757
- "content": {
35758
- "application/json": {
35759
- "schema": {
35760
- "$ref": "#/components/schemas/ErrorResponse"
35761
- }
35762
- }
35763
- },
35764
- "description": "Validation error"
35765
- },
35766
- "401": {
35767
- "content": {
35768
- "application/json": {
35769
- "schema": {
35770
- "$ref": "#/components/schemas/ErrorResponse"
35771
- }
35772
- }
35773
- },
35774
- "description": "Unauthorized"
35775
- },
35776
- "403": {
35777
- "content": {
35778
- "application/json": {
35779
- "schema": {
35780
- "$ref": "#/components/schemas/ErrorResponse"
35781
- }
35782
- }
35783
- },
35784
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35785
- },
35786
- "404": {
35787
- "content": {
35788
- "application/json": {
35789
- "schema": {
35790
- "$ref": "#/components/schemas/ErrorResponse"
35791
- }
35792
- }
35793
- },
35794
- "description": "Not found"
35795
- },
35796
- "413": {
35797
- "content": {
35798
- "application/json": {
35799
- "schema": {
35800
- "$ref": "#/components/schemas/PayloadTooLarge"
35801
- }
35802
- }
35803
- },
35804
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35805
- }
35806
- },
35807
- "summary": "County (FIPS) volume breakdown across this LO's loans",
35808
- "tags": [
35809
- "Originators"
35810
- ]
35811
- }
35812
- },
35813
- "/originators/{nmlsId}/breakdowns/lenders": {
35814
- "post": {
35815
- "operationId": "originatorLenders",
35816
- "parameters": [
35817
- {
35818
- "description": "Originator NMLS ID",
35819
- "in": "path",
35820
- "name": "nmlsId",
35821
- "required": true,
35822
- "schema": {
35823
- "description": "Originator NMLS ID",
35824
- "type": "string"
35825
- }
35826
- }
35827
- ],
35828
- "requestBody": {
35829
- "content": {
35830
- "application/json": {
35831
- "schema": {
35832
- "$ref": "#/components/schemas/BreakdownRequest"
35833
- }
35834
- }
35835
- }
35836
- },
35837
- "responses": {
35838
- "200": {
35839
- "content": {
35840
- "application/json": {
35841
- "schema": {
35842
- "$ref": "#/components/schemas/BreakdownResponse"
35843
- }
35844
- }
35845
- },
35846
- "description": "Breakdown of the LO's loans by lenders"
35847
- },
35848
- "400": {
35849
- "content": {
35850
- "application/json": {
35851
- "schema": {
35852
- "$ref": "#/components/schemas/ErrorResponse"
35853
- }
35854
- }
35855
- },
35856
- "description": "Validation error"
35857
- },
35858
- "401": {
35859
- "content": {
35860
- "application/json": {
35861
- "schema": {
35862
- "$ref": "#/components/schemas/ErrorResponse"
35863
- }
35864
- }
35865
- },
35866
- "description": "Unauthorized"
35867
- },
35868
- "403": {
35869
- "content": {
35870
- "application/json": {
35871
- "schema": {
35872
- "$ref": "#/components/schemas/ErrorResponse"
35873
- }
35874
- }
35875
- },
35876
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35877
- },
35878
- "404": {
35879
- "content": {
35880
- "application/json": {
35881
- "schema": {
35882
- "$ref": "#/components/schemas/ErrorResponse"
35883
- }
35884
- }
35885
- },
35886
- "description": "Not found"
35887
- },
35888
- "413": {
35889
- "content": {
35890
- "application/json": {
35891
- "schema": {
35892
- "$ref": "#/components/schemas/PayloadTooLarge"
35893
- }
35894
- }
35895
- },
35896
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35897
- }
35898
- },
35899
- "summary": "Lenders this LO has originated through",
35900
- "tags": [
35901
- "Originators"
35902
- ]
35903
- }
35904
- },
35905
- "/originators/{nmlsId}/breakdowns/offices": {
35906
- "post": {
35907
- "operationId": "originatorOffices",
35908
- "parameters": [
35909
- {
35910
- "description": "Originator NMLS ID",
35911
- "in": "path",
35912
- "name": "nmlsId",
35913
- "required": true,
35914
- "schema": {
35915
- "description": "Originator NMLS ID",
35916
- "type": "string"
35917
- }
35918
- }
35919
- ],
35920
- "requestBody": {
35921
- "content": {
35922
- "application/json": {
35923
- "schema": {
35924
- "$ref": "#/components/schemas/BreakdownRequest"
35925
- }
35926
- }
35927
- }
35928
- },
35929
- "responses": {
35930
- "200": {
35931
- "content": {
35932
- "application/json": {
35933
- "schema": {
35934
- "$ref": "#/components/schemas/BreakdownResponse"
35935
- }
35936
- }
35937
- },
35938
- "description": "Breakdown of the LO's loans by broker (office)"
35939
- },
35940
- "400": {
35941
- "content": {
35942
- "application/json": {
35943
- "schema": {
35944
- "$ref": "#/components/schemas/ErrorResponse"
35945
- }
35946
- }
35947
- },
35948
- "description": "Validation error"
35949
- },
35950
- "401": {
35951
- "content": {
35952
- "application/json": {
35953
- "schema": {
35954
- "$ref": "#/components/schemas/ErrorResponse"
35955
- }
35956
- }
35957
- },
35958
- "description": "Unauthorized"
35959
- },
35960
- "403": {
35961
- "content": {
35962
- "application/json": {
35963
- "schema": {
35964
- "$ref": "#/components/schemas/ErrorResponse"
35965
- }
35966
- }
35967
- },
35968
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
35969
- },
35970
- "404": {
35971
- "content": {
35972
- "application/json": {
35973
- "schema": {
35974
- "$ref": "#/components/schemas/ErrorResponse"
35975
- }
35976
- }
35977
- },
35978
- "description": "Not found"
35979
- },
35980
- "413": {
35981
- "content": {
35982
- "application/json": {
35983
- "schema": {
35984
- "$ref": "#/components/schemas/PayloadTooLarge"
35985
- }
35986
- }
35987
- },
35988
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
35989
- }
35990
- },
35991
- "summary": "Real-estate offices this LO closed through (with sponsoring company)",
35992
- "tags": [
35993
- "Originators"
35994
- ]
35995
- }
35996
- },
35997
- "/originators/{nmlsId}/breakdowns/states": {
35998
- "post": {
35999
- "operationId": "originatorStatesBreakdown",
36000
- "parameters": [
36001
- {
36002
- "description": "Originator NMLS ID",
36003
- "in": "path",
36004
- "name": "nmlsId",
36005
- "required": true,
36006
- "schema": {
36007
- "description": "Originator NMLS ID",
36008
- "type": "string"
36009
- }
36010
- }
36011
- ],
36012
- "requestBody": {
36013
- "content": {
36014
- "application/json": {
36015
- "schema": {
36016
- "$ref": "#/components/schemas/BreakdownRequest"
36017
- }
36018
- }
36019
- }
36020
- },
36021
- "responses": {
36022
- "200": {
36023
- "content": {
36024
- "application/json": {
36025
- "schema": {
36026
- "$ref": "#/components/schemas/BreakdownResponse"
36027
- }
36028
- }
36029
- },
36030
- "description": "Breakdown of the LO's loans by states"
36031
- },
36032
- "400": {
36033
- "content": {
36034
- "application/json": {
36035
- "schema": {
36036
- "$ref": "#/components/schemas/ErrorResponse"
36037
- }
36038
- }
36039
- },
36040
- "description": "Validation error"
36041
- },
36042
- "401": {
36043
- "content": {
36044
- "application/json": {
36045
- "schema": {
36046
- "$ref": "#/components/schemas/ErrorResponse"
36047
- }
36048
- }
36049
- },
36050
- "description": "Unauthorized"
36051
- },
36052
- "403": {
36053
- "content": {
36054
- "application/json": {
36055
- "schema": {
36056
- "$ref": "#/components/schemas/ErrorResponse"
36057
- }
36058
- }
36059
- },
36060
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36061
- },
36062
- "404": {
36063
- "content": {
36064
- "application/json": {
36065
- "schema": {
36066
- "$ref": "#/components/schemas/ErrorResponse"
36067
- }
36068
- }
36069
- },
36070
- "description": "Not found"
36071
- },
36072
- "413": {
36073
- "content": {
36074
- "application/json": {
36075
- "schema": {
36076
- "$ref": "#/components/schemas/PayloadTooLarge"
36077
- }
36078
- }
36079
- },
36080
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36081
- }
36082
- },
36083
- "summary": "State volume breakdown across this LO's loans",
36084
- "tags": [
36085
- "Originators"
36086
- ]
36087
- }
36088
- },
36089
- "/originators/{nmlsId}/breakdowns/title-companies": {
36090
- "post": {
36091
- "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`.",
36092
- "operationId": "originatorTitleCompanies",
36093
- "parameters": [
36094
- {
36095
- "description": "Originator NMLS ID",
36096
- "in": "path",
36097
- "name": "nmlsId",
36098
- "required": true,
36099
- "schema": {
36100
- "description": "Originator NMLS ID",
36101
- "type": "string"
36102
- }
36103
- }
36104
- ],
36105
- "requestBody": {
36106
- "content": {
36107
- "application/json": {
36108
- "schema": {
36109
- "$ref": "#/components/schemas/BreakdownRequest"
36110
- }
36111
- }
36112
- }
36113
- },
36114
- "responses": {
36115
- "200": {
36116
- "content": {
36117
- "application/json": {
36118
- "schema": {
36119
- "$ref": "#/components/schemas/BreakdownResponse"
36120
- }
36121
- }
36122
- },
36123
- "description": "Breakdown of the entity's loans by title company"
36124
- },
36125
- "400": {
36126
- "content": {
36127
- "application/json": {
36128
- "schema": {
36129
- "$ref": "#/components/schemas/ErrorResponse"
36130
- }
36131
- }
36132
- },
36133
- "description": "Validation error"
36134
- },
36135
- "401": {
36136
- "content": {
36137
- "application/json": {
36138
- "schema": {
36139
- "$ref": "#/components/schemas/ErrorResponse"
36140
- }
36141
- }
36142
- },
36143
- "description": "Unauthorized"
36144
- },
36145
- "403": {
36146
- "content": {
36147
- "application/json": {
36148
- "schema": {
36149
- "$ref": "#/components/schemas/ErrorResponse"
36150
- }
36151
- }
36152
- },
36153
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36154
- },
36155
- "404": {
36156
- "content": {
36157
- "application/json": {
36158
- "schema": {
36159
- "$ref": "#/components/schemas/ErrorResponse"
36160
- }
36161
- }
36162
- },
36163
- "description": "Not found"
36164
- },
36165
- "413": {
36166
- "content": {
36167
- "application/json": {
36168
- "schema": {
36169
- "$ref": "#/components/schemas/PayloadTooLarge"
36170
- }
36171
- }
36172
- },
36173
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36174
- }
36175
- },
36176
- "summary": "Title companies on this LO's loans (spellings merged)",
36177
- "tags": [
36178
- "Originators"
36179
- ]
36180
- }
36181
- },
36182
- "/originators/{nmlsId}/breakdowns/zip-codes": {
36183
- "post": {
36184
- "operationId": "originatorZipCodes",
36185
- "parameters": [
36186
- {
36187
- "description": "Originator NMLS ID",
36188
- "in": "path",
36189
- "name": "nmlsId",
36190
- "required": true,
36191
- "schema": {
36192
- "description": "Originator NMLS ID",
36193
- "type": "string"
36194
- }
36195
- }
36196
- ],
36197
- "requestBody": {
36198
- "content": {
36199
- "application/json": {
36200
- "schema": {
36201
- "$ref": "#/components/schemas/BreakdownRequest"
36202
- }
36203
- }
36204
- }
36205
- },
36206
- "responses": {
36207
- "200": {
36208
- "content": {
36209
- "application/json": {
36210
- "schema": {
36211
- "$ref": "#/components/schemas/BreakdownResponse"
36212
- }
36213
- }
36214
- },
36215
- "description": "Breakdown of the LO's loans by zip-codes"
36216
- },
36217
- "400": {
36218
- "content": {
36219
- "application/json": {
36220
- "schema": {
36221
- "$ref": "#/components/schemas/ErrorResponse"
36222
- }
36223
- }
36224
- },
36225
- "description": "Validation error"
36226
- },
36227
- "401": {
36228
- "content": {
36229
- "application/json": {
36230
- "schema": {
36231
- "$ref": "#/components/schemas/ErrorResponse"
36232
- }
36233
- }
36234
- },
36235
- "description": "Unauthorized"
36236
- },
36237
- "403": {
36238
- "content": {
36239
- "application/json": {
36240
- "schema": {
36241
- "$ref": "#/components/schemas/ErrorResponse"
36242
- }
36243
- }
36244
- },
36245
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36246
- },
36247
- "404": {
36248
- "content": {
36249
- "application/json": {
36250
- "schema": {
36251
- "$ref": "#/components/schemas/ErrorResponse"
36252
- }
36253
- }
36254
- },
36255
- "description": "Not found"
36256
- },
36257
- "413": {
36258
- "content": {
36259
- "application/json": {
36260
- "schema": {
36261
- "$ref": "#/components/schemas/PayloadTooLarge"
36262
- }
36263
- }
36264
- },
36265
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36266
- }
36267
- },
36268
- "summary": "Zip-code volume breakdown",
36269
- "tags": [
36270
- "Originators"
36271
- ]
36272
- }
36273
- },
36274
- "/originators/{nmlsId}/loans": {
36275
- "post": {
36276
- "operationId": "originatorLoans",
36277
- "parameters": [
36278
- {
36279
- "description": "Originator NMLS ID",
36280
- "in": "path",
36281
- "name": "nmlsId",
36282
- "required": true,
36283
- "schema": {
36284
- "description": "Originator NMLS ID",
36285
- "type": "string"
36286
- }
36287
- }
36288
- ],
36289
- "requestBody": {
36290
- "content": {
36291
- "application/json": {
36292
- "schema": {
36293
- "$ref": "#/components/schemas/LoanListRequest"
36294
- }
36295
- }
36296
- }
36297
- },
36298
- "responses": {
36299
- "200": {
36300
- "content": {
36301
- "application/json": {
36302
- "schema": {
36303
- "$ref": "#/components/schemas/LoanListResponse"
36304
- }
36305
- }
36306
- },
36307
- "description": "Paginated list of loans originated by this LO"
36308
- },
36309
- "400": {
36310
- "content": {
36311
- "application/json": {
36312
- "schema": {
36313
- "$ref": "#/components/schemas/ErrorResponse"
36314
- }
36315
- }
36316
- },
36317
- "description": "Validation error"
36318
- },
36319
- "401": {
36320
- "content": {
36321
- "application/json": {
36322
- "schema": {
36323
- "$ref": "#/components/schemas/ErrorResponse"
36324
- }
36325
- }
36326
- },
36327
- "description": "Unauthorized"
36328
- },
36329
- "403": {
36330
- "content": {
36331
- "application/json": {
36332
- "schema": {
36333
- "$ref": "#/components/schemas/ErrorResponse"
36334
- }
36335
- }
36336
- },
36337
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36338
- },
36339
- "404": {
36340
- "content": {
36341
- "application/json": {
36342
- "schema": {
36343
- "$ref": "#/components/schemas/ErrorResponse"
36344
- }
36345
- }
36346
- },
36347
- "description": "Not found"
36348
- },
36349
- "413": {
36350
- "content": {
36351
- "application/json": {
36352
- "schema": {
36353
- "$ref": "#/components/schemas/PayloadTooLarge"
36354
- }
36355
- }
36356
- },
36357
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36358
- }
36359
- },
36360
- "summary": "Loans originated by this LO",
36361
- "tags": [
36362
- "Originators"
36363
- ]
36364
- }
36365
- },
36366
- "/originators/{nmlsId}/markets": {
36367
- "post": {
36368
- "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.",
36369
- "operationId": "originatorMarkets",
36370
- "parameters": [
36371
- {
36372
- "description": "Originator NMLS ID",
36373
- "in": "path",
36374
- "name": "nmlsId",
36375
- "required": true,
36376
- "schema": {
36377
- "description": "Originator NMLS ID",
36378
- "type": "string"
36379
- }
36380
- }
36381
- ],
36382
- "requestBody": {
36383
- "content": {
36384
- "application/json": {
36385
- "schema": {
36386
- "$ref": "#/components/schemas/OriginatorMarketsRequest"
36387
- }
36388
- }
36389
- }
36390
- },
36391
- "responses": {
36392
- "200": {
36393
- "content": {
36394
- "application/json": {
36395
- "schema": {
36396
- "$ref": "#/components/schemas/OriginatorMarketsResponse"
36397
- }
36398
- }
36399
- },
36400
- "description": "The LO's blended market footprint"
36401
- },
36402
- "400": {
36403
- "content": {
36404
- "application/json": {
36405
- "schema": {
36406
- "$ref": "#/components/schemas/ErrorResponse"
36407
- }
36408
- }
36409
- },
36410
- "description": "Validation error"
36411
- },
36412
- "401": {
36413
- "content": {
36414
- "application/json": {
36415
- "schema": {
36416
- "$ref": "#/components/schemas/ErrorResponse"
36417
- }
36418
- }
36419
- },
36420
- "description": "Unauthorized"
36421
- },
36422
- "403": {
36423
- "content": {
36424
- "application/json": {
36425
- "schema": {
36426
- "$ref": "#/components/schemas/ErrorResponse"
36427
- }
36428
- }
36429
- },
36430
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36431
- },
36432
- "404": {
36433
- "content": {
36434
- "application/json": {
36435
- "schema": {
36436
- "$ref": "#/components/schemas/ErrorResponse"
36437
- }
36438
- }
36439
- },
36440
- "description": "Originator not found"
36441
- },
36442
- "413": {
36443
- "content": {
36444
- "application/json": {
36445
- "schema": {
36446
- "$ref": "#/components/schemas/PayloadTooLarge"
36447
- }
36448
- }
36449
- },
36450
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36451
- }
36452
- },
36453
- "summary": "The markets this LO lends in",
36454
- "tags": [
36455
- "Originators"
36456
- ]
36457
- }
36458
- },
36459
- "/originators/{nmlsId}/properties": {
36460
- "post": {
36461
- "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.",
36462
- "operationId": "originatorProperties",
36463
- "parameters": [
36464
- {
36465
- "description": "Originator NMLS ID",
36466
- "in": "path",
36467
- "name": "nmlsId",
36468
- "required": true,
36469
- "schema": {
36470
- "description": "Originator NMLS ID",
36471
- "type": "string"
36472
- }
36473
- }
36474
- ],
36475
- "requestBody": {
36476
- "content": {
36477
- "application/json": {
36478
- "schema": {
36479
- "$ref": "#/components/schemas/PropertyListRequest"
36480
- }
36481
- }
36482
- }
36483
- },
36484
- "responses": {
36485
- "200": {
36486
- "content": {
36487
- "application/json": {
36488
- "schema": {
36489
- "$ref": "#/components/schemas/PropertyListResponse"
36490
- }
36491
- }
36492
- },
36493
- "description": "Paginated list of parcels attributed to this LO"
36494
- },
36495
- "400": {
36496
- "content": {
36497
- "application/json": {
36498
- "schema": {
36499
- "$ref": "#/components/schemas/ErrorResponse"
36500
- }
36501
- }
36502
- },
36503
- "description": "Validation error"
36504
- },
36505
- "401": {
36506
- "content": {
36507
- "application/json": {
36508
- "schema": {
36509
- "$ref": "#/components/schemas/ErrorResponse"
36510
- }
36511
- }
36512
- },
36513
- "description": "Unauthorized"
36514
- },
36515
- "403": {
36516
- "content": {
36517
- "application/json": {
36518
- "schema": {
36519
- "$ref": "#/components/schemas/ErrorResponse"
36520
- }
36521
- }
36522
- },
36523
- "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
36524
- },
36525
- "404": {
36526
- "content": {
36527
- "application/json": {
36528
- "schema": {
36529
- "$ref": "#/components/schemas/ErrorResponse"
36530
- }
36531
- }
36532
- },
36533
- "description": "Not found"
36534
- },
36535
- "413": {
36536
- "content": {
36537
- "application/json": {
36538
- "schema": {
36539
- "$ref": "#/components/schemas/PayloadTooLarge"
36540
- }
36541
- }
36542
- },
36543
- "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
36544
- }
36545
- },
36546
- "summary": "Properties this loan officer has touched",
36547
- "tags": [
36548
- "Originators"
36549
- ]
36550
- }
36551
- },
36552
32774
  "/v1/admin/cad/links/{nmlsId}": {
36553
32775
  "get": {
36554
32776
  "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.",
@@ -57413,7 +53635,7 @@
57413
53635
  },
57414
53636
  "/v1/lenders/{id}/breakdowns/originators": {
57415
53637
  "post": {
57416
- "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 /originators/{nmlsId}`. Loans with no identified loan officer are excluded rather than collapsed into one unnavigable bucket.",
53638
+ "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.",
57417
53639
  "operationId": "lenderOriginators",
57418
53640
  "parameters": [
57419
53641
  {