@serviceai/api-spec 1.6.1 → 1.6.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/openapi.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "openapi": "3.1.0",
3
3
  "info": {
4
4
  "title": "ServiceAi API",
5
- "version": "1.6.1",
5
+ "version": "1.6.3",
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",
@@ -146,7 +146,7 @@
146
146
  "properties": {
147
147
  "apiVersion": {
148
148
  "type": "string",
149
- "example": "1.6.1"
149
+ "example": "1.6.3"
150
150
  },
151
151
  "minClientVersion": {
152
152
  "type": "string",
@@ -4975,6 +4975,85 @@
4975
4975
  ],
4976
4976
  "additionalProperties": false
4977
4977
  },
4978
+ {
4979
+ "type": "object",
4980
+ "properties": {
4981
+ "action": {
4982
+ "type": "string",
4983
+ "enum": [
4984
+ "separate"
4985
+ ]
4986
+ },
4987
+ "rooms": {
4988
+ "type": "array",
4989
+ "items": {
4990
+ "type": "object",
4991
+ "properties": {
4992
+ "id": {
4993
+ "type": "integer",
4994
+ "exclusiveMinimum": 0
4995
+ },
4996
+ "revision": {
4997
+ "type": "string",
4998
+ "pattern": "^[a-f0-9]{64}$"
4999
+ }
5000
+ },
5001
+ "required": [
5002
+ "id",
5003
+ "revision"
5004
+ ],
5005
+ "additionalProperties": false
5006
+ }
5007
+ }
5008
+ },
5009
+ "required": [
5010
+ "action",
5011
+ "rooms"
5012
+ ],
5013
+ "additionalProperties": false
5014
+ },
5015
+ {
5016
+ "type": "object",
5017
+ "properties": {
5018
+ "action": {
5019
+ "type": "string",
5020
+ "enum": [
5021
+ "disconnect"
5022
+ ]
5023
+ },
5024
+ "connectionId": {
5025
+ "type": "integer",
5026
+ "exclusiveMinimum": 0
5027
+ },
5028
+ "rooms": {
5029
+ "type": "array",
5030
+ "items": {
5031
+ "type": "object",
5032
+ "properties": {
5033
+ "id": {
5034
+ "type": "integer",
5035
+ "exclusiveMinimum": 0
5036
+ },
5037
+ "revision": {
5038
+ "type": "string",
5039
+ "pattern": "^[a-f0-9]{64}$"
5040
+ }
5041
+ },
5042
+ "required": [
5043
+ "id",
5044
+ "revision"
5045
+ ],
5046
+ "additionalProperties": false
5047
+ }
5048
+ }
5049
+ },
5050
+ "required": [
5051
+ "action",
5052
+ "connectionId",
5053
+ "rooms"
5054
+ ],
5055
+ "additionalProperties": false
5056
+ },
4978
5057
  {
4979
5058
  "type": "object",
4980
5059
  "properties": {
@@ -6306,159 +6385,571 @@
6306
6385
  "exclusiveMinimum": 0
6307
6386
  },
6308
6387
  {
6309
- "type": "string",
6310
- "pattern": "^\\d+$"
6388
+ "type": "string",
6389
+ "pattern": "^\\d+$"
6390
+ }
6391
+ ]
6392
+ },
6393
+ "itemId": {
6394
+ "anyOf": [
6395
+ {
6396
+ "type": "integer",
6397
+ "exclusiveMinimum": 0
6398
+ },
6399
+ {
6400
+ "type": "string",
6401
+ "pattern": "^\\d+$"
6402
+ }
6403
+ ]
6404
+ },
6405
+ "itemText": {
6406
+ "type": "string"
6407
+ },
6408
+ "photoId": {
6409
+ "anyOf": [
6410
+ {
6411
+ "type": "integer",
6412
+ "exclusiveMinimum": 0
6413
+ },
6414
+ {
6415
+ "type": "string",
6416
+ "pattern": "^\\d+$"
6417
+ }
6418
+ ]
6419
+ },
6420
+ "caption": {
6421
+ "type": "string"
6422
+ }
6423
+ },
6424
+ "required": [
6425
+ "photoId"
6426
+ ],
6427
+ "description": "`arguments` of the Chatty tool `attach_reference_photo_to_item` (POST /api/chatty-voice/tools/execute)."
6428
+ },
6429
+ "ChattyAttachReferencePhotoToItemData": {
6430
+ "type": "object",
6431
+ "properties": {
6432
+ "checklistId": {
6433
+ "type": "integer"
6434
+ },
6435
+ "itemId": {
6436
+ "type": "integer"
6437
+ },
6438
+ "referenceMedia": {
6439
+ "type": "array",
6440
+ "items": {
6441
+ "type": "object",
6442
+ "properties": {
6443
+ "assetId": {
6444
+ "type": "string",
6445
+ "minLength": 1,
6446
+ "maxLength": 64
6447
+ },
6448
+ "caption": {
6449
+ "type": [
6450
+ "string",
6451
+ "null"
6452
+ ],
6453
+ "maxLength": 300
6454
+ },
6455
+ "order": {
6456
+ "type": "integer",
6457
+ "minimum": 0
6458
+ }
6459
+ },
6460
+ "required": [
6461
+ "assetId"
6462
+ ]
6463
+ }
6464
+ }
6465
+ },
6466
+ "required": [
6467
+ "checklistId",
6468
+ "itemId",
6469
+ "referenceMedia"
6470
+ ],
6471
+ "description": "`data` of a successful `attach_reference_photo_to_item` call (`success: true`)."
6472
+ },
6473
+ "ChattyDraftChecklistFromJobPhotosArguments": {
6474
+ "type": "object",
6475
+ "properties": {
6476
+ "jobId": {
6477
+ "anyOf": [
6478
+ {
6479
+ "type": "integer",
6480
+ "exclusiveMinimum": 0
6481
+ },
6482
+ {
6483
+ "type": "string",
6484
+ "pattern": "^\\d+$"
6485
+ }
6486
+ ]
6487
+ },
6488
+ "name": {
6489
+ "type": "string"
6490
+ },
6491
+ "create": {
6492
+ "type": "boolean"
6493
+ }
6494
+ },
6495
+ "description": "`arguments` of the Chatty tool `draft_checklist_from_job_photos` (POST /api/chatty-voice/tools/execute)."
6496
+ },
6497
+ "ChattyDraftChecklistFromJobPhotosData": {
6498
+ "type": "object",
6499
+ "properties": {
6500
+ "id": {
6501
+ "type": "integer"
6502
+ },
6503
+ "jobId": {
6504
+ "type": "integer"
6505
+ },
6506
+ "name": {
6507
+ "type": "string"
6508
+ },
6509
+ "items": {
6510
+ "type": "array",
6511
+ "items": {
6512
+ "type": "object",
6513
+ "properties": {
6514
+ "itemText": {
6515
+ "type": "string"
6516
+ },
6517
+ "photos": {
6518
+ "type": "integer"
6519
+ }
6520
+ },
6521
+ "required": [
6522
+ "itemText",
6523
+ "photos"
6524
+ ]
6525
+ }
6526
+ },
6527
+ "unsortedPhotos": {
6528
+ "type": "integer"
6529
+ },
6530
+ "created": {
6531
+ "type": "boolean"
6532
+ }
6533
+ },
6534
+ "required": [
6535
+ "name",
6536
+ "items",
6537
+ "unsortedPhotos",
6538
+ "created"
6539
+ ],
6540
+ "description": "`data` of a successful `draft_checklist_from_job_photos` call (`success: true`)."
6541
+ },
6542
+ "AssetInitUploadRequest": {
6543
+ "type": "object",
6544
+ "properties": {
6545
+ "filename": {
6546
+ "anyOf": [
6547
+ {
6548
+ "type": "string",
6549
+ "maxLength": 10000
6550
+ },
6551
+ {
6552
+ "type": "number"
6553
+ },
6554
+ {
6555
+ "type": "null"
6556
+ }
6557
+ ]
6558
+ },
6559
+ "byteSize": {
6560
+ "anyOf": [
6561
+ {
6562
+ "type": "number"
6563
+ },
6564
+ {
6565
+ "type": "string",
6566
+ "maxLength": 10000
6567
+ },
6568
+ {
6569
+ "type": "null"
6570
+ }
6571
+ ]
6572
+ },
6573
+ "clientQueueId": {
6574
+ "anyOf": [
6575
+ {
6576
+ "type": "string",
6577
+ "maxLength": 10000
6578
+ },
6579
+ {
6580
+ "type": "number"
6581
+ },
6582
+ {
6583
+ "type": "null"
6584
+ }
6585
+ ]
6586
+ },
6587
+ "pendingMetadata": {
6588
+ "type": [
6589
+ "object",
6590
+ "null"
6591
+ ],
6592
+ "additionalProperties": {}
6593
+ },
6594
+ "mimeType": {
6595
+ "anyOf": [
6596
+ {
6597
+ "type": "string",
6598
+ "maxLength": 10000
6599
+ },
6600
+ {
6601
+ "type": "number"
6602
+ },
6603
+ {
6604
+ "type": "null"
6605
+ }
6606
+ ]
6607
+ },
6608
+ "contentType": {
6609
+ "anyOf": [
6610
+ {
6611
+ "type": "string",
6612
+ "maxLength": 10000
6613
+ },
6614
+ {
6615
+ "type": "number"
6616
+ },
6617
+ {
6618
+ "type": "null"
6619
+ }
6620
+ ]
6621
+ },
6622
+ "poster": {
6623
+ "type": [
6624
+ "object",
6625
+ "null"
6626
+ ],
6627
+ "properties": {
6628
+ "contentType": {
6629
+ "type": "string",
6630
+ "enum": [
6631
+ "image/jpeg"
6632
+ ]
6633
+ },
6634
+ "byteSize": {
6635
+ "type": "integer",
6636
+ "exclusiveMinimum": 0,
6637
+ "maximum": 2097152
6638
+ }
6639
+ },
6640
+ "required": [
6641
+ "contentType",
6642
+ "byteSize"
6643
+ ]
6644
+ }
6645
+ },
6646
+ "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`."
6647
+ },
6648
+ "AssetInitUploadResponse": {
6649
+ "type": "object",
6650
+ "properties": {
6651
+ "assetId": {
6652
+ "type": "string"
6653
+ },
6654
+ "key": {
6655
+ "type": "string",
6656
+ "description": "Storage key of the original (`org/<orgId>/assets/<assetId>/original`)."
6657
+ },
6658
+ "putUrl": {
6659
+ "type": "string",
6660
+ "description": "Presigned PUT for the original. Absent when `alreadyCompleted` is true."
6661
+ },
6662
+ "headersToSend": {
6663
+ "type": "object",
6664
+ "additionalProperties": {
6665
+ "type": "string"
6666
+ }
6667
+ },
6668
+ "putUrlExpiresAt": {
6669
+ "type": "string",
6670
+ "description": "ISO instant; also the expiry of `posterUploadUrl`."
6671
+ },
6672
+ "reused": {
6673
+ "type": "boolean"
6674
+ },
6675
+ "alreadyCompleted": {
6676
+ "type": "boolean"
6677
+ },
6678
+ "posterUploadUrl": {
6679
+ "type": "string",
6680
+ "description": "Presigned PUT (Content-Type: image/jpeg) for the poster frame. Present only when `poster` was sent."
6681
+ },
6682
+ "posterKey": {
6683
+ "type": "string",
6684
+ "description": "The poster's storage key: the asset prefix with `/original` replaced by `/thumb_320`."
6685
+ }
6686
+ },
6687
+ "required": [
6688
+ "assetId",
6689
+ "key"
6690
+ ]
6691
+ },
6692
+ "AssetCompleteUploadRequest": {
6693
+ "type": "object",
6694
+ "properties": {
6695
+ "assetId": {
6696
+ "anyOf": [
6697
+ {
6698
+ "type": "string",
6699
+ "maxLength": 10000
6700
+ },
6701
+ {
6702
+ "type": "number"
6703
+ },
6704
+ {
6705
+ "type": "null"
6706
+ }
6707
+ ]
6708
+ },
6709
+ "clientQueueId": {
6710
+ "anyOf": [
6711
+ {
6712
+ "type": "string",
6713
+ "maxLength": 10000
6714
+ },
6715
+ {
6716
+ "type": "number"
6717
+ },
6718
+ {
6719
+ "type": "null"
6720
+ }
6721
+ ]
6722
+ },
6723
+ "gpsLatitude": {
6724
+ "anyOf": [
6725
+ {
6726
+ "type": "number"
6727
+ },
6728
+ {
6729
+ "type": "string",
6730
+ "maxLength": 10000
6731
+ },
6732
+ {
6733
+ "type": "null"
6734
+ }
6735
+ ]
6736
+ },
6737
+ "gpsLongitude": {
6738
+ "anyOf": [
6739
+ {
6740
+ "type": "number"
6741
+ },
6742
+ {
6743
+ "type": "string",
6744
+ "maxLength": 10000
6745
+ },
6746
+ {
6747
+ "type": "null"
6748
+ }
6749
+ ]
6750
+ },
6751
+ "gpsAddress": {
6752
+ "anyOf": [
6753
+ {
6754
+ "type": "string",
6755
+ "maxLength": 10000
6756
+ },
6757
+ {
6758
+ "type": "number"
6759
+ },
6760
+ {
6761
+ "type": "null"
6762
+ }
6763
+ ]
6764
+ },
6765
+ "captureTimestamp": {
6766
+ "anyOf": [
6767
+ {
6768
+ "type": "string"
6769
+ },
6770
+ {
6771
+ "type": "number"
6772
+ },
6773
+ {
6774
+ "type": "string",
6775
+ "format": "date-time"
6776
+ },
6777
+ {
6778
+ "type": "null"
6779
+ }
6780
+ ]
6781
+ },
6782
+ "deviceInfo": {
6783
+ "anyOf": [
6784
+ {
6785
+ "type": "string",
6786
+ "maxLength": 10000
6787
+ },
6788
+ {
6789
+ "type": "number"
6790
+ },
6791
+ {
6792
+ "type": "null"
6793
+ }
6794
+ ]
6795
+ },
6796
+ "overlayApplied": {
6797
+ "anyOf": [
6798
+ {
6799
+ "type": "boolean"
6800
+ },
6801
+ {
6802
+ "type": "string"
6803
+ },
6804
+ {
6805
+ "type": "number"
6806
+ },
6807
+ {
6808
+ "type": "null"
6809
+ }
6810
+ ]
6811
+ },
6812
+ "hasMarkup": {
6813
+ "anyOf": [
6814
+ {
6815
+ "type": "boolean"
6816
+ },
6817
+ {
6818
+ "type": "string"
6819
+ },
6820
+ {
6821
+ "type": "number"
6822
+ },
6823
+ {
6824
+ "type": "null"
6825
+ }
6826
+ ]
6827
+ },
6828
+ "tags": {
6829
+ "type": [
6830
+ "array",
6831
+ "null"
6832
+ ],
6833
+ "items": {}
6834
+ },
6835
+ "projectId": {
6836
+ "anyOf": [
6837
+ {
6838
+ "type": "number"
6839
+ },
6840
+ {
6841
+ "type": "string",
6842
+ "maxLength": 10000
6843
+ },
6844
+ {
6845
+ "type": "null"
6846
+ }
6847
+ ]
6848
+ },
6849
+ "contactId": {
6850
+ "anyOf": [
6851
+ {
6852
+ "type": "number"
6853
+ },
6854
+ {
6855
+ "type": "string",
6856
+ "maxLength": 10000
6857
+ },
6858
+ {
6859
+ "type": "null"
6860
+ }
6861
+ ]
6862
+ },
6863
+ "folderId": {
6864
+ "anyOf": [
6865
+ {
6866
+ "type": "string",
6867
+ "maxLength": 10000
6868
+ },
6869
+ {
6870
+ "type": "number"
6871
+ },
6872
+ {
6873
+ "type": "null"
6311
6874
  }
6312
6875
  ]
6313
6876
  },
6314
- "itemId": {
6877
+ "description": {
6315
6878
  "anyOf": [
6316
6879
  {
6317
- "type": "integer",
6318
- "exclusiveMinimum": 0
6880
+ "type": "string",
6881
+ "maxLength": 200000
6319
6882
  },
6320
6883
  {
6321
- "type": "string",
6322
- "pattern": "^\\d+$"
6884
+ "type": "number"
6885
+ },
6886
+ {
6887
+ "type": "null"
6323
6888
  }
6324
6889
  ]
6325
6890
  },
6326
- "itemText": {
6327
- "type": "string"
6891
+ "serverOverlay": {
6892
+ "type": [
6893
+ "object",
6894
+ "null"
6895
+ ],
6896
+ "additionalProperties": {}
6328
6897
  },
6329
- "photoId": {
6898
+ "capturePose": {
6899
+ "type": [
6900
+ "object",
6901
+ "null"
6902
+ ],
6903
+ "additionalProperties": {}
6904
+ },
6905
+ "posterUploaded": {
6330
6906
  "anyOf": [
6331
6907
  {
6332
- "type": "integer",
6333
- "exclusiveMinimum": 0
6908
+ "type": "boolean"
6334
6909
  },
6335
6910
  {
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
- }
6911
+ "type": "string"
6380
6912
  },
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
6913
  {
6400
- "type": "integer",
6401
- "exclusiveMinimum": 0
6914
+ "type": "number"
6402
6915
  },
6403
6916
  {
6404
- "type": "string",
6405
- "pattern": "^\\d+$"
6917
+ "type": "null"
6406
6918
  }
6407
6919
  ]
6408
- },
6409
- "name": {
6410
- "type": "string"
6411
- },
6412
- "create": {
6413
- "type": "boolean"
6414
6920
  }
6415
6921
  },
6416
- "description": "`arguments` of the Chatty tool `draft_checklist_from_job_photos` (POST /api/chatty-voice/tools/execute)."
6922
+ "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."
6417
6923
  },
6418
- "ChattyDraftChecklistFromJobPhotosData": {
6924
+ "AssetCompleteUploadResponse": {
6419
6925
  "type": "object",
6420
6926
  "properties": {
6421
- "id": {
6422
- "type": "integer"
6423
- },
6424
- "jobId": {
6425
- "type": "integer"
6927
+ "ok": {
6928
+ "type": "boolean",
6929
+ "enum": [
6930
+ true
6931
+ ]
6426
6932
  },
6427
- "name": {
6933
+ "assetId": {
6428
6934
  "type": "string"
6429
6935
  },
6430
- "items": {
6936
+ "alreadyCompleted": {
6937
+ "type": "boolean"
6938
+ },
6939
+ "actions": {
6431
6940
  "type": "array",
6432
6941
  "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"
6942
+ "type": "string"
6943
+ },
6944
+ "description": "Human-readable log of what finalize did (status change, links, pipeline dispatch, `thumbnail: client poster accepted (thumb_320)`)."
6453
6945
  }
6454
6946
  },
6455
6947
  "required": [
6456
- "name",
6457
- "items",
6458
- "unsortedPhotos",
6459
- "created"
6460
- ],
6461
- "description": "`data` of a successful `draft_checklist_from_job_photos` call (`success: true`)."
6948
+ "ok",
6949
+ "assetId",
6950
+ "alreadyCompleted",
6951
+ "actions"
6952
+ ]
6462
6953
  }
6463
6954
  },
6464
6955
  "parameters": {}
@@ -13014,6 +13505,125 @@
13014
13505
  }
13015
13506
  }
13016
13507
  }
13508
+ },
13509
+ "/api/assets/init-upload": {
13510
+ "post": {
13511
+ "summary": "Open a direct-to-S3 upload: presigned PUT for the original, and for a video's optional poster frame.",
13512
+ "tags": [
13513
+ "photos"
13514
+ ],
13515
+ "parameters": [
13516
+ {
13517
+ "name": "X-Client-Version",
13518
+ "in": "header",
13519
+ "required": false,
13520
+ "schema": {
13521
+ "type": "string",
13522
+ "example": "1.0.0"
13523
+ },
13524
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
13525
+ }
13526
+ ],
13527
+ "requestBody": {
13528
+ "required": true,
13529
+ "content": {
13530
+ "application/json": {
13531
+ "schema": {
13532
+ "$ref": "#/components/schemas/AssetInitUploadRequest"
13533
+ }
13534
+ }
13535
+ }
13536
+ },
13537
+ "responses": {
13538
+ "200": {
13539
+ "description": "Presigned URL(s) and the asset id to pass to complete-upload.",
13540
+ "content": {
13541
+ "application/json": {
13542
+ "schema": {
13543
+ "$ref": "#/components/schemas/AssetInitUploadResponse"
13544
+ }
13545
+ }
13546
+ }
13547
+ },
13548
+ "400": {
13549
+ "description": "Missing filename/mimeType, or a `poster` on a non-video upload (`poster_requires_video`).",
13550
+ "content": {
13551
+ "application/json": {
13552
+ "schema": {
13553
+ "$ref": "#/components/schemas/ErrorEnvelope"
13554
+ }
13555
+ }
13556
+ }
13557
+ },
13558
+ "401": {
13559
+ "description": "Authentication required."
13560
+ },
13561
+ "413": {
13562
+ "description": "File larger than the single-PUT limit."
13563
+ }
13564
+ }
13565
+ }
13566
+ },
13567
+ "/api/assets/complete-upload": {
13568
+ "post": {
13569
+ "summary": "Mark a direct upload complete (idempotent); link it to a job/contact; dispatch processing.",
13570
+ "tags": [
13571
+ "photos"
13572
+ ],
13573
+ "parameters": [
13574
+ {
13575
+ "name": "X-Client-Version",
13576
+ "in": "header",
13577
+ "required": false,
13578
+ "schema": {
13579
+ "type": "string",
13580
+ "example": "1.0.0"
13581
+ },
13582
+ "description": "Semver of the calling app build. Drives the 426 / soft-upgrade handshake."
13583
+ }
13584
+ ],
13585
+ "requestBody": {
13586
+ "required": true,
13587
+ "content": {
13588
+ "application/json": {
13589
+ "schema": {
13590
+ "$ref": "#/components/schemas/AssetCompleteUploadRequest"
13591
+ }
13592
+ }
13593
+ }
13594
+ },
13595
+ "responses": {
13596
+ "200": {
13597
+ "description": "Finalized (or already was).",
13598
+ "content": {
13599
+ "application/json": {
13600
+ "schema": {
13601
+ "$ref": "#/components/schemas/AssetCompleteUploadResponse"
13602
+ }
13603
+ }
13604
+ }
13605
+ },
13606
+ "400": {
13607
+ "description": "Neither assetId nor clientQueueId.",
13608
+ "content": {
13609
+ "application/json": {
13610
+ "schema": {
13611
+ "$ref": "#/components/schemas/ErrorEnvelope"
13612
+ }
13613
+ }
13614
+ }
13615
+ },
13616
+ "401": {
13617
+ "description": "Authentication required."
13618
+ },
13619
+ "403": {
13620
+ "description": "Attaching to a job/contact without the Upload Files permission."
13621
+ },
13622
+ "404": {
13623
+ "description": "Asset, job or contact not found in the organization."
13624
+ }
13625
+ }
13626
+ }
13017
13627
  }
13018
13628
  },
13019
13629
  "webhooks": {}