@epilot/sdk 2.19.3 → 2.19.4

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 (222) hide show
  1. package/definitions/access-token-runtime.json +1 -0
  2. package/definitions/access-token.json +835 -0
  3. package/definitions/address-runtime.json +1 -0
  4. package/definitions/address-suggestions-runtime.json +1 -0
  5. package/definitions/address-suggestions.json +582 -0
  6. package/definitions/address.json +578 -0
  7. package/definitions/ai-agents-runtime.json +1 -0
  8. package/definitions/ai-agents.json +2863 -0
  9. package/definitions/app-runtime.json +1 -0
  10. package/definitions/app.json +5743 -0
  11. package/definitions/audit-logs-runtime.json +1 -0
  12. package/definitions/audit-logs.json +305 -0
  13. package/definitions/automation-runtime.json +1 -0
  14. package/definitions/automation.json +5557 -0
  15. package/definitions/billing-runtime.json +1 -0
  16. package/definitions/billing.json +2386 -0
  17. package/definitions/blueprint-manifest-runtime.json +1 -0
  18. package/definitions/blueprint-manifest.json +7718 -0
  19. package/definitions/calendar-runtime.json +1 -0
  20. package/definitions/calendar.json +2904 -0
  21. package/definitions/configuration-hub-runtime.json +1 -0
  22. package/definitions/configuration-hub.json +2250 -0
  23. package/definitions/consent-runtime.json +1 -0
  24. package/definitions/consent.json +344 -0
  25. package/definitions/customer-portal-runtime.json +1 -0
  26. package/definitions/customer-portal.json +19919 -0
  27. package/definitions/dashboard-runtime.json +1 -0
  28. package/definitions/dashboard.json +1355 -0
  29. package/definitions/data-governance-runtime.json +1 -0
  30. package/definitions/data-governance.json +1126 -0
  31. package/definitions/deduplication-runtime.json +1 -0
  32. package/definitions/deduplication.json +782 -0
  33. package/definitions/design-runtime.json +1 -0
  34. package/definitions/design.json +1827 -0
  35. package/definitions/document-runtime.json +1 -0
  36. package/definitions/document.json +758 -0
  37. package/definitions/email-settings-runtime.json +1 -0
  38. package/definitions/email-settings.json +3736 -0
  39. package/definitions/email-template-runtime.json +1 -0
  40. package/definitions/email-template.json +1441 -0
  41. package/definitions/entity-mapping-runtime.json +1 -0
  42. package/definitions/entity-mapping.json +1642 -0
  43. package/definitions/entity-runtime.json +1 -0
  44. package/definitions/entity.json +11517 -0
  45. package/definitions/environments-runtime.json +1 -0
  46. package/definitions/environments.json +539 -0
  47. package/definitions/event-catalog-runtime.json +1 -0
  48. package/definitions/event-catalog.json +1524 -0
  49. package/definitions/file-runtime.json +1 -0
  50. package/definitions/file.json +3905 -0
  51. package/definitions/iban-runtime.json +1 -0
  52. package/definitions/iban.json +132 -0
  53. package/definitions/integration-toolkit-runtime.json +1 -0
  54. package/definitions/integration-toolkit.json +12769 -0
  55. package/definitions/journey-runtime.json +1 -0
  56. package/definitions/journey.json +2640 -0
  57. package/definitions/kanban-runtime.json +1 -0
  58. package/definitions/kanban.json +1506 -0
  59. package/definitions/message-runtime.json +1 -0
  60. package/definitions/message.json +3667 -0
  61. package/definitions/metering-runtime.json +1 -0
  62. package/definitions/metering.json +3132 -0
  63. package/definitions/notes-runtime.json +1 -0
  64. package/definitions/notes.json +1698 -0
  65. package/definitions/notification-runtime.json +1 -0
  66. package/definitions/notification.json +1439 -0
  67. package/definitions/organization-runtime.json +1 -0
  68. package/definitions/organization.json +1192 -0
  69. package/definitions/partner-directory-runtime.json +1 -0
  70. package/definitions/partner-directory.json +2284 -0
  71. package/definitions/permissions-runtime.json +1 -0
  72. package/definitions/permissions.json +1598 -0
  73. package/definitions/pricing-runtime.json +1 -0
  74. package/definitions/pricing-tier-runtime.json +1 -0
  75. package/definitions/pricing-tier.json +105 -0
  76. package/definitions/pricing.json +11569 -0
  77. package/definitions/purpose-runtime.json +1 -0
  78. package/definitions/purpose.json +524 -0
  79. package/definitions/query-runtime.json +1 -0
  80. package/definitions/query.json +3178 -0
  81. package/definitions/sandbox-runtime.json +1 -0
  82. package/definitions/sandbox.json +453 -0
  83. package/definitions/sharing-runtime.json +1 -0
  84. package/definitions/sharing.json +956 -0
  85. package/definitions/snapshot-runtime.json +1 -0
  86. package/definitions/snapshot.json +1103 -0
  87. package/definitions/submission-runtime.json +1 -0
  88. package/definitions/submission.json +313 -0
  89. package/definitions/targeting-runtime.json +1 -0
  90. package/definitions/targeting.json +2222 -0
  91. package/definitions/template-variables-runtime.json +1 -0
  92. package/definitions/template-variables.json +1416 -0
  93. package/definitions/user-runtime.json +1 -0
  94. package/definitions/user.json +3051 -0
  95. package/definitions/validation-rules-runtime.json +1 -0
  96. package/definitions/validation-rules.json +2365 -0
  97. package/definitions/webhooks-runtime.json +1 -0
  98. package/definitions/webhooks.json +1875 -0
  99. package/definitions/workflow-definition-runtime.json +1 -0
  100. package/definitions/workflow-definition.json +3592 -0
  101. package/definitions/workflow-runtime.json +1 -0
  102. package/definitions/workflow.json +4669 -0
  103. package/dist/apis/access-token.cjs +6 -6
  104. package/dist/apis/access-token.js +1 -1
  105. package/dist/apis/address-suggestions.cjs +6 -6
  106. package/dist/apis/address-suggestions.js +1 -1
  107. package/dist/apis/address.cjs +6 -6
  108. package/dist/apis/address.js +1 -1
  109. package/dist/apis/ai-agents.cjs +6 -6
  110. package/dist/apis/ai-agents.js +1 -1
  111. package/dist/apis/app.cjs +6 -6
  112. package/dist/apis/app.js +1 -1
  113. package/dist/apis/audit-logs.cjs +6 -6
  114. package/dist/apis/audit-logs.js +1 -1
  115. package/dist/apis/automation.cjs +6 -6
  116. package/dist/apis/automation.js +1 -1
  117. package/dist/apis/billing.cjs +6 -6
  118. package/dist/apis/billing.js +1 -1
  119. package/dist/apis/blueprint-manifest.cjs +6 -6
  120. package/dist/apis/blueprint-manifest.js +1 -1
  121. package/dist/apis/calendar.cjs +6 -6
  122. package/dist/apis/calendar.js +1 -1
  123. package/dist/apis/configuration-hub.cjs +6 -6
  124. package/dist/apis/configuration-hub.js +1 -1
  125. package/dist/apis/consent.cjs +6 -6
  126. package/dist/apis/consent.js +1 -1
  127. package/dist/apis/customer-portal.cjs +6 -6
  128. package/dist/apis/customer-portal.js +1 -1
  129. package/dist/apis/dashboard.cjs +6 -6
  130. package/dist/apis/dashboard.js +1 -1
  131. package/dist/apis/data-governance.cjs +6 -6
  132. package/dist/apis/data-governance.js +1 -1
  133. package/dist/apis/deduplication.cjs +6 -6
  134. package/dist/apis/deduplication.js +1 -1
  135. package/dist/apis/design.cjs +6 -6
  136. package/dist/apis/design.js +1 -1
  137. package/dist/apis/document.cjs +6 -6
  138. package/dist/apis/document.js +1 -1
  139. package/dist/apis/email-settings.cjs +6 -6
  140. package/dist/apis/email-settings.js +1 -1
  141. package/dist/apis/email-template.cjs +6 -6
  142. package/dist/apis/email-template.js +1 -1
  143. package/dist/apis/entity-mapping.cjs +6 -6
  144. package/dist/apis/entity-mapping.js +1 -1
  145. package/dist/apis/entity.cjs +6 -6
  146. package/dist/apis/entity.js +1 -1
  147. package/dist/apis/environments.cjs +6 -6
  148. package/dist/apis/environments.js +1 -1
  149. package/dist/apis/event-catalog.cjs +6 -6
  150. package/dist/apis/event-catalog.js +1 -1
  151. package/dist/apis/file.cjs +6 -6
  152. package/dist/apis/file.js +1 -1
  153. package/dist/apis/iban.cjs +6 -6
  154. package/dist/apis/iban.js +1 -1
  155. package/dist/apis/integration-toolkit.cjs +6 -6
  156. package/dist/apis/integration-toolkit.js +1 -1
  157. package/dist/apis/journey.cjs +6 -6
  158. package/dist/apis/journey.js +1 -1
  159. package/dist/apis/kanban.cjs +6 -6
  160. package/dist/apis/kanban.js +1 -1
  161. package/dist/apis/message.cjs +6 -6
  162. package/dist/apis/message.js +1 -1
  163. package/dist/apis/metering.cjs +6 -6
  164. package/dist/apis/metering.js +1 -1
  165. package/dist/apis/notes.cjs +6 -6
  166. package/dist/apis/notes.js +1 -1
  167. package/dist/apis/notification.cjs +6 -6
  168. package/dist/apis/notification.js +1 -1
  169. package/dist/apis/organization.cjs +6 -6
  170. package/dist/apis/organization.js +1 -1
  171. package/dist/apis/partner-directory.cjs +6 -6
  172. package/dist/apis/partner-directory.js +1 -1
  173. package/dist/apis/permissions.cjs +6 -6
  174. package/dist/apis/permissions.js +1 -1
  175. package/dist/apis/pricing-tier.cjs +6 -6
  176. package/dist/apis/pricing-tier.js +1 -1
  177. package/dist/apis/pricing.cjs +6 -6
  178. package/dist/apis/pricing.js +1 -1
  179. package/dist/apis/purpose.cjs +6 -6
  180. package/dist/apis/purpose.js +1 -1
  181. package/dist/apis/query.cjs +6 -6
  182. package/dist/apis/query.js +1 -1
  183. package/dist/apis/sandbox.cjs +6 -6
  184. package/dist/apis/sandbox.js +1 -1
  185. package/dist/apis/sharing.cjs +6 -6
  186. package/dist/apis/sharing.js +1 -1
  187. package/dist/apis/snapshot.cjs +6 -6
  188. package/dist/apis/snapshot.js +1 -1
  189. package/dist/apis/submission.cjs +6 -6
  190. package/dist/apis/submission.js +1 -1
  191. package/dist/apis/target.cjs +6 -6
  192. package/dist/apis/target.js +1 -1
  193. package/dist/apis/targeting.cjs +6 -6
  194. package/dist/apis/targeting.d.cts +2 -2
  195. package/dist/apis/targeting.d.ts +2 -2
  196. package/dist/apis/targeting.js +1 -1
  197. package/dist/apis/template-variables.cjs +6 -6
  198. package/dist/apis/template-variables.js +1 -1
  199. package/dist/apis/user.cjs +6 -6
  200. package/dist/apis/user.js +1 -1
  201. package/dist/apis/validation-rules.cjs +6 -6
  202. package/dist/apis/validation-rules.js +1 -1
  203. package/dist/apis/webhooks.cjs +6 -6
  204. package/dist/apis/webhooks.js +1 -1
  205. package/dist/apis/workflow-definition.cjs +6 -6
  206. package/dist/apis/workflow-definition.js +1 -1
  207. package/dist/apis/workflow.cjs +6 -6
  208. package/dist/apis/workflow.js +1 -1
  209. package/dist/{chunk-QWWGJOYR.cjs → chunk-AD5FK5LK.cjs} +1 -1
  210. package/dist/{chunk-UC3IKFHD.js → chunk-PHOP6DMJ.js} +1 -1
  211. package/dist/index.cjs +8 -8
  212. package/dist/index.d.cts +1 -1
  213. package/dist/index.d.ts +1 -1
  214. package/dist/index.js +1 -1
  215. package/dist/targeting-5U4XGOXY.cjs +7 -0
  216. package/dist/targeting-R3G32HI4.js +7 -0
  217. package/dist/{targeting.d-16SvPyj4.d.cts → targeting.d-KcawmWBB.d.cts} +8 -0
  218. package/dist/{targeting.d-16SvPyj4.d.ts → targeting.d-KcawmWBB.d.ts} +8 -0
  219. package/docs/targeting.md +9 -1
  220. package/package.json +1 -1
  221. package/dist/targeting-BTVCLYFW.cjs +0 -7
  222. package/dist/targeting-NWYDE3E7.js +0 -7
@@ -0,0 +1,3736 @@
1
+ {
2
+ "openapi": "3.0.3",
3
+ "info": {
4
+ "title": "Messaging Settings API",
5
+ "version": "1.5.0",
6
+ "description": "The Messaging Settings API provides comprehensive management of email configurations for epilot organizations.\n\n## Overview\n\nThis API enables organizations to:\n- **Email Addresses**: Configure sender email addresses, set primary addresses, and manage email aliases\n- **Email Signatures**: Create and manage HTML email signatures that can be associated with email addresses\n- **Custom Domains**: Add and verify custom email domains for professional branding\n- **Shared Inboxes**: Organize incoming emails into categorized inboxes with team assignments\n- **Microsoft 365 Integration**: Connect Outlook mailboxes for seamless email synchronization\n\n## Key Concepts\n\n### Email Addresses\nEmail addresses represent the sender identities used when composing emails. Each address can have:\n- A display name (e.g., \"Sales Team\")\n- Assigned users and groups who can send from this address\n- A default signature\n- Association with a shared inbox\n\n### Shared Inboxes\nShared inboxes help teams organize and manage incoming emails. Features include:\n- Color-coded categorization\n- Team member assignments\n- Routing rules for incoming messages\n\n### Email Signatures\nHTML signatures that are automatically appended to outgoing emails. Signatures can include:\n- Rich text formatting\n- Images and logos\n- Contact information\n\n### Custom Domains\nOrganizations can configure custom email domains to send emails from their own domain (e.g., `support@yourcompany.com`). This requires:\n1. Adding the domain\n2. Configuring DNS records\n3. Verifying domain ownership\n\n## Authentication\n\nAll endpoints require authentication via Bearer token (JWT) unless otherwise specified.\nUse the `x-epilot-org-id` header to specify the target organization when using shared tenant access.\n"
7
+ },
8
+ "tags": [
9
+ {
10
+ "name": "Email settings",
11
+ "description": "Legacy settings endpoints for managing various email configuration types including signatures,\ncustom domains, email addresses, and duplicate detection settings.\n"
12
+ },
13
+ {
14
+ "name": "Email addresses",
15
+ "description": "Manage email sender addresses for your organization. Email addresses define the identities\nfrom which emails can be sent. Each address can be configured with display names, user/group\nassignments, default signatures, and shared inbox associations.\n"
16
+ },
17
+ {
18
+ "name": "Shared inboxes",
19
+ "description": "Shared inboxes provide team-based email organization. They allow multiple users to collaborate\non incoming messages with features like color-coding, assignee management, and email routing.\nA default inbox is always available and does not need to be explicitly created.\n"
20
+ },
21
+ {
22
+ "name": "Inbox buckets",
23
+ "description": "Inbox buckets are internal storage containers associated with shared inboxes. Each shared inbox\nhas a corresponding bucket for message storage. The default bucket is always available.\n"
24
+ },
25
+ {
26
+ "name": "O365 Outlook Connection",
27
+ "description": "Microsoft Office 365 Outlook integration endpoints. These endpoints enable organizations to:\n- Initiate OAuth connections with Microsoft 365\n- Connect Outlook shared mailboxes\n- Manage connection status and tokens\n- Disconnect integrations when needed\n\nThe integration supports multiple Azure AD tenants and handles token refresh automatically.\n"
28
+ },
29
+ {
30
+ "name": "Custom SMTP",
31
+ "description": "Custom SMTP connection management. Lets organizations configure their own outbound\nSMTP server (e.g. Mailgun, SendGrid, a self-hosted Postfix) for sending emails\nfrom epilot via their existing provider. Credentials are encrypted at rest using\na customer-managed KMS key. Only outbound sending is supported — replies do not\ncome back into epilot.\n"
32
+ },
33
+ {
34
+ "name": "Channels",
35
+ "description": "Channel integration endpoints. Channels represent external communication providers\n(e.g., Microsoft Teams, WhatsApp) that can be connected to an epilot organization.\n\nAll channel endpoints live under `/v2/channels/{channel}`.\n"
36
+ },
37
+ {
38
+ "name": "Settings",
39
+ "description": "Generic settings management for various email configuration types:\n- **signature**: HTML email signatures\n- **email_domain**: Custom email domains\n- **email_address**: Sender email addresses\n- **whitelist_email_address**: Addresses exempt from duplicate detection\n- **restrict_duplicates_within**: Time window for duplicate email detection\n"
40
+ },
41
+ {
42
+ "name": "Domains",
43
+ "description": "Custom email domain management. Add, verify, and configure custom domains to send emails\nfrom your organization's domain. Domain verification requires proper DNS configuration\nincluding MX records and SPF/DKIM settings.\n"
44
+ }
45
+ ],
46
+ "security": [
47
+ {
48
+ "EpilotAuth": []
49
+ },
50
+ {
51
+ "AsOrganization": []
52
+ },
53
+ {
54
+ "EpilotOrg": []
55
+ }
56
+ ],
57
+ "paths": {
58
+ "/v2/email-settings/email-addresses/epilot:provision": {
59
+ "put": {
60
+ "operationId": "provisionEpilotEmailAddress",
61
+ "summary": "provisionEpilotEmailAddress",
62
+ "description": "Provisions or reactivates an epilot-managed email address for the organization.\n\nWhen provisioning a new epilot email address, any previously active epilot email addresses\nwill be automatically deactivated. Only one epilot email address can be active at a time.\n\nEpilot email addresses use the `@epilot.cloud` domain and are fully managed by the platform.\n",
63
+ "tags": [
64
+ "Email addresses"
65
+ ],
66
+ "requestBody": {
67
+ "description": "The epilot email address to provision",
68
+ "required": true,
69
+ "content": {
70
+ "application/json": {
71
+ "schema": {
72
+ "$ref": "#/components/schemas/ProvisionEpilotEmailAddressPayload"
73
+ },
74
+ "example": {
75
+ "address": "mycompany@epilot.cloud"
76
+ }
77
+ }
78
+ }
79
+ },
80
+ "responses": {
81
+ "200": {
82
+ "$ref": "#/components/responses/ProvisionEpilotEmailAddressSuccessResponse"
83
+ },
84
+ "400": {
85
+ "$ref": "#/components/responses/BadRequest"
86
+ },
87
+ "409": {
88
+ "$ref": "#/components/responses/Conflict"
89
+ },
90
+ "500": {
91
+ "$ref": "#/components/responses/InternalServerError"
92
+ }
93
+ }
94
+ }
95
+ },
96
+ "/v2/email-settings/email-addresses/primary": {
97
+ "post": {
98
+ "operationId": "setEmailAddressPrimary",
99
+ "summary": "setEmailAddressPrimary",
100
+ "description": "Sets the specified email address as the primary address for the organization.\n\nThe primary email address is used as the default sender address when composing new emails.\nOnly one email address can be primary at a time; setting a new primary will unset the previous one.\n",
101
+ "tags": [
102
+ "Email addresses"
103
+ ],
104
+ "requestBody": {
105
+ "description": "The email address to set as primary",
106
+ "required": true,
107
+ "content": {
108
+ "application/json": {
109
+ "schema": {
110
+ "$ref": "#/components/schemas/SetEmailAddressPrimaryPayload"
111
+ },
112
+ "example": {
113
+ "address": "sales@yourcompany.com"
114
+ }
115
+ }
116
+ }
117
+ },
118
+ "responses": {
119
+ "200": {
120
+ "$ref": "#/components/responses/SetEmailAddressPrimarySuccessResponse"
121
+ },
122
+ "400": {
123
+ "$ref": "#/components/responses/BadRequest"
124
+ },
125
+ "403": {
126
+ "$ref": "#/components/responses/Forbidden"
127
+ },
128
+ "409": {
129
+ "$ref": "#/components/responses/Conflict"
130
+ },
131
+ "500": {
132
+ "$ref": "#/components/responses/InternalServerError"
133
+ }
134
+ }
135
+ }
136
+ },
137
+ "/v2/email-settings/email-addresses/{id}": {
138
+ "get": {
139
+ "operationId": "getEmailAddress",
140
+ "summary": "getEmailAddress",
141
+ "description": "Retrieves the details of a specific email address by its ID.\n\nReturns the full configuration including display name, assigned users/groups,\ndefault signature, and shared inbox association.\n",
142
+ "tags": [
143
+ "Email addresses"
144
+ ],
145
+ "parameters": [
146
+ {
147
+ "$ref": "#/components/parameters/EmailAddressId"
148
+ }
149
+ ],
150
+ "responses": {
151
+ "200": {
152
+ "$ref": "#/components/responses/GetEmailAddressSuccessResponse"
153
+ },
154
+ "403": {
155
+ "$ref": "#/components/responses/Forbidden"
156
+ },
157
+ "404": {
158
+ "$ref": "#/components/responses/NotFound"
159
+ },
160
+ "500": {
161
+ "$ref": "#/components/responses/InternalServerError"
162
+ }
163
+ }
164
+ },
165
+ "delete": {
166
+ "operationId": "deleteEmailAddress",
167
+ "summary": "deleteEmailAddress",
168
+ "description": "Permanently deletes an email address from the organization.\n\n**Warning**: This action cannot be undone. Users will no longer be able to send\nemails from this address after deletion.\n",
169
+ "tags": [
170
+ "Email addresses"
171
+ ],
172
+ "parameters": [
173
+ {
174
+ "$ref": "#/components/parameters/EmailAddressId"
175
+ }
176
+ ],
177
+ "responses": {
178
+ "204": {
179
+ "$ref": "#/components/responses/NoContent"
180
+ },
181
+ "403": {
182
+ "$ref": "#/components/responses/Forbidden"
183
+ },
184
+ "404": {
185
+ "$ref": "#/components/responses/NotFound"
186
+ },
187
+ "500": {
188
+ "$ref": "#/components/responses/InternalServerError"
189
+ }
190
+ }
191
+ },
192
+ "put": {
193
+ "operationId": "updateEmailAddress",
194
+ "summary": "updateEmailAddress",
195
+ "description": "Updates the configuration of an existing email address.\n\nYou can modify:\n- Display name\n- Assigned users and groups\n- Default signature\n- Shared inbox association\n- Active status\n",
196
+ "tags": [
197
+ "Email addresses"
198
+ ],
199
+ "parameters": [
200
+ {
201
+ "$ref": "#/components/parameters/EmailAddressId"
202
+ }
203
+ ],
204
+ "requestBody": {
205
+ "description": "The fields to update on the email address",
206
+ "content": {
207
+ "application/json": {
208
+ "schema": {
209
+ "$ref": "#/components/schemas/UpdateEmailAddressPayload"
210
+ },
211
+ "example": {
212
+ "name": "Sales Team",
213
+ "user_ids": [
214
+ "user-123",
215
+ "user-456"
216
+ ],
217
+ "default_signature_id": "sig-789",
218
+ "is_active": true
219
+ }
220
+ }
221
+ }
222
+ },
223
+ "responses": {
224
+ "200": {
225
+ "$ref": "#/components/responses/UpdateEmailAddressSuccessResponse"
226
+ },
227
+ "400": {
228
+ "$ref": "#/components/responses/BadRequest"
229
+ },
230
+ "403": {
231
+ "$ref": "#/components/responses/Forbidden"
232
+ },
233
+ "404": {
234
+ "$ref": "#/components/responses/NotFound"
235
+ },
236
+ "409": {
237
+ "$ref": "#/components/responses/Conflict"
238
+ },
239
+ "500": {
240
+ "$ref": "#/components/responses/InternalServerError"
241
+ }
242
+ }
243
+ }
244
+ },
245
+ "/v2/email-settings/email-addresses": {
246
+ "get": {
247
+ "operationId": "listEmailAddresses",
248
+ "summary": "listEmailAddresses",
249
+ "description": "Retrieves all email addresses configured for the organization.\n\nReturns an array of email address configurations including their IDs, display names,\nassigned users/groups, signatures, and status flags.\n",
250
+ "tags": [
251
+ "Email addresses"
252
+ ],
253
+ "responses": {
254
+ "200": {
255
+ "$ref": "#/components/responses/ListEmailAddressesSuccessResponse"
256
+ },
257
+ "403": {
258
+ "$ref": "#/components/responses/Forbidden"
259
+ },
260
+ "500": {
261
+ "$ref": "#/components/responses/InternalServerError"
262
+ }
263
+ }
264
+ },
265
+ "post": {
266
+ "operationId": "addEmailAddress",
267
+ "summary": "addEmailAddress",
268
+ "description": "Adds a new email address to the organization.\n\nThe email address can be from a custom domain (if configured) or any external\nemail provider. Optionally assign users, groups, and a default signature.\n",
269
+ "tags": [
270
+ "Email addresses"
271
+ ],
272
+ "requestBody": {
273
+ "description": "The email address configuration to create",
274
+ "required": true,
275
+ "content": {
276
+ "application/json": {
277
+ "schema": {
278
+ "$ref": "#/components/schemas/CreateEmailAddressPayload"
279
+ },
280
+ "example": {
281
+ "address": "support@yourcompany.com",
282
+ "name": "Customer Support",
283
+ "user_ids": [
284
+ "user-123"
285
+ ],
286
+ "group_ids": [
287
+ "group-456"
288
+ ],
289
+ "default_signature_id": "sig-789",
290
+ "shared_inbox_id": "inbox-abc"
291
+ }
292
+ }
293
+ }
294
+ },
295
+ "responses": {
296
+ "201": {
297
+ "$ref": "#/components/responses/CreateEmailAddressSuccessResponse"
298
+ },
299
+ "400": {
300
+ "$ref": "#/components/responses/BadRequest"
301
+ },
302
+ "403": {
303
+ "$ref": "#/components/responses/Forbidden"
304
+ },
305
+ "409": {
306
+ "$ref": "#/components/responses/Conflict"
307
+ },
308
+ "500": {
309
+ "$ref": "#/components/responses/InternalServerError"
310
+ }
311
+ }
312
+ }
313
+ },
314
+ "/v2/email-settings/shared-inboxes/{id}": {
315
+ "get": {
316
+ "operationId": "getSharedInbox",
317
+ "summary": "getSharedInbox",
318
+ "description": "Retrieves the details of a specific shared inbox by its ID.\n\nReturns the inbox configuration including name, color, description, assigned team members,\nand the associated bucket ID.\n",
319
+ "tags": [
320
+ "Shared inboxes"
321
+ ],
322
+ "parameters": [
323
+ {
324
+ "$ref": "#/components/parameters/SharedInboxId"
325
+ }
326
+ ],
327
+ "responses": {
328
+ "200": {
329
+ "$ref": "#/components/responses/GetSharedInboxSuccessResponse"
330
+ },
331
+ "403": {
332
+ "$ref": "#/components/responses/Forbidden"
333
+ },
334
+ "404": {
335
+ "$ref": "#/components/responses/NotFound"
336
+ },
337
+ "500": {
338
+ "$ref": "#/components/responses/InternalServerError"
339
+ }
340
+ }
341
+ },
342
+ "delete": {
343
+ "operationId": "deleteSharedInbox",
344
+ "summary": "deleteSharedInbox",
345
+ "description": "Deletes a shared inbox and reroutes all associated emails to a successor inbox.\n\nWhen a shared inbox is deleted:\n- All email addresses associated with this inbox will be reassigned to the successor\n- If no successor is specified, emails are routed to the default inbox\n- The inbox's message history is preserved in the successor inbox\n\n**Note**: The default inbox cannot be deleted.\n",
346
+ "tags": [
347
+ "Shared inboxes"
348
+ ],
349
+ "parameters": [
350
+ {
351
+ "$ref": "#/components/parameters/SharedInboxId"
352
+ },
353
+ {
354
+ "name": "successorInboxId",
355
+ "description": "ID of the inbox that will receive emails from the deleted inbox.\nIf not provided, the default inbox (`default`) will be used as the successor.\n",
356
+ "in": "query",
357
+ "required": false,
358
+ "schema": {
359
+ "type": "string"
360
+ },
361
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
362
+ }
363
+ ],
364
+ "responses": {
365
+ "204": {
366
+ "$ref": "#/components/responses/NoContent"
367
+ },
368
+ "400": {
369
+ "$ref": "#/components/responses/BadRequest"
370
+ },
371
+ "403": {
372
+ "$ref": "#/components/responses/Forbidden"
373
+ },
374
+ "404": {
375
+ "$ref": "#/components/responses/NotFound"
376
+ },
377
+ "500": {
378
+ "$ref": "#/components/responses/InternalServerError"
379
+ }
380
+ }
381
+ },
382
+ "put": {
383
+ "operationId": "updateSharedInbox",
384
+ "summary": "updateSharedInbox",
385
+ "description": "Updates the configuration of an existing shared inbox.\n\nYou can modify the inbox name, color, description, and team member assignments.\nChanges take effect immediately for all associated email addresses.\n",
386
+ "tags": [
387
+ "Shared inboxes"
388
+ ],
389
+ "parameters": [
390
+ {
391
+ "$ref": "#/components/parameters/SharedInboxId"
392
+ }
393
+ ],
394
+ "requestBody": {
395
+ "description": "The fields to update on the shared inbox",
396
+ "content": {
397
+ "application/json": {
398
+ "schema": {
399
+ "$ref": "#/components/schemas/UpdateSharedInboxPayload"
400
+ },
401
+ "example": {
402
+ "name": "Customer Support",
403
+ "color": "#4CAF50",
404
+ "description": "Incoming customer support requests",
405
+ "assignees": [
406
+ "user-123",
407
+ "user-456"
408
+ ]
409
+ }
410
+ }
411
+ }
412
+ },
413
+ "responses": {
414
+ "200": {
415
+ "$ref": "#/components/responses/UpdateSharedInboxSuccessResponse"
416
+ },
417
+ "400": {
418
+ "$ref": "#/components/responses/BadRequest"
419
+ },
420
+ "403": {
421
+ "$ref": "#/components/responses/Forbidden"
422
+ },
423
+ "404": {
424
+ "$ref": "#/components/responses/NotFound"
425
+ },
426
+ "409": {
427
+ "$ref": "#/components/responses/Conflict"
428
+ },
429
+ "500": {
430
+ "$ref": "#/components/responses/InternalServerError"
431
+ }
432
+ }
433
+ }
434
+ },
435
+ "/v2/email-settings/shared-inboxes": {
436
+ "get": {
437
+ "operationId": "listSharedInboxes",
438
+ "summary": "listSharedInboxes",
439
+ "description": "Retrieves all shared inboxes configured for the organization.\n\n**Note**: The default inbox (with ID `default`) is not included in this list but is\nalways available for all organizations. You do not need to create it explicitly.\n",
440
+ "tags": [
441
+ "Shared inboxes"
442
+ ],
443
+ "responses": {
444
+ "200": {
445
+ "$ref": "#/components/responses/ListSharedInboxesSuccessResponse"
446
+ },
447
+ "403": {
448
+ "$ref": "#/components/responses/Forbidden"
449
+ },
450
+ "500": {
451
+ "$ref": "#/components/responses/InternalServerError"
452
+ }
453
+ }
454
+ },
455
+ "post": {
456
+ "operationId": "addSharedInbox",
457
+ "summary": "addSharedInbox",
458
+ "description": "Creates a new shared inbox for the organization.\n\nShared inboxes help teams organize and categorize incoming emails.\nEach inbox requires a name and color for visual identification.\n",
459
+ "tags": [
460
+ "Shared inboxes"
461
+ ],
462
+ "requestBody": {
463
+ "description": "The shared inbox configuration to create",
464
+ "required": true,
465
+ "content": {
466
+ "application/json": {
467
+ "schema": {
468
+ "$ref": "#/components/schemas/CreateSharedInboxPayload"
469
+ },
470
+ "example": {
471
+ "name": "Sales Inquiries",
472
+ "color": "#2196F3",
473
+ "description": "Inbound sales and pricing requests",
474
+ "assignees": [
475
+ "user-123",
476
+ "user-456"
477
+ ]
478
+ }
479
+ }
480
+ }
481
+ },
482
+ "responses": {
483
+ "201": {
484
+ "$ref": "#/components/responses/CreateSharedInboxSuccessResponse"
485
+ },
486
+ "400": {
487
+ "$ref": "#/components/responses/BadRequest"
488
+ },
489
+ "403": {
490
+ "$ref": "#/components/responses/Forbidden"
491
+ },
492
+ "409": {
493
+ "$ref": "#/components/responses/Conflict"
494
+ },
495
+ "500": {
496
+ "$ref": "#/components/responses/InternalServerError"
497
+ }
498
+ }
499
+ }
500
+ },
501
+ "/v2/email-settings/inbox-buckets": {
502
+ "get": {
503
+ "operationId": "listInboxBuckets",
504
+ "summary": "listInboxBuckets",
505
+ "description": "Retrieves all inbox buckets for the organization.\n\nInbox buckets are internal storage containers that correspond to shared inboxes.\nEach shared inbox has an associated bucket for storing messages.\n\n**Note**: The default bucket (with ID `default`) is not included in this list but\nis always available for all organizations.\n",
506
+ "tags": [
507
+ "Inbox buckets"
508
+ ],
509
+ "responses": {
510
+ "200": {
511
+ "$ref": "#/components/responses/ListInboxBucketsSuccessResponse"
512
+ },
513
+ "403": {
514
+ "$ref": "#/components/responses/Forbidden"
515
+ },
516
+ "500": {
517
+ "$ref": "#/components/responses/InternalServerError"
518
+ }
519
+ }
520
+ }
521
+ },
522
+ "/v2/outlook/connect": {
523
+ "post": {
524
+ "operationId": "connectOutlook",
525
+ "summary": "connectOutlook",
526
+ "description": "Returns the Microsoft authorization URL for Outlook OAuth.\n\nThe request body selects which features to request scopes for. Feature\nflags are additive; Microsoft OAuth scopes are cumulative. Calling this\nendpoint again with a superset of features (e.g. `mail` already connected,\nand `calendar` added) triggers Microsoft's incremental-consent flow —\nthe user only sees a consent prompt for the new scopes.\n",
527
+ "tags": [
528
+ "O365 Outlook Connection"
529
+ ],
530
+ "requestBody": {
531
+ "required": true,
532
+ "content": {
533
+ "application/json": {
534
+ "schema": {
535
+ "$ref": "#/components/schemas/ConnectOutlookRequest"
536
+ }
537
+ }
538
+ }
539
+ },
540
+ "responses": {
541
+ "200": {
542
+ "description": "Authorization URL",
543
+ "content": {
544
+ "application/json": {
545
+ "schema": {
546
+ "type": "object",
547
+ "required": [
548
+ "authorization_url"
549
+ ],
550
+ "properties": {
551
+ "authorization_url": {
552
+ "type": "string"
553
+ }
554
+ }
555
+ }
556
+ }
557
+ }
558
+ },
559
+ "400": {
560
+ "$ref": "#/components/responses/OutlookErrorResponse"
561
+ },
562
+ "403": {
563
+ "$ref": "#/components/responses/OutlookErrorResponse"
564
+ }
565
+ }
566
+ }
567
+ },
568
+ "/v2/outlook/connection/status": {
569
+ "get": {
570
+ "operationId": "getOutlookConnectionStatus",
571
+ "summary": "getOutlookConnectionStatus",
572
+ "description": "Returns all Microsoft 365 / Outlook connections for the organization.\nSupports multiple connections (one per Azure AD tenant).\n\nEach connection includes an `action` field that tells the UI what button to show\nand what endpoint to call. All actions use GET /outlook/connect.\n",
573
+ "tags": [
574
+ "O365 Outlook Connection"
575
+ ],
576
+ "responses": {
577
+ "200": {
578
+ "description": "Connection status retrieved successfully",
579
+ "content": {
580
+ "application/json": {
581
+ "schema": {
582
+ "type": "object",
583
+ "required": [
584
+ "connections",
585
+ "has_connections"
586
+ ],
587
+ "properties": {
588
+ "connections": {
589
+ "type": "array",
590
+ "description": "List of Outlook connections (one per tenant)",
591
+ "items": {
592
+ "$ref": "#/components/schemas/OutlookConnectionStatus"
593
+ }
594
+ },
595
+ "has_connections": {
596
+ "type": "boolean",
597
+ "description": "Whether any connections exist"
598
+ },
599
+ "teams_enabled": {
600
+ "type": "boolean",
601
+ "description": "Whether Microsoft Teams features are enabled for this organization"
602
+ }
603
+ }
604
+ }
605
+ }
606
+ }
607
+ },
608
+ "400": {
609
+ "description": "Bad request - missing organization ID"
610
+ },
611
+ "500": {
612
+ "description": "Internal server error"
613
+ }
614
+ }
615
+ }
616
+ },
617
+ "/v2/outlook/calendar/admin-consent-status": {
618
+ "get": {
619
+ "operationId": "getCalendarAdminConsentStatus",
620
+ "summary": "getCalendarAdminConsentStatus",
621
+ "description": "Reports whether the caller's organization can connect personal Outlook\ncalendars.\n\nConnecting a personal calendar requires the tenant admin to have\nconsented to epilot's Microsoft 365 app. That consent is tenant-wide,\none-time, and granted for the full scope set (mail + calendar), so the\norg-level Outlook connection set up during onboarding is the gate.\n\nWhen consent is missing the response includes `admin_consent_url` for\nthe admin to open, and the UI should ask the user to involve their IT\ninstead of starting an OAuth flow that would fail.\n",
622
+ "tags": [
623
+ "O365 Outlook Connection"
624
+ ],
625
+ "responses": {
626
+ "200": {
627
+ "description": "Admin consent status for the organization",
628
+ "content": {
629
+ "application/json": {
630
+ "schema": {
631
+ "$ref": "#/components/schemas/CalendarAdminConsentStatus"
632
+ }
633
+ }
634
+ }
635
+ },
636
+ "401": {
637
+ "description": "Unauthorized"
638
+ },
639
+ "500": {
640
+ "description": "Internal server error"
641
+ }
642
+ }
643
+ }
644
+ },
645
+ "/v2/outlook/calendar/me": {
646
+ "get": {
647
+ "operationId": "getMyCalendarConnection",
648
+ "summary": "getMyCalendarConnection",
649
+ "description": "Returns the calling user's personal Outlook calendar connection,\nor null when the user hasn't connected yet.\n\nPer-user calendar connections are distinct from the org-level\nshared-mailbox connection (`/v2/outlook/connection/status`): each\nuser connects their own delegated token because reading user A's\ncalendar requires user A's consent.\n",
650
+ "tags": [
651
+ "O365 Outlook Connection"
652
+ ],
653
+ "responses": {
654
+ "200": {
655
+ "description": "Calendar connection (or null if absent)",
656
+ "content": {
657
+ "application/json": {
658
+ "schema": {
659
+ "$ref": "#/components/schemas/MyCalendarConnectionResponse"
660
+ }
661
+ }
662
+ }
663
+ },
664
+ "401": {
665
+ "description": "Unauthorized"
666
+ },
667
+ "500": {
668
+ "description": "Internal server error"
669
+ }
670
+ }
671
+ },
672
+ "delete": {
673
+ "operationId": "disconnectMyCalendar",
674
+ "summary": "disconnectMyCalendar",
675
+ "description": "Removes the calling user's personal calendar connection.",
676
+ "tags": [
677
+ "O365 Outlook Connection"
678
+ ],
679
+ "responses": {
680
+ "204": {
681
+ "description": "Disconnected"
682
+ },
683
+ "404": {
684
+ "description": "No connection to disconnect"
685
+ },
686
+ "500": {
687
+ "description": "Internal server error"
688
+ }
689
+ }
690
+ }
691
+ },
692
+ "/v2/outlook/connection/disconnect": {
693
+ "post": {
694
+ "operationId": "disconnectOutlook",
695
+ "summary": "disconnectOutlook",
696
+ "description": "Removes the Microsoft 365 / Outlook connection for a specific tenant.\nThis deletes the stored tokens and disconnects the integration.\n",
697
+ "tags": [
698
+ "O365 Outlook Connection"
699
+ ],
700
+ "requestBody": {
701
+ "required": true,
702
+ "content": {
703
+ "application/json": {
704
+ "schema": {
705
+ "type": "object",
706
+ "required": [
707
+ "tenant_id"
708
+ ],
709
+ "properties": {
710
+ "tenant_id": {
711
+ "type": "string",
712
+ "description": "Azure AD Tenant ID of the connection to disconnect"
713
+ }
714
+ }
715
+ }
716
+ }
717
+ }
718
+ },
719
+ "responses": {
720
+ "200": {
721
+ "description": "Successfully disconnected",
722
+ "content": {
723
+ "application/json": {
724
+ "schema": {
725
+ "type": "object",
726
+ "properties": {
727
+ "success": {
728
+ "type": "boolean"
729
+ },
730
+ "tenant_id": {
731
+ "type": "string",
732
+ "description": "The tenant ID that was disconnected"
733
+ },
734
+ "affected_shared_inboxes": {
735
+ "type": "array",
736
+ "items": {
737
+ "type": "string"
738
+ },
739
+ "description": "List of shared inbox IDs that were affected by the disconnection"
740
+ }
741
+ }
742
+ }
743
+ }
744
+ }
745
+ },
746
+ "400": {
747
+ "description": "Bad request - missing tenant_id or organization ID"
748
+ },
749
+ "404": {
750
+ "description": "Connection not found"
751
+ },
752
+ "500": {
753
+ "description": "Internal server error"
754
+ }
755
+ }
756
+ }
757
+ },
758
+ "/v2/channels/msteams/connect": {
759
+ "post": {
760
+ "operationId": "connectMsTeams",
761
+ "summary": "connectMsTeams",
762
+ "description": "Connects Microsoft Teams channel (click-to-call deep links, meetings) for the organization.\nRequires an active Microsoft 365 / Outlook connection.\n",
763
+ "tags": [
764
+ "Channels"
765
+ ],
766
+ "responses": {
767
+ "200": {
768
+ "description": "Teams channel connected successfully",
769
+ "content": {
770
+ "application/json": {
771
+ "schema": {
772
+ "type": "object",
773
+ "properties": {
774
+ "connected": {
775
+ "type": "boolean"
776
+ },
777
+ "connected_at": {
778
+ "type": "string",
779
+ "format": "date-time"
780
+ }
781
+ }
782
+ }
783
+ }
784
+ }
785
+ },
786
+ "400": {
787
+ "description": "No active Outlook connection found",
788
+ "content": {
789
+ "application/json": {
790
+ "schema": {
791
+ "type": "object",
792
+ "properties": {
793
+ "error": {
794
+ "type": "string"
795
+ },
796
+ "message": {
797
+ "type": "string"
798
+ }
799
+ }
800
+ }
801
+ }
802
+ }
803
+ }
804
+ }
805
+ }
806
+ },
807
+ "/v2/channels/msteams/disconnect": {
808
+ "post": {
809
+ "operationId": "disconnectMsTeams",
810
+ "summary": "disconnectMsTeams",
811
+ "description": "Disconnects Microsoft Teams channel for the organization.\n",
812
+ "tags": [
813
+ "Channels"
814
+ ],
815
+ "responses": {
816
+ "200": {
817
+ "description": "Teams channel disconnected successfully",
818
+ "content": {
819
+ "application/json": {
820
+ "schema": {
821
+ "type": "object",
822
+ "properties": {
823
+ "connected": {
824
+ "type": "boolean"
825
+ }
826
+ }
827
+ }
828
+ }
829
+ }
830
+ }
831
+ }
832
+ }
833
+ },
834
+ "/v2/channels/msteams/status": {
835
+ "get": {
836
+ "operationId": "getMsTeamsStatus",
837
+ "summary": "getMsTeamsStatus",
838
+ "description": "Returns the connection status of the Microsoft Teams channel for the organization.\n",
839
+ "tags": [
840
+ "Channels"
841
+ ],
842
+ "responses": {
843
+ "200": {
844
+ "description": "Teams channel status retrieved successfully",
845
+ "content": {
846
+ "application/json": {
847
+ "schema": {
848
+ "type": "object",
849
+ "properties": {
850
+ "connected": {
851
+ "type": "boolean",
852
+ "description": "Whether the Teams channel is connected"
853
+ },
854
+ "connected_at": {
855
+ "type": "string",
856
+ "format": "date-time",
857
+ "description": "When the Teams channel was connected"
858
+ },
859
+ "connected_by_user_id": {
860
+ "type": "string",
861
+ "description": "User ID who connected the Teams channel"
862
+ }
863
+ }
864
+ }
865
+ }
866
+ }
867
+ }
868
+ }
869
+ }
870
+ },
871
+ "/v2/outlook/mailbox/connect": {
872
+ "post": {
873
+ "operationId": "connectOutlookMailbox",
874
+ "summary": "connectOutlookMailbox",
875
+ "description": "Connects an Outlook mailbox:\n 1. Validates the user has access to the mailbox via Microsoft Graph API\n 2. Creates a mapping between the email address of the mailbox and the outlook connection\n 3. Enables the user to send emails as the mailbox's email address\n",
876
+ "tags": [
877
+ "O365 Outlook Connection"
878
+ ],
879
+ "requestBody": {
880
+ "required": true,
881
+ "content": {
882
+ "application/json": {
883
+ "schema": {
884
+ "type": "object",
885
+ "required": [
886
+ "email"
887
+ ],
888
+ "properties": {
889
+ "email": {
890
+ "type": "string",
891
+ "format": "email",
892
+ "description": "Email address of the Outlook mailbox to connect"
893
+ },
894
+ "shared_inbox_id": {
895
+ "type": "string",
896
+ "description": "Shared inbox ID to associate with the mailbox. Defaults to the default shared inbox.",
897
+ "default": "default"
898
+ },
899
+ "name": {
900
+ "type": "string",
901
+ "description": "Sender name to use for the Outlook mailbox email address."
902
+ },
903
+ "user_ids": {
904
+ "type": "array",
905
+ "items": {
906
+ "type": "string"
907
+ },
908
+ "description": "User IDs for which this email address should be available by default."
909
+ },
910
+ "group_ids": {
911
+ "type": "array",
912
+ "items": {
913
+ "type": "string"
914
+ },
915
+ "description": "Group IDs for which this email address should be available by default."
916
+ },
917
+ "default_signature_id": {
918
+ "type": "string",
919
+ "description": "Default signature ID to use for this Outlook mailbox email address."
920
+ },
921
+ "mailboxSyncTimeframe": {
922
+ "type": "string",
923
+ "enum": [
924
+ "5m",
925
+ "1w",
926
+ "2w",
927
+ "1m"
928
+ ],
929
+ "description": "Optional timeframe for initial mailbox sync. When provided, triggers an automatic\nmailbox sync after connecting the mailbox, syncing emails from the specified period.\n"
930
+ }
931
+ }
932
+ }
933
+ }
934
+ }
935
+ },
936
+ "responses": {
937
+ "201": {
938
+ "description": "Mailbox connected successfully",
939
+ "content": {
940
+ "application/json": {
941
+ "schema": {
942
+ "type": "object",
943
+ "required": [
944
+ "email_address",
945
+ "outlook_email",
946
+ "tenant_id",
947
+ "provider"
948
+ ],
949
+ "properties": {
950
+ "email_address": {
951
+ "$ref": "#/components/schemas/EmailAddressResponse"
952
+ },
953
+ "outlook_email": {
954
+ "type": "string",
955
+ "format": "email",
956
+ "description": "The email of the connected mailbox"
957
+ },
958
+ "tenant_id": {
959
+ "type": "string",
960
+ "description": "Azure AD Tenant ID that provisions this mailbox"
961
+ },
962
+ "provider": {
963
+ "type": "string",
964
+ "enum": [
965
+ "outlook"
966
+ ],
967
+ "description": "The provider type"
968
+ }
969
+ }
970
+ }
971
+ }
972
+ }
973
+ },
974
+ "400": {
975
+ "description": "Bad request - missing email parameter"
976
+ },
977
+ "401": {
978
+ "description": "Not connected to Microsoft 365"
979
+ },
980
+ "403": {
981
+ "description": "Access denied - user does not have access to the mailbox"
982
+ },
983
+ "409": {
984
+ "description": "A mailbox email already connected to an Outlook connection"
985
+ },
986
+ "500": {
987
+ "description": "Internal server error"
988
+ }
989
+ }
990
+ }
991
+ },
992
+ "/v2/outlook/mailbox/{email}/disconnect": {
993
+ "post": {
994
+ "operationId": "disconnectOutlookMailbox",
995
+ "summary": "Disconnect Outlook Mailbox",
996
+ "description": "Disconnects a single Outlook mailbox by email address.\nDeletes the email address entity, Outlook email mapping, and Graph API subscriptions.\nDoes not affect the tenant-level Outlook connection.\n",
997
+ "tags": [
998
+ "O365 Outlook Connection"
999
+ ],
1000
+ "parameters": [
1001
+ {
1002
+ "name": "email",
1003
+ "in": "path",
1004
+ "required": true,
1005
+ "schema": {
1006
+ "type": "string",
1007
+ "format": "email"
1008
+ },
1009
+ "description": "Email address of the Outlook mailbox to disconnect"
1010
+ }
1011
+ ],
1012
+ "responses": {
1013
+ "200": {
1014
+ "description": "Mailbox disconnected successfully",
1015
+ "content": {
1016
+ "application/json": {
1017
+ "schema": {
1018
+ "type": "object",
1019
+ "required": [
1020
+ "success",
1021
+ "email"
1022
+ ],
1023
+ "properties": {
1024
+ "success": {
1025
+ "type": "boolean"
1026
+ },
1027
+ "email": {
1028
+ "type": "string",
1029
+ "format": "email",
1030
+ "description": "The email address that was disconnected"
1031
+ }
1032
+ }
1033
+ }
1034
+ }
1035
+ }
1036
+ },
1037
+ "404": {
1038
+ "description": "No Outlook mapping found for this email address"
1039
+ },
1040
+ "500": {
1041
+ "description": "Internal server error"
1042
+ }
1043
+ }
1044
+ }
1045
+ },
1046
+ "/v2/outlook/mailbox/{email}/sync": {
1047
+ "post": {
1048
+ "operationId": "startMailboxSync",
1049
+ "summary": "Start Mailbox Sync",
1050
+ "description": "Triggers an Outlook mailbox sync for the specified email address.\nSyncs existing emails (inbox + sent items) for the specified timeframe.\n",
1051
+ "tags": [
1052
+ "O365 Outlook Connection"
1053
+ ],
1054
+ "parameters": [
1055
+ {
1056
+ "name": "email",
1057
+ "in": "path",
1058
+ "required": true,
1059
+ "schema": {
1060
+ "type": "string",
1061
+ "format": "email"
1062
+ },
1063
+ "description": "Email address of the Outlook mailbox to sync"
1064
+ }
1065
+ ],
1066
+ "requestBody": {
1067
+ "required": true,
1068
+ "content": {
1069
+ "application/json": {
1070
+ "schema": {
1071
+ "type": "object",
1072
+ "required": [
1073
+ "timeframe"
1074
+ ],
1075
+ "properties": {
1076
+ "timeframe": {
1077
+ "allOf": [
1078
+ {
1079
+ "$ref": "#/components/schemas/MailboxSyncTimeframePeriods"
1080
+ }
1081
+ ],
1082
+ "description": "Sync period:\n- 5m: last 5 minutes (quick sync)\n- 1w: 1 week\n- 2w: 2 weeks\n- 1m: 1 month\n"
1083
+ }
1084
+ }
1085
+ }
1086
+ }
1087
+ }
1088
+ },
1089
+ "responses": {
1090
+ "202": {
1091
+ "description": "Sync started successfully",
1092
+ "content": {
1093
+ "application/json": {
1094
+ "schema": {
1095
+ "type": "object",
1096
+ "required": [
1097
+ "execution_id",
1098
+ "status",
1099
+ "timeframe"
1100
+ ],
1101
+ "properties": {
1102
+ "execution_id": {
1103
+ "type": "string",
1104
+ "description": "The execution ID"
1105
+ },
1106
+ "status": {
1107
+ "$ref": "#/components/schemas/MailboxSyncStatuses"
1108
+ },
1109
+ "timeframe": {
1110
+ "$ref": "#/components/schemas/MailboxSyncTimeframePeriods"
1111
+ }
1112
+ }
1113
+ }
1114
+ }
1115
+ }
1116
+ },
1117
+ "400": {
1118
+ "description": "Invalid input provided"
1119
+ },
1120
+ "404": {
1121
+ "description": "Mailbox not connected for the provided email address"
1122
+ },
1123
+ "409": {
1124
+ "description": "A sync in progress for the provided mailbox"
1125
+ },
1126
+ "500": {
1127
+ "description": "Internal server error"
1128
+ }
1129
+ }
1130
+ }
1131
+ },
1132
+ "/v2/outlook/mailbox/{email}/sync/status": {
1133
+ "get": {
1134
+ "operationId": "getMailboxSyncStatus",
1135
+ "summary": "Get Mailbox Sync Status",
1136
+ "description": "Returns the current or latest sync status for the specified mailbox.\nPoll this endpoint to track sync progress.\n",
1137
+ "tags": [
1138
+ "O365 Outlook Connection"
1139
+ ],
1140
+ "parameters": [
1141
+ {
1142
+ "name": "email",
1143
+ "in": "path",
1144
+ "required": true,
1145
+ "schema": {
1146
+ "type": "string",
1147
+ "format": "email"
1148
+ },
1149
+ "description": "Email address of the Outlook mailbox"
1150
+ }
1151
+ ],
1152
+ "responses": {
1153
+ "200": {
1154
+ "description": "Sync status retrieved",
1155
+ "content": {
1156
+ "application/json": {
1157
+ "schema": {
1158
+ "$ref": "#/components/schemas/MailboxSyncStatus"
1159
+ }
1160
+ }
1161
+ }
1162
+ },
1163
+ "404": {
1164
+ "description": "No sync found for this mailbox"
1165
+ },
1166
+ "500": {
1167
+ "description": "Internal server error"
1168
+ }
1169
+ }
1170
+ }
1171
+ },
1172
+ "/v2/outlook/mailbox/{email}/sync/retry": {
1173
+ "post": {
1174
+ "operationId": "retryMailboxSync",
1175
+ "summary": "Retry Failed Messages",
1176
+ "description": "Retries failed messages from a previous sync execution.\nOnly retries messages with status FAILED (not PERMANENTLY_FAILED).\nMessages that fail 3+ retries become PERMANENTLY_FAILED.\n",
1177
+ "tags": [
1178
+ "O365 Outlook Connection"
1179
+ ],
1180
+ "parameters": [
1181
+ {
1182
+ "name": "email",
1183
+ "in": "path",
1184
+ "required": true,
1185
+ "schema": {
1186
+ "type": "string",
1187
+ "format": "email"
1188
+ },
1189
+ "description": "Email address of the Outlook mailbox"
1190
+ }
1191
+ ],
1192
+ "requestBody": {
1193
+ "required": true,
1194
+ "content": {
1195
+ "application/json": {
1196
+ "schema": {
1197
+ "type": "object",
1198
+ "required": [
1199
+ "sync_id"
1200
+ ],
1201
+ "properties": {
1202
+ "sync_id": {
1203
+ "type": "string",
1204
+ "description": "Execution ID of the sync to retry"
1205
+ },
1206
+ "scope": {
1207
+ "type": "string",
1208
+ "enum": [
1209
+ "all_failed"
1210
+ ],
1211
+ "description": "Retry scope. Use 'all_failed' to retry all retryable failed messages."
1212
+ },
1213
+ "message_ids": {
1214
+ "type": "array",
1215
+ "items": {
1216
+ "type": "string"
1217
+ },
1218
+ "description": "Specific Graph message IDs to retry (alternative to scope)"
1219
+ }
1220
+ }
1221
+ }
1222
+ }
1223
+ }
1224
+ },
1225
+ "responses": {
1226
+ "202": {
1227
+ "description": "Retry started",
1228
+ "content": {
1229
+ "application/json": {
1230
+ "schema": {
1231
+ "type": "object",
1232
+ "required": [
1233
+ "retry_execution_id",
1234
+ "messages_queued"
1235
+ ],
1236
+ "properties": {
1237
+ "retry_execution_id": {
1238
+ "type": "string",
1239
+ "description": "Execution ID for the retry sync"
1240
+ },
1241
+ "messages_queued": {
1242
+ "type": "integer",
1243
+ "description": "Number of messages queued for retry"
1244
+ }
1245
+ }
1246
+ }
1247
+ }
1248
+ }
1249
+ },
1250
+ "404": {
1251
+ "description": "No sync found or no retryable messages"
1252
+ },
1253
+ "409": {
1254
+ "description": "A sync is already running for this mailbox"
1255
+ },
1256
+ "500": {
1257
+ "description": "Internal server error"
1258
+ }
1259
+ }
1260
+ }
1261
+ },
1262
+ "/v2/outlook/mailbox/mappings": {
1263
+ "get": {
1264
+ "operationId": "getConnectedOutlookEmails",
1265
+ "summary": "getConnectedOutlookEmails",
1266
+ "description": "Returns all Outlook email addresses connected to the organization.\n",
1267
+ "tags": [
1268
+ "O365 Outlook Connection"
1269
+ ],
1270
+ "responses": {
1271
+ "200": {
1272
+ "description": "Outlook emails retrieved successfully",
1273
+ "content": {
1274
+ "application/json": {
1275
+ "schema": {
1276
+ "type": "object",
1277
+ "required": [
1278
+ "outlook_emails",
1279
+ "count"
1280
+ ],
1281
+ "properties": {
1282
+ "outlook_emails": {
1283
+ "type": "array",
1284
+ "items": {
1285
+ "$ref": "#/components/schemas/ConnectedOutlookEmail"
1286
+ }
1287
+ },
1288
+ "count": {
1289
+ "type": "integer",
1290
+ "description": "Number of Outlook emails"
1291
+ }
1292
+ }
1293
+ }
1294
+ }
1295
+ }
1296
+ },
1297
+ "400": {
1298
+ "description": "Bad request - missing organization ID"
1299
+ },
1300
+ "500": {
1301
+ "description": "Internal server error"
1302
+ }
1303
+ }
1304
+ }
1305
+ },
1306
+ "/v2/smtp/connections": {
1307
+ "get": {
1308
+ "operationId": "listSmtpConnections",
1309
+ "summary": "listSmtpConnections",
1310
+ "description": "Returns all custom SMTP connections configured for the organization.\nPasswords are never returned.\n",
1311
+ "tags": [
1312
+ "Custom SMTP"
1313
+ ],
1314
+ "responses": {
1315
+ "200": {
1316
+ "description": "SMTP connections listed",
1317
+ "content": {
1318
+ "application/json": {
1319
+ "schema": {
1320
+ "type": "object",
1321
+ "required": [
1322
+ "connections",
1323
+ "has_connections"
1324
+ ],
1325
+ "properties": {
1326
+ "connections": {
1327
+ "type": "array",
1328
+ "items": {
1329
+ "$ref": "#/components/schemas/SmtpConnection"
1330
+ }
1331
+ },
1332
+ "has_connections": {
1333
+ "type": "boolean"
1334
+ }
1335
+ }
1336
+ }
1337
+ }
1338
+ }
1339
+ },
1340
+ "403": {
1341
+ "$ref": "#/components/responses/Forbidden"
1342
+ },
1343
+ "500": {
1344
+ "$ref": "#/components/responses/InternalServerError"
1345
+ }
1346
+ }
1347
+ },
1348
+ "post": {
1349
+ "operationId": "createSmtpConnection",
1350
+ "summary": "createSmtpConnection",
1351
+ "description": "Creates a new custom SMTP connection. Runs a live verify against the SMTP server\nbefore persisting; on failure the request is rejected and nothing is saved. Pass\n`skip_test=true` to store the configuration untested instead.\n",
1352
+ "tags": [
1353
+ "Custom SMTP"
1354
+ ],
1355
+ "parameters": [
1356
+ {
1357
+ "name": "skip_test",
1358
+ "in": "query",
1359
+ "required": false,
1360
+ "description": "Save without running the live verify. Use when the server is not reachable from\nepilot yet, or when a referenced `{{ env.* }}` secret has not been set. The\nconnection is stored untested — `last_test_status` is left unset rather than\nclaimed as `ok` — and env references are not resolved either, since an\nunresolvable one is expected in this case.\n",
1361
+ "schema": {
1362
+ "type": "boolean",
1363
+ "default": false
1364
+ }
1365
+ }
1366
+ ],
1367
+ "requestBody": {
1368
+ "required": true,
1369
+ "content": {
1370
+ "application/json": {
1371
+ "schema": {
1372
+ "$ref": "#/components/schemas/CreateSmtpConnectionRequest"
1373
+ }
1374
+ }
1375
+ }
1376
+ },
1377
+ "responses": {
1378
+ "201": {
1379
+ "description": "SMTP connection created",
1380
+ "content": {
1381
+ "application/json": {
1382
+ "schema": {
1383
+ "$ref": "#/components/schemas/SmtpConnection"
1384
+ }
1385
+ }
1386
+ }
1387
+ },
1388
+ "400": {
1389
+ "description": "Validation error, SMTP test failed, or refused for security reasons\n(private IP, plaintext on non-localhost host, invalid TLS).\n"
1390
+ },
1391
+ "403": {
1392
+ "$ref": "#/components/responses/Forbidden"
1393
+ },
1394
+ "409": {
1395
+ "$ref": "#/components/responses/Conflict"
1396
+ },
1397
+ "500": {
1398
+ "$ref": "#/components/responses/InternalServerError"
1399
+ }
1400
+ }
1401
+ }
1402
+ },
1403
+ "/v2/smtp/connections/{connectionId}": {
1404
+ "parameters": [
1405
+ {
1406
+ "name": "connectionId",
1407
+ "in": "path",
1408
+ "required": true,
1409
+ "schema": {
1410
+ "type": "string"
1411
+ }
1412
+ }
1413
+ ],
1414
+ "get": {
1415
+ "operationId": "getSmtpConnection",
1416
+ "summary": "getSmtpConnection",
1417
+ "description": "Returns a single custom SMTP connection by id. The password is never returned.",
1418
+ "tags": [
1419
+ "Custom SMTP"
1420
+ ],
1421
+ "responses": {
1422
+ "200": {
1423
+ "description": "SMTP connection retrieved",
1424
+ "content": {
1425
+ "application/json": {
1426
+ "schema": {
1427
+ "$ref": "#/components/schemas/SmtpConnection"
1428
+ }
1429
+ }
1430
+ }
1431
+ },
1432
+ "403": {
1433
+ "$ref": "#/components/responses/Forbidden"
1434
+ },
1435
+ "404": {
1436
+ "$ref": "#/components/responses/NotFound"
1437
+ }
1438
+ }
1439
+ },
1440
+ "put": {
1441
+ "operationId": "updateSmtpConnection",
1442
+ "summary": "updateSmtpConnection",
1443
+ "description": "Partial update; omitted fields keep their existing values. The merged\nconfiguration is verified against the SMTP server before persisting. Pass\n`skip_test=true` to store it untested instead, which also clears any previous\ntest result — it described a configuration that no longer applies.\n",
1444
+ "tags": [
1445
+ "Custom SMTP"
1446
+ ],
1447
+ "parameters": [
1448
+ {
1449
+ "name": "skip_test",
1450
+ "in": "query",
1451
+ "required": false,
1452
+ "description": "Save without running the live verify. Use when the server is not reachable from\nepilot yet, or when a referenced `{{ env.* }}` secret has not been set. The\nconnection is stored untested — `last_test_status` is left unset rather than\nclaimed as `ok` — and env references are not resolved either, since an\nunresolvable one is expected in this case.\n",
1453
+ "schema": {
1454
+ "type": "boolean",
1455
+ "default": false
1456
+ }
1457
+ }
1458
+ ],
1459
+ "requestBody": {
1460
+ "required": true,
1461
+ "content": {
1462
+ "application/json": {
1463
+ "schema": {
1464
+ "$ref": "#/components/schemas/UpdateSmtpConnectionRequest"
1465
+ }
1466
+ }
1467
+ }
1468
+ },
1469
+ "responses": {
1470
+ "200": {
1471
+ "description": "SMTP connection updated",
1472
+ "content": {
1473
+ "application/json": {
1474
+ "schema": {
1475
+ "$ref": "#/components/schemas/SmtpConnection"
1476
+ }
1477
+ }
1478
+ }
1479
+ },
1480
+ "400": {
1481
+ "description": "Validation error or SMTP test failed"
1482
+ },
1483
+ "403": {
1484
+ "$ref": "#/components/responses/Forbidden"
1485
+ },
1486
+ "404": {
1487
+ "$ref": "#/components/responses/NotFound"
1488
+ },
1489
+ "409": {
1490
+ "$ref": "#/components/responses/Conflict"
1491
+ }
1492
+ }
1493
+ },
1494
+ "delete": {
1495
+ "operationId": "deleteSmtpConnection",
1496
+ "summary": "deleteSmtpConnection",
1497
+ "description": "Deletes a custom SMTP connection. Messages already sent are unaffected.",
1498
+ "tags": [
1499
+ "Custom SMTP"
1500
+ ],
1501
+ "responses": {
1502
+ "200": {
1503
+ "description": "SMTP connection deleted",
1504
+ "content": {
1505
+ "application/json": {
1506
+ "schema": {
1507
+ "type": "object",
1508
+ "properties": {
1509
+ "success": {
1510
+ "type": "boolean"
1511
+ },
1512
+ "connection_id": {
1513
+ "type": "string"
1514
+ }
1515
+ }
1516
+ }
1517
+ }
1518
+ }
1519
+ },
1520
+ "403": {
1521
+ "$ref": "#/components/responses/Forbidden"
1522
+ },
1523
+ "404": {
1524
+ "$ref": "#/components/responses/NotFound"
1525
+ }
1526
+ }
1527
+ }
1528
+ },
1529
+ "/v2/smtp/connections/{connectionId}/test": {
1530
+ "parameters": [
1531
+ {
1532
+ "name": "connectionId",
1533
+ "in": "path",
1534
+ "required": true,
1535
+ "schema": {
1536
+ "type": "string"
1537
+ }
1538
+ }
1539
+ ],
1540
+ "post": {
1541
+ "operationId": "testSmtpConnection",
1542
+ "summary": "testSmtpConnection",
1543
+ "description": "Re-runs a live SMTP verify against the saved configuration (EHLO + AUTH + NOOP + QUIT)\nand updates `last_test_status` / `last_tested_at` on the connection.\n",
1544
+ "tags": [
1545
+ "Custom SMTP"
1546
+ ],
1547
+ "responses": {
1548
+ "200": {
1549
+ "description": "SMTP test executed",
1550
+ "content": {
1551
+ "application/json": {
1552
+ "schema": {
1553
+ "$ref": "#/components/schemas/SmtpTestResult"
1554
+ }
1555
+ }
1556
+ }
1557
+ },
1558
+ "403": {
1559
+ "$ref": "#/components/responses/Forbidden"
1560
+ },
1561
+ "404": {
1562
+ "$ref": "#/components/responses/NotFound"
1563
+ }
1564
+ }
1565
+ }
1566
+ },
1567
+ "/v2/smtp/senders": {
1568
+ "get": {
1569
+ "operationId": "listSmtpSenders",
1570
+ "summary": "listSmtpSenders",
1571
+ "description": "Returns every address registered to send through a custom SMTP connection.",
1572
+ "tags": [
1573
+ "Custom SMTP"
1574
+ ],
1575
+ "responses": {
1576
+ "200": {
1577
+ "description": "SMTP senders listed",
1578
+ "content": {
1579
+ "application/json": {
1580
+ "schema": {
1581
+ "type": "object",
1582
+ "required": [
1583
+ "senders"
1584
+ ],
1585
+ "properties": {
1586
+ "senders": {
1587
+ "type": "array",
1588
+ "items": {
1589
+ "$ref": "#/components/schemas/SmtpSender"
1590
+ }
1591
+ }
1592
+ }
1593
+ }
1594
+ }
1595
+ }
1596
+ },
1597
+ "403": {
1598
+ "$ref": "#/components/responses/Forbidden"
1599
+ },
1600
+ "500": {
1601
+ "$ref": "#/components/responses/InternalServerError"
1602
+ }
1603
+ }
1604
+ },
1605
+ "post": {
1606
+ "operationId": "connectSmtpSender",
1607
+ "summary": "connectSmtpSender",
1608
+ "description": "Registers an address as a sender on a custom SMTP connection:\n 1. Creates the email address so it can be picked in the composer\n 2. Binds it to the connection, so outgoing mail from it is routed there\nThe SMTP server still has the final say on which From addresses it accepts.\n",
1609
+ "tags": [
1610
+ "Custom SMTP"
1611
+ ],
1612
+ "requestBody": {
1613
+ "required": true,
1614
+ "content": {
1615
+ "application/json": {
1616
+ "schema": {
1617
+ "$ref": "#/components/schemas/ConnectSmtpSenderRequest"
1618
+ }
1619
+ }
1620
+ }
1621
+ },
1622
+ "responses": {
1623
+ "201": {
1624
+ "description": "Sender connected",
1625
+ "content": {
1626
+ "application/json": {
1627
+ "schema": {
1628
+ "type": "object",
1629
+ "required": [
1630
+ "email_address",
1631
+ "sender"
1632
+ ],
1633
+ "properties": {
1634
+ "email_address": {
1635
+ "$ref": "#/components/schemas/EmailAddressResponse"
1636
+ },
1637
+ "sender": {
1638
+ "$ref": "#/components/schemas/SmtpSender"
1639
+ }
1640
+ }
1641
+ }
1642
+ }
1643
+ }
1644
+ },
1645
+ "400": {
1646
+ "description": "Validation error"
1647
+ },
1648
+ "403": {
1649
+ "$ref": "#/components/responses/Forbidden"
1650
+ },
1651
+ "404": {
1652
+ "description": "The referenced SMTP connection does not exist"
1653
+ },
1654
+ "409": {
1655
+ "description": "The address is already registered, here or in another organization"
1656
+ },
1657
+ "500": {
1658
+ "$ref": "#/components/responses/InternalServerError"
1659
+ }
1660
+ }
1661
+ }
1662
+ },
1663
+ "/v2/smtp/senders/{email}": {
1664
+ "parameters": [
1665
+ {
1666
+ "name": "email",
1667
+ "in": "path",
1668
+ "required": true,
1669
+ "schema": {
1670
+ "type": "string",
1671
+ "format": "email"
1672
+ }
1673
+ }
1674
+ ],
1675
+ "delete": {
1676
+ "operationId": "disconnectSmtpSender",
1677
+ "summary": "disconnectSmtpSender",
1678
+ "description": "Removes a sender address: deletes the email address and its binding to the SMTP\nconnection. The connection itself and messages already sent are unaffected.\n",
1679
+ "tags": [
1680
+ "Custom SMTP"
1681
+ ],
1682
+ "responses": {
1683
+ "200": {
1684
+ "description": "Sender disconnected",
1685
+ "content": {
1686
+ "application/json": {
1687
+ "schema": {
1688
+ "type": "object",
1689
+ "required": [
1690
+ "success",
1691
+ "email"
1692
+ ],
1693
+ "properties": {
1694
+ "success": {
1695
+ "type": "boolean"
1696
+ },
1697
+ "email": {
1698
+ "type": "string",
1699
+ "format": "email"
1700
+ }
1701
+ }
1702
+ }
1703
+ }
1704
+ }
1705
+ },
1706
+ "403": {
1707
+ "$ref": "#/components/responses/Forbidden"
1708
+ },
1709
+ "404": {
1710
+ "$ref": "#/components/responses/NotFound"
1711
+ },
1712
+ "500": {
1713
+ "$ref": "#/components/responses/InternalServerError"
1714
+ }
1715
+ }
1716
+ }
1717
+ },
1718
+ "/v2/outlook/oauth/callback": {
1719
+ "get": {
1720
+ "operationId": "outlookOAuthCallback",
1721
+ "summary": "outlookOAuthCallback",
1722
+ "description": "Exchanges authorization code for tokens and stores them.",
1723
+ "tags": [
1724
+ "O365 Outlook Connection"
1725
+ ],
1726
+ "security": [],
1727
+ "parameters": [
1728
+ {
1729
+ "name": "code",
1730
+ "in": "query",
1731
+ "required": false,
1732
+ "schema": {
1733
+ "type": "string"
1734
+ }
1735
+ },
1736
+ {
1737
+ "name": "state",
1738
+ "in": "query",
1739
+ "required": true,
1740
+ "schema": {
1741
+ "type": "string"
1742
+ }
1743
+ },
1744
+ {
1745
+ "name": "session_state",
1746
+ "in": "query",
1747
+ "required": false,
1748
+ "schema": {
1749
+ "type": "string"
1750
+ }
1751
+ },
1752
+ {
1753
+ "name": "error",
1754
+ "in": "query",
1755
+ "required": false,
1756
+ "schema": {
1757
+ "type": "string"
1758
+ }
1759
+ },
1760
+ {
1761
+ "name": "error_description",
1762
+ "in": "query",
1763
+ "required": false,
1764
+ "schema": {
1765
+ "type": "string"
1766
+ }
1767
+ },
1768
+ {
1769
+ "name": "error_subcode",
1770
+ "in": "query",
1771
+ "required": false,
1772
+ "schema": {
1773
+ "type": "string"
1774
+ }
1775
+ },
1776
+ {
1777
+ "name": "client_info",
1778
+ "in": "query",
1779
+ "required": false,
1780
+ "schema": {
1781
+ "type": "string"
1782
+ }
1783
+ },
1784
+ {
1785
+ "name": "error_uri",
1786
+ "in": "query",
1787
+ "required": false,
1788
+ "schema": {
1789
+ "type": "string"
1790
+ }
1791
+ },
1792
+ {
1793
+ "name": "admin_consent",
1794
+ "in": "query",
1795
+ "required": false,
1796
+ "schema": {
1797
+ "type": "string"
1798
+ }
1799
+ },
1800
+ {
1801
+ "name": "tenant",
1802
+ "in": "query",
1803
+ "required": false,
1804
+ "schema": {
1805
+ "type": "string"
1806
+ }
1807
+ },
1808
+ {
1809
+ "name": "clientdata",
1810
+ "in": "query",
1811
+ "required": false,
1812
+ "schema": {
1813
+ "type": "string"
1814
+ }
1815
+ }
1816
+ ],
1817
+ "responses": {
1818
+ "200": {
1819
+ "description": "Stored",
1820
+ "content": {
1821
+ "application/json": {
1822
+ "schema": {
1823
+ "type": "object",
1824
+ "properties": {
1825
+ "connected": {
1826
+ "type": "boolean"
1827
+ },
1828
+ "expires_at": {
1829
+ "type": "string",
1830
+ "format": "date-time"
1831
+ },
1832
+ "scope": {
1833
+ "type": "string"
1834
+ }
1835
+ }
1836
+ }
1837
+ }
1838
+ }
1839
+ }
1840
+ }
1841
+ }
1842
+ },
1843
+ "/v1/email-settings": {
1844
+ "get": {
1845
+ "operationId": "getSettings",
1846
+ "summary": "getSettings",
1847
+ "description": "Retrieves settings of a specific type for the organization.\n\nIf an `id` is provided, returns only that specific setting.\nOtherwise, returns all settings of the specified type.\n\n## Setting Types\n\n| Type | Description |\n|------|-------------|\n| `signature` | HTML email signatures |\n| `email_domain` | Custom email domains |\n| `email_address` | Sender email addresses |\n| `whitelist_email_address` | Addresses exempt from duplicate detection |\n| `restrict_duplicates_within` | Time window for duplicate email detection |\n",
1848
+ "tags": [
1849
+ "Settings"
1850
+ ],
1851
+ "parameters": [
1852
+ {
1853
+ "name": "type",
1854
+ "description": "The type of settings to retrieve. Determines which category of\nemail settings will be returned.\n",
1855
+ "in": "query",
1856
+ "required": true,
1857
+ "schema": {
1858
+ "$ref": "#/components/schemas/SettingType"
1859
+ },
1860
+ "example": "signature"
1861
+ },
1862
+ {
1863
+ "name": "id",
1864
+ "description": "Optional ID to retrieve a specific setting. If omitted, all settings\nof the specified type are returned.\n",
1865
+ "in": "query",
1866
+ "schema": {
1867
+ "type": "string"
1868
+ },
1869
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
1870
+ }
1871
+ ],
1872
+ "responses": {
1873
+ "200": {
1874
+ "description": "Successfully retrieved settings. Returns either a single setting object\n(when `id` is provided) or an array of settings.\n",
1875
+ "content": {
1876
+ "application/json": {
1877
+ "schema": {
1878
+ "$ref": "#/components/schemas/SettingsResponse"
1879
+ },
1880
+ "examples": {
1881
+ "signature_list": {
1882
+ "summary": "List of email signatures",
1883
+ "value": [
1884
+ {
1885
+ "id": "sig-123",
1886
+ "type": "signature",
1887
+ "name": "Default Signature",
1888
+ "value": "Best regards",
1889
+ "html": "<p>Best regards,<br/>The Team</p>",
1890
+ "created_at": "2024-01-15T10:30:00Z"
1891
+ }
1892
+ ]
1893
+ },
1894
+ "single_signature": {
1895
+ "summary": "Single signature by ID",
1896
+ "value": {
1897
+ "id": "sig-123",
1898
+ "type": "signature",
1899
+ "name": "Default Signature",
1900
+ "value": "Best regards",
1901
+ "html": "<p>Best regards,<br/>The Team</p>",
1902
+ "created_at": "2024-01-15T10:30:00Z"
1903
+ }
1904
+ }
1905
+ }
1906
+ }
1907
+ }
1908
+ },
1909
+ "403": {
1910
+ "$ref": "#/components/responses/Forbidden"
1911
+ },
1912
+ "404": {
1913
+ "$ref": "#/components/responses/NotFound"
1914
+ }
1915
+ }
1916
+ },
1917
+ "post": {
1918
+ "operationId": "addSetting",
1919
+ "summary": "addSetting",
1920
+ "description": "Creates a new setting of the specified type.\n\nThe setting type determines which fields are applicable:\n- **signature**: Requires `name`, `value` (plain text), and `html` (HTML content)\n- **email_domain**: Requires `value` (domain name)\n- **whitelist_email_address**: Requires `value` (email address)\n- **restrict_duplicates_within**: Requires `value` (time duration like \"5m\", \"1d\")\n",
1921
+ "tags": [
1922
+ "Settings"
1923
+ ],
1924
+ "requestBody": {
1925
+ "description": "The setting to create",
1926
+ "required": true,
1927
+ "content": {
1928
+ "application/json": {
1929
+ "schema": {
1930
+ "$ref": "#/components/schemas/Setting"
1931
+ },
1932
+ "examples": {
1933
+ "create_signature": {
1934
+ "summary": "Create an email signature",
1935
+ "value": {
1936
+ "type": "signature",
1937
+ "name": "Sales Signature",
1938
+ "value": "Best regards, Sales Team",
1939
+ "html": "<p>Best regards,<br/><strong>Sales Team</strong></p>"
1940
+ }
1941
+ },
1942
+ "create_whitelist": {
1943
+ "summary": "Whitelist an email address from duplicate detection",
1944
+ "value": {
1945
+ "type": "whitelist_email_address",
1946
+ "value": "noreply@automated-system.com"
1947
+ }
1948
+ },
1949
+ "set_duplicate_window": {
1950
+ "summary": "Set duplicate detection time window",
1951
+ "value": {
1952
+ "type": "restrict_duplicates_within",
1953
+ "value": "5m"
1954
+ }
1955
+ }
1956
+ }
1957
+ }
1958
+ }
1959
+ },
1960
+ "responses": {
1961
+ "200": {
1962
+ "description": "Setting created successfully",
1963
+ "content": {
1964
+ "application/json": {
1965
+ "schema": {
1966
+ "$ref": "#/components/schemas/SettingsResponse"
1967
+ }
1968
+ }
1969
+ }
1970
+ },
1971
+ "403": {
1972
+ "$ref": "#/components/responses/Forbidden"
1973
+ },
1974
+ "404": {
1975
+ "$ref": "#/components/responses/NotFound"
1976
+ }
1977
+ }
1978
+ },
1979
+ "delete": {
1980
+ "operationId": "deleteSetting",
1981
+ "summary": "deleteSetting",
1982
+ "description": "Deletes a setting by its ID and type.\n\nBoth the `id` and `type` are required to uniquely identify the setting to delete.\n\n**Warning**: This action cannot be undone.\n",
1983
+ "tags": [
1984
+ "Settings"
1985
+ ],
1986
+ "requestBody": {
1987
+ "description": "The setting identifier to delete",
1988
+ "required": true,
1989
+ "content": {
1990
+ "application/json": {
1991
+ "schema": {
1992
+ "type": "object",
1993
+ "required": [
1994
+ "id",
1995
+ "type"
1996
+ ],
1997
+ "properties": {
1998
+ "type": {
1999
+ "$ref": "#/components/schemas/SettingType"
2000
+ },
2001
+ "id": {
2002
+ "type": "string",
2003
+ "description": "The unique identifier of the setting to delete",
2004
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2005
+ }
2006
+ }
2007
+ },
2008
+ "example": {
2009
+ "type": "signature",
2010
+ "id": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2011
+ }
2012
+ }
2013
+ }
2014
+ },
2015
+ "responses": {
2016
+ "200": {
2017
+ "description": "Setting deleted successfully. Returns the deleted setting.",
2018
+ "content": {
2019
+ "application/json": {
2020
+ "schema": {
2021
+ "$ref": "#/components/schemas/Setting"
2022
+ }
2023
+ }
2024
+ }
2025
+ },
2026
+ "403": {
2027
+ "$ref": "#/components/responses/Forbidden"
2028
+ },
2029
+ "404": {
2030
+ "$ref": "#/components/responses/NotFound"
2031
+ }
2032
+ }
2033
+ }
2034
+ },
2035
+ "/v1/email-settings/{id}": {
2036
+ "post": {
2037
+ "operationId": "updateSetting",
2038
+ "summary": "updateSetting",
2039
+ "description": "Updates an existing setting identified by its ID.\n\nInclude the `type` field in the request body to specify which setting type\nis being updated. Only the fields provided will be updated.\n",
2040
+ "tags": [
2041
+ "Settings"
2042
+ ],
2043
+ "parameters": [
2044
+ {
2045
+ "name": "id",
2046
+ "description": "The unique identifier of the setting to update",
2047
+ "in": "path",
2048
+ "required": true,
2049
+ "schema": {
2050
+ "type": "string"
2051
+ },
2052
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2053
+ }
2054
+ ],
2055
+ "requestBody": {
2056
+ "description": "The setting fields to update",
2057
+ "required": true,
2058
+ "content": {
2059
+ "application/json": {
2060
+ "schema": {
2061
+ "$ref": "#/components/schemas/Setting"
2062
+ },
2063
+ "example": {
2064
+ "type": "signature",
2065
+ "name": "Updated Signature Name",
2066
+ "html": "<p>Updated signature content</p>"
2067
+ }
2068
+ }
2069
+ }
2070
+ },
2071
+ "responses": {
2072
+ "200": {
2073
+ "description": "Setting updated successfully. Returns the updated setting.",
2074
+ "content": {
2075
+ "application/json": {
2076
+ "schema": {
2077
+ "$ref": "#/components/schemas/Setting"
2078
+ }
2079
+ }
2080
+ }
2081
+ },
2082
+ "403": {
2083
+ "$ref": "#/components/responses/Forbidden"
2084
+ },
2085
+ "404": {
2086
+ "$ref": "#/components/responses/NotFound"
2087
+ }
2088
+ }
2089
+ }
2090
+ },
2091
+ "/v1/email-settings/domain": {
2092
+ "post": {
2093
+ "operationId": "addDomain",
2094
+ "summary": "addDomain",
2095
+ "description": "Adds a custom email domain to the organization.\n\nAfter adding the domain, you must:\n1. Configure the required DNS records (provided in the response)\n2. Verify the domain using the verification endpoint\n\nUntil verification is complete, the domain cannot be used for sending emails.\n",
2096
+ "tags": [
2097
+ "Domains"
2098
+ ],
2099
+ "requestBody": {
2100
+ "description": "The domain to add",
2101
+ "required": true,
2102
+ "content": {
2103
+ "application/json": {
2104
+ "schema": {
2105
+ "$ref": "#/components/schemas/Domain"
2106
+ },
2107
+ "example": {
2108
+ "domain": "mail.yourcompany.com"
2109
+ }
2110
+ }
2111
+ }
2112
+ },
2113
+ "responses": {
2114
+ "200": {
2115
+ "description": "Domain added successfully. The response includes DNS records that must be\nconfigured before verification.\n",
2116
+ "content": {
2117
+ "application/json": {
2118
+ "schema": {
2119
+ "$ref": "#/components/schemas/SettingsResponse"
2120
+ }
2121
+ }
2122
+ }
2123
+ },
2124
+ "403": {
2125
+ "$ref": "#/components/responses/Forbidden"
2126
+ },
2127
+ "404": {
2128
+ "$ref": "#/components/responses/NotFound"
2129
+ }
2130
+ }
2131
+ },
2132
+ "delete": {
2133
+ "operationId": "deleteDomain",
2134
+ "summary": "deleteDomain",
2135
+ "description": "Removes a custom email domain from the organization.\n\n**Warning**: Deleting a domain will prevent sending emails from any addresses\nusing this domain. Existing email addresses on this domain should be removed\nor reassigned before deleting the domain.\n",
2136
+ "tags": [
2137
+ "Domains"
2138
+ ],
2139
+ "requestBody": {
2140
+ "description": "The domain to delete",
2141
+ "required": true,
2142
+ "content": {
2143
+ "application/json": {
2144
+ "schema": {
2145
+ "$ref": "#/components/schemas/Domain"
2146
+ },
2147
+ "example": {
2148
+ "domain": "mail.yourcompany.com"
2149
+ }
2150
+ }
2151
+ }
2152
+ },
2153
+ "responses": {
2154
+ "204": {
2155
+ "description": "Domain deleted successfully"
2156
+ },
2157
+ "403": {
2158
+ "$ref": "#/components/responses/Forbidden"
2159
+ },
2160
+ "404": {
2161
+ "$ref": "#/components/responses/NotFound"
2162
+ }
2163
+ }
2164
+ },
2165
+ "get": {
2166
+ "operationId": "getDomains",
2167
+ "summary": "getDomains",
2168
+ "description": "Retrieves all custom email domains for the organization.\n",
2169
+ "tags": [
2170
+ "Domains"
2171
+ ],
2172
+ "responses": {
2173
+ "200": {
2174
+ "description": "Successfully retrieved domains.",
2175
+ "content": {
2176
+ "application/json": {
2177
+ "schema": {
2178
+ "type": "array",
2179
+ "items": {
2180
+ "type": "string"
2181
+ }
2182
+ }
2183
+ }
2184
+ }
2185
+ },
2186
+ "403": {
2187
+ "$ref": "#/components/responses/Forbidden"
2188
+ },
2189
+ "404": {
2190
+ "$ref": "#/components/responses/NotFound"
2191
+ }
2192
+ }
2193
+ }
2194
+ },
2195
+ "/v1/email-settings/domain/name-servers:verify": {
2196
+ "post": {
2197
+ "operationId": "verifyNameServers",
2198
+ "summary": "verifyNameServers",
2199
+ "description": "Verifies that the domain's name server (NS) records are correctly configured.\n\nThis check ensures that DNS resolution is properly set up for the domain\nbefore proceeding with full domain verification.\n\nRun this verification after configuring NS records in your DNS provider.\n\n**Deprecated**: Use `/domain/dns-records:verify` for new integrations.\n",
2200
+ "tags": [
2201
+ "Domains"
2202
+ ],
2203
+ "requestBody": {
2204
+ "description": "The domain to verify name servers for",
2205
+ "required": true,
2206
+ "content": {
2207
+ "application/json": {
2208
+ "schema": {
2209
+ "$ref": "#/components/schemas/Domain"
2210
+ },
2211
+ "example": {
2212
+ "domain": "mail.yourcompany.com"
2213
+ }
2214
+ }
2215
+ }
2216
+ },
2217
+ "responses": {
2218
+ "200": {
2219
+ "description": "Name server verification result. Check the response to see if\nverification passed or if additional DNS configuration is needed.\n",
2220
+ "content": {
2221
+ "application/json": {
2222
+ "schema": {
2223
+ "$ref": "#/components/schemas/SettingsResponse"
2224
+ }
2225
+ }
2226
+ }
2227
+ },
2228
+ "403": {
2229
+ "$ref": "#/components/responses/Forbidden"
2230
+ },
2231
+ "404": {
2232
+ "$ref": "#/components/responses/NotFound"
2233
+ }
2234
+ }
2235
+ }
2236
+ },
2237
+ "/v1/email-settings/domain/dns-records:verify": {
2238
+ "post": {
2239
+ "operationId": "verifyDnsRecords",
2240
+ "summary": "verifyDnsRecords",
2241
+ "description": "Verifies that the domain's DNS records (MX, TXT, CNAME) are correctly configured\nin the customer's DNS provider.\n\nThis check performs DNS lookups to confirm each required record is present\nbefore proceeding with full domain identity verification.\n\nRun this verification after configuring all DNS records in your DNS provider.\n",
2242
+ "tags": [
2243
+ "Domains"
2244
+ ],
2245
+ "requestBody": {
2246
+ "description": "The domain to verify DNS records for",
2247
+ "required": true,
2248
+ "content": {
2249
+ "application/json": {
2250
+ "schema": {
2251
+ "$ref": "#/components/schemas/Domain"
2252
+ },
2253
+ "example": {
2254
+ "domain": "mail.yourcompany.com"
2255
+ }
2256
+ }
2257
+ }
2258
+ },
2259
+ "responses": {
2260
+ "200": {
2261
+ "description": "DNS record verification result. Check the response to see if all records\nare verified or if additional DNS configuration is needed.\n",
2262
+ "content": {
2263
+ "application/json": {
2264
+ "schema": {
2265
+ "$ref": "#/components/schemas/SettingsResponse"
2266
+ }
2267
+ }
2268
+ }
2269
+ },
2270
+ "403": {
2271
+ "$ref": "#/components/responses/Forbidden"
2272
+ },
2273
+ "404": {
2274
+ "$ref": "#/components/responses/NotFound"
2275
+ }
2276
+ }
2277
+ }
2278
+ },
2279
+ "/v1/email-settings/domain:verify": {
2280
+ "post": {
2281
+ "operationId": "verifyDomain",
2282
+ "summary": "verifyDomain",
2283
+ "description": "Verifies ownership and configuration of a custom email domain.\n\nDomain verification checks:\n- DNS TXT records for domain ownership\n- MX records for email routing\n- SPF records for sender authentication\n- DKIM records for email signing\n\nOnce verified, the domain can be used to create email addresses and send emails.\n",
2284
+ "tags": [
2285
+ "Domains"
2286
+ ],
2287
+ "requestBody": {
2288
+ "description": "The domain to verify",
2289
+ "required": true,
2290
+ "content": {
2291
+ "application/json": {
2292
+ "schema": {
2293
+ "$ref": "#/components/schemas/Domain"
2294
+ },
2295
+ "example": {
2296
+ "domain": "mail.yourcompany.com"
2297
+ }
2298
+ }
2299
+ }
2300
+ },
2301
+ "responses": {
2302
+ "200": {
2303
+ "description": "Domain verification result. The response indicates whether verification\npassed and which DNS records (if any) still need configuration.\n",
2304
+ "content": {
2305
+ "application/json": {
2306
+ "schema": {
2307
+ "$ref": "#/components/schemas/SettingsResponse"
2308
+ }
2309
+ }
2310
+ }
2311
+ },
2312
+ "403": {
2313
+ "$ref": "#/components/responses/Forbidden"
2314
+ },
2315
+ "404": {
2316
+ "$ref": "#/components/responses/NotFound"
2317
+ }
2318
+ }
2319
+ }
2320
+ }
2321
+ },
2322
+ "components": {
2323
+ "responses": {
2324
+ "ListInboxBucketsSuccessResponse": {
2325
+ "description": "Success",
2326
+ "content": {
2327
+ "application/json": {
2328
+ "schema": {
2329
+ "type": "array",
2330
+ "items": {
2331
+ "$ref": "#/components/schemas/InboxBucketResponse"
2332
+ }
2333
+ }
2334
+ }
2335
+ }
2336
+ },
2337
+ "ProvisionEpilotEmailAddressSuccessResponse": {
2338
+ "description": "Success",
2339
+ "content": {
2340
+ "application/json": {
2341
+ "schema": {
2342
+ "$ref": "#/components/schemas/EmailAddressResponse"
2343
+ }
2344
+ }
2345
+ }
2346
+ },
2347
+ "SetEmailAddressPrimarySuccessResponse": {
2348
+ "description": "Success",
2349
+ "content": {
2350
+ "application/json": {
2351
+ "schema": {
2352
+ "$ref": "#/components/schemas/EmailAddressResponse"
2353
+ }
2354
+ }
2355
+ }
2356
+ },
2357
+ "CreateEmailAddressSuccessResponse": {
2358
+ "description": "Success",
2359
+ "content": {
2360
+ "application/json": {
2361
+ "schema": {
2362
+ "$ref": "#/components/schemas/EmailAddressResponse"
2363
+ }
2364
+ }
2365
+ }
2366
+ },
2367
+ "UpdateEmailAddressSuccessResponse": {
2368
+ "description": "Success",
2369
+ "content": {
2370
+ "application/json": {
2371
+ "schema": {
2372
+ "$ref": "#/components/schemas/EmailAddressResponse"
2373
+ }
2374
+ }
2375
+ }
2376
+ },
2377
+ "GetEmailAddressSuccessResponse": {
2378
+ "description": "Success",
2379
+ "content": {
2380
+ "application/json": {
2381
+ "schema": {
2382
+ "$ref": "#/components/schemas/EmailAddressResponse"
2383
+ }
2384
+ }
2385
+ }
2386
+ },
2387
+ "ListEmailAddressesSuccessResponse": {
2388
+ "description": "Success",
2389
+ "content": {
2390
+ "application/json": {
2391
+ "schema": {
2392
+ "type": "array",
2393
+ "items": {
2394
+ "$ref": "#/components/schemas/EmailAddressResponse"
2395
+ }
2396
+ }
2397
+ }
2398
+ }
2399
+ },
2400
+ "NoContent": {
2401
+ "description": "Success"
2402
+ },
2403
+ "CreateSharedInboxSuccessResponse": {
2404
+ "description": "Success",
2405
+ "content": {
2406
+ "application/json": {
2407
+ "schema": {
2408
+ "$ref": "#/components/schemas/SharedInboxResponse"
2409
+ }
2410
+ }
2411
+ }
2412
+ },
2413
+ "UpdateSharedInboxSuccessResponse": {
2414
+ "description": "Success",
2415
+ "content": {
2416
+ "application/json": {
2417
+ "schema": {
2418
+ "$ref": "#/components/schemas/SharedInboxResponse"
2419
+ }
2420
+ }
2421
+ }
2422
+ },
2423
+ "GetSharedInboxSuccessResponse": {
2424
+ "description": "Success",
2425
+ "content": {
2426
+ "application/json": {
2427
+ "schema": {
2428
+ "$ref": "#/components/schemas/SharedInboxResponse"
2429
+ }
2430
+ }
2431
+ }
2432
+ },
2433
+ "ListSharedInboxesSuccessResponse": {
2434
+ "description": "Success",
2435
+ "content": {
2436
+ "application/json": {
2437
+ "schema": {
2438
+ "type": "array",
2439
+ "items": {
2440
+ "$ref": "#/components/schemas/SharedInboxResponse"
2441
+ }
2442
+ }
2443
+ }
2444
+ }
2445
+ },
2446
+ "BadRequest": {
2447
+ "description": "The request was malformed or contains invalid data.\nCheck the error message for details on which fields are invalid.\n",
2448
+ "content": {
2449
+ "application/json": {
2450
+ "schema": {
2451
+ "$ref": "#/components/schemas/ErrorResponse"
2452
+ },
2453
+ "example": {
2454
+ "error": "Invalid email address format",
2455
+ "status": 400
2456
+ }
2457
+ }
2458
+ }
2459
+ },
2460
+ "Forbidden": {
2461
+ "description": "Access denied. The authenticated user does not have permission to perform\nthis operation. This may occur if:\n- The user lacks the required role or permissions\n- The resource belongs to a different organization\n",
2462
+ "content": {
2463
+ "application/json": {
2464
+ "schema": {
2465
+ "$ref": "#/components/schemas/ErrorResponse"
2466
+ },
2467
+ "example": {
2468
+ "error": "Insufficient permissions to access this resource",
2469
+ "status": 403
2470
+ }
2471
+ }
2472
+ }
2473
+ },
2474
+ "NotFound": {
2475
+ "description": "The requested resource was not found. Verify that:\n- The resource ID is correct\n- The resource exists in your organization\n- The resource has not been deleted\n",
2476
+ "content": {
2477
+ "application/json": {
2478
+ "schema": {
2479
+ "$ref": "#/components/schemas/ErrorResponse"
2480
+ },
2481
+ "example": {
2482
+ "error": "Email address not found",
2483
+ "status": 404
2484
+ }
2485
+ }
2486
+ }
2487
+ },
2488
+ "Conflict": {
2489
+ "description": "The request conflicts with the current state of the resource.\nCommon causes include:\n- Attempting to create a resource that already exists\n- Concurrent modification conflicts\n- Business rule violations (e.g., duplicate email address)\n",
2490
+ "content": {
2491
+ "application/json": {
2492
+ "schema": {
2493
+ "$ref": "#/components/schemas/ErrorResponse"
2494
+ },
2495
+ "example": {
2496
+ "error": "Email address already exists in another configuration",
2497
+ "status": 409
2498
+ }
2499
+ }
2500
+ }
2501
+ },
2502
+ "InternalServerError": {
2503
+ "description": "An unexpected error occurred on the server. If this error persists,\nplease contact support with the request details and timestamp.\n",
2504
+ "content": {
2505
+ "application/json": {
2506
+ "schema": {
2507
+ "$ref": "#/components/schemas/ErrorResponse"
2508
+ },
2509
+ "example": {
2510
+ "error": "An unexpected error occurred",
2511
+ "status": 500
2512
+ }
2513
+ }
2514
+ }
2515
+ },
2516
+ "OutlookErrorResponse": {
2517
+ "description": "An error response from the Outlook OAuth flow.\nMay include an admin consent URL if admin permissions are required.\n",
2518
+ "content": {
2519
+ "application/json": {
2520
+ "schema": {
2521
+ "$ref": "#/components/schemas/OutlookConnectionError"
2522
+ },
2523
+ "example": {
2524
+ "error": "access_denied",
2525
+ "error_description": "Access denied",
2526
+ "admin_consent_url": "https://login.microsoftonline.com/common/adminconsent?client_id=..."
2527
+ }
2528
+ }
2529
+ }
2530
+ }
2531
+ },
2532
+ "parameters": {
2533
+ "EmailAddressId": {
2534
+ "name": "id",
2535
+ "description": "Unique identifier of the email address. This can be either the UUID assigned\nwhen the email address was created, or the email address string itself.\n",
2536
+ "in": "path",
2537
+ "required": true,
2538
+ "schema": {
2539
+ "type": "string"
2540
+ },
2541
+ "examples": {
2542
+ "uuid": {
2543
+ "summary": "UUID identifier",
2544
+ "value": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2545
+ },
2546
+ "email": {
2547
+ "summary": "Email address string",
2548
+ "value": "sales@yourcompany.com"
2549
+ }
2550
+ }
2551
+ },
2552
+ "SharedInboxId": {
2553
+ "name": "id",
2554
+ "description": "Unique identifier (UUID) of the shared inbox.\nUse `default` to reference the organization's default inbox.\n",
2555
+ "in": "path",
2556
+ "required": true,
2557
+ "schema": {
2558
+ "type": "string"
2559
+ },
2560
+ "examples": {
2561
+ "uuid": {
2562
+ "summary": "UUID identifier",
2563
+ "value": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2564
+ },
2565
+ "default": {
2566
+ "summary": "Default inbox",
2567
+ "value": "default"
2568
+ }
2569
+ }
2570
+ }
2571
+ },
2572
+ "securitySchemes": {
2573
+ "EpilotAuth": {
2574
+ "type": "http",
2575
+ "scheme": "bearer",
2576
+ "description": "Primary authentication using epilot OAuth2 bearer token.\nInclude the JWT token in the Authorization header: `Authorization: Bearer <token>`\n",
2577
+ "bearerFormat": "JWT"
2578
+ },
2579
+ "AsOrganization": {
2580
+ "type": "apiKey",
2581
+ "in": "header",
2582
+ "name": "x-ivy-org-id",
2583
+ "description": "**Internal use only.** Sets the organization context when using internal service-to-service\nauthentication. Not intended for external API consumers.\n"
2584
+ },
2585
+ "EpilotOrg": {
2586
+ "type": "apiKey",
2587
+ "name": "x-epilot-org-id",
2588
+ "in": "header",
2589
+ "description": "Overrides the target organization for shared tenant access.\nUse this header when you have access to multiple organizations and need to\nspecify which organization's data to access.\n"
2590
+ }
2591
+ },
2592
+ "schemas": {
2593
+ "ConnectOutlookRequest": {
2594
+ "type": "object",
2595
+ "description": "Feature flags selecting which Microsoft Graph scopes to request.\nAt least one flag must be true. Passing a superset of previously\ngranted features triggers incremental consent for the delta only.\n",
2596
+ "additionalProperties": false,
2597
+ "minProperties": 1,
2598
+ "properties": {
2599
+ "mail": {
2600
+ "type": "boolean",
2601
+ "description": "Request 'mail' specific scopes."
2602
+ },
2603
+ "calendar": {
2604
+ "type": "boolean",
2605
+ "description": "Request 'calendar' specific scopes."
2606
+ },
2607
+ "return_to": {
2608
+ "type": "string",
2609
+ "maxLength": 512,
2610
+ "pattern": "^/[^/\\\\].*$",
2611
+ "description": "Optional same-origin frontend path to redirect to after the OAuth\nround-trip. Must start with a single \"/\" — protocol-relative\nand absolute URLs are rejected.\n"
2612
+ }
2613
+ }
2614
+ },
2615
+ "MailboxSyncStatus": {
2616
+ "type": "object",
2617
+ "required": [
2618
+ "execution_id",
2619
+ "status",
2620
+ "timeframe",
2621
+ "started_at"
2622
+ ],
2623
+ "properties": {
2624
+ "execution_id": {
2625
+ "type": "string"
2626
+ },
2627
+ "status": {
2628
+ "$ref": "#/components/schemas/MailboxSyncStatuses"
2629
+ },
2630
+ "timeframe": {
2631
+ "$ref": "#/components/schemas/MailboxSyncTimeframePeriods"
2632
+ },
2633
+ "started_at": {
2634
+ "type": "string",
2635
+ "format": "date-time"
2636
+ },
2637
+ "completed_at": {
2638
+ "type": "string",
2639
+ "format": "date-time"
2640
+ },
2641
+ "inbox": {
2642
+ "type": "object",
2643
+ "properties": {
2644
+ "status": {
2645
+ "$ref": "#/components/schemas/MailboxSyncFolderStatuses"
2646
+ },
2647
+ "total_messages": {
2648
+ "type": "integer"
2649
+ },
2650
+ "processed_messages": {
2651
+ "type": "integer"
2652
+ },
2653
+ "failed_messages": {
2654
+ "type": "integer"
2655
+ }
2656
+ }
2657
+ },
2658
+ "sent_items": {
2659
+ "type": "object",
2660
+ "properties": {
2661
+ "status": {
2662
+ "$ref": "#/components/schemas/MailboxSyncFolderStatuses"
2663
+ },
2664
+ "total_messages": {
2665
+ "type": "integer"
2666
+ },
2667
+ "processed_messages": {
2668
+ "type": "integer"
2669
+ },
2670
+ "failed_messages": {
2671
+ "type": "integer"
2672
+ }
2673
+ }
2674
+ }
2675
+ }
2676
+ },
2677
+ "MailboxSyncStatuses": {
2678
+ "type": "string",
2679
+ "enum": [
2680
+ "RUNNING",
2681
+ "COMPLETED",
2682
+ "COMPLETED_WITH_ERRORS",
2683
+ "FAILED",
2684
+ "CANCELLED"
2685
+ ]
2686
+ },
2687
+ "MailboxSyncFolderStatuses": {
2688
+ "type": "string",
2689
+ "enum": [
2690
+ "PENDING",
2691
+ "RUNNING",
2692
+ "COMPLETED",
2693
+ "FAILED",
2694
+ "SKIPPED"
2695
+ ]
2696
+ },
2697
+ "MailboxSyncTimeframePeriods": {
2698
+ "type": "string",
2699
+ "enum": [
2700
+ "5m",
2701
+ "1w",
2702
+ "2w",
2703
+ "1m"
2704
+ ]
2705
+ },
2706
+ "InboxBucketResponse": {
2707
+ "type": "object",
2708
+ "description": "Inbox bucket representing the storage container for a shared inbox.",
2709
+ "required": [
2710
+ "id",
2711
+ "inbox_id"
2712
+ ],
2713
+ "properties": {
2714
+ "id": {
2715
+ "type": "string",
2716
+ "description": "Unique identifier of the bucket",
2717
+ "example": "bucket-abc"
2718
+ },
2719
+ "inbox_id": {
2720
+ "type": "string",
2721
+ "description": "ID of the shared inbox associated with this bucket",
2722
+ "example": "inbox-xyz"
2723
+ }
2724
+ }
2725
+ },
2726
+ "ProvisionEpilotEmailAddressPayload": {
2727
+ "type": "object",
2728
+ "description": "Request payload for provisioning an epilot-managed email address.",
2729
+ "required": [
2730
+ "address"
2731
+ ],
2732
+ "properties": {
2733
+ "address": {
2734
+ "type": "string",
2735
+ "description": "The epilot email address to provision (must be on @epilot.cloud domain)",
2736
+ "example": "mycompany@epilot.cloud"
2737
+ }
2738
+ }
2739
+ },
2740
+ "SetEmailAddressPrimaryPayload": {
2741
+ "type": "object",
2742
+ "description": "Request payload for setting an email address as the organization's primary address.",
2743
+ "required": [
2744
+ "address"
2745
+ ],
2746
+ "properties": {
2747
+ "address": {
2748
+ "type": "string",
2749
+ "description": "The email address to set as primary",
2750
+ "example": "sales@yourcompany.com"
2751
+ }
2752
+ }
2753
+ },
2754
+ "UpdateEmailAddressPayload": {
2755
+ "type": "object",
2756
+ "description": "Request payload for updating an email address configuration.\nAll fields are optional; only provided fields will be updated.\n",
2757
+ "properties": {
2758
+ "name": {
2759
+ "type": "string",
2760
+ "description": "Display name shown as the sender name in emails",
2761
+ "example": "Sales Team"
2762
+ },
2763
+ "user_ids": {
2764
+ "type": "array",
2765
+ "description": "List of user IDs who can send from this address",
2766
+ "items": {
2767
+ "type": "string"
2768
+ },
2769
+ "example": [
2770
+ "user-123",
2771
+ "user-456"
2772
+ ]
2773
+ },
2774
+ "group_ids": {
2775
+ "type": "array",
2776
+ "description": "List of group IDs whose members can send from this address",
2777
+ "items": {
2778
+ "type": "string"
2779
+ },
2780
+ "example": [
2781
+ "group-789"
2782
+ ]
2783
+ },
2784
+ "default_signature_id": {
2785
+ "type": "string",
2786
+ "description": "ID of the signature to use by default when sending from this address",
2787
+ "example": "sig-abc"
2788
+ },
2789
+ "shared_inbox_id": {
2790
+ "type": "string",
2791
+ "description": "ID of the shared inbox to associate with this address",
2792
+ "example": "inbox-xyz"
2793
+ },
2794
+ "is_active": {
2795
+ "type": "boolean",
2796
+ "description": "Whether the email address is active and can be used for sending",
2797
+ "example": true
2798
+ }
2799
+ }
2800
+ },
2801
+ "CreateEmailAddressPayload": {
2802
+ "type": "object",
2803
+ "description": "Request payload for creating a new email address.",
2804
+ "required": [
2805
+ "address"
2806
+ ],
2807
+ "properties": {
2808
+ "address": {
2809
+ "type": "string",
2810
+ "description": "The email address to add (e.g., from a custom domain or external provider)",
2811
+ "example": "support@yourcompany.com"
2812
+ },
2813
+ "name": {
2814
+ "type": "string",
2815
+ "description": "Display name shown as the sender name in emails",
2816
+ "example": "Customer Support"
2817
+ },
2818
+ "user_ids": {
2819
+ "type": "array",
2820
+ "description": "List of user IDs who can send from this address",
2821
+ "items": {
2822
+ "type": "string"
2823
+ },
2824
+ "example": [
2825
+ "user-123"
2826
+ ]
2827
+ },
2828
+ "group_ids": {
2829
+ "type": "array",
2830
+ "description": "List of group IDs whose members can send from this address",
2831
+ "items": {
2832
+ "type": "string"
2833
+ },
2834
+ "example": [
2835
+ "group-456"
2836
+ ]
2837
+ },
2838
+ "default_signature_id": {
2839
+ "type": "string",
2840
+ "description": "ID of the signature to use by default when sending from this address",
2841
+ "example": "sig-789"
2842
+ },
2843
+ "shared_inbox_id": {
2844
+ "type": "string",
2845
+ "description": "ID of the shared inbox to associate with this address",
2846
+ "example": "inbox-abc"
2847
+ }
2848
+ }
2849
+ },
2850
+ "EmailAddressResponse": {
2851
+ "description": "Email address configuration with all associated metadata.",
2852
+ "allOf": [
2853
+ {
2854
+ "$ref": "#/components/schemas/SettingMeta"
2855
+ },
2856
+ {
2857
+ "type": "object",
2858
+ "required": [
2859
+ "address"
2860
+ ],
2861
+ "properties": {
2862
+ "address": {
2863
+ "type": "string",
2864
+ "description": "The email address string",
2865
+ "example": "sales@yourcompany.com"
2866
+ },
2867
+ "name": {
2868
+ "type": "string",
2869
+ "description": "Display name shown as the sender name",
2870
+ "example": "Sales Team"
2871
+ },
2872
+ "user_ids": {
2873
+ "type": "array",
2874
+ "description": "IDs of users who can send from this address",
2875
+ "items": {
2876
+ "type": "string"
2877
+ },
2878
+ "example": [
2879
+ "user-123",
2880
+ "user-456"
2881
+ ]
2882
+ },
2883
+ "group_ids": {
2884
+ "type": "array",
2885
+ "description": "IDs of groups whose members can send from this address",
2886
+ "items": {
2887
+ "type": "string"
2888
+ },
2889
+ "example": [
2890
+ "group-789"
2891
+ ]
2892
+ },
2893
+ "default_signature_id": {
2894
+ "type": "string",
2895
+ "description": "ID of the default signature for this address",
2896
+ "example": "sig-abc"
2897
+ },
2898
+ "shared_inbox_id": {
2899
+ "type": "string",
2900
+ "description": "ID of the associated shared inbox",
2901
+ "example": "inbox-xyz"
2902
+ },
2903
+ "is_active": {
2904
+ "type": "boolean",
2905
+ "description": "Whether the address is currently active for sending",
2906
+ "example": true
2907
+ },
2908
+ "is_primary": {
2909
+ "type": "boolean",
2910
+ "description": "Whether this is the organization's primary email address",
2911
+ "example": false
2912
+ },
2913
+ "is_epilot_email_address": {
2914
+ "type": "boolean",
2915
+ "description": "Whether this is an epilot-managed address (@epilot.cloud)",
2916
+ "example": false
2917
+ }
2918
+ }
2919
+ }
2920
+ ]
2921
+ },
2922
+ "ErrorResponse": {
2923
+ "type": "object",
2924
+ "description": "Standard error response format for all API errors.",
2925
+ "required": [
2926
+ "error",
2927
+ "status"
2928
+ ],
2929
+ "properties": {
2930
+ "error": {
2931
+ "type": "string",
2932
+ "description": "Human-readable error message describing what went wrong",
2933
+ "example": "Resource not found"
2934
+ },
2935
+ "status": {
2936
+ "type": "integer",
2937
+ "description": "HTTP status code of the error",
2938
+ "example": 404
2939
+ }
2940
+ }
2941
+ },
2942
+ "SettingMeta": {
2943
+ "type": "object",
2944
+ "description": "Common metadata fields for all settings and resources.",
2945
+ "required": [
2946
+ "id",
2947
+ "created_at"
2948
+ ],
2949
+ "properties": {
2950
+ "id": {
2951
+ "type": "string",
2952
+ "description": "Unique identifier (UUID) for the resource",
2953
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
2954
+ },
2955
+ "created_at": {
2956
+ "type": "string",
2957
+ "format": "date-time",
2958
+ "description": "Timestamp when the resource was created",
2959
+ "example": "2024-01-15T10:30:00Z"
2960
+ },
2961
+ "updated_at": {
2962
+ "type": "string",
2963
+ "format": "date-time",
2964
+ "description": "Timestamp when the resource was last updated",
2965
+ "example": "2024-01-20T14:45:00Z"
2966
+ },
2967
+ "created_by": {
2968
+ "type": "string",
2969
+ "description": "User ID of the user who created the resource",
2970
+ "example": "user-123"
2971
+ },
2972
+ "updated_by": {
2973
+ "type": "string",
2974
+ "description": "User ID of the user who last updated the resource",
2975
+ "example": "user-456"
2976
+ }
2977
+ }
2978
+ },
2979
+ "UpdateSharedInboxPayload": {
2980
+ "type": "object",
2981
+ "description": "Request payload for updating a shared inbox configuration.\nAll fields are optional; only provided fields will be updated.\n",
2982
+ "properties": {
2983
+ "color": {
2984
+ "type": "string",
2985
+ "description": "Hex color code for visual identification in the UI",
2986
+ "example": "#4CAF50"
2987
+ },
2988
+ "name": {
2989
+ "type": "string",
2990
+ "description": "Display name of the shared inbox",
2991
+ "example": "Customer Support"
2992
+ },
2993
+ "assignees": {
2994
+ "type": "array",
2995
+ "description": "List of user IDs assigned to this inbox",
2996
+ "items": {
2997
+ "type": "string"
2998
+ },
2999
+ "example": [
3000
+ "user-123",
3001
+ "user-456"
3002
+ ]
3003
+ },
3004
+ "description": {
3005
+ "type": "string",
3006
+ "description": "Optional description of the inbox purpose",
3007
+ "example": "Incoming customer support requests"
3008
+ }
3009
+ }
3010
+ },
3011
+ "CreateSharedInboxPayload": {
3012
+ "type": "object",
3013
+ "description": "Request payload for creating a new shared inbox.",
3014
+ "required": [
3015
+ "name",
3016
+ "color"
3017
+ ],
3018
+ "properties": {
3019
+ "id": {
3020
+ "type": "string",
3021
+ "description": "Optional custom ID for the inbox (auto-generated if not provided)",
3022
+ "example": "support-inbox"
3023
+ },
3024
+ "color": {
3025
+ "type": "string",
3026
+ "description": "Hex color code for visual identification in the UI (required)",
3027
+ "example": "#2196F3"
3028
+ },
3029
+ "name": {
3030
+ "type": "string",
3031
+ "description": "Display name of the shared inbox (required)",
3032
+ "example": "Sales Inquiries"
3033
+ },
3034
+ "assignees": {
3035
+ "type": "array",
3036
+ "description": "List of user IDs to assign to this inbox",
3037
+ "default": [],
3038
+ "items": {
3039
+ "type": "string"
3040
+ },
3041
+ "example": [
3042
+ "user-123",
3043
+ "user-456"
3044
+ ]
3045
+ },
3046
+ "description": {
3047
+ "type": "string",
3048
+ "description": "Optional description of the inbox purpose",
3049
+ "example": "Inbound sales and pricing requests"
3050
+ }
3051
+ }
3052
+ },
3053
+ "SharedInboxResponse": {
3054
+ "description": "Shared inbox configuration with all associated metadata.",
3055
+ "allOf": [
3056
+ {
3057
+ "$ref": "#/components/schemas/SettingMeta"
3058
+ },
3059
+ {
3060
+ "type": "object",
3061
+ "required": [
3062
+ "id",
3063
+ "name",
3064
+ "color",
3065
+ "assignees",
3066
+ "bucket_id"
3067
+ ],
3068
+ "properties": {
3069
+ "id": {
3070
+ "type": "string",
3071
+ "description": "Unique identifier of the shared inbox",
3072
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
3073
+ },
3074
+ "name": {
3075
+ "type": "string",
3076
+ "description": "Display name of the shared inbox",
3077
+ "example": "Customer Support"
3078
+ },
3079
+ "color": {
3080
+ "type": "string",
3081
+ "description": "Hex color code for visual identification",
3082
+ "example": "#4CAF50"
3083
+ },
3084
+ "assignees": {
3085
+ "type": "array",
3086
+ "description": "List of user IDs assigned to this inbox",
3087
+ "default": [],
3088
+ "items": {
3089
+ "type": "string"
3090
+ },
3091
+ "example": [
3092
+ "user-123",
3093
+ "user-456"
3094
+ ]
3095
+ },
3096
+ "description": {
3097
+ "type": "string",
3098
+ "description": "Description of the inbox purpose",
3099
+ "example": "Incoming customer support requests"
3100
+ },
3101
+ "bucket_id": {
3102
+ "type": "string",
3103
+ "description": "ID of the associated storage bucket for messages",
3104
+ "example": "bucket-xyz"
3105
+ }
3106
+ }
3107
+ }
3108
+ ]
3109
+ },
3110
+ "SettingsResponse": {
3111
+ "oneOf": [
3112
+ {
3113
+ "type": "array",
3114
+ "items": {
3115
+ "$ref": "#/components/schemas/Setting"
3116
+ }
3117
+ },
3118
+ {
3119
+ "$ref": "#/components/schemas/Setting"
3120
+ }
3121
+ ]
3122
+ },
3123
+ "ConnectedOutlookEmail": {
3124
+ "type": "object",
3125
+ "description": "Mapping between an Outlook email and its Outlook Connection.\nThis tracks which provider/tenant provisions each Outlook email.\n",
3126
+ "required": [
3127
+ "outlook_email"
3128
+ ],
3129
+ "properties": {
3130
+ "outlook_email": {
3131
+ "type": "string",
3132
+ "format": "email",
3133
+ "description": "The Outlook shared mailbox email address"
3134
+ },
3135
+ "tenant_id": {
3136
+ "type": "string",
3137
+ "description": "Azure AD Tenant ID that provisions this mailbox"
3138
+ },
3139
+ "provider": {
3140
+ "type": "string",
3141
+ "enum": [
3142
+ "outlook"
3143
+ ],
3144
+ "description": "Provider type (for future extensibility)"
3145
+ },
3146
+ "connected_at": {
3147
+ "type": "string",
3148
+ "format": "date-time",
3149
+ "description": "When the mailbox was connected"
3150
+ },
3151
+ "connected_by_user_id": {
3152
+ "type": "string",
3153
+ "description": "User who connected this mailbox"
3154
+ }
3155
+ }
3156
+ },
3157
+ "OutlookConnectionError": {
3158
+ "type": "object",
3159
+ "required": [
3160
+ "error"
3161
+ ],
3162
+ "properties": {
3163
+ "error": {
3164
+ "type": "string",
3165
+ "description": "Error code or message from the OAuth flow."
3166
+ },
3167
+ "error_description": {
3168
+ "type": "string",
3169
+ "description": "Human-readable description of the error."
3170
+ },
3171
+ "admin_consent_url": {
3172
+ "type": "string",
3173
+ "format": "uri",
3174
+ "description": "URL for tenant admin to grant consent, if applicable."
3175
+ }
3176
+ }
3177
+ },
3178
+ "CalendarAdminConsentStatus": {
3179
+ "type": "object",
3180
+ "required": [
3181
+ "admin_consented"
3182
+ ],
3183
+ "properties": {
3184
+ "admin_consented": {
3185
+ "type": "boolean",
3186
+ "description": "True when the tenant admin has consented to epilot's Microsoft 365\napp, so users in this organization can connect personal calendars.\n"
3187
+ },
3188
+ "admin_consent_url": {
3189
+ "type": "string",
3190
+ "format": "uri",
3191
+ "description": "Microsoft admin-consent URL for an administrator to open. Present\nonly when `admin_consented` is false.\n"
3192
+ }
3193
+ }
3194
+ },
3195
+ "MyCalendarConnectionResponse": {
3196
+ "type": "object",
3197
+ "description": "Per-user calendar connection metadata, or null when the caller has\nnot connected their personal calendar yet.\n",
3198
+ "properties": {
3199
+ "connection": {
3200
+ "allOf": [
3201
+ {
3202
+ "$ref": "#/components/schemas/CalendarConnectionInfo"
3203
+ }
3204
+ ],
3205
+ "nullable": true
3206
+ }
3207
+ }
3208
+ },
3209
+ "CalendarConnectionInfo": {
3210
+ "type": "object",
3211
+ "required": [
3212
+ "user_id",
3213
+ "tenant_id",
3214
+ "status"
3215
+ ],
3216
+ "properties": {
3217
+ "user_id": {
3218
+ "type": "string",
3219
+ "description": "Azure AD Object ID of the connected user"
3220
+ },
3221
+ "tenant_id": {
3222
+ "type": "string",
3223
+ "description": "Microsoft Azure AD tenant ID"
3224
+ },
3225
+ "status": {
3226
+ "type": "string",
3227
+ "enum": [
3228
+ "connected",
3229
+ "expired"
3230
+ ],
3231
+ "description": "Token health for this calendar connection"
3232
+ },
3233
+ "scopes": {
3234
+ "type": "array",
3235
+ "items": {
3236
+ "type": "string"
3237
+ },
3238
+ "description": "Granted permission scopes on the user's token"
3239
+ },
3240
+ "connected_by_display_name": {
3241
+ "type": "string"
3242
+ },
3243
+ "connected_by_email": {
3244
+ "type": "string",
3245
+ "format": "email"
3246
+ },
3247
+ "connected_at": {
3248
+ "type": "string",
3249
+ "format": "date-time"
3250
+ },
3251
+ "updated_at": {
3252
+ "type": "string",
3253
+ "format": "date-time"
3254
+ },
3255
+ "expires_at": {
3256
+ "type": "string",
3257
+ "format": "date-time"
3258
+ }
3259
+ }
3260
+ },
3261
+ "OutlookConnectionStatus": {
3262
+ "type": "object",
3263
+ "required": [
3264
+ "status",
3265
+ "action",
3266
+ "action_label",
3267
+ "tenant_id"
3268
+ ],
3269
+ "properties": {
3270
+ "status": {
3271
+ "type": "string",
3272
+ "enum": [
3273
+ "connected",
3274
+ "expired",
3275
+ "pending_auth",
3276
+ "not_connected"
3277
+ ],
3278
+ "description": "Current connection status:\n- pending_auth: Admin consent granted, waiting for user OAuth\n- connected: Fully connected with valid tokens\n- expired: Tokens expired, need to re-authenticate\n- not_connected: No connection, initiate OAuth\n"
3279
+ },
3280
+ "action": {
3281
+ "type": "string",
3282
+ "enum": [
3283
+ "connect",
3284
+ "authorize",
3285
+ "reconnect",
3286
+ "none"
3287
+ ],
3288
+ "description": "Action for UI to take (all call POST /outlook/connect):\n- connect: No connection, initiate OAuth\n- authorize: Admin consent done, complete OAuth\n- reconnect: Re-authenticate expired session or approve updated permissions\n- none: Fully connected, no action needed\n"
3289
+ },
3290
+ "action_reason": {
3291
+ "type": "string",
3292
+ "enum": [
3293
+ "expired",
3294
+ "permission_update"
3295
+ ],
3296
+ "description": "Discriminates the cause when `action` is `reconnect`:\n- expired: Stored tokens are no longer valid; user must re-authenticate\n- permission_update: Token is valid, but the granted scopes do not cover the\n scopes required by the configured Outlook integrations (currently `mail`).\n The user must reconnect to grant the additional permissions; Microsoft's\n incremental-consent flow will only prompt for the delta.\n"
3297
+ },
3298
+ "connected_by_display_name": {
3299
+ "type": "string",
3300
+ "description": "Display name of user who connected"
3301
+ },
3302
+ "connected_by_email": {
3303
+ "type": "string",
3304
+ "format": "email",
3305
+ "description": "Email of the user who connected"
3306
+ },
3307
+ "connected_by_user_id": {
3308
+ "type": "string",
3309
+ "description": "Azure AD Object ID of user who connected"
3310
+ },
3311
+ "connected_at": {
3312
+ "type": "string",
3313
+ "format": "date-time",
3314
+ "description": "When the connection was established"
3315
+ },
3316
+ "updated_at": {
3317
+ "type": "string",
3318
+ "format": "date-time",
3319
+ "description": "When the connection was last updated"
3320
+ },
3321
+ "tenant_id": {
3322
+ "type": "string",
3323
+ "description": "Microsoft Azure AD tenant ID"
3324
+ },
3325
+ "scopes": {
3326
+ "type": "array",
3327
+ "items": {
3328
+ "type": "string"
3329
+ },
3330
+ "description": "Granted permission scopes"
3331
+ },
3332
+ "expires_at": {
3333
+ "type": "string",
3334
+ "format": "date-time",
3335
+ "description": "When the current access token expires"
3336
+ },
3337
+ "is_token_valid": {
3338
+ "type": "boolean",
3339
+ "description": "Whether the current token is still valid"
3340
+ }
3341
+ }
3342
+ },
3343
+ "SmtpConnection": {
3344
+ "type": "object",
3345
+ "required": [
3346
+ "connection_id",
3347
+ "smtp_host",
3348
+ "smtp_port",
3349
+ "smtp_secure",
3350
+ "smtp_username"
3351
+ ],
3352
+ "properties": {
3353
+ "connection_id": {
3354
+ "type": "string",
3355
+ "description": "Stable identifier for this SMTP connection"
3356
+ },
3357
+ "smtp_host": {
3358
+ "type": "string",
3359
+ "description": "Hostname of the SMTP server (e.g. smtp.mailgun.org)"
3360
+ },
3361
+ "smtp_port": {
3362
+ "type": "string",
3363
+ "description": "SMTP port (typically 587 for STARTTLS or 465 for TLS). A string, because it\nmay hold a `{{ env.your_key }}` reference rather than a literal port.\n"
3364
+ },
3365
+ "smtp_secure": {
3366
+ "type": "string",
3367
+ "enum": [
3368
+ "tls",
3369
+ "starttls"
3370
+ ],
3371
+ "description": "Connection security mode. Plaintext SMTP is not offered: it would put the\nSMTP password on the wire in the clear.\n- tls: Implicit TLS (port 465)\n- starttls: STARTTLS upgrade (port 587)\n"
3372
+ },
3373
+ "smtp_username": {
3374
+ "type": "string",
3375
+ "description": "SMTP auth username"
3376
+ },
3377
+ "smtp_password": {
3378
+ "type": "string",
3379
+ "description": "Only returned when the stored value is exactly one `{{ env.your_key }}`\nreference, which names a secret rather than being one — that lets the\nsettings UI edit the reference without dropping it. A literal password, or a\npartly templated one, is omitted entirely: submit an update without this\nfield to keep the stored value.\n"
3380
+ },
3381
+ "connected_by_display_name": {
3382
+ "type": "string"
3383
+ },
3384
+ "connected_by_email": {
3385
+ "type": "string",
3386
+ "format": "email"
3387
+ },
3388
+ "connected_by_user_id": {
3389
+ "type": "string"
3390
+ },
3391
+ "connected_at": {
3392
+ "type": "string",
3393
+ "format": "date-time"
3394
+ },
3395
+ "updated_at": {
3396
+ "type": "string",
3397
+ "format": "date-time"
3398
+ },
3399
+ "last_tested_at": {
3400
+ "type": "string",
3401
+ "format": "date-time"
3402
+ },
3403
+ "last_test_status": {
3404
+ "type": "string",
3405
+ "enum": [
3406
+ "ok",
3407
+ "auth_failed",
3408
+ "tls_failed",
3409
+ "host_unreachable",
3410
+ "timeout",
3411
+ "secret_missing",
3412
+ "unknown"
3413
+ ]
3414
+ },
3415
+ "last_test_error": {
3416
+ "type": "string",
3417
+ "description": "Latest test error message, if any"
3418
+ }
3419
+ }
3420
+ },
3421
+ "CreateSmtpConnectionRequest": {
3422
+ "type": "object",
3423
+ "required": [
3424
+ "smtp_host",
3425
+ "smtp_port",
3426
+ "smtp_secure",
3427
+ "smtp_username",
3428
+ "smtp_password"
3429
+ ],
3430
+ "properties": {
3431
+ "smtp_host": {
3432
+ "type": "string"
3433
+ },
3434
+ "smtp_port": {
3435
+ "description": "A port between 1 and 65535, or a `{{ env.your_key }}` template resolving to\none. An integer is still accepted, so callers predating the template support\nkeep working.\n",
3436
+ "oneOf": [
3437
+ {
3438
+ "type": "string"
3439
+ },
3440
+ {
3441
+ "type": "integer",
3442
+ "minimum": 1,
3443
+ "maximum": 65535
3444
+ }
3445
+ ]
3446
+ },
3447
+ "smtp_secure": {
3448
+ "type": "string",
3449
+ "enum": [
3450
+ "tls",
3451
+ "starttls"
3452
+ ]
3453
+ },
3454
+ "smtp_username": {
3455
+ "type": "string"
3456
+ },
3457
+ "smtp_password": {
3458
+ "type": "string",
3459
+ "description": "May contain `{{ env.your_key }}` templates referencing the organization's\nenvironment variables (including secrets), resolved at send time. Stored as\nentered, so the settings UI edits the template rather than a resolved value.\n",
3460
+ "example": "{{ env.smtp_password }}"
3461
+ }
3462
+ }
3463
+ },
3464
+ "UpdateSmtpConnectionRequest": {
3465
+ "type": "object",
3466
+ "description": "Partial update; omitted fields keep their existing values.",
3467
+ "properties": {
3468
+ "smtp_host": {
3469
+ "type": "string"
3470
+ },
3471
+ "smtp_port": {
3472
+ "description": "A port between 1 and 65535, or a `{{ env.your_key }}` template resolving to\none. An integer is still accepted, so callers predating the template support\nkeep working.\n",
3473
+ "oneOf": [
3474
+ {
3475
+ "type": "string"
3476
+ },
3477
+ {
3478
+ "type": "integer",
3479
+ "minimum": 1,
3480
+ "maximum": 65535
3481
+ }
3482
+ ]
3483
+ },
3484
+ "smtp_secure": {
3485
+ "type": "string",
3486
+ "enum": [
3487
+ "tls",
3488
+ "starttls"
3489
+ ]
3490
+ },
3491
+ "smtp_username": {
3492
+ "type": "string"
3493
+ },
3494
+ "smtp_password": {
3495
+ "type": "string"
3496
+ }
3497
+ }
3498
+ },
3499
+ "SmtpSender": {
3500
+ "type": "object",
3501
+ "description": "An address allowed to send through a custom SMTP connection. Mirrors an Outlook\nmailbox: the address, its display name and its assignees live on the shared\nemail-address record, while this row binds it to a set of SMTP credentials.\n",
3502
+ "required": [
3503
+ "email",
3504
+ "connection_id"
3505
+ ],
3506
+ "properties": {
3507
+ "email": {
3508
+ "type": "string",
3509
+ "format": "email",
3510
+ "description": "The sender address. Stored lower-cased."
3511
+ },
3512
+ "connection_id": {
3513
+ "type": "string",
3514
+ "description": "SMTP connection this address sends through"
3515
+ },
3516
+ "reply_to_email": {
3517
+ "type": "string",
3518
+ "description": "Default Reply-To for messages from this address. Custom SMTP is send-only, so\npoint this at a mailbox someone actually monitors. May contain a\n`{{ env.your_key }}` template, so this is not constrained to `format: email`.\nA per-message Reply-To still wins.\n"
3519
+ },
3520
+ "connected_at": {
3521
+ "type": "string",
3522
+ "format": "date-time"
3523
+ },
3524
+ "connected_by_user_id": {
3525
+ "type": "string"
3526
+ }
3527
+ }
3528
+ },
3529
+ "ConnectSmtpSenderRequest": {
3530
+ "type": "object",
3531
+ "required": [
3532
+ "email",
3533
+ "connection_id"
3534
+ ],
3535
+ "properties": {
3536
+ "email": {
3537
+ "type": "string",
3538
+ "format": "email",
3539
+ "description": "Address to send from. Must be one the SMTP server accepts as a From."
3540
+ },
3541
+ "connection_id": {
3542
+ "type": "string",
3543
+ "description": "SMTP connection to send through"
3544
+ },
3545
+ "name": {
3546
+ "type": "string",
3547
+ "description": "Sender name shown on outgoing messages."
3548
+ },
3549
+ "reply_to_email": {
3550
+ "type": "string",
3551
+ "description": "Email address, or a `{{ env.your_key }}` template resolving to one."
3552
+ },
3553
+ "shared_inbox_id": {
3554
+ "type": "string",
3555
+ "description": "Shared inbox to associate with the address. Defaults to the default shared inbox.",
3556
+ "default": "default"
3557
+ },
3558
+ "user_ids": {
3559
+ "type": "array",
3560
+ "items": {
3561
+ "type": "string"
3562
+ },
3563
+ "description": "User IDs for which this address should be available by default."
3564
+ },
3565
+ "group_ids": {
3566
+ "type": "array",
3567
+ "items": {
3568
+ "type": "string"
3569
+ },
3570
+ "description": "Group IDs for which this address should be available by default."
3571
+ },
3572
+ "default_signature_id": {
3573
+ "type": "string",
3574
+ "description": "Default signature ID to use for this address."
3575
+ }
3576
+ }
3577
+ },
3578
+ "SmtpTestResult": {
3579
+ "type": "object",
3580
+ "required": [
3581
+ "status",
3582
+ "tested_at"
3583
+ ],
3584
+ "properties": {
3585
+ "status": {
3586
+ "type": "string",
3587
+ "enum": [
3588
+ "ok",
3589
+ "auth_failed",
3590
+ "tls_failed",
3591
+ "host_unreachable",
3592
+ "timeout",
3593
+ "secret_missing",
3594
+ "unknown"
3595
+ ]
3596
+ },
3597
+ "error": {
3598
+ "type": "string"
3599
+ },
3600
+ "tested_at": {
3601
+ "type": "string",
3602
+ "format": "date-time"
3603
+ }
3604
+ }
3605
+ },
3606
+ "SignatureSetting": {
3607
+ "type": "string",
3608
+ "description": "Setting that allows to add a signature.",
3609
+ "enum": [
3610
+ "signature"
3611
+ ]
3612
+ },
3613
+ "EmailDomainSetting": {
3614
+ "type": "string",
3615
+ "description": "Setting that allows to add a custom domain. For e.g; doe.com",
3616
+ "enum": [
3617
+ "email_domain"
3618
+ ]
3619
+ },
3620
+ "EmailAddressSetting": {
3621
+ "type": "string",
3622
+ "description": "Setting that allows to add an email address on the custom domain. For e.g; john@doe.com",
3623
+ "enum": [
3624
+ "email_address"
3625
+ ]
3626
+ },
3627
+ "WhitelistEmailAddressSetting": {
3628
+ "type": "string",
3629
+ "description": "- Setting that specifies a list of addresses exempt from being flagged as duplicate emails.\n- An email will be flagged as a duplicate if it has the same content and is sent to the same recipient within the time frame specified in the RestrictDuplicatesWithinSetting.\n",
3630
+ "enum": [
3631
+ "whitelist_email_address"
3632
+ ]
3633
+ },
3634
+ "RestrictDuplicatesWithinSetting": {
3635
+ "type": "string",
3636
+ "description": "- Restrict duplicates within:\n * 10s\n * 5m\n * 1d\n * 5000 // It converts to 5 seconds.When expressed as a numerical value, it will be interpreted as being in milliseconds.\n- Defaults to 3 minutes\n- Negative values will be treated same as positive values\n- If not set, defaults to 3 min\n- If set as 0, then the no email will be treated as a duplicate\n- Cannot have multiple values\n",
3637
+ "enum": [
3638
+ "restrict_duplicates_within"
3639
+ ]
3640
+ },
3641
+ "SettingType": {
3642
+ "oneOf": [
3643
+ {
3644
+ "$ref": "#/components/schemas/SignatureSetting"
3645
+ },
3646
+ {
3647
+ "$ref": "#/components/schemas/EmailDomainSetting"
3648
+ },
3649
+ {
3650
+ "$ref": "#/components/schemas/EmailAddressSetting"
3651
+ },
3652
+ {
3653
+ "$ref": "#/components/schemas/WhitelistEmailAddressSetting"
3654
+ },
3655
+ {
3656
+ "$ref": "#/components/schemas/RestrictDuplicatesWithinSetting"
3657
+ }
3658
+ ]
3659
+ },
3660
+ "Setting": {
3661
+ "type": "object",
3662
+ "description": "Generic setting object used for various email configuration types.\nThe applicable fields depend on the setting type:\n- **signature**: Uses `name`, `value` (plain text), and `html` (rich text)\n- **email_domain**: Uses `value` (domain name)\n- **whitelist_email_address**: Uses `value` (email address)\n- **restrict_duplicates_within**: Uses `value` (time duration)\n",
3663
+ "required": [
3664
+ "type"
3665
+ ],
3666
+ "properties": {
3667
+ "id": {
3668
+ "type": "string",
3669
+ "description": "Unique identifier of the setting",
3670
+ "example": "a10bd0ff-4391-4cfc-88ee-b19d718a9bf7"
3671
+ },
3672
+ "name": {
3673
+ "type": "string",
3674
+ "description": "Display name of the setting (used for signatures)",
3675
+ "example": "Default Signature"
3676
+ },
3677
+ "org_id": {
3678
+ "type": "string",
3679
+ "description": "Organization ID that owns this setting",
3680
+ "example": "org-123"
3681
+ },
3682
+ "type": {
3683
+ "$ref": "#/components/schemas/SettingType"
3684
+ },
3685
+ "value": {
3686
+ "type": "string",
3687
+ "description": "The setting value. Interpretation depends on type:\n- signature: Plain text version of the signature\n- email_domain: Domain name (e.g., \"yourcompany.com\")\n- whitelist_email_address: Email address to whitelist\n- restrict_duplicates_within: Time duration (e.g., \"5m\", \"1d\")\n",
3688
+ "example": "Best regards, The Team"
3689
+ },
3690
+ "html": {
3691
+ "type": "string",
3692
+ "description": "HTML content (only applicable for signature type)",
3693
+ "example": "<p>Best regards,<br/><strong>The Team</strong></p>"
3694
+ },
3695
+ "created_at": {
3696
+ "type": "string",
3697
+ "description": "ISO 8601 timestamp when the setting was created",
3698
+ "example": "2024-01-15T10:30:00Z"
3699
+ },
3700
+ "updated_at": {
3701
+ "type": "string",
3702
+ "description": "ISO 8601 timestamp when the setting was last updated",
3703
+ "example": "2024-01-20T14:45:00Z"
3704
+ },
3705
+ "created_by": {
3706
+ "type": "string",
3707
+ "description": "User ID of the creator",
3708
+ "example": "user-123"
3709
+ },
3710
+ "updated_by": {
3711
+ "type": "string",
3712
+ "description": "User ID of the last editor",
3713
+ "example": "user-456"
3714
+ }
3715
+ },
3716
+ "additionalProperties": true
3717
+ },
3718
+ "Domain": {
3719
+ "type": "object",
3720
+ "description": "Custom email domain configuration.",
3721
+ "properties": {
3722
+ "domain": {
3723
+ "type": "string",
3724
+ "description": "The domain name to add or verify. Can be a root domain or subdomain.\nExamples: \"yourcompany.com\", \"mail.yourcompany.com\"\n",
3725
+ "example": "mail.yourcompany.com"
3726
+ }
3727
+ }
3728
+ }
3729
+ }
3730
+ },
3731
+ "servers": [
3732
+ {
3733
+ "url": "https://email-settings.sls.epilot.io"
3734
+ }
3735
+ ]
3736
+ }