@serviceai/api-spec 1.2.434 → 1.6.2

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 +2480 -85
  2. package/openapi.yaml +1557 -7
  3. package/package.json +1 -1
  4. package/types.d.ts +963 -63
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "ServiceAi API",
5
- "version": "1.2.434",
5
+ "version": "1.6.2",
6
6
  "description": "Source-of-truth API contract for ServiceAi. Generated from `shared/schema.ts` Zod schemas by `scripts/build-api-spec.ts`. Versioning policy: see `docs/api-versioning.md`. The hand-written docs/ios-contract.md and docs/lidar-mobile-upload-contract.md are human-readable design notes only — this spec is the canonical wire contract.",
7
7
  "license": {
8
8
  "name": "Proprietary",
@@ -52,6 +52,10 @@
52
52
  "name": "chatty",
53
53
  "description": "Realtime voice-enabled AI assistant."
54
54
  },
55
+ {
56
+ "name": "checklists",
57
+ "description": "Job checklists: the voice walk-through draft."
58
+ },
55
59
  {
56
60
  "name": "time-tracking",
57
61
  "description": "The clock. A work day is the master clock and the payroll number; time entries sit inside it and say where the time went. Automatic clock-in/out is solved SERVER-side from reported fence crossings — a client reports what it saw and reads the outcome back."
@@ -66,6 +70,22 @@
66
70
  }
67
71
  ],
68
72
  "components": {
73
+ "securitySchemes": {
74
+ "UserBearer": {
75
+ "type": "http",
76
+ "scheme": "bearer"
77
+ },
78
+ "BrowserSession": {
79
+ "type": "apiKey",
80
+ "in": "cookie",
81
+ "name": "connect.sid"
82
+ },
83
+ "BrowserAuthCookie": {
84
+ "type": "apiKey",
85
+ "in": "cookie",
86
+ "name": "auth_token"
87
+ }
88
+ },
69
89
  "schemas": {
70
90
  "ErrorEnvelope": {
71
91
  "type": "object",
@@ -126,7 +146,7 @@
126
146
  "properties": {
127
147
  "apiVersion": {
128
148
  "type": "string",
129
- "example": "1.2.434"
149
+ "example": "1.6.2"
130
150
  },
131
151
  "minClientVersion": {
132
152
  "type": "string",
@@ -2748,6 +2768,39 @@
2748
2768
  "roomConnections"
2749
2769
  ]
2750
2770
  },
2771
+ "EventStreamTicketResponse": {
2772
+ "type": "object",
2773
+ "properties": {
2774
+ "ticket": {
2775
+ "type": "string",
2776
+ "minLength": 1,
2777
+ "maxLength": 8192
2778
+ }
2779
+ },
2780
+ "required": [
2781
+ "ticket"
2782
+ ],
2783
+ "additionalProperties": false
2784
+ },
2785
+ "StreamAuthenticationError": {
2786
+ "type": "object",
2787
+ "properties": {
2788
+ "message": {
2789
+ "type": "string"
2790
+ },
2791
+ "code": {
2792
+ "type": "string",
2793
+ "enum": [
2794
+ "IMPERSONATION_UNAVAILABLE",
2795
+ "SUPPORT_IMPERSONATION_UNAVAILABLE",
2796
+ "auth_unavailable"
2797
+ ]
2798
+ }
2799
+ },
2800
+ "required": [
2801
+ "message"
2802
+ ]
2803
+ },
2751
2804
  "JobSummary": {
2752
2805
  "type": "object",
2753
2806
  "properties": {
@@ -5026,109 +5079,2163 @@
5026
5079
  "token",
5027
5080
  "roomIds"
5028
5081
  ]
5029
- }
5030
- },
5031
- "parameters": {}
5032
- },
5033
- "paths": {
5034
- "/api/version": {
5035
- "get": {
5036
- "summary": "Cross-platform version handshake manifest.",
5037
- "tags": [
5038
- "version"
5039
- ],
5040
- "responses": {
5041
- "200": {
5042
- "description": "Always returned. Body is the canonical handshake manifest.",
5043
- "content": {
5044
- "application/json": {
5045
- "schema": {
5046
- "$ref": "#/components/schemas/VersionManifest"
5082
+ },
5083
+ "WalkthroughDraftRequest": {
5084
+ "type": "object",
5085
+ "properties": {
5086
+ "transcript": {
5087
+ "type": "array",
5088
+ "items": {
5089
+ "type": "object",
5090
+ "properties": {
5091
+ "text": {
5092
+ "type": "string",
5093
+ "minLength": 1,
5094
+ "maxLength": 1000
5095
+ },
5096
+ "startedAt": {
5097
+ "type": "string",
5098
+ "format": "date-time"
5099
+ },
5100
+ "endedAt": {
5101
+ "type": "string",
5102
+ "format": "date-time"
5047
5103
  }
5048
- }
5049
- }
5050
- }
5051
- }
5052
- }
5053
- },
5054
- "/api/ping": {
5055
- "get": {
5056
- "summary": "Liveness probe. Bypasses the version handshake.",
5057
- "tags": [
5058
- "version"
5059
- ],
5060
- "responses": {
5061
- "200": {
5062
- "description": "Static OK envelope.",
5063
- "content": {
5064
- "application/json": {
5065
- "schema": {
5066
- "type": "object",
5104
+ },
5105
+ "required": [
5106
+ "text",
5107
+ "startedAt",
5108
+ "endedAt"
5109
+ ]
5110
+ },
5111
+ "minItems": 1,
5112
+ "maxItems": 400
5113
+ },
5114
+ "photos": {
5115
+ "type": "array",
5116
+ "items": {
5117
+ "type": "object",
5118
+ "properties": {
5119
+ "assetId": {
5120
+ "type": "string",
5121
+ "minLength": 1,
5122
+ "maxLength": 64
5123
+ },
5124
+ "capturedAt": {
5125
+ "type": "string",
5126
+ "format": "date-time"
5127
+ },
5128
+ "roomHint": {
5129
+ "type": [
5130
+ "string",
5131
+ "null"
5132
+ ],
5133
+ "maxLength": 200
5134
+ },
5135
+ "sketchRoomId": {
5136
+ "type": [
5137
+ "integer",
5138
+ "null"
5139
+ ],
5140
+ "exclusiveMinimum": 0
5141
+ },
5142
+ "capturePose": {
5143
+ "type": [
5144
+ "object",
5145
+ "null"
5146
+ ],
5067
5147
  "properties": {
5068
- "status": {
5069
- "type": "string",
5070
- "enum": [
5071
- "ok"
5072
- ]
5148
+ "x": {
5149
+ "type": "number"
5073
5150
  },
5074
- "timestamp": {
5075
- "type": "string"
5151
+ "y": {
5152
+ "type": "number"
5076
5153
  },
5077
- "env": {
5154
+ "z": {
5155
+ "type": "number"
5156
+ },
5157
+ "floorId": {
5078
5158
  "type": [
5079
- "string",
5159
+ "integer",
5080
5160
  "null"
5081
- ]
5161
+ ],
5162
+ "exclusiveMinimum": 0
5163
+ },
5164
+ "sketchId": {
5165
+ "type": [
5166
+ "integer",
5167
+ "null"
5168
+ ],
5169
+ "exclusiveMinimum": 0
5170
+ },
5171
+ "scanSessionId": {
5172
+ "type": "string",
5173
+ "maxLength": 64
5174
+ },
5175
+ "scanRoomLocalId": {
5176
+ "type": "string",
5177
+ "maxLength": 128
5178
+ },
5179
+ "scanRoomName": {
5180
+ "type": "string",
5181
+ "maxLength": 200
5082
5182
  }
5083
- },
5084
- "required": [
5085
- "status",
5086
- "timestamp",
5087
- "env"
5088
- ]
5183
+ }
5089
5184
  }
5090
- }
5091
- }
5092
- }
5093
- }
5094
- }
5095
- },
5096
- "/api/me/features": {
5097
- "get": {
5098
- "summary": "Capability discovery — iOS calls on launch to gate UI affordances.",
5099
- "tags": [
5100
- "auth",
5101
- "features"
5102
- ],
5103
- "parameters": [
5104
- {
5105
- "name": "X-Client-Version",
5106
- "in": "header",
5107
- "required": false,
5108
- "schema": {
5109
- "type": "string",
5110
- "example": "1.0.0"
5185
+ },
5186
+ "required": [
5187
+ "assetId",
5188
+ "capturedAt"
5189
+ ]
5111
5190
  },
5112
- "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
5191
+ "maxItems": 200
5192
+ },
5193
+ "sections": {
5194
+ "type": "array",
5195
+ "items": {
5196
+ "type": "object",
5197
+ "properties": {
5198
+ "name": {
5199
+ "type": "string",
5200
+ "minLength": 1,
5201
+ "maxLength": 200
5202
+ },
5203
+ "startedAt": {
5204
+ "type": "string",
5205
+ "format": "date-time"
5206
+ },
5207
+ "sketchRoomId": {
5208
+ "type": [
5209
+ "integer",
5210
+ "null"
5211
+ ],
5212
+ "exclusiveMinimum": 0
5213
+ }
5214
+ },
5215
+ "required": [
5216
+ "name",
5217
+ "startedAt"
5218
+ ]
5219
+ },
5220
+ "maxItems": 100
5221
+ },
5222
+ "roomsFrom": {
5223
+ "type": "string",
5224
+ "enum": [
5225
+ "speech",
5226
+ "scan"
5227
+ ]
5113
5228
  }
5114
- ],
5115
- "responses": {
5116
- "200": {
5117
- "description": "Flat feature map. Unknown / missing flags must be treated as false by the client.",
5229
+ },
5230
+ "required": [
5231
+ "transcript"
5232
+ ]
5233
+ },
5234
+ "ChecklistDraft": {
5235
+ "type": "object",
5236
+ "properties": {
5237
+ "name": {
5238
+ "type": "string"
5239
+ },
5240
+ "sections": {
5241
+ "type": "array",
5242
+ "items": {
5243
+ "type": "object",
5244
+ "properties": {
5245
+ "key": {
5246
+ "type": "string"
5247
+ },
5248
+ "title": {
5249
+ "type": "string"
5250
+ },
5251
+ "sketchRoomId": {
5252
+ "type": [
5253
+ "integer",
5254
+ "null"
5255
+ ]
5256
+ },
5257
+ "kind": {
5258
+ "type": "string",
5259
+ "enum": [
5260
+ "room",
5261
+ "custom",
5262
+ "not_sure"
5263
+ ]
5264
+ },
5265
+ "items": {
5266
+ "type": "array",
5267
+ "items": {
5268
+ "type": "object",
5269
+ "properties": {
5270
+ "key": {
5271
+ "type": "string"
5272
+ },
5273
+ "itemText": {
5274
+ "type": "string"
5275
+ },
5276
+ "description": {
5277
+ "type": [
5278
+ "string",
5279
+ "null"
5280
+ ]
5281
+ },
5282
+ "itemType": {
5283
+ "type": "string",
5284
+ "enum": [
5285
+ "checkbox",
5286
+ "yes/no",
5287
+ "text",
5288
+ "number",
5289
+ "date",
5290
+ "dropdown",
5291
+ "multi-select",
5292
+ "photo",
5293
+ "signature"
5294
+ ]
5295
+ },
5296
+ "required": {
5297
+ "type": "boolean"
5298
+ },
5299
+ "options": {
5300
+ "type": [
5301
+ "object",
5302
+ "null"
5303
+ ],
5304
+ "additionalProperties": {}
5305
+ },
5306
+ "referenceMedia": {
5307
+ "type": "array",
5308
+ "items": {
5309
+ "type": "object",
5310
+ "properties": {
5311
+ "assetId": {
5312
+ "type": "string",
5313
+ "minLength": 1,
5314
+ "maxLength": 64
5315
+ },
5316
+ "caption": {
5317
+ "type": [
5318
+ "string",
5319
+ "null"
5320
+ ],
5321
+ "maxLength": 300
5322
+ },
5323
+ "order": {
5324
+ "type": "integer",
5325
+ "minimum": 0
5326
+ }
5327
+ },
5328
+ "required": [
5329
+ "assetId"
5330
+ ]
5331
+ },
5332
+ "maxItems": 10
5333
+ },
5334
+ "hints": {
5335
+ "type": "array",
5336
+ "items": {
5337
+ "type": "string",
5338
+ "enum": [
5339
+ "photo_required",
5340
+ "yes_no",
5341
+ "required",
5342
+ "reading"
5343
+ ]
5344
+ }
5345
+ },
5346
+ "roomSource": {
5347
+ "type": "string",
5348
+ "enum": [
5349
+ "pose",
5350
+ "named",
5351
+ "vision",
5352
+ "time",
5353
+ "none"
5354
+ ]
5355
+ },
5356
+ "spokenAt": {
5357
+ "type": "string"
5358
+ },
5359
+ "quote": {
5360
+ "type": [
5361
+ "string",
5362
+ "null"
5363
+ ]
5364
+ }
5365
+ },
5366
+ "required": [
5367
+ "key",
5368
+ "itemText",
5369
+ "description",
5370
+ "itemType",
5371
+ "required",
5372
+ "options",
5373
+ "referenceMedia",
5374
+ "hints",
5375
+ "roomSource",
5376
+ "spokenAt",
5377
+ "quote"
5378
+ ]
5379
+ }
5380
+ }
5381
+ },
5382
+ "required": [
5383
+ "key",
5384
+ "title",
5385
+ "sketchRoomId",
5386
+ "kind",
5387
+ "items"
5388
+ ]
5389
+ }
5390
+ },
5391
+ "photos": {
5392
+ "type": "array",
5393
+ "items": {
5394
+ "type": "object",
5395
+ "properties": {
5396
+ "assetId": {
5397
+ "type": "string"
5398
+ },
5399
+ "capturedAt": {
5400
+ "type": "string"
5401
+ },
5402
+ "sectionKey": {
5403
+ "type": [
5404
+ "string",
5405
+ "null"
5406
+ ]
5407
+ },
5408
+ "roomSource": {
5409
+ "type": "string",
5410
+ "enum": [
5411
+ "pose",
5412
+ "named",
5413
+ "vision",
5414
+ "time",
5415
+ "none"
5416
+ ]
5417
+ },
5418
+ "itemKeys": {
5419
+ "type": "array",
5420
+ "items": {
5421
+ "type": "string"
5422
+ }
5423
+ }
5424
+ },
5425
+ "required": [
5426
+ "assetId",
5427
+ "capturedAt",
5428
+ "sectionKey",
5429
+ "roomSource",
5430
+ "itemKeys"
5431
+ ]
5432
+ }
5433
+ },
5434
+ "visionUsed": {
5435
+ "type": "boolean"
5436
+ },
5437
+ "model": {
5438
+ "type": [
5439
+ "string",
5440
+ "null"
5441
+ ]
5442
+ },
5443
+ "promptVersion": {
5444
+ "type": "string"
5445
+ }
5446
+ },
5447
+ "required": [
5448
+ "name",
5449
+ "sections",
5450
+ "photos",
5451
+ "visionUsed",
5452
+ "model",
5453
+ "promptVersion"
5454
+ ]
5455
+ },
5456
+ "WalkthroughDraftResponse": {
5457
+ "type": "object",
5458
+ "properties": {
5459
+ "status": {
5460
+ "type": "string",
5461
+ "enum": [
5462
+ "completed",
5463
+ "running",
5464
+ "failed"
5465
+ ]
5466
+ },
5467
+ "runId": {
5468
+ "type": [
5469
+ "integer",
5470
+ "null"
5471
+ ]
5472
+ },
5473
+ "draft": {
5474
+ "type": [
5475
+ "object",
5476
+ "null"
5477
+ ],
5478
+ "properties": {
5479
+ "name": {
5480
+ "type": "string"
5481
+ },
5482
+ "sections": {
5483
+ "type": "array",
5484
+ "items": {
5485
+ "type": "object",
5486
+ "properties": {
5487
+ "key": {
5488
+ "type": "string"
5489
+ },
5490
+ "title": {
5491
+ "type": "string"
5492
+ },
5493
+ "sketchRoomId": {
5494
+ "type": [
5495
+ "integer",
5496
+ "null"
5497
+ ]
5498
+ },
5499
+ "kind": {
5500
+ "type": "string",
5501
+ "enum": [
5502
+ "room",
5503
+ "custom",
5504
+ "not_sure"
5505
+ ]
5506
+ },
5507
+ "items": {
5508
+ "type": "array",
5509
+ "items": {
5510
+ "type": "object",
5511
+ "properties": {
5512
+ "key": {
5513
+ "type": "string"
5514
+ },
5515
+ "itemText": {
5516
+ "type": "string"
5517
+ },
5518
+ "description": {
5519
+ "type": [
5520
+ "string",
5521
+ "null"
5522
+ ]
5523
+ },
5524
+ "itemType": {
5525
+ "type": "string",
5526
+ "enum": [
5527
+ "checkbox",
5528
+ "yes/no",
5529
+ "text",
5530
+ "number",
5531
+ "date",
5532
+ "dropdown",
5533
+ "multi-select",
5534
+ "photo",
5535
+ "signature"
5536
+ ]
5537
+ },
5538
+ "required": {
5539
+ "type": "boolean"
5540
+ },
5541
+ "options": {
5542
+ "type": [
5543
+ "object",
5544
+ "null"
5545
+ ],
5546
+ "additionalProperties": {}
5547
+ },
5548
+ "referenceMedia": {
5549
+ "type": "array",
5550
+ "items": {
5551
+ "type": "object",
5552
+ "properties": {
5553
+ "assetId": {
5554
+ "type": "string",
5555
+ "minLength": 1,
5556
+ "maxLength": 64
5557
+ },
5558
+ "caption": {
5559
+ "type": [
5560
+ "string",
5561
+ "null"
5562
+ ],
5563
+ "maxLength": 300
5564
+ },
5565
+ "order": {
5566
+ "type": "integer",
5567
+ "minimum": 0
5568
+ }
5569
+ },
5570
+ "required": [
5571
+ "assetId"
5572
+ ]
5573
+ },
5574
+ "maxItems": 10
5575
+ },
5576
+ "hints": {
5577
+ "type": "array",
5578
+ "items": {
5579
+ "type": "string",
5580
+ "enum": [
5581
+ "photo_required",
5582
+ "yes_no",
5583
+ "required",
5584
+ "reading"
5585
+ ]
5586
+ }
5587
+ },
5588
+ "roomSource": {
5589
+ "type": "string",
5590
+ "enum": [
5591
+ "pose",
5592
+ "named",
5593
+ "vision",
5594
+ "time",
5595
+ "none"
5596
+ ]
5597
+ },
5598
+ "spokenAt": {
5599
+ "type": "string"
5600
+ },
5601
+ "quote": {
5602
+ "type": [
5603
+ "string",
5604
+ "null"
5605
+ ]
5606
+ }
5607
+ },
5608
+ "required": [
5609
+ "key",
5610
+ "itemText",
5611
+ "description",
5612
+ "itemType",
5613
+ "required",
5614
+ "options",
5615
+ "referenceMedia",
5616
+ "hints",
5617
+ "roomSource",
5618
+ "spokenAt",
5619
+ "quote"
5620
+ ]
5621
+ }
5622
+ }
5623
+ },
5624
+ "required": [
5625
+ "key",
5626
+ "title",
5627
+ "sketchRoomId",
5628
+ "kind",
5629
+ "items"
5630
+ ]
5631
+ }
5632
+ },
5633
+ "photos": {
5634
+ "type": "array",
5635
+ "items": {
5636
+ "type": "object",
5637
+ "properties": {
5638
+ "assetId": {
5639
+ "type": "string"
5640
+ },
5641
+ "capturedAt": {
5642
+ "type": "string"
5643
+ },
5644
+ "sectionKey": {
5645
+ "type": [
5646
+ "string",
5647
+ "null"
5648
+ ]
5649
+ },
5650
+ "roomSource": {
5651
+ "type": "string",
5652
+ "enum": [
5653
+ "pose",
5654
+ "named",
5655
+ "vision",
5656
+ "time",
5657
+ "none"
5658
+ ]
5659
+ },
5660
+ "itemKeys": {
5661
+ "type": "array",
5662
+ "items": {
5663
+ "type": "string"
5664
+ }
5665
+ }
5666
+ },
5667
+ "required": [
5668
+ "assetId",
5669
+ "capturedAt",
5670
+ "sectionKey",
5671
+ "roomSource",
5672
+ "itemKeys"
5673
+ ]
5674
+ }
5675
+ },
5676
+ "visionUsed": {
5677
+ "type": "boolean"
5678
+ },
5679
+ "model": {
5680
+ "type": [
5681
+ "string",
5682
+ "null"
5683
+ ]
5684
+ },
5685
+ "promptVersion": {
5686
+ "type": "string"
5687
+ }
5688
+ },
5689
+ "required": [
5690
+ "name",
5691
+ "sections",
5692
+ "photos",
5693
+ "visionUsed",
5694
+ "model",
5695
+ "promptVersion"
5696
+ ]
5697
+ },
5698
+ "sortRun": {
5699
+ "type": [
5700
+ "object",
5701
+ "null"
5702
+ ],
5703
+ "properties": {
5704
+ "status": {
5705
+ "type": "string",
5706
+ "enum": [
5707
+ "running",
5708
+ "completed",
5709
+ "failed"
5710
+ ]
5711
+ },
5712
+ "total": {
5713
+ "type": "integer"
5714
+ },
5715
+ "done": {
5716
+ "type": "integer"
5717
+ }
5718
+ },
5719
+ "required": [
5720
+ "status",
5721
+ "total",
5722
+ "done"
5723
+ ]
5724
+ },
5725
+ "message": {
5726
+ "type": [
5727
+ "string",
5728
+ "null"
5729
+ ]
5730
+ }
5731
+ },
5732
+ "required": [
5733
+ "status",
5734
+ "runId",
5735
+ "draft",
5736
+ "sortRun",
5737
+ "message"
5738
+ ]
5739
+ },
5740
+ "ChattyListJobChecklistsArguments": {
5741
+ "type": "object",
5742
+ "properties": {
5743
+ "jobId": {
5744
+ "anyOf": [
5745
+ {
5746
+ "type": "integer",
5747
+ "exclusiveMinimum": 0
5748
+ },
5749
+ {
5750
+ "type": "string",
5751
+ "pattern": "^\\d+$"
5752
+ }
5753
+ ]
5754
+ }
5755
+ },
5756
+ "description": "`arguments` of the Chatty tool `list_job_checklists` (POST /api/chatty-voice/tools/execute)."
5757
+ },
5758
+ "ChattyListJobChecklistsData": {
5759
+ "type": "array",
5760
+ "items": {
5761
+ "type": "object",
5762
+ "properties": {
5763
+ "id": {
5764
+ "type": "integer"
5765
+ },
5766
+ "name": {
5767
+ "type": "string"
5768
+ },
5769
+ "status": {
5770
+ "type": [
5771
+ "string",
5772
+ "null"
5773
+ ]
5774
+ },
5775
+ "completionPercentage": {
5776
+ "type": "number"
5777
+ },
5778
+ "templateId": {
5779
+ "type": [
5780
+ "integer",
5781
+ "null"
5782
+ ]
5783
+ }
5784
+ },
5785
+ "required": [
5786
+ "id",
5787
+ "name",
5788
+ "status",
5789
+ "completionPercentage",
5790
+ "templateId"
5791
+ ]
5792
+ },
5793
+ "description": "`data` of a successful `list_job_checklists` call (`success: true`)."
5794
+ },
5795
+ "ChattyGetChecklistArguments": {
5796
+ "type": "object",
5797
+ "properties": {
5798
+ "checklistId": {
5799
+ "anyOf": [
5800
+ {
5801
+ "type": "integer",
5802
+ "exclusiveMinimum": 0
5803
+ },
5804
+ {
5805
+ "type": "string",
5806
+ "pattern": "^\\d+$"
5807
+ }
5808
+ ]
5809
+ },
5810
+ "checklistName": {
5811
+ "type": "string"
5812
+ },
5813
+ "jobId": {
5814
+ "anyOf": [
5815
+ {
5816
+ "type": "integer",
5817
+ "exclusiveMinimum": 0
5818
+ },
5819
+ {
5820
+ "type": "string",
5821
+ "pattern": "^\\d+$"
5822
+ }
5823
+ ]
5824
+ }
5825
+ },
5826
+ "description": "`arguments` of the Chatty tool `get_checklist` (POST /api/chatty-voice/tools/execute)."
5827
+ },
5828
+ "ChattyGetChecklistData": {
5829
+ "type": "object",
5830
+ "properties": {
5831
+ "id": {
5832
+ "type": "integer"
5833
+ },
5834
+ "name": {
5835
+ "type": "string"
5836
+ },
5837
+ "status": {
5838
+ "type": [
5839
+ "string",
5840
+ "null"
5841
+ ]
5842
+ },
5843
+ "completionPercentage": {
5844
+ "type": "number"
5845
+ },
5846
+ "jobId": {
5847
+ "type": [
5848
+ "integer",
5849
+ "null"
5850
+ ]
5851
+ },
5852
+ "items": {
5853
+ "type": "array",
5854
+ "items": {
5855
+ "type": "object",
5856
+ "properties": {
5857
+ "id": {
5858
+ "type": "integer"
5859
+ },
5860
+ "itemText": {
5861
+ "type": "string"
5862
+ },
5863
+ "itemType": {
5864
+ "type": "string"
5865
+ },
5866
+ "required": {
5867
+ "type": "boolean"
5868
+ },
5869
+ "done": {
5870
+ "type": "boolean"
5871
+ },
5872
+ "value": {
5873
+ "type": [
5874
+ "string",
5875
+ "null"
5876
+ ]
5877
+ },
5878
+ "section": {
5879
+ "type": [
5880
+ "string",
5881
+ "null"
5882
+ ]
5883
+ },
5884
+ "referencePhotos": {
5885
+ "type": "integer"
5886
+ }
5887
+ },
5888
+ "required": [
5889
+ "id",
5890
+ "itemText",
5891
+ "itemType",
5892
+ "required",
5893
+ "done",
5894
+ "value",
5895
+ "section",
5896
+ "referencePhotos"
5897
+ ]
5898
+ }
5899
+ }
5900
+ },
5901
+ "required": [
5902
+ "id",
5903
+ "name",
5904
+ "status",
5905
+ "completionPercentage",
5906
+ "jobId",
5907
+ "items"
5908
+ ],
5909
+ "description": "`data` of a successful `get_checklist` call (`success: true`)."
5910
+ },
5911
+ "ChattyCreateChecklistArguments": {
5912
+ "type": "object",
5913
+ "properties": {
5914
+ "jobId": {
5915
+ "anyOf": [
5916
+ {
5917
+ "type": "integer",
5918
+ "exclusiveMinimum": 0
5919
+ },
5920
+ {
5921
+ "type": "string",
5922
+ "pattern": "^\\d+$"
5923
+ }
5924
+ ]
5925
+ },
5926
+ "name": {
5927
+ "type": "string"
5928
+ },
5929
+ "templateId": {
5930
+ "anyOf": [
5931
+ {
5932
+ "type": "integer",
5933
+ "exclusiveMinimum": 0
5934
+ },
5935
+ {
5936
+ "type": "string",
5937
+ "pattern": "^\\d+$"
5938
+ }
5939
+ ]
5940
+ },
5941
+ "templateName": {
5942
+ "type": "string"
5943
+ },
5944
+ "notes": {
5945
+ "type": "string"
5946
+ },
5947
+ "items": {
5948
+ "type": "array",
5949
+ "items": {
5950
+ "type": "string"
5951
+ }
5952
+ }
5953
+ },
5954
+ "description": "`arguments` of the Chatty tool `create_checklist` (POST /api/chatty-voice/tools/execute)."
5955
+ },
5956
+ "ChattyCreateChecklistData": {
5957
+ "type": "object",
5958
+ "properties": {
5959
+ "id": {
5960
+ "type": "integer"
5961
+ },
5962
+ "name": {
5963
+ "type": "string"
5964
+ },
5965
+ "jobId": {
5966
+ "type": "integer"
5967
+ },
5968
+ "itemCount": {
5969
+ "type": "integer"
5970
+ },
5971
+ "templateId": {
5972
+ "type": "integer"
5973
+ },
5974
+ "sections": {
5975
+ "type": "array",
5976
+ "items": {
5977
+ "type": "object",
5978
+ "properties": {
5979
+ "title": {
5980
+ "type": "string"
5981
+ },
5982
+ "items": {
5983
+ "type": "array",
5984
+ "items": {
5985
+ "type": "object",
5986
+ "properties": {
5987
+ "itemText": {
5988
+ "type": "string"
5989
+ },
5990
+ "itemType": {
5991
+ "type": "string",
5992
+ "enum": [
5993
+ "checkbox",
5994
+ "yes/no",
5995
+ "text",
5996
+ "number",
5997
+ "date",
5998
+ "dropdown",
5999
+ "multi-select",
6000
+ "photo",
6001
+ "signature"
6002
+ ]
6003
+ },
6004
+ "required": {
6005
+ "type": "boolean"
6006
+ }
6007
+ },
6008
+ "required": [
6009
+ "itemText",
6010
+ "itemType",
6011
+ "required"
6012
+ ]
6013
+ }
6014
+ }
6015
+ },
6016
+ "required": [
6017
+ "title",
6018
+ "items"
6019
+ ]
6020
+ }
6021
+ }
6022
+ },
6023
+ "required": [
6024
+ "id",
6025
+ "name",
6026
+ "jobId",
6027
+ "itemCount"
6028
+ ],
6029
+ "description": "`data` of a successful `create_checklist` call (`success: true`)."
6030
+ },
6031
+ "ChattyAddChecklistItemArguments": {
6032
+ "type": "object",
6033
+ "properties": {
6034
+ "checklistId": {
6035
+ "anyOf": [
6036
+ {
6037
+ "type": "integer",
6038
+ "exclusiveMinimum": 0
6039
+ },
6040
+ {
6041
+ "type": "string",
6042
+ "pattern": "^\\d+$"
6043
+ }
6044
+ ]
6045
+ },
6046
+ "checklistName": {
6047
+ "type": "string"
6048
+ },
6049
+ "jobId": {
6050
+ "anyOf": [
6051
+ {
6052
+ "type": "integer",
6053
+ "exclusiveMinimum": 0
6054
+ },
6055
+ {
6056
+ "type": "string",
6057
+ "pattern": "^\\d+$"
6058
+ }
6059
+ ]
6060
+ },
6061
+ "itemText": {
6062
+ "type": "string"
6063
+ },
6064
+ "itemType": {
6065
+ "type": "string",
6066
+ "enum": [
6067
+ "checkbox",
6068
+ "yes/no",
6069
+ "text",
6070
+ "number",
6071
+ "date",
6072
+ "dropdown",
6073
+ "multi-select",
6074
+ "photo",
6075
+ "signature"
6076
+ ]
6077
+ },
6078
+ "required": {
6079
+ "type": "boolean"
6080
+ },
6081
+ "description": {
6082
+ "type": "string"
6083
+ },
6084
+ "sectionName": {
6085
+ "type": "string"
6086
+ }
6087
+ },
6088
+ "required": [
6089
+ "itemText"
6090
+ ],
6091
+ "description": "`arguments` of the Chatty tool `add_checklist_item` (POST /api/chatty-voice/tools/execute)."
6092
+ },
6093
+ "ChattyAddChecklistItemData": {
6094
+ "type": "object",
6095
+ "properties": {
6096
+ "id": {
6097
+ "type": "integer"
6098
+ },
6099
+ "checklistId": {
6100
+ "type": "integer"
6101
+ },
6102
+ "itemText": {
6103
+ "type": "string"
6104
+ },
6105
+ "itemType": {
6106
+ "type": "string",
6107
+ "enum": [
6108
+ "checkbox",
6109
+ "yes/no",
6110
+ "text",
6111
+ "number",
6112
+ "date",
6113
+ "dropdown",
6114
+ "multi-select",
6115
+ "photo",
6116
+ "signature"
6117
+ ]
6118
+ },
6119
+ "required": {
6120
+ "type": "boolean"
6121
+ },
6122
+ "section": {
6123
+ "type": [
6124
+ "string",
6125
+ "null"
6126
+ ]
6127
+ }
6128
+ },
6129
+ "required": [
6130
+ "id",
6131
+ "checklistId",
6132
+ "itemText",
6133
+ "itemType",
6134
+ "required",
6135
+ "section"
6136
+ ],
6137
+ "description": "`data` of a successful `add_checklist_item` call (`success: true`)."
6138
+ },
6139
+ "ChattyCompleteChecklistItemArguments": {
6140
+ "type": "object",
6141
+ "properties": {
6142
+ "checklistId": {
6143
+ "anyOf": [
6144
+ {
6145
+ "type": "integer",
6146
+ "exclusiveMinimum": 0
6147
+ },
6148
+ {
6149
+ "type": "string",
6150
+ "pattern": "^\\d+$"
6151
+ }
6152
+ ]
6153
+ },
6154
+ "checklistName": {
6155
+ "type": "string"
6156
+ },
6157
+ "jobId": {
6158
+ "anyOf": [
6159
+ {
6160
+ "type": "integer",
6161
+ "exclusiveMinimum": 0
6162
+ },
6163
+ {
6164
+ "type": "string",
6165
+ "pattern": "^\\d+$"
6166
+ }
6167
+ ]
6168
+ },
6169
+ "itemId": {
6170
+ "anyOf": [
6171
+ {
6172
+ "type": "integer",
6173
+ "exclusiveMinimum": 0
6174
+ },
6175
+ {
6176
+ "type": "string",
6177
+ "pattern": "^\\d+$"
6178
+ }
6179
+ ]
6180
+ },
6181
+ "itemText": {
6182
+ "type": "string"
6183
+ },
6184
+ "completed": {
6185
+ "type": "boolean"
6186
+ }
6187
+ },
6188
+ "description": "`arguments` of the Chatty tool `complete_checklist_item` (POST /api/chatty-voice/tools/execute)."
6189
+ },
6190
+ "ChattyCompleteChecklistItemData": {
6191
+ "type": "object",
6192
+ "properties": {
6193
+ "checklistId": {
6194
+ "type": "integer"
6195
+ },
6196
+ "itemId": {
6197
+ "type": "integer"
6198
+ },
6199
+ "completed": {
6200
+ "type": "boolean"
6201
+ }
6202
+ },
6203
+ "required": [
6204
+ "checklistId",
6205
+ "itemId",
6206
+ "completed"
6207
+ ],
6208
+ "description": "`data` of a successful `complete_checklist_item` call (`success: true`)."
6209
+ },
6210
+ "ChattySetChecklistItemAnswerArguments": {
6211
+ "type": "object",
6212
+ "properties": {
6213
+ "checklistId": {
6214
+ "anyOf": [
6215
+ {
6216
+ "type": "integer",
6217
+ "exclusiveMinimum": 0
6218
+ },
6219
+ {
6220
+ "type": "string",
6221
+ "pattern": "^\\d+$"
6222
+ }
6223
+ ]
6224
+ },
6225
+ "checklistName": {
6226
+ "type": "string"
6227
+ },
6228
+ "jobId": {
6229
+ "anyOf": [
6230
+ {
6231
+ "type": "integer",
6232
+ "exclusiveMinimum": 0
6233
+ },
6234
+ {
6235
+ "type": "string",
6236
+ "pattern": "^\\d+$"
6237
+ }
6238
+ ]
6239
+ },
6240
+ "itemId": {
6241
+ "anyOf": [
6242
+ {
6243
+ "type": "integer",
6244
+ "exclusiveMinimum": 0
6245
+ },
6246
+ {
6247
+ "type": "string",
6248
+ "pattern": "^\\d+$"
6249
+ }
6250
+ ]
6251
+ },
6252
+ "itemText": {
6253
+ "type": "string"
6254
+ },
6255
+ "value": {
6256
+ "type": "string"
6257
+ }
6258
+ },
6259
+ "required": [
6260
+ "value"
6261
+ ],
6262
+ "description": "`arguments` of the Chatty tool `set_checklist_item_answer` (POST /api/chatty-voice/tools/execute)."
6263
+ },
6264
+ "ChattySetChecklistItemAnswerData": {
6265
+ "type": "object",
6266
+ "properties": {
6267
+ "checklistId": {
6268
+ "type": "integer"
6269
+ },
6270
+ "itemId": {
6271
+ "type": "integer"
6272
+ },
6273
+ "value": {
6274
+ "type": "string"
6275
+ }
6276
+ },
6277
+ "required": [
6278
+ "checklistId",
6279
+ "itemId",
6280
+ "value"
6281
+ ],
6282
+ "description": "`data` of a successful `set_checklist_item_answer` call (`success: true`)."
6283
+ },
6284
+ "ChattyAttachReferencePhotoToItemArguments": {
6285
+ "type": "object",
6286
+ "properties": {
6287
+ "checklistId": {
6288
+ "anyOf": [
6289
+ {
6290
+ "type": "integer",
6291
+ "exclusiveMinimum": 0
6292
+ },
6293
+ {
6294
+ "type": "string",
6295
+ "pattern": "^\\d+$"
6296
+ }
6297
+ ]
6298
+ },
6299
+ "checklistName": {
6300
+ "type": "string"
6301
+ },
6302
+ "jobId": {
6303
+ "anyOf": [
6304
+ {
6305
+ "type": "integer",
6306
+ "exclusiveMinimum": 0
6307
+ },
6308
+ {
6309
+ "type": "string",
6310
+ "pattern": "^\\d+$"
6311
+ }
6312
+ ]
6313
+ },
6314
+ "itemId": {
6315
+ "anyOf": [
6316
+ {
6317
+ "type": "integer",
6318
+ "exclusiveMinimum": 0
6319
+ },
6320
+ {
6321
+ "type": "string",
6322
+ "pattern": "^\\d+$"
6323
+ }
6324
+ ]
6325
+ },
6326
+ "itemText": {
6327
+ "type": "string"
6328
+ },
6329
+ "photoId": {
6330
+ "anyOf": [
6331
+ {
6332
+ "type": "integer",
6333
+ "exclusiveMinimum": 0
6334
+ },
6335
+ {
6336
+ "type": "string",
6337
+ "pattern": "^\\d+$"
6338
+ }
6339
+ ]
6340
+ },
6341
+ "caption": {
6342
+ "type": "string"
6343
+ }
6344
+ },
6345
+ "required": [
6346
+ "photoId"
6347
+ ],
6348
+ "description": "`arguments` of the Chatty tool `attach_reference_photo_to_item` (POST /api/chatty-voice/tools/execute)."
6349
+ },
6350
+ "ChattyAttachReferencePhotoToItemData": {
6351
+ "type": "object",
6352
+ "properties": {
6353
+ "checklistId": {
6354
+ "type": "integer"
6355
+ },
6356
+ "itemId": {
6357
+ "type": "integer"
6358
+ },
6359
+ "referenceMedia": {
6360
+ "type": "array",
6361
+ "items": {
6362
+ "type": "object",
6363
+ "properties": {
6364
+ "assetId": {
6365
+ "type": "string",
6366
+ "minLength": 1,
6367
+ "maxLength": 64
6368
+ },
6369
+ "caption": {
6370
+ "type": [
6371
+ "string",
6372
+ "null"
6373
+ ],
6374
+ "maxLength": 300
6375
+ },
6376
+ "order": {
6377
+ "type": "integer",
6378
+ "minimum": 0
6379
+ }
6380
+ },
6381
+ "required": [
6382
+ "assetId"
6383
+ ]
6384
+ }
6385
+ }
6386
+ },
6387
+ "required": [
6388
+ "checklistId",
6389
+ "itemId",
6390
+ "referenceMedia"
6391
+ ],
6392
+ "description": "`data` of a successful `attach_reference_photo_to_item` call (`success: true`)."
6393
+ },
6394
+ "ChattyDraftChecklistFromJobPhotosArguments": {
6395
+ "type": "object",
6396
+ "properties": {
6397
+ "jobId": {
6398
+ "anyOf": [
6399
+ {
6400
+ "type": "integer",
6401
+ "exclusiveMinimum": 0
6402
+ },
6403
+ {
6404
+ "type": "string",
6405
+ "pattern": "^\\d+$"
6406
+ }
6407
+ ]
6408
+ },
6409
+ "name": {
6410
+ "type": "string"
6411
+ },
6412
+ "create": {
6413
+ "type": "boolean"
6414
+ }
6415
+ },
6416
+ "description": "`arguments` of the Chatty tool `draft_checklist_from_job_photos` (POST /api/chatty-voice/tools/execute)."
6417
+ },
6418
+ "ChattyDraftChecklistFromJobPhotosData": {
6419
+ "type": "object",
6420
+ "properties": {
6421
+ "id": {
6422
+ "type": "integer"
6423
+ },
6424
+ "jobId": {
6425
+ "type": "integer"
6426
+ },
6427
+ "name": {
6428
+ "type": "string"
6429
+ },
6430
+ "items": {
6431
+ "type": "array",
6432
+ "items": {
6433
+ "type": "object",
6434
+ "properties": {
6435
+ "itemText": {
6436
+ "type": "string"
6437
+ },
6438
+ "photos": {
6439
+ "type": "integer"
6440
+ }
6441
+ },
6442
+ "required": [
6443
+ "itemText",
6444
+ "photos"
6445
+ ]
6446
+ }
6447
+ },
6448
+ "unsortedPhotos": {
6449
+ "type": "integer"
6450
+ },
6451
+ "created": {
6452
+ "type": "boolean"
6453
+ }
6454
+ },
6455
+ "required": [
6456
+ "name",
6457
+ "items",
6458
+ "unsortedPhotos",
6459
+ "created"
6460
+ ],
6461
+ "description": "`data` of a successful `draft_checklist_from_job_photos` call (`success: true`)."
6462
+ },
6463
+ "AssetInitUploadRequest": {
6464
+ "type": "object",
6465
+ "properties": {
6466
+ "filename": {
6467
+ "anyOf": [
6468
+ {
6469
+ "type": "string",
6470
+ "maxLength": 10000
6471
+ },
6472
+ {
6473
+ "type": "number"
6474
+ },
6475
+ {
6476
+ "type": "null"
6477
+ }
6478
+ ]
6479
+ },
6480
+ "byteSize": {
6481
+ "anyOf": [
6482
+ {
6483
+ "type": "number"
6484
+ },
6485
+ {
6486
+ "type": "string",
6487
+ "maxLength": 10000
6488
+ },
6489
+ {
6490
+ "type": "null"
6491
+ }
6492
+ ]
6493
+ },
6494
+ "clientQueueId": {
6495
+ "anyOf": [
6496
+ {
6497
+ "type": "string",
6498
+ "maxLength": 10000
6499
+ },
6500
+ {
6501
+ "type": "number"
6502
+ },
6503
+ {
6504
+ "type": "null"
6505
+ }
6506
+ ]
6507
+ },
6508
+ "pendingMetadata": {
6509
+ "type": [
6510
+ "object",
6511
+ "null"
6512
+ ],
6513
+ "additionalProperties": {}
6514
+ },
6515
+ "mimeType": {
6516
+ "anyOf": [
6517
+ {
6518
+ "type": "string",
6519
+ "maxLength": 10000
6520
+ },
6521
+ {
6522
+ "type": "number"
6523
+ },
6524
+ {
6525
+ "type": "null"
6526
+ }
6527
+ ]
6528
+ },
6529
+ "contentType": {
6530
+ "anyOf": [
6531
+ {
6532
+ "type": "string",
6533
+ "maxLength": 10000
6534
+ },
6535
+ {
6536
+ "type": "number"
6537
+ },
6538
+ {
6539
+ "type": "null"
6540
+ }
6541
+ ]
6542
+ },
6543
+ "poster": {
6544
+ "type": [
6545
+ "object",
6546
+ "null"
6547
+ ],
6548
+ "properties": {
6549
+ "contentType": {
6550
+ "type": "string",
6551
+ "enum": [
6552
+ "image/jpeg"
6553
+ ]
6554
+ },
6555
+ "byteSize": {
6556
+ "type": "integer",
6557
+ "exclusiveMinimum": 0,
6558
+ "maximum": 2097152
6559
+ }
6560
+ },
6561
+ "required": [
6562
+ "contentType",
6563
+ "byteSize"
6564
+ ]
6565
+ }
6566
+ },
6567
+ "description": "POST /api/assets/init-upload body. `filename` and `mimeType` (alias `contentType`) are required by the handler. `poster` is accepted only when the upload's content type is `video/*`: a JPEG frame of at most 2 MiB the client renders locally and PUTs to `posterUploadUrl`; on any other content type the response is 400 `poster_requires_video`."
6568
+ },
6569
+ "AssetInitUploadResponse": {
6570
+ "type": "object",
6571
+ "properties": {
6572
+ "assetId": {
6573
+ "type": "string"
6574
+ },
6575
+ "key": {
6576
+ "type": "string",
6577
+ "description": "Storage key of the original (`org/<orgId>/assets/<assetId>/original`)."
6578
+ },
6579
+ "putUrl": {
6580
+ "type": "string",
6581
+ "description": "Presigned PUT for the original. Absent when `alreadyCompleted` is true."
6582
+ },
6583
+ "headersToSend": {
6584
+ "type": "object",
6585
+ "additionalProperties": {
6586
+ "type": "string"
6587
+ }
6588
+ },
6589
+ "putUrlExpiresAt": {
6590
+ "type": "string",
6591
+ "description": "ISO instant; also the expiry of `posterUploadUrl`."
6592
+ },
6593
+ "reused": {
6594
+ "type": "boolean"
6595
+ },
6596
+ "alreadyCompleted": {
6597
+ "type": "boolean"
6598
+ },
6599
+ "posterUploadUrl": {
6600
+ "type": "string",
6601
+ "description": "Presigned PUT (Content-Type: image/jpeg) for the poster frame. Present only when `poster` was sent."
6602
+ },
6603
+ "posterKey": {
6604
+ "type": "string",
6605
+ "description": "The poster's storage key: the asset prefix with `/original` replaced by `/thumb_320`."
6606
+ }
6607
+ },
6608
+ "required": [
6609
+ "assetId",
6610
+ "key"
6611
+ ]
6612
+ },
6613
+ "AssetCompleteUploadRequest": {
6614
+ "type": "object",
6615
+ "properties": {
6616
+ "assetId": {
6617
+ "anyOf": [
6618
+ {
6619
+ "type": "string",
6620
+ "maxLength": 10000
6621
+ },
6622
+ {
6623
+ "type": "number"
6624
+ },
6625
+ {
6626
+ "type": "null"
6627
+ }
6628
+ ]
6629
+ },
6630
+ "clientQueueId": {
6631
+ "anyOf": [
6632
+ {
6633
+ "type": "string",
6634
+ "maxLength": 10000
6635
+ },
6636
+ {
6637
+ "type": "number"
6638
+ },
6639
+ {
6640
+ "type": "null"
6641
+ }
6642
+ ]
6643
+ },
6644
+ "gpsLatitude": {
6645
+ "anyOf": [
6646
+ {
6647
+ "type": "number"
6648
+ },
6649
+ {
6650
+ "type": "string",
6651
+ "maxLength": 10000
6652
+ },
6653
+ {
6654
+ "type": "null"
6655
+ }
6656
+ ]
6657
+ },
6658
+ "gpsLongitude": {
6659
+ "anyOf": [
6660
+ {
6661
+ "type": "number"
6662
+ },
6663
+ {
6664
+ "type": "string",
6665
+ "maxLength": 10000
6666
+ },
6667
+ {
6668
+ "type": "null"
6669
+ }
6670
+ ]
6671
+ },
6672
+ "gpsAddress": {
6673
+ "anyOf": [
6674
+ {
6675
+ "type": "string",
6676
+ "maxLength": 10000
6677
+ },
6678
+ {
6679
+ "type": "number"
6680
+ },
6681
+ {
6682
+ "type": "null"
6683
+ }
6684
+ ]
6685
+ },
6686
+ "captureTimestamp": {
6687
+ "anyOf": [
6688
+ {
6689
+ "type": "string"
6690
+ },
6691
+ {
6692
+ "type": "number"
6693
+ },
6694
+ {
6695
+ "type": "string",
6696
+ "format": "date-time"
6697
+ },
6698
+ {
6699
+ "type": "null"
6700
+ }
6701
+ ]
6702
+ },
6703
+ "deviceInfo": {
6704
+ "anyOf": [
6705
+ {
6706
+ "type": "string",
6707
+ "maxLength": 10000
6708
+ },
6709
+ {
6710
+ "type": "number"
6711
+ },
6712
+ {
6713
+ "type": "null"
6714
+ }
6715
+ ]
6716
+ },
6717
+ "overlayApplied": {
6718
+ "anyOf": [
6719
+ {
6720
+ "type": "boolean"
6721
+ },
6722
+ {
6723
+ "type": "string"
6724
+ },
6725
+ {
6726
+ "type": "number"
6727
+ },
6728
+ {
6729
+ "type": "null"
6730
+ }
6731
+ ]
6732
+ },
6733
+ "hasMarkup": {
6734
+ "anyOf": [
6735
+ {
6736
+ "type": "boolean"
6737
+ },
6738
+ {
6739
+ "type": "string"
6740
+ },
6741
+ {
6742
+ "type": "number"
6743
+ },
6744
+ {
6745
+ "type": "null"
6746
+ }
6747
+ ]
6748
+ },
6749
+ "tags": {
6750
+ "type": [
6751
+ "array",
6752
+ "null"
6753
+ ],
6754
+ "items": {}
6755
+ },
6756
+ "projectId": {
6757
+ "anyOf": [
6758
+ {
6759
+ "type": "number"
6760
+ },
6761
+ {
6762
+ "type": "string",
6763
+ "maxLength": 10000
6764
+ },
6765
+ {
6766
+ "type": "null"
6767
+ }
6768
+ ]
6769
+ },
6770
+ "contactId": {
6771
+ "anyOf": [
6772
+ {
6773
+ "type": "number"
6774
+ },
6775
+ {
6776
+ "type": "string",
6777
+ "maxLength": 10000
6778
+ },
6779
+ {
6780
+ "type": "null"
6781
+ }
6782
+ ]
6783
+ },
6784
+ "folderId": {
6785
+ "anyOf": [
6786
+ {
6787
+ "type": "string",
6788
+ "maxLength": 10000
6789
+ },
6790
+ {
6791
+ "type": "number"
6792
+ },
6793
+ {
6794
+ "type": "null"
6795
+ }
6796
+ ]
6797
+ },
6798
+ "description": {
6799
+ "anyOf": [
6800
+ {
6801
+ "type": "string",
6802
+ "maxLength": 200000
6803
+ },
6804
+ {
6805
+ "type": "number"
6806
+ },
6807
+ {
6808
+ "type": "null"
6809
+ }
6810
+ ]
6811
+ },
6812
+ "serverOverlay": {
6813
+ "type": [
6814
+ "object",
6815
+ "null"
6816
+ ],
6817
+ "additionalProperties": {}
6818
+ },
6819
+ "capturePose": {
6820
+ "type": [
6821
+ "object",
6822
+ "null"
6823
+ ],
6824
+ "additionalProperties": {}
6825
+ },
6826
+ "posterUploaded": {
6827
+ "anyOf": [
6828
+ {
6829
+ "type": "boolean"
6830
+ },
6831
+ {
6832
+ "type": "string"
6833
+ },
6834
+ {
6835
+ "type": "number"
6836
+ },
6837
+ {
6838
+ "type": "null"
6839
+ }
6840
+ ]
6841
+ }
6842
+ },
6843
+ "description": "POST /api/assets/complete-upload body. `assetId` or `clientQueueId` is required. `posterUploaded: true` (video uploads only) asks the server to verify the poster frame PUT to `posterUploadUrl` and use it as the thumbnail at once; a missing, oversized or non-JPEG poster never fails the upload — it completes without it."
6844
+ },
6845
+ "AssetCompleteUploadResponse": {
6846
+ "type": "object",
6847
+ "properties": {
6848
+ "ok": {
6849
+ "type": "boolean",
6850
+ "enum": [
6851
+ true
6852
+ ]
6853
+ },
6854
+ "assetId": {
6855
+ "type": "string"
6856
+ },
6857
+ "alreadyCompleted": {
6858
+ "type": "boolean"
6859
+ },
6860
+ "actions": {
6861
+ "type": "array",
6862
+ "items": {
6863
+ "type": "string"
6864
+ },
6865
+ "description": "Human-readable log of what finalize did (status change, links, pipeline dispatch, `thumbnail: client poster accepted (thumb_320)`)."
6866
+ }
6867
+ },
6868
+ "required": [
6869
+ "ok",
6870
+ "assetId",
6871
+ "alreadyCompleted",
6872
+ "actions"
6873
+ ]
6874
+ }
6875
+ },
6876
+ "parameters": {}
6877
+ },
6878
+ "paths": {
6879
+ "/api/version": {
6880
+ "get": {
6881
+ "summary": "Cross-platform version handshake manifest.",
6882
+ "tags": [
6883
+ "version"
6884
+ ],
6885
+ "responses": {
6886
+ "200": {
6887
+ "description": "Always returned. Body is the canonical handshake manifest.",
6888
+ "content": {
6889
+ "application/json": {
6890
+ "schema": {
6891
+ "$ref": "#/components/schemas/VersionManifest"
6892
+ }
6893
+ }
6894
+ }
6895
+ }
6896
+ }
6897
+ }
6898
+ },
6899
+ "/api/ping": {
6900
+ "get": {
6901
+ "summary": "Liveness probe. Bypasses the version handshake.",
6902
+ "tags": [
6903
+ "version"
6904
+ ],
6905
+ "responses": {
6906
+ "200": {
6907
+ "description": "Static OK envelope.",
6908
+ "content": {
6909
+ "application/json": {
6910
+ "schema": {
6911
+ "type": "object",
6912
+ "properties": {
6913
+ "status": {
6914
+ "type": "string",
6915
+ "enum": [
6916
+ "ok"
6917
+ ]
6918
+ },
6919
+ "timestamp": {
6920
+ "type": "string"
6921
+ },
6922
+ "env": {
6923
+ "type": [
6924
+ "string",
6925
+ "null"
6926
+ ]
6927
+ }
6928
+ },
6929
+ "required": [
6930
+ "status",
6931
+ "timestamp",
6932
+ "env"
6933
+ ]
6934
+ }
6935
+ }
6936
+ }
6937
+ }
6938
+ }
6939
+ }
6940
+ },
6941
+ "/api/me/features": {
6942
+ "get": {
6943
+ "summary": "Capability discovery — iOS calls on launch to gate UI affordances.",
6944
+ "tags": [
6945
+ "auth",
6946
+ "features"
6947
+ ],
6948
+ "parameters": [
6949
+ {
6950
+ "name": "X-Client-Version",
6951
+ "in": "header",
6952
+ "required": false,
6953
+ "schema": {
6954
+ "type": "string",
6955
+ "example": "1.0.0"
6956
+ },
6957
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
6958
+ }
6959
+ ],
6960
+ "responses": {
6961
+ "200": {
6962
+ "description": "Flat feature map. Unknown / missing flags must be treated as false by the client.",
6963
+ "content": {
6964
+ "application/json": {
6965
+ "schema": {
6966
+ "$ref": "#/components/schemas/FeatureFlags"
6967
+ }
6968
+ }
6969
+ }
6970
+ },
6971
+ "426": {
6972
+ "description": "Client major below minClientVersion.",
6973
+ "content": {
6974
+ "application/json": {
6975
+ "schema": {
6976
+ "$ref": "#/components/schemas/UpgradeRequiredEnvelope"
6977
+ }
6978
+ }
6979
+ }
6980
+ }
6981
+ }
6982
+ }
6983
+ },
6984
+ "/api/impersonate/native-read-ticket": {
6985
+ "post": {
6986
+ "tags": [
6987
+ "auth"
6988
+ ],
6989
+ "summary": "Authorize an exact browser-native download URL for the current support session.",
6990
+ "description": "Requires the current typed support session and X-Support-Impersonation: 1. A narrow fixed GET allowlist only; record permissions still run on every GET. Admission lasts at most 15 minutes and never outlives the original one-hour support grant. The same browser session is required; URL alone is insufficient. GET/Range retries recheck current authority. Response is no-store with no-referrer. No user bearer is issued.",
6991
+ "security": [
6992
+ {
6993
+ "BrowserSession": []
6994
+ }
6995
+ ],
6996
+ "parameters": [
6997
+ {
6998
+ "schema": {
6999
+ "type": "string",
7000
+ "enum": [
7001
+ "1"
7002
+ ]
7003
+ },
7004
+ "required": true,
7005
+ "name": "X-Support-Impersonation",
7006
+ "in": "header"
7007
+ }
7008
+ ],
7009
+ "requestBody": {
7010
+ "required": true,
7011
+ "content": {
7012
+ "application/json": {
7013
+ "schema": {
7014
+ "type": "object",
7015
+ "properties": {
7016
+ "url": {
7017
+ "type": "string",
7018
+ "minLength": 1,
7019
+ "maxLength": 1024
7020
+ }
7021
+ },
7022
+ "required": [
7023
+ "url"
7024
+ ],
7025
+ "additionalProperties": false
7026
+ }
7027
+ }
7028
+ }
7029
+ },
7030
+ "responses": {
7031
+ "200": {
7032
+ "description": "Exact relative URL and terminal admission deadline.",
7033
+ "content": {
7034
+ "application/json": {
7035
+ "schema": {
7036
+ "type": "object",
7037
+ "properties": {
7038
+ "url": {
7039
+ "type": "string",
7040
+ "minLength": 1,
7041
+ "maxLength": 8192
7042
+ },
7043
+ "expiresAt": {
7044
+ "type": "integer",
7045
+ "exclusiveMinimum": 0
7046
+ }
7047
+ },
7048
+ "required": [
7049
+ "url",
7050
+ "expiresAt"
7051
+ ],
7052
+ "additionalProperties": false
7053
+ }
7054
+ }
7055
+ }
7056
+ },
7057
+ "400": {
7058
+ "description": "Unsupported destination or malformed request."
7059
+ },
7060
+ "401": {
7061
+ "description": "No authenticated session."
7062
+ },
7063
+ "403": {
7064
+ "description": "Support authority unavailable; explicit exit required.",
7065
+ "content": {
7066
+ "application/json": {
7067
+ "schema": {
7068
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7069
+ }
7070
+ }
7071
+ }
7072
+ },
7073
+ "503": {
7074
+ "description": "Authentication lookup temporarily unavailable.",
7075
+ "content": {
7076
+ "application/json": {
7077
+ "schema": {
7078
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7079
+ }
7080
+ }
7081
+ }
7082
+ }
7083
+ }
7084
+ }
7085
+ },
7086
+ "/api/events/ticket": {
7087
+ "post": {
7088
+ "tags": [
7089
+ "auth"
7090
+ ],
7091
+ "summary": "Create a short-lived stream-only admission ticket from the current authenticated actor.",
7092
+ "description": "Connect within at most 60 seconds using GET /api/events?ticket=.... The ticket preserves the real principal, effective target and original login/impersonation deadlines; it cannot authenticate ordinary API requests. It is never a target-user bearer token. Response Cache-Control is no-store. An invalid temporary context returns 403 and must be explicitly exited, without dropping the real login.",
7093
+ "security": [
7094
+ {
7095
+ "UserBearer": []
7096
+ },
7097
+ {
7098
+ "BrowserSession": []
7099
+ },
7100
+ {
7101
+ "BrowserAuthCookie": []
7102
+ }
7103
+ ],
7104
+ "requestBody": {
7105
+ "required": false,
7106
+ "content": {
7107
+ "application/json": {
7108
+ "schema": {
7109
+ "type": "object",
7110
+ "properties": {},
7111
+ "additionalProperties": false
7112
+ }
7113
+ }
7114
+ }
7115
+ },
7116
+ "responses": {
7117
+ "200": {
7118
+ "description": "Opaque ticket, usable only for short-lived stream admission.",
7119
+ "content": {
7120
+ "application/json": {
7121
+ "schema": {
7122
+ "$ref": "#/components/schemas/EventStreamTicketResponse"
7123
+ }
7124
+ }
7125
+ }
7126
+ },
7127
+ "400": {
7128
+ "description": "Unexpected request fields.",
7129
+ "content": {
7130
+ "application/json": {
7131
+ "schema": {
7132
+ "type": "object",
7133
+ "properties": {
7134
+ "message": {
7135
+ "type": "string"
7136
+ },
7137
+ "errors": {
7138
+ "type": "array",
7139
+ "items": {}
7140
+ }
7141
+ },
7142
+ "required": [
7143
+ "message",
7144
+ "errors"
7145
+ ]
7146
+ }
7147
+ }
7148
+ }
7149
+ },
7150
+ "401": {
7151
+ "description": "Real principal is missing, deleted, revoked or expired.",
7152
+ "content": {
7153
+ "application/json": {
7154
+ "schema": {
7155
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7156
+ }
7157
+ }
7158
+ }
7159
+ },
7160
+ "403": {
7161
+ "description": "Impersonation is unavailable; explicitly exit before continuing as the real principal.",
7162
+ "content": {
7163
+ "application/json": {
7164
+ "schema": {
7165
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7166
+ }
7167
+ }
7168
+ }
7169
+ },
7170
+ "503": {
7171
+ "description": "Authentication lookup unavailable; retry without discarding credentials.",
7172
+ "content": {
7173
+ "application/json": {
7174
+ "schema": {
7175
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7176
+ }
7177
+ }
7178
+ }
7179
+ }
7180
+ }
7181
+ }
7182
+ },
7183
+ "/api/events": {
7184
+ "get": {
7185
+ "tags": [
7186
+ "auth"
7187
+ ],
7188
+ "summary": "Open the authenticated server-sent event stream.",
7189
+ "description": "New clients use a stream-only ticket in the ticket query parameter. Legacy authenticated connections remain supported. A supplied invalid ticket never falls back to another credential. Current user, session and revocation state is rechecked before admission and each delivery batch/heartbeat. Original authority deadlines also close idle or blocked sockets. A stream:resync hint means refresh authorized snapshots; this stream is not a replay log.",
7190
+ "parameters": [
7191
+ {
7192
+ "schema": {
7193
+ "type": "string",
7194
+ "minLength": 1,
7195
+ "maxLength": 8192
7196
+ },
7197
+ "required": false,
7198
+ "name": "ticket",
7199
+ "in": "query"
7200
+ }
7201
+ ],
7202
+ "responses": {
7203
+ "200": {
7204
+ "description": "Bounded SSE hints and heartbeat comments until disconnect or authority expiry.",
7205
+ "content": {
7206
+ "text/event-stream": {
7207
+ "schema": {
7208
+ "type": "string"
7209
+ }
7210
+ }
7211
+ }
7212
+ },
7213
+ "401": {
7214
+ "description": "Ticket/source authentication expired, revoked or invalid.",
7215
+ "content": {
7216
+ "application/json": {
7217
+ "schema": {
7218
+ "$ref": "#/components/schemas/StreamAuthenticationError"
7219
+ }
7220
+ }
7221
+ }
7222
+ },
7223
+ "403": {
7224
+ "description": "Legacy temporary context is unavailable.",
5118
7225
  "content": {
5119
7226
  "application/json": {
5120
7227
  "schema": {
5121
- "$ref": "#/components/schemas/FeatureFlags"
7228
+ "$ref": "#/components/schemas/StreamAuthenticationError"
5122
7229
  }
5123
7230
  }
5124
7231
  }
5125
7232
  },
5126
- "426": {
5127
- "description": "Client major below minClientVersion.",
7233
+ "503": {
7234
+ "description": "Authorization temporarily unavailable; retry with backoff.",
5128
7235
  "content": {
5129
7236
  "application/json": {
5130
7237
  "schema": {
5131
- "$ref": "#/components/schemas/UpgradeRequiredEnvelope"
7238
+ "$ref": "#/components/schemas/StreamAuthenticationError"
5132
7239
  }
5133
7240
  }
5134
7241
  }
@@ -11150,6 +13257,294 @@
11150
13257
  }
11151
13258
  }
11152
13259
  }
13260
+ },
13261
+ "/api/projects/{projectId}/documents/draft-from-walkthrough": {
13262
+ "post": {
13263
+ "tags": [
13264
+ "checklists"
13265
+ ],
13266
+ "summary": "Turn a voice walk-through (timed transcript + photos) into a checklist draft.",
13267
+ "description": "Returns a DRAFT only; nothing is saved to the job. The phone's review screen creates the checklist with POST /api/projects/{projectId}/documents (custom `items`, carrying `referenceMedia`). Sections come from, in order: the camera pose of a scan, the room the tech named (the item's words, the photo's room chip, a section opened), the AI Image Sort's room for the item's photo (add-on), then the last room mentioned; items with no signal go to Not sure. GPS is never used. Item types come from spoken hints only (checkbox unless \"photo required\", \"yes or no\" or a reading; \"required\" sets the flag). Reference photos are the shots taken from 10 s before a sentence to 20 s after it. 200 when the draft is ready at once; 202 with `runId` while the photos go through an AI vision sort (poll the runs route). Requires the job (404 otherwise) and the Create Checklists permission (403). Photos that are not the organization's assets are left out.",
13268
+ "parameters": [
13269
+ {
13270
+ "name": "projectId",
13271
+ "in": "path",
13272
+ "required": true,
13273
+ "schema": {
13274
+ "type": "integer",
13275
+ "minimum": 1
13276
+ }
13277
+ }
13278
+ ],
13279
+ "requestBody": {
13280
+ "required": true,
13281
+ "content": {
13282
+ "application/json": {
13283
+ "schema": {
13284
+ "$ref": "#/components/schemas/WalkthroughDraftRequest"
13285
+ }
13286
+ }
13287
+ }
13288
+ },
13289
+ "responses": {
13290
+ "200": {
13291
+ "description": "The draft (status completed).",
13292
+ "content": {
13293
+ "application/json": {
13294
+ "schema": {
13295
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
13296
+ }
13297
+ }
13298
+ }
13299
+ },
13300
+ "202": {
13301
+ "description": "A vision sort runs first (status running); poll GET …/draft-from-walkthrough/runs/{runId}.",
13302
+ "content": {
13303
+ "application/json": {
13304
+ "schema": {
13305
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
13306
+ }
13307
+ }
13308
+ }
13309
+ },
13310
+ "400": {
13311
+ "description": "No transcript, or a wrong shape.",
13312
+ "content": {
13313
+ "application/json": {
13314
+ "schema": {
13315
+ "$ref": "#/components/schemas/ErrorEnvelope"
13316
+ }
13317
+ }
13318
+ }
13319
+ },
13320
+ "401": {
13321
+ "description": "Authentication required."
13322
+ },
13323
+ "403": {
13324
+ "description": "The role cannot create checklists.",
13325
+ "content": {
13326
+ "application/json": {
13327
+ "schema": {
13328
+ "$ref": "#/components/schemas/ErrorEnvelope"
13329
+ }
13330
+ }
13331
+ }
13332
+ },
13333
+ "404": {
13334
+ "description": "Job not found.",
13335
+ "content": {
13336
+ "application/json": {
13337
+ "schema": {
13338
+ "$ref": "#/components/schemas/ErrorEnvelope"
13339
+ }
13340
+ }
13341
+ }
13342
+ },
13343
+ "502": {
13344
+ "description": "The AI's answer could not be used.",
13345
+ "content": {
13346
+ "application/json": {
13347
+ "schema": {
13348
+ "$ref": "#/components/schemas/ErrorEnvelope"
13349
+ }
13350
+ }
13351
+ }
13352
+ },
13353
+ "503": {
13354
+ "description": "AI is not configured.",
13355
+ "content": {
13356
+ "application/json": {
13357
+ "schema": {
13358
+ "$ref": "#/components/schemas/ErrorEnvelope"
13359
+ }
13360
+ }
13361
+ }
13362
+ }
13363
+ }
13364
+ }
13365
+ },
13366
+ "/api/projects/{projectId}/documents/draft-from-walkthrough/runs/{runId}": {
13367
+ "get": {
13368
+ "tags": [
13369
+ "checklists"
13370
+ ],
13371
+ "summary": "Poll a walk-through draft that waits for an AI vision sort.",
13372
+ "description": "Status `running` (with the sort's progress in `sortRun`) until the draft is ready, then `completed` with `draft`, or `failed` with `message`. A run that stops making progress is marked failed on the next poll and never re-run.",
13373
+ "parameters": [
13374
+ {
13375
+ "name": "projectId",
13376
+ "in": "path",
13377
+ "required": true,
13378
+ "schema": {
13379
+ "type": "integer",
13380
+ "minimum": 1
13381
+ }
13382
+ },
13383
+ {
13384
+ "name": "runId",
13385
+ "in": "path",
13386
+ "required": true,
13387
+ "schema": {
13388
+ "type": "integer",
13389
+ "minimum": 1
13390
+ }
13391
+ }
13392
+ ],
13393
+ "responses": {
13394
+ "200": {
13395
+ "description": "The run's envelope.",
13396
+ "content": {
13397
+ "application/json": {
13398
+ "schema": {
13399
+ "$ref": "#/components/schemas/WalkthroughDraftResponse"
13400
+ }
13401
+ }
13402
+ }
13403
+ },
13404
+ "401": {
13405
+ "description": "Authentication required."
13406
+ },
13407
+ "403": {
13408
+ "description": "The role cannot create checklists.",
13409
+ "content": {
13410
+ "application/json": {
13411
+ "schema": {
13412
+ "$ref": "#/components/schemas/ErrorEnvelope"
13413
+ }
13414
+ }
13415
+ }
13416
+ },
13417
+ "404": {
13418
+ "description": "Job or run not found.",
13419
+ "content": {
13420
+ "application/json": {
13421
+ "schema": {
13422
+ "$ref": "#/components/schemas/ErrorEnvelope"
13423
+ }
13424
+ }
13425
+ }
13426
+ }
13427
+ }
13428
+ }
13429
+ },
13430
+ "/api/assets/init-upload": {
13431
+ "post": {
13432
+ "summary": "Open a direct-to-S3 upload: presigned PUT for the original, and for a video's optional poster frame.",
13433
+ "tags": [
13434
+ "photos"
13435
+ ],
13436
+ "parameters": [
13437
+ {
13438
+ "name": "X-Client-Version",
13439
+ "in": "header",
13440
+ "required": false,
13441
+ "schema": {
13442
+ "type": "string",
13443
+ "example": "1.0.0"
13444
+ },
13445
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
13446
+ }
13447
+ ],
13448
+ "requestBody": {
13449
+ "required": true,
13450
+ "content": {
13451
+ "application/json": {
13452
+ "schema": {
13453
+ "$ref": "#/components/schemas/AssetInitUploadRequest"
13454
+ }
13455
+ }
13456
+ }
13457
+ },
13458
+ "responses": {
13459
+ "200": {
13460
+ "description": "Presigned URL(s) and the asset id to pass to complete-upload.",
13461
+ "content": {
13462
+ "application/json": {
13463
+ "schema": {
13464
+ "$ref": "#/components/schemas/AssetInitUploadResponse"
13465
+ }
13466
+ }
13467
+ }
13468
+ },
13469
+ "400": {
13470
+ "description": "Missing filename/mimeType, or a `poster` on a non-video upload (`poster_requires_video`).",
13471
+ "content": {
13472
+ "application/json": {
13473
+ "schema": {
13474
+ "$ref": "#/components/schemas/ErrorEnvelope"
13475
+ }
13476
+ }
13477
+ }
13478
+ },
13479
+ "401": {
13480
+ "description": "Authentication required."
13481
+ },
13482
+ "413": {
13483
+ "description": "File larger than the single-PUT limit."
13484
+ }
13485
+ }
13486
+ }
13487
+ },
13488
+ "/api/assets/complete-upload": {
13489
+ "post": {
13490
+ "summary": "Mark a direct upload complete (idempotent); link it to a job/contact; dispatch processing.",
13491
+ "tags": [
13492
+ "photos"
13493
+ ],
13494
+ "parameters": [
13495
+ {
13496
+ "name": "X-Client-Version",
13497
+ "in": "header",
13498
+ "required": false,
13499
+ "schema": {
13500
+ "type": "string",
13501
+ "example": "1.0.0"
13502
+ },
13503
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
13504
+ }
13505
+ ],
13506
+ "requestBody": {
13507
+ "required": true,
13508
+ "content": {
13509
+ "application/json": {
13510
+ "schema": {
13511
+ "$ref": "#/components/schemas/AssetCompleteUploadRequest"
13512
+ }
13513
+ }
13514
+ }
13515
+ },
13516
+ "responses": {
13517
+ "200": {
13518
+ "description": "Finalized (or already was).",
13519
+ "content": {
13520
+ "application/json": {
13521
+ "schema": {
13522
+ "$ref": "#/components/schemas/AssetCompleteUploadResponse"
13523
+ }
13524
+ }
13525
+ }
13526
+ },
13527
+ "400": {
13528
+ "description": "Neither assetId nor clientQueueId.",
13529
+ "content": {
13530
+ "application/json": {
13531
+ "schema": {
13532
+ "$ref": "#/components/schemas/ErrorEnvelope"
13533
+ }
13534
+ }
13535
+ }
13536
+ },
13537
+ "401": {
13538
+ "description": "Authentication required."
13539
+ },
13540
+ "403": {
13541
+ "description": "Attaching to a job/contact without the Upload Files permission."
13542
+ },
13543
+ "404": {
13544
+ "description": "Asset, job or contact not found in the organization."
13545
+ }
13546
+ }
13547
+ }
11153
13548
  }
11154
13549
  },
11155
13550
  "webhooks": {}