@serviceai/api-spec 1.2.433 → 1.6.1

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 (4) hide show
  1. package/openapi.json +2415 -141
  2. package/openapi.yaml +1837 -172
  3. package/package.json +1 -1
  4. package/types.d.ts +1033 -68
package/openapi.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  openapi: 3.1.0
2
2
  info:
3
3
  title: ServiceAi API
4
- version: 1.2.433
4
+ version: 1.6.1
5
5
  description: >-
6
6
  Source-of-truth API contract for ServiceAi. Generated from `shared/schema.ts` Zod schemas by
7
7
  `scripts/build-api-spec.ts`. Versioning policy: see `docs/api-versioning.md`. The hand-written docs/ios-contract.md
@@ -32,6 +32,8 @@ tags:
32
32
  description: Job (project) lifecycle surface.
33
33
  - name: chatty
34
34
  description: Realtime voice-enabled AI assistant.
35
+ - name: checklists
36
+ description: 'Job checklists: the voice walk-through draft.'
35
37
  - name: time-tracking
36
38
  description: >-
37
39
  The clock. A work day is the master clock and the payroll number; time entries sit inside it and say where the
@@ -44,6 +46,18 @@ tags:
44
46
  - name: account
45
47
  description: 'The signed-in person''s own account: asking for it to be deleted.'
46
48
  components:
49
+ securitySchemes:
50
+ UserBearer:
51
+ type: http
52
+ scheme: bearer
53
+ BrowserSession:
54
+ type: apiKey
55
+ in: cookie
56
+ name: connect.sid
57
+ BrowserAuthCookie:
58
+ type: apiKey
59
+ in: cookie
60
+ name: auth_token
47
61
  schemas:
48
62
  ErrorEnvelope:
49
63
  type: object
@@ -89,7 +103,7 @@ components:
89
103
  properties:
90
104
  apiVersion:
91
105
  type: string
92
- example: 1.2.433
106
+ example: 1.6.1
93
107
  minClientVersion:
94
108
  type: string
95
109
  example: 1.0.0
@@ -164,11 +178,11 @@ components:
164
178
  additionalProperties: {}
165
179
  - type: array
166
180
  items: {}
167
- - type: 'null'
168
181
  lastContactDate:
169
182
  type:
170
183
  - string
171
184
  - 'null'
185
+ format: date-time
172
186
  parentContactId:
173
187
  type:
174
188
  - integer
@@ -281,6 +295,7 @@ components:
281
295
  type:
282
296
  - string
283
297
  - 'null'
298
+ format: date-time
284
299
  qboLastPushedHash:
285
300
  type:
286
301
  - string
@@ -293,6 +308,7 @@ components:
293
308
  type:
294
309
  - string
295
310
  - 'null'
311
+ format: date-time
296
312
  deletedBy:
297
313
  type:
298
314
  - string
@@ -432,7 +448,6 @@ components:
432
448
  additionalProperties: {}
433
449
  - type: array
434
450
  items: {}
435
- - type: 'null'
436
451
  featureTier:
437
452
  type:
438
453
  - string
@@ -447,7 +462,6 @@ components:
447
462
  additionalProperties: {}
448
463
  - type: array
449
464
  items: {}
450
- - type: 'null'
451
465
  parentScanId:
452
466
  type:
453
467
  - integer
@@ -464,7 +478,6 @@ components:
464
478
  additionalProperties: {}
465
479
  - type: array
466
480
  items: {}
467
- - type: 'null'
468
481
  doorwayLinks:
469
482
  anyOf:
470
483
  - type: string
@@ -475,7 +488,6 @@ components:
475
488
  additionalProperties: {}
476
489
  - type: array
477
490
  items: {}
478
- - type: 'null'
479
491
  description: >-
480
492
  Persisted append-room doorway links on a composite scan. Each link carries both a `sourceOpeningKind` (the
481
493
  appended child scan's entry side — always `door` in practice, since iOS does not capture openings on a
@@ -493,7 +505,6 @@ components:
493
505
  additionalProperties: {}
494
506
  - type: array
495
507
  items: {}
496
- - type: 'null'
497
508
  cleanupPipelineVersion:
498
509
  type:
499
510
  - string
@@ -516,7 +527,6 @@ components:
516
527
  additionalProperties: {}
517
528
  - type: array
518
529
  items: {}
519
- - type: 'null'
520
530
  deviceTrack:
521
531
  anyOf:
522
532
  - type: string
@@ -527,15 +537,12 @@ components:
527
537
  additionalProperties: {}
528
538
  - type: array
529
539
  items: {}
530
- - type: 'null'
531
540
  referencePhotoKeys:
532
541
  type:
533
542
  - array
534
543
  - 'null'
535
544
  items:
536
- type:
537
- - string
538
- - 'null'
545
+ type: string
539
546
  metricCorrection:
540
547
  type:
541
548
  - number
@@ -566,6 +573,7 @@ components:
566
573
  type:
567
574
  - string
568
575
  - 'null'
576
+ format: date-time
569
577
  captureMode:
570
578
  type:
571
579
  - string
@@ -580,6 +588,12 @@ components:
580
588
  type:
581
589
  - string
582
590
  - 'null'
591
+ format: date-time
592
+ clientScanId:
593
+ type:
594
+ - string
595
+ - 'null'
596
+ maxLength: 64
583
597
  floorPlanAssetId:
584
598
  type:
585
599
  - string
@@ -614,6 +628,42 @@ components:
614
628
  - 'null'
615
629
  minimum: -2147483648
616
630
  maximum: 2147483647
631
+ sourceSketchId:
632
+ type:
633
+ - integer
634
+ - 'null'
635
+ minimum: -2147483648
636
+ maximum: 2147483647
637
+ takeoffPagePixelsPerMeter:
638
+ type:
639
+ - number
640
+ - 'null'
641
+ minimum: -140737488355328
642
+ maximum: 140737488355327
643
+ takeoffPageOffsetX:
644
+ type:
645
+ - number
646
+ - 'null'
647
+ minimum: -140737488355328
648
+ maximum: 140737488355327
649
+ takeoffPageOffsetY:
650
+ type:
651
+ - number
652
+ - 'null'
653
+ minimum: -140737488355328
654
+ maximum: 140737488355327
655
+ takeoffPageWidthPx:
656
+ type:
657
+ - integer
658
+ - 'null'
659
+ minimum: -2147483648
660
+ maximum: 2147483647
661
+ takeoffPageHeightPx:
662
+ type:
663
+ - integer
664
+ - 'null'
665
+ minimum: -2147483648
666
+ maximum: 2147483647
617
667
  floorId:
618
668
  type:
619
669
  - integer
@@ -632,6 +682,7 @@ components:
632
682
  type:
633
683
  - string
634
684
  - 'null'
685
+ format: date-time
635
686
  deletedBy:
636
687
  type:
637
688
  - string
@@ -687,10 +738,12 @@ components:
687
738
  type:
688
739
  - string
689
740
  - 'null'
741
+ format: date-time
690
742
  dueDate:
691
743
  type:
692
744
  - string
693
745
  - 'null'
746
+ format: date-time
694
747
  allDay:
695
748
  type:
696
749
  - boolean
@@ -713,7 +766,6 @@ components:
713
766
  additionalProperties: {}
714
767
  - type: array
715
768
  items: {}
716
- - type: 'null'
717
769
  assignedContactIds:
718
770
  anyOf:
719
771
  - type: string
@@ -724,7 +776,6 @@ components:
724
776
  additionalProperties: {}
725
777
  - type: array
726
778
  items: {}
727
- - type: 'null'
728
779
  isPersonal:
729
780
  type:
730
781
  - boolean
@@ -745,7 +796,6 @@ components:
745
796
  additionalProperties: {}
746
797
  - type: array
747
798
  items: {}
748
- - type: 'null'
749
799
  relatedFiles:
750
800
  anyOf:
751
801
  - type: string
@@ -756,7 +806,6 @@ components:
756
806
  additionalProperties: {}
757
807
  - type: array
758
808
  items: {}
759
- - type: 'null'
760
809
  reminder:
761
810
  type:
762
811
  - string
@@ -769,6 +818,7 @@ components:
769
818
  - 1_hour
770
819
  - 1_day
771
820
  - 1_week
821
+ - null
772
822
  reminderNotificationId:
773
823
  type:
774
824
  - integer
@@ -793,6 +843,7 @@ components:
793
843
  type:
794
844
  - string
795
845
  - 'null'
846
+ format: date-time
796
847
  parentTaskId:
797
848
  type:
798
849
  - integer
@@ -803,6 +854,7 @@ components:
803
854
  type:
804
855
  - string
805
856
  - 'null'
857
+ format: date-time
806
858
  isRecurrenceException:
807
859
  type:
808
860
  - boolean
@@ -817,7 +869,6 @@ components:
817
869
  additionalProperties: {}
818
870
  - type: array
819
871
  items: {}
820
- - type: 'null'
821
872
  displayIndex:
822
873
  type:
823
874
  - integer
@@ -828,6 +879,7 @@ components:
828
879
  type:
829
880
  - string
830
881
  - 'null'
882
+ format: date-time
831
883
  deletedBy:
832
884
  type:
833
885
  - string
@@ -865,6 +917,7 @@ components:
865
917
  type:
866
918
  - string
867
919
  - 'null'
920
+ format: date-time
868
921
  deletedBy:
869
922
  type:
870
923
  - string
@@ -916,15 +969,12 @@ components:
916
969
  additionalProperties: {}
917
970
  - type: array
918
971
  items: {}
919
- - type: 'null'
920
972
  tags:
921
973
  type:
922
974
  - array
923
975
  - 'null'
924
976
  items:
925
- type:
926
- - string
927
- - 'null'
977
+ type: string
928
978
  uploadedBy:
929
979
  type:
930
980
  - string
@@ -933,6 +983,7 @@ components:
933
983
  type:
934
984
  - string
935
985
  - 'null'
986
+ format: date-time
936
987
  deletedBy:
937
988
  type:
938
989
  - string
@@ -971,6 +1022,7 @@ components:
971
1022
  type:
972
1023
  - string
973
1024
  - 'null'
1025
+ format: date-time
974
1026
  deletedBy:
975
1027
  type:
976
1028
  - string
@@ -1063,7 +1115,6 @@ components:
1063
1115
  additionalProperties: {}
1064
1116
  - type: array
1065
1117
  items: {}
1066
- - type: 'null'
1067
1118
  terms:
1068
1119
  type:
1069
1120
  - string
@@ -1080,14 +1131,17 @@ components:
1080
1131
  type:
1081
1132
  - string
1082
1133
  - 'null'
1134
+ format: date-time
1083
1135
  sentAt:
1084
1136
  type:
1085
1137
  - string
1086
1138
  - 'null'
1139
+ format: date-time
1087
1140
  approvedAt:
1088
1141
  type:
1089
1142
  - string
1090
1143
  - 'null'
1144
+ format: date-time
1091
1145
  approvedBy:
1092
1146
  type:
1093
1147
  - string
@@ -1096,6 +1150,7 @@ components:
1096
1150
  type:
1097
1151
  - string
1098
1152
  - 'null'
1153
+ format: date-time
1099
1154
  rejectionReason:
1100
1155
  type:
1101
1156
  - string
@@ -1104,6 +1159,7 @@ components:
1104
1159
  type:
1105
1160
  - string
1106
1161
  - 'null'
1162
+ format: date-time
1107
1163
  signatureMeta:
1108
1164
  anyOf:
1109
1165
  - type: string
@@ -1114,7 +1170,6 @@ components:
1114
1170
  additionalProperties: {}
1115
1171
  - type: array
1116
1172
  items: {}
1117
- - type: 'null'
1118
1173
  signatureProvider:
1119
1174
  type:
1120
1175
  - string
@@ -1139,6 +1194,7 @@ components:
1139
1194
  type:
1140
1195
  - string
1141
1196
  - 'null'
1197
+ format: date-time
1142
1198
  revisionNotes:
1143
1199
  type:
1144
1200
  - string
@@ -1147,6 +1203,7 @@ components:
1147
1203
  type:
1148
1204
  - string
1149
1205
  - 'null'
1206
+ format: date-time
1150
1207
  convertedToInvoiceId:
1151
1208
  type:
1152
1209
  - integer
@@ -1157,6 +1214,7 @@ components:
1157
1214
  type:
1158
1215
  - string
1159
1216
  - 'null'
1217
+ format: date-time
1160
1218
  voidedBy:
1161
1219
  type:
1162
1220
  - string
@@ -1189,6 +1247,7 @@ components:
1189
1247
  type:
1190
1248
  - string
1191
1249
  - 'null'
1250
+ format: date-time
1192
1251
  qboId:
1193
1252
  type:
1194
1253
  - string
@@ -1201,6 +1260,7 @@ components:
1201
1260
  type:
1202
1261
  - string
1203
1262
  - 'null'
1263
+ format: date-time
1204
1264
  qboLastPushedHash:
1205
1265
  type:
1206
1266
  - string
@@ -1221,6 +1281,17 @@ components:
1221
1281
  type:
1222
1282
  - string
1223
1283
  - 'null'
1284
+ format: date-time
1285
+ sourceKind:
1286
+ type:
1287
+ - string
1288
+ - 'null'
1289
+ takeoffScanId:
1290
+ type:
1291
+ - integer
1292
+ - 'null'
1293
+ minimum: -2147483648
1294
+ maximum: 2147483647
1224
1295
  createdBy:
1225
1296
  type:
1226
1297
  - string
@@ -1229,6 +1300,7 @@ components:
1229
1300
  type:
1230
1301
  - string
1231
1302
  - 'null'
1303
+ format: date-time
1232
1304
  deletedBy:
1233
1305
  type:
1234
1306
  - string
@@ -1342,8 +1414,10 @@ components:
1342
1414
  type: boolean
1343
1415
  isOpening:
1344
1416
  type: boolean
1417
+ additionalProperties: {}
1345
1418
  captureMethod:
1346
1419
  type: string
1420
+ additionalProperties: {}
1347
1421
  doors:
1348
1422
  type: array
1349
1423
  items:
@@ -1365,6 +1439,10 @@ components:
1365
1439
  height:
1366
1440
  type: number
1367
1441
  exclusiveMinimum: 0
1442
+ sillHeightM:
1443
+ type: number
1444
+ minimum: 0
1445
+ maximum: 50
1368
1446
  hostWallIndex:
1369
1447
  type:
1370
1448
  - integer
@@ -1375,13 +1453,13 @@ components:
1375
1453
  minimum: 0
1376
1454
  swingHand:
1377
1455
  type: string
1378
- enum: &ref_0
1456
+ enum:
1379
1457
  - left
1380
1458
  - right
1381
1459
  - none
1382
1460
  placementSource:
1383
1461
  type: string
1384
- enum: &ref_1
1462
+ enum:
1385
1463
  - auto
1386
1464
  - manual
1387
1465
  required:
@@ -1409,6 +1487,10 @@ components:
1409
1487
  height:
1410
1488
  type: number
1411
1489
  exclusiveMinimum: 0
1490
+ sillHeightM:
1491
+ type: number
1492
+ minimum: 0
1493
+ maximum: 50
1412
1494
  hostWallIndex:
1413
1495
  type:
1414
1496
  - integer
@@ -1419,10 +1501,15 @@ components:
1419
1501
  minimum: 0
1420
1502
  swingHand:
1421
1503
  type: string
1422
- enum: *ref_0
1504
+ enum:
1505
+ - left
1506
+ - right
1507
+ - none
1423
1508
  placementSource:
1424
1509
  type: string
1425
- enum: *ref_1
1510
+ enum:
1511
+ - auto
1512
+ - manual
1426
1513
  required:
1427
1514
  - position
1428
1515
  - width
@@ -1448,6 +1535,10 @@ components:
1448
1535
  height:
1449
1536
  type: number
1450
1537
  exclusiveMinimum: 0
1538
+ sillHeightM:
1539
+ type: number
1540
+ minimum: 0
1541
+ maximum: 50
1451
1542
  hostWallIndex:
1452
1543
  type:
1453
1544
  - integer
@@ -1458,10 +1549,15 @@ components:
1458
1549
  minimum: 0
1459
1550
  swingHand:
1460
1551
  type: string
1461
- enum: *ref_0
1552
+ enum:
1553
+ - left
1554
+ - right
1555
+ - none
1462
1556
  placementSource:
1463
1557
  type: string
1464
- enum: *ref_1
1558
+ enum:
1559
+ - auto
1560
+ - manual
1465
1561
  required:
1466
1562
  - position
1467
1563
  - width
@@ -1500,6 +1596,7 @@ components:
1500
1596
  required:
1501
1597
  - id
1502
1598
  - position
1599
+ additionalProperties: {}
1503
1600
  objects:
1504
1601
  type: array
1505
1602
  items:
@@ -1528,6 +1625,7 @@ components:
1528
1625
  type: number
1529
1626
  rotation:
1530
1627
  type: number
1628
+ additionalProperties: {}
1531
1629
  boundaryPolygon:
1532
1630
  type: array
1533
1631
  items:
@@ -1545,6 +1643,7 @@ components:
1545
1643
  maxLength: 4096
1546
1644
  entryDoorwayId:
1547
1645
  type: string
1646
+ additionalProperties: {}
1548
1647
  description: >-
1549
1648
  Mobile-upload scan room. `doors`, `windows`, and `openings` are three distinct non-overlapping arrays
1550
1649
  — array membership IS the discriminator (there is no `kind` / `type` field on the item itself).
@@ -1554,6 +1653,7 @@ components:
1554
1653
  an `entryDoorwayId` target.
1555
1654
  required:
1556
1655
  - rooms
1656
+ additionalProperties: {}
1557
1657
  description: >-
1558
1658
  RoomPlan JSON envelope. `rooms[]` carries the per-room geometry
1559
1659
  (walls/doors/windows/openings/pins/objects/boundaryPolygon). iOS continues to upload positions in the
@@ -1701,6 +1801,7 @@ components:
1701
1801
  required:
1702
1802
  - roomPlanJSON
1703
1803
  - name
1804
+ additionalProperties: {}
1704
1805
  description: >-
1705
1806
  POST /api/jobs/:jobId/scans/mobile-upload body. v5 of the LiDAR contract (Task #879) — additive over v3/v4.
1706
1807
  Required: `roomPlanJSON` (object with nested `rooms` array) + `name`. All v3 and v4 payloads remain accepted
@@ -1755,6 +1856,29 @@ components:
1755
1856
  - manualMeasurements
1756
1857
  - scanRoomSnapshots
1757
1858
  - roomConnections
1859
+ EventStreamTicketResponse:
1860
+ type: object
1861
+ properties:
1862
+ ticket:
1863
+ type: string
1864
+ minLength: 1
1865
+ maxLength: 8192
1866
+ required:
1867
+ - ticket
1868
+ additionalProperties: false
1869
+ StreamAuthenticationError:
1870
+ type: object
1871
+ properties:
1872
+ message:
1873
+ type: string
1874
+ code:
1875
+ type: string
1876
+ enum:
1877
+ - IMPERSONATION_UNAVAILABLE
1878
+ - SUPPORT_IMPERSONATION_UNAVAILABLE
1879
+ - auth_unavailable
1880
+ required:
1881
+ - message
1758
1882
  JobSummary:
1759
1883
  type: object
1760
1884
  properties:
@@ -2174,7 +2298,7 @@ components:
2174
2298
  description: Null at the office — see siteType.
2175
2299
  siteType:
2176
2300
  type: string
2177
- enum: &ref_2
2301
+ enum:
2178
2302
  - job
2179
2303
  - office
2180
2304
  workDayId:
@@ -2213,8 +2337,8 @@ components:
2213
2337
  - 'null'
2214
2338
  source:
2215
2339
  type: string
2216
- description: '''manual'' (a button press) or ''auto'' (the resolver).'
2217
2340
  example: auto
2341
+ description: '''manual'' (a button press) or ''auto'' (the resolver).'
2218
2342
  excludedFromBudget:
2219
2343
  type: boolean
2220
2344
  description: >-
@@ -2263,6 +2387,7 @@ components:
2263
2387
  enum:
2264
2388
  - away
2265
2389
  - no_location
2390
+ - null
2266
2391
  description: >-
2267
2392
  Job time started by hand away from the job ('away') or with no usable location ('no_location'); null for a
2268
2393
  normal start. The office decides it.
@@ -2279,6 +2404,7 @@ components:
2279
2404
  - approved
2280
2405
  - not_approved
2281
2406
  - moved
2407
+ - null
2282
2408
  description: >-
2283
2409
  The office's decision on a flagged start; null while it waits. 'not_approved' stays on the timesheet but off
2284
2410
  the job's costing.
@@ -2379,8 +2505,8 @@ components:
2379
2505
  description: Null while the day is running.
2380
2506
  openedBy:
2381
2507
  type: string
2382
- description: '''tech'' (the button), ''admin'', or ''job_clock_in''.'
2383
2508
  example: tech
2509
+ description: '''tech'' (the button), ''admin'', or ''job_clock_in''.'
2384
2510
  closedBy:
2385
2511
  type:
2386
2512
  - string
@@ -2685,7 +2811,9 @@ components:
2685
2811
  description: Null for the office fence (siteType 'office').
2686
2812
  siteType:
2687
2813
  type: string
2688
- enum: *ref_2
2814
+ enum:
2815
+ - job
2816
+ - office
2689
2817
  jobName:
2690
2818
  type: string
2691
2819
  jobNumber:
@@ -2752,7 +2880,9 @@ components:
2752
2880
  - 'null'
2753
2881
  siteType:
2754
2882
  type: string
2755
- enum: *ref_2
2883
+ enum:
2884
+ - job
2885
+ - office
2756
2886
  description: Defaults to 'office' when jobId is null, else 'job'.
2757
2887
  kind:
2758
2888
  type: string
@@ -2788,10 +2918,11 @@ components:
2788
2918
  type:
2789
2919
  - string
2790
2920
  - 'null'
2791
- enum: &ref_5
2921
+ enum:
2792
2922
  - ios
2793
2923
  - web
2794
2924
  - android
2925
+ - null
2795
2926
  autoClockEnabled:
2796
2927
  type: boolean
2797
2928
  description: The user's auto-clock toggle at crossing time. False → the crossing is logged but never acted on.
@@ -2843,8 +2974,8 @@ components:
2843
2974
  type:
2844
2975
  - string
2845
2976
  - 'null'
2846
- description: Why the batch was dropped. On 'no_consent' the client should clear its queue rather than retry.
2847
2977
  example: no_consent
2978
+ description: Why the batch was dropped. On 'no_consent' the client should clear its queue rather than retry.
2848
2979
  resolver:
2849
2980
  type:
2850
2981
  - object
@@ -2894,16 +3025,16 @@ components:
2894
3025
  type: boolean
2895
3026
  dwellSeconds:
2896
3027
  type: integer
2897
- description: >-
2898
- How long a device must stay on one side of a fence before it counts. A choice from a fixed set of steps, not
2899
- a free number: a tech driving past a job must not be clocked in, and one walking in must not wait. An older
2900
- org may still have a free value stored; the server snaps it to the nearest step, so read this value rather
2901
- than assuming what was configured.
2902
3028
  enum:
2903
3029
  - 30
2904
3030
  - 60
2905
3031
  - 100
2906
3032
  - 120
3033
+ description: >-
3034
+ How long a device must stay on one side of a fence before it counts. A choice from a fixed set of steps, not
3035
+ a free number: a tech driving past a job must not be clocked in, and one walking in must not wait. An older
3036
+ org may still have a free value stored; the server snaps it to the nearest step, so read this value rather
3037
+ than assuming what was configured.
2907
3038
  staleShiftHours:
2908
3039
  type: integer
2909
3040
  autoCloseHours:
@@ -3045,14 +3176,14 @@ components:
3045
3176
  type:
3046
3177
  - string
3047
3178
  - 'null'
3048
- description: '''HH:MM'' local. Null = all day, and always null for ''off'' and ''pto''.'
3049
3179
  example: '08:00'
3180
+ description: '''HH:MM'' local. Null = all day, and always null for ''off'' and ''pto''.'
3050
3181
  endTime:
3051
3182
  type:
3052
3183
  - string
3053
3184
  - 'null'
3054
- description: An end at or before the start means the shift runs overnight into the next day.
3055
3185
  example: '17:00'
3186
+ description: An end at or before the start means the shift runs overnight into the next day.
3056
3187
  kind:
3057
3188
  type: string
3058
3189
  enum:
@@ -3115,7 +3246,7 @@ components:
3115
3246
  - rejected
3116
3247
  kind:
3117
3248
  type: string
3118
- enum: &ref_7
3249
+ enum:
3119
3250
  - pto
3120
3251
  - sick
3121
3252
  - 'off'
@@ -3323,82 +3454,1317 @@ components:
3323
3454
  description: >-
3324
3455
  The signed-in person's request to have their account deleted. pending: waiting for the company; completed: the
3325
3456
  company marked it done; cancelled: the company cancelled it (asking again starts a new one).
3326
- parameters: {}
3327
- paths:
3328
- /api/version:
3329
- get:
3330
- summary: Cross-platform version handshake manifest.
3331
- tags:
3332
- - version
3333
- responses:
3334
- '200':
3335
- description: Always returned. Body is the canonical handshake manifest.
3336
- content:
3337
- application/json:
3338
- schema:
3339
- $ref: '#/components/schemas/VersionManifest'
3340
- /api/ping:
3341
- get:
3342
- summary: Liveness probe. Bypasses the version handshake.
3343
- tags:
3344
- - version
3345
- responses:
3346
- '200':
3347
- description: Static OK envelope.
3457
+ DoorwayEditCommand:
3458
+ oneOf:
3459
+ - type: object
3460
+ properties:
3461
+ action:
3462
+ type: string
3463
+ enum:
3464
+ - delete
3465
+ roomId:
3466
+ type: integer
3467
+ exclusiveMinimum: 0
3468
+ openingId:
3469
+ type: string
3470
+ pattern: ^[A-Za-z0-9:_-]{1,128}$
3471
+ revision:
3472
+ type: string
3473
+ pattern: ^[a-f0-9]{64}$
3474
+ confirmed:
3475
+ type: boolean
3476
+ enum:
3477
+ - true
3478
+ required:
3479
+ - action
3480
+ - roomId
3481
+ - openingId
3482
+ - revision
3483
+ - confirmed
3484
+ additionalProperties: false
3485
+ - type: object
3486
+ properties:
3487
+ action:
3488
+ type: string
3489
+ enum:
3490
+ - undo
3491
+ token:
3492
+ type: string
3493
+ minLength: 1
3494
+ maxLength: 1500100
3495
+ required:
3496
+ - action
3497
+ - token
3498
+ additionalProperties: false
3499
+ - type: object
3500
+ properties:
3501
+ action:
3502
+ type: string
3503
+ enum:
3504
+ - connect
3505
+ rooms:
3506
+ type: array
3507
+ items:
3508
+ type: object
3509
+ properties:
3510
+ id:
3511
+ type: integer
3512
+ exclusiveMinimum: 0
3513
+ revision:
3514
+ type: string
3515
+ pattern: ^[a-f0-9]{64}$
3516
+ geometry:
3517
+ type: object
3518
+ additionalProperties: {}
3519
+ required:
3520
+ - id
3521
+ - revision
3522
+ - geometry
3523
+ additionalProperties: false
3524
+ links:
3525
+ type: array
3526
+ items:
3527
+ type: object
3528
+ properties:
3529
+ roomAId:
3530
+ type: integer
3531
+ exclusiveMinimum: 0
3532
+ roomBId:
3533
+ type: integer
3534
+ exclusiveMinimum: 0
3535
+ doorAIndex:
3536
+ type: integer
3537
+ minimum: 0
3538
+ maximum: 63
3539
+ doorBIndex:
3540
+ type: integer
3541
+ minimum: 0
3542
+ maximum: 63
3543
+ required:
3544
+ - roomAId
3545
+ - roomBId
3546
+ - doorAIndex
3547
+ - doorBIndex
3548
+ additionalProperties: false
3549
+ minItems: 1
3550
+ maxItems: 64
3551
+ required:
3552
+ - action
3553
+ - rooms
3554
+ - links
3555
+ additionalProperties: false
3556
+ DoorwayEditResult:
3557
+ type: object
3558
+ properties:
3559
+ ok:
3560
+ type: boolean
3561
+ enum:
3562
+ - true
3563
+ token:
3564
+ type: string
3565
+ roomIds:
3566
+ type: array
3567
+ items:
3568
+ type: integer
3569
+ required:
3570
+ - ok
3571
+ - token
3572
+ - roomIds
3573
+ WalkthroughDraftRequest:
3574
+ type: object
3575
+ properties:
3576
+ transcript:
3577
+ type: array
3578
+ items:
3579
+ type: object
3580
+ properties:
3581
+ text:
3582
+ type: string
3583
+ minLength: 1
3584
+ maxLength: 1000
3585
+ startedAt:
3586
+ type: string
3587
+ format: date-time
3588
+ endedAt:
3589
+ type: string
3590
+ format: date-time
3591
+ required:
3592
+ - text
3593
+ - startedAt
3594
+ - endedAt
3595
+ minItems: 1
3596
+ maxItems: 400
3597
+ photos:
3598
+ type: array
3599
+ items:
3600
+ type: object
3601
+ properties:
3602
+ assetId:
3603
+ type: string
3604
+ minLength: 1
3605
+ maxLength: 64
3606
+ capturedAt:
3607
+ type: string
3608
+ format: date-time
3609
+ roomHint:
3610
+ type:
3611
+ - string
3612
+ - 'null'
3613
+ maxLength: 200
3614
+ sketchRoomId:
3615
+ type:
3616
+ - integer
3617
+ - 'null'
3618
+ exclusiveMinimum: 0
3619
+ capturePose:
3620
+ type:
3621
+ - object
3622
+ - 'null'
3623
+ properties:
3624
+ x:
3625
+ type: number
3626
+ 'y':
3627
+ type: number
3628
+ z:
3629
+ type: number
3630
+ floorId:
3631
+ type:
3632
+ - integer
3633
+ - 'null'
3634
+ exclusiveMinimum: 0
3635
+ sketchId:
3636
+ type:
3637
+ - integer
3638
+ - 'null'
3639
+ exclusiveMinimum: 0
3640
+ scanSessionId:
3641
+ type: string
3642
+ maxLength: 64
3643
+ scanRoomLocalId:
3644
+ type: string
3645
+ maxLength: 128
3646
+ scanRoomName:
3647
+ type: string
3648
+ maxLength: 200
3649
+ required:
3650
+ - assetId
3651
+ - capturedAt
3652
+ maxItems: 200
3653
+ sections:
3654
+ type: array
3655
+ items:
3656
+ type: object
3657
+ properties:
3658
+ name:
3659
+ type: string
3660
+ minLength: 1
3661
+ maxLength: 200
3662
+ startedAt:
3663
+ type: string
3664
+ format: date-time
3665
+ sketchRoomId:
3666
+ type:
3667
+ - integer
3668
+ - 'null'
3669
+ exclusiveMinimum: 0
3670
+ required:
3671
+ - name
3672
+ - startedAt
3673
+ maxItems: 100
3674
+ roomsFrom:
3675
+ type: string
3676
+ enum:
3677
+ - speech
3678
+ - scan
3679
+ required:
3680
+ - transcript
3681
+ ChecklistDraft:
3682
+ type: object
3683
+ properties:
3684
+ name:
3685
+ type: string
3686
+ sections:
3687
+ type: array
3688
+ items:
3689
+ type: object
3690
+ properties:
3691
+ key:
3692
+ type: string
3693
+ title:
3694
+ type: string
3695
+ sketchRoomId:
3696
+ type:
3697
+ - integer
3698
+ - 'null'
3699
+ kind:
3700
+ type: string
3701
+ enum:
3702
+ - room
3703
+ - custom
3704
+ - not_sure
3705
+ items:
3706
+ type: array
3707
+ items:
3708
+ type: object
3709
+ properties:
3710
+ key:
3711
+ type: string
3712
+ itemText:
3713
+ type: string
3714
+ description:
3715
+ type:
3716
+ - string
3717
+ - 'null'
3718
+ itemType:
3719
+ type: string
3720
+ enum:
3721
+ - checkbox
3722
+ - yes/no
3723
+ - text
3724
+ - number
3725
+ - date
3726
+ - dropdown
3727
+ - multi-select
3728
+ - photo
3729
+ - signature
3730
+ required:
3731
+ type: boolean
3732
+ options:
3733
+ type:
3734
+ - object
3735
+ - 'null'
3736
+ additionalProperties: {}
3737
+ referenceMedia:
3738
+ type: array
3739
+ items:
3740
+ type: object
3741
+ properties:
3742
+ assetId:
3743
+ type: string
3744
+ minLength: 1
3745
+ maxLength: 64
3746
+ caption:
3747
+ type:
3748
+ - string
3749
+ - 'null'
3750
+ maxLength: 300
3751
+ order:
3752
+ type: integer
3753
+ minimum: 0
3754
+ required:
3755
+ - assetId
3756
+ maxItems: 10
3757
+ hints:
3758
+ type: array
3759
+ items:
3760
+ type: string
3761
+ enum:
3762
+ - photo_required
3763
+ - yes_no
3764
+ - required
3765
+ - reading
3766
+ roomSource:
3767
+ type: string
3768
+ enum:
3769
+ - pose
3770
+ - named
3771
+ - vision
3772
+ - time
3773
+ - none
3774
+ spokenAt:
3775
+ type: string
3776
+ quote:
3777
+ type:
3778
+ - string
3779
+ - 'null'
3780
+ required:
3781
+ - key
3782
+ - itemText
3783
+ - description
3784
+ - itemType
3785
+ - required
3786
+ - options
3787
+ - referenceMedia
3788
+ - hints
3789
+ - roomSource
3790
+ - spokenAt
3791
+ - quote
3792
+ required:
3793
+ - key
3794
+ - title
3795
+ - sketchRoomId
3796
+ - kind
3797
+ - items
3798
+ photos:
3799
+ type: array
3800
+ items:
3801
+ type: object
3802
+ properties:
3803
+ assetId:
3804
+ type: string
3805
+ capturedAt:
3806
+ type: string
3807
+ sectionKey:
3808
+ type:
3809
+ - string
3810
+ - 'null'
3811
+ roomSource:
3812
+ type: string
3813
+ enum:
3814
+ - pose
3815
+ - named
3816
+ - vision
3817
+ - time
3818
+ - none
3819
+ itemKeys:
3820
+ type: array
3821
+ items:
3822
+ type: string
3823
+ required:
3824
+ - assetId
3825
+ - capturedAt
3826
+ - sectionKey
3827
+ - roomSource
3828
+ - itemKeys
3829
+ visionUsed:
3830
+ type: boolean
3831
+ model:
3832
+ type:
3833
+ - string
3834
+ - 'null'
3835
+ promptVersion:
3836
+ type: string
3837
+ required:
3838
+ - name
3839
+ - sections
3840
+ - photos
3841
+ - visionUsed
3842
+ - model
3843
+ - promptVersion
3844
+ WalkthroughDraftResponse:
3845
+ type: object
3846
+ properties:
3847
+ status:
3848
+ type: string
3849
+ enum:
3850
+ - completed
3851
+ - running
3852
+ - failed
3853
+ runId:
3854
+ type:
3855
+ - integer
3856
+ - 'null'
3857
+ draft:
3858
+ type:
3859
+ - object
3860
+ - 'null'
3861
+ properties:
3862
+ name:
3863
+ type: string
3864
+ sections:
3865
+ type: array
3866
+ items:
3867
+ type: object
3868
+ properties:
3869
+ key:
3870
+ type: string
3871
+ title:
3872
+ type: string
3873
+ sketchRoomId:
3874
+ type:
3875
+ - integer
3876
+ - 'null'
3877
+ kind:
3878
+ type: string
3879
+ enum:
3880
+ - room
3881
+ - custom
3882
+ - not_sure
3883
+ items:
3884
+ type: array
3885
+ items:
3886
+ type: object
3887
+ properties:
3888
+ key:
3889
+ type: string
3890
+ itemText:
3891
+ type: string
3892
+ description:
3893
+ type:
3894
+ - string
3895
+ - 'null'
3896
+ itemType:
3897
+ type: string
3898
+ enum:
3899
+ - checkbox
3900
+ - yes/no
3901
+ - text
3902
+ - number
3903
+ - date
3904
+ - dropdown
3905
+ - multi-select
3906
+ - photo
3907
+ - signature
3908
+ required:
3909
+ type: boolean
3910
+ options:
3911
+ type:
3912
+ - object
3913
+ - 'null'
3914
+ additionalProperties: {}
3915
+ referenceMedia:
3916
+ type: array
3917
+ items:
3918
+ type: object
3919
+ properties:
3920
+ assetId:
3921
+ type: string
3922
+ minLength: 1
3923
+ maxLength: 64
3924
+ caption:
3925
+ type:
3926
+ - string
3927
+ - 'null'
3928
+ maxLength: 300
3929
+ order:
3930
+ type: integer
3931
+ minimum: 0
3932
+ required:
3933
+ - assetId
3934
+ maxItems: 10
3935
+ hints:
3936
+ type: array
3937
+ items:
3938
+ type: string
3939
+ enum:
3940
+ - photo_required
3941
+ - yes_no
3942
+ - required
3943
+ - reading
3944
+ roomSource:
3945
+ type: string
3946
+ enum:
3947
+ - pose
3948
+ - named
3949
+ - vision
3950
+ - time
3951
+ - none
3952
+ spokenAt:
3953
+ type: string
3954
+ quote:
3955
+ type:
3956
+ - string
3957
+ - 'null'
3958
+ required:
3959
+ - key
3960
+ - itemText
3961
+ - description
3962
+ - itemType
3963
+ - required
3964
+ - options
3965
+ - referenceMedia
3966
+ - hints
3967
+ - roomSource
3968
+ - spokenAt
3969
+ - quote
3970
+ required:
3971
+ - key
3972
+ - title
3973
+ - sketchRoomId
3974
+ - kind
3975
+ - items
3976
+ photos:
3977
+ type: array
3978
+ items:
3979
+ type: object
3980
+ properties:
3981
+ assetId:
3982
+ type: string
3983
+ capturedAt:
3984
+ type: string
3985
+ sectionKey:
3986
+ type:
3987
+ - string
3988
+ - 'null'
3989
+ roomSource:
3990
+ type: string
3991
+ enum:
3992
+ - pose
3993
+ - named
3994
+ - vision
3995
+ - time
3996
+ - none
3997
+ itemKeys:
3998
+ type: array
3999
+ items:
4000
+ type: string
4001
+ required:
4002
+ - assetId
4003
+ - capturedAt
4004
+ - sectionKey
4005
+ - roomSource
4006
+ - itemKeys
4007
+ visionUsed:
4008
+ type: boolean
4009
+ model:
4010
+ type:
4011
+ - string
4012
+ - 'null'
4013
+ promptVersion:
4014
+ type: string
4015
+ required:
4016
+ - name
4017
+ - sections
4018
+ - photos
4019
+ - visionUsed
4020
+ - model
4021
+ - promptVersion
4022
+ sortRun:
4023
+ type:
4024
+ - object
4025
+ - 'null'
4026
+ properties:
4027
+ status:
4028
+ type: string
4029
+ enum:
4030
+ - running
4031
+ - completed
4032
+ - failed
4033
+ total:
4034
+ type: integer
4035
+ done:
4036
+ type: integer
4037
+ required:
4038
+ - status
4039
+ - total
4040
+ - done
4041
+ message:
4042
+ type:
4043
+ - string
4044
+ - 'null'
4045
+ required:
4046
+ - status
4047
+ - runId
4048
+ - draft
4049
+ - sortRun
4050
+ - message
4051
+ ChattyListJobChecklistsArguments:
4052
+ type: object
4053
+ properties:
4054
+ jobId:
4055
+ anyOf:
4056
+ - type: integer
4057
+ exclusiveMinimum: 0
4058
+ - type: string
4059
+ pattern: ^\d+$
4060
+ description: '`arguments` of the Chatty tool `list_job_checklists` (POST /api/chatty-voice/tools/execute).'
4061
+ ChattyListJobChecklistsData:
4062
+ type: array
4063
+ items:
4064
+ type: object
4065
+ properties:
4066
+ id:
4067
+ type: integer
4068
+ name:
4069
+ type: string
4070
+ status:
4071
+ type:
4072
+ - string
4073
+ - 'null'
4074
+ completionPercentage:
4075
+ type: number
4076
+ templateId:
4077
+ type:
4078
+ - integer
4079
+ - 'null'
4080
+ required:
4081
+ - id
4082
+ - name
4083
+ - status
4084
+ - completionPercentage
4085
+ - templateId
4086
+ description: '`data` of a successful `list_job_checklists` call (`success: true`).'
4087
+ ChattyGetChecklistArguments:
4088
+ type: object
4089
+ properties:
4090
+ checklistId:
4091
+ anyOf:
4092
+ - type: integer
4093
+ exclusiveMinimum: 0
4094
+ - type: string
4095
+ pattern: ^\d+$
4096
+ checklistName:
4097
+ type: string
4098
+ jobId:
4099
+ anyOf:
4100
+ - type: integer
4101
+ exclusiveMinimum: 0
4102
+ - type: string
4103
+ pattern: ^\d+$
4104
+ description: '`arguments` of the Chatty tool `get_checklist` (POST /api/chatty-voice/tools/execute).'
4105
+ ChattyGetChecklistData:
4106
+ type: object
4107
+ properties:
4108
+ id:
4109
+ type: integer
4110
+ name:
4111
+ type: string
4112
+ status:
4113
+ type:
4114
+ - string
4115
+ - 'null'
4116
+ completionPercentage:
4117
+ type: number
4118
+ jobId:
4119
+ type:
4120
+ - integer
4121
+ - 'null'
4122
+ items:
4123
+ type: array
4124
+ items:
4125
+ type: object
4126
+ properties:
4127
+ id:
4128
+ type: integer
4129
+ itemText:
4130
+ type: string
4131
+ itemType:
4132
+ type: string
4133
+ required:
4134
+ type: boolean
4135
+ done:
4136
+ type: boolean
4137
+ value:
4138
+ type:
4139
+ - string
4140
+ - 'null'
4141
+ section:
4142
+ type:
4143
+ - string
4144
+ - 'null'
4145
+ referencePhotos:
4146
+ type: integer
4147
+ required:
4148
+ - id
4149
+ - itemText
4150
+ - itemType
4151
+ - required
4152
+ - done
4153
+ - value
4154
+ - section
4155
+ - referencePhotos
4156
+ required:
4157
+ - id
4158
+ - name
4159
+ - status
4160
+ - completionPercentage
4161
+ - jobId
4162
+ - items
4163
+ description: '`data` of a successful `get_checklist` call (`success: true`).'
4164
+ ChattyCreateChecklistArguments:
4165
+ type: object
4166
+ properties:
4167
+ jobId:
4168
+ anyOf:
4169
+ - type: integer
4170
+ exclusiveMinimum: 0
4171
+ - type: string
4172
+ pattern: ^\d+$
4173
+ name:
4174
+ type: string
4175
+ templateId:
4176
+ anyOf:
4177
+ - type: integer
4178
+ exclusiveMinimum: 0
4179
+ - type: string
4180
+ pattern: ^\d+$
4181
+ templateName:
4182
+ type: string
4183
+ notes:
4184
+ type: string
4185
+ items:
4186
+ type: array
4187
+ items:
4188
+ type: string
4189
+ description: '`arguments` of the Chatty tool `create_checklist` (POST /api/chatty-voice/tools/execute).'
4190
+ ChattyCreateChecklistData:
4191
+ type: object
4192
+ properties:
4193
+ id:
4194
+ type: integer
4195
+ name:
4196
+ type: string
4197
+ jobId:
4198
+ type: integer
4199
+ itemCount:
4200
+ type: integer
4201
+ templateId:
4202
+ type: integer
4203
+ sections:
4204
+ type: array
4205
+ items:
4206
+ type: object
4207
+ properties:
4208
+ title:
4209
+ type: string
4210
+ items:
4211
+ type: array
4212
+ items:
4213
+ type: object
4214
+ properties:
4215
+ itemText:
4216
+ type: string
4217
+ itemType:
4218
+ type: string
4219
+ enum:
4220
+ - checkbox
4221
+ - yes/no
4222
+ - text
4223
+ - number
4224
+ - date
4225
+ - dropdown
4226
+ - multi-select
4227
+ - photo
4228
+ - signature
4229
+ required:
4230
+ type: boolean
4231
+ required:
4232
+ - itemText
4233
+ - itemType
4234
+ - required
4235
+ required:
4236
+ - title
4237
+ - items
4238
+ required:
4239
+ - id
4240
+ - name
4241
+ - jobId
4242
+ - itemCount
4243
+ description: '`data` of a successful `create_checklist` call (`success: true`).'
4244
+ ChattyAddChecklistItemArguments:
4245
+ type: object
4246
+ properties:
4247
+ checklistId:
4248
+ anyOf:
4249
+ - type: integer
4250
+ exclusiveMinimum: 0
4251
+ - type: string
4252
+ pattern: ^\d+$
4253
+ checklistName:
4254
+ type: string
4255
+ jobId:
4256
+ anyOf:
4257
+ - type: integer
4258
+ exclusiveMinimum: 0
4259
+ - type: string
4260
+ pattern: ^\d+$
4261
+ itemText:
4262
+ type: string
4263
+ itemType:
4264
+ type: string
4265
+ enum:
4266
+ - checkbox
4267
+ - yes/no
4268
+ - text
4269
+ - number
4270
+ - date
4271
+ - dropdown
4272
+ - multi-select
4273
+ - photo
4274
+ - signature
4275
+ required:
4276
+ type: boolean
4277
+ description:
4278
+ type: string
4279
+ sectionName:
4280
+ type: string
4281
+ required:
4282
+ - itemText
4283
+ description: '`arguments` of the Chatty tool `add_checklist_item` (POST /api/chatty-voice/tools/execute).'
4284
+ ChattyAddChecklistItemData:
4285
+ type: object
4286
+ properties:
4287
+ id:
4288
+ type: integer
4289
+ checklistId:
4290
+ type: integer
4291
+ itemText:
4292
+ type: string
4293
+ itemType:
4294
+ type: string
4295
+ enum:
4296
+ - checkbox
4297
+ - yes/no
4298
+ - text
4299
+ - number
4300
+ - date
4301
+ - dropdown
4302
+ - multi-select
4303
+ - photo
4304
+ - signature
4305
+ required:
4306
+ type: boolean
4307
+ section:
4308
+ type:
4309
+ - string
4310
+ - 'null'
4311
+ required:
4312
+ - id
4313
+ - checklistId
4314
+ - itemText
4315
+ - itemType
4316
+ - required
4317
+ - section
4318
+ description: '`data` of a successful `add_checklist_item` call (`success: true`).'
4319
+ ChattyCompleteChecklistItemArguments:
4320
+ type: object
4321
+ properties:
4322
+ checklistId:
4323
+ anyOf:
4324
+ - type: integer
4325
+ exclusiveMinimum: 0
4326
+ - type: string
4327
+ pattern: ^\d+$
4328
+ checklistName:
4329
+ type: string
4330
+ jobId:
4331
+ anyOf:
4332
+ - type: integer
4333
+ exclusiveMinimum: 0
4334
+ - type: string
4335
+ pattern: ^\d+$
4336
+ itemId:
4337
+ anyOf:
4338
+ - type: integer
4339
+ exclusiveMinimum: 0
4340
+ - type: string
4341
+ pattern: ^\d+$
4342
+ itemText:
4343
+ type: string
4344
+ completed:
4345
+ type: boolean
4346
+ description: '`arguments` of the Chatty tool `complete_checklist_item` (POST /api/chatty-voice/tools/execute).'
4347
+ ChattyCompleteChecklistItemData:
4348
+ type: object
4349
+ properties:
4350
+ checklistId:
4351
+ type: integer
4352
+ itemId:
4353
+ type: integer
4354
+ completed:
4355
+ type: boolean
4356
+ required:
4357
+ - checklistId
4358
+ - itemId
4359
+ - completed
4360
+ description: '`data` of a successful `complete_checklist_item` call (`success: true`).'
4361
+ ChattySetChecklistItemAnswerArguments:
4362
+ type: object
4363
+ properties:
4364
+ checklistId:
4365
+ anyOf:
4366
+ - type: integer
4367
+ exclusiveMinimum: 0
4368
+ - type: string
4369
+ pattern: ^\d+$
4370
+ checklistName:
4371
+ type: string
4372
+ jobId:
4373
+ anyOf:
4374
+ - type: integer
4375
+ exclusiveMinimum: 0
4376
+ - type: string
4377
+ pattern: ^\d+$
4378
+ itemId:
4379
+ anyOf:
4380
+ - type: integer
4381
+ exclusiveMinimum: 0
4382
+ - type: string
4383
+ pattern: ^\d+$
4384
+ itemText:
4385
+ type: string
4386
+ value:
4387
+ type: string
4388
+ required:
4389
+ - value
4390
+ description: '`arguments` of the Chatty tool `set_checklist_item_answer` (POST /api/chatty-voice/tools/execute).'
4391
+ ChattySetChecklistItemAnswerData:
4392
+ type: object
4393
+ properties:
4394
+ checklistId:
4395
+ type: integer
4396
+ itemId:
4397
+ type: integer
4398
+ value:
4399
+ type: string
4400
+ required:
4401
+ - checklistId
4402
+ - itemId
4403
+ - value
4404
+ description: '`data` of a successful `set_checklist_item_answer` call (`success: true`).'
4405
+ ChattyAttachReferencePhotoToItemArguments:
4406
+ type: object
4407
+ properties:
4408
+ checklistId:
4409
+ anyOf:
4410
+ - type: integer
4411
+ exclusiveMinimum: 0
4412
+ - type: string
4413
+ pattern: ^\d+$
4414
+ checklistName:
4415
+ type: string
4416
+ jobId:
4417
+ anyOf:
4418
+ - type: integer
4419
+ exclusiveMinimum: 0
4420
+ - type: string
4421
+ pattern: ^\d+$
4422
+ itemId:
4423
+ anyOf:
4424
+ - type: integer
4425
+ exclusiveMinimum: 0
4426
+ - type: string
4427
+ pattern: ^\d+$
4428
+ itemText:
4429
+ type: string
4430
+ photoId:
4431
+ anyOf:
4432
+ - type: integer
4433
+ exclusiveMinimum: 0
4434
+ - type: string
4435
+ pattern: ^\d+$
4436
+ caption:
4437
+ type: string
4438
+ required:
4439
+ - photoId
4440
+ description: '`arguments` of the Chatty tool `attach_reference_photo_to_item` (POST /api/chatty-voice/tools/execute).'
4441
+ ChattyAttachReferencePhotoToItemData:
4442
+ type: object
4443
+ properties:
4444
+ checklistId:
4445
+ type: integer
4446
+ itemId:
4447
+ type: integer
4448
+ referenceMedia:
4449
+ type: array
4450
+ items:
4451
+ type: object
4452
+ properties:
4453
+ assetId:
4454
+ type: string
4455
+ minLength: 1
4456
+ maxLength: 64
4457
+ caption:
4458
+ type:
4459
+ - string
4460
+ - 'null'
4461
+ maxLength: 300
4462
+ order:
4463
+ type: integer
4464
+ minimum: 0
4465
+ required:
4466
+ - assetId
4467
+ required:
4468
+ - checklistId
4469
+ - itemId
4470
+ - referenceMedia
4471
+ description: '`data` of a successful `attach_reference_photo_to_item` call (`success: true`).'
4472
+ ChattyDraftChecklistFromJobPhotosArguments:
4473
+ type: object
4474
+ properties:
4475
+ jobId:
4476
+ anyOf:
4477
+ - type: integer
4478
+ exclusiveMinimum: 0
4479
+ - type: string
4480
+ pattern: ^\d+$
4481
+ name:
4482
+ type: string
4483
+ create:
4484
+ type: boolean
4485
+ description: '`arguments` of the Chatty tool `draft_checklist_from_job_photos` (POST /api/chatty-voice/tools/execute).'
4486
+ ChattyDraftChecklistFromJobPhotosData:
4487
+ type: object
4488
+ properties:
4489
+ id:
4490
+ type: integer
4491
+ jobId:
4492
+ type: integer
4493
+ name:
4494
+ type: string
4495
+ items:
4496
+ type: array
4497
+ items:
4498
+ type: object
4499
+ properties:
4500
+ itemText:
4501
+ type: string
4502
+ photos:
4503
+ type: integer
4504
+ required:
4505
+ - itemText
4506
+ - photos
4507
+ unsortedPhotos:
4508
+ type: integer
4509
+ created:
4510
+ type: boolean
4511
+ required:
4512
+ - name
4513
+ - items
4514
+ - unsortedPhotos
4515
+ - created
4516
+ description: '`data` of a successful `draft_checklist_from_job_photos` call (`success: true`).'
4517
+ parameters: {}
4518
+ paths:
4519
+ /api/version:
4520
+ get:
4521
+ summary: Cross-platform version handshake manifest.
4522
+ tags:
4523
+ - version
4524
+ responses:
4525
+ '200':
4526
+ description: Always returned. Body is the canonical handshake manifest.
4527
+ content:
4528
+ application/json:
4529
+ schema:
4530
+ $ref: '#/components/schemas/VersionManifest'
4531
+ /api/ping:
4532
+ get:
4533
+ summary: Liveness probe. Bypasses the version handshake.
4534
+ tags:
4535
+ - version
4536
+ responses:
4537
+ '200':
4538
+ description: Static OK envelope.
4539
+ content:
4540
+ application/json:
4541
+ schema:
4542
+ type: object
4543
+ properties:
4544
+ status:
4545
+ type: string
4546
+ enum:
4547
+ - ok
4548
+ timestamp:
4549
+ type: string
4550
+ env:
4551
+ type:
4552
+ - string
4553
+ - 'null'
4554
+ required:
4555
+ - status
4556
+ - timestamp
4557
+ - env
4558
+ /api/me/features:
4559
+ get:
4560
+ summary: Capability discovery — iOS calls on launch to gate UI affordances.
4561
+ tags:
4562
+ - auth
4563
+ - features
4564
+ parameters:
4565
+ - &ref_0
4566
+ name: X-Client-Version
4567
+ in: header
4568
+ required: false
4569
+ schema:
4570
+ type: string
4571
+ example: 1.0.0
4572
+ description: Semver of the calling app build. Drives the 426 / soft-upgrade handshake.
4573
+ responses:
4574
+ '200':
4575
+ description: Flat feature map. Unknown / missing flags must be treated as false by the client.
4576
+ content:
4577
+ application/json:
4578
+ schema:
4579
+ $ref: '#/components/schemas/FeatureFlags'
4580
+ '426':
4581
+ description: Client major below minClientVersion.
4582
+ content:
4583
+ application/json:
4584
+ schema:
4585
+ $ref: '#/components/schemas/UpgradeRequiredEnvelope'
4586
+ /api/impersonate/native-read-ticket:
4587
+ post:
4588
+ tags:
4589
+ - auth
4590
+ summary: Authorize an exact browser-native download URL for the current support session.
4591
+ description: >-
4592
+ Requires the current typed support session and X-Support-Impersonation: 1. A narrow fixed GET allowlist only;
4593
+ record permissions still run on every GET. Admission lasts at most 15 minutes and never outlives the original
4594
+ one-hour support grant. The same browser session is required; URL alone is insufficient. GET/Range retries
4595
+ recheck current authority. Response is no-store with no-referrer. No user bearer is issued.
4596
+ security:
4597
+ - BrowserSession: []
4598
+ parameters:
4599
+ - schema:
4600
+ type: string
4601
+ enum:
4602
+ - '1'
4603
+ required: true
4604
+ name: X-Support-Impersonation
4605
+ in: header
4606
+ requestBody:
4607
+ required: true
4608
+ content:
4609
+ application/json:
4610
+ schema:
4611
+ type: object
4612
+ properties:
4613
+ url:
4614
+ type: string
4615
+ minLength: 1
4616
+ maxLength: 1024
4617
+ required:
4618
+ - url
4619
+ additionalProperties: false
4620
+ responses:
4621
+ '200':
4622
+ description: Exact relative URL and terminal admission deadline.
4623
+ content:
4624
+ application/json:
4625
+ schema:
4626
+ type: object
4627
+ properties:
4628
+ url:
4629
+ type: string
4630
+ minLength: 1
4631
+ maxLength: 8192
4632
+ expiresAt:
4633
+ type: integer
4634
+ exclusiveMinimum: 0
4635
+ required:
4636
+ - url
4637
+ - expiresAt
4638
+ additionalProperties: false
4639
+ '400':
4640
+ description: Unsupported destination or malformed request.
4641
+ '401':
4642
+ description: No authenticated session.
4643
+ '403':
4644
+ description: Support authority unavailable; explicit exit required.
4645
+ content:
4646
+ application/json:
4647
+ schema:
4648
+ $ref: '#/components/schemas/StreamAuthenticationError'
4649
+ '503':
4650
+ description: Authentication lookup temporarily unavailable.
4651
+ content:
4652
+ application/json:
4653
+ schema:
4654
+ $ref: '#/components/schemas/StreamAuthenticationError'
4655
+ /api/events/ticket:
4656
+ post:
4657
+ tags:
4658
+ - auth
4659
+ summary: Create a short-lived stream-only admission ticket from the current authenticated actor.
4660
+ description: >-
4661
+ Connect within at most 60 seconds using GET /api/events?ticket=.... The ticket preserves the real principal,
4662
+ effective target and original login/impersonation deadlines; it cannot authenticate ordinary API requests. It is
4663
+ never a target-user bearer token. Response Cache-Control is no-store. An invalid temporary context returns 403
4664
+ and must be explicitly exited, without dropping the real login.
4665
+ security:
4666
+ - UserBearer: []
4667
+ - BrowserSession: []
4668
+ - BrowserAuthCookie: []
4669
+ requestBody:
4670
+ required: false
4671
+ content:
4672
+ application/json:
4673
+ schema:
4674
+ type: object
4675
+ properties: {}
4676
+ additionalProperties: false
4677
+ responses:
4678
+ '200':
4679
+ description: Opaque ticket, usable only for short-lived stream admission.
4680
+ content:
4681
+ application/json:
4682
+ schema:
4683
+ $ref: '#/components/schemas/EventStreamTicketResponse'
4684
+ '400':
4685
+ description: Unexpected request fields.
4686
+ content:
4687
+ application/json:
4688
+ schema:
4689
+ type: object
4690
+ properties:
4691
+ message:
4692
+ type: string
4693
+ errors:
4694
+ type: array
4695
+ items: {}
4696
+ required:
4697
+ - message
4698
+ - errors
4699
+ '401':
4700
+ description: Real principal is missing, deleted, revoked or expired.
3348
4701
  content:
3349
4702
  application/json:
3350
4703
  schema:
3351
- type: object
3352
- properties:
3353
- status:
3354
- type: string
3355
- enum:
3356
- - ok
3357
- timestamp:
3358
- type: string
3359
- env:
3360
- type:
3361
- - string
3362
- - 'null'
3363
- required:
3364
- - status
3365
- - timestamp
3366
- - env
3367
- /api/me/features:
4704
+ $ref: '#/components/schemas/StreamAuthenticationError'
4705
+ '403':
4706
+ description: Impersonation is unavailable; explicitly exit before continuing as the real principal.
4707
+ content:
4708
+ application/json:
4709
+ schema:
4710
+ $ref: '#/components/schemas/StreamAuthenticationError'
4711
+ '503':
4712
+ description: Authentication lookup unavailable; retry without discarding credentials.
4713
+ content:
4714
+ application/json:
4715
+ schema:
4716
+ $ref: '#/components/schemas/StreamAuthenticationError'
4717
+ /api/events:
3368
4718
  get:
3369
- summary: Capability discovery — iOS calls on launch to gate UI affordances.
3370
4719
  tags:
3371
4720
  - auth
3372
- - features
4721
+ summary: Open the authenticated server-sent event stream.
4722
+ description: >-
4723
+ New clients use a stream-only ticket in the ticket query parameter. Legacy authenticated connections remain
4724
+ supported. A supplied invalid ticket never falls back to another credential. Current user, session and
4725
+ revocation state is rechecked before admission and each delivery batch/heartbeat. Original authority deadlines
4726
+ also close idle or blocked sockets. A stream:resync hint means refresh authorized snapshots; this stream is not
4727
+ a replay log.
3373
4728
  parameters:
3374
- - &ref_3
3375
- name: X-Client-Version
3376
- in: header
3377
- required: false
3378
- schema:
4729
+ - schema:
3379
4730
  type: string
3380
- example: 1.0.0
3381
- description: Semver of the calling app build. Drives the 426 / soft-upgrade handshake.
4731
+ minLength: 1
4732
+ maxLength: 8192
4733
+ required: false
4734
+ name: ticket
4735
+ in: query
3382
4736
  responses:
3383
4737
  '200':
3384
- description: Flat feature map. Unknown / missing flags must be treated as false by the client.
4738
+ description: Bounded SSE hints and heartbeat comments until disconnect or authority expiry.
4739
+ content:
4740
+ text/event-stream:
4741
+ schema:
4742
+ type: string
4743
+ '401':
4744
+ description: Ticket/source authentication expired, revoked or invalid.
3385
4745
  content:
3386
4746
  application/json:
3387
4747
  schema:
3388
- $ref: '#/components/schemas/FeatureFlags'
3389
- '426':
3390
- description: Client major below minClientVersion.
4748
+ $ref: '#/components/schemas/StreamAuthenticationError'
4749
+ '403':
4750
+ description: Legacy temporary context is unavailable.
3391
4751
  content:
3392
4752
  application/json:
3393
4753
  schema:
3394
- $ref: '#/components/schemas/UpgradeRequiredEnvelope'
4754
+ $ref: '#/components/schemas/StreamAuthenticationError'
4755
+ '503':
4756
+ description: Authorization temporarily unavailable; retry with backoff.
4757
+ content:
4758
+ application/json:
4759
+ schema:
4760
+ $ref: '#/components/schemas/StreamAuthenticationError'
3395
4761
  /api/jobs/{jobId}/scans/mobile-upload:
3396
4762
  post:
3397
4763
  summary: iOS LiDAR scan upload. v2 fields are additive — v1 payloads remain byte-identical.
3398
4764
  tags:
3399
4765
  - lidar
3400
4766
  parameters:
3401
- - *ref_3
4767
+ - *ref_0
3402
4768
  - schema:
3403
4769
  type: integer
3404
4770
  exclusiveMinimum: 0
@@ -3453,7 +4819,7 @@ paths:
3453
4819
  tags:
3454
4820
  - lidar
3455
4821
  parameters:
3456
- - *ref_3
4822
+ - *ref_0
3457
4823
  - schema:
3458
4824
  type: integer
3459
4825
  exclusiveMinimum: 0
@@ -3586,7 +4952,7 @@ paths:
3586
4952
  tags:
3587
4953
  - jobs
3588
4954
  parameters:
3589
- - *ref_3
4955
+ - *ref_0
3590
4956
  responses:
3591
4957
  '200':
3592
4958
  description: Array of jobs.
@@ -3607,7 +4973,7 @@ paths:
3607
4973
  tags:
3608
4974
  - jobs
3609
4975
  parameters:
3610
- - *ref_3
4976
+ - *ref_0
3611
4977
  requestBody:
3612
4978
  content:
3613
4979
  application/json:
@@ -3632,7 +4998,7 @@ paths:
3632
4998
  tags:
3633
4999
  - jobs
3634
5000
  parameters:
3635
- - *ref_3
5001
+ - *ref_0
3636
5002
  - schema:
3637
5003
  type: integer
3638
5004
  exclusiveMinimum: 0
@@ -3664,7 +5030,7 @@ paths:
3664
5030
  tags:
3665
5031
  - chatty
3666
5032
  parameters:
3667
- - *ref_3
5033
+ - *ref_0
3668
5034
  requestBody:
3669
5035
  content:
3670
5036
  application/json:
@@ -3701,7 +5067,7 @@ paths:
3701
5067
  tags:
3702
5068
  - chatty
3703
5069
  parameters:
3704
- - *ref_3
5070
+ - *ref_0
3705
5071
  - schema:
3706
5072
  type: string
3707
5073
  required: true
@@ -3734,7 +5100,7 @@ paths:
3734
5100
  tags:
3735
5101
  - chatty
3736
5102
  parameters:
3737
- - *ref_3
5103
+ - *ref_0
3738
5104
  - schema:
3739
5105
  type: string
3740
5106
  required: true
@@ -3761,7 +5127,7 @@ paths:
3761
5127
  tags:
3762
5128
  - auth
3763
5129
  parameters:
3764
- - *ref_3
5130
+ - *ref_0
3765
5131
  responses:
3766
5132
  '200':
3767
5133
  description: Authenticated user.
@@ -3787,7 +5153,7 @@ paths:
3787
5153
  tags:
3788
5154
  - crm
3789
5155
  parameters:
3790
- - *ref_3
5156
+ - *ref_0
3791
5157
  responses:
3792
5158
  '200':
3793
5159
  description: Array of contacts.
@@ -3845,11 +5211,11 @@ paths:
3845
5211
  additionalProperties: {}
3846
5212
  - type: array
3847
5213
  items: {}
3848
- - type: 'null'
3849
5214
  lastContactDate:
3850
5215
  type:
3851
5216
  - string
3852
5217
  - 'null'
5218
+ format: date-time
3853
5219
  parentContactId:
3854
5220
  type:
3855
5221
  - integer
@@ -3962,6 +5328,7 @@ paths:
3962
5328
  type:
3963
5329
  - string
3964
5330
  - 'null'
5331
+ format: date-time
3965
5332
  qboLastPushedHash:
3966
5333
  type:
3967
5334
  - string
@@ -3974,6 +5341,7 @@ paths:
3974
5341
  type:
3975
5342
  - string
3976
5343
  - 'null'
5344
+ format: date-time
3977
5345
  deletedBy:
3978
5346
  type:
3979
5347
  - string
@@ -3997,7 +5365,7 @@ paths:
3997
5365
  tags:
3998
5366
  - crm
3999
5367
  parameters:
4000
- - *ref_3
5368
+ - *ref_0
4001
5369
  requestBody:
4002
5370
  content:
4003
5371
  application/json:
@@ -4050,11 +5418,11 @@ paths:
4050
5418
  additionalProperties: {}
4051
5419
  - type: array
4052
5420
  items: {}
4053
- - type: 'null'
4054
5421
  lastContactDate:
4055
5422
  type:
4056
5423
  - string
4057
5424
  - 'null'
5425
+ format: date-time
4058
5426
  parentContactId:
4059
5427
  type:
4060
5428
  - integer
@@ -4167,6 +5535,7 @@ paths:
4167
5535
  type:
4168
5536
  - string
4169
5537
  - 'null'
5538
+ format: date-time
4170
5539
  qboLastPushedHash:
4171
5540
  type:
4172
5541
  - string
@@ -4179,6 +5548,7 @@ paths:
4179
5548
  type:
4180
5549
  - string
4181
5550
  - 'null'
5551
+ format: date-time
4182
5552
  deletedBy:
4183
5553
  type:
4184
5554
  - string
@@ -4240,11 +5610,11 @@ paths:
4240
5610
  additionalProperties: {}
4241
5611
  - type: array
4242
5612
  items: {}
4243
- - type: 'null'
4244
5613
  lastContactDate:
4245
5614
  type:
4246
5615
  - string
4247
5616
  - 'null'
5617
+ format: date-time
4248
5618
  parentContactId:
4249
5619
  type:
4250
5620
  - integer
@@ -4357,6 +5727,7 @@ paths:
4357
5727
  type:
4358
5728
  - string
4359
5729
  - 'null'
5730
+ format: date-time
4360
5731
  qboLastPushedHash:
4361
5732
  type:
4362
5733
  - string
@@ -4369,6 +5740,7 @@ paths:
4369
5740
  type:
4370
5741
  - string
4371
5742
  - 'null'
5743
+ format: date-time
4372
5744
  deletedBy:
4373
5745
  type:
4374
5746
  - string
@@ -4393,7 +5765,7 @@ paths:
4393
5765
  tags:
4394
5766
  - photos
4395
5767
  parameters:
4396
- - *ref_3
5768
+ - *ref_0
4397
5769
  - schema:
4398
5770
  type: integer
4399
5771
  exclusiveMinimum: 0
@@ -4436,7 +5808,7 @@ paths:
4436
5808
  tags:
4437
5809
  - lidar
4438
5810
  parameters:
4439
- - *ref_3
5811
+ - *ref_0
4440
5812
  - schema:
4441
5813
  type: integer
4442
5814
  exclusiveMinimum: 0
@@ -4459,7 +5831,7 @@ paths:
4459
5831
  tags:
4460
5832
  - lidar
4461
5833
  parameters:
4462
- - *ref_3
5834
+ - *ref_0
4463
5835
  - schema:
4464
5836
  type: integer
4465
5837
  exclusiveMinimum: 0
@@ -4506,6 +5878,10 @@ paths:
4506
5878
  height:
4507
5879
  type: number
4508
5880
  exclusiveMinimum: 0
5881
+ sillHeightM:
5882
+ type: number
5883
+ minimum: 0
5884
+ maximum: 50
4509
5885
  hostWallIndex:
4510
5886
  type:
4511
5887
  - integer
@@ -4516,10 +5892,15 @@ paths:
4516
5892
  minimum: 0
4517
5893
  swingHand:
4518
5894
  type: string
4519
- enum: *ref_0
5895
+ enum:
5896
+ - left
5897
+ - right
5898
+ - none
4520
5899
  placementSource:
4521
5900
  type: string
4522
- enum: *ref_1
5901
+ enum:
5902
+ - auto
5903
+ - manual
4523
5904
  duplicateOf:
4524
5905
  type: object
4525
5906
  properties:
@@ -4568,6 +5949,10 @@ paths:
4568
5949
  height:
4569
5950
  type: number
4570
5951
  exclusiveMinimum: 0
5952
+ sillHeightM:
5953
+ type: number
5954
+ minimum: 0
5955
+ maximum: 50
4571
5956
  hostWallIndex:
4572
5957
  type:
4573
5958
  - integer
@@ -4578,10 +5963,15 @@ paths:
4578
5963
  minimum: 0
4579
5964
  swingHand:
4580
5965
  type: string
4581
- enum: *ref_0
5966
+ enum:
5967
+ - left
5968
+ - right
5969
+ - none
4582
5970
  placementSource:
4583
5971
  type: string
4584
- enum: *ref_1
5972
+ enum:
5973
+ - auto
5974
+ - manual
4585
5975
  required:
4586
5976
  - position
4587
5977
  - width
@@ -4610,6 +6000,10 @@ paths:
4610
6000
  height:
4611
6001
  type: number
4612
6002
  exclusiveMinimum: 0
6003
+ sillHeightM:
6004
+ type: number
6005
+ minimum: 0
6006
+ maximum: 50
4613
6007
  hostWallIndex:
4614
6008
  type:
4615
6009
  - integer
@@ -4620,10 +6014,15 @@ paths:
4620
6014
  minimum: 0
4621
6015
  swingHand:
4622
6016
  type: string
4623
- enum: *ref_0
6017
+ enum:
6018
+ - left
6019
+ - right
6020
+ - none
4624
6021
  placementSource:
4625
6022
  type: string
4626
- enum: *ref_1
6023
+ enum:
6024
+ - auto
6025
+ - manual
4627
6026
  required:
4628
6027
  - position
4629
6028
  - width
@@ -4686,7 +6085,7 @@ paths:
4686
6085
  tags:
4687
6086
  - lidar
4688
6087
  parameters:
4689
- - *ref_3
6088
+ - *ref_0
4690
6089
  - schema:
4691
6090
  type: integer
4692
6091
  exclusiveMinimum: 0
@@ -4767,6 +6166,10 @@ paths:
4767
6166
  height:
4768
6167
  type: number
4769
6168
  exclusiveMinimum: 0
6169
+ sillHeightM:
6170
+ type: number
6171
+ minimum: 0
6172
+ maximum: 50
4770
6173
  hostWallIndex:
4771
6174
  type:
4772
6175
  - integer
@@ -4777,10 +6180,15 @@ paths:
4777
6180
  minimum: 0
4778
6181
  swingHand:
4779
6182
  type: string
4780
- enum: *ref_0
6183
+ enum:
6184
+ - left
6185
+ - right
6186
+ - none
4781
6187
  placementSource:
4782
6188
  type: string
4783
- enum: *ref_1
6189
+ enum:
6190
+ - auto
6191
+ - manual
4784
6192
  duplicateOf:
4785
6193
  type: object
4786
6194
  properties:
@@ -4830,6 +6238,10 @@ paths:
4830
6238
  height:
4831
6239
  type: number
4832
6240
  exclusiveMinimum: 0
6241
+ sillHeightM:
6242
+ type: number
6243
+ minimum: 0
6244
+ maximum: 50
4833
6245
  hostWallIndex:
4834
6246
  type:
4835
6247
  - integer
@@ -4840,10 +6252,15 @@ paths:
4840
6252
  minimum: 0
4841
6253
  swingHand:
4842
6254
  type: string
4843
- enum: *ref_0
6255
+ enum:
6256
+ - left
6257
+ - right
6258
+ - none
4844
6259
  placementSource:
4845
6260
  type: string
4846
- enum: *ref_1
6261
+ enum:
6262
+ - auto
6263
+ - manual
4847
6264
  required:
4848
6265
  - position
4849
6266
  - width
@@ -4872,6 +6289,10 @@ paths:
4872
6289
  height:
4873
6290
  type: number
4874
6291
  exclusiveMinimum: 0
6292
+ sillHeightM:
6293
+ type: number
6294
+ minimum: 0
6295
+ maximum: 50
4875
6296
  hostWallIndex:
4876
6297
  type:
4877
6298
  - integer
@@ -4882,10 +6303,15 @@ paths:
4882
6303
  minimum: 0
4883
6304
  swingHand:
4884
6305
  type: string
4885
- enum: *ref_0
6306
+ enum:
6307
+ - left
6308
+ - right
6309
+ - none
4886
6310
  placementSource:
4887
6311
  type: string
4888
- enum: *ref_1
6312
+ enum:
6313
+ - auto
6314
+ - manual
4889
6315
  required:
4890
6316
  - position
4891
6317
  - width
@@ -4941,7 +6367,7 @@ paths:
4941
6367
  tags:
4942
6368
  - chatty
4943
6369
  parameters:
4944
- - *ref_3
6370
+ - *ref_0
4945
6371
  responses:
4946
6372
  '200':
4947
6373
  description: Bare array of tool definitions.
@@ -5043,7 +6469,7 @@ paths:
5043
6469
  tags:
5044
6470
  - chatty
5045
6471
  parameters:
5046
- - *ref_3
6472
+ - *ref_0
5047
6473
  requestBody:
5048
6474
  content:
5049
6475
  application/json:
@@ -5118,7 +6544,7 @@ paths:
5118
6544
  tags:
5119
6545
  - chatty
5120
6546
  parameters:
5121
- - *ref_3
6547
+ - *ref_0
5122
6548
  responses:
5123
6549
  '200':
5124
6550
  description: System instructions + knowledge-base / workflow-stage load flags.
@@ -5168,7 +6594,7 @@ paths:
5168
6594
  tags:
5169
6595
  - chatty
5170
6596
  parameters:
5171
- - *ref_3
6597
+ - *ref_0
5172
6598
  requestBody:
5173
6599
  content:
5174
6600
  application/json:
@@ -5285,7 +6711,7 @@ paths:
5285
6711
  tags:
5286
6712
  - chatty
5287
6713
  parameters:
5288
- - *ref_3
6714
+ - *ref_0
5289
6715
  responses:
5290
6716
  '200':
5291
6717
  description: Fresh CSRF token.
@@ -5321,7 +6747,7 @@ paths:
5321
6747
  tags:
5322
6748
  - chatty
5323
6749
  parameters:
5324
- - *ref_3
6750
+ - *ref_0
5325
6751
  - name: X-CSRF-Token
5326
6752
  in: header
5327
6753
  required: true
@@ -5409,8 +6835,8 @@ paths:
5409
6835
  tags:
5410
6836
  - time-tracking
5411
6837
  parameters:
5412
- - *ref_3
5413
- - &ref_4
6838
+ - *ref_0
6839
+ - &ref_1
5414
6840
  name: X-Day-Clock
5415
6841
  in: header
5416
6842
  required: false
@@ -5457,8 +6883,8 @@ paths:
5457
6883
  tags:
5458
6884
  - time-tracking
5459
6885
  parameters:
5460
- - *ref_3
5461
- - *ref_4
6886
+ - *ref_0
6887
+ - *ref_1
5462
6888
  requestBody:
5463
6889
  content:
5464
6890
  application/json:
@@ -5486,7 +6912,11 @@ paths:
5486
6912
  type:
5487
6913
  - string
5488
6914
  - 'null'
5489
- enum: *ref_5
6915
+ enum:
6916
+ - ios
6917
+ - web
6918
+ - android
6919
+ - null
5490
6920
  occurredAt:
5491
6921
  type:
5492
6922
  - string
@@ -5593,8 +7023,8 @@ paths:
5593
7023
  tags:
5594
7024
  - time-tracking
5595
7025
  parameters:
5596
- - *ref_3
5597
- - *ref_4
7026
+ - *ref_0
7027
+ - *ref_1
5598
7028
  description: >-
5599
7029
  A late Clock Out (T6): with tapElapsedMs proving its time, it keeps its real time however old. When the safety
5600
7030
  net already closed the day (the automatic close), a proven Clock Out earlier than that close replaces it
@@ -5627,7 +7057,11 @@ paths:
5627
7057
  type:
5628
7058
  - string
5629
7059
  - 'null'
5630
- enum: *ref_5
7060
+ enum:
7061
+ - ios
7062
+ - web
7063
+ - android
7064
+ - null
5631
7065
  occurredAt:
5632
7066
  type:
5633
7067
  - string
@@ -5732,8 +7166,8 @@ paths:
5732
7166
  tags:
5733
7167
  - time-tracking
5734
7168
  parameters:
5735
- - *ref_3
5736
- - &ref_6
7169
+ - *ref_0
7170
+ - &ref_2
5737
7171
  name: X-Sites
5738
7172
  in: header
5739
7173
  required: false
@@ -5800,7 +7234,7 @@ paths:
5800
7234
  tags:
5801
7235
  - time-tracking
5802
7236
  parameters:
5803
- - *ref_3
7237
+ - *ref_0
5804
7238
  responses:
5805
7239
  '200':
5806
7240
  description: Effective settings, clamped.
@@ -5838,7 +7272,7 @@ paths:
5838
7272
  tags:
5839
7273
  - time-tracking
5840
7274
  parameters:
5841
- - *ref_3
7275
+ - *ref_0
5842
7276
  - name: scope
5843
7277
  in: query
5844
7278
  required: false
@@ -5903,8 +7337,8 @@ paths:
5903
7337
  tags:
5904
7338
  - time-tracking
5905
7339
  parameters:
5906
- - *ref_3
5907
- - *ref_6
7340
+ - *ref_0
7341
+ - *ref_2
5908
7342
  - name: scope
5909
7343
  in: query
5910
7344
  required: false
@@ -5953,8 +7387,8 @@ paths:
5953
7387
  tags:
5954
7388
  - time-tracking
5955
7389
  parameters:
5956
- - *ref_3
5957
- - *ref_6
7390
+ - *ref_0
7391
+ - *ref_2
5958
7392
  - name: userId
5959
7393
  in: query
5960
7394
  required: false
@@ -6031,9 +7465,9 @@ paths:
6031
7465
  tags:
6032
7466
  - time-tracking
6033
7467
  parameters:
6034
- - *ref_3
6035
- - *ref_6
6036
- - *ref_4
7468
+ - *ref_0
7469
+ - *ref_2
7470
+ - *ref_1
6037
7471
  requestBody:
6038
7472
  content:
6039
7473
  application/json:
@@ -6047,7 +7481,9 @@ paths:
6047
7481
  description: Omit or null together with siteType 'office'.
6048
7482
  siteType:
6049
7483
  type: string
6050
- enum: *ref_2
7484
+ enum:
7485
+ - job
7486
+ - office
6051
7487
  userId:
6052
7488
  type: string
6053
7489
  description: Clock someone else in. Requires time_tracking.edit_all.
@@ -6091,7 +7527,11 @@ paths:
6091
7527
  type:
6092
7528
  - string
6093
7529
  - 'null'
6094
- enum: *ref_5
7530
+ enum:
7531
+ - ios
7532
+ - web
7533
+ - android
7534
+ - null
6095
7535
  canConfirmAway:
6096
7536
  type: boolean
6097
7537
  description: >-
@@ -6210,9 +7650,9 @@ paths:
6210
7650
  tags:
6211
7651
  - time-tracking
6212
7652
  parameters:
6213
- - *ref_3
6214
- - *ref_6
6215
- - *ref_4
7653
+ - *ref_0
7654
+ - *ref_2
7655
+ - *ref_1
6216
7656
  requestBody:
6217
7657
  content:
6218
7658
  application/json:
@@ -6225,7 +7665,9 @@ paths:
6225
7665
  - 'null'
6226
7666
  siteType:
6227
7667
  type: string
6228
- enum: *ref_2
7668
+ enum:
7669
+ - job
7670
+ - office
6229
7671
  userId:
6230
7672
  type: string
6231
7673
  description: Requires time_tracking.edit_all.
@@ -6256,7 +7698,11 @@ paths:
6256
7698
  type:
6257
7699
  - string
6258
7700
  - 'null'
6259
- enum: *ref_5
7701
+ enum:
7702
+ - ios
7703
+ - web
7704
+ - android
7705
+ - null
6260
7706
  tapElapsedMs:
6261
7707
  type:
6262
7708
  - integer
@@ -6341,7 +7787,7 @@ paths:
6341
7787
  tags:
6342
7788
  - time-tracking
6343
7789
  parameters:
6344
- - *ref_3
7790
+ - *ref_0
6345
7791
  requestBody:
6346
7792
  content:
6347
7793
  application/json:
@@ -6492,7 +7938,7 @@ paths:
6492
7938
  tags:
6493
7939
  - time-tracking
6494
7940
  parameters:
6495
- - *ref_3
7941
+ - *ref_0
6496
7942
  - schema:
6497
7943
  type: integer
6498
7944
  required: true
@@ -6552,7 +7998,7 @@ paths:
6552
7998
  tags:
6553
7999
  - time-tracking
6554
8000
  parameters:
6555
- - *ref_3
8001
+ - *ref_0
6556
8002
  - schema:
6557
8003
  type: integer
6558
8004
  required: true
@@ -6586,7 +8032,11 @@ paths:
6586
8032
  type:
6587
8033
  - string
6588
8034
  - 'null'
6589
- enum: *ref_5
8035
+ enum:
8036
+ - ios
8037
+ - web
8038
+ - android
8039
+ - null
6590
8040
  required:
6591
8041
  - kind
6592
8042
  - lat
@@ -6660,7 +8110,7 @@ paths:
6660
8110
  tags:
6661
8111
  - time-tracking
6662
8112
  parameters:
6663
- - *ref_3
8113
+ - *ref_0
6664
8114
  requestBody:
6665
8115
  content:
6666
8116
  application/json:
@@ -6710,7 +8160,11 @@ paths:
6710
8160
  type:
6711
8161
  - string
6712
8162
  - 'null'
6713
- enum: *ref_5
8163
+ enum:
8164
+ - ios
8165
+ - web
8166
+ - android
8167
+ - null
6714
8168
  required:
6715
8169
  - pings
6716
8170
  responses:
@@ -6756,7 +8210,7 @@ paths:
6756
8210
  tags:
6757
8211
  - time-tracking
6758
8212
  parameters:
6759
- - *ref_3
8213
+ - *ref_0
6760
8214
  - name: since
6761
8215
  in: query
6762
8216
  required: false
@@ -6825,7 +8279,7 @@ paths:
6825
8279
  tags:
6826
8280
  - schedule
6827
8281
  parameters:
6828
- - *ref_3
8282
+ - *ref_0
6829
8283
  - name: date
6830
8284
  in: query
6831
8285
  required: false
@@ -6861,7 +8315,7 @@ paths:
6861
8315
  tags:
6862
8316
  - schedule
6863
8317
  parameters:
6864
- - *ref_3
8318
+ - *ref_0
6865
8319
  requestBody:
6866
8320
  content:
6867
8321
  application/json:
@@ -6870,7 +8324,10 @@ paths:
6870
8324
  properties:
6871
8325
  kind:
6872
8326
  type: string
6873
- enum: *ref_7
8327
+ enum:
8328
+ - pto
8329
+ - sick
8330
+ - 'off'
6874
8331
  startDate:
6875
8332
  type: string
6876
8333
  format: date
@@ -6936,7 +8393,7 @@ paths:
6936
8393
  tags:
6937
8394
  - account
6938
8395
  parameters:
6939
- - *ref_3
8396
+ - *ref_0
6940
8397
  requestBody:
6941
8398
  content:
6942
8399
  application/json:
@@ -6997,7 +8454,7 @@ paths:
6997
8454
  tags:
6998
8455
  - account
6999
8456
  parameters:
7000
- - *ref_3
8457
+ - *ref_0
7001
8458
  responses:
7002
8459
  '200':
7003
8460
  description: The newest request, whatever its status.
@@ -7035,4 +8492,212 @@ paths:
7035
8492
  application/json:
7036
8493
  schema:
7037
8494
  $ref: '#/components/schemas/UpgradeRequiredEnvelope'
8495
+ /api/sketches/{sketchId}/doorway-edits:
8496
+ post:
8497
+ tags:
8498
+ - lidar
8499
+ summary: Save a confirmed shared-doorway edit atomically, or undo it.
8500
+ description: >-
8501
+ Requires authenticated organization and job access. Delete removes both linked openings and only their doorway
8502
+ connection. Undo receipts are user/scope-bound, expire after eight hours, and reject intervening geometry or
8503
+ connection changes. Connect is supported for sketches only. Room reads provide openingId and openingRevision;
8504
+ existing records are not backfilled.
8505
+ parameters:
8506
+ - name: sketchId
8507
+ in: path
8508
+ required: true
8509
+ schema:
8510
+ type: integer
8511
+ minimum: 1
8512
+ requestBody:
8513
+ required: true
8514
+ content:
8515
+ application/json:
8516
+ schema:
8517
+ $ref: '#/components/schemas/DoorwayEditCommand'
8518
+ responses:
8519
+ '200':
8520
+ description: Committed both rooms and their connection changes; token reverses this action.
8521
+ content:
8522
+ application/json:
8523
+ schema:
8524
+ $ref: '#/components/schemas/DoorwayEditResult'
8525
+ '400':
8526
+ description: Invalid command or missing explicit confirmation.
8527
+ content:
8528
+ application/json:
8529
+ schema:
8530
+ $ref: '#/components/schemas/ErrorEnvelope'
8531
+ '401':
8532
+ description: Authentication required.
8533
+ '403':
8534
+ description: Job access denied.
8535
+ '404':
8536
+ description: Scope not found in the organization.
8537
+ '409':
8538
+ description: Stale or ambiguous opening identity, or undo would overwrite newer work.
8539
+ content:
8540
+ application/json:
8541
+ schema:
8542
+ $ref: '#/components/schemas/ErrorEnvelope'
8543
+ /api/floors/{floorId}/doorway-edits:
8544
+ post:
8545
+ tags:
8546
+ - lidar
8547
+ summary: Save a confirmed shared-doorway edit atomically, or undo it.
8548
+ description: >-
8549
+ Requires authenticated organization and job access. Delete removes both linked openings and only their doorway
8550
+ connection. Undo receipts are user/scope-bound, expire after eight hours, and reject intervening geometry or
8551
+ connection changes. Connect is supported for sketches only. Room reads provide openingId and openingRevision;
8552
+ existing records are not backfilled.
8553
+ parameters:
8554
+ - name: floorId
8555
+ in: path
8556
+ required: true
8557
+ schema:
8558
+ type: integer
8559
+ minimum: 1
8560
+ requestBody:
8561
+ required: true
8562
+ content:
8563
+ application/json:
8564
+ schema:
8565
+ $ref: '#/components/schemas/DoorwayEditCommand'
8566
+ responses:
8567
+ '200':
8568
+ description: Committed both rooms and their connection changes; token reverses this action.
8569
+ content:
8570
+ application/json:
8571
+ schema:
8572
+ $ref: '#/components/schemas/DoorwayEditResult'
8573
+ '400':
8574
+ description: Invalid command or missing explicit confirmation.
8575
+ content:
8576
+ application/json:
8577
+ schema:
8578
+ $ref: '#/components/schemas/ErrorEnvelope'
8579
+ '401':
8580
+ description: Authentication required.
8581
+ '403':
8582
+ description: Job access denied.
8583
+ '404':
8584
+ description: Scope not found in the organization.
8585
+ '409':
8586
+ description: Stale or ambiguous opening identity, or undo would overwrite newer work.
8587
+ content:
8588
+ application/json:
8589
+ schema:
8590
+ $ref: '#/components/schemas/ErrorEnvelope'
8591
+ /api/projects/{projectId}/documents/draft-from-walkthrough:
8592
+ post:
8593
+ tags:
8594
+ - checklists
8595
+ summary: Turn a voice walk-through (timed transcript + photos) into a checklist draft.
8596
+ description: >-
8597
+ Returns a DRAFT only; nothing is saved to the job. The phone's review screen creates the checklist with POST
8598
+ /api/projects/{projectId}/documents (custom `items`, carrying `referenceMedia`). Sections come from, in order:
8599
+ the camera pose of a scan, the room the tech named (the item's words, the photo's room chip, a section opened),
8600
+ the AI Image Sort's room for the item's photo (add-on), then the last room mentioned; items with no signal go to
8601
+ Not sure. GPS is never used. Item types come from spoken hints only (checkbox unless "photo required", "yes or
8602
+ no" or a reading; "required" sets the flag). Reference photos are the shots taken from 10 s before a sentence to
8603
+ 20 s after it. 200 when the draft is ready at once; 202 with `runId` while the photos go through an AI vision
8604
+ sort (poll the runs route). Requires the job (404 otherwise) and the Create Checklists permission (403). Photos
8605
+ that are not the organization's assets are left out.
8606
+ parameters:
8607
+ - &ref_3
8608
+ name: projectId
8609
+ in: path
8610
+ required: true
8611
+ schema:
8612
+ type: integer
8613
+ minimum: 1
8614
+ requestBody:
8615
+ required: true
8616
+ content:
8617
+ application/json:
8618
+ schema:
8619
+ $ref: '#/components/schemas/WalkthroughDraftRequest'
8620
+ responses:
8621
+ '200':
8622
+ description: The draft (status completed).
8623
+ content:
8624
+ application/json:
8625
+ schema:
8626
+ $ref: '#/components/schemas/WalkthroughDraftResponse'
8627
+ '202':
8628
+ description: A vision sort runs first (status running); poll GET …/draft-from-walkthrough/runs/{runId}.
8629
+ content:
8630
+ application/json:
8631
+ schema:
8632
+ $ref: '#/components/schemas/WalkthroughDraftResponse'
8633
+ '400':
8634
+ description: No transcript, or a wrong shape.
8635
+ content:
8636
+ application/json:
8637
+ schema:
8638
+ $ref: '#/components/schemas/ErrorEnvelope'
8639
+ '401':
8640
+ description: Authentication required.
8641
+ '403':
8642
+ description: The role cannot create checklists.
8643
+ content:
8644
+ application/json:
8645
+ schema:
8646
+ $ref: '#/components/schemas/ErrorEnvelope'
8647
+ '404':
8648
+ description: Job not found.
8649
+ content:
8650
+ application/json:
8651
+ schema:
8652
+ $ref: '#/components/schemas/ErrorEnvelope'
8653
+ '502':
8654
+ description: The AI's answer could not be used.
8655
+ content:
8656
+ application/json:
8657
+ schema:
8658
+ $ref: '#/components/schemas/ErrorEnvelope'
8659
+ '503':
8660
+ description: AI is not configured.
8661
+ content:
8662
+ application/json:
8663
+ schema:
8664
+ $ref: '#/components/schemas/ErrorEnvelope'
8665
+ /api/projects/{projectId}/documents/draft-from-walkthrough/runs/{runId}:
8666
+ get:
8667
+ tags:
8668
+ - checklists
8669
+ summary: Poll a walk-through draft that waits for an AI vision sort.
8670
+ description: >-
8671
+ Status `running` (with the sort's progress in `sortRun`) until the draft is ready, then `completed` with
8672
+ `draft`, or `failed` with `message`. A run that stops making progress is marked failed on the next poll and
8673
+ never re-run.
8674
+ parameters:
8675
+ - *ref_3
8676
+ - name: runId
8677
+ in: path
8678
+ required: true
8679
+ schema:
8680
+ type: integer
8681
+ minimum: 1
8682
+ responses:
8683
+ '200':
8684
+ description: The run's envelope.
8685
+ content:
8686
+ application/json:
8687
+ schema:
8688
+ $ref: '#/components/schemas/WalkthroughDraftResponse'
8689
+ '401':
8690
+ description: Authentication required.
8691
+ '403':
8692
+ description: The role cannot create checklists.
8693
+ content:
8694
+ application/json:
8695
+ schema:
8696
+ $ref: '#/components/schemas/ErrorEnvelope'
8697
+ '404':
8698
+ description: Job or run not found.
8699
+ content:
8700
+ application/json:
8701
+ schema:
8702
+ $ref: '#/components/schemas/ErrorEnvelope'
7038
8703
  webhooks: {}