@epilot/cli 0.1.208 → 0.1.210

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 (78) hide show
  1. package/README.md +1 -1
  2. package/definitions/message.json +1312 -14
  3. package/definitions/pricing.json +26 -5
  4. package/dist/{access-token-56RZRZWB.js → access-token-HCIEQVZQ.js} +2 -2
  5. package/dist/{add-component-QRFQYLQS.js → add-component-FQ6XKAVB.js} +2 -2
  6. package/dist/{add-function-74E5CYMM.js → add-function-SQVYOTL4.js} +2 -2
  7. package/dist/{address-4IAYJRPK.js → address-MTFPTR73.js} +2 -2
  8. package/dist/{address-suggestions-C4U2IMWS.js → address-suggestions-7VPIWBHI.js} +2 -2
  9. package/dist/{ai-agents-SVWKMSMH.js → ai-agents-XTEPEZLU.js} +2 -2
  10. package/dist/{api-BF5RIJSL.js → api-SVJ22JMM.js} +2 -2
  11. package/dist/app-EIMY6SUD.js +26 -0
  12. package/dist/{audit-logs-JCU5WBRO.js → audit-logs-VSLIKGKN.js} +2 -2
  13. package/dist/{automation-5N2VJ7EJ.js → automation-OQQ56PMS.js} +2 -2
  14. package/dist/{billing-IPKKGPVB.js → billing-O6ZU7HB2.js} +2 -2
  15. package/dist/bin/epilot.js +61 -61
  16. package/dist/{blueprint-manifest-B5XSF7CQ.js → blueprint-manifest-SWK5VMJS.js} +2 -2
  17. package/dist/{calendar-AKIAACOJ.js → calendar-D6DQKNGB.js} +2 -2
  18. package/dist/{chat-NL727COF.js → chat-PILUY6C2.js} +2 -2
  19. package/dist/{chunk-MUYLBXHF.js → chunk-5RFFYPAR.js} +3 -1
  20. package/dist/{chunk-HWZO7CYG.js → chunk-BHXZQ2L3.js} +1 -1
  21. package/dist/{chunk-OE5W4UDT.js → chunk-QXCVA4V7.js} +1 -1
  22. package/dist/{chunk-SD64YL5A.js → chunk-ZNSV3LQ7.js} +1 -1
  23. package/dist/{completion-OKQFJS6O.js → completion-P2M7EXKA.js} +1 -1
  24. package/dist/{configuration-hub-VMOJPJAD.js → configuration-hub-GMU2SU36.js} +2 -2
  25. package/dist/{consent-3OGAIS4Y.js → consent-FTUSYRWZ.js} +2 -2
  26. package/dist/{customer-portal-YFFXYOM3.js → customer-portal-AK4DTE2K.js} +2 -2
  27. package/dist/{dashboard-IBT6P47V.js → dashboard-PYCSBO7R.js} +2 -2
  28. package/dist/{data-governance-7IOD6IW2.js → data-governance-KUOS6L56.js} +2 -2
  29. package/dist/{deduplication-JXNB7LS6.js → deduplication-KVUC3R7Q.js} +2 -2
  30. package/dist/{deploy-JPV2ONCY.js → deploy-KVYUYZKR.js} +2 -2
  31. package/dist/{design-IJT33BDU.js → design-MY4U2AUC.js} +2 -2
  32. package/dist/{dev-WX3JLSGY.js → dev-VXG57KRE.js} +2 -2
  33. package/dist/{document-SKGXMEIP.js → document-D52DIT3C.js} +2 -2
  34. package/dist/{email-settings-DM3BAISC.js → email-settings-HCQE3V4H.js} +2 -2
  35. package/dist/{email-template-FH7W6UJW.js → email-template-ZVMYW3XL.js} +2 -2
  36. package/dist/{entity-2U2FE763.js → entity-Y7BHHX54.js} +2 -2
  37. package/dist/{entity-mapping-PNRFXAI3.js → entity-mapping-JJ5JNA4C.js} +2 -2
  38. package/dist/{environments-V4LBMJDG.js → environments-WB7GOP2D.js} +2 -2
  39. package/dist/{event-catalog-JUIEUQKE.js → event-catalog-AD6P5QH5.js} +2 -2
  40. package/dist/{export-S7BU5MY4.js → export-DS67N27J.js} +2 -2
  41. package/dist/{external-values-2DXY4CAL.js → external-values-GKJ6GSUY.js} +2 -2
  42. package/dist/{file-HICQQOND.js → file-TGJX7EUX.js} +2 -2
  43. package/dist/{iban-WGGKZQ6X.js → iban-SWV3XWOS.js} +2 -2
  44. package/dist/{identity-ZEFGCXB5.js → identity-VD2PUR26.js} +2 -2
  45. package/dist/{init-BSDL3O3Q.js → init-AMUYG2AS.js} +2 -2
  46. package/dist/{integration-toolkit-VYZU6OUS.js → integration-toolkit-APSBNFVR.js} +2 -2
  47. package/dist/{journey-CYSI2OZR.js → journey-YWFJG5Q7.js} +2 -2
  48. package/dist/{kanban-RSDYLF7C.js → kanban-DI37YU3I.js} +2 -2
  49. package/dist/{message-WFVKNLV6.js → message-TDP4GWEP.js} +2 -2
  50. package/dist/{metering-IJMNW32A.js → metering-CIZBDFVA.js} +2 -2
  51. package/dist/{notes-I6Q4UGHK.js → notes-LVM54LMJ.js} +2 -2
  52. package/dist/{notification-4N4L4XKA.js → notification-NPKQNHKN.js} +2 -2
  53. package/dist/{organization-2V5ZAXFA.js → organization-7ESLQB6G.js} +2 -2
  54. package/dist/{partner-directory-EMAXXLRQ.js → partner-directory-I3NPSI7J.js} +2 -2
  55. package/dist/{permissions-7C255CEB.js → permissions-QPHDNEP2.js} +2 -2
  56. package/dist/{phone-integration-HHZXEIM4.js → phone-integration-REEEQ27R.js} +2 -2
  57. package/dist/{pricing-QKAFXF4D.js → pricing-6WHYL7YI.js} +2 -2
  58. package/dist/{pricing-tier-7UKMXHBQ.js → pricing-tier-PJHTVFY5.js} +2 -2
  59. package/dist/{purpose-327JD2BL.js → purpose-2R4FSH7D.js} +2 -2
  60. package/dist/{query-AZ3S4YJ4.js → query-N4HGU3PQ.js} +2 -2
  61. package/dist/{remove-component-XZCXWYJM.js → remove-component-CMJD2V4A.js} +2 -2
  62. package/dist/{review-DY74XJMY.js → review-GLYYK7VR.js} +2 -2
  63. package/dist/{sandbox-IZPT2CCN.js → sandbox-EGRCO77E.js} +2 -2
  64. package/dist/{sharing-QYW6Z7J2.js → sharing-HTMWA75M.js} +2 -2
  65. package/dist/{snapshot-5TWQP2YP.js → snapshot-PLFU7BXZ.js} +2 -2
  66. package/dist/{submission-GOW55ZZI.js → submission-Y2EDOYHM.js} +2 -2
  67. package/dist/{targeting-OWZMQQ6J.js → targeting-I42SJWE5.js} +2 -2
  68. package/dist/{template-variables-PHSJTIRP.js → template-variables-SKLJAVAZ.js} +2 -2
  69. package/dist/{upgrade-JSRASQJ6.js → upgrade-YF7GYUKY.js} +1 -1
  70. package/dist/{user-DQBMBSPA.js → user-YDA6LWAO.js} +2 -2
  71. package/dist/{validate-MY54PZAU.js → validate-MNRIKRNL.js} +2 -2
  72. package/dist/{validation-rules-OUZYYKLB.js → validation-rules-EFWCOGSH.js} +2 -2
  73. package/dist/{versions-NZUJ3RH3.js → versions-Q7LPGM7U.js} +2 -2
  74. package/dist/{webhooks-GGHO4J66.js → webhooks-KDRG7UT2.js} +2 -2
  75. package/dist/{workflow-ER4BUSGS.js → workflow-VBTV7QDA.js} +2 -2
  76. package/dist/{workflow-definition-IYC7STTG.js → workflow-definition-KWG2PI5G.js} +2 -2
  77. package/package.json +1 -1
  78. package/dist/app-RNEC6DP6.js +0 -26
@@ -23,6 +23,7 @@
23
23
  {
24
24
  "name": "Drafts"
25
25
  },
26
+ null,
26
27
  {
27
28
  "name": "message_schema",
28
29
  "x-displayName": "Message",
@@ -55,8 +56,21 @@
55
56
  "/v1/message/messages": {
56
57
  "post": {
57
58
  "operationId": "sendMessage",
59
+ "x-epilot-permissions": [
60
+ {
61
+ "action": "message:send"
62
+ },
63
+ {
64
+ "action": "entity:create",
65
+ "resource": "message"
66
+ },
67
+ {
68
+ "action": "entity:create",
69
+ "resource": "thread"
70
+ }
71
+ ],
58
72
  "summary": "sendMessage",
59
- "description": "Send an email message",
73
+ "description": "Send an email message\n\nRequires `message:send` and `entity:create` on `message`; `entity:create` on `thread` only when the\nrequest starts a new thread (a `thread` and no `parent_id`). With `do_not_create_entities=true` only\n`message:send` is required. Checked with the caller's token before the send is queued (403).\n",
60
74
  "tags": [
61
75
  "Messages"
62
76
  ],
@@ -98,6 +112,16 @@
98
112
  },
99
113
  "put": {
100
114
  "operationId": "updateMessage",
115
+ "x-epilot-permissions": [
116
+ {
117
+ "action": "entity:edit",
118
+ "resource": "message"
119
+ },
120
+ {
121
+ "action": "entity:view",
122
+ "resource": "thread"
123
+ }
124
+ ],
101
125
  "summary": "updateMessage",
102
126
  "description": "Update message metadata",
103
127
  "tags": [
@@ -158,6 +182,12 @@
158
182
  "/v1/message/messages/{id}": {
159
183
  "get": {
160
184
  "operationId": "getMessage",
185
+ "x-epilot-permissions": [
186
+ {
187
+ "action": "entity:view",
188
+ "resource": "message"
189
+ }
190
+ ],
161
191
  "summary": "getMessage",
162
192
  "description": "Get an email message by id",
163
193
  "tags": [
@@ -212,6 +242,16 @@
212
242
  },
213
243
  "delete": {
214
244
  "operationId": "deleteMessage",
245
+ "x-epilot-permissions": [
246
+ {
247
+ "action": "entity:view",
248
+ "resource": "message"
249
+ },
250
+ {
251
+ "action": "entity:delete",
252
+ "resource": "message"
253
+ }
254
+ ],
215
255
  "summary": "deleteMessage",
216
256
  "description": "Immediately and permanently delete a message. This operation cannot be undone.",
217
257
  "tags": [
@@ -241,6 +281,12 @@
241
281
  "/v1/message/messages/{id}/eml": {
242
282
  "get": {
243
283
  "operationId": "getMessageEml",
284
+ "x-epilot-permissions": [
285
+ {
286
+ "action": "entity:view",
287
+ "resource": "message"
288
+ }
289
+ ],
244
290
  "summary": "getMessageEml",
245
291
  "description": "Download a message as an EML file.\nReturns a 302 redirect to a pre-signed S3 URL where the EML file can be downloaded.\n",
246
292
  "tags": [
@@ -282,6 +328,13 @@
282
328
  "/v1/message/messages:search": {
283
329
  "post": {
284
330
  "operationId": "searchMessages",
331
+ "x-epilot-permissions": [
332
+ {
333
+ "action": "entity:view",
334
+ "resource": "message",
335
+ "filter": true
336
+ }
337
+ ],
285
338
  "summary": "searchMessages",
286
339
  "description": "Search Messages",
287
340
  "tags": [
@@ -341,6 +394,20 @@
341
394
  "/v1/message/messages/{id}/trash": {
342
395
  "post": {
343
396
  "operationId": "trashMessage",
397
+ "x-epilot-permissions": [
398
+ {
399
+ "action": "entity:view",
400
+ "resource": "message"
401
+ },
402
+ {
403
+ "action": "entity:edit",
404
+ "resource": "message"
405
+ },
406
+ {
407
+ "action": "entity:edit",
408
+ "resource": "thread"
409
+ }
410
+ ],
344
411
  "summary": "trashMessage",
345
412
  "description": "Move a message to the trash",
346
413
  "tags": [
@@ -370,6 +437,20 @@
370
437
  "/v1/message/messages/{id}/untrash": {
371
438
  "post": {
372
439
  "operationId": "untrashMessage",
440
+ "x-epilot-permissions": [
441
+ {
442
+ "action": "entity:view",
443
+ "resource": "message"
444
+ },
445
+ {
446
+ "action": "entity:edit",
447
+ "resource": "message"
448
+ },
449
+ {
450
+ "action": "entity:edit",
451
+ "resource": "thread"
452
+ }
453
+ ],
373
454
  "summary": "untrashMessage",
374
455
  "description": "Restore a trashed message",
375
456
  "tags": [
@@ -399,6 +480,16 @@
399
480
  "/v1/message/messages/{id}/read": {
400
481
  "post": {
401
482
  "operationId": "markReadMessage",
483
+ "x-epilot-permissions": [
484
+ {
485
+ "action": "entity:view",
486
+ "resource": "message"
487
+ },
488
+ {
489
+ "action": "entity:edit",
490
+ "resource": "message"
491
+ }
492
+ ],
402
493
  "summary": "markReadMessage",
403
494
  "description": "Mark message as read",
404
495
  "tags": [
@@ -428,6 +519,16 @@
428
519
  "/v2/message/messages/{id}/read": {
429
520
  "post": {
430
521
  "operationId": "markReadMessageV2",
522
+ "x-epilot-permissions": [
523
+ {
524
+ "action": "entity:view",
525
+ "resource": "message"
526
+ },
527
+ {
528
+ "action": "entity:edit",
529
+ "resource": "message"
530
+ }
531
+ ],
431
532
  "summary": "markReadMessageV2",
432
533
  "description": "Mark message as read within a scope",
433
534
  "tags": [
@@ -467,6 +568,16 @@
467
568
  "/v1/message/messages/{id}/unread": {
468
569
  "post": {
469
570
  "operationId": "markUnreadMessage",
571
+ "x-epilot-permissions": [
572
+ {
573
+ "action": "entity:view",
574
+ "resource": "message"
575
+ },
576
+ {
577
+ "action": "entity:edit",
578
+ "resource": "message"
579
+ }
580
+ ],
470
581
  "summary": "markUnreadMessage",
471
582
  "description": "Mark message as unread",
472
583
  "tags": [
@@ -496,6 +607,13 @@
496
607
  "/v1/message/messages/unread/{actor}": {
497
608
  "get": {
498
609
  "operationId": "getUnread",
610
+ "x-epilot-permissions": [
611
+ {
612
+ "action": "entity:view",
613
+ "resource": "message",
614
+ "filter": true
615
+ }
616
+ ],
499
617
  "summary": "getUnread",
500
618
  "description": "Get all unread messages by actor",
501
619
  "tags": [
@@ -584,6 +702,13 @@
584
702
  "/v1/message/unread:counts": {
585
703
  "post": {
586
704
  "operationId": "getUnreadCounts",
705
+ "x-epilot-permissions": [
706
+ {
707
+ "action": "entity:view",
708
+ "resource": "message",
709
+ "filter": true
710
+ }
711
+ ],
587
712
  "summary": "getUnreadCounts",
588
713
  "description": "Unread counts for several named scopes in one request.\n\nA scope is a name plus the same parameters the thread list already takes (`q`, `inbox_id`),\nso a scope's count and the list beneath it are the same predicate and agree by construction.\nThe server adds only the read-state condition; it does not re-author the caller's view.\n\nThe `organization` scope is the exception and takes no `q`: it reuses the four canonical\ncentral-inbox queries, so its numbers match `getUnread` exactly.\n\nWhich buckets come back varies by scope type and actor. Every scope other than `organization`\nreturns `unread` alone. An `organization` scope returns all four (`unread`, `drafts`,\n`unassigned`, `spam`) for `actor: organization`, and `unread` and `drafts` only for\n`actor: user`. `getUnread` returns all four for both actors; this endpoint omits the two that\nno per-user surface renders, since each costs an aggregation.\n\nGated on the `message-unread-counts` flag, evaluated once per request against the calling\norg. With the flag off the response is `{ \"enabled\": false, \"counts\": {} }` and no\nElasticsearch query is issued.\n",
589
714
  "tags": [
@@ -622,6 +747,16 @@
622
747
  "/v2/message/messages/{id}/unread": {
623
748
  "post": {
624
749
  "operationId": "markUnreadMessageV2",
750
+ "x-epilot-permissions": [
751
+ {
752
+ "action": "entity:view",
753
+ "resource": "message"
754
+ },
755
+ {
756
+ "action": "entity:edit",
757
+ "resource": "message"
758
+ }
759
+ ],
625
760
  "summary": "markUnreadMessageV2",
626
761
  "description": "Mark message as unread within a scope",
627
762
  "tags": [
@@ -661,6 +796,18 @@
661
796
  "/v1/message/threads:search": {
662
797
  "post": {
663
798
  "operationId": "searchThreads",
799
+ "x-epilot-permissions": [
800
+ {
801
+ "action": "entity:view",
802
+ "resource": "message",
803
+ "filter": true
804
+ },
805
+ {
806
+ "action": "entity:view",
807
+ "resource": "thread",
808
+ "filter": true
809
+ }
810
+ ],
664
811
  "summary": "searchThreads",
665
812
  "description": "Search for threads of email messages.\n\nMessages with no replies yet are treated as threads with single message.\n\nLucene syntax supported.\n",
666
813
  "tags": [
@@ -720,6 +867,18 @@
720
867
  "/v2/message/threads:search": {
721
868
  "post": {
722
869
  "operationId": "searchThreadsV2",
870
+ "x-epilot-permissions": [
871
+ {
872
+ "action": "entity:view",
873
+ "resource": "message",
874
+ "filter": true
875
+ },
876
+ {
877
+ "action": "entity:view",
878
+ "resource": "thread",
879
+ "filter": true
880
+ }
881
+ ],
723
882
  "summary": "searchThreadsV2",
724
883
  "description": "Search for threads of email messages.\n\nMessages with no replies yet are treated as threads with single message.\n\nLucene syntax supported.\n",
725
884
  "tags": [
@@ -779,6 +938,18 @@
779
938
  "/v1/message/threads:searchIds": {
780
939
  "post": {
781
940
  "operationId": "searchIds",
941
+ "x-epilot-permissions": [
942
+ {
943
+ "action": "entity:view",
944
+ "resource": "message",
945
+ "filter": true
946
+ },
947
+ {
948
+ "action": "entity:view",
949
+ "resource": "thread",
950
+ "filter": true
951
+ }
952
+ ],
782
953
  "summary": "Search threads and return all id's",
783
954
  "description": "Return all thread id's that match a criteria\n\nLucene syntax supported.\n",
784
955
  "tags": [
@@ -831,8 +1002,15 @@
831
1002
  "/v2/message/threads:workload": {
832
1003
  "post": {
833
1004
  "operationId": "getAssigneeWorkload",
1005
+ "x-epilot-permissions": [
1006
+ {
1007
+ "action": "entity:view",
1008
+ "resource": "message",
1009
+ "filter": true
1010
+ }
1011
+ ],
834
1012
  "summary": "getAssigneeWorkload",
835
- "description": "Return the open-thread workload for a set of user ids.\n\nFor each requested user id, returns the number of *open* threads assigned\ndirectly to that user \u2014 matching what the user sees in their central-inbox\nopen view: in inbox, not trashed, not done, and excluding notification-only\nand spam threads.\n\nOnly threads assigned directly to a user are counted; threads assigned to a\ngroup the user belongs to are not. Intended for assignment load-balancing\n(e.g. even-distribution automations) that need a consistent, inbox-aligned\nworkload per user.\n",
1013
+ "description": "Return the open-thread workload for a set of user ids.\n\nFor each requested user id, returns the number of *open* threads assigned\ndirectly to that user — matching what the user sees in their central-inbox\nopen view: in inbox, not trashed, not done, and excluding notification-only\nand spam threads.\n\nOnly threads assigned directly to a user are counted; threads assigned to a\ngroup the user belongs to are not. Intended for assignment load-balancing\n(e.g. even-distribution automations) that need a consistent, inbox-aligned\nworkload per user.\n",
836
1014
  "tags": [
837
1015
  "Threads"
838
1016
  ],
@@ -866,6 +1044,16 @@
866
1044
  "/v1/message/threads": {
867
1045
  "put": {
868
1046
  "operationId": "updateThread",
1047
+ "x-epilot-permissions": [
1048
+ {
1049
+ "action": "entity:edit",
1050
+ "resource": "thread"
1051
+ },
1052
+ {
1053
+ "action": "entity:edit",
1054
+ "resource": "message"
1055
+ }
1056
+ ],
869
1057
  "summary": "updateThread",
870
1058
  "description": "Modify thread metadata",
871
1059
  "tags": [
@@ -898,6 +1086,20 @@
898
1086
  "/v1/message/threads/{id}": {
899
1087
  "delete": {
900
1088
  "operationId": "deleteThread",
1089
+ "x-epilot-permissions": [
1090
+ {
1091
+ "action": "entity:view",
1092
+ "resource": "thread"
1093
+ },
1094
+ {
1095
+ "action": "entity:delete",
1096
+ "resource": "message"
1097
+ },
1098
+ {
1099
+ "action": "entity:delete",
1100
+ "resource": "thread"
1101
+ }
1102
+ ],
901
1103
  "summary": "deleteThread",
902
1104
  "description": "Immediately and permanently delete a thread. This operation cannot be undone.",
903
1105
  "tags": [
@@ -927,6 +1129,20 @@
927
1129
  "/v1/message/threads/{id}:move": {
928
1130
  "post": {
929
1131
  "operationId": "moveThread",
1132
+ "x-epilot-permissions": [
1133
+ {
1134
+ "action": "entity:view",
1135
+ "resource": "thread"
1136
+ },
1137
+ {
1138
+ "action": "entity:edit",
1139
+ "resource": "thread"
1140
+ },
1141
+ {
1142
+ "action": "entity:edit",
1143
+ "resource": "message"
1144
+ }
1145
+ ],
930
1146
  "summary": "moveThread",
931
1147
  "description": "Move thread to a different Inbox",
932
1148
  "tags": [
@@ -978,6 +1194,20 @@
978
1194
  "/v1/message/threads/{id}:markAsDone": {
979
1195
  "post": {
980
1196
  "operationId": "markThreadAsDone",
1197
+ "x-epilot-permissions": [
1198
+ {
1199
+ "action": "entity:view",
1200
+ "resource": "thread"
1201
+ },
1202
+ {
1203
+ "action": "entity:edit",
1204
+ "resource": "thread"
1205
+ },
1206
+ {
1207
+ "action": "entity:edit",
1208
+ "resource": "message"
1209
+ }
1210
+ ],
981
1211
  "summary": "markThreadAsDone",
982
1212
  "description": "Mark thread as done",
983
1213
  "tags": [
@@ -1007,6 +1237,20 @@
1007
1237
  "/v1/message/threads/{id}:markAsOpen": {
1008
1238
  "post": {
1009
1239
  "operationId": "markThreadAsOpen",
1240
+ "x-epilot-permissions": [
1241
+ {
1242
+ "action": "entity:view",
1243
+ "resource": "thread"
1244
+ },
1245
+ {
1246
+ "action": "entity:edit",
1247
+ "resource": "thread"
1248
+ },
1249
+ {
1250
+ "action": "entity:edit",
1251
+ "resource": "message"
1252
+ }
1253
+ ],
1010
1254
  "summary": "markThreadAsOpen",
1011
1255
  "description": "Mark thread as open",
1012
1256
  "tags": [
@@ -1036,6 +1280,12 @@
1036
1280
  "/v1/message/threads/{id}/timeline": {
1037
1281
  "get": {
1038
1282
  "operationId": "getThreadTimeline",
1283
+ "x-epilot-permissions": [
1284
+ {
1285
+ "action": "entity:view",
1286
+ "resource": "thread"
1287
+ }
1288
+ ],
1039
1289
  "summary": "getThreadTimeline",
1040
1290
  "description": "Get thread timeline",
1041
1291
  "tags": [
@@ -1069,9 +1319,90 @@
1069
1319
  }
1070
1320
  }
1071
1321
  },
1322
+ "/v1/message/threads/{id}/summary": {
1323
+ "get": {
1324
+ "operationId": "getThreadSummary",
1325
+ "x-epilot-permissions": [
1326
+ {
1327
+ "action": "entity:view",
1328
+ "resource": "thread"
1329
+ }
1330
+ ],
1331
+ "summary": "getThreadSummary",
1332
+ "description": "AI summary of a thread. Returns `202` while it is generated; poll until `jobStatus.status` is `COMPLETED` or `FAILED`.\n",
1333
+ "tags": [
1334
+ "Threads"
1335
+ ],
1336
+ "parameters": [
1337
+ {
1338
+ "name": "id",
1339
+ "description": "Thread ID",
1340
+ "in": "path",
1341
+ "required": true,
1342
+ "schema": {
1343
+ "type": "string"
1344
+ }
1345
+ },
1346
+ {
1347
+ "name": "message_id",
1348
+ "description": "Message to summarize the thread up to. Defaults to the latest message of the thread.",
1349
+ "in": "query",
1350
+ "required": false,
1351
+ "schema": {
1352
+ "type": "string"
1353
+ }
1354
+ }
1355
+ ],
1356
+ "responses": {
1357
+ "200": {
1358
+ "description": "Summary job of the message",
1359
+ "content": {
1360
+ "application/json": {
1361
+ "schema": {
1362
+ "$ref": "#/components/schemas/ThreadSummary"
1363
+ }
1364
+ }
1365
+ }
1366
+ },
1367
+ "202": {
1368
+ "description": "Summary generation started",
1369
+ "content": {
1370
+ "application/json": {
1371
+ "schema": {
1372
+ "$ref": "#/components/schemas/ThreadSummary"
1373
+ }
1374
+ }
1375
+ }
1376
+ },
1377
+ "400": {
1378
+ "description": "Thread can't be summarized (e.g. too short or only automated messages)"
1379
+ },
1380
+ "403": {
1381
+ "description": "Forbidden"
1382
+ },
1383
+ "404": {
1384
+ "description": "Thread has no messages, or no summary exists for the message"
1385
+ }
1386
+ }
1387
+ }
1388
+ },
1072
1389
  "/v1/message/threads/{id}/trash": {
1073
1390
  "post": {
1074
1391
  "operationId": "trashThread",
1392
+ "x-epilot-permissions": [
1393
+ {
1394
+ "action": "entity:view",
1395
+ "resource": "thread"
1396
+ },
1397
+ {
1398
+ "action": "entity:edit",
1399
+ "resource": "thread"
1400
+ },
1401
+ {
1402
+ "action": "entity:edit",
1403
+ "resource": "message"
1404
+ }
1405
+ ],
1075
1406
  "summary": "trashThread",
1076
1407
  "description": "Move a thread to trash",
1077
1408
  "tags": [
@@ -1101,6 +1432,20 @@
1101
1432
  "/v1/message/threads/{id}/untrash": {
1102
1433
  "post": {
1103
1434
  "operationId": "untrashThread",
1435
+ "x-epilot-permissions": [
1436
+ {
1437
+ "action": "entity:view",
1438
+ "resource": "thread"
1439
+ },
1440
+ {
1441
+ "action": "entity:edit",
1442
+ "resource": "thread"
1443
+ },
1444
+ {
1445
+ "action": "entity:edit",
1446
+ "resource": "message"
1447
+ }
1448
+ ],
1104
1449
  "summary": "untrashThread",
1105
1450
  "description": "Restore a trashed thread",
1106
1451
  "tags": [
@@ -1130,6 +1475,20 @@
1130
1475
  "/v1/message/threads/{id}/spam": {
1131
1476
  "post": {
1132
1477
  "operationId": "spamThread",
1478
+ "x-epilot-permissions": [
1479
+ {
1480
+ "action": "entity:view",
1481
+ "resource": "thread"
1482
+ },
1483
+ {
1484
+ "action": "entity:edit",
1485
+ "resource": "thread"
1486
+ },
1487
+ {
1488
+ "action": "entity:edit",
1489
+ "resource": "message"
1490
+ }
1491
+ ],
1133
1492
  "summary": "spamThread",
1134
1493
  "description": "Mark a thread as spam",
1135
1494
  "tags": [
@@ -1162,6 +1521,20 @@
1162
1521
  "/v1/message/threads/{id}/unspam": {
1163
1522
  "post": {
1164
1523
  "operationId": "unspamThread",
1524
+ "x-epilot-permissions": [
1525
+ {
1526
+ "action": "entity:view",
1527
+ "resource": "thread"
1528
+ },
1529
+ {
1530
+ "action": "entity:edit",
1531
+ "resource": "thread"
1532
+ },
1533
+ {
1534
+ "action": "entity:edit",
1535
+ "resource": "message"
1536
+ }
1537
+ ],
1165
1538
  "summary": "unspamThread",
1166
1539
  "description": "Remove spam marking from a thread",
1167
1540
  "tags": [
@@ -1194,6 +1567,24 @@
1194
1567
  "/v1/message/messages/{id}/spam": {
1195
1568
  "post": {
1196
1569
  "operationId": "spamMessage",
1570
+ "x-epilot-permissions": [
1571
+ {
1572
+ "action": "entity:view",
1573
+ "resource": "message"
1574
+ },
1575
+ {
1576
+ "action": "entity:edit",
1577
+ "resource": "message"
1578
+ },
1579
+ {
1580
+ "action": "entity:view",
1581
+ "resource": "thread"
1582
+ },
1583
+ {
1584
+ "action": "entity:edit",
1585
+ "resource": "thread"
1586
+ }
1587
+ ],
1197
1588
  "summary": "spamMessage",
1198
1589
  "description": "Mark a single message as spam. Also marks the parent thread as spam if all messages in the thread are spam.",
1199
1590
  "tags": [
@@ -1226,6 +1617,24 @@
1226
1617
  "/v1/message/messages/{id}/unspam": {
1227
1618
  "post": {
1228
1619
  "operationId": "unspamMessage",
1620
+ "x-epilot-permissions": [
1621
+ {
1622
+ "action": "entity:view",
1623
+ "resource": "message"
1624
+ },
1625
+ {
1626
+ "action": "entity:edit",
1627
+ "resource": "message"
1628
+ },
1629
+ {
1630
+ "action": "entity:view",
1631
+ "resource": "thread"
1632
+ },
1633
+ {
1634
+ "action": "entity:edit",
1635
+ "resource": "thread"
1636
+ }
1637
+ ],
1229
1638
  "summary": "unspamMessage",
1230
1639
  "description": "Remove spam marking from a single message. Also removes spam from the parent thread if no other messages are spam.",
1231
1640
  "tags": [
@@ -1258,6 +1667,20 @@
1258
1667
  "/v1/message/threads/bulk:move": {
1259
1668
  "post": {
1260
1669
  "operationId": "bulkMoveThreads",
1670
+ "x-epilot-permissions": [
1671
+ {
1672
+ "action": "entity:view",
1673
+ "resource": "thread"
1674
+ },
1675
+ {
1676
+ "action": "entity:edit",
1677
+ "resource": "thread"
1678
+ },
1679
+ {
1680
+ "action": "entity:edit",
1681
+ "resource": "message"
1682
+ }
1683
+ ],
1261
1684
  "summary": "bulkMoveThreads",
1262
1685
  "description": "Move many threads to a different inbox",
1263
1686
  "tags": [
@@ -1286,6 +1709,20 @@
1286
1709
  "/v1/message/threads/bulk:assign": {
1287
1710
  "post": {
1288
1711
  "operationId": "bulkAssignThreads",
1712
+ "x-epilot-permissions": [
1713
+ {
1714
+ "action": "entity:view",
1715
+ "resource": "thread"
1716
+ },
1717
+ {
1718
+ "action": "entity:edit",
1719
+ "resource": "thread"
1720
+ },
1721
+ {
1722
+ "action": "entity:edit",
1723
+ "resource": "message"
1724
+ }
1725
+ ],
1289
1726
  "summary": "bulkAssignThreads",
1290
1727
  "description": "Assign many threads",
1291
1728
  "tags": [
@@ -1314,6 +1751,16 @@
1314
1751
  "/v1/message/threads/bulk:read": {
1315
1752
  "post": {
1316
1753
  "operationId": "threadBulkActionsRead",
1754
+ "x-epilot-permissions": [
1755
+ {
1756
+ "action": "entity:view",
1757
+ "resource": "thread"
1758
+ },
1759
+ {
1760
+ "action": "entity:edit",
1761
+ "resource": "thread"
1762
+ }
1763
+ ],
1317
1764
  "summary": "threadBulkActionsRead",
1318
1765
  "description": "Perform a bulk action of marking an array of thread ids as read",
1319
1766
  "tags": [
@@ -1342,6 +1789,16 @@
1342
1789
  "/v1/message/threads/bulk:unread": {
1343
1790
  "post": {
1344
1791
  "operationId": "threadBulkActionsUnread",
1792
+ "x-epilot-permissions": [
1793
+ {
1794
+ "action": "entity:view",
1795
+ "resource": "thread"
1796
+ },
1797
+ {
1798
+ "action": "entity:edit",
1799
+ "resource": "thread"
1800
+ }
1801
+ ],
1345
1802
  "summary": "threadBulkActionsUnread",
1346
1803
  "description": "Perform a bulk action of marking an array of thread ids as unread",
1347
1804
  "tags": [
@@ -1370,6 +1827,20 @@
1370
1827
  "/v1/message/threads/bulk:favorite": {
1371
1828
  "post": {
1372
1829
  "operationId": "threadBulkActionsFavorite",
1830
+ "x-epilot-permissions": [
1831
+ {
1832
+ "action": "entity:view",
1833
+ "resource": "thread"
1834
+ },
1835
+ {
1836
+ "action": "entity:edit",
1837
+ "resource": "thread"
1838
+ },
1839
+ {
1840
+ "action": "entity:edit",
1841
+ "resource": "message"
1842
+ }
1843
+ ],
1373
1844
  "summary": "threadBulkActionsFavorite",
1374
1845
  "description": "Perform a bulk action of marking an array of thread ids favorite",
1375
1846
  "tags": [
@@ -1398,6 +1869,20 @@
1398
1869
  "/v1/message/threads/bulk:unfavorite": {
1399
1870
  "post": {
1400
1871
  "operationId": "threadBulkActionsUnfavorite",
1872
+ "x-epilot-permissions": [
1873
+ {
1874
+ "action": "entity:view",
1875
+ "resource": "thread"
1876
+ },
1877
+ {
1878
+ "action": "entity:edit",
1879
+ "resource": "thread"
1880
+ },
1881
+ {
1882
+ "action": "entity:edit",
1883
+ "resource": "message"
1884
+ }
1885
+ ],
1401
1886
  "summary": "threadBulkActionsUnfavorite",
1402
1887
  "description": "Perform a bulk action of marking an array of thread ids unfavorited",
1403
1888
  "tags": [
@@ -1426,7 +1911,21 @@
1426
1911
  "/v1/message/threads/bulk:trash": {
1427
1912
  "post": {
1428
1913
  "operationId": "threadBulkActionsTrash",
1429
- "summary": "threadBulkActionsTrash",
1914
+ "x-epilot-permissions": [
1915
+ {
1916
+ "action": "entity:view",
1917
+ "resource": "thread"
1918
+ },
1919
+ {
1920
+ "action": "entity:edit",
1921
+ "resource": "thread"
1922
+ },
1923
+ {
1924
+ "action": "entity:edit",
1925
+ "resource": "message"
1926
+ }
1927
+ ],
1928
+ "summary": "threadBulkActionsTrash",
1430
1929
  "description": "Perform a bulk action of trashing an array of threads",
1431
1930
  "tags": [
1432
1931
  "Threads"
@@ -1454,6 +1953,20 @@
1454
1953
  "/v1/message/threads/bulk:untrash": {
1455
1954
  "post": {
1456
1955
  "operationId": "threadBulkActionsUntrash",
1956
+ "x-epilot-permissions": [
1957
+ {
1958
+ "action": "entity:view",
1959
+ "resource": "thread"
1960
+ },
1961
+ {
1962
+ "action": "entity:edit",
1963
+ "resource": "thread"
1964
+ },
1965
+ {
1966
+ "action": "entity:edit",
1967
+ "resource": "message"
1968
+ }
1969
+ ],
1457
1970
  "summary": "threadBulkActionsUntrash",
1458
1971
  "description": "Perform a bulk action of untrashing an array of threads",
1459
1972
  "tags": [
@@ -1482,6 +1995,20 @@
1482
1995
  "/v1/message/threads/bulk:delete": {
1483
1996
  "post": {
1484
1997
  "operationId": "threadBulkActionsDelete",
1998
+ "x-epilot-permissions": [
1999
+ {
2000
+ "action": "entity:view",
2001
+ "resource": "thread"
2002
+ },
2003
+ {
2004
+ "action": "entity:delete",
2005
+ "resource": "message"
2006
+ },
2007
+ {
2008
+ "action": "entity:delete",
2009
+ "resource": "thread"
2010
+ }
2011
+ ],
1485
2012
  "summary": "threadBulkActionsDelete",
1486
2013
  "description": "Performs a bulk permanent delete for all threads",
1487
2014
  "tags": [
@@ -1510,6 +2037,20 @@
1510
2037
  "/v1/message/threads/bulk:done": {
1511
2038
  "post": {
1512
2039
  "operationId": "threadBulkActionsDone",
2040
+ "x-epilot-permissions": [
2041
+ {
2042
+ "action": "entity:view",
2043
+ "resource": "thread"
2044
+ },
2045
+ {
2046
+ "action": "entity:edit",
2047
+ "resource": "thread"
2048
+ },
2049
+ {
2050
+ "action": "entity:edit",
2051
+ "resource": "message"
2052
+ }
2053
+ ],
1513
2054
  "summary": "threadBulkActionsDone",
1514
2055
  "description": "Perform a bulk action of marking an array of threads as done",
1515
2056
  "tags": [
@@ -1538,6 +2079,20 @@
1538
2079
  "/v1/message/threads/bulk:open": {
1539
2080
  "post": {
1540
2081
  "operationId": "threadBulkActionsOpen",
2082
+ "x-epilot-permissions": [
2083
+ {
2084
+ "action": "entity:view",
2085
+ "resource": "thread"
2086
+ },
2087
+ {
2088
+ "action": "entity:edit",
2089
+ "resource": "thread"
2090
+ },
2091
+ {
2092
+ "action": "entity:edit",
2093
+ "resource": "message"
2094
+ }
2095
+ ],
1541
2096
  "summary": "threadBulkActionsOpen",
1542
2097
  "description": "Perform a bulk action of marking an array of threads as open",
1543
2098
  "tags": [
@@ -1566,6 +2121,16 @@
1566
2121
  "/v1/message/threads/{id}/read": {
1567
2122
  "post": {
1568
2123
  "operationId": "markReadThread",
2124
+ "x-epilot-permissions": [
2125
+ {
2126
+ "action": "entity:view",
2127
+ "resource": "thread"
2128
+ },
2129
+ {
2130
+ "action": "entity:edit",
2131
+ "resource": "thread"
2132
+ }
2133
+ ],
1569
2134
  "summary": "markReadThread",
1570
2135
  "description": "Mark thread as read",
1571
2136
  "tags": [
@@ -1595,6 +2160,16 @@
1595
2160
  "/v2/message/threads/{id}/read": {
1596
2161
  "post": {
1597
2162
  "operationId": "markReadThreadV2",
2163
+ "x-epilot-permissions": [
2164
+ {
2165
+ "action": "entity:view",
2166
+ "resource": "thread"
2167
+ },
2168
+ {
2169
+ "action": "entity:edit",
2170
+ "resource": "thread"
2171
+ }
2172
+ ],
1598
2173
  "summary": "markReadThreadV2",
1599
2174
  "description": "Mark thread as read within a scope",
1600
2175
  "tags": [
@@ -1634,6 +2209,16 @@
1634
2209
  "/v1/message/threads/{id}/unread": {
1635
2210
  "post": {
1636
2211
  "operationId": "markUnreadThread",
2212
+ "x-epilot-permissions": [
2213
+ {
2214
+ "action": "entity:view",
2215
+ "resource": "thread"
2216
+ },
2217
+ {
2218
+ "action": "entity:edit",
2219
+ "resource": "thread"
2220
+ }
2221
+ ],
1637
2222
  "summary": "markUnreadThread",
1638
2223
  "description": "Mark thread as unread",
1639
2224
  "tags": [
@@ -1663,6 +2248,16 @@
1663
2248
  "/v2/message/threads/{id}/unread": {
1664
2249
  "post": {
1665
2250
  "operationId": "markUnreadThreadV2",
2251
+ "x-epilot-permissions": [
2252
+ {
2253
+ "action": "entity:view",
2254
+ "resource": "thread"
2255
+ },
2256
+ {
2257
+ "action": "entity:edit",
2258
+ "resource": "thread"
2259
+ }
2260
+ ],
1666
2261
  "summary": "markUnreadThreadV2",
1667
2262
  "description": "Mark thread as unread within a scope",
1668
2263
  "tags": [
@@ -1702,6 +2297,20 @@
1702
2297
  "/v1/message/threads/{id}/assign": {
1703
2298
  "post": {
1704
2299
  "operationId": "assignThread",
2300
+ "x-epilot-permissions": [
2301
+ {
2302
+ "action": "entity:view",
2303
+ "resource": "thread"
2304
+ },
2305
+ {
2306
+ "action": "entity:edit",
2307
+ "resource": "thread"
2308
+ },
2309
+ {
2310
+ "action": "entity:edit",
2311
+ "resource": "message"
2312
+ }
2313
+ ],
1705
2314
  "summary": "assignThread",
1706
2315
  "description": "Assign thread to entities",
1707
2316
  "tags": [
@@ -1764,9 +2373,114 @@
1764
2373
  }
1765
2374
  }
1766
2375
  },
2376
+ "/v1/message/threads/{id}/link-suggestions/dismiss": {
2377
+ "post": {
2378
+ "operationId": "dismissThreadLinkSuggestions",
2379
+ "x-epilot-permissions": [
2380
+ {
2381
+ "action": "entity:view",
2382
+ "resource": "thread"
2383
+ },
2384
+ {
2385
+ "action": "entity:edit",
2386
+ "resource": "thread"
2387
+ },
2388
+ {
2389
+ "action": "entity:edit",
2390
+ "resource": "message"
2391
+ }
2392
+ ],
2393
+ "summary": "dismissThreadLinkSuggestions",
2394
+ "description": "Dismiss pending candidates of entity-link suggestions on a thread. A suggestion is recorded on a message when an identifier in it matched entities of different customers, so nothing was linked automatically. Each candidate is resolved on its own: linking one (assignThread) leaves the others suggested until they are linked or dismissed. A suggestion whose candidates are all resolved is not suggested again for the thread.",
2395
+ "tags": [
2396
+ "Threads"
2397
+ ],
2398
+ "parameters": [
2399
+ {
2400
+ "name": "id",
2401
+ "description": "Thread ID",
2402
+ "in": "path",
2403
+ "required": true,
2404
+ "schema": {
2405
+ "type": "string"
2406
+ }
2407
+ }
2408
+ ],
2409
+ "requestBody": {
2410
+ "required": false,
2411
+ "content": {
2412
+ "application/json": {
2413
+ "schema": {
2414
+ "type": "object",
2415
+ "properties": {
2416
+ "suggestion_ids": {
2417
+ "description": "Suggestions to dismiss candidates of. Omit for every pending suggestion on the thread.",
2418
+ "type": "array",
2419
+ "items": {
2420
+ "type": "string"
2421
+ }
2422
+ },
2423
+ "entity_ids": {
2424
+ "description": "Candidates to dismiss. Omit to dismiss every pending candidate of the selected suggestions.",
2425
+ "type": "array",
2426
+ "items": {
2427
+ "type": "string"
2428
+ }
2429
+ }
2430
+ }
2431
+ }
2432
+ }
2433
+ }
2434
+ },
2435
+ "responses": {
2436
+ "200": {
2437
+ "description": "Success",
2438
+ "content": {
2439
+ "application/json": {
2440
+ "schema": {
2441
+ "type": "object",
2442
+ "required": [
2443
+ "dismissed"
2444
+ ],
2445
+ "properties": {
2446
+ "dismissed": {
2447
+ "description": "IDs of the suggestions that had at least one candidate dismissed",
2448
+ "type": "array",
2449
+ "items": {
2450
+ "type": "string"
2451
+ }
2452
+ }
2453
+ }
2454
+ }
2455
+ }
2456
+ }
2457
+ },
2458
+ "403": {
2459
+ "description": "Forbidden"
2460
+ },
2461
+ "404": {
2462
+ "description": "Thread not found"
2463
+ }
2464
+ }
2465
+ }
2466
+ },
1767
2467
  "/v1/message/threads/{id}/unassign": {
1768
2468
  "post": {
1769
2469
  "operationId": "unassignThread",
2470
+ "x-epilot-permissions": [
2471
+ {
2472
+ "action": "entity:view",
2473
+ "resource": "thread"
2474
+ },
2475
+ {
2476
+ "action": "entity:edit",
2477
+ "resource": "thread"
2478
+ },
2479
+ {
2480
+ "action": "entity:edit",
2481
+ "resource": "message"
2482
+ }
2483
+ ],
1770
2484
  "summary": "unassignThread",
1771
2485
  "description": "Unassign thread from entities",
1772
2486
  "tags": [
@@ -1832,6 +2546,20 @@
1832
2546
  "/v1/message/threads/{id}/assign:users": {
1833
2547
  "post": {
1834
2548
  "operationId": "assignUsers",
2549
+ "x-epilot-permissions": [
2550
+ {
2551
+ "action": "entity:view",
2552
+ "resource": "thread"
2553
+ },
2554
+ {
2555
+ "action": "entity:edit",
2556
+ "resource": "thread"
2557
+ },
2558
+ {
2559
+ "action": "entity:edit",
2560
+ "resource": "message"
2561
+ }
2562
+ ],
1835
2563
  "summary": "assignUsers",
1836
2564
  "description": "Assign users to thread for receiving notifications.\nThe operation replaces all existing assigned users in thread.\n",
1837
2565
  "tags": [
@@ -1882,6 +2610,20 @@
1882
2610
  "/v2/message/threads/{id}/assign:users": {
1883
2611
  "post": {
1884
2612
  "operationId": "assignUsersV2",
2613
+ "x-epilot-permissions": [
2614
+ {
2615
+ "action": "entity:view",
2616
+ "resource": "thread"
2617
+ },
2618
+ {
2619
+ "action": "entity:edit",
2620
+ "resource": "thread"
2621
+ },
2622
+ {
2623
+ "action": "entity:edit",
2624
+ "resource": "message"
2625
+ }
2626
+ ],
1885
2627
  "summary": "assignUsersV2",
1886
2628
  "description": "Assign users to thread.\n",
1887
2629
  "tags": [
@@ -1943,6 +2685,20 @@
1943
2685
  "/v1/message/threads/{id}:pin": {
1944
2686
  "post": {
1945
2687
  "operationId": "pinThread",
2688
+ "x-epilot-permissions": [
2689
+ {
2690
+ "action": "entity:view",
2691
+ "resource": "thread"
2692
+ },
2693
+ {
2694
+ "action": "entity:edit",
2695
+ "resource": "thread"
2696
+ },
2697
+ {
2698
+ "action": "entity:edit",
2699
+ "resource": "message"
2700
+ }
2701
+ ],
1946
2702
  "summary": "Pin a single thread",
1947
2703
  "description": "Pin a single thread",
1948
2704
  "tags": [
@@ -1979,6 +2735,20 @@
1979
2735
  },
1980
2736
  "delete": {
1981
2737
  "operationId": "unpinThread",
2738
+ "x-epilot-permissions": [
2739
+ {
2740
+ "action": "entity:view",
2741
+ "resource": "thread"
2742
+ },
2743
+ {
2744
+ "action": "entity:edit",
2745
+ "resource": "thread"
2746
+ },
2747
+ {
2748
+ "action": "entity:edit",
2749
+ "resource": "message"
2750
+ }
2751
+ ],
1982
2752
  "summary": "Unpin a single thread",
1983
2753
  "description": "Unpin a single thread",
1984
2754
  "tags": [
@@ -2017,8 +2787,14 @@
2017
2787
  "/v1/message/drafts": {
2018
2788
  "post": {
2019
2789
  "operationId": "createDraft",
2790
+ "x-epilot-permissions": [
2791
+ {
2792
+ "action": "entity:create",
2793
+ "resource": "message"
2794
+ }
2795
+ ],
2020
2796
  "summary": "createDraft",
2021
- "description": "Create a new draft",
2797
+ "description": "Create a new draft\n\nRequires `entity:create` on `message`, checked with the caller's token before anything is created (403).\n",
2022
2798
  "tags": [
2023
2799
  "Drafts"
2024
2800
  ],
@@ -2058,8 +2834,21 @@
2058
2834
  "/v1/message/drafts:send": {
2059
2835
  "post": {
2060
2836
  "operationId": "sendDraft",
2837
+ "x-epilot-permissions": [
2838
+ {
2839
+ "action": "message:send"
2840
+ },
2841
+ {
2842
+ "action": "entity:create",
2843
+ "resource": "message"
2844
+ },
2845
+ {
2846
+ "action": "entity:edit",
2847
+ "resource": "message"
2848
+ }
2849
+ ],
2061
2850
  "summary": "sendDraft",
2062
- "description": "Send the existing draft to the recipients",
2851
+ "description": "Send the existing draft to the recipients.\n\nRequires `message:send`, `entity:create` on `message` and `entity:edit` on the draft, checked with the\ncaller's token (403). The id must be a DRAFT of the given thread (409).\n",
2063
2852
  "tags": [
2064
2853
  "Drafts"
2065
2854
  ],
@@ -2082,7 +2871,10 @@
2082
2871
  }
2083
2872
  },
2084
2873
  "403": {
2085
- "description": "Forbidden"
2874
+ "description": "Forbidden – the caller is not the draft's author and cannot view the draft"
2875
+ },
2876
+ "409": {
2877
+ "description": "The message is not a draft of the given thread (e.g. already sent)"
2086
2878
  }
2087
2879
  }
2088
2880
  }
@@ -2090,6 +2882,12 @@
2090
2882
  "/v2/message/messages/{id}": {
2091
2883
  "get": {
2092
2884
  "operationId": "getMessageV2",
2885
+ "x-epilot-permissions": [
2886
+ {
2887
+ "action": "entity:view",
2888
+ "resource": "message"
2889
+ }
2890
+ ],
2093
2891
  "summary": "getMessageV2",
2094
2892
  "description": "- Fetches message by ID\n- If the message html is omitted on the entity, then it keeps the content on the message as a signed url\n {\n ...\n _id: \"4d74976d-fb64-47fd-85e2-65eea140f5eb\",\n _schema: \"message\",\n _org: \"org-123\",\n html_omitted: true,\n html_download_url: \"https://s3.eu-central-1.amazonaws.com/epilot-attachments/3f34ce73-089c-4d45-a5ee-c161234e41c3/3f34ce73-089c-4d45-a5ee-c161234e41c3.html\"\n }\n",
2095
2893
  "tags": [
@@ -2465,6 +3263,13 @@
2465
3263
  }
2466
3264
  ],
2467
3265
  "properties": {
3266
+ "link_suggestions": {
3267
+ "type": "array",
3268
+ "description": "Entity-link suggestions recorded when the message arrived: identifiers that matched entities of different customers, so none was linked automatically.",
3269
+ "items": {
3270
+ "$ref": "#/components/schemas/LinkSuggestion"
3271
+ }
3272
+ },
2468
3273
  "html_omitted": {
2469
3274
  "type": "boolean",
2470
3275
  "description": "If true then html is not provided and must be downloaded using the html_download_url",
@@ -2594,7 +3399,7 @@
2594
3399
  },
2595
3400
  "mark_thread_as_read": {
2596
3401
  "type": "boolean",
2597
- "description": "Whether to mark the thread as read by the sender's org/user after sending a reply.\nOnly applies when `parent_id` is set. When false, the thread's `org_read_message` and\n`user_read_message` arrays are left unchanged, so the thread remains unread for anyone\nwho had it unread before. Defaults to true for backward compatibility.\n",
3402
+ "description": "When true (default), replying marks the whole thread read for the sender: every message on the\nthread is marked read, so the thread is read without leaving any message unread under it. When\nfalse, no message is marked and the thread's read-state reflects its messages — a message still\nunread keeps the thread unread (e.g. an automated reply-in-thread stays unread for a human to\npick up). Only applies to replies (`parent_id` set); a new thread always reflects its single\nmessage. Defaults to true.\n",
2598
3403
  "default": true
2599
3404
  },
2600
3405
  "thread": {
@@ -2825,7 +3630,7 @@
2825
3630
  "shared_inbox",
2826
3631
  "saved_view"
2827
3632
  ],
2828
- "description": "Decides which buckets come back, and whether `q` is required. `organization` returns all\nfour buckets from the canonical central-inbox queries and takes no `q`. `shared_inbox`\nand `saved_view` return `unread` alone. A `saved_view` scope names its view with `view_id`;\na `shared_inbox` scope needs only its `inbox_id`, since the query follows from the type.\n\nA `shared_inbox` scope additionally requires `actor: organization` and is refused with a\n400 otherwise. A shared inbox is an organization-level construct \u2014 selecting one always\nswitches the mailbox to the organization \u2014 so it has no per-user read state and the\ncombination would compute a number no surface renders. `saved_view` accepts either actor,\nbecause a view's own configuration names its mailbox.\n"
3633
+ "description": "Decides which buckets come back, and whether `q` is required. `organization` returns all\nfour buckets from the canonical central-inbox queries and takes no `q`. `shared_inbox`\nand `saved_view` return `unread` alone. A `saved_view` scope names its view with `view_id`;\na `shared_inbox` scope needs only its `inbox_id`, since the query follows from the type.\n\nA `shared_inbox` scope additionally requires `actor: organization` and is refused with a\n400 otherwise. A shared inbox is an organization-level construct — selecting one always\nswitches the mailbox to the organization — so it has no per-user read state and the\ncombination would compute a number no surface renders. `saved_view` accepts either actor,\nbecause a view's own configuration names its mailbox.\n"
2829
3634
  },
2830
3635
  "q": {
2831
3636
  "type": "string",
@@ -2867,21 +3672,21 @@
2867
3672
  "organization",
2868
3673
  "user"
2869
3674
  ],
2870
- "description": "Which read state to count against \u2014 the org's or the calling user's. Same meaning as\n`getUnread`'s path parameter, and unrelated to a scope's `type`.\n"
3675
+ "description": "Which read state to count against — the org's or the calling user's. Same meaning as\n`getUnread`'s path parameter, and unrelated to a scope's `type`.\n"
2871
3676
  },
2872
3677
  "email_filter": {
2873
3678
  "type": "array",
2874
3679
  "items": {
2875
3680
  "type": "string"
2876
3681
  },
2877
- "description": "Restrict every scope to messages involving these addresses."
3682
+ "description": "The addresses selected in the address filter, applied to the `organization` scope only.\n\nNot a request-level restriction, despite arriving at request level. A `shared_inbox`\nscope's own list applies no address filter at all, because scoping to an inbox is what\nswitches it off, and a `saved_view` ignores the address lens entirely. Applying this to\neither would make the badge answer a narrower question than the list beneath it.\n"
2878
3683
  },
2879
3684
  "user_groups": {
2880
3685
  "type": "array",
2881
3686
  "items": {
2882
3687
  "type": "string"
2883
3688
  },
2884
- "description": "The caller's group ids, as `group_<id>`, with the same meaning and constraints as on\n`threads:search`. Read only when a scope carries a `view`. Entries not matching\n`group_<id>` are dropped. Not an authorization input.\n"
3689
+ "description": "The caller's group ids, as `group_<id>`, with the same meaning and constraints as on\n`threads:search`. Read when a scope carries a `view` or an organization scope is present. Entries not matching\n`group_<id>` are dropped. Not an authorization input.\n"
2885
3690
  },
2886
3691
  "scopes": {
2887
3692
  "type": "array",
@@ -3175,6 +3980,329 @@
3175
3980
  "user"
3176
3981
  ]
3177
3982
  },
3983
+ "ThreadReplyContext": {
3984
+ "type": "object",
3985
+ "required": [
3986
+ "thread_id",
3987
+ "messages",
3988
+ "related_entities"
3989
+ ],
3990
+ "properties": {
3991
+ "thread_id": {
3992
+ "type": "string"
3993
+ },
3994
+ "topic": {
3995
+ "type": "string"
3996
+ },
3997
+ "reply_to_message_id": {
3998
+ "type": "string",
3999
+ "description": "ID of the latest received message, i.e. the one a reply would answer. Absent if none."
4000
+ },
4001
+ "messages": {
4002
+ "type": "array",
4003
+ "description": "Conversation oldest first, cleaned for prompting",
4004
+ "items": {
4005
+ "$ref": "#/components/schemas/ReplyContextMessage"
4006
+ }
4007
+ },
4008
+ "related_entities": {
4009
+ "type": "array",
4010
+ "description": "Entities linked to the conversation (recipients, message relations), not hydrated",
4011
+ "items": {
4012
+ "$ref": "#/components/schemas/ReplyContextEntityRef"
4013
+ }
4014
+ }
4015
+ }
4016
+ },
4017
+ "ReplyContextMessage": {
4018
+ "type": "object",
4019
+ "required": [
4020
+ "id",
4021
+ "type",
4022
+ "role",
4023
+ "text"
4024
+ ],
4025
+ "properties": {
4026
+ "id": {
4027
+ "type": "string"
4028
+ },
4029
+ "created_at": {
4030
+ "type": "string",
4031
+ "format": "date-time"
4032
+ },
4033
+ "type": {
4034
+ "type": "string",
4035
+ "enum": [
4036
+ "RECEIVED",
4037
+ "SENT"
4038
+ ]
4039
+ },
4040
+ "role": {
4041
+ "type": "string",
4042
+ "description": "Who wrote the message from the organization's point of view",
4043
+ "enum": [
4044
+ "customer",
4045
+ "agent",
4046
+ "partner"
4047
+ ]
4048
+ },
4049
+ "subject": {
4050
+ "type": "string"
4051
+ },
4052
+ "from": {
4053
+ "type": "object",
4054
+ "properties": {
4055
+ "address": {
4056
+ "type": "string"
4057
+ },
4058
+ "name": {
4059
+ "type": "string"
4060
+ }
4061
+ }
4062
+ },
4063
+ "text": {
4064
+ "type": "string",
4065
+ "description": "Plain text body with quotes, forwarded content, reply headers and links removed"
4066
+ }
4067
+ }
4068
+ },
4069
+ "ReplyContextEntityRef": {
4070
+ "type": "object",
4071
+ "required": [
4072
+ "_id",
4073
+ "_schema"
4074
+ ],
4075
+ "properties": {
4076
+ "_id": {
4077
+ "type": "string"
4078
+ },
4079
+ "_schema": {
4080
+ "type": "string"
4081
+ }
4082
+ }
4083
+ },
4084
+ "ThreadSummary": {
4085
+ "type": "object",
4086
+ "required": [
4087
+ "orgId",
4088
+ "jobId",
4089
+ "jobStatus",
4090
+ "createdAt",
4091
+ "updatedAt"
4092
+ ],
4093
+ "properties": {
4094
+ "orgId": {
4095
+ "type": "string"
4096
+ },
4097
+ "jobId": {
4098
+ "type": "string",
4099
+ "description": "Opaque ID of the summary job"
4100
+ },
4101
+ "executionId": {
4102
+ "type": "string",
4103
+ "description": "ID of the AI agent execution generating the summary. Absent until generation has started."
4104
+ },
4105
+ "jobStatus": {
4106
+ "type": "object",
4107
+ "required": [
4108
+ "status"
4109
+ ],
4110
+ "properties": {
4111
+ "status": {
4112
+ "type": "string",
4113
+ "enum": [
4114
+ "INITIATED",
4115
+ "IN_PROGRESS",
4116
+ "COMPLETED",
4117
+ "FAILED"
4118
+ ]
4119
+ },
4120
+ "error": {
4121
+ "type": "string",
4122
+ "description": "Error message if the job failed"
4123
+ }
4124
+ }
4125
+ },
4126
+ "payload": {
4127
+ "$ref": "#/components/schemas/ThreadSummaryPayload"
4128
+ },
4129
+ "createdAt": {
4130
+ "type": "string",
4131
+ "format": "date-time"
4132
+ },
4133
+ "updatedAt": {
4134
+ "type": "string",
4135
+ "format": "date-time"
4136
+ }
4137
+ }
4138
+ },
4139
+ "ThreadSummaryPayload": {
4140
+ "type": "object",
4141
+ "description": "Present once the summary is generated",
4142
+ "properties": {
4143
+ "summary": {
4144
+ "type": "array",
4145
+ "description": "Bullet points summarizing the thread",
4146
+ "nullable": true,
4147
+ "items": {
4148
+ "type": "string"
4149
+ }
4150
+ },
4151
+ "topics": {
4152
+ "type": "array",
4153
+ "description": "Main topics of the thread",
4154
+ "nullable": true,
4155
+ "items": {
4156
+ "type": "string"
4157
+ }
4158
+ },
4159
+ "next_steps": {
4160
+ "type": "array",
4161
+ "description": "Recommended next steps for the agent",
4162
+ "nullable": true,
4163
+ "items": {
4164
+ "type": "string"
4165
+ }
4166
+ },
4167
+ "refs": {
4168
+ "type": "array",
4169
+ "description": "Entities whose IDs can appear in the summary, topics and next steps",
4170
+ "items": {
4171
+ "$ref": "#/components/schemas/ThreadSummaryEntityRef"
4172
+ }
4173
+ }
4174
+ }
4175
+ },
4176
+ "ThreadSummaryEntityRef": {
4177
+ "type": "object",
4178
+ "required": [
4179
+ "id",
4180
+ "displayText",
4181
+ "schema"
4182
+ ],
4183
+ "properties": {
4184
+ "id": {
4185
+ "type": "string"
4186
+ },
4187
+ "displayText": {
4188
+ "type": "string",
4189
+ "example": "Raven GmbH"
4190
+ },
4191
+ "schema": {
4192
+ "type": "string",
4193
+ "description": "Entity schema, or `internal` for a user of the organization",
4194
+ "example": "contact"
4195
+ }
4196
+ }
4197
+ },
4198
+ "ThreadSummaryContext": {
4199
+ "type": "object",
4200
+ "required": [
4201
+ "thread_id",
4202
+ "message_id",
4203
+ "subject",
4204
+ "conversation",
4205
+ "entity_context"
4206
+ ],
4207
+ "properties": {
4208
+ "thread_id": {
4209
+ "type": "string"
4210
+ },
4211
+ "message_id": {
4212
+ "type": "string",
4213
+ "description": "Message the summary is generated for"
4214
+ },
4215
+ "subject": {
4216
+ "type": "string",
4217
+ "description": "Subject of the first message, \"No subject\" if empty"
4218
+ },
4219
+ "conversation": {
4220
+ "type": "string",
4221
+ "description": "Messages formatted as <Message> blocks, ready to insert into the prompt"
4222
+ },
4223
+ "entity_context": {
4224
+ "type": "string",
4225
+ "description": "Entities of the conversation formatted as <Entity> lines, ready to insert into the prompt"
4226
+ }
4227
+ }
4228
+ },
4229
+ "SimilarSentMessagesRequest": {
4230
+ "type": "object",
4231
+ "required": [
4232
+ "queries"
4233
+ ],
4234
+ "properties": {
4235
+ "queries": {
4236
+ "type": "array",
4237
+ "description": "Texts to search with. Results are merged across queries, best score per message wins.",
4238
+ "minItems": 1,
4239
+ "maxItems": 5,
4240
+ "items": {
4241
+ "type": "string",
4242
+ "minLength": 1,
4243
+ "maxLength": 20000
4244
+ }
4245
+ },
4246
+ "limit": {
4247
+ "type": "integer",
4248
+ "description": "Maximum number of messages to return",
4249
+ "minimum": 1,
4250
+ "maximum": 10,
4251
+ "default": 3
4252
+ },
4253
+ "min_score": {
4254
+ "type": "number",
4255
+ "description": "Minimum similarity (0-1, cosine certainty) a message must reach to be returned",
4256
+ "minimum": 0,
4257
+ "maximum": 1,
4258
+ "default": 0.6
4259
+ }
4260
+ }
4261
+ },
4262
+ "SimilarSentMessagesResponse": {
4263
+ "type": "object",
4264
+ "required": [
4265
+ "results"
4266
+ ],
4267
+ "properties": {
4268
+ "results": {
4269
+ "type": "array",
4270
+ "items": {
4271
+ "$ref": "#/components/schemas/SimilarSentMessage"
4272
+ }
4273
+ }
4274
+ }
4275
+ },
4276
+ "SimilarSentMessage": {
4277
+ "type": "object",
4278
+ "required": [
4279
+ "message_id",
4280
+ "text",
4281
+ "score"
4282
+ ],
4283
+ "properties": {
4284
+ "message_id": {
4285
+ "type": "string"
4286
+ },
4287
+ "thread_id": {
4288
+ "type": "string"
4289
+ },
4290
+ "subject": {
4291
+ "type": "string"
4292
+ },
4293
+ "text": {
4294
+ "type": "string",
4295
+ "description": "Anonymized plain text of the sent message"
4296
+ },
4297
+ "created_at": {
4298
+ "type": "string"
4299
+ },
4300
+ "score": {
4301
+ "type": "number",
4302
+ "description": "Similarity in 0-1, higher is more similar"
4303
+ }
4304
+ }
4305
+ },
3178
4306
  "ThreadTimeline": {
3179
4307
  "type": "object",
3180
4308
  "required": [
@@ -3310,7 +4438,7 @@
3310
4438
  },
3311
4439
  "label_name": {
3312
4440
  "type": "string",
3313
- "description": "Resolved taxonomy classification display name (e.g. `Ver\u00e4rgert`), when the label is a classification. Absent for free-form tags."
4441
+ "description": "Resolved taxonomy classification display name (e.g. `Verärgert`), when the label is a classification. Absent for free-form tags."
3314
4442
  }
3315
4443
  }
3316
4444
  },
@@ -3333,7 +4461,7 @@
3333
4461
  },
3334
4462
  "label_name": {
3335
4463
  "type": "string",
3336
- "description": "Resolved taxonomy classification display name (e.g. `Ver\u00e4rgert`), when the label is a classification. Absent for free-form tags."
4464
+ "description": "Resolved taxonomy classification display name (e.g. `Verärgert`), when the label is a classification. Absent for free-form tags."
3337
4465
  }
3338
4466
  }
3339
4467
  },
@@ -3361,6 +4489,10 @@
3361
4489
  "manual",
3362
4490
  "auto"
3363
4491
  ]
4492
+ },
4493
+ "from_suggestion": {
4494
+ "type": "boolean",
4495
+ "description": "The link accepted a pending entity-link suggestion"
3364
4496
  }
3365
4497
  }
3366
4498
  },
@@ -3463,6 +4595,166 @@
3463
4595
  }
3464
4596
  }
3465
4597
  },
4598
+ "LinkSuggestionCandidate": {
4599
+ "type": "object",
4600
+ "required": [
4601
+ "entity_id",
4602
+ "schema"
4603
+ ],
4604
+ "properties": {
4605
+ "entity_id": {
4606
+ "type": "string"
4607
+ },
4608
+ "schema": {
4609
+ "type": "string",
4610
+ "description": "Entity schema slug, e.g. \"contract\""
4611
+ },
4612
+ "attribute": {
4613
+ "type": "string",
4614
+ "description": "The identifier attribute that matched, e.g. \"contract_number\""
4615
+ },
4616
+ "attribute_value": {
4617
+ "type": "string",
4618
+ "description": "The stored value that matched"
4619
+ },
4620
+ "title": {
4621
+ "type": "string",
4622
+ "description": "Entity title when the suggestion was recorded"
4623
+ },
4624
+ "status": {
4625
+ "type": "string",
4626
+ "description": "Resolution of this candidate. Absent on suggestions recorded before candidates were resolved individually.",
4627
+ "enum": [
4628
+ "pending",
4629
+ "linked",
4630
+ "dismissed"
4631
+ ]
4632
+ },
4633
+ "resolved_by": {
4634
+ "$ref": "#/components/schemas/TimelineActor"
4635
+ },
4636
+ "resolved_at": {
4637
+ "type": "string",
4638
+ "format": "date-time"
4639
+ }
4640
+ }
4641
+ },
4642
+ "LinkSuggestion": {
4643
+ "type": "object",
4644
+ "required": [
4645
+ "id",
4646
+ "identifier",
4647
+ "status",
4648
+ "candidates"
4649
+ ],
4650
+ "properties": {
4651
+ "id": {
4652
+ "type": "string",
4653
+ "description": "Stable id of the suggestion (identifier + candidate set), shared across a thread's messages"
4654
+ },
4655
+ "identifier": {
4656
+ "type": "string",
4657
+ "description": "The identifier found in the message, as written there"
4658
+ },
4659
+ "found_in": {
4660
+ "type": "string",
4661
+ "description": "Where the identifier was found, e.g. \"subject\" or \"text\""
4662
+ },
4663
+ "status": {
4664
+ "type": "string",
4665
+ "description": "pending while any candidate is pending; once all are resolved, accepted if any candidate was linked, otherwise dismissed",
4666
+ "enum": [
4667
+ "pending",
4668
+ "accepted",
4669
+ "dismissed"
4670
+ ]
4671
+ },
4672
+ "candidates": {
4673
+ "type": "array",
4674
+ "items": {
4675
+ "$ref": "#/components/schemas/LinkSuggestionCandidate"
4676
+ }
4677
+ },
4678
+ "accepted_entity_ids": {
4679
+ "type": "array",
4680
+ "description": "Candidates that were linked from this suggestion",
4681
+ "items": {
4682
+ "type": "string"
4683
+ }
4684
+ },
4685
+ "resolved_by": {
4686
+ "$ref": "#/components/schemas/TimelineActor"
4687
+ },
4688
+ "resolved_at": {
4689
+ "type": "string",
4690
+ "format": "date-time"
4691
+ },
4692
+ "created_at": {
4693
+ "type": "string",
4694
+ "format": "date-time"
4695
+ }
4696
+ }
4697
+ },
4698
+ "TimelineLinkSuggestion": {
4699
+ "type": "object",
4700
+ "required": [
4701
+ "identifier"
4702
+ ],
4703
+ "properties": {
4704
+ "id": {
4705
+ "type": "string"
4706
+ },
4707
+ "identifier": {
4708
+ "type": "string"
4709
+ },
4710
+ "candidates": {
4711
+ "type": "array",
4712
+ "items": {
4713
+ "$ref": "#/components/schemas/TimelineLinkedEntity"
4714
+ }
4715
+ }
4716
+ }
4717
+ },
4718
+ "MessageEntityLinkSuggestedEvent": {
4719
+ "type": "object",
4720
+ "required": [
4721
+ "type"
4722
+ ],
4723
+ "properties": {
4724
+ "type": {
4725
+ "type": "string",
4726
+ "enum": [
4727
+ "MESSAGE_ENTITY_LINK_SUGGESTED"
4728
+ ]
4729
+ },
4730
+ "suggestions": {
4731
+ "type": "array",
4732
+ "items": {
4733
+ "$ref": "#/components/schemas/TimelineLinkSuggestion"
4734
+ }
4735
+ }
4736
+ }
4737
+ },
4738
+ "MessageEntityLinkSuggestionDismissedEvent": {
4739
+ "type": "object",
4740
+ "required": [
4741
+ "type"
4742
+ ],
4743
+ "properties": {
4744
+ "type": {
4745
+ "type": "string",
4746
+ "enum": [
4747
+ "MESSAGE_ENTITY_LINK_SUGGESTION_DISMISSED"
4748
+ ]
4749
+ },
4750
+ "suggestions": {
4751
+ "type": "array",
4752
+ "items": {
4753
+ "$ref": "#/components/schemas/TimelineLinkSuggestion"
4754
+ }
4755
+ }
4756
+ }
4757
+ },
3466
4758
  "TimelineLinkedEntity": {
3467
4759
  "type": "object",
3468
4760
  "required": [
@@ -3519,6 +4811,12 @@
3519
4811
  {
3520
4812
  "$ref": "#/components/schemas/MessageEntityUnlinkedEvent"
3521
4813
  },
4814
+ {
4815
+ "$ref": "#/components/schemas/MessageEntityLinkSuggestedEvent"
4816
+ },
4817
+ {
4818
+ "$ref": "#/components/schemas/MessageEntityLinkSuggestionDismissedEvent"
4819
+ },
3522
4820
  {
3523
4821
  "$ref": "#/components/schemas/MessageAutoReplySentEvent"
3524
4822
  },
@@ -3550,7 +4848,7 @@
3550
4848
  "timestamp": {
3551
4849
  "type": "string",
3552
4850
  "description": "Timestamp of the event",
3553
- "example": "2024-01-01T00:00:00.000Z"
4851
+ "example": "2024-01-01T00:00:00Z"
3554
4852
  },
3555
4853
  "message_id": {
3556
4854
  "type": "string",