@warmio/contracts 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. package/README.md +15 -0
  2. package/dist/api/endpoints.d.ts +461 -0
  3. package/dist/api/endpoints.d.ts.map +1 -0
  4. package/dist/api/endpoints.js +397 -0
  5. package/dist/api/endpoints.js.map +1 -0
  6. package/dist/api/index.d.ts +2 -0
  7. package/dist/api/index.d.ts.map +1 -0
  8. package/dist/api/index.js +2 -0
  9. package/dist/api/index.js.map +1 -0
  10. package/dist/examples/automation.d.ts +16 -0
  11. package/dist/examples/automation.d.ts.map +1 -0
  12. package/dist/examples/automation.js +17 -0
  13. package/dist/examples/automation.js.map +1 -0
  14. package/dist/examples/financial-context.d.ts +32 -0
  15. package/dist/examples/financial-context.d.ts.map +1 -0
  16. package/dist/examples/financial-context.js +29 -0
  17. package/dist/examples/financial-context.js.map +1 -0
  18. package/dist/examples/index.d.ts +3 -0
  19. package/dist/examples/index.d.ts.map +1 -0
  20. package/dist/examples/index.js +3 -0
  21. package/dist/examples/index.js.map +1 -0
  22. package/dist/generated/base-openapi.d.ts +2 -0
  23. package/dist/generated/base-openapi.d.ts.map +1 -0
  24. package/dist/generated/base-openapi.js +3 -0
  25. package/dist/generated/base-openapi.js.map +1 -0
  26. package/dist/generated/private-mcp-tool-descriptors.d.ts +1031 -0
  27. package/dist/generated/private-mcp-tool-descriptors.d.ts.map +1 -0
  28. package/dist/generated/private-mcp-tool-descriptors.js +1541 -0
  29. package/dist/generated/private-mcp-tool-descriptors.js.map +1 -0
  30. package/dist/index.d.ts +6 -0
  31. package/dist/index.d.ts.map +1 -0
  32. package/dist/index.js +6 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/manifest.d.ts +3 -0
  35. package/dist/manifest.d.ts.map +1 -0
  36. package/dist/manifest.js +3 -0
  37. package/dist/manifest.js.map +1 -0
  38. package/dist/mcp/index.d.ts +2 -0
  39. package/dist/mcp/index.d.ts.map +1 -0
  40. package/dist/mcp/index.js +2 -0
  41. package/dist/mcp/index.js.map +1 -0
  42. package/dist/mcp/tools.d.ts +88 -0
  43. package/dist/mcp/tools.d.ts.map +1 -0
  44. package/dist/mcp/tools.js +124 -0
  45. package/dist/mcp/tools.js.map +1 -0
  46. package/dist/openapi/base.yaml +1679 -0
  47. package/dist/openapi/build-openapi.d.ts +28 -0
  48. package/dist/openapi/build-openapi.d.ts.map +1 -0
  49. package/dist/openapi/build-openapi.js +89 -0
  50. package/dist/openapi/build-openapi.js.map +1 -0
  51. package/dist/openapi/index.d.ts +2 -0
  52. package/dist/openapi/index.d.ts.map +1 -0
  53. package/dist/openapi/index.js +2 -0
  54. package/dist/openapi/index.js.map +1 -0
  55. package/dist/schemas/automation.d.ts +248 -0
  56. package/dist/schemas/automation.d.ts.map +1 -0
  57. package/dist/schemas/automation.js +46 -0
  58. package/dist/schemas/automation.js.map +1 -0
  59. package/dist/schemas/common.d.ts +76 -0
  60. package/dist/schemas/common.d.ts.map +1 -0
  61. package/dist/schemas/common.js +23 -0
  62. package/dist/schemas/common.js.map +1 -0
  63. package/dist/schemas/financial-context.d.ts +1300 -0
  64. package/dist/schemas/financial-context.d.ts.map +1 -0
  65. package/dist/schemas/financial-context.js +271 -0
  66. package/dist/schemas/financial-context.js.map +1 -0
  67. package/dist/schemas/index.d.ts +4 -0
  68. package/dist/schemas/index.d.ts.map +1 -0
  69. package/dist/schemas/index.js +4 -0
  70. package/dist/schemas/index.js.map +1 -0
  71. package/dist/types.d.ts +68 -0
  72. package/dist/types.d.ts.map +1 -0
  73. package/dist/types.js +2 -0
  74. package/dist/types.js.map +1 -0
  75. package/package.json +94 -0
@@ -0,0 +1,1679 @@
1
+ openapi: 3.1.0
2
+ info:
3
+ title: Warm API
4
+ description: |
5
+ Read your financial context or invoke supported Warm actions through a compact operation catalog.
6
+
7
+ ## Authentication
8
+ All requests use `Authorization: Bearer`. API keys are created for either read-only context
9
+ access or automation access in Settings on paid Warm plans.
10
+
11
+ Read/export routes accept `Authorization: Bearer YOUR_API_KEY_OR_ACCESS_TOKEN`.
12
+ Automation routes require an automation key (`warm_auto_...`) and do not accept access tokens.
13
+
14
+ Unauthenticated responses include `WWW-Authenticate` guidance and protected resource metadata.
15
+
16
+ ## Rate Limits
17
+ - Context keys: 200 requests per hour per key
18
+ - Automation keys: 500 requests per hour per key
19
+ - Rate limit headers included in authenticated responses
20
+ - `/api/export` supports dataset-scoped delta sync with `since` and publishes edge-cache metadata headers
21
+ version: '2.0.0'
22
+ contact:
23
+ name: Warm Support
24
+ url: https://warm.io/support
25
+ license:
26
+ name: Proprietary
27
+ url: https://warm.io/terms
28
+
29
+ servers:
30
+ - url: https://app.warm.io
31
+ description: Production
32
+
33
+ security:
34
+ - BearerAuth: []
35
+
36
+ paths:
37
+ /api/verify:
38
+ get:
39
+ operationId: verifyApiAccess
40
+ summary: Verify API credentials
41
+ description: |
42
+ Validate a Warm API key or signed-in user access token against the public verification route.
43
+
44
+ This endpoint is the canonical readiness check for public API clients and discovery tools.
45
+ tags:
46
+ - Verification
47
+ responses:
48
+ '200':
49
+ description: Credentials are valid and the caller has API access
50
+ content:
51
+ application/json:
52
+ schema:
53
+ type: object
54
+ required:
55
+ - status
56
+ - valid
57
+ - auth
58
+ properties:
59
+ status:
60
+ type: string
61
+ enum: [ok]
62
+ valid:
63
+ type: boolean
64
+ auth:
65
+ type: string
66
+ description: Auth method used to satisfy verification
67
+ audience:
68
+ type: string
69
+ enum: [context, automation, oauth]
70
+ '401':
71
+ $ref: '#/components/responses/Unauthorized'
72
+ '403':
73
+ $ref: '#/components/responses/Forbidden'
74
+ '429':
75
+ $ref: '#/components/responses/RateLimited'
76
+
77
+ /api/export:
78
+ get:
79
+ operationId: getDatasetExport
80
+ summary: Get a typed dataset export
81
+ description: |
82
+ Fetch a canonical financial dataset export from the unified `/api/export` surface.
83
+
84
+ Use `dataset=transactions` for paginated transaction history. Other datasets return
85
+ a typed JSON object keyed by the dataset name or retained public alias.
86
+
87
+ Preferred dataset names are `accounts`, `transactions`, `snapshots`, `recurring`,
88
+ `budgets`, `goals`, `health`, `liabilities`, and `holdings`.
89
+ tags:
90
+ - Export
91
+ parameters:
92
+ - name: dataset
93
+ in: query
94
+ description: Dataset identifier or retained public alias
95
+ required: true
96
+ schema:
97
+ type: string
98
+ enum:
99
+ - accounts
100
+ - transactions
101
+ - snapshots
102
+ - recurring
103
+ - budgets
104
+ - goals
105
+ - health
106
+ - liabilities
107
+ - holdings
108
+ - name: since
109
+ in: query
110
+ description: ISO timestamp for incremental exports
111
+ required: false
112
+ schema:
113
+ type: string
114
+ format: date-time
115
+ - name: last_knowledge
116
+ in: query
117
+ description: Legacy alias for `since`
118
+ required: false
119
+ schema:
120
+ type: string
121
+ format: date-time
122
+ - name: limit
123
+ in: query
124
+ description: Maximum transactions per page when `dataset=transactions`
125
+ required: false
126
+ schema:
127
+ type: integer
128
+ minimum: 1
129
+ maximum: 1000
130
+ - name: cursor
131
+ in: query
132
+ description: Pagination token from `pagination.next_cursor` when `dataset=transactions`
133
+ required: false
134
+ schema:
135
+ type: string
136
+ - name: accountId
137
+ in: query
138
+ description: Optional account filter when `dataset=transactions`
139
+ required: false
140
+ schema:
141
+ type: string
142
+ - name: search
143
+ in: query
144
+ description: Optional merchant or description search filter when `dataset=transactions`
145
+ required: false
146
+ schema:
147
+ type: string
148
+ minLength: 1
149
+ maxLength: 120
150
+ responses:
151
+ '200':
152
+ description: Successful dataset export
153
+ content:
154
+ application/json:
155
+ schema:
156
+ type: object
157
+ description: Dataset-shaped JSON response keyed by the requested dataset
158
+ properties:
159
+ generated_at:
160
+ type: string
161
+ format: date-time
162
+ next_knowledge:
163
+ type: string
164
+ format: date-time
165
+ nullable: true
166
+ pagination:
167
+ $ref: '#/components/schemas/Pagination'
168
+ additionalProperties: true
169
+ '400':
170
+ description: Invalid query parameters
171
+ '401':
172
+ $ref: '#/components/responses/Unauthorized'
173
+ '403':
174
+ $ref: '#/components/responses/Forbidden'
175
+ '429':
176
+ $ref: '#/components/responses/RateLimited'
177
+
178
+ /api/financial-context:
179
+ get:
180
+ operationId: getFinancialContext
181
+ summary: Get compact financial context
182
+ description: |
183
+ Fetch the current compact FinancialContext artifact for the authenticated user.
184
+
185
+ This response does not include transaction items. Use
186
+ `/api/financial-context/transactions` for month-addressed transaction pages or the
187
+ fixed 10-day latest transaction window.
188
+ tags:
189
+ - Export
190
+ responses:
191
+ '200':
192
+ description: Compact FinancialContext artifact
193
+ headers:
194
+ ETag:
195
+ $ref: '#/components/headers/ETag'
196
+ Cache-Control:
197
+ $ref: '#/components/headers/PrivateNoStore'
198
+ content:
199
+ application/json:
200
+ schema:
201
+ $ref: '#/components/schemas/FinancialContext'
202
+ '304':
203
+ description: The caller's If-None-Match value matches the current content hash
204
+ '401':
205
+ $ref: '#/components/responses/Unauthorized'
206
+ '403':
207
+ $ref: '#/components/responses/Forbidden'
208
+ '413':
209
+ $ref: '#/components/responses/PayloadTooLarge'
210
+ '429':
211
+ $ref: '#/components/responses/RateLimited'
212
+
213
+ /api/financial-context/transactions:
214
+ get:
215
+ operationId: getFinancialContextTransactions
216
+ summary: Get financial-context transactions
217
+ description: |
218
+ Fetch one transaction month or the fixed 10-day latest transaction window from the
219
+ current financial-context artifact.
220
+
221
+ The raw API requires exactly one selector: `month=YYYY-MM` or `latest=1`.
222
+ Bare calls are invalid on the raw API. The `@warmio/mcp` v7 `get_transactions` tool
223
+ maps bare calls to the fixed latest window and accepts only `month` (`YYYY-MM`) or
224
+ `latest: true`; it does not accept cursor, search, or `last_knowledge`.
225
+ Transaction amounts use the Warm/Plaid sign convention:
226
+ positive = expense/debit, negative = income/credit.
227
+
228
+ A well-formed month inside the covered range with no matching items returns `200` with
229
+ `count: 0` and `items: []`. Months before the earliest indexed month or after the latest
230
+ covered month return `404`.
231
+ tags:
232
+ - Export
233
+ parameters:
234
+ - name: month
235
+ in: query
236
+ description: Transaction month selector in YYYY-MM format. Mutually exclusive with `latest`.
237
+ required: false
238
+ schema:
239
+ type: string
240
+ pattern: '^\d{4}-(0[1-9]|1[0-2])$'
241
+ example: '2026-07'
242
+ - name: latest
243
+ in: query
244
+ description: Set to `1` for the fixed 10-day latest transaction window.
245
+ required: false
246
+ schema:
247
+ type: string
248
+ enum: ['1']
249
+ responses:
250
+ '200':
251
+ description: Transaction month page or latest transaction window
252
+ headers:
253
+ ETag:
254
+ $ref: '#/components/headers/ETag'
255
+ Cache-Control:
256
+ $ref: '#/components/headers/PrivateNoStore'
257
+ content:
258
+ application/json:
259
+ schema:
260
+ oneOf:
261
+ - $ref: '#/components/schemas/TransactionMonth'
262
+ - $ref: '#/components/schemas/LatestTransactions'
263
+ '304':
264
+ description: The caller's If-None-Match value matches the current content hash
265
+ '400':
266
+ description: Missing selectors, mutually exclusive selectors, malformed `month`, or `latest` other than `1`
267
+ content:
268
+ application/json:
269
+ schema:
270
+ $ref: '#/components/schemas/Error'
271
+ '401':
272
+ $ref: '#/components/responses/Unauthorized'
273
+ '403':
274
+ $ref: '#/components/responses/Forbidden'
275
+ '413':
276
+ $ref: '#/components/responses/PayloadTooLarge'
277
+ '429':
278
+ $ref: '#/components/responses/RateLimited'
279
+
280
+ /api/financial-context/meta:
281
+ get:
282
+ operationId: getFinancialContextMeta
283
+ summary: Get financial-context metadata
284
+ description: |
285
+ Fetch operational metadata for the current financial-context artifact, including the
286
+ content hash used as the ETag, byte length, row counts, and freshness timestamps.
287
+ `content_hash` is the public artifact version token; this metadata does not expose a
288
+ public `data_version`.
289
+ tags:
290
+ - Export
291
+ responses:
292
+ '200':
293
+ description: Financial-context metadata
294
+ headers:
295
+ ETag:
296
+ $ref: '#/components/headers/ETag'
297
+ Cache-Control:
298
+ $ref: '#/components/headers/PrivateNoStore'
299
+ content:
300
+ application/json:
301
+ schema:
302
+ $ref: '#/components/schemas/FinancialContextMeta'
303
+ '304':
304
+ description: The caller's If-None-Match value matches the current content hash
305
+ '401':
306
+ $ref: '#/components/responses/Unauthorized'
307
+ '403':
308
+ $ref: '#/components/responses/Forbidden'
309
+ '413':
310
+ $ref: '#/components/responses/PayloadTooLarge'
311
+ '429':
312
+ $ref: '#/components/responses/RateLimited'
313
+
314
+ /api/automation/operations/search:
315
+ post:
316
+ operationId: searchOperations
317
+ summary: Search supported automation operations
318
+ tags: [Automation]
319
+ security:
320
+ - AutomationKeyAuth: []
321
+ requestBody:
322
+ required: false
323
+ content:
324
+ application/json:
325
+ schema:
326
+ type: object
327
+ additionalProperties: false
328
+ properties:
329
+ query:
330
+ type: string
331
+ maxLength: 200
332
+ responses:
333
+ '200':
334
+ description: Matching operations
335
+ content:
336
+ application/json:
337
+ schema:
338
+ type: object
339
+ additionalProperties: false
340
+ required: [operations]
341
+ properties:
342
+ operations:
343
+ type: array
344
+ items:
345
+ $ref: '#/components/schemas/AutomationOperation'
346
+ '401':
347
+ $ref: '#/components/responses/Unauthorized'
348
+ '403':
349
+ $ref: '#/components/responses/Forbidden'
350
+ '400':
351
+ $ref: '#/components/responses/BadRequest'
352
+ '429':
353
+ $ref: '#/components/responses/RateLimited'
354
+ '500':
355
+ $ref: '#/components/responses/InternalError'
356
+
357
+ /api/automation/operations/describe:
358
+ post:
359
+ operationId: describeOperation
360
+ summary: Describe one operation and request owner approval when required
361
+ tags: [Automation]
362
+ security:
363
+ - AutomationKeyAuth: []
364
+ requestBody:
365
+ required: true
366
+ content:
367
+ application/json:
368
+ schema:
369
+ $ref: '#/components/schemas/OperationRequest'
370
+ responses:
371
+ '200':
372
+ description: Operation schema and optional pending owner approval
373
+ content:
374
+ application/json:
375
+ schema:
376
+ type: object
377
+ additionalProperties: false
378
+ required: [operation]
379
+ properties:
380
+ operation:
381
+ allOf:
382
+ - $ref: '#/components/schemas/AutomationOperation'
383
+ - type: object
384
+ properties:
385
+ input_schema:
386
+ type: object
387
+ approval:
388
+ type: object
389
+ additionalProperties: false
390
+ required: [id, status, approval_url, expires_at]
391
+ properties:
392
+ id: { type: string, format: uuid }
393
+ status: { type: string, enum: [pending] }
394
+ approval_url: { type: string, format: uri }
395
+ expires_at: { type: string, format: date-time }
396
+ '400':
397
+ $ref: '#/components/responses/BadRequest'
398
+ '401':
399
+ $ref: '#/components/responses/Unauthorized'
400
+ '403':
401
+ $ref: '#/components/responses/Forbidden'
402
+ '404':
403
+ $ref: '#/components/responses/NotFound'
404
+ '429':
405
+ $ref: '#/components/responses/RateLimited'
406
+ '500':
407
+ $ref: '#/components/responses/InternalError'
408
+
409
+ /api/automation/operations/invoke:
410
+ post:
411
+ operationId: invokeOperation
412
+ summary: Invoke one supported operation
413
+ tags: [Automation]
414
+ security:
415
+ - AutomationKeyAuth: []
416
+ requestBody:
417
+ required: true
418
+ content:
419
+ application/json:
420
+ schema:
421
+ $ref: '#/components/schemas/OperationInvokeRequest'
422
+ responses:
423
+ '200':
424
+ description: Wrapped response from the invoked operation
425
+ content:
426
+ application/json:
427
+ schema:
428
+ $ref: '#/components/schemas/AutomationInvocationResponse'
429
+ '400':
430
+ $ref: '#/components/responses/BadRequest'
431
+ '401':
432
+ $ref: '#/components/responses/Unauthorized'
433
+ '403':
434
+ $ref: '#/components/responses/Forbidden'
435
+ '404':
436
+ $ref: '#/components/responses/NotFound'
437
+ '409':
438
+ description: Owner approval is required, invalid, expired, or already used
439
+ content:
440
+ application/json:
441
+ schema:
442
+ $ref: '#/components/schemas/Error'
443
+ '429':
444
+ $ref: '#/components/responses/RateLimited'
445
+ '500':
446
+ $ref: '#/components/responses/InternalError'
447
+
448
+ components:
449
+ securitySchemes:
450
+ BearerAuth:
451
+ type: http
452
+ scheme: bearer
453
+ description: 'Read/export format: `Authorization: Bearer YOUR_API_KEY_OR_ACCESS_TOKEN`'
454
+ AutomationKeyAuth:
455
+ type: http
456
+ scheme: bearer
457
+ description: 'Automation format: `Authorization: Bearer warm_auto_...`'
458
+
459
+ headers:
460
+ ETag:
461
+ description: Quoted content hash for If-None-Match revalidation
462
+ schema:
463
+ type: string
464
+ example: '"7b6f9d4c..."'
465
+ PrivateNoStore:
466
+ description: Private financial responses are not stored by browsers or shared caches
467
+ schema:
468
+ type: string
469
+ example: private, no-store
470
+
471
+ responses:
472
+ BadRequest:
473
+ description: The request body or operation input is invalid
474
+ content:
475
+ application/json:
476
+ schema:
477
+ $ref: '#/components/schemas/Error'
478
+ Unauthorized:
479
+ description: Missing or invalid credentials
480
+ content:
481
+ application/json:
482
+ schema:
483
+ $ref: '#/components/schemas/Error'
484
+ Forbidden:
485
+ description: The caller is authenticated but does not have API access
486
+ content:
487
+ application/json:
488
+ schema:
489
+ $ref: '#/components/schemas/Error'
490
+ NotFound:
491
+ description: The requested operation does not exist
492
+ content:
493
+ application/json:
494
+ schema:
495
+ $ref: '#/components/schemas/Error'
496
+ InternalError:
497
+ description: The request could not be completed safely
498
+ content:
499
+ application/json:
500
+ schema:
501
+ $ref: '#/components/schemas/Error'
502
+ PayloadTooLarge:
503
+ description: The response would exceed the public API response-size limit
504
+ content:
505
+ application/json:
506
+ schema:
507
+ $ref: '#/components/schemas/Error'
508
+ RateLimited:
509
+ description: Hourly per-credential rate limit exceeded
510
+ headers:
511
+ Retry-After:
512
+ description: Seconds until the rate-limit window resets
513
+ schema:
514
+ type: integer
515
+ example: 3600
516
+ content:
517
+ application/json:
518
+ schema:
519
+ $ref: '#/components/schemas/Error'
520
+
521
+ schemas:
522
+ AutomationOperation:
523
+ type: object
524
+ additionalProperties: false
525
+ required: [operation_id, summary, description, method, path, risk, confirmation_required]
526
+ properties:
527
+ operation_id: { type: string }
528
+ summary: { type: string }
529
+ description: { type: string }
530
+ method: { type: string, enum: [GET, POST, PATCH, PUT, DELETE] }
531
+ path: { type: string }
532
+ risk:
533
+ type: array
534
+ items: { type: string, enum: [read, write, destructive, external_effect] }
535
+ confirmation_required: { type: boolean }
536
+ OperationRequest:
537
+ type: object
538
+ additionalProperties: false
539
+ required: [operation_id]
540
+ properties:
541
+ operation_id: { type: string }
542
+ input:
543
+ $ref: '#/components/schemas/OperationInput'
544
+ OperationInvokeRequest:
545
+ type: object
546
+ additionalProperties: false
547
+ required: [operation_id]
548
+ properties:
549
+ operation_id: { type: string }
550
+ input:
551
+ $ref: '#/components/schemas/OperationInput'
552
+ approval_id:
553
+ type: string
554
+ format: uuid
555
+ description: Matching owner approval required for every write operation
556
+ OperationInput:
557
+ type: object
558
+ additionalProperties: false
559
+ properties:
560
+ params: { type: object, additionalProperties: { type: string } }
561
+ body: { type: object, additionalProperties: true }
562
+ AutomationInvocationResponse:
563
+ type: object
564
+ additionalProperties: false
565
+ required: [body, headers, operation_id, status]
566
+ properties:
567
+ body: {}
568
+ headers:
569
+ type: object
570
+ additionalProperties: { type: string }
571
+ operation_id: { type: string }
572
+ status: { type: integer, minimum: 100, maximum: 599 }
573
+ ExportResponse:
574
+ type: object
575
+ required:
576
+ - schema_version
577
+ - generated_at
578
+ - user_id
579
+ - data_version
580
+ - next_knowledge
581
+ - accounts
582
+ - transactions
583
+ - snapshots
584
+ - pagination
585
+ properties:
586
+ schema_version:
587
+ type: string
588
+ description: API schema version
589
+ example: v1
590
+ generated_at:
591
+ type: string
592
+ format: date-time
593
+ description: Response generation timestamp
594
+ example: '2026-01-10T15:30:00Z'
595
+ user_id:
596
+ type: string
597
+ format: uuid
598
+ description: Your user ID
599
+ example: a1b2c3d4-e5f6-7890-abcd-ef1234567890
600
+ data_version:
601
+ type: integer
602
+ description: Monotonic version number (increments on data changes)
603
+ example: 42
604
+ next_knowledge:
605
+ type: string
606
+ format: date-time
607
+ description: Use as `last_knowledge` in next request for delta sync
608
+ example: '2026-01-10T15:30:00Z'
609
+ accounts:
610
+ type: array
611
+ items:
612
+ $ref: '#/components/schemas/Account'
613
+ transactions:
614
+ type: array
615
+ items:
616
+ $ref: '#/components/schemas/Transaction'
617
+ snapshots:
618
+ type: array
619
+ items:
620
+ $ref: '#/components/schemas/Snapshot'
621
+ pagination:
622
+ $ref: '#/components/schemas/Pagination'
623
+
624
+ Account:
625
+ type: object
626
+ required:
627
+ - id
628
+ - name
629
+ - type
630
+ - current_balance
631
+ - iso_currency_code
632
+ - is_active
633
+ properties:
634
+ id:
635
+ type: string
636
+ format: uuid
637
+ description: Unique account identifier
638
+ example: acc_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
639
+ account_id:
640
+ type: string
641
+ description: External account ID (from Plaid)
642
+ example: plaid_acc_ABC123xyz
643
+ name:
644
+ type: string
645
+ description: Display name with masked account number
646
+ example: 'Checking ****1234'
647
+ type:
648
+ type: string
649
+ enum: [depository, credit, loan, investment, brokerage, other]
650
+ description: Account type
651
+ example: depository
652
+ subtype:
653
+ type: string
654
+ description: Specific subtype
655
+ example: checking
656
+ enum:
657
+ - checking
658
+ - savings
659
+ - money market
660
+ - cd
661
+ - credit card
662
+ - mortgage
663
+ - student
664
+ - auto
665
+ - 401k
666
+ - ira
667
+ - brokerage
668
+ - other
669
+ current_balance:
670
+ type: number
671
+ description: Current balance (positive for assets)
672
+ example: 5420.50
673
+ available_balance:
674
+ type: number
675
+ nullable: true
676
+ description: Available balance (may differ from current)
677
+ example: 5320.50
678
+ iso_currency_code:
679
+ type: string
680
+ description: ISO 4217 currency code
681
+ example: USD
682
+ mask:
683
+ type: string
684
+ description: Last 4 digits of account number
685
+ example: '1234'
686
+ is_active:
687
+ type: boolean
688
+ description: Whether account is actively syncing
689
+ example: true
690
+ created_at:
691
+ type: string
692
+ format: date-time
693
+ example: '2025-06-15T10:00:00Z'
694
+ updated_at:
695
+ type: string
696
+ format: date-time
697
+ example: '2026-01-10T12:00:00Z'
698
+
699
+ Transaction:
700
+ type: object
701
+ required:
702
+ - id
703
+ - account_id
704
+ - date
705
+ - amount
706
+ - name
707
+ - primary_category
708
+ - detailed_category
709
+ - pending
710
+ - iso_currency_code
711
+ properties:
712
+ id:
713
+ type: string
714
+ format: uuid
715
+ description: Unique transaction identifier
716
+ example: txn_9a8b7c6d-5e4f-3a2b-1c0d-9e8f7a6b5c4d
717
+ transaction_id:
718
+ type: string
719
+ description: External transaction ID (from Plaid)
720
+ example: plaid_txn_XYZ789abc
721
+ account_id:
722
+ type: string
723
+ format: uuid
724
+ description: Parent account ID
725
+ example: acc_8f3a2b1c-4d5e-6f7a-8b9c-0d1e2f3a4b5c
726
+ date:
727
+ type: string
728
+ format: date
729
+ description: Posted date
730
+ example: '2026-01-09'
731
+ authorized_date:
732
+ type: string
733
+ format: date
734
+ nullable: true
735
+ description: Authorization date (if different)
736
+ example: '2026-01-08'
737
+ amount:
738
+ type: number
739
+ description: Amount (positive = expense/debit, negative = income/credit)
740
+ example: 42.50
741
+ name:
742
+ type: string
743
+ description: Raw transaction description from bank
744
+ example: 'TRADER JOES #123 SAN FRANCISCO'
745
+ merchant_name:
746
+ type: string
747
+ nullable: true
748
+ description: Cleaned merchant name
749
+ example: "Trader Joe's"
750
+ merchant_entity_id:
751
+ type: string
752
+ nullable: true
753
+ description: Unique merchant identifier
754
+ example: eyg8o776k0QmNgVpAmaQj4WgzW9Qzo6O51gdd
755
+ logo:
756
+ type: string
757
+ format: uri
758
+ nullable: true
759
+ description: URL to merchant logo
760
+ example: https://plaid-merchant-logos.plaid.com/trader_joes.png
761
+ primary_category:
762
+ type: string
763
+ description: High-level category
764
+ example: FOOD_AND_DRINK
765
+ enum:
766
+ - INCOME
767
+ - TRANSFER_IN
768
+ - TRANSFER_OUT
769
+ - LOAN_PAYMENTS
770
+ - BANK_FEES
771
+ - ENTERTAINMENT
772
+ - FOOD_AND_DRINK
773
+ - GENERAL_MERCHANDISE
774
+ - HOME_IMPROVEMENT
775
+ - MEDICAL
776
+ - PERSONAL_CARE
777
+ - GENERAL_SERVICES
778
+ - GOVERNMENT_AND_NON_PROFIT
779
+ - TRANSPORTATION
780
+ - TRAVEL
781
+ - RENT_AND_UTILITIES
782
+ detailed_category:
783
+ type: string
784
+ description: Specific category
785
+ example: FOOD_AND_DRINK_GROCERIES
786
+ category_confidence:
787
+ type: string
788
+ enum: [VERY_HIGH, HIGH, MEDIUM, LOW, UNKNOWN]
789
+ description: Category confidence level
790
+ example: VERY_HIGH
791
+ payment_channel:
792
+ type: string
793
+ enum: [in_store, online, other]
794
+ description: How payment was made
795
+ example: in_store
796
+ pending:
797
+ type: boolean
798
+ description: Whether transaction is still pending
799
+ example: false
800
+ iso_currency_code:
801
+ type: string
802
+ description: ISO 4217 currency code
803
+ example: USD
804
+ location:
805
+ $ref: '#/components/schemas/Location'
806
+ created_at:
807
+ type: string
808
+ format: date-time
809
+ example: '2026-01-09T18:30:00Z'
810
+
811
+ Location:
812
+ type: object
813
+ nullable: true
814
+ properties:
815
+ city:
816
+ type: string
817
+ nullable: true
818
+ example: San Francisco
819
+ region:
820
+ type: string
821
+ nullable: true
822
+ example: CA
823
+ postal_code:
824
+ type: string
825
+ nullable: true
826
+ example: '94110'
827
+ country:
828
+ type: string
829
+ nullable: true
830
+ example: US
831
+
832
+ Snapshot:
833
+ type: object
834
+ required:
835
+ - id
836
+ - period_type
837
+ - period_start
838
+ - period_end
839
+ - snapshot_date
840
+ properties:
841
+ id:
842
+ type: string
843
+ format: uuid
844
+ description: Unique snapshot identifier
845
+ example: snap_1a2b3c4d-5e6f-7a8b-9c0d-1e2f3a4b5c6d
846
+ period_type:
847
+ type: string
848
+ enum: [daily, weekly, monthly]
849
+ description: Period granularity
850
+ example: daily
851
+ period_start:
852
+ type: string
853
+ format: date
854
+ description: Period start date
855
+ example: '2026-01-01'
856
+ period_end:
857
+ type: string
858
+ format: date
859
+ description: Period end date
860
+ example: '2026-01-31'
861
+ snapshot_date:
862
+ type: string
863
+ format: date
864
+ description: When snapshot was taken
865
+ example: '2026-01-10'
866
+ income:
867
+ type: number
868
+ description: Total income for period
869
+ example: 6500.00
870
+ expenses:
871
+ type: number
872
+ description: Total expenses for period
873
+ example: 4200.00
874
+ net_cash_flow:
875
+ type: number
876
+ description: Income minus expenses
877
+ example: 2300.00
878
+ savings_rate:
879
+ type: number
880
+ description: Percentage saved (0.0 to 1.0)
881
+ example: 0.35
882
+ net_worth:
883
+ type: number
884
+ description: Total assets minus liabilities
885
+ example: 45000.00
886
+ total_cash:
887
+ type: number
888
+ description: Sum of depository balances
889
+ example: 12500.00
890
+ total_debt:
891
+ type: number
892
+ description: Sum of credit/loan balances
893
+ example: 8500.00
894
+ investment_value:
895
+ type: number
896
+ description: Investment account value
897
+ example: 28000.00
898
+ asset_value:
899
+ type: number
900
+ description: Other asset values
901
+ example: 15000.00
902
+ burn_rate:
903
+ type: number
904
+ description: Average daily spending
905
+ example: 140.00
906
+ runway_days:
907
+ type: integer
908
+ description: Days of expenses covered by cash
909
+ example: 89
910
+ safe_to_spend:
911
+ type: number
912
+ description: Estimated discretionary spending available
913
+ example: 1800.00
914
+ recurring_total:
915
+ type: number
916
+ description: Sum of recurring expenses
917
+ example: 1250.00
918
+ spending_by_category:
919
+ type: array
920
+ items:
921
+ $ref: '#/components/schemas/CategorySpending'
922
+ top_merchants:
923
+ type: array
924
+ items:
925
+ $ref: '#/components/schemas/MerchantSpending'
926
+ income_vs_last_period:
927
+ type: number
928
+ description: Percentage change from previous period
929
+ example: 0.05
930
+ spending_vs_last_period:
931
+ type: number
932
+ description: Percentage change from previous period
933
+ example: -0.08
934
+ created_at:
935
+ type: string
936
+ format: date-time
937
+ updated_at:
938
+ type: string
939
+ format: date-time
940
+
941
+ CategorySpending:
942
+ type: object
943
+ properties:
944
+ category:
945
+ type: string
946
+ example: FOOD_AND_DRINK
947
+ amount:
948
+ type: number
949
+ example: 850.00
950
+ percentage:
951
+ type: number
952
+ example: 20.2
953
+
954
+ MerchantSpending:
955
+ type: object
956
+ properties:
957
+ merchant:
958
+ type: string
959
+ example: Whole Foods
960
+ amount:
961
+ type: number
962
+ example: 420.00
963
+ count:
964
+ type: integer
965
+ example: 8
966
+
967
+ Pagination:
968
+ type: object
969
+ properties:
970
+ limit:
971
+ type: integer
972
+ description: Transactions per page
973
+ example: 1000
974
+ next_cursor:
975
+ type: string
976
+ nullable: true
977
+ description: Token for next page (null if no more pages)
978
+ example: eyJkYXRlIjoiMjAyNi0wMS0wMSIsImlkIjoiYWJjMTIzIn0
979
+
980
+ RecurringStream:
981
+ type: object
982
+ properties:
983
+ id:
984
+ type: string
985
+ format: uuid
986
+ description: Unique stream identifier
987
+ example: cb3daddd-1f82-43ed-ba9f-60ecf8c937e3
988
+ stream_id:
989
+ type: string
990
+ description: External stream ID (from Plaid)
991
+ example: LN053MyLw9H9MQ5ybwrJim1Kj495gbsJ98aeM
992
+ account_id:
993
+ type: string
994
+ description: Account ID this stream belongs to
995
+ example: Dpnjw06KAJHYVmr5jqejimy4nE0OQJczvD8KD
996
+ stream_type:
997
+ type: string
998
+ enum: [inflow, outflow]
999
+ description: Direction of recurring payment
1000
+ example: outflow
1001
+ merchant_name:
1002
+ type: string
1003
+ description: Merchant or payee name
1004
+ example: Ting
1005
+ description:
1006
+ type: string
1007
+ description: Transaction description pattern
1008
+ example: 'TING* INV#MI-4636263'
1009
+ category:
1010
+ type: object
1011
+ properties:
1012
+ primary:
1013
+ type: string
1014
+ example: RENT_AND_UTILITIES
1015
+ detailed:
1016
+ type: string
1017
+ example: RENT_AND_UTILITIES_TELEPHONE
1018
+ confidence_level:
1019
+ type: string
1020
+ enum: [VERY_HIGH, HIGH, MEDIUM, LOW, UNKNOWN]
1021
+ frequency:
1022
+ type: string
1023
+ enum: [WEEKLY, BIWEEKLY, SEMI_MONTHLY, MONTHLY, ANNUALLY, UNKNOWN]
1024
+ description: Payment frequency
1025
+ example: MONTHLY
1026
+ average_amount:
1027
+ type: number
1028
+ description: Average transaction amount
1029
+ example: 118.98
1030
+ last_amount:
1031
+ type: number
1032
+ description: Most recent transaction amount
1033
+ example: 146.58
1034
+ is_active:
1035
+ type: boolean
1036
+ description: Whether stream is currently active
1037
+ example: true
1038
+ status:
1039
+ type: string
1040
+ enum: [MATURE, EARLY_DETECTION, TOMBSTONED]
1041
+ description: Detection status
1042
+ example: MATURE
1043
+ first_date:
1044
+ type: string
1045
+ format: date
1046
+ description: First detected transaction date
1047
+ example: '2025-07-15'
1048
+ last_date:
1049
+ type: string
1050
+ format: date
1051
+ description: Most recent transaction date
1052
+ example: '2025-09-15'
1053
+ next_date:
1054
+ type: string
1055
+ format: date
1056
+ description: Predicted next transaction date
1057
+ example: '2025-10-15'
1058
+ source:
1059
+ type: string
1060
+ enum: [plaid, user]
1061
+ description: How stream was detected
1062
+ example: plaid
1063
+
1064
+ Error:
1065
+ type: object
1066
+ required:
1067
+ - error
1068
+ properties:
1069
+ error:
1070
+ type: string
1071
+ description: Human-readable error message
1072
+ example: Invalid API key.
1073
+
1074
+ FinancialContext:
1075
+ type: object
1076
+ required:
1077
+ - version
1078
+ - updated_at
1079
+ - currency
1080
+ - status
1081
+ - transactions
1082
+ - recurring
1083
+ - budgets
1084
+ - goals
1085
+ - snapshots
1086
+ - liabilities
1087
+ - holdings
1088
+ - health
1089
+ properties:
1090
+ version:
1091
+ type: string
1092
+ enum: [v1]
1093
+ updated_at:
1094
+ type: string
1095
+ format: date-time
1096
+ description: Latest represented source-data freshness timestamp
1097
+ currency:
1098
+ type: string
1099
+ enum: [USD]
1100
+ status:
1101
+ $ref: '#/components/schemas/FinancialContextStatus'
1102
+ transactions:
1103
+ $ref: '#/components/schemas/TransactionIndex'
1104
+ recurring:
1105
+ type: array
1106
+ items:
1107
+ $ref: '#/components/schemas/FinancialContextRecurring'
1108
+ budgets:
1109
+ type: array
1110
+ items:
1111
+ $ref: '#/components/schemas/FinancialContextBudget'
1112
+ goals:
1113
+ type: array
1114
+ items:
1115
+ $ref: '#/components/schemas/FinancialContextGoal'
1116
+ snapshots:
1117
+ type: array
1118
+ items:
1119
+ $ref: '#/components/schemas/FinancialContextSnapshot'
1120
+ liabilities:
1121
+ type: array
1122
+ items:
1123
+ $ref: '#/components/schemas/FinancialContextLiability'
1124
+ holdings:
1125
+ type: array
1126
+ items:
1127
+ $ref: '#/components/schemas/FinancialContextHolding'
1128
+ health:
1129
+ oneOf:
1130
+ - $ref: '#/components/schemas/FinancialContextHealth'
1131
+ - type: 'null'
1132
+
1133
+ FinancialContextStatus:
1134
+ type: object
1135
+ required:
1136
+ - position
1137
+ - accounts
1138
+ properties:
1139
+ position:
1140
+ oneOf:
1141
+ - $ref: '#/components/schemas/FinancialContextPosition'
1142
+ - type: 'null'
1143
+ accounts:
1144
+ type: array
1145
+ items:
1146
+ $ref: '#/components/schemas/FinancialContextAccount'
1147
+
1148
+ FinancialContextPosition:
1149
+ type: object
1150
+ required:
1151
+ - date
1152
+ - net_worth
1153
+ - cash
1154
+ - debt
1155
+ - investments
1156
+ - other_assets
1157
+ - total_assets
1158
+ properties:
1159
+ date:
1160
+ type: string
1161
+ format: date
1162
+ nullable: true
1163
+ net_worth:
1164
+ type: number
1165
+ nullable: true
1166
+ cash:
1167
+ type: number
1168
+ nullable: true
1169
+ debt:
1170
+ type: number
1171
+ nullable: true
1172
+ investments:
1173
+ type: number
1174
+ nullable: true
1175
+ other_assets:
1176
+ type: number
1177
+ nullable: true
1178
+ total_assets:
1179
+ type: number
1180
+ nullable: true
1181
+
1182
+ FinancialContextAccount:
1183
+ type: object
1184
+ required:
1185
+ - id
1186
+ - name
1187
+ - type
1188
+ - subtype
1189
+ - group
1190
+ - institution
1191
+ - mask
1192
+ - balance
1193
+ - available
1194
+ - currency
1195
+ - updated_at
1196
+ properties:
1197
+ id:
1198
+ type: string
1199
+ name:
1200
+ type: string
1201
+ type:
1202
+ type: string
1203
+ enum: [depository, credit, loan, investment, brokerage, other]
1204
+ subtype:
1205
+ type: string
1206
+ nullable: true
1207
+ group:
1208
+ type: string
1209
+ enum: [cash, debt, investments]
1210
+ nullable: true
1211
+ institution:
1212
+ type: string
1213
+ nullable: true
1214
+ mask:
1215
+ type: string
1216
+ nullable: true
1217
+ balance:
1218
+ type: number
1219
+ nullable: true
1220
+ available:
1221
+ type: number
1222
+ nullable: true
1223
+ currency:
1224
+ type: string
1225
+ nullable: true
1226
+ updated_at:
1227
+ type: string
1228
+ format: date-time
1229
+ nullable: true
1230
+
1231
+ TransactionIndex:
1232
+ type: object
1233
+ required:
1234
+ - total
1235
+ - months
1236
+ properties:
1237
+ total:
1238
+ type: integer
1239
+ minimum: 0
1240
+ months:
1241
+ type: array
1242
+ items:
1243
+ type: object
1244
+ required:
1245
+ - month
1246
+ - count
1247
+ properties:
1248
+ month:
1249
+ type: string
1250
+ pattern: '^\d{4}-\d{2}$'
1251
+ count:
1252
+ type: integer
1253
+ minimum: 0
1254
+
1255
+ TransactionMonth:
1256
+ type: object
1257
+ required:
1258
+ - month
1259
+ - start_date
1260
+ - end_date
1261
+ - count
1262
+ - items
1263
+ properties:
1264
+ month:
1265
+ type: string
1266
+ pattern: '^\d{4}-\d{2}$'
1267
+ start_date:
1268
+ type: string
1269
+ format: date
1270
+ end_date:
1271
+ type: string
1272
+ format: date
1273
+ count:
1274
+ type: integer
1275
+ minimum: 0
1276
+ items:
1277
+ type: array
1278
+ items:
1279
+ $ref: '#/components/schemas/FinancialContextTransaction'
1280
+
1281
+ LatestTransactions:
1282
+ type: object
1283
+ required:
1284
+ - since
1285
+ - window_days
1286
+ - count
1287
+ - items
1288
+ properties:
1289
+ since:
1290
+ type: string
1291
+ format: date
1292
+ description: Inclusive lower bound for the latest transaction window
1293
+ window_days:
1294
+ type: integer
1295
+ enum: [10]
1296
+ count:
1297
+ type: integer
1298
+ minimum: 0
1299
+ items:
1300
+ type: array
1301
+ items:
1302
+ $ref: '#/components/schemas/FinancialContextTransaction'
1303
+
1304
+ FinancialContextTransaction:
1305
+ type: object
1306
+ required:
1307
+ - id
1308
+ - account_id
1309
+ - date
1310
+ - amount
1311
+ - merchant
1312
+ - name
1313
+ - category
1314
+ - subcategory
1315
+ - pending
1316
+ - currency
1317
+ properties:
1318
+ id:
1319
+ type: string
1320
+ account_id:
1321
+ type: string
1322
+ nullable: true
1323
+ date:
1324
+ type: string
1325
+ format: date
1326
+ nullable: true
1327
+ amount:
1328
+ type: number
1329
+ description: Amount (positive = expense/debit, negative = income/credit)
1330
+ merchant:
1331
+ type: string
1332
+ nullable: true
1333
+ name:
1334
+ type: string
1335
+ nullable: true
1336
+ category:
1337
+ type: string
1338
+ nullable: true
1339
+ subcategory:
1340
+ type: string
1341
+ nullable: true
1342
+ pending:
1343
+ type: boolean
1344
+ nullable: true
1345
+ currency:
1346
+ type: string
1347
+ nullable: true
1348
+
1349
+ FinancialContextRecurring:
1350
+ type: object
1351
+ required:
1352
+ - id
1353
+ - account_id
1354
+ - direction
1355
+ - frequency
1356
+ - status
1357
+ - merchant
1358
+ - amount
1359
+ - next_date
1360
+ properties:
1361
+ id:
1362
+ type: string
1363
+ account_id:
1364
+ type: string
1365
+ nullable: true
1366
+ direction:
1367
+ type: string
1368
+ enum: [inflow, outflow]
1369
+ nullable: true
1370
+ frequency:
1371
+ type: string
1372
+ enum: [WEEKLY, BIWEEKLY, MONTHLY, QUARTERLY, SEMI_ANNUALLY, ANNUALLY]
1373
+ nullable: true
1374
+ status:
1375
+ type: string
1376
+ enum: [active, inactive, dismissed]
1377
+ nullable: true
1378
+ merchant:
1379
+ type: string
1380
+ nullable: true
1381
+ amount:
1382
+ type: number
1383
+ nullable: true
1384
+ next_date:
1385
+ type: string
1386
+ format: date
1387
+ nullable: true
1388
+
1389
+ FinancialContextBudget:
1390
+ type: object
1391
+ required:
1392
+ - id
1393
+ - name
1394
+ - type
1395
+ - period
1396
+ - status
1397
+ - amount
1398
+ - spent
1399
+ - remaining
1400
+ - used_percent
1401
+ properties:
1402
+ id:
1403
+ type: string
1404
+ name:
1405
+ type: string
1406
+ type:
1407
+ type: string
1408
+ enum: [category, merchant]
1409
+ period:
1410
+ type: string
1411
+ enum: [weekly, biweekly, monthly]
1412
+ status:
1413
+ type: string
1414
+ enum: [under, warning, over]
1415
+ amount:
1416
+ type: number
1417
+ spent:
1418
+ type: number
1419
+ remaining:
1420
+ type: number
1421
+ used_percent:
1422
+ type: number
1423
+
1424
+ FinancialContextGoal:
1425
+ type: object
1426
+ required:
1427
+ - id
1428
+ - name
1429
+ - category
1430
+ - status
1431
+ - target
1432
+ - current
1433
+ - progress_percent
1434
+ - target_date
1435
+ properties:
1436
+ id:
1437
+ type: string
1438
+ name:
1439
+ type: string
1440
+ category:
1441
+ type: string
1442
+ status:
1443
+ type: string
1444
+ enum: [not_started, in_progress, on_track, behind, completed]
1445
+ target:
1446
+ type: number
1447
+ current:
1448
+ type: number
1449
+ progress_percent:
1450
+ type: number
1451
+ target_date:
1452
+ type: string
1453
+ format: date
1454
+ nullable: true
1455
+
1456
+ FinancialContextSnapshot:
1457
+ type: object
1458
+ required:
1459
+ - date
1460
+ - net_worth
1461
+ - cash
1462
+ - debt
1463
+ - income
1464
+ - expenses
1465
+ - cash_flow
1466
+ - savings_rate
1467
+ - investments
1468
+ - assets
1469
+ - health_score
1470
+ properties:
1471
+ date:
1472
+ type: string
1473
+ format: date
1474
+ net_worth:
1475
+ type: number
1476
+ nullable: true
1477
+ cash:
1478
+ type: number
1479
+ nullable: true
1480
+ debt:
1481
+ type: number
1482
+ nullable: true
1483
+ income:
1484
+ type: number
1485
+ nullable: true
1486
+ expenses:
1487
+ type: number
1488
+ nullable: true
1489
+ cash_flow:
1490
+ type: number
1491
+ nullable: true
1492
+ savings_rate:
1493
+ type: number
1494
+ nullable: true
1495
+ investments:
1496
+ type: number
1497
+ nullable: true
1498
+ assets:
1499
+ type: number
1500
+ nullable: true
1501
+ health_score:
1502
+ type: number
1503
+ nullable: true
1504
+
1505
+ FinancialContextLiability:
1506
+ type: object
1507
+ required:
1508
+ - account_id
1509
+ - type
1510
+ - balance
1511
+ - minimum_payment
1512
+ - due_date
1513
+ - interest_rate
1514
+ - rate_type
1515
+ - overdue
1516
+ properties:
1517
+ account_id:
1518
+ type: string
1519
+ nullable: true
1520
+ type:
1521
+ type: string
1522
+ enum: [credit, student, mortgage, other]
1523
+ nullable: true
1524
+ balance:
1525
+ type: number
1526
+ nullable: true
1527
+ minimum_payment:
1528
+ type: number
1529
+ nullable: true
1530
+ due_date:
1531
+ type: string
1532
+ format: date
1533
+ nullable: true
1534
+ interest_rate:
1535
+ type: number
1536
+ nullable: true
1537
+ rate_type:
1538
+ type: string
1539
+ enum: [fixed, variable]
1540
+ nullable: true
1541
+ overdue:
1542
+ type: boolean
1543
+ nullable: true
1544
+
1545
+ FinancialContextHolding:
1546
+ type: object
1547
+ required:
1548
+ - account_id
1549
+ - symbol
1550
+ - name
1551
+ - type
1552
+ - quantity
1553
+ - value
1554
+ - cost_basis
1555
+ properties:
1556
+ account_id:
1557
+ type: string
1558
+ nullable: true
1559
+ symbol:
1560
+ type: string
1561
+ nullable: true
1562
+ name:
1563
+ type: string
1564
+ nullable: true
1565
+ type:
1566
+ type: string
1567
+ enum: [cash, derivative, equity, etf, fixed_income, mutual_fund, other]
1568
+ nullable: true
1569
+ quantity:
1570
+ type: number
1571
+ nullable: true
1572
+ value:
1573
+ type: number
1574
+ nullable: true
1575
+ cost_basis:
1576
+ type: number
1577
+ nullable: true
1578
+
1579
+ FinancialContextHealth:
1580
+ type: object
1581
+ required:
1582
+ - score
1583
+ - label
1584
+ - level
1585
+ - summary
1586
+ - data_completeness
1587
+ - pillars
1588
+ properties:
1589
+ score:
1590
+ type: number
1591
+ label:
1592
+ type: string
1593
+ enum: [Needs Attention, Good, Strong]
1594
+ level:
1595
+ type: string
1596
+ enum: [critical, poor, fair, good, strong]
1597
+ summary:
1598
+ type: string
1599
+ data_completeness:
1600
+ type: number
1601
+ pillars:
1602
+ oneOf:
1603
+ - type: object
1604
+ required:
1605
+ - spend
1606
+ - save
1607
+ - borrow
1608
+ - build
1609
+ properties:
1610
+ spend:
1611
+ type: number
1612
+ nullable: true
1613
+ save:
1614
+ type: number
1615
+ nullable: true
1616
+ borrow:
1617
+ type: number
1618
+ nullable: true
1619
+ build:
1620
+ type: number
1621
+ nullable: true
1622
+ - type: 'null'
1623
+
1624
+ FinancialContextMeta:
1625
+ type: object
1626
+ required:
1627
+ - version
1628
+ - user_id
1629
+ - context_id
1630
+ - generated_at
1631
+ - updated_at
1632
+ - content_hash
1633
+ - byte_length
1634
+ - counts
1635
+ properties:
1636
+ version:
1637
+ type: string
1638
+ enum: [v1]
1639
+ user_id:
1640
+ type: string
1641
+ context_id:
1642
+ type: string
1643
+ generated_at:
1644
+ type: string
1645
+ format: date-time
1646
+ updated_at:
1647
+ type: string
1648
+ format: date-time
1649
+ description: Latest represented source-data freshness timestamp
1650
+ content_hash:
1651
+ type: string
1652
+ description: Opaque artifact version token and ETag value. This is the only public artifact version token.
1653
+ byte_length:
1654
+ type: integer
1655
+ minimum: 0
1656
+ counts:
1657
+ type: object
1658
+ required:
1659
+ - accounts
1660
+ - transaction_months
1661
+ - transactions
1662
+ - snapshots
1663
+ properties:
1664
+ accounts:
1665
+ type: integer
1666
+ minimum: 0
1667
+ transaction_months:
1668
+ type: integer
1669
+ minimum: 0
1670
+ transactions:
1671
+ type: integer
1672
+ minimum: 0
1673
+ snapshots:
1674
+ type: integer
1675
+ minimum: 0
1676
+
1677
+ tags:
1678
+ - name: Export
1679
+ description: Export financial data as structured JSON