@remit/api-openapi-spec 0.0.49 → 0.0.51

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 (2) hide show
  1. package/openapi.json +68 -8
  2. package/package.json +1 -1
package/openapi.json CHANGED
@@ -1367,7 +1367,7 @@
1367
1367
  "/addresses/{addressId}": {
1368
1368
  "patch": {
1369
1369
  "operationId": "AddressDetailOperations_updateAddress",
1370
- "description": "Update an address (currently: per-sender flags). Pass `flags: { <name>: null }` to remove a flag. Other flags are untouched.",
1370
+ "description": "Update an address (currently: per-sender flags). Pass `flags` to set flags and `clearFlags: [\"<name>\"]` to remove them. Other flags are untouched.",
1371
1371
  "parameters": [
1372
1372
  {
1373
1373
  "name": "addressId",
@@ -2764,6 +2764,7 @@
2764
2764
  "name": "query",
2765
2765
  "in": "query",
2766
2766
  "required": false,
2767
+ "description": "Free text to match against subject, From address and body text. Whitespace splits it into terms and every term must match, each against any one of the three. Body text is the stored preview the row carries — the first prose of the message with quoted replies removed — so a term further into a long message is not reached; a term the reader can see on the row is. Matching is accent- and case-insensitive substring, not tokenized full-text, so it neither stems nor ranks.",
2767
2768
  "schema": {
2768
2769
  "type": "string"
2769
2770
  }
@@ -2772,6 +2773,7 @@
2772
2773
  "name": "subject",
2773
2774
  "in": "query",
2774
2775
  "required": false,
2776
+ "description": "Match the subject alone, where `query` matches all three fields at once.",
2775
2777
  "schema": {
2776
2778
  "type": "string"
2777
2779
  }
@@ -2780,6 +2782,7 @@
2780
2782
  "name": "from",
2781
2783
  "in": "query",
2782
2784
  "required": false,
2785
+ "description": "Match the From address or display name alone, where `query` matches all three fields at once.",
2783
2786
  "schema": {
2784
2787
  "type": "string"
2785
2788
  }
@@ -4101,7 +4104,7 @@
4101
4104
  "/threads": {
4102
4105
  "get": {
4103
4106
  "operationId": "UnifiedThreadOperations_listAllThreads",
4104
- "description": "List threads across all non-muted accounts of the caller, ordered by sentDate desc. Each row carries an attached `accountId` (derived from a mailboxId→accountId map at read time) plus the usual `senderTrust` enrichment; `category` is served from the ThreadMessage row. Served by the `byDate` LSI1 (pk = the caller's account config), so the caller can never see another account config's threads.\n\nINBOX scope: results are filtered to each account's top-level INBOX, matched by exact path `fullPath === \"INBOX\"` (RFC 6154 defines no Inbox special-use). By design this excludes namespaced sub-paths like `INBOX/Receipts` and non-English server primaries — the unified inbox is each account's primary INBOX, not its sub-folders. Soft-deleted rows are also excluded.\n\nMute exclusion: muted accounts and muted mailboxes are excluded. The inbox/mute filter set is rebuilt per page from live state, so muting/unmuting a mailbox mid-pagination takes effect on the next page (never retroactively).\n\nPagination: pass the returned `continuationToken` to fetch the next page; keep paging until it is absent. In the default (INBOX) mode the INBOX/deleted filter is applied after the index read with a bounded read window per request, so a page may return FEWER than `limit` rows while still carrying a `continuationToken` — treat the presence of the token (not a full page) as the \"more results\" signal. No rows are skipped or duplicated across pages.\n\nStarred mode (`starred=true`): served by the `byStarred` LSI4 instead. A star is a marker on the mail rather than on its placement, so the INBOX scope does not apply and a starred thread in Archive is still returned. Excluded are muted and soft-deleted rows as usual, plus the folders a star never surfaces from: Junk, Trash, and Gmail's All Mail (a second copy of everything, whose rows would otherwise double every starred message). All filtering happens in the query, so a page is short only when the results are exhausted. Rows are per mailbox: the same mail filed in two folders is two rows sharing a `threadId`, and a client rendering one row per conversation collapses by `threadId` across the pages it has accumulated.\n\nSearch mode (`query=<text>`): the listing widens past the INBOX scope to every non-muted mailbox of every non-muted account, and returns only rows whose subject or From address matches the text. This is the unscoped search of the daily brief: one query reaching every folder of every account. Whitespace splits the text into terms and every term must match (AND), each against subject OR From. Matching is case-insensitive substring, not tokenized full-text, so it neither stems nor ranks.\n\nSearch scope: every non-muted mailbox EXCEPT Trash. The scope is defined by what it excludes, so anything a server offers that is not on that list is searched — Spam, Drafts and Gmail's virtual folders (All Mail, Starred, Important) included. Spam is deliberately in scope: the point of an unscoped search is that it reaches the folders the user did not think to look in. Combining `query` with `starred=true` searches the starred scope instead.\n\nDuplicates: a virtual folder holds a second copy of mail that also lives in a real folder, so a backend keying a row by its mailbox returns the same message several times — a starred, Important Gmail inbox message four times. The extras are dropped from the response by message identity, keeping the copy in a real folder, so one message is one row. This is done after the read rather than by barring those folders from the scope, because a message whose only stored row sits in one of them would otherwise become unfindable. De-duplication is per page: a duplicate split across a page boundary survives, the same caveat that applies to collapsing by `threadId`. A page may therefore return fewer rows than `limit` while still carrying a `continuationToken`.\n\nSearch mode and pagination: `limit` is a page size over MATCHES, capped server-side at 500. A page may be shorter than `limit` for two reasons — the matches ran out, or duplicates were dropped from it — so treat the presence of a `continuationToken` as the \"more results\" signal rather than a full page. There is no total match count; page until the token is absent.\n\nWhat a row is in search mode: one per message, not one per mailbox. This differs from the starred mode above, where the same mail filed in two folders is two rows sharing a `threadId`. Collapsing by `threadId` is still a client's job if it renders one row per CONVERSATION, since distinct messages in one thread remain distinct rows here.\n\nCallers that omit `query` are unaffected: the INBOX (and starred) listings behave exactly as before.\n\nRow filters: `category`, `unread` and `attachments` are columns on the ThreadMessage row, so each is a predicate inside the query rather than a pass over what a page returned. They compose with every mode above — INBOX, starred and search alike — and a page therefore comes back full of matches however rare the criterion is. This is what the cross-account collections need: filtering the pages a client happens to have loaded shows an empty list whenever the matching mail sits below the newest page (#308).\n\nCounting: `count=true` answers how many CONVERSATIONS match, over the whole scope and independent of `limit`. `results=false` omits the rows, which is how a header total is read without also paying for a page of mail. Conversations rather than rows because that is what this listing renders: a row is per mailbox, so the same mail filed in two folders is two rows sharing a `threadId`, and clients collapse by it. Counting rows would put a third number beside a list that shows a second one.",
4107
+ "description": "List threads across all non-muted accounts of the caller, ordered by sentDate desc. Each row carries an attached `accountId` (derived from a mailboxId→accountId map at read time) plus the usual `senderTrust` enrichment; `category` is served from the ThreadMessage row. Served by the `byDate` LSI1 (pk = the caller's account config), so the caller can never see another account config's threads.\n\nINBOX scope: results are filtered to each account's top-level INBOX, matched by exact path `fullPath === \"INBOX\"` (RFC 6154 defines no Inbox special-use). By design this excludes namespaced sub-paths like `INBOX/Receipts` and non-English server primaries — the unified inbox is each account's primary INBOX, not its sub-folders. Soft-deleted rows are also excluded.\n\nMute exclusion: muted accounts and muted mailboxes are excluded. The inbox/mute filter set is rebuilt per page from live state, so muting/unmuting a mailbox mid-pagination takes effect on the next page (never retroactively).\n\nPagination: pass the returned `continuationToken` to fetch the next page; keep paging until it is absent. In the default (INBOX) mode the INBOX/deleted filter is applied after the index read with a bounded read window per request, so a page may return FEWER than `limit` rows while still carrying a `continuationToken` — treat the presence of the token (not a full page) as the \"more results\" signal. No rows are skipped or duplicated across pages.\n\nStarred mode (`starred=true`): served by the `byStarred` LSI4 instead. A star is a marker on the mail rather than on its placement, so the INBOX scope does not apply and a starred thread in Archive is still returned. Excluded are muted and soft-deleted rows as usual, plus the folders a star never surfaces from: Junk, Trash, and Gmail's All Mail (a second copy of everything, whose rows would otherwise double every starred message). All filtering happens in the query, so a page is short only when the results are exhausted. Rows are per mailbox: the same mail filed in two folders is two rows sharing a `threadId`, and a client rendering one row per conversation collapses by `threadId` across the pages it has accumulated.\n\nSearch mode (`query=<text>`): the listing widens past the INBOX scope to every non-muted mailbox of every non-muted account, and returns only rows whose subject, From address or body text matches the text. This is the unscoped search of the daily brief: one query reaching every folder of every account. Whitespace splits the text into terms and every term must match (AND), each against subject OR From OR body. Matching is case-insensitive substring, not tokenized full-text, so it neither stems nor ranks.\n\nBody text is the stored preview the row carries — the first prose of the message with quoted replies removed, which is the same text the row renders under its subject. A term further into a long message is not reached; a term the reader can see on the row is.\n\nSearch scope: every non-muted mailbox EXCEPT Trash. The scope is defined by what it excludes, so anything a server offers that is not on that list is searched — Spam, Drafts and Gmail's virtual folders (All Mail, Starred, Important) included. Spam is deliberately in scope: the point of an unscoped search is that it reaches the folders the user did not think to look in. Combining `query` with `starred=true` searches the starred scope instead.\n\nDuplicates: a virtual folder holds a second copy of mail that also lives in a real folder, so a backend keying a row by its mailbox returns the same message several times — a starred, Important Gmail inbox message four times. The extras are dropped from the response by message identity, keeping the copy in a real folder, so one message is one row. This is done after the read rather than by barring those folders from the scope, because a message whose only stored row sits in one of them would otherwise become unfindable. De-duplication is per page: a duplicate split across a page boundary survives, the same caveat that applies to collapsing by `threadId`. A page may therefore return fewer rows than `limit` while still carrying a `continuationToken`.\n\nSearch mode and pagination: `limit` is a page size over MATCHES, capped server-side at 500. A page may be shorter than `limit` for two reasons — the matches ran out, or duplicates were dropped from it — so treat the presence of a `continuationToken` as the \"more results\" signal rather than a full page. There is no total match count; page until the token is absent.\n\nWhat a row is in search mode: one per message, not one per mailbox. This differs from the starred mode above, where the same mail filed in two folders is two rows sharing a `threadId`. Collapsing by `threadId` is still a client's job if it renders one row per CONVERSATION, since distinct messages in one thread remain distinct rows here.\n\nCallers that omit `query` are unaffected: the INBOX (and starred) listings behave exactly as before.\n\nRow filters: `category`, `unread` and `attachments` are columns on the ThreadMessage row, so each is a predicate inside the query rather than a pass over what a page returned. They compose with every mode above — INBOX, starred and search alike — and a page therefore comes back full of matches however rare the criterion is. This is what the cross-account collections need: filtering the pages a client happens to have loaded shows an empty list whenever the matching mail sits below the newest page (#308).\n\nField filters: `from` and `subject` each match one field, which the single `query` cannot express — it matches both at once. They compose with `query` and with each other as further AND terms.\n\nAccount scope: `accountId` narrows every mode to the mailboxes of one account. The scope is built from the account's own mailboxes, so the listing, the count and the search all answer over the same set. Without it the listing is the cross-account aggregate.\n\nMuted senders: `muted=false` excludes rows whose From address is muted, `muted=true` returns only those, and omitting it filters nothing. Muting is a property of the address rather than a column on the row, so this is the one predicate that reaches outside the ThreadMessage table; it applies to the listing and the `count` alike, which is what lets a caller that hides muted mail state a number that is the size of what it renders.\n\nCounting: `count=true` answers how many CONVERSATIONS match, over the whole scope and independent of `limit`. `results=false` omits the rows, which is how a header total is read without also paying for a page of mail. Conversations rather than rows because that is what this listing renders: a row is per mailbox, so the same mail filed in two folders is two rows sharing a `threadId`, and clients collapse by it. Counting rows would put a third number beside a list that shows a second one.",
4105
4108
  "parameters": [
4106
4109
  {
4107
4110
  "name": "continuationToken",
@@ -4141,11 +4144,47 @@
4141
4144
  "name": "query",
4142
4145
  "in": "query",
4143
4146
  "required": false,
4144
- "description": "Free text to match against subject and From address. Supplying it switches the listing into search mode, which widens the scope past INBOX to every non-muted mailbox — see the operation description. Omitting it leaves the listing unchanged.",
4147
+ "description": "Free text to match against subject, From address and body text. Supplying it switches the listing into search mode, which widens the scope past INBOX to every non-muted mailbox — see the operation description. Omitting it leaves the listing unchanged.",
4145
4148
  "schema": {
4146
4149
  "type": "string"
4147
4150
  }
4148
4151
  },
4152
+ {
4153
+ "name": "from",
4154
+ "in": "query",
4155
+ "required": false,
4156
+ "description": "Match the From address or display name against this text. One field, where `query` matches subject and From at once, so `from:` can be asked for on its own. Applied as a SQL predicate over the whole scope; it does not widen the scope the way `query` does.",
4157
+ "schema": {
4158
+ "type": "string"
4159
+ }
4160
+ },
4161
+ {
4162
+ "name": "subject",
4163
+ "in": "query",
4164
+ "required": false,
4165
+ "description": "Match the subject against this text. One field, where `query` matches subject and From at once, so `subject:` can be asked for on its own. Applied as a SQL predicate over the whole scope; it does not widen the scope the way `query` does.",
4166
+ "schema": {
4167
+ "type": "string"
4168
+ }
4169
+ },
4170
+ {
4171
+ "name": "accountId",
4172
+ "in": "query",
4173
+ "required": false,
4174
+ "description": "Narrow every mode to one account's mailboxes. The listing, the search and the `count` all read the same narrowed scope, so a count is the size of what the caller renders rather than of the cross-account aggregate. An account the caller does not own, or one that is muted, holds no mailboxes here and matches nothing.",
4175
+ "schema": {
4176
+ "$ref": "#/components/schemas/UUID"
4177
+ }
4178
+ },
4179
+ {
4180
+ "name": "muted",
4181
+ "in": "query",
4182
+ "required": false,
4183
+ "description": "Filter by whether the From address is muted. `false` excludes muted senders, `true` returns only them, and omitting it filters nothing. Muting lives on the Address rather than on the row, so this is evaluated against the sender's flags; it narrows the `count` exactly as it narrows the listing.",
4184
+ "schema": {
4185
+ "type": "boolean"
4186
+ }
4187
+ },
4149
4188
  {
4150
4189
  "name": "category",
4151
4190
  "in": "query",
@@ -4852,6 +4891,20 @@
4852
4891
  },
4853
4892
  "description": "Common metadata for sender-level flags"
4854
4893
  },
4894
+ "RemitImap.AddressFlagKey": {
4895
+ "type": "string",
4896
+ "enum": [
4897
+ "trusted",
4898
+ "blocked",
4899
+ "muted",
4900
+ "vip",
4901
+ "junkOnly",
4902
+ "category",
4903
+ "autoArchive",
4904
+ "unsubscribed"
4905
+ ],
4906
+ "description": "Names a key of `AddressFlags` that a client may address in `PATCH /addresses/{addressId}`. `wellknown` is deliberately absent: it is server-owned, derived from engagement counters, and is never written or removed by a client."
4907
+ },
4855
4908
  "RemitImap.AddressFlags": {
4856
4909
  "type": "object",
4857
4910
  "properties": {
@@ -7390,7 +7443,7 @@
7390
7443
  "$ref": "#/components/schemas/RemitImap.AddressFlagBase"
7391
7444
  }
7392
7445
  ],
7393
- "description": "Address was only ever seen on mail in a Junk folder: withheld from autocomplete suggestions until the account corresponds with it, flags it, or meets it on live mail. Written by sync and by the boot-time repair; clear it by patching this key to null."
7446
+ "description": "Address was only ever seen on mail in a Junk folder: withheld from autocomplete suggestions until the account corresponds with it, flags it, or meets it on live mail. Written by sync and by the boot-time repair; clear it by naming this key in `UpdateAddressInput.clearFlags`."
7394
7447
  },
7395
7448
  "RemitImap.JunkOnlyFlagUpdate": {
7396
7449
  "type": "object",
@@ -7404,7 +7457,7 @@
7404
7457
  "$ref": "#/components/schemas/RemitImap.AddressFlagBaseUpdate"
7405
7458
  }
7406
7459
  ],
7407
- "description": "Address was only ever seen on mail in a Junk folder: withheld from autocomplete suggestions until the account corresponds with it, flags it, or meets it on live mail. Written by sync and by the boot-time repair; clear it by patching this key to null."
7460
+ "description": "Address was only ever seen on mail in a Junk folder: withheld from autocomplete suggestions until the account corresponds with it, flags it, or meets it on live mail. Written by sync and by the boot-time repair; clear it by naming this key in `UpdateAddressInput.clearFlags`."
7408
7461
  },
7409
7462
  "RemitImap.LabelAction": {
7410
7463
  "type": "string",
@@ -10019,7 +10072,7 @@
10019
10072
  }
10020
10073
  ],
10021
10074
  "nullable": true,
10022
- "description": "Set to `null` to offer this address in autocomplete again"
10075
+ "description": "Name this key in `clearFlags` to offer the address in autocomplete again"
10023
10076
  },
10024
10077
  "category": {
10025
10078
  "type": "object",
@@ -10049,7 +10102,7 @@
10049
10102
  "nullable": true
10050
10103
  }
10051
10104
  },
10052
- "description": "Patch payload for a single AddressFlags entry. Pass `null` for a flag key to remove that flag while leaving the others untouched."
10105
+ "description": "Patch payload for AddressFlags entries. Sets the flags named here and leaves the others untouched. Removal travels in `UpdateAddressInput.clearFlags`, not here: the `null` alternative below is unreachable over OAS 3.0, where a nullable `$ref` emits as `allOf` and the request validator drops the `nullable` — and no `null` form exists at all for `category`, whose value is an enum with no false-equivalent member."
10053
10106
  },
10054
10107
  "RemitImap.UpdateAddressInput": {
10055
10108
  "type": "object",
@@ -10060,7 +10113,14 @@
10060
10113
  "$ref": "#/components/schemas/RemitImap.UpdateAddressFlagsInput"
10061
10114
  }
10062
10115
  ],
10063
- "description": "Per-flag merge update; omitted flags are untouched, `null` removes the flag"
10116
+ "description": "Per-flag merge update; omitted flags are untouched"
10117
+ },
10118
+ "clearFlags": {
10119
+ "type": "array",
10120
+ "items": {
10121
+ "$ref": "#/components/schemas/RemitImap.AddressFlagKey"
10122
+ },
10123
+ "description": "Flag keys to remove from the sparse map, leaving the rest untouched. This is the removal form for every flag, whatever its value type — clearing `category` reverts the sender to automatic classification. Applied after `flags`, so a key named in both ends up removed. Removing an absent flag succeeds and changes nothing."
10064
10124
  }
10065
10125
  },
10066
10126
  "description": "Input for updating an Address (currently flag updates only)"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remit/api-openapi-spec",
3
- "version": "0.0.49",
3
+ "version": "0.0.51",
4
4
  "description": "Remit API OpenAPI 3 document, generated from TypeSpec.",
5
5
  "exports": {
6
6
  ".": "./openapi.json",