@model-match/api 3.50.0 → 3.52.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
@@ -8142,7 +8142,7 @@
8142
8142
  "$ref": "#/components/schemas/BranchSlice"
8143
8143
  },
8144
8144
  {
8145
- "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."
8145
+ "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice` (400). Combines with `size` / `after` paging on a party slice: the cursor pages the `slice` ranking and every bucket on each page carries its own segments (e.g. `slice: \"broker\", segment: \"lender\"` walks every broker shop × its lenders)."
8146
8146
  }
8147
8147
  ]
8148
8148
  },
@@ -9460,6 +9460,50 @@
9460
9460
  ],
9461
9461
  "type": "string"
9462
9462
  },
9463
+ "BranchStatsResponse": {
9464
+ "properties": {
9465
+ "data": {
9466
+ "properties": {
9467
+ "avgLoCount": {
9468
+ "description": "Mean current roster size (`loCount`) across matching branches; `null` when none carry one. A snapshot — does not vary by period.",
9469
+ "nullable": true,
9470
+ "type": "number"
9471
+ },
9472
+ "branches": {
9473
+ "description": "Branches matching the request — equals `countBranches.total`.",
9474
+ "type": "integer"
9475
+ },
9476
+ "producingBranches": {
9477
+ "description": "Matching branches with at least one loan (units > 0) in the period.",
9478
+ "type": "integer"
9479
+ },
9480
+ "topUnits": {
9481
+ "description": "Units of the 3 highest-unit matching branches, descending. Divide their sum by `totalUnits` for top-3 concentration.",
9482
+ "items": {
9483
+ "type": "number"
9484
+ },
9485
+ "type": "array"
9486
+ },
9487
+ "totalUnits": {
9488
+ "description": "Sum of the period's branch-level units.",
9489
+ "type": "number"
9490
+ }
9491
+ },
9492
+ "required": [
9493
+ "branches",
9494
+ "producingBranches",
9495
+ "avgLoCount",
9496
+ "totalUnits",
9497
+ "topUnits"
9498
+ ],
9499
+ "type": "object"
9500
+ }
9501
+ },
9502
+ "required": [
9503
+ "data"
9504
+ ],
9505
+ "type": "object"
9506
+ },
9463
9507
  "BranchSummary": {
9464
9508
  "properties": {
9465
9509
  "avgLoanAmount": {
@@ -11079,6 +11123,16 @@
11079
11123
  ],
11080
11124
  "type": "string"
11081
11125
  },
11126
+ "billingStatus": {
11127
+ "description": "Outcome of the job's single debit, taken before anything is delivered: `charged`, `capped` (balance / spend cap / daily cap declined it — the job fails `insufficient_credits`), `billing_error` (the debit could not be made — the job fails `billing_unavailable`), or `none` (nothing to bill: free delivery or zero rows). Absent until billing has run, and on older jobs.",
11128
+ "enum": [
11129
+ "charged",
11130
+ "capped",
11131
+ "billing_error",
11132
+ "none"
11133
+ ],
11134
+ "type": "string"
11135
+ },
11082
11136
  "bytes": {
11083
11137
  "minimum": 0,
11084
11138
  "type": "integer"
@@ -11096,7 +11150,7 @@
11096
11150
  "type": "string"
11097
11151
  },
11098
11152
  "creditsCharged": {
11099
- "description": "Credits debited for this job (1 credit / row). Absent until the job completes; absent on a failed billing call.",
11153
+ "description": "Credits ACTUALLY debited for this job (1 credit / row) — `0` when the debit was declined or failed; read `billingStatus` for why. Absent until billing has run.",
11100
11154
  "minimum": 0,
11101
11155
  "type": "number"
11102
11156
  },
@@ -11111,7 +11165,7 @@
11111
11165
  "type": "string"
11112
11166
  },
11113
11167
  "error": {
11114
- "description": "Why the job failed. `push_handoff_failed` = the rows were exported but could not be handed to the push target (not billed).",
11168
+ "description": "Why the job failed. `insufficient_credits` = the charge was declined (balance, spend cap or daily cap), nothing delivered. `billing_unavailable` = the charge could not be made, nothing delivered — retry. `push_handoff_failed` = the rows were exported and charged but could not be handed to the push target (see `billingStatus`).",
11115
11169
  "type": "string"
11116
11170
  },
11117
11171
  "estimatedTotal": {
@@ -11328,6 +11382,167 @@
11328
11382
  ],
11329
11383
  "type": "object"
11330
11384
  },
11385
+ "CommunityLendingBenchmark": {
11386
+ "description": "Peer rank of an entity's neighborhood lending shares. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.",
11387
+ "nullable": true,
11388
+ "properties": {
11389
+ "lowModIncomeTract": {
11390
+ "properties": {
11391
+ "pct": {
11392
+ "description": "This entity's share, 0-100.",
11393
+ "nullable": true,
11394
+ "type": "number"
11395
+ },
11396
+ "peerAvgPct": {
11397
+ "description": "Peer mean share, 0-100. Null with no peers.",
11398
+ "nullable": true,
11399
+ "type": "number"
11400
+ },
11401
+ "percentileRank": {
11402
+ "description": "0-100: share of peers with a lower value. Null when this entity has no value or there are no peers.",
11403
+ "nullable": true,
11404
+ "type": "number"
11405
+ }
11406
+ },
11407
+ "required": [
11408
+ "pct",
11409
+ "percentileRank",
11410
+ "peerAvgPct"
11411
+ ],
11412
+ "type": "object"
11413
+ },
11414
+ "majorityMinorityTract": {
11415
+ "properties": {
11416
+ "pct": {
11417
+ "description": "This entity's share, 0-100.",
11418
+ "nullable": true,
11419
+ "type": "number"
11420
+ },
11421
+ "peerAvgPct": {
11422
+ "description": "Peer mean share, 0-100. Null with no peers.",
11423
+ "nullable": true,
11424
+ "type": "number"
11425
+ },
11426
+ "percentileRank": {
11427
+ "description": "0-100: share of peers with a lower value. Null when this entity has no value or there are no peers.",
11428
+ "nullable": true,
11429
+ "type": "number"
11430
+ }
11431
+ },
11432
+ "required": [
11433
+ "pct",
11434
+ "percentileRank",
11435
+ "peerAvgPct"
11436
+ ],
11437
+ "type": "object"
11438
+ },
11439
+ "peerPopulation": {
11440
+ "type": "number"
11441
+ },
11442
+ "states": {
11443
+ "description": "The footprint states peers were drawn from (top by units). Empty = nationwide.",
11444
+ "items": {
11445
+ "type": "string"
11446
+ },
11447
+ "type": "array"
11448
+ }
11449
+ },
11450
+ "required": [
11451
+ "states",
11452
+ "peerPopulation",
11453
+ "lowModIncomeTract",
11454
+ "majorityMinorityTract"
11455
+ ],
11456
+ "type": "object"
11457
+ },
11458
+ "CommunityLendingBenchmarkResponse": {
11459
+ "properties": {
11460
+ "data": {
11461
+ "$ref": "#/components/schemas/CommunityLendingBenchmark"
11462
+ }
11463
+ },
11464
+ "required": [
11465
+ "data"
11466
+ ],
11467
+ "type": "object"
11468
+ },
11469
+ "CommunityLendingMapPoint": {
11470
+ "properties": {
11471
+ "address": {
11472
+ "nullable": true,
11473
+ "type": "string"
11474
+ },
11475
+ "id": {
11476
+ "type": "string"
11477
+ },
11478
+ "lat": {
11479
+ "type": "number"
11480
+ },
11481
+ "lon": {
11482
+ "type": "number"
11483
+ },
11484
+ "mortgageAmount": {
11485
+ "nullable": true,
11486
+ "type": "number"
11487
+ },
11488
+ "tractGeoId": {
11489
+ "description": "11-digit Census tract GEOID (state + county + tract FIPS) — the join key for a tract boundary layer.",
11490
+ "nullable": true,
11491
+ "type": "string"
11492
+ },
11493
+ "transactionDate": {
11494
+ "nullable": true,
11495
+ "type": "string"
11496
+ },
11497
+ "transactionType": {
11498
+ "nullable": true,
11499
+ "type": "string"
11500
+ }
11501
+ },
11502
+ "required": [
11503
+ "id",
11504
+ "lat",
11505
+ "lon",
11506
+ "address",
11507
+ "mortgageAmount",
11508
+ "transactionDate",
11509
+ "transactionType",
11510
+ "tractGeoId"
11511
+ ],
11512
+ "type": "object"
11513
+ },
11514
+ "CommunityLendingMapResponse": {
11515
+ "properties": {
11516
+ "points": {
11517
+ "items": {
11518
+ "$ref": "#/components/schemas/CommunityLendingMapPoint"
11519
+ },
11520
+ "type": "array"
11521
+ },
11522
+ "total": {
11523
+ "description": "Every geocoded loan in scope for the period.",
11524
+ "type": "number"
11525
+ },
11526
+ "tractCounts": {
11527
+ "additionalProperties": {
11528
+ "type": "number"
11529
+ },
11530
+ "description": "Plotted loans per tract GEOID. Values describe the U.S. Census tract (neighborhood) as a whole — tract-level aggregate statistics, never an individual, household or applicant attribute. Percentages are 0-100.",
11531
+ "type": "object"
11532
+ },
11533
+ "truncated": {
11534
+ "description": "More than 4000 loans matched; the newest are returned.",
11535
+ "type": "boolean"
11536
+ }
11537
+ },
11538
+ "required": [
11539
+ "points",
11540
+ "tractCounts",
11541
+ "total",
11542
+ "truncated"
11543
+ ],
11544
+ "type": "object"
11545
+ },
11331
11546
  "CompanyBranch": {
11332
11547
  "properties": {
11333
11548
  "branchNmlsId": {
@@ -12407,7 +12622,7 @@
12407
12622
  "$ref": "#/components/schemas/CompanySlice"
12408
12623
  },
12409
12624
  {
12410
- "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."
12625
+ "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice` (400). Combines with `size` / `after` paging on a party slice: the cursor pages the `slice` ranking and every bucket on each page carries its own segments (e.g. `slice: \"broker\", segment: \"lender\"` walks every broker shop × its lenders)."
12411
12626
  }
12412
12627
  ]
12413
12628
  },
@@ -18834,11 +19049,13 @@
18834
19049
  "type": "string"
18835
19050
  },
18836
19051
  "outcome": {
18837
- "description": "Reporting classification (`status` fields only). Absent = in-progress. Seed ids `won`/`lost` classify by convention when unset.",
19052
+ "description": "Reporting classification (`status` fields only). Absent = in-progress. Seed ids `won`/`lost` classify by convention when absent; `null` explicitly un-classifies them (in-progress).",
18838
19053
  "enum": [
18839
19054
  "won",
18840
- "lost"
19055
+ "lost",
19056
+ null
18841
19057
  ],
19058
+ "nullable": true,
18842
19059
  "type": "string"
18843
19060
  }
18844
19061
  },
@@ -20607,6 +20824,14 @@
20607
20824
  "createdAt": {
20608
20825
  "type": "number"
20609
20826
  },
20827
+ "defaultView": {
20828
+ "description": "Layout the list opens in for viewers who haven't picked one: the records `table` or a status `kanban` board.",
20829
+ "enum": [
20830
+ "table",
20831
+ "kanban"
20832
+ ],
20833
+ "type": "string"
20834
+ },
20610
20835
  "hasMember": {
20611
20836
  "type": "boolean"
20612
20837
  },
@@ -20637,7 +20862,8 @@
20637
20862
  "objectType",
20638
20863
  "visibility",
20639
20864
  "memberCount",
20640
- "createdAt"
20865
+ "createdAt",
20866
+ "defaultView"
20641
20867
  ],
20642
20868
  "type": "object"
20643
20869
  },
@@ -21143,6 +21369,13 @@
21143
21369
  },
21144
21370
  "CrmListUpdateBody": {
21145
21371
  "properties": {
21372
+ "defaultView": {
21373
+ "enum": [
21374
+ "table",
21375
+ "kanban"
21376
+ ],
21377
+ "type": "string"
21378
+ },
21146
21379
  "name": {
21147
21380
  "type": "string"
21148
21381
  },
@@ -27017,6 +27250,10 @@
27017
27250
  }
27018
27251
  ]
27019
27252
  },
27253
+ "reverseRefinance": {
27254
+ "description": "HECM-to-HECM. `true`: keep only reverse loans recorded AFTER an earlier reverse loan (≥ $1,000) on the same property — a refinance of an existing reverse mortgage, resolved from the property's loan history because the transaction type does not record it. Pair with `loanType: \"reverse\"`. Resolves up to 50,000 distinct properties per request (else 400). Chart only.",
27255
+ "type": "boolean"
27256
+ },
27020
27257
  "saleDate": {
27021
27258
  "$ref": "#/components/schemas/DateFilterValue"
27022
27259
  },
@@ -27057,7 +27294,7 @@
27057
27294
  "$ref": "#/components/schemas/LoanSlice"
27058
27295
  },
27059
27296
  {
27060
- "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."
27297
+ "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice` (400). Combines with `size` / `after` paging on a party slice: the cursor pages the `slice` ranking and every bucket on each page carries its own segments (e.g. `slice: \"broker\", segment: \"lender\"` walks every broker shop × its lenders)."
27061
27298
  }
27062
27299
  ]
27063
27300
  },
@@ -27785,6 +28022,11 @@
27785
28022
  "nullable": true,
27786
28023
  "type": "number"
27787
28024
  },
28025
+ "interestRateType": {
28026
+ "description": "Recorded rate type (e.g. `FIXED`, `ADJUSTABLE`); null when not on file.",
28027
+ "nullable": true,
28028
+ "type": "string"
28029
+ },
27788
28030
  "lenderId": {
27789
28031
  "description": "Normalized lender id — the value the `lender` filter takes.",
27790
28032
  "nullable": true,
@@ -32798,7 +33040,7 @@
32798
33040
  "$ref": "#/components/schemas/OriginatorSlice"
32799
33041
  },
32800
33042
  {
32801
- "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice`, and cannot be combined with `size` / `after` paging (400)."
33043
+ "description": "Optional second dimension. Each bucket of `slice` then carries `segments`: the same `measure` broken down by this dimension (e.g. `slice: \"loanType\", segment: \"lender\"` is loan type × lender in one call), top 25 per bucket ranked by `measure`, with the remainder counted in `segmentsOmittedCount`. Omit it and the response is the one-dimensional chart, unchanged. Must differ from `slice` (400). Combines with `size` / `after` paging on a party slice: the cursor pages the `slice` ranking and every bucket on each page carries its own segments (e.g. `slice: \"broker\", segment: \"lender\"` walks every broker shop × its lenders)."
32802
33044
  }
32803
33045
  ]
32804
33046
  },
@@ -34775,6 +35017,11 @@
34775
35017
  "nullable": true,
34776
35018
  "type": "boolean"
34777
35019
  },
35020
+ "isBroker": {
35021
+ "description": "Broker (`true`) vs retail (`false`) for the selected period — the same period-scoped flag the `isBroker` filter matches. Null when the period bucket is absent.",
35022
+ "nullable": true,
35023
+ "type": "boolean"
35024
+ },
34778
35025
  "isWorking": {
34779
35026
  "description": "True when the originator holds an active company sponsorship or registration.",
34780
35027
  "nullable": true,
@@ -37051,6 +37298,11 @@
37051
37298
  "nullable": true,
37052
37299
  "type": "boolean"
37053
37300
  },
37301
+ "isBroker": {
37302
+ "description": "Broker (`true`) vs retail (`false`) for the selected period — the same period-scoped flag the `isBroker` filter matches. Null when the period bucket is absent.",
37303
+ "nullable": true,
37304
+ "type": "boolean"
37305
+ },
37054
37306
  "isWorking": {
37055
37307
  "description": "True when the originator holds an active company sponsorship or registration.",
37056
37308
  "nullable": true,
@@ -41697,6 +41949,16 @@
41697
41949
  ],
41698
41950
  "type": "string"
41699
41951
  },
41952
+ "propertyId": {
41953
+ "allOf": [
41954
+ {
41955
+ "$ref": "#/components/schemas/TextFilterValue"
41956
+ },
41957
+ {
41958
+ "description": "Parcel id — every MLS sale record of one property (the `mmPropertyId` on a loan or property record). Loans' `propertyId` selects the same parcel."
41959
+ }
41960
+ ]
41961
+ },
41700
41962
  "propertyType": {
41701
41963
  "$ref": "#/components/schemas/TextFilterValue"
41702
41964
  },
@@ -41856,6 +42118,16 @@
41856
42118
  "nullable": true,
41857
42119
  "type": "string"
41858
42120
  },
42121
+ "coListAgentId": {
42122
+ "description": "ModelMatch agent ID for the co-listing agent, same rule",
42123
+ "nullable": true,
42124
+ "type": "string"
42125
+ },
42126
+ "coListAgentName": {
42127
+ "description": "Co-listing agent's name as the MLS recorded it",
42128
+ "nullable": true,
42129
+ "type": "string"
42130
+ },
41859
42131
  "coordinates": {
41860
42132
  "nullable": true,
41861
42133
  "properties": {
@@ -41884,13 +42156,18 @@
41884
42156
  "description": "Document ID",
41885
42157
  "type": "string"
41886
42158
  },
42159
+ "listDate": {
42160
+ "description": "MLS list date (`YYYY-MM-DD`)",
42161
+ "nullable": true,
42162
+ "type": "string"
42163
+ },
41887
42164
  "listPrice": {
41888
42165
  "description": "MLS list price in dollars",
41889
42166
  "nullable": true,
41890
42167
  "type": "number"
41891
42168
  },
41892
42169
  "listingAgentId": {
41893
- "description": "ModelMatch agent ID for the listing agent",
42170
+ "description": "ModelMatch agent ID for the listing agent — the agent the MLS keys resolve to (the `agentSales` / loans rule), else the sale's linked agent id",
41894
42171
  "nullable": true,
41895
42172
  "type": "string"
41896
42173
  },
@@ -41949,7 +42226,7 @@
41949
42226
  "type": "string"
41950
42227
  },
41951
42228
  "soldAgentId": {
41952
- "description": "ModelMatch agent ID for the sold/buying agent",
42229
+ "description": "ModelMatch agent ID for the sold/buying agent, same rule",
41953
42230
  "nullable": true,
41954
42231
  "type": "string"
41955
42232
  },
@@ -41957,6 +42234,11 @@
41957
42234
  "nullable": true,
41958
42235
  "type": "string"
41959
42236
  },
42237
+ "soldDate": {
42238
+ "description": "MLS sold date (`YYYY-MM-DD`) — the MLS close, which can differ from `transactionDate` (the recorded deed)",
42239
+ "nullable": true,
42240
+ "type": "string"
42241
+ },
41960
42242
  "soldPrice": {
41961
42243
  "description": "MLS sold price in dollars",
41962
42244
  "nullable": true,
@@ -43927,7 +44209,7 @@
43927
44209
  "info": {
43928
44210
  "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.",
43929
44211
  "title": "ModelMatch API",
43930
- "version": "3.112.0"
44212
+ "version": "3.119.0"
43931
44213
  },
43932
44214
  "openapi": "3.1.0",
43933
44215
  "paths": {
@@ -44454,7 +44736,7 @@
44454
44736
  }
44455
44737
  }
44456
44738
  },
44457
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
44739
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
44458
44740
  }
44459
44741
  },
44460
44742
  "summary": "Submit a bulk-delivery job for agents",
@@ -50254,7 +50536,7 @@
50254
50536
  }
50255
50537
  }
50256
50538
  },
50257
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
50539
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
50258
50540
  }
50259
50541
  },
50260
50542
  "summary": "Submit a bulk-delivery job for branches",
@@ -50490,6 +50772,97 @@
50490
50772
  "x-mm-records-via": "listBranches"
50491
50773
  }
50492
50774
  },
50775
+ "/v1/branches/stats": {
50776
+ "post": {
50777
+ "description": "Accepts the same request body as `listBranches` (pagination and sort are ignored) and returns aggregate KPIs over every matching branch: count, producing count, average roster size, total units and the top 3 branches' units. Use it for a company's branch network summary (`flatFilters.company`).",
50778
+ "operationId": "branchStats",
50779
+ "requestBody": {
50780
+ "content": {
50781
+ "application/json": {
50782
+ "schema": {
50783
+ "$ref": "#/components/schemas/BranchListRequest"
50784
+ }
50785
+ }
50786
+ }
50787
+ },
50788
+ "responses": {
50789
+ "200": {
50790
+ "content": {
50791
+ "application/json": {
50792
+ "schema": {
50793
+ "$ref": "#/components/schemas/BranchStatsResponse"
50794
+ }
50795
+ }
50796
+ },
50797
+ "description": "Branch roll-up KPIs"
50798
+ },
50799
+ "400": {
50800
+ "content": {
50801
+ "application/json": {
50802
+ "schema": {
50803
+ "$ref": "#/components/schemas/ErrorResponse"
50804
+ }
50805
+ }
50806
+ },
50807
+ "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."
50808
+ },
50809
+ "401": {
50810
+ "content": {
50811
+ "application/json": {
50812
+ "schema": {
50813
+ "$ref": "#/components/schemas/ErrorResponse"
50814
+ }
50815
+ }
50816
+ },
50817
+ "description": "Unauthorized"
50818
+ },
50819
+ "403": {
50820
+ "content": {
50821
+ "application/json": {
50822
+ "schema": {
50823
+ "$ref": "#/components/schemas/ErrorResponse"
50824
+ }
50825
+ }
50826
+ },
50827
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
50828
+ },
50829
+ "404": {
50830
+ "content": {
50831
+ "application/json": {
50832
+ "schema": {
50833
+ "$ref": "#/components/schemas/ErrorResponse"
50834
+ }
50835
+ }
50836
+ },
50837
+ "description": "Not found"
50838
+ },
50839
+ "413": {
50840
+ "content": {
50841
+ "application/json": {
50842
+ "schema": {
50843
+ "$ref": "#/components/schemas/PayloadTooLarge"
50844
+ }
50845
+ }
50846
+ },
50847
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
50848
+ },
50849
+ "503": {
50850
+ "content": {
50851
+ "application/json": {
50852
+ "schema": {
50853
+ "$ref": "#/components/schemas/SearchUnavailable"
50854
+ }
50855
+ }
50856
+ },
50857
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
50858
+ }
50859
+ },
50860
+ "summary": "Roll-up KPIs over the branches matching filters",
50861
+ "tags": [
50862
+ "Branches"
50863
+ ]
50864
+ }
50865
+ },
50493
50866
  "/v1/branches/{nmlsId}": {
50494
50867
  "get": {
50495
50868
  "description": "Retrieve full details for a single NMLS mortgage branch including name, address, parent company, managers, trade names, licensing, and branch-level production for the selected period.",
@@ -50853,16 +51226,119 @@
50853
51226
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
50854
51227
  }
50855
51228
  },
50856
- "summary": "Lenders this branch originated through",
51229
+ "summary": "Lenders this branch originated through",
51230
+ "tags": [
51231
+ "Branches"
51232
+ ]
51233
+ }
51234
+ },
51235
+ "/v1/branches/{nmlsId}/breakdowns/originators": {
51236
+ "post": {
51237
+ "description": "Ranks the loan officers whose loans public record attributes to this branch, by volume. Each label is the LO's NMLS ID, so it chains straight into `GET /v1/originators/{nmlsId}`. This is the branch's RECORDED roster, not its licensing roster: it answers who actually wrote loans here in the period, which is narrower than everyone registered to the branch and can include someone who has since moved. For the licensed managers on file, read `managers` on `GET /v1/branches/{nmlsId}`.",
51238
+ "operationId": "branchOriginators",
51239
+ "parameters": [
51240
+ {
51241
+ "description": "Branch NMLS ID",
51242
+ "in": "path",
51243
+ "name": "nmlsId",
51244
+ "required": true,
51245
+ "schema": {
51246
+ "description": "Branch NMLS ID",
51247
+ "type": "string"
51248
+ }
51249
+ }
51250
+ ],
51251
+ "requestBody": {
51252
+ "content": {
51253
+ "application/json": {
51254
+ "schema": {
51255
+ "$ref": "#/components/schemas/BreakdownRequest"
51256
+ }
51257
+ }
51258
+ }
51259
+ },
51260
+ "responses": {
51261
+ "200": {
51262
+ "content": {
51263
+ "application/json": {
51264
+ "schema": {
51265
+ "$ref": "#/components/schemas/BreakdownResponse"
51266
+ }
51267
+ }
51268
+ },
51269
+ "description": "Breakdown of this branch's loans by originators"
51270
+ },
51271
+ "400": {
51272
+ "content": {
51273
+ "application/json": {
51274
+ "schema": {
51275
+ "$ref": "#/components/schemas/ErrorResponse"
51276
+ }
51277
+ }
51278
+ },
51279
+ "description": "Validation error"
51280
+ },
51281
+ "401": {
51282
+ "content": {
51283
+ "application/json": {
51284
+ "schema": {
51285
+ "$ref": "#/components/schemas/ErrorResponse"
51286
+ }
51287
+ }
51288
+ },
51289
+ "description": "Unauthorized"
51290
+ },
51291
+ "403": {
51292
+ "content": {
51293
+ "application/json": {
51294
+ "schema": {
51295
+ "$ref": "#/components/schemas/ErrorResponse"
51296
+ }
51297
+ }
51298
+ },
51299
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
51300
+ },
51301
+ "404": {
51302
+ "content": {
51303
+ "application/json": {
51304
+ "schema": {
51305
+ "$ref": "#/components/schemas/ErrorResponse"
51306
+ }
51307
+ }
51308
+ },
51309
+ "description": "Not found"
51310
+ },
51311
+ "413": {
51312
+ "content": {
51313
+ "application/json": {
51314
+ "schema": {
51315
+ "$ref": "#/components/schemas/PayloadTooLarge"
51316
+ }
51317
+ }
51318
+ },
51319
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
51320
+ },
51321
+ "503": {
51322
+ "content": {
51323
+ "application/json": {
51324
+ "schema": {
51325
+ "$ref": "#/components/schemas/SearchUnavailable"
51326
+ }
51327
+ }
51328
+ },
51329
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
51330
+ }
51331
+ },
51332
+ "summary": "Loan officers who wrote this branch's loans",
50857
51333
  "tags": [
50858
51334
  "Branches"
50859
51335
  ]
50860
51336
  }
50861
51337
  },
50862
- "/v1/branches/{nmlsId}/breakdowns/originators": {
51338
+ "/v1/branches/{nmlsId}/breakdowns/states": {
50863
51339
  "post": {
50864
- "description": "Ranks the loan officers whose loans public record attributes to this branch, by volume. Each label is the LO's NMLS ID, so it chains straight into `GET /v1/originators/{nmlsId}`. This is the branch's RECORDED roster, not its licensing roster: it answers who actually wrote loans here in the period, which is narrower than everyone registered to the branch and can include someone who has since moved. For the licensed managers on file, read `managers` on `GET /v1/branches/{nmlsId}`.",
50865
- "operationId": "branchOriginators",
51340
+ "description": "Ranks the states this branch's loans were secured in, by volume. Labels are two-letter state abbreviations. This is where the branch actually transacted, which is narrower than where it is licensed — licensed states are returned by `GET /v1/branches/{nmlsId}`.",
51341
+ "operationId": "branchStates",
50866
51342
  "parameters": [
50867
51343
  {
50868
51344
  "description": "Branch NMLS ID",
@@ -50893,7 +51369,7 @@
50893
51369
  }
50894
51370
  }
50895
51371
  },
50896
- "description": "Breakdown of this branch's loans by originators"
51372
+ "description": "Breakdown of this branch's loans by states"
50897
51373
  },
50898
51374
  "400": {
50899
51375
  "content": {
@@ -50956,16 +51432,16 @@
50956
51432
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
50957
51433
  }
50958
51434
  },
50959
- "summary": "Loan officers who wrote this branch's loans",
51435
+ "summary": "State volume breakdown across this branch's loans",
50960
51436
  "tags": [
50961
51437
  "Branches"
50962
51438
  ]
50963
51439
  }
50964
51440
  },
50965
- "/v1/branches/{nmlsId}/breakdowns/states": {
51441
+ "/v1/branches/{nmlsId}/breakdowns/title-companies": {
50966
51442
  "post": {
50967
- "description": "Ranks the states this branch's loans were secured in, by volume. Labels are two-letter state abbreviations. This is where the branch actually transacted, which is narrower than where it is licensed — licensed states are returned by `GET /v1/branches/{nmlsId}`.",
50968
- "operationId": "branchStates",
51443
+ "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`.",
51444
+ "operationId": "branchTitleCompanies",
50969
51445
  "parameters": [
50970
51446
  {
50971
51447
  "description": "Branch NMLS ID",
@@ -50996,7 +51472,7 @@
50996
51472
  }
50997
51473
  }
50998
51474
  },
50999
- "description": "Breakdown of this branch's loans by states"
51475
+ "description": "Breakdown of the entity's loans by title company"
51000
51476
  },
51001
51477
  "400": {
51002
51478
  "content": {
@@ -51059,47 +51535,54 @@
51059
51535
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
51060
51536
  }
51061
51537
  },
51062
- "summary": "State volume breakdown across this branch's loans",
51538
+ "summary": "Title companies on this branch's loans (spellings merged)",
51063
51539
  "tags": [
51064
51540
  "Branches"
51065
51541
  ]
51066
51542
  }
51067
51543
  },
51068
- "/v1/branches/{nmlsId}/breakdowns/title-companies": {
51069
- "post": {
51070
- "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`.",
51071
- "operationId": "branchTitleCompanies",
51544
+ "/v1/branches/{nmlsId}/community-lending/map": {
51545
+ "get": {
51546
+ "description": "Map points for loans written by this branch's current roster in the period that resolved to a Census tract, newest first (up to 4,000), plus a per-tract loan count keyed by 11-digit tract GEOID for a choropleth.",
51547
+ "operationId": "branchCommunityLendingMap",
51072
51548
  "parameters": [
51073
51549
  {
51074
- "description": "Branch NMLS ID",
51550
+ "description": "Branche NMLS ID",
51075
51551
  "in": "path",
51076
51552
  "name": "nmlsId",
51077
51553
  "required": true,
51078
51554
  "schema": {
51079
- "description": "Branch NMLS ID",
51555
+ "description": "Branche NMLS ID",
51080
51556
  "type": "string"
51081
51557
  }
51082
- }
51083
- ],
51084
- "requestBody": {
51085
- "content": {
51086
- "application/json": {
51087
- "schema": {
51088
- "$ref": "#/components/schemas/BreakdownRequest"
51089
- }
51558
+ },
51559
+ {
51560
+ "description": "Period window (default: last12Months).",
51561
+ "in": "query",
51562
+ "name": "period",
51563
+ "required": false,
51564
+ "schema": {
51565
+ "allOf": [
51566
+ {
51567
+ "$ref": "#/components/schemas/Period"
51568
+ },
51569
+ {
51570
+ "description": "Period window (default: last12Months)."
51571
+ }
51572
+ ]
51090
51573
  }
51091
51574
  }
51092
- },
51575
+ ],
51093
51576
  "responses": {
51094
51577
  "200": {
51095
51578
  "content": {
51096
51579
  "application/json": {
51097
51580
  "schema": {
51098
- "$ref": "#/components/schemas/BreakdownResponse"
51581
+ "$ref": "#/components/schemas/CommunityLendingMapResponse"
51099
51582
  }
51100
51583
  }
51101
51584
  },
51102
- "description": "Breakdown of the entity's loans by title company"
51585
+ "description": "Map feed"
51103
51586
  },
51104
51587
  "400": {
51105
51588
  "content": {
@@ -51162,7 +51645,7 @@
51162
51645
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
51163
51646
  }
51164
51647
  },
51165
- "summary": "Title companies on this branch's loans (spellings merged)",
51648
+ "summary": "Community Lending map: geocoded loans + per-tract counts",
51166
51649
  "tags": [
51167
51650
  "Branches"
51168
51651
  ]
@@ -51897,7 +52380,7 @@
51897
52380
  }
51898
52381
  }
51899
52382
  },
51900
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
52383
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
51901
52384
  }
51902
52385
  },
51903
52386
  "summary": "Submit a bulk-delivery job for companies",
@@ -53328,47 +53811,259 @@
53328
53811
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
53329
53812
  }
53330
53813
  },
53331
- "summary": "State volume breakdown across this company's loans",
53814
+ "summary": "State volume breakdown across this company's loans",
53815
+ "tags": [
53816
+ "Companies"
53817
+ ]
53818
+ }
53819
+ },
53820
+ "/v1/companies/{nmlsId}/breakdowns/title-companies": {
53821
+ "post": {
53822
+ "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`.",
53823
+ "operationId": "companyTitleCompanies",
53824
+ "parameters": [
53825
+ {
53826
+ "description": "Company NMLS ID",
53827
+ "in": "path",
53828
+ "name": "nmlsId",
53829
+ "required": true,
53830
+ "schema": {
53831
+ "description": "Company NMLS ID",
53832
+ "type": "string"
53833
+ }
53834
+ }
53835
+ ],
53836
+ "requestBody": {
53837
+ "content": {
53838
+ "application/json": {
53839
+ "schema": {
53840
+ "$ref": "#/components/schemas/CompanyBreakdownRequest"
53841
+ }
53842
+ }
53843
+ }
53844
+ },
53845
+ "responses": {
53846
+ "200": {
53847
+ "content": {
53848
+ "application/json": {
53849
+ "schema": {
53850
+ "$ref": "#/components/schemas/BreakdownResponse"
53851
+ }
53852
+ }
53853
+ },
53854
+ "description": "Breakdown of the entity's loans by title company"
53855
+ },
53856
+ "400": {
53857
+ "content": {
53858
+ "application/json": {
53859
+ "schema": {
53860
+ "$ref": "#/components/schemas/ErrorResponse"
53861
+ }
53862
+ }
53863
+ },
53864
+ "description": "Validation error"
53865
+ },
53866
+ "401": {
53867
+ "content": {
53868
+ "application/json": {
53869
+ "schema": {
53870
+ "$ref": "#/components/schemas/ErrorResponse"
53871
+ }
53872
+ }
53873
+ },
53874
+ "description": "Unauthorized"
53875
+ },
53876
+ "403": {
53877
+ "content": {
53878
+ "application/json": {
53879
+ "schema": {
53880
+ "$ref": "#/components/schemas/ErrorResponse"
53881
+ }
53882
+ }
53883
+ },
53884
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
53885
+ },
53886
+ "404": {
53887
+ "content": {
53888
+ "application/json": {
53889
+ "schema": {
53890
+ "$ref": "#/components/schemas/ErrorResponse"
53891
+ }
53892
+ }
53893
+ },
53894
+ "description": "Not found"
53895
+ },
53896
+ "413": {
53897
+ "content": {
53898
+ "application/json": {
53899
+ "schema": {
53900
+ "$ref": "#/components/schemas/PayloadTooLarge"
53901
+ }
53902
+ }
53903
+ },
53904
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
53905
+ },
53906
+ "503": {
53907
+ "content": {
53908
+ "application/json": {
53909
+ "schema": {
53910
+ "$ref": "#/components/schemas/SearchUnavailable"
53911
+ }
53912
+ }
53913
+ },
53914
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
53915
+ }
53916
+ },
53917
+ "summary": "Title companies on this company's loans (spellings merged)",
53918
+ "tags": [
53919
+ "Companies"
53920
+ ]
53921
+ }
53922
+ },
53923
+ "/v1/companies/{nmlsId}/breakdowns/zip-codes": {
53924
+ "post": {
53925
+ "operationId": "companyZipCodes",
53926
+ "parameters": [
53927
+ {
53928
+ "description": "Company NMLS ID",
53929
+ "in": "path",
53930
+ "name": "nmlsId",
53931
+ "required": true,
53932
+ "schema": {
53933
+ "description": "Company NMLS ID",
53934
+ "type": "string"
53935
+ }
53936
+ }
53937
+ ],
53938
+ "requestBody": {
53939
+ "content": {
53940
+ "application/json": {
53941
+ "schema": {
53942
+ "$ref": "#/components/schemas/CompanyBreakdownRequest"
53943
+ }
53944
+ }
53945
+ }
53946
+ },
53947
+ "responses": {
53948
+ "200": {
53949
+ "content": {
53950
+ "application/json": {
53951
+ "schema": {
53952
+ "$ref": "#/components/schemas/BreakdownResponse"
53953
+ }
53954
+ }
53955
+ },
53956
+ "description": "Breakdown of the company's loans by zip-codes"
53957
+ },
53958
+ "400": {
53959
+ "content": {
53960
+ "application/json": {
53961
+ "schema": {
53962
+ "$ref": "#/components/schemas/ErrorResponse"
53963
+ }
53964
+ }
53965
+ },
53966
+ "description": "Validation error"
53967
+ },
53968
+ "401": {
53969
+ "content": {
53970
+ "application/json": {
53971
+ "schema": {
53972
+ "$ref": "#/components/schemas/ErrorResponse"
53973
+ }
53974
+ }
53975
+ },
53976
+ "description": "Unauthorized"
53977
+ },
53978
+ "403": {
53979
+ "content": {
53980
+ "application/json": {
53981
+ "schema": {
53982
+ "$ref": "#/components/schemas/ErrorResponse"
53983
+ }
53984
+ }
53985
+ },
53986
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
53987
+ },
53988
+ "404": {
53989
+ "content": {
53990
+ "application/json": {
53991
+ "schema": {
53992
+ "$ref": "#/components/schemas/ErrorResponse"
53993
+ }
53994
+ }
53995
+ },
53996
+ "description": "Not found"
53997
+ },
53998
+ "413": {
53999
+ "content": {
54000
+ "application/json": {
54001
+ "schema": {
54002
+ "$ref": "#/components/schemas/PayloadTooLarge"
54003
+ }
54004
+ }
54005
+ },
54006
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
54007
+ },
54008
+ "503": {
54009
+ "content": {
54010
+ "application/json": {
54011
+ "schema": {
54012
+ "$ref": "#/components/schemas/SearchUnavailable"
54013
+ }
54014
+ }
54015
+ },
54016
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
54017
+ }
54018
+ },
54019
+ "summary": "Zip-code volume breakdown across this company's loans",
53332
54020
  "tags": [
53333
54021
  "Companies"
53334
54022
  ]
53335
54023
  }
53336
54024
  },
53337
- "/v1/companies/{nmlsId}/breakdowns/title-companies": {
53338
- "post": {
53339
- "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`.",
53340
- "operationId": "companyTitleCompanies",
54025
+ "/v1/companies/{nmlsId}/community-lending/benchmark": {
54026
+ "get": {
54027
+ "description": "Percentile rank and peer average of this entity's low- or moderate-income and majority-minority neighborhood shares, against peers producing in its top 12 states by units. `data` is null when the entity has no neighborhood-resolved loans in the period.",
54028
+ "operationId": "companyCommunityLendingBenchmark",
53341
54029
  "parameters": [
53342
54030
  {
53343
- "description": "Company NMLS ID",
54031
+ "description": "Companie NMLS ID",
53344
54032
  "in": "path",
53345
54033
  "name": "nmlsId",
53346
54034
  "required": true,
53347
54035
  "schema": {
53348
- "description": "Company NMLS ID",
54036
+ "description": "Companie NMLS ID",
53349
54037
  "type": "string"
53350
54038
  }
53351
- }
53352
- ],
53353
- "requestBody": {
53354
- "content": {
53355
- "application/json": {
53356
- "schema": {
53357
- "$ref": "#/components/schemas/CompanyBreakdownRequest"
53358
- }
54039
+ },
54040
+ {
54041
+ "description": "Period window (default: last12Months).",
54042
+ "in": "query",
54043
+ "name": "period",
54044
+ "required": false,
54045
+ "schema": {
54046
+ "allOf": [
54047
+ {
54048
+ "$ref": "#/components/schemas/Period"
54049
+ },
54050
+ {
54051
+ "description": "Period window (default: last12Months)."
54052
+ }
54053
+ ]
53359
54054
  }
53360
54055
  }
53361
- },
54056
+ ],
53362
54057
  "responses": {
53363
54058
  "200": {
53364
54059
  "content": {
53365
54060
  "application/json": {
53366
54061
  "schema": {
53367
- "$ref": "#/components/schemas/BreakdownResponse"
54062
+ "$ref": "#/components/schemas/CommunityLendingBenchmarkResponse"
53368
54063
  }
53369
54064
  }
53370
54065
  },
53371
- "description": "Breakdown of the entity's loans by title company"
54066
+ "description": "Peer benchmark"
53372
54067
  },
53373
54068
  "400": {
53374
54069
  "content": {
@@ -53431,46 +54126,54 @@
53431
54126
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
53432
54127
  }
53433
54128
  },
53434
- "summary": "Title companies on this company's loans (spellings merged)",
54129
+ "summary": "Community Lending peer benchmark (LMI / majority-minority)",
53435
54130
  "tags": [
53436
54131
  "Companies"
53437
54132
  ]
53438
54133
  }
53439
54134
  },
53440
- "/v1/companies/{nmlsId}/breakdowns/zip-codes": {
53441
- "post": {
53442
- "operationId": "companyZipCodes",
54135
+ "/v1/companies/{nmlsId}/community-lending/map": {
54136
+ "get": {
54137
+ "description": "Map points for loans naming this company on the loan document in the period that resolved to a Census tract, newest first (up to 4,000), plus a per-tract loan count keyed by 11-digit tract GEOID for a choropleth.",
54138
+ "operationId": "companyCommunityLendingMap",
53443
54139
  "parameters": [
53444
54140
  {
53445
- "description": "Company NMLS ID",
54141
+ "description": "Companie NMLS ID",
53446
54142
  "in": "path",
53447
54143
  "name": "nmlsId",
53448
54144
  "required": true,
53449
54145
  "schema": {
53450
- "description": "Company NMLS ID",
54146
+ "description": "Companie NMLS ID",
53451
54147
  "type": "string"
53452
54148
  }
53453
- }
53454
- ],
53455
- "requestBody": {
53456
- "content": {
53457
- "application/json": {
53458
- "schema": {
53459
- "$ref": "#/components/schemas/CompanyBreakdownRequest"
53460
- }
54149
+ },
54150
+ {
54151
+ "description": "Period window (default: last12Months).",
54152
+ "in": "query",
54153
+ "name": "period",
54154
+ "required": false,
54155
+ "schema": {
54156
+ "allOf": [
54157
+ {
54158
+ "$ref": "#/components/schemas/Period"
54159
+ },
54160
+ {
54161
+ "description": "Period window (default: last12Months)."
54162
+ }
54163
+ ]
53461
54164
  }
53462
54165
  }
53463
- },
54166
+ ],
53464
54167
  "responses": {
53465
54168
  "200": {
53466
54169
  "content": {
53467
54170
  "application/json": {
53468
54171
  "schema": {
53469
- "$ref": "#/components/schemas/BreakdownResponse"
54172
+ "$ref": "#/components/schemas/CommunityLendingMapResponse"
53470
54173
  }
53471
54174
  }
53472
54175
  },
53473
- "description": "Breakdown of the company's loans by zip-codes"
54176
+ "description": "Map feed"
53474
54177
  },
53475
54178
  "400": {
53476
54179
  "content": {
@@ -53533,7 +54236,7 @@
53533
54236
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
53534
54237
  }
53535
54238
  },
53536
- "summary": "Zip-code volume breakdown across this company's loans",
54239
+ "summary": "Community Lending map: geocoded loans + per-tract counts",
53537
54240
  "tags": [
53538
54241
  "Companies"
53539
54242
  ]
@@ -59891,7 +60594,7 @@
59891
60594
  "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
59892
60595
  }
59893
60596
  },
59894
- "summary": "Update a list's name, visibility, or whole-org role",
60597
+ "summary": "Update a list's name, visibility, whole-org role, or default view",
59895
60598
  "tags": [
59896
60599
  "CRM"
59897
60600
  ]
@@ -70779,7 +71482,7 @@
70779
71482
  }
70780
71483
  }
70781
71484
  },
70782
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
71485
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
70783
71486
  }
70784
71487
  },
70785
71488
  "summary": "Submit a bulk-delivery job for loans",
@@ -75224,7 +75927,7 @@
75224
75927
  }
75225
75928
  }
75226
75929
  },
75227
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
75930
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
75228
75931
  }
75229
75932
  },
75230
75933
  "summary": "Submit a bulk-delivery job for originators",
@@ -76988,6 +77691,226 @@
76988
77691
  ]
76989
77692
  }
76990
77693
  },
77694
+ "/v1/originators/{nmlsId}/community-lending/benchmark": {
77695
+ "get": {
77696
+ "description": "Percentile rank and peer average of this entity's low- or moderate-income and majority-minority neighborhood shares, against peers producing in its top 12 states by units. `data` is null when the entity has no neighborhood-resolved loans in the period.",
77697
+ "operationId": "originatorCommunityLendingBenchmark",
77698
+ "parameters": [
77699
+ {
77700
+ "description": "Originator NMLS ID",
77701
+ "in": "path",
77702
+ "name": "nmlsId",
77703
+ "required": true,
77704
+ "schema": {
77705
+ "description": "Originator NMLS ID",
77706
+ "type": "string"
77707
+ }
77708
+ },
77709
+ {
77710
+ "description": "Period window (default: last12Months).",
77711
+ "in": "query",
77712
+ "name": "period",
77713
+ "required": false,
77714
+ "schema": {
77715
+ "allOf": [
77716
+ {
77717
+ "$ref": "#/components/schemas/Period"
77718
+ },
77719
+ {
77720
+ "description": "Period window (default: last12Months)."
77721
+ }
77722
+ ]
77723
+ }
77724
+ }
77725
+ ],
77726
+ "responses": {
77727
+ "200": {
77728
+ "content": {
77729
+ "application/json": {
77730
+ "schema": {
77731
+ "$ref": "#/components/schemas/CommunityLendingBenchmarkResponse"
77732
+ }
77733
+ }
77734
+ },
77735
+ "description": "Peer benchmark"
77736
+ },
77737
+ "400": {
77738
+ "content": {
77739
+ "application/json": {
77740
+ "schema": {
77741
+ "$ref": "#/components/schemas/ErrorResponse"
77742
+ }
77743
+ }
77744
+ },
77745
+ "description": "Validation error"
77746
+ },
77747
+ "401": {
77748
+ "content": {
77749
+ "application/json": {
77750
+ "schema": {
77751
+ "$ref": "#/components/schemas/ErrorResponse"
77752
+ }
77753
+ }
77754
+ },
77755
+ "description": "Unauthorized"
77756
+ },
77757
+ "403": {
77758
+ "content": {
77759
+ "application/json": {
77760
+ "schema": {
77761
+ "$ref": "#/components/schemas/ErrorResponse"
77762
+ }
77763
+ }
77764
+ },
77765
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
77766
+ },
77767
+ "404": {
77768
+ "content": {
77769
+ "application/json": {
77770
+ "schema": {
77771
+ "$ref": "#/components/schemas/ErrorResponse"
77772
+ }
77773
+ }
77774
+ },
77775
+ "description": "Not found"
77776
+ },
77777
+ "413": {
77778
+ "content": {
77779
+ "application/json": {
77780
+ "schema": {
77781
+ "$ref": "#/components/schemas/PayloadTooLarge"
77782
+ }
77783
+ }
77784
+ },
77785
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
77786
+ },
77787
+ "503": {
77788
+ "content": {
77789
+ "application/json": {
77790
+ "schema": {
77791
+ "$ref": "#/components/schemas/SearchUnavailable"
77792
+ }
77793
+ }
77794
+ },
77795
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
77796
+ }
77797
+ },
77798
+ "summary": "Community Lending peer benchmark (LMI / majority-minority)",
77799
+ "tags": [
77800
+ "Originators"
77801
+ ]
77802
+ }
77803
+ },
77804
+ "/v1/originators/{nmlsId}/community-lending/map": {
77805
+ "get": {
77806
+ "description": "Map points for this loan officer's loans in the period that resolved to a Census tract, newest first (up to 4,000), plus a per-tract loan count keyed by 11-digit tract GEOID for a choropleth.",
77807
+ "operationId": "originatorCommunityLendingMap",
77808
+ "parameters": [
77809
+ {
77810
+ "description": "Originator NMLS ID",
77811
+ "in": "path",
77812
+ "name": "nmlsId",
77813
+ "required": true,
77814
+ "schema": {
77815
+ "description": "Originator NMLS ID",
77816
+ "type": "string"
77817
+ }
77818
+ },
77819
+ {
77820
+ "description": "Period window (default: last12Months).",
77821
+ "in": "query",
77822
+ "name": "period",
77823
+ "required": false,
77824
+ "schema": {
77825
+ "allOf": [
77826
+ {
77827
+ "$ref": "#/components/schemas/Period"
77828
+ },
77829
+ {
77830
+ "description": "Period window (default: last12Months)."
77831
+ }
77832
+ ]
77833
+ }
77834
+ }
77835
+ ],
77836
+ "responses": {
77837
+ "200": {
77838
+ "content": {
77839
+ "application/json": {
77840
+ "schema": {
77841
+ "$ref": "#/components/schemas/CommunityLendingMapResponse"
77842
+ }
77843
+ }
77844
+ },
77845
+ "description": "Map feed"
77846
+ },
77847
+ "400": {
77848
+ "content": {
77849
+ "application/json": {
77850
+ "schema": {
77851
+ "$ref": "#/components/schemas/ErrorResponse"
77852
+ }
77853
+ }
77854
+ },
77855
+ "description": "Validation error"
77856
+ },
77857
+ "401": {
77858
+ "content": {
77859
+ "application/json": {
77860
+ "schema": {
77861
+ "$ref": "#/components/schemas/ErrorResponse"
77862
+ }
77863
+ }
77864
+ },
77865
+ "description": "Unauthorized"
77866
+ },
77867
+ "403": {
77868
+ "content": {
77869
+ "application/json": {
77870
+ "schema": {
77871
+ "$ref": "#/components/schemas/ErrorResponse"
77872
+ }
77873
+ }
77874
+ },
77875
+ "description": "Forbidden (authenticated, but missing required context — e.g. no active organization)"
77876
+ },
77877
+ "404": {
77878
+ "content": {
77879
+ "application/json": {
77880
+ "schema": {
77881
+ "$ref": "#/components/schemas/ErrorResponse"
77882
+ }
77883
+ }
77884
+ },
77885
+ "description": "Not found"
77886
+ },
77887
+ "413": {
77888
+ "content": {
77889
+ "application/json": {
77890
+ "schema": {
77891
+ "$ref": "#/components/schemas/PayloadTooLarge"
77892
+ }
77893
+ }
77894
+ },
77895
+ "description": "Response payload too large — detail endpoint capped to fit Lambda response limits"
77896
+ },
77897
+ "503": {
77898
+ "content": {
77899
+ "application/json": {
77900
+ "schema": {
77901
+ "$ref": "#/components/schemas/SearchUnavailable"
77902
+ }
77903
+ }
77904
+ },
77905
+ "description": "Search timed out or the cluster is overloaded — retry after `Retry-After` seconds."
77906
+ }
77907
+ },
77908
+ "summary": "Community Lending map: geocoded loans + per-tract counts",
77909
+ "tags": [
77910
+ "Originators"
77911
+ ]
77912
+ }
77913
+ },
76991
77914
  "/v1/originators/{nmlsId}/loans": {
76992
77915
  "post": {
76993
77916
  "operationId": "originatorLoans",
@@ -77842,7 +78765,7 @@
77842
78765
  }
77843
78766
  }
77844
78767
  },
77845
- "description": "Preflight / S3 / DDB / ECS launch failure, or the push-target check could not reach the auth server"
78768
+ "description": "Preflight / S3 / DDB / ECS launch failure, the push-target check could not reach the auth server, or the credit balance could not be read (`billing_unavailable` — retry; a paid delivery is never queued unverified)"
77846
78769
  }
77847
78770
  },
77848
78771
  "summary": "Submit a bulk-delivery job for properties",
@@ -78271,7 +79194,7 @@
78271
79194
  }
78272
79195
  }
78273
79196
  },
78274
- "description": "Failed to launch task or stage inputs"
79197
+ "description": "Failed to launch task or stage inputs, or the credit balance could not be read (`billing_unavailable`, nothing queued)"
78275
79198
  }
78276
79199
  },
78277
79200
  "summary": "Submit a bulk skip-trace job",