@fourier-labs/harbour-contracts 0.84.0 → 0.86.0

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.
@@ -2,7 +2,7 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "$id": "https://schemas.harbour.dev/integration-execute-result.schema.json",
4
4
  "title": "IntegrationExecuteResult",
5
- "description": "The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the operation results (thirty-three operations since 0.78.0, ADR 0018, ADR 0022 and ADR 0024): slack.channel.history -> {messages, hasMore, nextCursor?} (plain text/IDs/time, plus the display name and emoji icon a per-app-named app post carries \u2014 authorName/authorIcon, 0.55.0 \u2014 never the provider payload; `nextCursor` when hasMore, to pass as the next read's `cursor`); slack.message.post, slack.message.update, slack.message.delete -> {messageId} (the Slack ts); slack.dm.send -> {messageId, channelId} (the ts and the DM channel it went to); slack.user.lookup -> {userId, displayName}; gmail.thread.list -> {threads, hasMore, nextPageToken?} (newest matching threads; each `messageId` is the thread's newest message, what gmail.message.read takes; `nextPageToken` when hasMore); gmail.thread.read -> {id, emails} (every message of the thread, oldest first, each shaped like a gmail.message.read result); gmail.message.read -> {id, threadId, subject, from, to, date, text, truncated, attachments?} (headers plus the plain text with html stripped, cut at 16 KiB with `truncated` set; `attachments` lists the files without their bytes, which gmail.attachment.read fetches by id); gmail.attachment.read -> {filename, mimeType, size, dataBase64}; gmail.message.send -> {messageId, threadId} (the Gmail ids of the sent message and its thread); warehouse.view.read -> {rows, truncated} (rows keyed by the selected columns, or for an aggregate read by the groupBy columns then the aggregate aliases; decimal/64-bit values as strings, dates as ISO strings; since 0.70.0 every server sends `truncated`, true when more rows matched than `limit` \u2014 the server reads limit+1 rows to know \u2014 so the rows are incomplete and must not be totalled or averaged; a server before 0.70.0 omitted it). Basecamp (0.76.0, ADR 0022; every id a string of digits, every page at most 100 items, `nextPageToken` only when hasMore, text cut at 16 KiB like Gmail): basecamp.project.list -> {projects, hasMore, nextPageToken?}; basecamp.todolist.list -> {todolists, hasMore, nextPageToken?}; basecamp.todo.list -> {todos, hasMore, nextPageToken?}; basecamp.message.list -> {boardMessages, hasMore, nextPageToken?} (`boardMessages`, not `messages`, which is the Slack history shape); basecamp.comment.list -> {comments, hasMore, nextPageToken?}; basecamp.people.list -> {people, hasMore, nextPageToken?}; basecamp.todo.create, basecamp.message.post, basecamp.comment.post, basecamp.campfire.post -> {id, appUrl} (the new recording and its Basecamp page); basecamp.todo.complete -> {id, completed} with completed always true. SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id, `nextPageToken` only when hasMore and up to 2048 characters for a Graph `$skiptoken`): sharepoint.list.list -> {lists, hasMore, nextPageToken?} (at most 100, hidden lists dropped); sharepoint.item.list -> {items, hasMore, nextPageToken?} (at most 50; each item's `fields` are the column values as Graph returns them with the system columns dropped, the whole object cut at 16 KiB); sharepoint.drive.list -> {drives, hasMore, nextPageToken?}; sharepoint.file.list and sharepoint.file.search -> {files, hasMore, nextPageToken?} (at most 100 entries, folders included with isFolder); sharepoint.file.read -> {id, filename, mimeType, size, dataBase64} (the Gmail attachment shape plus the file's id; at most 2 MiB of bytes); sharepoint.item.create -> {id, webUrl} (the new item and its SharePoint page); sharepoint.item.update -> {id}; sharepoint.file.upload -> {id, filename, webUrl} (the stored file, under the name `conflict` rename may have given it). An unknown send outcome is never a result; it is an error with details.code SEND_OUTCOME_UNKNOWN. A whole result over 1 MiB is rejected, never cut down to fit \u2014 except a gmail.attachment.read or a sharepoint.file.read, whose single file is bounded by its own 2 MiB.",
5
+ "description": "The `data` member of a successful execute response `{data, requestId}`; the SDK unwraps `data`. Exactly one of the operation results (eighty-one operations since 0.86.0, ADR 0018, ADR 0022, ADR 0024, ADR 0028, ADR 0029 and ADR 0032): slack.channel.history -> {messages, hasMore, nextCursor?} (plain text/IDs/time, plus the display name and emoji icon a per-app-named app post carries \u2014 authorName/authorIcon, 0.55.0 \u2014 never the provider payload; `nextCursor` when hasMore, to pass as the next read's `cursor`); slack.message.post, slack.message.update, slack.message.delete -> {messageId} (the Slack ts); slack.dm.send -> {messageId, channelId} (the ts and the DM channel it went to); slack.user.lookup -> {userId, displayName}; gmail.thread.list -> {threads, hasMore, nextPageToken?} (newest matching threads; each `messageId` is the thread's newest message, what gmail.message.read takes; `nextPageToken` when hasMore); gmail.thread.read -> {id, emails} (every message of the thread, oldest first, each shaped like a gmail.message.read result); gmail.message.read -> {id, threadId, subject, from, to, date, text, truncated, attachments?} (headers plus the plain text with html stripped, cut at 16 KiB with `truncated` set; `attachments` lists the files without their bytes, which gmail.attachment.read fetches by id); gmail.attachment.read -> {filename, mimeType, size, dataBase64}; gmail.message.send -> {messageId, threadId} (the Gmail ids of the sent message and its thread); warehouse.view.read -> {rows, truncated} (rows keyed by the selected columns, or for an aggregate read by the groupBy columns then the aggregate aliases; decimal/64-bit values as strings, dates as ISO strings; since 0.70.0 every server sends `truncated`, true when more rows matched than `limit` \u2014 the server reads limit+1 rows to know \u2014 so the rows are incomplete and must not be totalled or averaged; a server before 0.70.0 omitted it). Basecamp (0.76.0, ADR 0022; every id a string of digits, every page at most 100 items, `nextPageToken` only when hasMore, text cut at 16 KiB like Gmail): basecamp.project.list -> {projects, hasMore, nextPageToken?}; basecamp.todolist.list -> {todolists, hasMore, nextPageToken?}; basecamp.todo.list -> {todos, hasMore, nextPageToken?}; basecamp.message.list -> {boardMessages, hasMore, nextPageToken?} (`boardMessages`, not `messages`, which is the Slack history shape); basecamp.comment.list -> {comments, hasMore, nextPageToken?}; basecamp.people.list -> {people, hasMore, nextPageToken?}; basecamp.todo.create, basecamp.message.post, basecamp.comment.post, basecamp.campfire.post -> {id, appUrl} (the new recording and its Basecamp page); basecamp.todo.complete -> {id, completed} with completed always true. SharePoint (0.78.0, ADR 0024; every id a Microsoft Graph id, `nextPageToken` only when hasMore and up to 2048 characters for a Graph `$skiptoken`): sharepoint.list.list -> {lists, hasMore, nextPageToken?} (at most 100, hidden lists dropped); sharepoint.item.list -> {items, hasMore, nextPageToken?} (at most 50; each item's `fields` are the column values as Graph returns them with the system columns dropped, the whole object cut at 16 KiB); sharepoint.drive.list -> {drives, hasMore, nextPageToken?}; sharepoint.file.list and sharepoint.file.search -> {files, hasMore, nextPageToken?} (at most 100 entries, folders included with isFolder); sharepoint.file.read -> {id, filename, mimeType, size, dataBase64} (the Gmail attachment shape plus the file's id; at most 2 MiB of bytes); sharepoint.item.create -> {id, webUrl} (the new item and its SharePoint page); sharepoint.item.update -> {id}; sharepoint.file.upload -> {id, filename, webUrl} (the stored file, under the name `conflict` rename may have given it). Google Workspace and Microsoft 365 (0.86.0, ADR 0032; every page at most 100 items, `nextPageToken` only when hasMore, up to 2048 characters): calendar.calendar.list -> {calendars, hasMore, nextPageToken?}; calendar.event.list and outlook.event.list -> {events, hasMore, nextPageToken?}; calendar.event.read and outlook.event.read -> the event itself, {id, title, start, end, allDay, timeZone?, location?, description?, attendees, organizer?, webUrl, eventStatus} (the CalendarEvent shape spread at the top level, the way gmail.message.read spreads GmailMessage; `eventStatus`, because `status` is the HTTP status of a service.request result); calendar.event.create and outlook.event.create -> {id, webUrl}; calendar.event.update, calendar.event.cancel, outlook.event.update, outlook.event.cancel -> {id}; drive.file.list, drive.file.search, onedrive.file.list, onedrive.file.search -> {files, hasMore, nextPageToken?} (the SharePoint entry shape); drive.file.read and onedrive.file.read -> {id, filename, mimeType, size, dataBase64} (the sharepoint.file.read shape; `filename` and `mimeType` are the stored or exported name and type); drive.file.upload and onedrive.file.upload -> {id, filename, webUrl}; drive.folder.create and onedrive.folder.create -> {id, webUrl}; docs.document.read -> {id, title, text, revisionId, webUrl, truncated} (the body as plain text cut at 64 KiB); docs.document.create -> {id, webUrl}; docs.document.append -> {id, revisionId}; docs.text.replace -> {id, replaced} (how many occurrences changed); sheets.spreadsheet.read -> {id, title, sheets, webUrl}; sheets.values.read -> {range, values} (the range Google answered with and the cells as rows; a trailing empty row or cell is dropped by Google); sheets.values.append -> {range, updatedRows}; sheets.values.update -> {range, updatedCells}; sheets.values.clear -> {range}; sheets.spreadsheet.create -> {id, webUrl}; outlook.message.list -> {mailMessages, hasMore, nextPageToken?} (`mailMessages`, not `messages`, which is the Slack history shape); outlook.message.read -> the gmail.message.read shape {id, threadId, subject, from, to, date, text, truncated, attachments?} with `threadId` the Graph conversationId; outlook.attachment.read -> {id, filename, mimeType, size, dataBase64}; outlook.message.send and outlook.message.reply -> {id} (the sent message's id, which Graph does not return for a send: governance's own internetMessageId); excel.worksheet.list -> {worksheets}; excel.range.read -> {address, values}; excel.range.update -> {address, updatedCells}; excel.table.list -> {tables}; excel.row.add -> {index, updatedRows} (the index of the first added row); excel.worksheet.add -> {id, name}; teams.message.list -> {teamsMessages, hasMore, nextPageToken?} (`teamsMessages`, apart from Slack's `messages`); teams.message.post and teams.reply.post -> {id, webUrl}. An unknown send outcome is never a result; it is an error with details.code SEND_OUTCOME_UNKNOWN. A whole result over 1 MiB is rejected, never cut down to fit \u2014 except a gmail.attachment.read, a sharepoint.file.read, a drive.file.read, an onedrive.file.read or an outlook.attachment.read, whose single file is bounded by its own 2 MiB.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "properties": {
@@ -54,18 +54,19 @@
54
54
  "type": "string",
55
55
  "minLength": 1,
56
56
  "maxLength": 2048,
57
- "description": "gmail.thread.list (0.71.0), the basecamp.* lists (0.76.0) and the paged sharepoint.* reads (0.78.0): the token of the next page, present only when hasMore; up to 2048 characters since 0.78.0 for a Graph $skiptoken."
57
+ "description": "gmail.thread.list (0.71.0), the basecamp.* lists (0.76.0) and the paged sharepoint.* reads (0.78.0): the token of the next page, present only when hasMore; up to 2048 characters since 0.78.0 for a Graph $skiptoken. The paged 0.86.0 reads (calendars, events, files, mailMessages, teamsMessages) page the same way."
58
58
  },
59
59
  "id": {
60
60
  "type": "string",
61
61
  "minLength": 1,
62
- "maxLength": 256,
63
- "description": "gmail.thread.read / gmail.message.read: the Gmail id; the Basecamp writes and complete (0.76.0): the recording's id; the SharePoint writes and sharepoint.file.read (0.78.0): the Graph id of the item or file (up to 256 characters since 0.78.0, the GraphId bound)."
62
+ "maxLength": 1024,
63
+ "description": "gmail.thread.read / gmail.message.read: the Gmail id; the Basecamp writes and complete (0.76.0): the recording's id; the SharePoint writes and sharepoint.file.read (0.78.0): the Graph id of the item or file (up to 256 characters since 0.78.0, the GraphId bound). The Google Workspace and Microsoft 365 operations (0.86.0): the event, file, folder, document, spreadsheet, message or worksheet id (up to 1024 characters since 0.86.0, a Google event id's bound)."
64
64
  },
65
65
  "threadId": {
66
66
  "type": "string",
67
67
  "minLength": 1,
68
- "maxLength": 128
68
+ "maxLength": 256,
69
+ "description": "gmail.message.read / gmail.message.send: the Gmail thread id. outlook.message.read (0.86.0): the Graph conversationId (up to 256 characters since 0.86.0)."
69
70
  },
70
71
  "subject": {
71
72
  "type": "string",
@@ -85,11 +86,12 @@
85
86
  },
86
87
  "text": {
87
88
  "type": "string",
88
- "maxLength": 16384
89
+ "maxLength": 65536,
90
+ "description": "gmail.message.read and outlook.message.read (0.86.0): the plain-text body, cut at 16 KiB with `truncated` set. docs.document.read (0.86.0): the document's body as plain text, cut at 64 KiB (the shared bound)."
89
91
  },
90
92
  "truncated": {
91
93
  "type": "boolean",
92
- "description": "gmail.message.read: the text was cut at 16 KiB. warehouse.view.read (0.70.0): more rows matched than the read's limit, so `rows` is incomplete."
94
+ "description": "gmail.message.read: the text was cut at 16 KiB. warehouse.view.read (0.70.0): more rows matched than the read's limit, so `rows` is incomplete. docs.document.read (0.86.0): the text was cut at 64 KiB."
93
95
  },
94
96
  "sample": {
95
97
  "type": "boolean",
@@ -114,12 +116,14 @@
114
116
  "filename": {
115
117
  "type": "string",
116
118
  "minLength": 1,
117
- "maxLength": 255
119
+ "maxLength": 255,
120
+ "description": "gmail.attachment.read / sharepoint.file.read / sharepoint.file.upload: the file's name. drive.file.read / onedrive.file.read / outlook.attachment.read (0.86.0): the stored name, or for an exported Google file the name with the export's extension. drive.file.upload / onedrive.file.upload: the stored name, which `conflict` rename may have changed."
118
121
  },
119
122
  "mimeType": {
120
123
  "type": "string",
121
124
  "minLength": 1,
122
- "maxLength": 128
125
+ "maxLength": 128,
126
+ "description": "gmail.attachment.read / sharepoint.file.read / outlook.attachment.read (0.86.0): the file's MIME type. drive.file.read / onedrive.file.read (0.86.0): the stored type, or the export's (text/plain, text/csv, application/pdf)."
123
127
  },
124
128
  "size": {
125
129
  "type": "integer",
@@ -229,14 +233,192 @@
229
233
  "items": {
230
234
  "$ref": "#/definitions/SharePointFile"
231
235
  },
232
- "description": "sharepoint.file.list / sharepoint.file.search (0.78.0): one page of a folder's entries (files and folders) or of the files matching the search."
236
+ "description": "sharepoint.file.list / sharepoint.file.search (0.78.0): one page of a folder's entries (files and folders) or of the files matching the search. drive.file.list / drive.file.search / onedrive.file.list / onedrive.file.search (0.86.0): the same shape for a Google Drive folder or search and for a OneDrive one."
233
237
  },
234
238
  "webUrl": {
235
239
  "type": "string",
236
240
  "format": "uri",
237
241
  "minLength": 1,
238
242
  "maxLength": 2048,
239
- "description": "sharepoint.item.create / sharepoint.file.upload (0.78.0): the SharePoint page of the new item or file, for a person to open."
243
+ "description": "sharepoint.item.create / sharepoint.file.upload (0.78.0): the SharePoint page of the new item or file, for a person to open. The Google Workspace and Microsoft 365 writes (0.86.0): the page of the new event, file, folder, document, spreadsheet or message, for a person to open."
244
+ },
245
+ "calendars": {
246
+ "type": "array",
247
+ "maxItems": 100,
248
+ "items": {
249
+ "$ref": "#/definitions/CalendarListEntry"
250
+ },
251
+ "description": "calendar.calendar.list (0.86.0): one page of the calendars the signed-in person can see; `id` is what the calendar.event.* operations take as `calendarId`."
252
+ },
253
+ "events": {
254
+ "type": "array",
255
+ "maxItems": 100,
256
+ "items": {
257
+ "$ref": "#/definitions/CalendarEvent"
258
+ },
259
+ "description": "calendar.event.list / outlook.event.list (0.86.0): one page of the events in the window, recurring events expanded to instances, ordered by start."
260
+ },
261
+ "title": {
262
+ "type": "string",
263
+ "maxLength": 2048,
264
+ "description": "calendar.event.read / outlook.event.read (0.86.0): the event's title. docs.document.read: the document's title. sheets.spreadsheet.read: the spreadsheet's title."
265
+ },
266
+ "start": {
267
+ "type": "string",
268
+ "minLength": 1,
269
+ "maxLength": 64,
270
+ "description": "calendar.event.read / outlook.event.read (0.86.0): when the event starts, an RFC 3339 date-time, or a YYYY-MM-DD date for an all-day event."
271
+ },
272
+ "end": {
273
+ "type": "string",
274
+ "minLength": 1,
275
+ "maxLength": 64,
276
+ "description": "calendar.event.read / outlook.event.read (0.86.0): when the event ends, the same way (the day after the last day for an all-day event)."
277
+ },
278
+ "allDay": {
279
+ "type": "boolean",
280
+ "description": "calendar.event.read / outlook.event.read (0.86.0): whether the event spans whole days."
281
+ },
282
+ "timeZone": {
283
+ "type": "string",
284
+ "minLength": 1,
285
+ "maxLength": 64,
286
+ "description": "calendar.event.read / outlook.event.read (0.86.0): the IANA zone the event is shown in, when the provider reports one."
287
+ },
288
+ "location": {
289
+ "type": "string",
290
+ "maxLength": 2048,
291
+ "description": "calendar.event.read / outlook.event.read (0.86.0): where the event is, as free text, when set."
292
+ },
293
+ "description": {
294
+ "type": "string",
295
+ "maxLength": 16384,
296
+ "description": "calendar.event.read / outlook.event.read (0.86.0): the event's description as plain text, cut at 16 KiB, when set."
297
+ },
298
+ "attendees": {
299
+ "type": "array",
300
+ "maxItems": 500,
301
+ "items": {
302
+ "$ref": "#/definitions/CalendarAttendee"
303
+ },
304
+ "description": "calendar.event.read / outlook.event.read (0.86.0): who is invited and how they answered; empty when the event has no attendees."
305
+ },
306
+ "organizer": {
307
+ "$ref": "#/definitions/CalendarAttendee",
308
+ "description": "calendar.event.read / outlook.event.read (0.86.0): who organises the event, when the provider reports one."
309
+ },
310
+ "eventStatus": {
311
+ "$ref": "#/definitions/CalendarEventStatus",
312
+ "description": "calendar.event.read / outlook.event.read (0.86.0): confirmed, tentative or cancelled. Named apart from `status`, the HTTP status of a service.request result."
313
+ },
314
+ "revisionId": {
315
+ "type": "string",
316
+ "minLength": 1,
317
+ "maxLength": 256,
318
+ "description": "docs.document.read / docs.document.append (0.86.0): the document's revision after the read or the append, as Google names it."
319
+ },
320
+ "replaced": {
321
+ "type": "integer",
322
+ "minimum": 0,
323
+ "description": "docs.text.replace (0.86.0): how many occurrences were replaced over all the pairs."
324
+ },
325
+ "sheets": {
326
+ "type": "array",
327
+ "maxItems": 200,
328
+ "items": {
329
+ "$ref": "#/definitions/SheetProperties"
330
+ },
331
+ "description": "sheets.spreadsheet.read (0.86.0): the spreadsheet's sheets in tab order, with their grid sizes."
332
+ },
333
+ "range": {
334
+ "type": "string",
335
+ "minLength": 1,
336
+ "maxLength": 256,
337
+ "description": "sheets.values.read / sheets.values.append / sheets.values.update / sheets.values.clear (0.86.0): the range Google answered with in A1 notation (for an append, the cells the rows went into)."
338
+ },
339
+ "values": {
340
+ "type": "array",
341
+ "maxItems": 1000,
342
+ "items": {
343
+ "type": "array",
344
+ "maxItems": 100,
345
+ "items": {
346
+ "oneOf": [
347
+ {
348
+ "type": "string",
349
+ "maxLength": 50000
350
+ },
351
+ {
352
+ "type": "number"
353
+ },
354
+ {
355
+ "type": "boolean"
356
+ },
357
+ {
358
+ "type": "null"
359
+ }
360
+ ]
361
+ }
362
+ },
363
+ "description": "sheets.values.read / excel.range.read (0.86.0): the cells as rows, each cell a string, a number, a boolean or null (an empty cell); unformatted values (a date cell is its serial number at Google, its text at Excel). The whole object is cut at 1 MiB by the result cap, never trimmed."
364
+ },
365
+ "updatedRows": {
366
+ "type": "integer",
367
+ "minimum": 0,
368
+ "description": "sheets.values.append / excel.row.add (0.86.0): how many rows were written."
369
+ },
370
+ "updatedCells": {
371
+ "type": "integer",
372
+ "minimum": 0,
373
+ "description": "sheets.values.update / excel.range.update (0.86.0): how many cells were written."
374
+ },
375
+ "worksheets": {
376
+ "type": "array",
377
+ "maxItems": 500,
378
+ "items": {
379
+ "$ref": "#/definitions/ExcelWorksheet"
380
+ },
381
+ "description": "excel.worksheet.list (0.86.0): the workbook's worksheets in tab order."
382
+ },
383
+ "address": {
384
+ "type": "string",
385
+ "minLength": 1,
386
+ "maxLength": 256,
387
+ "description": "excel.range.read / excel.range.update (0.86.0): the range Excel answered with, e.g. `Orders!A1:D10`."
388
+ },
389
+ "tables": {
390
+ "type": "array",
391
+ "maxItems": 500,
392
+ "items": {
393
+ "$ref": "#/definitions/ExcelTable"
394
+ },
395
+ "description": "excel.table.list (0.86.0): the workbook's or the worksheet's tables; `name` is what excel.row.add takes as `tableName`."
396
+ },
397
+ "index": {
398
+ "type": "integer",
399
+ "minimum": 0,
400
+ "description": "excel.row.add (0.86.0): the zero-based index, within the table, of the first row added."
401
+ },
402
+ "name": {
403
+ "type": "string",
404
+ "maxLength": 256,
405
+ "description": "excel.worksheet.add (0.86.0): the new worksheet's name."
406
+ },
407
+ "mailMessages": {
408
+ "type": "array",
409
+ "maxItems": 100,
410
+ "items": {
411
+ "$ref": "#/definitions/OutlookMessageSummary"
412
+ },
413
+ "description": "outlook.message.list (0.86.0): one page of the folder's messages, newest first (or by relevance for a search), without their bodies; `id` is what outlook.message.read takes. Named apart from `messages`, the Slack history shape, and `emails`, the Gmail thread shape."
414
+ },
415
+ "teamsMessages": {
416
+ "type": "array",
417
+ "maxItems": 100,
418
+ "items": {
419
+ "$ref": "#/definitions/TeamsMessage"
420
+ },
421
+ "description": "teams.message.list (0.86.0): one page of the channel's top-level messages, newest first; `id` is what teams.reply.post takes as `messageId`. Named apart from `messages`, the Slack history shape."
240
422
  },
241
423
  "status": {
242
424
  "type": "integer"
@@ -528,6 +710,187 @@
528
710
  "dataBase64"
529
711
  ],
530
712
  "maxProperties": 5
713
+ },
714
+ {
715
+ "required": [
716
+ "calendars",
717
+ "hasMore"
718
+ ],
719
+ "propertyNames": {
720
+ "enum": [
721
+ "calendars",
722
+ "hasMore",
723
+ "nextPageToken"
724
+ ]
725
+ }
726
+ },
727
+ {
728
+ "required": [
729
+ "events",
730
+ "hasMore"
731
+ ],
732
+ "propertyNames": {
733
+ "enum": [
734
+ "events",
735
+ "hasMore",
736
+ "nextPageToken"
737
+ ]
738
+ }
739
+ },
740
+ {
741
+ "required": [
742
+ "id",
743
+ "title",
744
+ "start",
745
+ "end",
746
+ "allDay",
747
+ "attendees",
748
+ "webUrl",
749
+ "eventStatus"
750
+ ],
751
+ "propertyNames": {
752
+ "enum": [
753
+ "id",
754
+ "title",
755
+ "start",
756
+ "end",
757
+ "allDay",
758
+ "timeZone",
759
+ "location",
760
+ "description",
761
+ "attendees",
762
+ "organizer",
763
+ "webUrl",
764
+ "eventStatus"
765
+ ]
766
+ }
767
+ },
768
+ {
769
+ "required": [
770
+ "id",
771
+ "title",
772
+ "text",
773
+ "revisionId",
774
+ "webUrl",
775
+ "truncated"
776
+ ],
777
+ "maxProperties": 6
778
+ },
779
+ {
780
+ "required": [
781
+ "id",
782
+ "revisionId"
783
+ ],
784
+ "maxProperties": 2
785
+ },
786
+ {
787
+ "required": [
788
+ "id",
789
+ "replaced"
790
+ ],
791
+ "maxProperties": 2
792
+ },
793
+ {
794
+ "required": [
795
+ "id",
796
+ "title",
797
+ "sheets",
798
+ "webUrl"
799
+ ],
800
+ "maxProperties": 4
801
+ },
802
+ {
803
+ "required": [
804
+ "range",
805
+ "values"
806
+ ],
807
+ "maxProperties": 2
808
+ },
809
+ {
810
+ "required": [
811
+ "range",
812
+ "updatedRows"
813
+ ],
814
+ "maxProperties": 2
815
+ },
816
+ {
817
+ "required": [
818
+ "range",
819
+ "updatedCells"
820
+ ],
821
+ "maxProperties": 2
822
+ },
823
+ {
824
+ "required": [
825
+ "range"
826
+ ],
827
+ "maxProperties": 1
828
+ },
829
+ {
830
+ "required": [
831
+ "worksheets"
832
+ ],
833
+ "maxProperties": 1
834
+ },
835
+ {
836
+ "required": [
837
+ "address",
838
+ "values"
839
+ ],
840
+ "maxProperties": 2
841
+ },
842
+ {
843
+ "required": [
844
+ "address",
845
+ "updatedCells"
846
+ ],
847
+ "maxProperties": 2
848
+ },
849
+ {
850
+ "required": [
851
+ "tables"
852
+ ],
853
+ "maxProperties": 1
854
+ },
855
+ {
856
+ "required": [
857
+ "index",
858
+ "updatedRows"
859
+ ],
860
+ "maxProperties": 2
861
+ },
862
+ {
863
+ "required": [
864
+ "id",
865
+ "name"
866
+ ],
867
+ "maxProperties": 2
868
+ },
869
+ {
870
+ "required": [
871
+ "mailMessages",
872
+ "hasMore"
873
+ ],
874
+ "propertyNames": {
875
+ "enum": [
876
+ "mailMessages",
877
+ "hasMore",
878
+ "nextPageToken"
879
+ ]
880
+ }
881
+ },
882
+ {
883
+ "required": [
884
+ "teamsMessages",
885
+ "hasMore"
886
+ ],
887
+ "propertyNames": {
888
+ "enum": [
889
+ "teamsMessages",
890
+ "hasMore",
891
+ "nextPageToken"
892
+ ]
893
+ }
531
894
  }
532
895
  ],
533
896
  "definitions": {
@@ -1079,7 +1442,7 @@
1079
1442
  "webUrl",
1080
1443
  "modifiedAt"
1081
1444
  ],
1082
- "description": "One entry of a sharepoint.file.list or sharepoint.file.search result (0.78.0): a file (`mimeType` set, `id` is what sharepoint.file.read takes as `fileId`) or a folder (`isFolder`, `id` is what sharepoint.file.list and sharepoint.file.upload take as `folderId`). `size` is in bytes; a folder's is the total of its contents.",
1445
+ "description": "One entry of a sharepoint.file.list or sharepoint.file.search result (0.78.0): a file (`mimeType` set, `id` is what sharepoint.file.read takes as `fileId`) or a folder (`isFolder`, `id` is what sharepoint.file.list and sharepoint.file.upload take as `folderId`). `size` is in bytes; a folder's is the total of its contents. drive.file.list / drive.file.search / onedrive.file.list / onedrive.file.search (0.86.0) answer the same entries: for Google Drive `mimeType` is the Drive type (a Google Docs file is application/vnd.google-apps.document) and `size` 0 for a Google-native file; `id` is what drive.file.read / onedrive.file.read take as `fileId`, a folder's what file.list, file.upload and folder.create take as `folderId`.",
1083
1446
  "properties": {
1084
1447
  "id": {
1085
1448
  "$ref": "app-integrations-declaration.schema.json#/definitions/GraphId"
@@ -1111,25 +1474,339 @@
1111
1474
  "format": "date-time"
1112
1475
  }
1113
1476
  }
1114
- }
1115
- },
1116
- "examples": [
1117
- {
1118
- "messages": [
1119
- {
1120
- "id": "1725840000.000100",
1121
- "text": "Shipped the weekly report.",
1122
- "authorId": "U0123456",
1123
- "createdAt": "2026-09-09T08:00:00Z"
1124
- }
1125
- ],
1126
- "hasMore": false
1127
- },
1128
- {
1129
- "messageId": "1725840100.000200"
1130
1477
  },
1131
- {
1132
- "messageId": "18f2c3a4b5d6e7f9",
1478
+ "CalendarListEntry": {
1479
+ "type": "object",
1480
+ "additionalProperties": false,
1481
+ "required": [
1482
+ "id",
1483
+ "name",
1484
+ "primary",
1485
+ "accessRole"
1486
+ ],
1487
+ "description": "One calendar of a calendar.calendar.list result (0.86.0); `id` is what the calendar.event.* operations take as `calendarId`, `primary` marks the person's own calendar, `accessRole` is Google's (owner, writer, reader, freeBusyReader).",
1488
+ "properties": {
1489
+ "id": {
1490
+ "type": "string",
1491
+ "minLength": 1,
1492
+ "maxLength": 256
1493
+ },
1494
+ "name": {
1495
+ "type": "string",
1496
+ "maxLength": 256
1497
+ },
1498
+ "primary": {
1499
+ "type": "boolean"
1500
+ },
1501
+ "accessRole": {
1502
+ "type": "string",
1503
+ "minLength": 1,
1504
+ "maxLength": 32
1505
+ }
1506
+ }
1507
+ },
1508
+ "CalendarEventStatus": {
1509
+ "type": "string",
1510
+ "enum": [
1511
+ "confirmed",
1512
+ "tentative",
1513
+ "cancelled"
1514
+ ],
1515
+ "description": "An event's state (0.86.0): confirmed (Google `confirmed`, Graph not cancelled and not tentative), tentative, or cancelled."
1516
+ },
1517
+ "CalendarAttendee": {
1518
+ "type": "object",
1519
+ "additionalProperties": false,
1520
+ "required": [
1521
+ "email"
1522
+ ],
1523
+ "description": "A person on an event (0.86.0): an attendee or the organizer. `response` is theirs when the provider reports it: accepted, declined, tentative or needsAction.",
1524
+ "properties": {
1525
+ "email": {
1526
+ "type": "string",
1527
+ "maxLength": 254
1528
+ },
1529
+ "name": {
1530
+ "type": "string",
1531
+ "maxLength": 256
1532
+ },
1533
+ "response": {
1534
+ "type": "string",
1535
+ "enum": [
1536
+ "accepted",
1537
+ "declined",
1538
+ "tentative",
1539
+ "needsAction"
1540
+ ]
1541
+ }
1542
+ }
1543
+ },
1544
+ "CalendarEvent": {
1545
+ "type": "object",
1546
+ "additionalProperties": false,
1547
+ "required": [
1548
+ "id",
1549
+ "title",
1550
+ "start",
1551
+ "end",
1552
+ "allDay",
1553
+ "attendees",
1554
+ "webUrl",
1555
+ "eventStatus"
1556
+ ],
1557
+ "description": "One event of a calendar.event.list or outlook.event.list result (0.86.0), and the shape calendar.event.read and outlook.event.read spread at the top level. `start` and `end` are RFC 3339 date-times, or YYYY-MM-DD dates when `allDay`; `description` is plain text cut at 16 KiB; `id` is what the event.read, event.update and event.cancel operations take as `eventId`.",
1558
+ "properties": {
1559
+ "id": {
1560
+ "type": "string",
1561
+ "minLength": 1,
1562
+ "maxLength": 1024
1563
+ },
1564
+ "title": {
1565
+ "type": "string",
1566
+ "maxLength": 2048
1567
+ },
1568
+ "start": {
1569
+ "type": "string",
1570
+ "minLength": 1,
1571
+ "maxLength": 64
1572
+ },
1573
+ "end": {
1574
+ "type": "string",
1575
+ "minLength": 1,
1576
+ "maxLength": 64
1577
+ },
1578
+ "allDay": {
1579
+ "type": "boolean"
1580
+ },
1581
+ "timeZone": {
1582
+ "type": "string",
1583
+ "minLength": 1,
1584
+ "maxLength": 64
1585
+ },
1586
+ "location": {
1587
+ "type": "string",
1588
+ "maxLength": 2048
1589
+ },
1590
+ "description": {
1591
+ "type": "string",
1592
+ "maxLength": 16384
1593
+ },
1594
+ "attendees": {
1595
+ "type": "array",
1596
+ "maxItems": 500,
1597
+ "items": {
1598
+ "$ref": "#/definitions/CalendarAttendee"
1599
+ }
1600
+ },
1601
+ "organizer": {
1602
+ "$ref": "#/definitions/CalendarAttendee"
1603
+ },
1604
+ "webUrl": {
1605
+ "type": "string",
1606
+ "format": "uri",
1607
+ "minLength": 1,
1608
+ "maxLength": 2048
1609
+ },
1610
+ "eventStatus": {
1611
+ "$ref": "#/definitions/CalendarEventStatus"
1612
+ }
1613
+ }
1614
+ },
1615
+ "SheetProperties": {
1616
+ "type": "object",
1617
+ "additionalProperties": false,
1618
+ "required": [
1619
+ "id",
1620
+ "title",
1621
+ "rows",
1622
+ "columns"
1623
+ ],
1624
+ "description": "One sheet (tab) of a sheets.spreadsheet.read result (0.86.0): Google's numeric sheetId, its title (what a `range` names before the `!`) and its grid size.",
1625
+ "properties": {
1626
+ "id": {
1627
+ "type": "integer",
1628
+ "minimum": 0
1629
+ },
1630
+ "title": {
1631
+ "type": "string",
1632
+ "maxLength": 256
1633
+ },
1634
+ "rows": {
1635
+ "type": "integer",
1636
+ "minimum": 0
1637
+ },
1638
+ "columns": {
1639
+ "type": "integer",
1640
+ "minimum": 0
1641
+ }
1642
+ }
1643
+ },
1644
+ "OutlookMessageSummary": {
1645
+ "type": "object",
1646
+ "additionalProperties": false,
1647
+ "required": [
1648
+ "id",
1649
+ "conversationId",
1650
+ "subject",
1651
+ "from",
1652
+ "to",
1653
+ "receivedAt",
1654
+ "preview",
1655
+ "hasAttachments",
1656
+ "webUrl"
1657
+ ],
1658
+ "description": "One message of an outlook.message.list result (0.86.0), without its body: `preview` is Graph's bodyPreview (at most 255 characters), `from` and `to` are addresses as text; `id` is what outlook.message.read, outlook.attachment.read and outlook.message.reply take as `messageId`.",
1659
+ "properties": {
1660
+ "id": {
1661
+ "type": "string",
1662
+ "minLength": 1,
1663
+ "maxLength": 256
1664
+ },
1665
+ "conversationId": {
1666
+ "type": "string",
1667
+ "minLength": 1,
1668
+ "maxLength": 256
1669
+ },
1670
+ "subject": {
1671
+ "type": "string",
1672
+ "maxLength": 2048
1673
+ },
1674
+ "from": {
1675
+ "type": "string",
1676
+ "maxLength": 2048
1677
+ },
1678
+ "to": {
1679
+ "type": "string",
1680
+ "maxLength": 8192
1681
+ },
1682
+ "receivedAt": {
1683
+ "type": "string",
1684
+ "format": "date-time"
1685
+ },
1686
+ "preview": {
1687
+ "type": "string",
1688
+ "maxLength": 1024
1689
+ },
1690
+ "hasAttachments": {
1691
+ "type": "boolean"
1692
+ },
1693
+ "webUrl": {
1694
+ "type": "string",
1695
+ "format": "uri",
1696
+ "minLength": 1,
1697
+ "maxLength": 2048
1698
+ }
1699
+ }
1700
+ },
1701
+ "ExcelWorksheet": {
1702
+ "type": "object",
1703
+ "additionalProperties": false,
1704
+ "required": [
1705
+ "id",
1706
+ "name",
1707
+ "position"
1708
+ ],
1709
+ "description": "One worksheet of an excel.worksheet.list result (0.86.0); `name` or `id` is what excel.range.read, excel.range.update and excel.table.list take as `worksheet`; `position` is its zero-based tab index.",
1710
+ "properties": {
1711
+ "id": {
1712
+ "type": "string",
1713
+ "minLength": 1,
1714
+ "maxLength": 256
1715
+ },
1716
+ "name": {
1717
+ "type": "string",
1718
+ "maxLength": 256
1719
+ },
1720
+ "position": {
1721
+ "type": "integer",
1722
+ "minimum": 0
1723
+ }
1724
+ }
1725
+ },
1726
+ "ExcelTable": {
1727
+ "type": "object",
1728
+ "additionalProperties": false,
1729
+ "required": [
1730
+ "id",
1731
+ "name",
1732
+ "worksheet"
1733
+ ],
1734
+ "description": "One table of an excel.table.list result (0.86.0); `name` is what excel.row.add takes as `tableName`, `worksheet` the name of the sheet it lives on.",
1735
+ "properties": {
1736
+ "id": {
1737
+ "type": "string",
1738
+ "minLength": 1,
1739
+ "maxLength": 256
1740
+ },
1741
+ "name": {
1742
+ "type": "string",
1743
+ "maxLength": 256
1744
+ },
1745
+ "worksheet": {
1746
+ "type": "string",
1747
+ "maxLength": 256
1748
+ }
1749
+ }
1750
+ },
1751
+ "TeamsMessage": {
1752
+ "type": "object",
1753
+ "additionalProperties": false,
1754
+ "required": [
1755
+ "id",
1756
+ "from",
1757
+ "text",
1758
+ "createdAt",
1759
+ "webUrl"
1760
+ ],
1761
+ "description": "One top-level message of a teams.message.list result (0.86.0): `from` is the sender's display name (or the app's), `text` the body as plain text with HTML stripped, cut at 16 KiB, `replyCount` how many replies it has when Graph reports it; `id` is what teams.reply.post takes as `messageId`.",
1762
+ "properties": {
1763
+ "id": {
1764
+ "type": "string",
1765
+ "minLength": 1,
1766
+ "maxLength": 128
1767
+ },
1768
+ "from": {
1769
+ "type": "string",
1770
+ "maxLength": 256
1771
+ },
1772
+ "text": {
1773
+ "type": "string",
1774
+ "maxLength": 16384
1775
+ },
1776
+ "createdAt": {
1777
+ "type": "string",
1778
+ "format": "date-time"
1779
+ },
1780
+ "webUrl": {
1781
+ "type": "string",
1782
+ "format": "uri",
1783
+ "minLength": 1,
1784
+ "maxLength": 2048
1785
+ },
1786
+ "replyCount": {
1787
+ "type": "integer",
1788
+ "minimum": 0
1789
+ }
1790
+ }
1791
+ }
1792
+ },
1793
+ "examples": [
1794
+ {
1795
+ "messages": [
1796
+ {
1797
+ "id": "1725840000.000100",
1798
+ "text": "Shipped the weekly report.",
1799
+ "authorId": "U0123456",
1800
+ "createdAt": "2026-09-09T08:00:00Z"
1801
+ }
1802
+ ],
1803
+ "hasMore": false
1804
+ },
1805
+ {
1806
+ "messageId": "1725840100.000200"
1807
+ },
1808
+ {
1809
+ "messageId": "18f2c3a4b5d6e7f9",
1133
1810
  "threadId": "18f2c3a4b5d6e7f0"
1134
1811
  },
1135
1812
  {
@@ -1476,6 +2153,233 @@
1476
2153
  "id": "01BYE5RZ7KQJ2A3BUFOFD3GSPGOHDJD37L",
1477
2154
  "filename": "weekly-report 1.pdf",
1478
2155
  "webUrl": "https://fourier.sharepoint.com/sites/intranet/Shared%20Documents/Reports/weekly-report%201.pdf"
2156
+ },
2157
+ {
2158
+ "calendars": [
2159
+ {
2160
+ "id": "saketh@example.com",
2161
+ "name": "Saketh",
2162
+ "primary": true,
2163
+ "accessRole": "owner"
2164
+ },
2165
+ {
2166
+ "id": "c_1a2b3c4d5e6f7g8h9i0j@group.calendar.google.com",
2167
+ "name": "Engineering",
2168
+ "primary": false,
2169
+ "accessRole": "writer"
2170
+ }
2171
+ ],
2172
+ "hasMore": false
2173
+ },
2174
+ {
2175
+ "events": [
2176
+ {
2177
+ "id": "7qk2m9f4c1a8b3d5e6f7g8h9i0",
2178
+ "title": "Sprint review",
2179
+ "start": "2026-10-21T09:00:00+05:30",
2180
+ "end": "2026-10-21T10:00:00+05:30",
2181
+ "allDay": false,
2182
+ "timeZone": "Asia/Kolkata",
2183
+ "location": "Room 4",
2184
+ "description": "Demo of the weekly report app.",
2185
+ "attendees": [
2186
+ {
2187
+ "email": "jane@example.com",
2188
+ "name": "Jane Doe",
2189
+ "response": "accepted"
2190
+ },
2191
+ {
2192
+ "email": "sam@example.com",
2193
+ "response": "needsAction"
2194
+ }
2195
+ ],
2196
+ "organizer": {
2197
+ "email": "saketh@example.com",
2198
+ "name": "Saketh"
2199
+ },
2200
+ "webUrl": "https://www.google.com/calendar/event?eid=N3FrMm05ZjRjMWE4YjNkNWU2ZjdnOGg5aTAgamFuZUBleGFtcGxlLmNvbQ",
2201
+ "eventStatus": "confirmed"
2202
+ }
2203
+ ],
2204
+ "hasMore": true,
2205
+ "nextPageToken": "CigKGjdxazJtOWY0YzFhOGIzZDVlNmY3ZzhoOWkwGAEggIDA6rOW-wIaDQgAEgAYASCA"
2206
+ },
2207
+ {
2208
+ "id": "7qk2m9f4c1a8b3d5e6f7g8h9i0",
2209
+ "title": "Sprint review",
2210
+ "start": "2026-10-21T09:00:00+05:30",
2211
+ "end": "2026-10-21T10:00:00+05:30",
2212
+ "allDay": false,
2213
+ "timeZone": "Asia/Kolkata",
2214
+ "location": "Room 4",
2215
+ "description": "Demo of the weekly report app.",
2216
+ "attendees": [
2217
+ {
2218
+ "email": "jane@example.com",
2219
+ "name": "Jane Doe",
2220
+ "response": "accepted"
2221
+ },
2222
+ {
2223
+ "email": "sam@example.com",
2224
+ "response": "needsAction"
2225
+ }
2226
+ ],
2227
+ "organizer": {
2228
+ "email": "saketh@example.com",
2229
+ "name": "Saketh"
2230
+ },
2231
+ "webUrl": "https://www.google.com/calendar/event?eid=N3FrMm05ZjRjMWE4YjNkNWU2ZjdnOGg5aTAgamFuZUBleGFtcGxlLmNvbQ",
2232
+ "eventStatus": "confirmed"
2233
+ },
2234
+ {
2235
+ "id": "1x2y3z4A5B6C7D8E9F0G1H2I3J4K5L6M7N8O9P0Q1R2S",
2236
+ "title": "Weekly report, week 42",
2237
+ "text": "Shipped the weekly report app.\n\nNext: the Sheets export.",
2238
+ "revisionId": "ALBJ4LtK9Qx2mYhR3nV0pWcE7sD1fG8hJ",
2239
+ "webUrl": "https://docs.google.com/document/d/1x2y3z4A5B6C7D8E9F0G1H2I3J4K5L6M7N8O9P0Q1R2S/edit",
2240
+ "truncated": false
2241
+ },
2242
+ {
2243
+ "id": "1x2y3z4A5B6C7D8E9F0G1H2I3J4K5L6M7N8O9P0Q1R2S",
2244
+ "revisionId": "ALBJ4LtL0Ry3nZiS4oW1qXdF8tE2gH9iK"
2245
+ },
2246
+ {
2247
+ "id": "1x2y3z4A5B6C7D8E9F0G1H2I3J4K5L6M7N8O9P0Q1R2S",
2248
+ "replaced": 3
2249
+ },
2250
+ {
2251
+ "id": "1qW2eR3tY4uI5oP6aS7dF8gH9jK0lZ1xC2vB3nM4Q5w6",
2252
+ "title": "Q4 pipeline",
2253
+ "sheets": [
2254
+ {
2255
+ "id": 0,
2256
+ "title": "Deals",
2257
+ "rows": 1000,
2258
+ "columns": 26
2259
+ },
2260
+ {
2261
+ "id": 1498710651,
2262
+ "title": "Notes",
2263
+ "rows": 1000,
2264
+ "columns": 26
2265
+ }
2266
+ ],
2267
+ "webUrl": "https://docs.google.com/spreadsheets/d/1qW2eR3tY4uI5oP6aS7dF8gH9jK0lZ1xC2vB3nM4Q5w6/edit"
2268
+ },
2269
+ {
2270
+ "range": "Orders!A1:D3",
2271
+ "values": [
2272
+ [
2273
+ "date",
2274
+ "invoice",
2275
+ "amount",
2276
+ "paid"
2277
+ ],
2278
+ [
2279
+ "2026-10-17",
2280
+ "INV-1042",
2281
+ 1250.5,
2282
+ true
2283
+ ],
2284
+ [
2285
+ "2026-10-17",
2286
+ "INV-1043",
2287
+ 980,
2288
+ false
2289
+ ]
2290
+ ]
2291
+ },
2292
+ {
2293
+ "range": "Orders!A4:D5",
2294
+ "updatedRows": 2
2295
+ },
2296
+ {
2297
+ "range": "Orders!C2:D2",
2298
+ "updatedCells": 2
2299
+ },
2300
+ {
2301
+ "range": "Orders!A2:D1000"
2302
+ },
2303
+ {
2304
+ "mailMessages": [
2305
+ {
2306
+ "id": "AAMkAGI2THVSAAA-ZmQ0NzY2M2EtMDAwMC00YzI4LWFhYTEtYmJjYzEyMzQ1Njc4AQAAAAAAWbKCSXNo0UOjEqSs3Og1AAA=",
2307
+ "conversationId": "AAQkAGI2THVSAAAQAK5f9c0P2kZEoYw3QmX3xYQ=",
2308
+ "subject": "Weekly report",
2309
+ "from": "Jane Doe <jane@example.com>",
2310
+ "to": "saketh@example.com",
2311
+ "receivedAt": "2026-10-17T08:00:00Z",
2312
+ "preview": "The weekly report is attached.",
2313
+ "hasAttachments": true,
2314
+ "webUrl": "https://outlook.office365.com/owa/?ItemID=AAMkAGI2THVSAAA%3D&exvsurl=1&viewmodel=ReadMessageItem"
2315
+ }
2316
+ ],
2317
+ "hasMore": false
2318
+ },
2319
+ {
2320
+ "worksheets": [
2321
+ {
2322
+ "id": "{00000000-0001-0000-0000-000000000000}",
2323
+ "name": "Orders",
2324
+ "position": 0
2325
+ },
2326
+ {
2327
+ "id": "{00000000-0001-0000-0100-000000000000}",
2328
+ "name": "Week 42",
2329
+ "position": 1
2330
+ }
2331
+ ]
2332
+ },
2333
+ {
2334
+ "address": "Orders!A1:D2",
2335
+ "values": [
2336
+ [
2337
+ "date",
2338
+ "invoice",
2339
+ "amount",
2340
+ "paid"
2341
+ ],
2342
+ [
2343
+ "2026-10-17",
2344
+ "INV-1042",
2345
+ 1250.5,
2346
+ true
2347
+ ]
2348
+ ]
2349
+ },
2350
+ {
2351
+ "address": "Orders!C2:D2",
2352
+ "updatedCells": 2
2353
+ },
2354
+ {
2355
+ "tables": [
2356
+ {
2357
+ "id": "{5A3B2C1D-0000-0000-0000-000000000001}",
2358
+ "name": "OrdersTable",
2359
+ "worksheet": "Orders"
2360
+ }
2361
+ ]
2362
+ },
2363
+ {
2364
+ "index": 41,
2365
+ "updatedRows": 1
2366
+ },
2367
+ {
2368
+ "id": "{00000000-0001-0000-0100-000000000000}",
2369
+ "name": "Week 42"
2370
+ },
2371
+ {
2372
+ "teamsMessages": [
2373
+ {
2374
+ "id": "1729159200123",
2375
+ "from": "Jane Doe",
2376
+ "text": "Weekly report posted.",
2377
+ "createdAt": "2026-10-17T08:00:00.123Z",
2378
+ "webUrl": "https://teams.microsoft.com/l/message/19%3Aa1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6%40thread.tacv2/1729159200123?tenantId=3f2c9b1e-7d4a-4c6b-9e8f-0a1b2c3d4e5f",
2379
+ "replyCount": 2
2380
+ }
2381
+ ],
2382
+ "hasMore": false
1479
2383
  }
1480
2384
  ]
1481
2385
  }