@lerianstudio/matcher-mcp 5.0.0-beta.13 → 5.0.0-beta.130

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.
Files changed (273) hide show
  1. package/README.md +28 -13
  2. package/dist/auth/request-token.js +11 -69
  3. package/dist/auth/request-token.js.map +1 -1
  4. package/dist/config.js +6 -21
  5. package/dist/config.js.map +1 -1
  6. package/dist/copilot/agent.js +5 -9
  7. package/dist/copilot/agent.js.map +1 -1
  8. package/dist/copilot/provider-anthropic.js +75 -23
  9. package/dist/copilot/provider-anthropic.js.map +1 -1
  10. package/dist/copilot/provider-openrouter.js +5 -18
  11. package/dist/copilot/provider-openrouter.js.map +1 -1
  12. package/dist/copilot/provider-shared.js +11 -0
  13. package/dist/copilot/provider-shared.js.map +1 -1
  14. package/dist/copilot/speech-provider.js +84 -0
  15. package/dist/copilot/speech-provider.js.map +1 -0
  16. package/dist/copilot/sse.js +5 -0
  17. package/dist/copilot/sse.js.map +1 -1
  18. package/dist/copilot/system-prompt.js +6 -2
  19. package/dist/copilot/system-prompt.js.map +1 -1
  20. package/dist/copilot/tools.js +14 -65
  21. package/dist/copilot/tools.js.map +1 -1
  22. package/dist/copilot/transcribe-handler.js +8 -93
  23. package/dist/copilot/transcribe-handler.js.map +1 -1
  24. package/dist/copilot/turn-request.js +76 -0
  25. package/dist/copilot/turn-request.js.map +1 -0
  26. package/dist/copilot/turns-handler.js +11 -102
  27. package/dist/copilot/turns-handler.js.map +1 -1
  28. package/dist/matcher/client.js +14 -0
  29. package/dist/matcher/client.js.map +1 -1
  30. package/dist/matcher/idempotency.js +94 -0
  31. package/dist/matcher/idempotency.js.map +1 -0
  32. package/dist/observability/otel.js +7 -29
  33. package/dist/observability/otel.js.map +1 -1
  34. package/dist/server.js +12 -81
  35. package/dist/server.js.map +1 -1
  36. package/dist/spec/curated-operations.js +111 -95
  37. package/dist/spec/curated-operations.js.map +1 -1
  38. package/dist/spec/enum-policy.js +21 -26
  39. package/dist/spec/enum-policy.js.map +1 -1
  40. package/dist/spec/openapi.yaml +875 -64
  41. package/dist/spec/schema-parity.js +23 -28
  42. package/dist/spec/schema-parity.js.map +1 -1
  43. package/dist/tools/context/create.js +14 -3
  44. package/dist/tools/context/create.js.map +1 -1
  45. package/dist/tools/context/index.js +137 -17
  46. package/dist/tools/context/index.js.map +1 -1
  47. package/dist/tools/context/list.js +9 -35
  48. package/dist/tools/context/list.js.map +1 -1
  49. package/dist/tools/context/setup-progress.js +3 -2
  50. package/dist/tools/context/setup-progress.js.map +1 -1
  51. package/dist/tools/context/shared.js +7 -48
  52. package/dist/tools/context/shared.js.map +1 -1
  53. package/dist/tools/context/update.js +15 -7
  54. package/dist/tools/context/update.js.map +1 -1
  55. package/dist/tools/curated-tool.js +39 -0
  56. package/dist/tools/curated-tool.js.map +1 -0
  57. package/dist/tools/dashboard/index.js +124 -19
  58. package/dist/tools/dashboard/index.js.map +1 -1
  59. package/dist/tools/dashboard/shared.js +9 -68
  60. package/dist/tools/dashboard/shared.js.map +1 -1
  61. package/dist/tools/dispute/close.js +5 -5
  62. package/dist/tools/dispute/close.js.map +1 -1
  63. package/dist/tools/dispute/index.js +34 -6
  64. package/dist/tools/dispute/index.js.map +1 -1
  65. package/dist/tools/dispute/list.js +18 -47
  66. package/dist/tools/dispute/list.js.map +1 -1
  67. package/dist/tools/dispute/shared.js +4 -43
  68. package/dist/tools/dispute/shared.js.map +1 -1
  69. package/dist/tools/dispute/submit-evidence.js +5 -5
  70. package/dist/tools/dispute/submit-evidence.js.map +1 -1
  71. package/dist/tools/exception/add-comment.js +3 -2
  72. package/dist/tools/exception/add-comment.js.map +1 -1
  73. package/dist/tools/exception/adjust-entry.js +5 -5
  74. package/dist/tools/exception/adjust-entry.js.map +1 -1
  75. package/dist/tools/exception/bulk-assign.js +3 -2
  76. package/dist/tools/exception/bulk-assign.js.map +1 -1
  77. package/dist/tools/exception/bulk-dispatch.js +12 -4
  78. package/dist/tools/exception/bulk-dispatch.js.map +1 -1
  79. package/dist/tools/exception/bulk-resolve.js +3 -2
  80. package/dist/tools/exception/bulk-resolve.js.map +1 -1
  81. package/dist/tools/exception/dispatch.js +13 -5
  82. package/dist/tools/exception/dispatch.js.map +1 -1
  83. package/dist/tools/exception/force-match.js +3 -2
  84. package/dist/tools/exception/force-match.js.map +1 -1
  85. package/dist/tools/exception/history.js +8 -24
  86. package/dist/tools/exception/history.js.map +1 -1
  87. package/dist/tools/exception/index.js +88 -18
  88. package/dist/tools/exception/index.js.map +1 -1
  89. package/dist/tools/exception/list.js +14 -57
  90. package/dist/tools/exception/list.js.map +1 -1
  91. package/dist/tools/exception/open-dispute.js +3 -2
  92. package/dist/tools/exception/open-dispute.js.map +1 -1
  93. package/dist/tools/exception/shared.js +10 -46
  94. package/dist/tools/exception/shared.js.map +1 -1
  95. package/dist/tools/fee-rule/create.js +5 -5
  96. package/dist/tools/fee-rule/create.js.map +1 -1
  97. package/dist/tools/fee-rule/index.js +50 -8
  98. package/dist/tools/fee-rule/index.js.map +1 -1
  99. package/dist/tools/fee-rule/list.js +9 -29
  100. package/dist/tools/fee-rule/list.js.map +1 -1
  101. package/dist/tools/fee-rule/shared.js +5 -47
  102. package/dist/tools/fee-rule/shared.js.map +1 -1
  103. package/dist/tools/fee-rule/update.js +5 -5
  104. package/dist/tools/fee-rule/update.js.map +1 -1
  105. package/dist/tools/fee-schedule/create.js +8 -3
  106. package/dist/tools/fee-schedule/create.js.map +1 -1
  107. package/dist/tools/fee-schedule/index.js +62 -11
  108. package/dist/tools/fee-schedule/index.js.map +1 -1
  109. package/dist/tools/fee-schedule/list.js +8 -24
  110. package/dist/tools/fee-schedule/list.js.map +1 -1
  111. package/dist/tools/fee-schedule/shared.js +5 -44
  112. package/dist/tools/fee-schedule/shared.js.map +1 -1
  113. package/dist/tools/fee-schedule/simulate.js +5 -5
  114. package/dist/tools/fee-schedule/simulate.js.map +1 -1
  115. package/dist/tools/fee-schedule/update.js +5 -5
  116. package/dist/tools/fee-schedule/update.js.map +1 -1
  117. package/dist/tools/field-map/create.js +3 -2
  118. package/dist/tools/field-map/create.js.map +1 -1
  119. package/dist/tools/field-map/index.js +65 -11
  120. package/dist/tools/field-map/index.js.map +1 -1
  121. package/dist/tools/field-map/list.js +9 -29
  122. package/dist/tools/field-map/list.js.map +1 -1
  123. package/dist/tools/field-map/shared.js +6 -42
  124. package/dist/tools/field-map/shared.js.map +1 -1
  125. package/dist/tools/field-map/update.js +3 -2
  126. package/dist/tools/field-map/update.js.map +1 -1
  127. package/dist/tools/generic/invoke.js +16 -39
  128. package/dist/tools/generic/invoke.js.map +1 -1
  129. package/dist/tools/ingestion/index.js +100 -12
  130. package/dist/tools/ingestion/index.js.map +1 -1
  131. package/dist/tools/ingestion/job-transactions-list.js +10 -40
  132. package/dist/tools/ingestion/job-transactions-list.js.map +1 -1
  133. package/dist/tools/ingestion/jobs-list.js +9 -35
  134. package/dist/tools/ingestion/jobs-list.js.map +1 -1
  135. package/dist/tools/ingestion/shared.js +4 -41
  136. package/dist/tools/ingestion/shared.js.map +1 -1
  137. package/dist/tools/ingestion/transactions-search.js +9 -44
  138. package/dist/tools/ingestion/transactions-search.js.map +1 -1
  139. package/dist/tools/ingestion/upload.js +3 -2
  140. package/dist/tools/ingestion/upload.js.map +1 -1
  141. package/dist/tools/input-fields.js +51 -0
  142. package/dist/tools/input-fields.js.map +1 -0
  143. package/dist/tools/match-rule/index.js +130 -13
  144. package/dist/tools/match-rule/index.js.map +1 -1
  145. package/dist/tools/match-rule/list.js +9 -33
  146. package/dist/tools/match-rule/list.js.map +1 -1
  147. package/dist/tools/match-rule/shared.js +16 -46
  148. package/dist/tools/match-rule/shared.js.map +1 -1
  149. package/dist/tools/match-rule/update.js +7 -11
  150. package/dist/tools/match-rule/update.js.map +1 -1
  151. package/dist/tools/matching/get.js +5 -5
  152. package/dist/tools/matching/get.js.map +1 -1
  153. package/dist/tools/matching/groups.js +6 -14
  154. package/dist/tools/matching/groups.js.map +1 -1
  155. package/dist/tools/matching/index.js +77 -5
  156. package/dist/tools/matching/index.js.map +1 -1
  157. package/dist/tools/matching/list.js +9 -32
  158. package/dist/tools/matching/list.js.map +1 -1
  159. package/dist/tools/matching/shared.js +5 -46
  160. package/dist/tools/matching/shared.js.map +1 -1
  161. package/dist/tools/query-handler.js +9 -0
  162. package/dist/tools/query-handler.js.map +1 -0
  163. package/dist/tools/report/index.js +260 -30
  164. package/dist/tools/report/index.js.map +1 -1
  165. package/dist/tools/report/shared.js +24 -98
  166. package/dist/tools/report/shared.js.map +1 -1
  167. package/dist/tools/request-fields.js +17 -0
  168. package/dist/tools/request-fields.js.map +1 -0
  169. package/dist/tools/shared-dispatch.js +38 -0
  170. package/dist/tools/shared-dispatch.js.map +1 -0
  171. package/dist/tools/source/create.js +146 -23
  172. package/dist/tools/source/create.js.map +1 -1
  173. package/dist/tools/source/index.js +101 -13
  174. package/dist/tools/source/index.js.map +1 -1
  175. package/dist/tools/source/list.js +9 -32
  176. package/dist/tools/source/list.js.map +1 -1
  177. package/dist/tools/source/shared.js +5 -42
  178. package/dist/tools/source/shared.js.map +1 -1
  179. package/dist/tools/source/update.js +16 -33
  180. package/dist/tools/source/update.js.map +1 -1
  181. package/dist/tools/workspace/usage.js +27 -41
  182. package/dist/tools/workspace/usage.js.map +1 -1
  183. package/package.json +4 -4
  184. package/dist/tools/context/archive.js +0 -37
  185. package/dist/tools/context/archive.js.map +0 -1
  186. package/dist/tools/context/get.js +0 -31
  187. package/dist/tools/context/get.js.map +0 -1
  188. package/dist/tools/context/next-step.js +0 -99
  189. package/dist/tools/context/next-step.js.map +0 -1
  190. package/dist/tools/context/restore.js +0 -34
  191. package/dist/tools/context/restore.js.map +0 -1
  192. package/dist/tools/dashboard/aggregates.js +0 -37
  193. package/dist/tools/dashboard/aggregates.js.map +0 -1
  194. package/dist/tools/dashboard/cash-impact.js +0 -37
  195. package/dist/tools/dashboard/cash-impact.js.map +0 -1
  196. package/dist/tools/dashboard/match-rate.js +0 -37
  197. package/dist/tools/dashboard/match-rate.js.map +0 -1
  198. package/dist/tools/dashboard/metrics.js +0 -37
  199. package/dist/tools/dashboard/metrics.js.map +0 -1
  200. package/dist/tools/dashboard/sla.js +0 -34
  201. package/dist/tools/dashboard/sla.js.map +0 -1
  202. package/dist/tools/dashboard/source-breakdown.js +0 -37
  203. package/dist/tools/dashboard/source-breakdown.js.map +0 -1
  204. package/dist/tools/dashboard/volume.js +0 -37
  205. package/dist/tools/dashboard/volume.js.map +0 -1
  206. package/dist/tools/dispute/get.js +0 -27
  207. package/dist/tools/dispute/get.js.map +0 -1
  208. package/dist/tools/exception/delete-comment.js +0 -40
  209. package/dist/tools/exception/delete-comment.js.map +0 -1
  210. package/dist/tools/exception/get.js +0 -34
  211. package/dist/tools/exception/get.js.map +0 -1
  212. package/dist/tools/exception/list-comments.js +0 -35
  213. package/dist/tools/exception/list-comments.js.map +0 -1
  214. package/dist/tools/fee-rule/delete.js +0 -27
  215. package/dist/tools/fee-rule/delete.js.map +0 -1
  216. package/dist/tools/fee-rule/get.js +0 -27
  217. package/dist/tools/fee-rule/get.js.map +0 -1
  218. package/dist/tools/fee-schedule/delete.js +0 -32
  219. package/dist/tools/fee-schedule/delete.js.map +0 -1
  220. package/dist/tools/fee-schedule/get.js +0 -30
  221. package/dist/tools/fee-schedule/get.js.map +0 -1
  222. package/dist/tools/field-map/delete.js +0 -37
  223. package/dist/tools/field-map/delete.js.map +0 -1
  224. package/dist/tools/field-map/get.js +0 -43
  225. package/dist/tools/field-map/get.js.map +0 -1
  226. package/dist/tools/ingestion/job-errors-list.js +0 -45
  227. package/dist/tools/ingestion/job-errors-list.js.map +0 -1
  228. package/dist/tools/ingestion/job-get.js +0 -42
  229. package/dist/tools/ingestion/job-get.js.map +0 -1
  230. package/dist/tools/ingestion/transaction-ignore.js +0 -51
  231. package/dist/tools/ingestion/transaction-ignore.js.map +0 -1
  232. package/dist/tools/match-rule/create.js +0 -67
  233. package/dist/tools/match-rule/create.js.map +0 -1
  234. package/dist/tools/match-rule/delete.js +0 -35
  235. package/dist/tools/match-rule/delete.js.map +0 -1
  236. package/dist/tools/match-rule/get.js +0 -32
  237. package/dist/tools/match-rule/get.js.map +0 -1
  238. package/dist/tools/match-rule/reorder.js +0 -45
  239. package/dist/tools/match-rule/reorder.js.map +0 -1
  240. package/dist/tools/matching/start.js +0 -81
  241. package/dist/tools/matching/start.js.map +0 -1
  242. package/dist/tools/report/count-exceptions.js +0 -46
  243. package/dist/tools/report/count-exceptions.js.map +0 -1
  244. package/dist/tools/report/count-matched.js +0 -47
  245. package/dist/tools/report/count-matched.js.map +0 -1
  246. package/dist/tools/report/count-transactions.js +0 -45
  247. package/dist/tools/report/count-transactions.js.map +0 -1
  248. package/dist/tools/report/count-unmatched.js +0 -45
  249. package/dist/tools/report/count-unmatched.js.map +0 -1
  250. package/dist/tools/report/export-exceptions.js +0 -48
  251. package/dist/tools/report/export-exceptions.js.map +0 -1
  252. package/dist/tools/report/export-matched.js +0 -49
  253. package/dist/tools/report/export-matched.js.map +0 -1
  254. package/dist/tools/report/export-summary.js +0 -49
  255. package/dist/tools/report/export-summary.js.map +0 -1
  256. package/dist/tools/report/export-unmatched.js +0 -49
  257. package/dist/tools/report/export-unmatched.js.map +0 -1
  258. package/dist/tools/report/export-variance.js +0 -48
  259. package/dist/tools/report/export-variance.js.map +0 -1
  260. package/dist/tools/report/matched.js +0 -48
  261. package/dist/tools/report/matched.js.map +0 -1
  262. package/dist/tools/report/summary.js +0 -43
  263. package/dist/tools/report/summary.js.map +0 -1
  264. package/dist/tools/report/unmatched.js +0 -48
  265. package/dist/tools/report/unmatched.js.map +0 -1
  266. package/dist/tools/report/variance.js +0 -48
  267. package/dist/tools/report/variance.js.map +0 -1
  268. package/dist/tools/source/archive.js +0 -46
  269. package/dist/tools/source/archive.js.map +0 -1
  270. package/dist/tools/source/get.js +0 -57
  271. package/dist/tools/source/get.js.map +0 -1
  272. package/dist/tools/source/restore.js +0 -39
  273. package/dist/tools/source/restore.js.map +0 -1
@@ -184,6 +184,9 @@ components:
184
184
  type: string
185
185
  direction:
186
186
  description: "Direction of the entry: DEBIT explains a shortfall (moves the outstanding variance up, toward zero), CREDIT explains a surplus (moves it down)"
187
+ enum:
188
+ - DEBIT
189
+ - CREDIT
187
190
  examples:
188
191
  - DEBIT
189
192
  type: string
@@ -209,6 +212,12 @@ components:
209
212
  type: string
210
213
  type:
211
214
  description: "Adjustment type: BANK_FEE (bank charge), FX_DIFFERENCE (currency conversion variance), ROUNDING (minor-unit rounding), WRITE_OFF (uncollectible balance), or MISCELLANEOUS (other)"
215
+ enum:
216
+ - BANK_FEE
217
+ - FX_DIFFERENCE
218
+ - ROUNDING
219
+ - WRITE_OFF
220
+ - MISCELLANEOUS
212
221
  examples:
213
222
  - BANK_FEE
214
223
  type: string
@@ -230,6 +239,33 @@ components:
230
239
  - createdAt
231
240
  - updatedAt
232
241
  type: object
242
+ AdminAssignPlanInputBody:
243
+ additionalProperties: false
244
+ properties:
245
+ plan:
246
+ description: "The plan code to assign. ONLY \"enterprise\" is accepted: self-serve plans are bought through checkout and converged from the live subscription's price, so assigning one here would be a payment-processor bypass the next processor delivery silently reverts. Any other code is refused with 409."
247
+ maxLength: 64
248
+ type: string
249
+ required:
250
+ - plan
251
+ type: object
252
+ AdminAssignPlanResult:
253
+ additionalProperties: false
254
+ properties:
255
+ billingStatus:
256
+ description: The commercial standing the workspace now holds. An enterprise contract is in good standing the moment it is signed, so this is always "active".
257
+ type: string
258
+ plan:
259
+ description: The plan the workspace now holds.
260
+ type: string
261
+ slug:
262
+ description: The workspace assigned.
263
+ type: string
264
+ required:
265
+ - slug
266
+ - plan
267
+ - billingStatus
268
+ type: object
233
269
  AdminWorkspaceBilling:
234
270
  additionalProperties: false
235
271
  properties:
@@ -321,10 +357,15 @@ components:
321
357
  additionalProperties: false
322
358
  properties:
323
359
  accountRef:
324
- description: Stored opaque vendor account reference (Pluggy itemId, Belvo link id)
360
+ description: Stored opaque vendor account reference (Pluggy itemId, Belvo link id); empty while the connection is awaiting consent
325
361
  examples:
326
362
  - a1b2c3d4-5678-90ab-cdef-1234567890ab
327
363
  type: string
364
+ awaitingConsent:
365
+ description: Whether the connection is still awaiting the end customer's vendor consent (no vendor item/link bound yet)
366
+ examples:
367
+ - false
368
+ type: boolean
328
369
  baseUrl:
329
370
  description: Stored vendor API base URL
330
371
  examples:
@@ -342,7 +383,7 @@ components:
342
383
  - a1b2c3d4-5678-90ab-cdef-1234567890ab
343
384
  type: string
344
385
  testable:
345
- description: Whether Matcher can run a connectivity test for this connection's aggregator vendor
386
+ description: Whether Matcher can run a connectivity test for this connection right now (its vendor has a test path AND it is bound to a vendor item/link)
346
387
  examples:
347
388
  - true
348
389
  type: boolean
@@ -361,6 +402,7 @@ components:
361
402
  - baseUrl
362
403
  - accountRef
363
404
  - testable
405
+ - awaitingConsent
364
406
  type: object
365
407
  AggregatorConnectionListResponse:
366
408
  additionalProperties: false
@@ -400,10 +442,9 @@ components:
400
442
  additionalProperties: false
401
443
  properties:
402
444
  accountRef:
403
- description: Opaque vendor account reference (Pluggy itemId, Belvo link id) the webhook pull threads onto its request
445
+ description: Opaque vendor account reference (Pluggy itemId, Belvo link id) the webhook pull threads onto its request. Omit to create a connection awaiting consent — the connect flow binds it after the end customer authorizes.
404
446
  examples:
405
447
  - a1b2c3d4-5678-90ab-cdef-1234567890ab
406
- minLength: 1
407
448
  type: string
408
449
  baseUrl:
409
450
  description: Vendor API base URL, stored as the connection host
@@ -438,7 +479,6 @@ components:
438
479
  - vendor
439
480
  - configName
440
481
  - baseUrl
441
- - accountRef
442
482
  - clientId
443
483
  - secret
444
484
  type: object
@@ -446,10 +486,15 @@ components:
446
486
  additionalProperties: false
447
487
  properties:
448
488
  accountRef:
449
- description: Stored opaque vendor account reference (Pluggy itemId, Belvo link id)
489
+ description: Stored opaque vendor account reference (Pluggy itemId, Belvo link id); empty while the connection is awaiting consent
450
490
  examples:
451
491
  - a1b2c3d4-5678-90ab-cdef-1234567890ab
452
492
  type: string
493
+ awaitingConsent:
494
+ description: Whether the connection is still awaiting the end customer's vendor consent (no vendor item/link bound yet)
495
+ examples:
496
+ - false
497
+ type: boolean
453
498
  baseUrl:
454
499
  description: Stored vendor API base URL
455
500
  examples:
@@ -474,6 +519,52 @@ components:
474
519
  - configName
475
520
  - baseUrl
476
521
  - accountRef
522
+ - awaitingConsent
523
+ type: object
524
+ AggregatorConsentTokenResponse:
525
+ additionalProperties: false
526
+ properties:
527
+ accountRef:
528
+ description: Vendor item/link id this token was scoped to (the stored binding); empty on a first consent. Pass it to the vendor widget's update mode alongside the token — do not substitute a locally cached value.
529
+ examples:
530
+ - a1b2c3d4-5678-90ab-cdef-1234567890ab
531
+ type: string
532
+ configName:
533
+ description: Config name of the connection the token was minted for
534
+ examples:
535
+ - pluggy-main
536
+ type: string
537
+ expiresAt:
538
+ description: UTC instant after which the vendor rejects this consent token
539
+ examples:
540
+ - "2026-08-23T12:30:00Z"
541
+ format: date-time
542
+ type: string
543
+ reconsent:
544
+ description: Whether the token re-authorizes the connection's existing vendor item/link (true) or will create a new one (false)
545
+ examples:
546
+ - false
547
+ type: boolean
548
+ token:
549
+ description: Short-lived, widget-ready consent token. Returned exactly once and never stored — pass it to the vendor widget and discard it.
550
+ examples:
551
+ - eyJhbGciOi...
552
+ type: string
553
+ vendor:
554
+ description: Aggregator vendor the consent token was minted against
555
+ enum:
556
+ - pluggy
557
+ - belvo
558
+ examples:
559
+ - pluggy
560
+ type: string
561
+ required:
562
+ - vendor
563
+ - configName
564
+ - token
565
+ - expiresAt
566
+ - reconsent
567
+ - accountRef
477
568
  type: object
478
569
  ApproveExtractionResponse:
479
570
  additionalProperties: false
@@ -638,6 +729,12 @@ components:
638
729
  - 0
639
730
  format: int64
640
731
  type: integer
732
+ fromSeq:
733
+ description: "Effective verification floor: the first tenant_seq eligible for inspection (1 when fromSeq was omitted). Resume a truncated run at fromSeq + verifiedCount"
734
+ examples:
735
+ - 1
736
+ format: int64
737
+ type: integer
641
738
  intact:
642
739
  description: True when every inspected record links to the previous one and matches its stored hash
643
740
  examples:
@@ -656,6 +753,7 @@ components:
656
753
  type: integer
657
754
  required:
658
755
  - intact
756
+ - fromSeq
659
757
  - verifiedCount
660
758
  - truncated
661
759
  type: object
@@ -937,7 +1035,15 @@ components:
937
1035
  additionalProperties: false
938
1036
  properties:
939
1037
  canonicalKey:
940
- description: Canonical field-map key (e.g. amount, external_id, currency, date)
1038
+ description: Canonical field-map key. The closed vocabulary is the required keys (external_id, amount, currency, date) plus the optional ones (description, fee_amount, fee_currency); the extractor drops any key outside it before a candidate is persisted
1039
+ enum:
1040
+ - external_id
1041
+ - amount
1042
+ - currency
1043
+ - date
1044
+ - description
1045
+ - fee_amount
1046
+ - fee_currency
941
1047
  examples:
942
1048
  - amount
943
1049
  type: string
@@ -1007,6 +1113,11 @@ components:
1007
1113
  type: string
1008
1114
  ruleType:
1009
1115
  description: Strategy of the rule that produced the best score
1116
+ enum:
1117
+ - EXACT
1118
+ - TOLERANCE
1119
+ - DATE_LAG
1120
+ - FUZZY
1010
1121
  examples:
1011
1122
  - EXACT
1012
1123
  type: string
@@ -1065,6 +1176,9 @@ components:
1065
1176
  - "null"
1066
1177
  source:
1067
1178
  description: "Extraction lane that produced this candidate: text_layer (PDF text, higher trust) or vision (OCR/vision model, lower trust)"
1179
+ enum:
1180
+ - text_layer
1181
+ - vision
1068
1182
  examples:
1069
1183
  - text_layer
1070
1184
  type: string
@@ -1779,6 +1893,14 @@ components:
1779
1893
  type:
1780
1894
  - array
1781
1895
  - "null"
1896
+ signConvention:
1897
+ description: "How this context's data carries sign. SAME: a payment carries the same sign as what it settles, so a negative amount is a reversal. OPPOSITE: a payment carries the opposite sign of the invoice it settles. Defaults to SAME."
1898
+ enum:
1899
+ - SAME
1900
+ - OPPOSITE
1901
+ examples:
1902
+ - SAME
1903
+ type: string
1782
1904
  sources:
1783
1905
  description: Sources to create inline with the context.
1784
1906
  items:
@@ -1806,7 +1928,91 @@ components:
1806
1928
  properties:
1807
1929
  config:
1808
1930
  additionalProperties: {}
1809
- description: "Source-specific configuration object (connection and parsing settings). Optional; defaults to an empty object when omitted. Reserved key duplicate_key: the ordered list of mapped fields that make two rows the same row — any of external_id, amount, currency, date, description, fee_amount, fee_currency. Omit it and rows are deduplicated on external_id alone. A field this source's field map does not fill is refused, because a key over a field that is always empty makes every row a duplicate of every other. A source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate key of its own: the aggregator retracts a movement by naming its external id, so that id has to stay this source's row identity. A config holding both is refused in either direction — drop duplicate_key from a bound source, or disconnect the aggregator connection first. Reserved read-only key duplicate_key_changed_at: the RFC 3339 moment duplicate-key detection last changed meaning on this source, set by the server; a value sent by a client is discarded. It moves for either change that re-keys future rows — editing duplicate_key, or the field map remapping the column a declared field reads (a source keyed on description whose description column moves derives a different key for the same movement). Reserved key duplicate_policy: what happens to a row repeating the duplicate key — FLAG_AS_EXCEPTION (the default: the repeat is kept out of the import and raised as a duplicate exception on the row it repeated), KEEP_FIRST (the repeat is dropped and nothing is raised), or REJECT (the repeat is counted as an import error). Changing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under."
1931
+ description: "Source-specific configuration object. Cross-key rules the schema cannot express: a duplicate_key component this source's field map does not fill is refused, because a key over an always-empty field makes every row a duplicate of every other; a source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate_key of its own, and a config holding both is refused in either direction; and editing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under, so a duplicate straddling the change is knowingly not detected."
1932
+ properties:
1933
+ blank_external_id:
1934
+ description: What happens to a row whose mapped external id is blank. REJECT (the default when the key is absent) fails the row. NEEDS_REVIEW imports it under a synthetic reference with status PENDING_REVIEW, so a blank reference becomes a reviewable import instead of an import failure.
1935
+ enum:
1936
+ - REJECT
1937
+ - NEEDS_REVIEW
1938
+ type: string
1939
+ camt053:
1940
+ additionalProperties: false
1941
+ description: How this source's camt.053 files map onto the canonical fields. Every other field is fixed by ISO 20022 itself. An absent object, or an absent sub-key, keeps the ISO defaults (booking, ntry_ref).
1942
+ properties:
1943
+ date_basis:
1944
+ description: "Entry date element: booking is BookgDt/Dt, valuation is ValDt/Dt. Default booking."
1945
+ enum:
1946
+ - booking
1947
+ - valuation
1948
+ type: string
1949
+ external_id_source:
1950
+ description: "Entry reference element: ntry_ref is NtryRef, end_to_end_id is NtryDtls/TxDtls/Refs/EndToEndId, tx_id is NtryDtls/TxDtls/Refs/TxId. Default ntry_ref."
1951
+ enum:
1952
+ - ntry_ref
1953
+ - end_to_end_id
1954
+ - tx_id
1955
+ type: string
1956
+ type: object
1957
+ dialect:
1958
+ additionalProperties: false
1959
+ description: How this source's delimited files are encoded and formatted. Declaration-driven only — there is no auto-detection. An absent object, or an absent sub-key, keeps the defaults (utf-8, comma, dot, iso).
1960
+ properties:
1961
+ date_style:
1962
+ enum:
1963
+ - iso
1964
+ - iso_offset
1965
+ - dmy
1966
+ - mdy
1967
+ type: string
1968
+ decimal_style:
1969
+ description: dot is 1234.56, comma is 1.234,56.
1970
+ enum:
1971
+ - dot
1972
+ - comma
1973
+ type: string
1974
+ delimiter:
1975
+ enum:
1976
+ - comma
1977
+ - semicolon
1978
+ - tab
1979
+ - pipe
1980
+ type: string
1981
+ encoding:
1982
+ enum:
1983
+ - utf-8
1984
+ - utf-8-sig
1985
+ - cp1252
1986
+ - iso-8859-1
1987
+ type: string
1988
+ type: object
1989
+ duplicate_key:
1990
+ description: The ordered list of mapped fields that make two rows the same row. Absent means external_id alone. On a source bound to an aggregator connection the aggregator retracts a movement by naming its external id, so that id has to stay the row identity.
1991
+ items:
1992
+ enum:
1993
+ - external_id
1994
+ - amount
1995
+ - currency
1996
+ - date
1997
+ - description
1998
+ - fee_amount
1999
+ - fee_currency
2000
+ type: string
2001
+ minItems: 1
2002
+ type: array
2003
+ uniqueItems: true
2004
+ duplicate_policy:
2005
+ description: What happens to a row that repeats this source's duplicate key. FLAG_AS_EXCEPTION (the default when the key is absent) keeps the repeat out of the import and raises a duplicate exception on the row it repeated. KEEP_FIRST drops the repeat and raises nothing, so a collision leaves no trace anyone can act on. REJECT counts the repeat as an import error.
2006
+ enum:
2007
+ - FLAG_AS_EXCEPTION
2008
+ - KEEP_FIRST
2009
+ - REJECT
2010
+ type: string
2011
+ fail_on_error_rate_percent:
2012
+ description: "Fail the whole import when the percentage of failed rows exceeds this whole number. Absent means never auto-fail. The ceiling is 99, not 100: the comparison is strict, so 100 could never fire."
2013
+ maximum: 99
2014
+ minimum: 1
2015
+ type: integer
1810
2016
  type: object
1811
2017
  mapping:
1812
2018
  additionalProperties: {}
@@ -1976,10 +2182,10 @@ components:
1976
2182
  type: integer
1977
2183
  structure:
1978
2184
  additionalProperties: {}
1979
- description: "Type-specific structure. FLAT: {\"amount\":\"1.50\"}. PERCENTAGE: {\"rate\":\"0.029\"} where rate is a 0..1 fraction of the base amount (0.029 means 2.9%), not a percent value. TIERED: {\"tiers\":[{\"rate\":\"0.01\",\"upTo\":\"1000\"},...]} with the same 0..1 fraction semantics per tier rate. EXPRESSION: {\"expression\":\"gross - desconto + multa + juros_dia * days_late(due_date, pay_date)\"} a formula over metadata fields (+ - * /, parentheses, and the functions days_late, days_between, max, min, abs, clamp)."
2185
+ description: "Type-specific structure. FLAT: {\"amount\":\"1.50\"}. PERCENTAGE: {\"rate\":\"0.029\"} where rate is a 0..1 fraction of the base amount (0.029 means 2.9%), not a percent value. TIERED: {\"tiers\":[{\"rate\":\"0.01\",\"upTo\":\"1000\"},...]} with the same 0..1 fraction semantics per tier rate. EXPRESSION: {\"expression\":\"gross - desconto + multa + juros_dia * days_late(due_date, pay_date)\"} a formula over metadata fields (+ - * /, parentheses, and the functions days_late, days_between, max, min, abs, clamp). A formula that is only the base amount times numeric literals is a percentage rate and is bounded 0..1: gross * 0.029 is 2.9%, gross * 2.9 is refused; any other formula is unbounded."
1980
2186
  type: object
1981
2187
  structureType:
1982
- description: Shape of the fee structure. FLAT is a fixed amount; PERCENTAGE is a rate of the base; TIERED applies different rates per amount tier; EXPRESSION computes the fee from a bounded arithmetic formula over transaction metadata.
2188
+ description: Shape of the fee structure; the structure field documents the object each one takes.
1983
2189
  enum:
1984
2190
  - FLAT
1985
2191
  - PERCENTAGE
@@ -2236,7 +2442,91 @@ components:
2236
2442
  properties:
2237
2443
  config:
2238
2444
  additionalProperties: {}
2239
- description: "Source-specific configuration object (connection and parsing settings). Optional; defaults to an empty object when omitted. Reserved key duplicate_key: the ordered list of mapped fields that make two rows the same row — any of external_id, amount, currency, date, description, fee_amount, fee_currency. Omit it and rows are deduplicated on external_id alone. A field this source's field map does not fill is refused, because a key over a field that is always empty makes every row a duplicate of every other. A source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate key of its own: the aggregator retracts a movement by naming its external id, so that id has to stay this source's row identity. A config holding both is refused in either direction — drop duplicate_key from a bound source, or disconnect the aggregator connection first. Reserved read-only key duplicate_key_changed_at: the RFC 3339 moment duplicate-key detection last changed meaning on this source, set by the server; a value sent by a client is discarded. It moves for either change that re-keys future rows — editing duplicate_key, or the field map remapping the column a declared field reads (a source keyed on description whose description column moves derives a different key for the same movement). Reserved key duplicate_policy: what happens to a row repeating the duplicate key — FLAG_AS_EXCEPTION (the default: the repeat is kept out of the import and raised as a duplicate exception on the row it repeated), KEEP_FIRST (the repeat is dropped and nothing is raised), or REJECT (the repeat is counted as an import error). Changing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under."
2445
+ description: "Source-specific configuration object. Cross-key rules the schema cannot express: a duplicate_key component this source's field map does not fill is refused, because a key over an always-empty field makes every row a duplicate of every other; a source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate_key of its own, and a config holding both is refused in either direction; and editing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under, so a duplicate straddling the change is knowingly not detected."
2446
+ properties:
2447
+ blank_external_id:
2448
+ description: What happens to a row whose mapped external id is blank. REJECT (the default when the key is absent) fails the row. NEEDS_REVIEW imports it under a synthetic reference with status PENDING_REVIEW, so a blank reference becomes a reviewable import instead of an import failure.
2449
+ enum:
2450
+ - REJECT
2451
+ - NEEDS_REVIEW
2452
+ type: string
2453
+ camt053:
2454
+ additionalProperties: false
2455
+ description: How this source's camt.053 files map onto the canonical fields. Every other field is fixed by ISO 20022 itself. An absent object, or an absent sub-key, keeps the ISO defaults (booking, ntry_ref).
2456
+ properties:
2457
+ date_basis:
2458
+ description: "Entry date element: booking is BookgDt/Dt, valuation is ValDt/Dt. Default booking."
2459
+ enum:
2460
+ - booking
2461
+ - valuation
2462
+ type: string
2463
+ external_id_source:
2464
+ description: "Entry reference element: ntry_ref is NtryRef, end_to_end_id is NtryDtls/TxDtls/Refs/EndToEndId, tx_id is NtryDtls/TxDtls/Refs/TxId. Default ntry_ref."
2465
+ enum:
2466
+ - ntry_ref
2467
+ - end_to_end_id
2468
+ - tx_id
2469
+ type: string
2470
+ type: object
2471
+ dialect:
2472
+ additionalProperties: false
2473
+ description: How this source's delimited files are encoded and formatted. Declaration-driven only — there is no auto-detection. An absent object, or an absent sub-key, keeps the defaults (utf-8, comma, dot, iso).
2474
+ properties:
2475
+ date_style:
2476
+ enum:
2477
+ - iso
2478
+ - iso_offset
2479
+ - dmy
2480
+ - mdy
2481
+ type: string
2482
+ decimal_style:
2483
+ description: dot is 1234.56, comma is 1.234,56.
2484
+ enum:
2485
+ - dot
2486
+ - comma
2487
+ type: string
2488
+ delimiter:
2489
+ enum:
2490
+ - comma
2491
+ - semicolon
2492
+ - tab
2493
+ - pipe
2494
+ type: string
2495
+ encoding:
2496
+ enum:
2497
+ - utf-8
2498
+ - utf-8-sig
2499
+ - cp1252
2500
+ - iso-8859-1
2501
+ type: string
2502
+ type: object
2503
+ duplicate_key:
2504
+ description: The ordered list of mapped fields that make two rows the same row. Absent means external_id alone. On a source bound to an aggregator connection the aggregator retracts a movement by naming its external id, so that id has to stay the row identity.
2505
+ items:
2506
+ enum:
2507
+ - external_id
2508
+ - amount
2509
+ - currency
2510
+ - date
2511
+ - description
2512
+ - fee_amount
2513
+ - fee_currency
2514
+ type: string
2515
+ minItems: 1
2516
+ type: array
2517
+ uniqueItems: true
2518
+ duplicate_policy:
2519
+ description: What happens to a row that repeats this source's duplicate key. FLAG_AS_EXCEPTION (the default when the key is absent) keeps the repeat out of the import and raises a duplicate exception on the row it repeated. KEEP_FIRST drops the repeat and raises nothing, so a collision leaves no trace anyone can act on. REJECT counts the repeat as an import error.
2520
+ enum:
2521
+ - FLAG_AS_EXCEPTION
2522
+ - KEEP_FIRST
2523
+ - REJECT
2524
+ type: string
2525
+ fail_on_error_rate_percent:
2526
+ description: "Fail the whole import when the percentage of failed rows exceeds this whole number. Absent means never auto-fail. The ceiling is 99, not 100: the comparison is strict, so 100 could never fire."
2527
+ maximum: 99
2528
+ minimum: 1
2529
+ type: integer
2240
2530
  type: object
2241
2531
  name:
2242
2532
  description: Human-readable name of the source.
@@ -2432,6 +2722,11 @@ components:
2432
2722
  sla:
2433
2723
  $ref: "#/components/schemas/SLAStatsResponse"
2434
2724
  description: SLA compliance statistics for the window.
2725
+ unmatchedByCurrency:
2726
+ description: Unreconciled exposure split by currency; the amounts sum to volume.unmatchedAmount. Empty when no transaction in the window is UNMATCHED or PENDING_REVIEW; always an array, never null. volume.unmatchedAmount is the engine's arithmetic sum of those amounts across currencies, so it is a meaningful money figure only when this split carries a single currency. Clients must not render it as money when the split names more than one currency.
2727
+ items:
2728
+ $ref: "#/components/schemas/CurrencyExposureResponse"
2729
+ type: array
2435
2730
  updatedAt:
2436
2731
  description: Timestamp when these aggregates were computed (RFC 3339, UTC).
2437
2732
  examples:
@@ -2445,6 +2740,7 @@ components:
2445
2740
  - volume
2446
2741
  - matchRate
2447
2742
  - sla
2743
+ - unmatchedByCurrency
2448
2744
  - updatedAt
2449
2745
  type: object
2450
2746
  Detail:
@@ -2500,21 +2796,39 @@ components:
2500
2796
  properties:
2501
2797
  dateStyle:
2502
2798
  description: "Detected date convention: iso (YYYY-MM-DD), iso_offset (RFC 3339 with offset), dmy (DD/MM/YYYY), or mdy (MM/DD/YYYY)"
2799
+ enum:
2800
+ - iso
2801
+ - iso_offset
2802
+ - dmy
2803
+ - mdy
2503
2804
  examples:
2504
2805
  - iso
2505
2806
  type: string
2506
2807
  decimalStyle:
2507
2808
  description: "Detected amount decimal convention: dot (1234.56) or comma (1234,56)"
2809
+ enum:
2810
+ - dot
2811
+ - comma
2508
2812
  examples:
2509
2813
  - comma
2510
2814
  type: string
2511
2815
  delimiter:
2512
2816
  description: "Detected CSV field separator: comma, semicolon, tab, or pipe"
2817
+ enum:
2818
+ - comma
2819
+ - semicolon
2820
+ - tab
2821
+ - pipe
2513
2822
  examples:
2514
2823
  - semicolon
2515
2824
  type: string
2516
2825
  encoding:
2517
2826
  description: "Detected file character encoding: utf-8, utf-8-sig (UTF-8 with BOM), cp1252 (Windows Latin-1), or iso-8859-1"
2827
+ enum:
2828
+ - utf-8
2829
+ - utf-8-sig
2830
+ - cp1252
2831
+ - iso-8859-1
2518
2832
  examples:
2519
2833
  - utf-8
2520
2834
  type: string
@@ -2606,11 +2920,12 @@ components:
2606
2920
  additionalProperties: false
2607
2921
  properties:
2608
2922
  category:
2609
- description: "Dispute category: BANK_FEE_ERROR (incorrect fee), UNRECOGNIZED_CHARGE, DUPLICATE_TRANSACTION, or OTHER"
2923
+ description: "Dispute category: BANK_FEE_ERROR (incorrect fee), UNRECOGNIZED_CHARGE, DUPLICATE_TRANSACTION, AMOUNT_MISMATCH, or OTHER"
2610
2924
  enum:
2611
2925
  - BANK_FEE_ERROR
2612
2926
  - UNRECOGNIZED_CHARGE
2613
2927
  - DUPLICATE_TRANSACTION
2928
+ - AMOUNT_MISMATCH
2614
2929
  - OTHER
2615
2930
  examples:
2616
2931
  - BANK_FEE_ERROR
@@ -2770,7 +3085,7 @@ components:
2770
3085
  additionalProperties: false
2771
3086
  properties:
2772
3087
  amount:
2773
- description: "Enrichment: the exception transaction's amount as a decimal string in the transaction's currency. Present on list rows whose transaction still exists; absent on the get-by-id/resolution paths and when the transaction was deleted."
3088
+ description: "Enrichment: the exception transaction's amount as a decimal string in the transaction's currency. Present on list rows and get-by-id when the transaction still exists."
2774
3089
  examples:
2775
3090
  - "1250.50"
2776
3091
  type: string
@@ -2780,7 +3095,7 @@ components:
2780
3095
  - user@example.com
2781
3096
  type: string
2782
3097
  contextId:
2783
- description: "Enrichment: id of the reconciliation context the exception's source belongs to (UUID). Present on list rows whose transaction and source still exist; powers the global triage queue's context attribution."
3098
+ description: "Enrichment: id of the reconciliation context the exception's source belongs to (UUID). Present on list rows and get-by-id when the transaction and source still exist; powers the global triage queue's context attribution."
2784
3099
  examples:
2785
3100
  - 550e8400-e29b-41d4-a716-446655440004
2786
3101
  type: string
@@ -2790,7 +3105,7 @@ components:
2790
3105
  - "2025-01-15T10:30:00Z"
2791
3106
  type: string
2792
3107
  currency:
2793
- description: "Enrichment: ISO 4217 currency code of the exception transaction's amount. Present on list rows whose transaction still exists."
3108
+ description: "Enrichment: ISO 4217 currency code of the exception transaction's amount. Present on list rows and get-by-id when the transaction still exists."
2794
3109
  examples:
2795
3110
  - USD
2796
3111
  type: string
@@ -2852,6 +3167,9 @@ components:
2852
3167
  examples:
2853
3168
  - 550e8400-e29b-41d4-a716-446655440002
2854
3169
  type: string
3170
+ settlement:
3171
+ $ref: "#/components/schemas/ExceptionSettlementResponse"
3172
+ description: Settlement figures for a fee break (expected vs credited and the signed difference), derived from the live fee-variance snapshot recorded for the exception's transaction. Present on get-by-id only, and only when the snapshot and the transaction amount are both available in the same currency.
2855
3173
  severity:
2856
3174
  description: "Severity level: LOW and MEDIUM are informational, HIGH needs prompt review, CRITICAL requires immediate action"
2857
3175
  enum:
@@ -2863,21 +3181,27 @@ components:
2863
3181
  - HIGH
2864
3182
  type: string
2865
3183
  sourceId:
2866
- description: "Enrichment: id of the reconciliation source the exception transaction belongs to (UUID). Present on list rows whose transaction still exists."
3184
+ description: "Enrichment: id of the reconciliation source the exception transaction belongs to (UUID). Present on list rows and get-by-id when the transaction still exists."
2867
3185
  examples:
2868
3186
  - 550e8400-e29b-41d4-a716-446655440003
2869
3187
  type: string
3188
+ sourceName:
3189
+ description: "Enrichment: display name of the reconciliation source. Present on get-by-id when the transaction and its source still exist."
3190
+ examples:
3191
+ - Bank feed
3192
+ type: string
2870
3193
  status:
2871
- description: "Lifecycle status: OPEN (unhandled), ASSIGNED (owned by a user), RESOLVED (closed out)"
3194
+ description: "Lifecycle status: OPEN (unhandled), ASSIGNED (owned by a user), PENDING_RESOLUTION (a resolution is in flight), RESOLVED (closed out)"
2872
3195
  enum:
2873
3196
  - OPEN
2874
3197
  - ASSIGNED
3198
+ - PENDING_RESOLUTION
2875
3199
  - RESOLVED
2876
3200
  examples:
2877
3201
  - OPEN
2878
3202
  type: string
2879
3203
  transactionDate:
2880
- description: "Enrichment: the exception transaction's value date as an RFC 3339 timestamp. Present on list rows whose transaction still exists."
3204
+ description: "Enrichment: the exception transaction's value date as an RFC 3339 timestamp. Present on list rows and get-by-id when the transaction still exists."
2881
3205
  examples:
2882
3206
  - "2025-01-14T00:00:00Z"
2883
3207
  type: string
@@ -2899,6 +3223,35 @@ components:
2899
3223
  - createdAt
2900
3224
  - updatedAt
2901
3225
  type: object
3226
+ ExceptionSettlementResponse:
3227
+ additionalProperties: false
3228
+ properties:
3229
+ credited:
3230
+ description: Amount actually credited (the transaction amount), as a decimal string
3231
+ examples:
3232
+ - "95.00"
3233
+ type: string
3234
+ currency:
3235
+ description: ISO 4217 currency code of the settlement amounts (the transaction's currency)
3236
+ examples:
3237
+ - BRL
3238
+ type: string
3239
+ difference:
3240
+ description: Signed difference credited minus expected, as a decimal string; negative when the credit fell short
3241
+ examples:
3242
+ - "-2.00"
3243
+ type: string
3244
+ expected:
3245
+ description: Amount the transaction should have credited under the expected fee, as a decimal string
3246
+ examples:
3247
+ - "97.00"
3248
+ type: string
3249
+ required:
3250
+ - expected
3251
+ - credited
3252
+ - difference
3253
+ - currency
3254
+ type: object
2902
3255
  ExportCountResponse:
2903
3256
  additionalProperties: false
2904
3257
  properties:
@@ -3074,6 +3427,8 @@ components:
3074
3427
  type: string
3075
3428
  status:
3076
3429
  description: Lifecycle status of the queued review (always PENDING_REVIEW on enqueue)
3430
+ enum:
3431
+ - PENDING_REVIEW
3077
3432
  examples:
3078
3433
  - PENDING_REVIEW
3079
3434
  type: string
@@ -3228,6 +3583,10 @@ components:
3228
3583
  type: string
3229
3584
  status:
3230
3585
  description: "Review lifecycle: PENDING_REVIEW (awaiting decision), APPROVED (candidates ingested), REJECTED (discarded)"
3586
+ enum:
3587
+ - PENDING_REVIEW
3588
+ - APPROVED
3589
+ - REJECTED
3231
3590
  examples:
3232
3591
  - PENDING_REVIEW
3233
3592
  type: string
@@ -3367,7 +3726,7 @@ components:
3367
3726
  type: integer
3368
3727
  structure:
3369
3728
  additionalProperties: {}
3370
- description: "Type-specific structure. FLAT: {\"amount\":\"1.50\"}. PERCENTAGE: {\"rate\":\"0.029\"} where rate is a 0..1 fraction of the base amount (0.029 means 2.9%), not a percent value. TIERED: {\"tiers\":[{\"rate\":\"0.01\",\"upTo\":\"1000\"},...]} with the same 0..1 fraction semantics per tier rate. EXPRESSION: {\"expression\":\"gross - desconto + multa + juros_dia * days_late(due_date, pay_date)\"} a formula over metadata fields (+ - * /, parentheses, and the functions days_late, days_between, max, min, abs, clamp)."
3729
+ description: "Type-specific structure. FLAT: {\"amount\":\"1.50\"}. PERCENTAGE: {\"rate\":\"0.029\"} where rate is a 0..1 fraction of the base amount (0.029 means 2.9%), not a percent value. TIERED: {\"tiers\":[{\"rate\":\"0.01\",\"upTo\":\"1000\"},...]} with the same 0..1 fraction semantics per tier rate. EXPRESSION: {\"expression\":\"gross - desconto + multa + juros_dia * days_late(due_date, pay_date)\"} a formula over metadata fields (+ - * /, parentheses, and the functions days_late, days_between, max, min, abs, clamp). A formula that is only the base amount times numeric literals is a percentage rate and is bounded 0..1: gross * 0.029 is 2.9%, gross * 2.9 is refused; any other formula is unbounded."
3371
3730
  type: object
3372
3731
  structureType:
3373
3732
  description: Shape of the fee structure. FLAT is a fixed amount; PERCENTAGE is a rate of the base; TIERED applies different rates per amount tier; EXPRESSION computes the fee from a bounded arithmetic formula over transaction metadata.
@@ -3680,7 +4039,15 @@ components:
3680
4039
  additionalProperties: false
3681
4040
  properties:
3682
4041
  canonicalKey:
3683
- description: Canonical field-map key the proposal targets
4042
+ description: Canonical field-map key the proposal targets. The closed vocabulary is the required keys (external_id, amount, currency, date) plus the optional ones (description, fee_amount, fee_currency); the advisor drops any key outside it before the proposal is returned
4043
+ enum:
4044
+ - external_id
4045
+ - amount
4046
+ - currency
4047
+ - date
4048
+ - description
4049
+ - fee_amount
4050
+ - fee_currency
3684
4051
  examples:
3685
4052
  - amount
3686
4053
  type: string
@@ -3993,9 +4360,13 @@ components:
3993
4360
  - TXN-12345
3994
4361
  type: string
3995
4362
  extractionStatus:
3996
- description: "Field-extraction status: PENDING (queued), EXTRACTED (fields parsed), FAILED (extraction error)"
4363
+ description: "Field-extraction status: PENDING (queued), COMPLETE (fields parsed), FAILED (extraction error)"
4364
+ enum:
4365
+ - PENDING
4366
+ - COMPLETE
4367
+ - FAILED
3997
4368
  examples:
3998
- - EXTRACTED
4369
+ - COMPLETE
3999
4370
  type: string
4000
4371
  id:
4001
4372
  description: Unique identifier for the transaction
@@ -4020,9 +4391,14 @@ components:
4020
4391
  format: uuid
4021
4392
  type: string
4022
4393
  status:
4023
- description: "Matching status: PENDING (not yet evaluated), MATCHED (reconciled), UNMATCHED (no match found)"
4394
+ description: "Matching status: UNMATCHED (no match found), MATCHED (reconciled), IGNORED (excluded from reconciliation by an operator), PENDING_REVIEW (imported under the blank-external-id review policy and awaiting an operator decision)"
4395
+ enum:
4396
+ - UNMATCHED
4397
+ - MATCHED
4398
+ - IGNORED
4399
+ - PENDING_REVIEW
4024
4400
  examples:
4025
- - PENDING
4401
+ - UNMATCHED
4026
4402
  type: string
4027
4403
  required:
4028
4404
  - id
@@ -4142,6 +4518,11 @@ components:
4142
4518
  type: string
4143
4519
  status:
4144
4520
  description: "Job lifecycle status: QUEUED (awaiting a worker), PROCESSING (parsing/normalizing rows), COMPLETED (finished), FAILED (aborted wholesale)"
4521
+ enum:
4522
+ - QUEUED
4523
+ - PROCESSING
4524
+ - COMPLETED
4525
+ - FAILED
4145
4526
  examples:
4146
4527
  - PROCESSING
4147
4528
  type: string
@@ -4212,7 +4593,11 @@ components:
4212
4593
  additionalProperties: false
4213
4594
  properties:
4214
4595
  kind:
4215
- description: "Value type: string (raw text), decimal (money/numeric verbatim token, parsed downstream), or date. A money column MUST be decimal"
4596
+ description: "Value type: string (raw text), decimal (money/numeric verbatim token, parsed downstream), or date. A money column MUST be decimal — declaring it string or date is refused by the server-side submission gate, which the schema enum does not replace"
4597
+ enum:
4598
+ - string
4599
+ - decimal
4600
+ - date
4216
4601
  examples:
4217
4602
  - decimal
4218
4603
  type: string
@@ -4244,6 +4629,10 @@ components:
4244
4629
  properties:
4245
4630
  kind:
4246
4631
  description: "Value type: string (raw text), decimal (money/numeric verbatim token, parsed downstream), or date"
4632
+ enum:
4633
+ - string
4634
+ - decimal
4635
+ - date
4247
4636
  examples:
4248
4637
  - decimal
4249
4638
  type: string
@@ -5209,7 +5598,12 @@ components:
5209
5598
  - 550e8400-e29b-41d4-a716-446655440000
5210
5599
  type: string
5211
5600
  status:
5212
- description: "Current status of the group: PROPOSED (awaiting review), CONFIRMED (accepted), or REJECTED (broken/unmatched)"
5601
+ description: "Current status of the group: PROPOSED (awaiting review), CONFIRMED (accepted), REJECTED (a proposed group discarded before confirmation), or REVOKED (a confirmed group whose confirmation was later undone by an unmatch; the original confirmation timestamp is kept for audit)"
5602
+ enum:
5603
+ - PROPOSED
5604
+ - CONFIRMED
5605
+ - REJECTED
5606
+ - REVOKED
5213
5607
  examples:
5214
5608
  - PROPOSED
5215
5609
  type: string
@@ -5268,6 +5662,9 @@ components:
5268
5662
  type: string
5269
5663
  side:
5270
5664
  description: "Reconciliation side of the item's source: LEFT or RIGHT. Resolved from the transaction's source; absent when the source side could not be resolved"
5665
+ enum:
5666
+ - LEFT
5667
+ - RIGHT
5271
5668
  examples:
5272
5669
  - LEFT
5273
5670
  type: string
@@ -5426,6 +5823,9 @@ components:
5426
5823
  type: string
5427
5824
  mode:
5428
5825
  description: "Execution mode: DRY_RUN evaluates rules without committing matches; COMMIT persists matches"
5826
+ enum:
5827
+ - DRY_RUN
5828
+ - COMMIT
5429
5829
  examples:
5430
5830
  - DRY_RUN
5431
5831
  type: string
@@ -5445,10 +5845,10 @@ components:
5445
5845
  additionalProperties:
5446
5846
  format: int64
5447
5847
  type: integer
5448
- description: Aggregate run statistics as an open key-value map; consumers must tolerate unknown keys and treat a missing key as unknown rather than zero. Known keys include matches, candidates_left, candidates_right, unmatched_left, unmatched_right, unmatched_external, auto_matched_left, auto_matched_right, pending_review_left, pending_review_right, proposed_left, proposed_right, exceptions_raised (newly created), exceptions_updated (re-touched), plus per-rule families rule_matched:<ruleID> and rule_meta:<ruleID>:<TYPE>
5848
+ description: Aggregate run statistics as an open key-value map; consumers must tolerate unknown keys and treat a missing key as unknown rather than zero. Known keys include matches, candidates_left, candidates_right, unmatched_left, unmatched_right, unmatched_external, auto_matched_left, auto_matched_right, pending_review_left, pending_review_right, proposed_left, proposed_right, exceptions_raised (newly created), exceptions_updated (re-touched), plus per-rule families rule_matched:<ruleID> and rule_meta:<ruleID>:<TYPE>. A run recovered after an interruption reports the exception rows its earlier attempt created under exceptions_updated, not exceptions_raised
5449
5849
  type: object
5450
5850
  status:
5451
- description: "Current status of the run: QUEUED (async submit, awaiting worker pickup), PROCESSING (in flight), FINALIZING (a transient finishing-up state — a poll MAY briefly observe it between PROCESSING and COMPLETED, and it is also observable while a run is recovered after a crash; treat it as in-flight, not terminal), COMPLETED (finished), or FAILED (errored)"
5851
+ description: "Current status of the run: QUEUED (async submit, awaiting worker pickup), PROCESSING (in flight), FINALIZING (a transient finishing-up state — a poll MAY briefly observe it between PROCESSING and COMPLETED, and it is also observable while a run is recovered after a crash; treat it as in-flight, not terminal), COMPLETED (finished), or FAILED (errored). An async run in flight when its pod stops goes back from PROCESSING to QUEUED and is picked up again with a new startedAt"
5452
5852
  enum:
5453
5853
  - QUEUED
5454
5854
  - PROCESSING
@@ -5493,14 +5893,18 @@ components:
5493
5893
  - 550e8400-e29b-41d4-a716-446655440000
5494
5894
  type: string
5495
5895
  type:
5496
- description: "Rule type at run time: EXACT (strict equality), TOLERANCE (within an amount band), DATE_LAG (allowing a settlement-date offset), or FUZZY (normalized/similarity-scored references, always proposes)"
5896
+ description: "Rule type at run time: EXACT (strict equality), TOLERANCE (within an amount band), DATE_LAG (allowing a settlement-date offset), or FUZZY (normalized/similarity-scored references, always proposes). Absent when the run recorded a match count for the rule without its metadata sibling"
5897
+ enum:
5898
+ - EXACT
5899
+ - TOLERANCE
5900
+ - DATE_LAG
5901
+ - FUZZY
5497
5902
  examples:
5498
5903
  - EXACT
5499
5904
  type: string
5500
5905
  required:
5501
5906
  - ruleId
5502
5907
  - priority
5503
- - type
5504
5908
  - matched
5505
5909
  type: object
5506
5910
  MatchedItemResponse:
@@ -5713,6 +6117,12 @@ components:
5713
6117
  type: string
5714
6118
  status:
5715
6119
  description: "Lifecycle status: OPEN (fresh residual), PARTIALLY_CLEARED (a leg netted but a residual remains), CLEARED (netted within tolerance), AGED (exceeded its aging threshold while still open), or WITHDRAWN (the confirmed match that opened it was un-matched, so the obligation was taken back with it)"
6120
+ enum:
6121
+ - OPEN
6122
+ - PARTIALLY_CLEARED
6123
+ - CLEARED
6124
+ - AGED
6125
+ - WITHDRAWN
5716
6126
  examples:
5717
6127
  - PARTIALLY_CLEARED
5718
6128
  type: string
@@ -5995,6 +6405,14 @@ components:
5995
6405
  examples:
5996
6406
  - Bank Reconciliation Q1
5997
6407
  type: string
6408
+ signConvention:
6409
+ description: "How this context's data carries sign. SAME: a payment carries the same sign as what it settles, so a negative amount is a reversal. OPPOSITE: a payment carries the opposite sign of the invoice it settles."
6410
+ enum:
6411
+ - SAME
6412
+ - OPPOSITE
6413
+ examples:
6414
+ - SAME
6415
+ type: string
5998
6416
  status:
5999
6417
  description: Lifecycle status. DRAFT is being configured; ACTIVE runs; PAUSED is suspended; ARCHIVED is retired.
6000
6418
  enum:
@@ -6034,6 +6452,7 @@ components:
6034
6452
  - feeToleranceAbs
6035
6453
  - feeTolerancePct
6036
6454
  - autoMatchOnUpload
6455
+ - signConvention
6037
6456
  - createdAt
6038
6457
  - updatedAt
6039
6458
  type: object
@@ -6047,7 +6466,96 @@ components:
6047
6466
  type: string
6048
6467
  config:
6049
6468
  additionalProperties: {}
6050
- description: Source-specific configuration object (connection and parsing settings). duplicate_key holds the ordered list of mapped fields that make two rows the same row; absent means rows are deduplicated on external_id alone. duplicate_key_changed_at is the server-set RFC 3339 moment duplicate-key detection last changed meaning on this source — either that list changing, or the field map remapping the column a declared field reads; rows imported before it keep the key they were deduplicated under.
6469
+ description: "Source-specific configuration object. Cross-key rules the schema cannot express: a duplicate_key component this source's field map does not fill is refused, because a key over an always-empty field makes every row a duplicate of every other; a source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate_key of its own, and a config holding both is refused in either direction; and editing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under, so a duplicate straddling the change is knowingly not detected."
6470
+ properties:
6471
+ blank_external_id:
6472
+ description: What happens to a row whose mapped external id is blank. REJECT (the default when the key is absent) fails the row. NEEDS_REVIEW imports it under a synthetic reference with status PENDING_REVIEW, so a blank reference becomes a reviewable import instead of an import failure.
6473
+ enum:
6474
+ - REJECT
6475
+ - NEEDS_REVIEW
6476
+ type: string
6477
+ camt053:
6478
+ additionalProperties: false
6479
+ description: How this source's camt.053 files map onto the canonical fields. Every other field is fixed by ISO 20022 itself. An absent object, or an absent sub-key, keeps the ISO defaults (booking, ntry_ref).
6480
+ properties:
6481
+ date_basis:
6482
+ description: "Entry date element: booking is BookgDt/Dt, valuation is ValDt/Dt. Default booking."
6483
+ enum:
6484
+ - booking
6485
+ - valuation
6486
+ type: string
6487
+ external_id_source:
6488
+ description: "Entry reference element: ntry_ref is NtryRef, end_to_end_id is NtryDtls/TxDtls/Refs/EndToEndId, tx_id is NtryDtls/TxDtls/Refs/TxId. Default ntry_ref."
6489
+ enum:
6490
+ - ntry_ref
6491
+ - end_to_end_id
6492
+ - tx_id
6493
+ type: string
6494
+ type: object
6495
+ dialect:
6496
+ additionalProperties: false
6497
+ description: How this source's delimited files are encoded and formatted. Declaration-driven only — there is no auto-detection. An absent object, or an absent sub-key, keeps the defaults (utf-8, comma, dot, iso).
6498
+ properties:
6499
+ date_style:
6500
+ enum:
6501
+ - iso
6502
+ - iso_offset
6503
+ - dmy
6504
+ - mdy
6505
+ type: string
6506
+ decimal_style:
6507
+ description: dot is 1234.56, comma is 1.234,56.
6508
+ enum:
6509
+ - dot
6510
+ - comma
6511
+ type: string
6512
+ delimiter:
6513
+ enum:
6514
+ - comma
6515
+ - semicolon
6516
+ - tab
6517
+ - pipe
6518
+ type: string
6519
+ encoding:
6520
+ enum:
6521
+ - utf-8
6522
+ - utf-8-sig
6523
+ - cp1252
6524
+ - iso-8859-1
6525
+ type: string
6526
+ type: object
6527
+ duplicate_key:
6528
+ description: The ordered list of mapped fields that make two rows the same row. Absent means external_id alone. On a source bound to an aggregator connection the aggregator retracts a movement by naming its external id, so that id has to stay the row identity.
6529
+ items:
6530
+ enum:
6531
+ - external_id
6532
+ - amount
6533
+ - currency
6534
+ - date
6535
+ - description
6536
+ - fee_amount
6537
+ - fee_currency
6538
+ type: string
6539
+ minItems: 1
6540
+ type: array
6541
+ uniqueItems: true
6542
+ duplicate_key_changed_at:
6543
+ description: SERVER-OWNED. The moment duplicate-key detection last changed meaning on this source, either because duplicate_key was edited or because the field map remapped the column a declared component reads. Rows imported before it keep the key they were deduplicated under. A value sent by a client is discarded.
6544
+ format: date-time
6545
+ readOnly: true
6546
+ type: string
6547
+ duplicate_policy:
6548
+ description: What happens to a row that repeats this source's duplicate key. FLAG_AS_EXCEPTION (the default when the key is absent) keeps the repeat out of the import and raises a duplicate exception on the row it repeated. KEEP_FIRST drops the repeat and raises nothing, so a collision leaves no trace anyone can act on. REJECT counts the repeat as an import error.
6549
+ enum:
6550
+ - FLAG_AS_EXCEPTION
6551
+ - KEEP_FIRST
6552
+ - REJECT
6553
+ type: string
6554
+ fail_on_error_rate_percent:
6555
+ description: "Fail the whole import when the percentage of failed rows exceeds this whole number. Absent means never auto-fail. The ceiling is 99, not 100: the comparison is strict, so 100 could never fire."
6556
+ maximum: 99
6557
+ minimum: 1
6558
+ type: integer
6051
6559
  type: object
6052
6560
  contextId:
6053
6561
  description: Identifier of the context this source belongs to.
@@ -6223,7 +6731,11 @@ components:
6223
6731
  - near-miss amounts cluster under 1%
6224
6732
  type: string
6225
6733
  type:
6226
- description: "Proposed rule type from the closed vocabulary: EXACT (strict equality), TOLERANCE (within an amount band), or DATE_LAG (allowing a settlement-date offset)"
6734
+ description: "Proposed rule type from the closed vocabulary: EXACT (strict equality), TOLERANCE (within an amount band), or DATE_LAG (allowing a settlement-date offset). FUZZY is excluded on purpose: a fuzzy rule only ever proposes graded-confidence links a human must review, so an operator configures one deliberately rather than accepting it from a suggestion"
6735
+ enum:
6736
+ - EXACT
6737
+ - TOLERANCE
6738
+ - DATE_LAG
6227
6739
  examples:
6228
6740
  - TOLERANCE
6229
6741
  type: string
@@ -6302,6 +6814,10 @@ components:
6302
6814
  type: string
6303
6815
  status:
6304
6816
  description: "Lifecycle status: PENDING_REVIEW (awaiting human decision), APPROVED (rule created), or REJECTED (discarded)"
6817
+ enum:
6818
+ - PENDING_REVIEW
6819
+ - APPROVED
6820
+ - REJECTED
6305
6821
  examples:
6306
6822
  - PENDING_REVIEW
6307
6823
  type: string
@@ -6668,7 +7184,9 @@ components:
6668
7184
  required:
6669
7185
  - id
6670
7186
  - status
6671
- type: object
7187
+ type:
7188
+ - object
7189
+ - "null"
6672
7190
  SetupProgressMatchRulesResponse:
6673
7191
  additionalProperties: false
6674
7192
  properties:
@@ -6730,7 +7248,9 @@ components:
6730
7248
  - method
6731
7249
  - path
6732
7250
  - requiredFields
6733
- type: object
7251
+ type:
7252
+ - object
7253
+ - "null"
6734
7254
  SetupProgressReadinessResponse:
6735
7255
  additionalProperties: false
6736
7256
  properties:
@@ -7060,6 +7580,11 @@ components:
7060
7580
  type: string
7061
7581
  ruleType:
7062
7582
  description: Strategy of the previewed rule
7583
+ enum:
7584
+ - EXACT
7585
+ - TOLERANCE
7586
+ - DATE_LAG
7587
+ - FUZZY
7063
7588
  examples:
7064
7589
  - EXACT
7065
7590
  type: string
@@ -7107,6 +7632,11 @@ components:
7107
7632
  type: object
7108
7633
  type:
7109
7634
  description: Rule strategy of the inline candidate rule
7635
+ enum:
7636
+ - EXACT
7637
+ - TOLERANCE
7638
+ - DATE_LAG
7639
+ - FUZZY
7110
7640
  examples:
7111
7641
  - EXACT
7112
7642
  type: string
@@ -7373,7 +7903,96 @@ components:
7373
7903
  type: string
7374
7904
  config:
7375
7905
  additionalProperties: {}
7376
- description: Source-specific configuration object (connection and parsing settings). duplicate_key holds the ordered list of mapped fields that make two rows the same row; absent means rows are deduplicated on external_id alone. duplicate_key_changed_at is the server-set RFC 3339 moment duplicate-key detection last changed meaning on this source — either that list changing, or the field map remapping the column a declared field reads; rows imported before it keep the key they were deduplicated under.
7906
+ description: "Source-specific configuration object. Cross-key rules the schema cannot express: a duplicate_key component this source's field map does not fill is refused, because a key over an always-empty field makes every row a duplicate of every other; a source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate_key of its own, and a config holding both is refused in either direction; and editing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under, so a duplicate straddling the change is knowingly not detected."
7907
+ properties:
7908
+ blank_external_id:
7909
+ description: What happens to a row whose mapped external id is blank. REJECT (the default when the key is absent) fails the row. NEEDS_REVIEW imports it under a synthetic reference with status PENDING_REVIEW, so a blank reference becomes a reviewable import instead of an import failure.
7910
+ enum:
7911
+ - REJECT
7912
+ - NEEDS_REVIEW
7913
+ type: string
7914
+ camt053:
7915
+ additionalProperties: false
7916
+ description: How this source's camt.053 files map onto the canonical fields. Every other field is fixed by ISO 20022 itself. An absent object, or an absent sub-key, keeps the ISO defaults (booking, ntry_ref).
7917
+ properties:
7918
+ date_basis:
7919
+ description: "Entry date element: booking is BookgDt/Dt, valuation is ValDt/Dt. Default booking."
7920
+ enum:
7921
+ - booking
7922
+ - valuation
7923
+ type: string
7924
+ external_id_source:
7925
+ description: "Entry reference element: ntry_ref is NtryRef, end_to_end_id is NtryDtls/TxDtls/Refs/EndToEndId, tx_id is NtryDtls/TxDtls/Refs/TxId. Default ntry_ref."
7926
+ enum:
7927
+ - ntry_ref
7928
+ - end_to_end_id
7929
+ - tx_id
7930
+ type: string
7931
+ type: object
7932
+ dialect:
7933
+ additionalProperties: false
7934
+ description: How this source's delimited files are encoded and formatted. Declaration-driven only — there is no auto-detection. An absent object, or an absent sub-key, keeps the defaults (utf-8, comma, dot, iso).
7935
+ properties:
7936
+ date_style:
7937
+ enum:
7938
+ - iso
7939
+ - iso_offset
7940
+ - dmy
7941
+ - mdy
7942
+ type: string
7943
+ decimal_style:
7944
+ description: dot is 1234.56, comma is 1.234,56.
7945
+ enum:
7946
+ - dot
7947
+ - comma
7948
+ type: string
7949
+ delimiter:
7950
+ enum:
7951
+ - comma
7952
+ - semicolon
7953
+ - tab
7954
+ - pipe
7955
+ type: string
7956
+ encoding:
7957
+ enum:
7958
+ - utf-8
7959
+ - utf-8-sig
7960
+ - cp1252
7961
+ - iso-8859-1
7962
+ type: string
7963
+ type: object
7964
+ duplicate_key:
7965
+ description: The ordered list of mapped fields that make two rows the same row. Absent means external_id alone. On a source bound to an aggregator connection the aggregator retracts a movement by naming its external id, so that id has to stay the row identity.
7966
+ items:
7967
+ enum:
7968
+ - external_id
7969
+ - amount
7970
+ - currency
7971
+ - date
7972
+ - description
7973
+ - fee_amount
7974
+ - fee_currency
7975
+ type: string
7976
+ minItems: 1
7977
+ type: array
7978
+ uniqueItems: true
7979
+ duplicate_key_changed_at:
7980
+ description: SERVER-OWNED. The moment duplicate-key detection last changed meaning on this source, either because duplicate_key was edited or because the field map remapped the column a declared component reads. Rows imported before it keep the key they were deduplicated under. A value sent by a client is discarded.
7981
+ format: date-time
7982
+ readOnly: true
7983
+ type: string
7984
+ duplicate_policy:
7985
+ description: What happens to a row that repeats this source's duplicate key. FLAG_AS_EXCEPTION (the default when the key is absent) keeps the repeat out of the import and raises a duplicate exception on the row it repeated. KEEP_FIRST drops the repeat and raises nothing, so a collision leaves no trace anyone can act on. REJECT counts the repeat as an import error.
7986
+ enum:
7987
+ - FLAG_AS_EXCEPTION
7988
+ - KEEP_FIRST
7989
+ - REJECT
7990
+ type: string
7991
+ fail_on_error_rate_percent:
7992
+ description: "Fail the whole import when the percentage of failed rows exceeds this whole number. Absent means never auto-fail. The ceiling is 99, not 100: the comparison is strict, so 100 could never fire."
7993
+ maximum: 99
7994
+ minimum: 1
7995
+ type: integer
7377
7996
  type: object
7378
7997
  contextId:
7379
7998
  description: Identifier of the context this source belongs to.
@@ -7692,9 +8311,13 @@ components:
7692
8311
  - TXN-12345
7693
8312
  type: string
7694
8313
  extractionStatus:
7695
- description: "Field-extraction status: PENDING (queued), EXTRACTED (fields parsed), FAILED (extraction error)"
8314
+ description: "Field-extraction status: PENDING (queued), COMPLETE (fields parsed), FAILED (extraction error)"
8315
+ enum:
8316
+ - PENDING
8317
+ - COMPLETE
8318
+ - FAILED
7696
8319
  examples:
7697
- - EXTRACTED
8320
+ - COMPLETE
7698
8321
  type: string
7699
8322
  id:
7700
8323
  description: Unique identifier for the transaction
@@ -7719,9 +8342,14 @@ components:
7719
8342
  format: uuid
7720
8343
  type: string
7721
8344
  status:
7722
- description: "Matching status: PENDING (not yet evaluated), MATCHED (reconciled), UNMATCHED (no match found)"
8345
+ description: "Matching status: UNMATCHED (no match found), MATCHED (reconciled), IGNORED (excluded from reconciliation by an operator), PENDING_REVIEW (imported under the blank-external-id review policy and awaiting an operator decision)"
8346
+ enum:
8347
+ - UNMATCHED
8348
+ - MATCHED
8349
+ - IGNORED
8350
+ - PENDING_REVIEW
7723
8351
  examples:
7724
- - PENDING
8352
+ - UNMATCHED
7725
8353
  type: string
7726
8354
  required:
7727
8355
  - id
@@ -7868,34 +8496,27 @@ components:
7868
8496
  additionalProperties: false
7869
8497
  properties:
7870
8498
  accountRef:
7871
- description: Opaque vendor account reference (Pluggy itemId, Belvo link id) the webhook pull threads onto its request
8499
+ description: Opaque vendor account reference (Pluggy itemId, Belvo link id). Supply it to bind (or re-bind) the connection after the vendor's consent widget returns one; omit it to leave the stored value untouched.
7872
8500
  examples:
7873
8501
  - a1b2c3d4-5678-90ab-cdef-1234567890ab
7874
- minLength: 1
7875
8502
  type: string
7876
8503
  baseUrl:
7877
- description: Vendor API base URL, stored as the connection host
8504
+ description: Vendor API base URL, stored as the connection host. Omit it to leave the stored URL untouched.
7878
8505
  examples:
7879
8506
  - https://api.pluggy.ai
7880
8507
  format: uri
7881
- minLength: 1
7882
8508
  type: string
7883
8509
  clientId:
7884
8510
  description: Aggregator API client id (optional; supply with secret to rotate, omit both to keep the stored credential; sealed; never emitted)
7885
8511
  type: string
7886
8512
  configName:
7887
- description: Unique connection config name (tenant-scoped); the mint endpoint binds a token to this name
8513
+ description: Unique connection config name (tenant-scoped); the mint endpoint binds a token to this name. Omit it to leave the stored name untouched.
7888
8514
  examples:
7889
8515
  - pluggy-main
7890
- minLength: 1
7891
8516
  type: string
7892
8517
  secret:
7893
8518
  description: Aggregator API client secret (optional; supply with clientId to rotate, omit both to keep the stored credential; sealed; never emitted)
7894
8519
  type: string
7895
- required:
7896
- - configName
7897
- - baseUrl
7898
- - accountRef
7899
8520
  type: object
7900
8521
  UpdateContextRequest:
7901
8522
  additionalProperties: false
@@ -7943,6 +8564,14 @@ components:
7943
8564
  - Bank Reconciliation Q2
7944
8565
  maxLength: 100
7945
8566
  type: string
8567
+ signConvention:
8568
+ description: "How this context's data carries sign. SAME: a payment carries the same sign as what it settles, so a negative amount is a reversal. OPPOSITE: a payment carries the opposite sign of the invoice it settles. Omit to leave it unchanged."
8569
+ enum:
8570
+ - SAME
8571
+ - OPPOSITE
8572
+ examples:
8573
+ - OPPOSITE
8574
+ type: string
7946
8575
  status:
7947
8576
  description: Lifecycle status to transition to. ACTIVE runs the context; PAUSED suspends scheduling; ARCHIVED retires it.
7948
8577
  enum:
@@ -8116,7 +8745,91 @@ components:
8116
8745
  properties:
8117
8746
  config:
8118
8747
  additionalProperties: {}
8119
- description: "Source-specific configuration object (connection and parsing settings). Reserved key duplicate_key: the ordered list of mapped fields that make two rows the same row — any of external_id, amount, currency, date, description, fee_amount, fee_currency. Send it empty of that key and rows are deduplicated on external_id alone. A field this source's field map does not fill is refused, because a key over a field that is always empty makes every row a duplicate of every other. A source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate key of its own: the aggregator retracts a movement by naming its external id, so that id has to stay this source's row identity. A config holding both is refused in either direction — drop duplicate_key from a bound source, or disconnect the aggregator connection first. Editing duplicate_key is allowed at any time and governs later imports only: rows already imported keep the key they were deduplicated under, and a duplicate straddling the change is knowingly not detected. Reserved read-only key duplicate_key_changed_at: the RFC 3339 moment duplicate-key detection last changed meaning on this source, set by the server; a value sent by a client is discarded. It moves for either change that re-keys future rows — editing duplicate_key, or the field map remapping the column a declared field reads (a source keyed on description whose description column moves derives a different key for the same movement). Reserved key duplicate_policy: what happens to a row repeating the duplicate key — FLAG_AS_EXCEPTION (the default: the repeat is kept out of the import and raised as a duplicate exception on the row it repeated), KEEP_FIRST (the repeat is dropped and nothing is raised), or REJECT (the repeat is counted as an import error)."
8748
+ description: "Source-specific configuration object. Cross-key rules the schema cannot express: a duplicate_key component this source's field map does not fill is refused, because a key over an always-empty field makes every row a duplicate of every other; a source bound to an aggregator connection (reserved key connection_config_name) cannot carry a duplicate_key of its own, and a config holding both is refused in either direction; and editing duplicate_key governs later imports only — rows already imported keep the key they were deduplicated under, so a duplicate straddling the change is knowingly not detected."
8749
+ properties:
8750
+ blank_external_id:
8751
+ description: What happens to a row whose mapped external id is blank. REJECT (the default when the key is absent) fails the row. NEEDS_REVIEW imports it under a synthetic reference with status PENDING_REVIEW, so a blank reference becomes a reviewable import instead of an import failure.
8752
+ enum:
8753
+ - REJECT
8754
+ - NEEDS_REVIEW
8755
+ type: string
8756
+ camt053:
8757
+ additionalProperties: false
8758
+ description: How this source's camt.053 files map onto the canonical fields. Every other field is fixed by ISO 20022 itself. An absent object, or an absent sub-key, keeps the ISO defaults (booking, ntry_ref).
8759
+ properties:
8760
+ date_basis:
8761
+ description: "Entry date element: booking is BookgDt/Dt, valuation is ValDt/Dt. Default booking."
8762
+ enum:
8763
+ - booking
8764
+ - valuation
8765
+ type: string
8766
+ external_id_source:
8767
+ description: "Entry reference element: ntry_ref is NtryRef, end_to_end_id is NtryDtls/TxDtls/Refs/EndToEndId, tx_id is NtryDtls/TxDtls/Refs/TxId. Default ntry_ref."
8768
+ enum:
8769
+ - ntry_ref
8770
+ - end_to_end_id
8771
+ - tx_id
8772
+ type: string
8773
+ type: object
8774
+ dialect:
8775
+ additionalProperties: false
8776
+ description: How this source's delimited files are encoded and formatted. Declaration-driven only — there is no auto-detection. An absent object, or an absent sub-key, keeps the defaults (utf-8, comma, dot, iso).
8777
+ properties:
8778
+ date_style:
8779
+ enum:
8780
+ - iso
8781
+ - iso_offset
8782
+ - dmy
8783
+ - mdy
8784
+ type: string
8785
+ decimal_style:
8786
+ description: dot is 1234.56, comma is 1.234,56.
8787
+ enum:
8788
+ - dot
8789
+ - comma
8790
+ type: string
8791
+ delimiter:
8792
+ enum:
8793
+ - comma
8794
+ - semicolon
8795
+ - tab
8796
+ - pipe
8797
+ type: string
8798
+ encoding:
8799
+ enum:
8800
+ - utf-8
8801
+ - utf-8-sig
8802
+ - cp1252
8803
+ - iso-8859-1
8804
+ type: string
8805
+ type: object
8806
+ duplicate_key:
8807
+ description: The ordered list of mapped fields that make two rows the same row. Absent means external_id alone. On a source bound to an aggregator connection the aggregator retracts a movement by naming its external id, so that id has to stay the row identity.
8808
+ items:
8809
+ enum:
8810
+ - external_id
8811
+ - amount
8812
+ - currency
8813
+ - date
8814
+ - description
8815
+ - fee_amount
8816
+ - fee_currency
8817
+ type: string
8818
+ minItems: 1
8819
+ type: array
8820
+ uniqueItems: true
8821
+ duplicate_policy:
8822
+ description: What happens to a row that repeats this source's duplicate key. FLAG_AS_EXCEPTION (the default when the key is absent) keeps the repeat out of the import and raises a duplicate exception on the row it repeated. KEEP_FIRST drops the repeat and raises nothing, so a collision leaves no trace anyone can act on. REJECT counts the repeat as an import error.
8823
+ enum:
8824
+ - FLAG_AS_EXCEPTION
8825
+ - KEEP_FIRST
8826
+ - REJECT
8827
+ type: string
8828
+ fail_on_error_rate_percent:
8829
+ description: "Fail the whole import when the percentage of failed rows exceeds this whole number. Absent means never auto-fail. The ceiling is 99, not 100: the comparison is strict, so 100 could never fire."
8830
+ maximum: 99
8831
+ minimum: 1
8832
+ type: integer
8120
8833
  type: object
8121
8834
  name:
8122
8835
  description: New human-readable name of the source.
@@ -8391,7 +9104,7 @@ components:
8391
9104
  format: int64
8392
9105
  type: integer
8393
9106
  monthlyLineAllowance:
8394
- description: Billable lines the plan includes per month, from the price list. Monthly on every plan regardless of billing interval. 0 when the stored plan code is not in the catalogue.
9107
+ description: Billable lines the plan includes per month, from the price list. Monthly on every plan regardless of billing interval. 0 when the plan is unmetered (see volumeUnmetered) or the stored plan code is not in the catalogue.
8395
9108
  format: int64
8396
9109
  type: integer
8397
9110
  overageCreditBalanceCents:
@@ -8399,7 +9112,7 @@ components:
8399
9112
  format: int64
8400
9113
  type: integer
8401
9114
  overageRateCentsPerThousandLines:
8402
- description: What lines beyond the allowance cost, in integer BRL cents per THOUSAND lines (per-thousand because the entry rate is 0,4 cents a line and would truncate to zero). 0 when the stored plan code is not in the catalogue.
9115
+ description: What lines beyond the allowance cost, in integer BRL cents per THOUSAND lines (per-thousand because the entry rate is 0,4 cents a line and would truncate to zero). 0 when the plan is unmetered (see volumeUnmetered) or the stored plan code is not in the catalogue.
8403
9116
  format: int64
8404
9117
  type: integer
8405
9118
  overageUncoveredCents:
@@ -8416,7 +9129,7 @@ components:
8416
9129
  description: "Setup lifecycle of the workspace: \"provisioning\" (still being built), \"active\" (ready to use), or \"failed\" (setup will not complete on its own — we have been told)."
8417
9130
  type: string
8418
9131
  provisioningStep:
8419
- description: "The setup step that is owed: \"create_tenant\", \"associate_service\", \"migrate_tenant\", \"provision_console\", or \"\" when nothing is owed. On a failed workspace this is the step it died on."
9132
+ description: "The setup step that is owed: \"create_tenant\", \"associate_service\", \"migrate_tenant\", \"provision_console\", \"grant_admin\", or \"\" when nothing is owed. On a failed workspace this is the step it died on."
8420
9133
  type: string
8421
9134
  trialEndsAt:
8422
9135
  description: When the free trial ends (UTC). Omitted for a paid plan that never trialed.
@@ -8425,6 +9138,9 @@ components:
8425
9138
  trialExpired:
8426
9139
  description: Whether the trial is over on EITHER axis (time or volume), or the workspace is already suspended.
8427
9140
  type: boolean
9141
+ volumeUnmetered:
9142
+ description: "Whether this plan is unmetered: its volume ceiling and its overage price are contractual (enterprise) rather than from the price list. When true, monthlyLineAllowance and overageRateCentsPerThousandLines are both 0 because no figure applies — do NOT render them as terms, and do not read the zero rate as free overage."
9143
+ type: boolean
8428
9144
  required:
8429
9145
  - plan
8430
9146
  - billingStatus
@@ -8437,6 +9153,7 @@ components:
8437
9153
  - provisioningState
8438
9154
  - provisioningStep
8439
9155
  - provisioningFailed
9156
+ - volumeUnmetered
8440
9157
  - monthlyLineAllowance
8441
9158
  - overageRateCentsPerThousandLines
8442
9159
  - overageCreditBalanceCents
@@ -8473,7 +9190,22 @@ info:
8473
9190
  email: support@lerian.studio
8474
9191
  name: Lerian Studio Support
8475
9192
  url: https://discord.gg/DnhqKwkGv3
8476
- description: Reconciliation engine for the Lerian Studio ecosystem. Provides automated transaction matching between Midaz ledger and external systems.
9193
+ description: |-
9194
+ Reconciliation engine for the Lerian Studio ecosystem. Provides automated transaction matching between Midaz ledger and external systems.
9195
+
9196
+ ## Idempotency
9197
+
9198
+ POST, PUT and PATCH requests accept an optional `X-Idempotency` header. It is the one header a key travels in and it has no synonym: a mutating request that carries an older spelling and no `X-Idempotency` is refused with 400 rather than processed unkeyed. Keys are 1-128 characters of letters, digits, hyphen, underscore or colon, are scoped per tenant, caller, method and request target, and are strictly opt-in: a request sent without the header is never de-duplicated. A retry under a key whose first attempt completed replays that stored response and carries `X-Idempotency-Replayed: true`; a retry that arrives while the first attempt is still in flight is refused with 409.
9199
+
9200
+ A retry must repeat the original request. On an ordinary route the body is part of what identifies it, so a completed key re-sent with a DIFFERENT body is refused with 422 and nothing is applied — send the correction under a new key. The two file routes (`POST /v1/imports/contexts/{contextId}/sources/{sourceId}/upload` and the matching `/preview`) consume their body as a live stream and cannot re-read it, so there the key itself is the identity under that method and path: a completed key re-sent replays the first answer whatever file the retry carries.
9201
+
9202
+ A key is ONE attempt. A refusal the request earned is recorded like any other answer, and every resend under that key replays it for the retention window — a caller that wants to correct its request mints a new key. Three answers do NOT spend the key, because none of them is an answer to the request itself: a 429 from the rate limiter, a 402 from the volume quota, and a 502 with code `MTCH-0513`, where the dispatch target answered and DECLINED before anything was created there. Every other 5xx HOLDS the key, including that code's near neighbour, the dispatch whose outcome could not be confirmed (502, code `MTCH-0514`), whose exception may already exist in the target system: the outcome was not recorded, so every resend under that key is refused 409 and nothing is sent again. Deliberately attempting such an operation again therefore requires a NEW key.
9203
+
9204
+ `X-Idempotency-Fenced` rides every response whose outcome the guard could not receipt, a 2xx included. `true` means the hold landed: the key still protects the operation and every resend under it is refused 409. Only `false` means a resend would EXECUTE — the answer in hand may already have applied and the key no longer protects it, so check whether the first attempt took effect before sending anything again.
9205
+
9206
+ Two bounds close the contract. A response larger than about 1 MB is delivered to its caller in full, but it is not stored for replay: a duplicate under the same key is answered 409 instead of replayed. And an over-sized body is refused with 413 and spends nothing. On every route but one the service-wide request body limit refuses it before the key is read. The streaming upload (`POST /v1/imports/contexts/{contextId}/sources/{sourceId}/upload`) is exempt from that limit: the key is read first and ingestion enforces its own upload limit inside the handler, so its 413 is a fourth answer that releases the key, and a smaller file may be re-sent under it.
9207
+
9208
+ Secret mints are another, sharper exception. `POST /v1/discovery/aggregator-connections/{id}/connect-token`, `POST /v1/discovery/webhooks/tokens`, `POST /v1/exceptions/callbacks/credentials` and `POST /v1/exceptions/callbacks/credentials/{credentialId}/rotate` each return a raw credential exactly ONCE, and storing that answer would keep the secret re-readable for the life of the key — so those four routes IGNORE the idempotency header entirely. Nothing is stored, nothing is replayed, and `X-Idempotency-Replayed` is never sent on them. A retry under the same key MINTS AGAIN and leaves a second live credential behind, so treat a mint as non-idempotent: read the first attempt's response rather than resending it. A surplus callback credential can be revoked through its own operation; a surplus aggregator webhook token has no revoke operation today and stays live.
8477
9209
  license:
8478
9210
  name: Lerian Studio General License
8479
9211
  title: Matcher Reconciliation API
@@ -8558,6 +9290,43 @@ paths:
8558
9290
  summary: Read a workspace's invoicing identification (backoffice)
8559
9291
  tags:
8560
9292
  - Onboarding
9293
+ /v1/admin/workspaces/{slug}/plan:
9294
+ put:
9295
+ description: "Puts a workspace on the contractual enterprise plan: persists plan=enterprise and billing_status=active together, then evicts the billing edge-gate and volume-resolver caches so the contractual ceiling applies immediately. ONLY \"enterprise\" is accepted. This is not a generic set-plan operation: self-serve plans are bought through hosted checkout and converged from the live subscription's price, so assigning one by hand would be a payment-processor bypass that the next processor delivery silently reverts — any other plan code returns 409. It REFUSES a workspace whose subscription the payment processor could still bill (409): the operator cancels there first, where the proration and refund decision gets human eyes, and this route never moves processor money. That refusal covers every subscription that is not permanently over — one awaiting card authentication or one that is paused is not charging today and resumes tomorrow, and it would revert this plan the moment it does; only a cancelled or expired subscription is assignable over. If the processor cannot be asked, the request is refused as retryable (503) rather than allowed through. A suspended workspace is refused (409) because this operation moves no access posture — reactivate it first, and the write is compare-and-swapped on the status read, so a suspension landing mid-request is refused rather than reversed. There is no reverse: removing the enterprise plan is not offered. The target slug comes from the URL path (backoffice operation, workspace admin action). An unknown workspace returns 404. Errors use RFC 9457 problem+json. Every refusal on this route carries its own product code, because the sentence of a 503 is scrubbed before it leaves the process and the code is then the whole answer: 409 MTCH-0803 (a subscription the processor can still bill — cancel it there first), 409 MTCH-0804 (a plan code other than enterprise), 409 MTCH-0805 (the workspace's billing status does not allow the change — reload it), 503 MTCH-0802 (the processor could not be asked — retry) and 503 MTCH-0801 (no payment processor is configured on this deployment — NO retry clears it; the lever is configuration). MTCH-0805 is the same code the suspend and reactivate routes answer for a refused billing-status transition."
9296
+ operationId: admin-assign-workspace-plan
9297
+ parameters:
9298
+ - description: Slug of the workspace to assign the plan to.
9299
+ in: path
9300
+ name: slug
9301
+ required: true
9302
+ schema:
9303
+ description: Slug of the workspace to assign the plan to.
9304
+ maxLength: 255
9305
+ type: string
9306
+ requestBody:
9307
+ content:
9308
+ application/json:
9309
+ schema:
9310
+ $ref: "#/components/schemas/AdminAssignPlanInputBody"
9311
+ required: true
9312
+ responses:
9313
+ "200":
9314
+ content:
9315
+ application/json:
9316
+ schema:
9317
+ $ref: "#/components/schemas/AdminAssignPlanResult"
9318
+ description: OK
9319
+ default:
9320
+ content:
9321
+ application/problem+json:
9322
+ schema:
9323
+ $ref: "#/components/schemas/Detail"
9324
+ description: Error
9325
+ security:
9326
+ - BearerAuth: []
9327
+ summary: Assign the enterprise plan to a workspace (backoffice)
9328
+ tags:
9329
+ - Onboarding
8561
9330
  /v1/admin/workspaces/{slug}/reactivate:
8562
9331
  put:
8563
9332
  description: "Restores a suspended workspace: persists billing_status=active, re-enables interactive console login at the IdP, reactivates the tenant at the Tenant Manager (best-effort), and evicts the billing edge-gate cache. The target slug comes from the URL path (backoffice operation, workspace admin action). Idempotent. Errors use RFC 9457 problem+json."
@@ -8622,7 +9391,7 @@ paths:
8622
9391
  - Onboarding
8623
9392
  /v1/billing/webhook:
8624
9393
  post:
8625
- description: "Receives a signed billing event from the payment processor and applies it to the workspace's commercial state. This route carries NO operator JWT and no tenant identifier of any kind: a processor event has no tenant until its customer id is resolved server-side. Authentication is the Stripe-Signature signature over the RAW request body, verified inside the processor's own tolerance window. It is fail-closed on configuration — with no signing secret configured every event is rejected, and there is no value that means accept anything. Delivery is idempotent by the processor's event id: a redelivery of an event already applied returns a quiet 200 and changes nothing, an event still being applied elsewhere returns 503 so the processor retries, and an event id reused with a DIFFERENT body is a 409 rather than an acknowledgement. A processing failure returns 5xx and never records the event as applied, so the processor's retry reclaims it. Errors use the RFC 9457 application/problem+json contract and never echo the signature, the secret or the body."
9394
+ description: "Receives a signed billing event from the payment processor and applies it to the workspace's commercial state. This route carries NO operator JWT and no tenant identifier of any kind: a processor event has no tenant until its customer id is resolved server-side. Authentication is the Stripe-Signature signature over the RAW request body, verified inside the processor's own tolerance window. It is fail-closed on configuration — with no signing secret configured every event is rejected, and there is no value that means accept anything. Delivery is idempotent by the processor's event id: a redelivery of an event already applied returns a quiet 200 and changes nothing, an event still being applied elsewhere returns 503 so the processor retries, and an event id reused with a DIFFERENT body is a 409 rather than an acknowledgement. A processing failure returns 5xx and never records the event as applied, so the processor's retry reclaims it. Errors use the RFC 9457 application/problem+json contract and never echo the signature, the secret or the body. The divergent-replay conflict carries its own product code, 409 MTCH-0811."
8626
9395
  operationId: receiveBillingWebhook
8627
9396
  parameters:
8628
9397
  - description: The processor's signature over the raw body, verified inside the processor's own tolerance window.
@@ -10357,6 +11126,36 @@ paths:
10357
11126
  summary: Update aggregator connection
10358
11127
  tags:
10359
11128
  - Discovery
11129
+ /v1/discovery/aggregator-connections/{id}/connect-token:
11130
+ post:
11131
+ description: "Mints the short-lived token the aggregator vendor's OWN consent widget (Pluggy Connect / the Belvo widget) consumes in the end customer's browser, using the connection's already-sealed credential. The token is returned exactly once: it is never persisted, never logged, and there is no endpoint that reads it back. Nothing is supplied in the request — the vendor is read off the stored connection, and the mode is derived from it: a connection already bound to a vendor item/link gets a RE-CONSENT token for that same item (`reconsent: true`, and `accountRef` echoes the exact item/link the token was scoped to), while a connection awaiting consent gets a first-consent token that mints a new one (`accountRef` empty). Pass the returned `accountRef` to the vendor widget's update mode rather than a locally cached value: the token is item-scoped, and pairing it with a stale id makes the vendor run the create flow and orphan the original item. The item/link id the widget returns is bound back through PUT /v1/discovery/aggregator-connections/{id} with `accountRef` (no credential needs re-supplying). A non-aggregator connection id returns 404; a vendor with no consent path on this deployment returns 422 MTCH-0213."
11132
+ operationId: mintAggregatorConsentToken
11133
+ parameters:
11134
+ - description: Opaque aggregator connection id
11135
+ in: path
11136
+ name: id
11137
+ required: true
11138
+ schema:
11139
+ description: Opaque aggregator connection id
11140
+ type: string
11141
+ responses:
11142
+ "201":
11143
+ content:
11144
+ application/json:
11145
+ schema:
11146
+ $ref: "#/components/schemas/AggregatorConsentTokenResponse"
11147
+ description: Created
11148
+ default:
11149
+ content:
11150
+ application/problem+json:
11151
+ schema:
11152
+ $ref: "#/components/schemas/Detail"
11153
+ description: Error
11154
+ security:
11155
+ - BearerAuth: []
11156
+ summary: Mint aggregator consent token
11157
+ tags:
11158
+ - Discovery
10360
11159
  /v1/discovery/connections:
10361
11160
  get:
10362
11161
  description: Returns all discovered Fetcher database connections.
@@ -11710,7 +12509,7 @@ paths:
11710
12509
  - Exception
11711
12510
  /v1/exceptions/{exceptionId}:
11712
12511
  get:
11713
- description: Retrieves a single exception by its ID.
12512
+ description: Retrieves a single exception by its ID, including the amount/currency/date/source/context of its transaction and, for fee breaks, the expected vs credited settlement figures.
11714
12513
  operationId: getException
11715
12514
  parameters:
11716
12515
  - description: Exception ID (UUID)
@@ -11843,7 +12642,7 @@ paths:
11843
12642
  type: string
11844
12643
  - description: Idempotency key for deduplication
11845
12644
  in: header
11846
- name: X-Idempotency-Key
12645
+ name: X-Idempotency
11847
12646
  required: true
11848
12647
  schema:
11849
12648
  description: Idempotency key for deduplication
@@ -13041,7 +13840,10 @@ paths:
13041
13840
  - Governance
13042
13841
  /v1/governance/audit-logs/verify:
13043
13842
  get:
13044
- description: "Re-verifies the calling tenant's tamper-evident audit hash chain and returns a structured verdict (intact, verified count, and the first broken tenant_seq when a break is found). The check is strictly read-only: it recomputes nothing into storage and never mutates an audit record. Use the optional maxRecords query parameter to bound how many records are inspected."
13843
+ description: |-
13844
+ Re-verifies the calling tenant's tamper-evident audit hash chain and returns a structured verdict (intact, verified count, and the first broken tenant_seq when a break is found). The check is strictly read-only: it recomputes nothing into storage and never mutates an audit record. Use the optional maxRecords query parameter to bound how many records are inspected.
13845
+
13846
+ Use the optional fromSeq query parameter to bind the verification floor: the first record inspected is the one with tenant_seq == fromSeq. A floor above 1 TRUSTS that record's stored prev_hash instead of validating it against the genesis hash, so tampering BELOW the floor is out of scope for that run and is not reported. Two uses follow from that: (1) resuming — when a verdict comes back truncated, re-run with fromSeq = fromSeq + verifiedCount to verify the remainder; (2) archived-partition tenants — once the archival worker has dropped the bottom partitions, verify from the current floor, because a run from seq 1 no longer has the records it would need. The verdict always echoes the effective fromSeq, so an empty range (verifiedCount 0 with a high fromSeq) is never mistaken for an intact chain verified from genesis.
13045
13847
  operationId: verifyAuditLogChain
13046
13848
  parameters:
13047
13849
  - description: Maximum number of records to inspect; clamped to the server bound. Omit to use the default bound.
@@ -13054,6 +13856,15 @@ paths:
13054
13856
  maximum: 10000
13055
13857
  minimum: 1
13056
13858
  type: integer
13859
+ - description: "Verification floor: the first record inspected is the one with this tenant_seq. Omit to start at the chain start (seq 1)."
13860
+ explode: false
13861
+ in: query
13862
+ name: fromSeq
13863
+ schema:
13864
+ description: "Verification floor: the first record inspected is the one with this tenant_seq. Omit to start at the chain start (seq 1)."
13865
+ format: int64
13866
+ minimum: 1
13867
+ type: integer
13057
13868
  responses:
13058
13869
  "200":
13059
13870
  content:
@@ -13575,7 +14386,7 @@ paths:
13575
14386
  - Ingestion
13576
14387
  /v1/imports/contexts/{contextId}/sources/{sourceId}/extract-document:
13577
14388
  post:
13578
- description: "Stores the uploaded source document tenant-scoped, runs deterministic + AI extraction, and enqueues the resulting transaction CANDIDATES in a human-review queue. AI output is NEVER authoritative: no transaction is reconciled until a human approves the review. The lane is gated by a global kill-switch AND a per-tenant opt-in (fail-closed: a non-opted-in tenant gets 403). The tenant is resolved from the JWT and the context/source from the path — never from the body."
14389
+ description: "Stores the uploaded source document tenant-scoped, runs deterministic + AI extraction, and enqueues the resulting transaction CANDIDATES in a human-review queue. AI output is NEVER authoritative: no transaction is reconciled until a human approves the review. The lane is gated by a global kill-switch AND one process-wide operator consent switch — NOT a per-customer opt-in: granting consent grants AI egress for EVERY customer at once, and while it is off every caller gets 403 (fail-closed). The tenant is resolved from the JWT and the context/source from the path — never from the body."
13579
14390
  operationId: extractDocument
13580
14391
  parameters:
13581
14392
  - description: Context ID
@@ -14475,7 +15286,7 @@ paths:
14475
15286
  tags:
14476
15287
  - Matching
14477
15288
  post:
14478
- description: "Builds AGGREGATE, privacy-safe history features for the context, asks the AI advisor for config-only candidate rules, and enqueues each surviving candidate in a human-review queue. AI output is NEVER authoritative: producing a suggestion CREATES NO rule. A rule is created only when a human APPROVES a suggestion. The lane is gated by a global advisor kill-switch AND a per-tenant opt-in (fail-closed: a non-opted-in tenant gets 403). Tenant from the JWT, context from the path. The egress payload is aggregates only — no raw transaction, money, or PII."
15289
+ description: "Builds AGGREGATE, privacy-safe history features for the context, asks the AI advisor for config-only candidate rules, and enqueues each surviving candidate in a human-review queue. AI output is NEVER authoritative: producing a suggestion CREATES NO rule. A rule is created only when a human APPROVES a suggestion. The lane is gated by a global advisor kill-switch AND one process-wide operator consent switch — NOT a per-customer opt-in: granting consent grants AI egress for EVERY customer at once. Until consent is granted the endpoint fails closed with 403. Tenant from the JWT, context from the path. The egress payload is aggregates only — no raw transaction, money, or PII."
14479
15290
  operationId: suggestMatchRules
14480
15291
  parameters:
14481
15292
  - description: Context ID
@@ -16262,7 +17073,7 @@ paths:
16262
17073
  - Onboarding
16263
17074
  /v1/signup/verify:
16264
17075
  post:
16265
- description: "Completes email verification and starts self-service onboarding. This is a PUBLIC, anonymous, pre-tenant route: it exchanges the emailed verification token for a workspace whose setup is now under way, and returns the workspace handle. It does NOT wait for setup to finish — creating the environment includes a schema migration whose duration the server does not control, so a background worker drives it to completion and the response comes back immediately. It is idempotent: a repeat call records nothing new, and a token that no longer resolves (already used or expired) returns the same 200 response. The route is rate-limited per client IP."
17076
+ description: "Completes email verification and starts self-service onboarding. This is a PUBLIC, anonymous, pre-tenant route: it exchanges the emailed verification token for a workspace whose setup is now under way, and returns the workspace handle. It does NOT wait for setup to finish — creating the environment includes a schema migration whose duration the server does not control, so a background worker drives it to completion and the response comes back immediately. It is idempotent: a repeat call records nothing new, and a token that no longer resolves (already used or expired) returns the same 200 response. The route is rate-limited per client IP. Its two conflicts carry their own product codes, and they are not the same answer: 409 MTCH-0812 (the workspace already exists and MAY be the caller's own — sign in, or sign up under another company name) and 409 MTCH-0813 (the name belongs to another account — only a different company name clears it)."
16266
17077
  operationId: signup-verify
16267
17078
  requestBody:
16268
17079
  content:
@@ -16311,7 +17122,7 @@ paths:
16311
17122
  - Onboarding
16312
17123
  /v1/workspace/billing-portal:
16313
17124
  post:
16314
- description: Opens the payment processor's hosted customer portal for the AUTHENTICATED tenant's own workspace and returns the URL to redirect the browser to. Card update, invoice history and cancellation live there, not here; cancellation takes effect at the end of the period already paid for. Errors use the RFC 9457 application/problem+json contract.
17125
+ description: "Opens the payment processor's hosted customer portal for the AUTHENTICATED tenant's own workspace and returns the URL to redirect the browser to. Card update, invoice history and cancellation live there, not here; cancellation takes effect at the end of the period already paid for. Errors use the RFC 9457 application/problem+json contract. Its two refusals carry their own product codes: 409 MTCH-0806 (plan set by contract, so there is no self-serve subscription to manage) and 409 MTCH-0810 (no billing account yet — subscribe first)."
16315
17126
  operationId: workspace-billing-portal
16316
17127
  responses:
16317
17128
  "200":
@@ -16333,7 +17144,7 @@ paths:
16333
17144
  - Onboarding
16334
17145
  /v1/workspace/checkout:
16335
17146
  post:
16336
- description: "Opens a hosted checkout session that subscribes the AUTHENTICATED tenant's own workspace to a self-serve plan, and returns the URL to redirect the browser to. The workspace is resolved from the JWT tenant-slug claim: this endpoint never accepts a tenant identifier in the body, path, query or headers, and the session is bound to the caller's tenant. The billing interval selects the payment methods — monthly is card, annual is boleto and Pix — so a session is never created with an instrument the amount cannot clear. A plan that is not self-serve, an unknown plan or interval, and a workspace that already has a subscription are all refused before the processor is called. The return URLs carry no activation-bearing parameter: the plan is activated only by the verified webhook, and the return page reads the resulting state from GET /v1/workspace/billing. Errors use the RFC 9457 application/problem+json contract."
17147
+ description: "Opens a hosted checkout session that subscribes the AUTHENTICATED tenant's own workspace to a self-serve plan, and returns the URL to redirect the browser to. The workspace is resolved from the JWT tenant-slug claim: this endpoint never accepts a tenant identifier in the body, path, query or headers, and the session is bound to the caller's tenant. The billing interval selects the payment methods — monthly is card, annual is boleto and Pix — so a session is never created with an instrument the amount cannot clear. A plan that is not self-serve, an unknown plan or interval, and a workspace that already has a subscription are all refused before the processor is called. The return URLs carry no activation-bearing parameter: the plan is activated only by the verified webhook, and the return page reads the resulting state from GET /v1/workspace/billing. Errors use the RFC 9457 application/problem+json contract. Each refusal carries its own product code so a client never has to read the sentence: 409 MTCH-0806 (plan set by contract), 409 MTCH-0807 (already subscribed), 409 MTCH-0808 (a checkout is open for a different plan or interval), 409 MTCH-0809 (a checkout is being opened right now — retry), 422 MTCH-0814 (the plan is not sold self-serve) and 400 MTCH-0001 (unknown plan or interval)."
16337
17148
  operationId: workspace-checkout
16338
17149
  requestBody:
16339
17150
  content:
@@ -16383,7 +17194,7 @@ paths:
16383
17194
  - Onboarding
16384
17195
  /v1/workspace/credit-purchase:
16385
17196
  post:
16386
- description: "Opens a ONE-OFF hosted payment session that buys prepaid overage credit for the AUTHENTICATED tenant's own workspace, and returns the URL to redirect the browser to. It is never a subscription. The workspace is resolved from the JWT tenant-slug claim: this endpoint never accepts a tenant identifier in the body, path, query or headers. Any workspace may buy — trialing, lapsed, monthly or annual — because the customer who has run out of allowance is the one being told to buy. Payment is by CARD on every plan, including annual: the instrument that funds overage credit is deliberately not the subscription's instrument, and the card is saved for future CREDIT purchases only. An amount outside the price list's minimum and maximum is refused before the processor is called. The credit balance moves ONLY when the processor confirms the payment through the verified webhook — never on the return page and never in this response. Errors use the RFC 9457 application/problem+json contract."
17197
+ description: "Opens a ONE-OFF hosted payment session that buys prepaid overage credit for the AUTHENTICATED tenant's own workspace, and returns the URL to redirect the browser to. It is never a subscription. The workspace is resolved from the JWT tenant-slug claim: this endpoint never accepts a tenant identifier in the body, path, query or headers. Any workspace on a self-serve plan may buy — trialing, lapsed, monthly or annual — because the customer who has run out of allowance is the one being told to buy. A workspace on a CONTRACTUAL plan is refused with 409: its volume is not metered, so prepaid overage credit buys it nothing. Payment is by CARD on every plan, including annual: the instrument that funds overage credit is deliberately not the subscription's instrument, and the card is saved for future CREDIT purchases only. An amount outside the price list's minimum and maximum is refused before the processor is called. The credit balance moves ONLY when the processor confirms the payment through the verified webhook — never on the return page and never in this response. Errors use the RFC 9457 application/problem+json contract. Its two refusals carry their own product codes: 422 MTCH-0815 (the amount is outside the purchasable range) and 409 MTCH-0806 (plan set by contract, so volume is not metered and credit buys nothing)."
16387
17198
  operationId: workspace-credit-purchase
16388
17199
  requestBody:
16389
17200
  content: