featurebase-node 0.15.1 → 0.15.2

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 (81) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/client.d.mts +2 -2
  3. package/client.d.mts.map +1 -1
  4. package/client.d.ts +2 -2
  5. package/client.d.ts.map +1 -1
  6. package/client.js.map +1 -1
  7. package/client.mjs.map +1 -1
  8. package/package.json +1 -1
  9. package/resources/changelogs/changelogs.d.mts +1166 -6
  10. package/resources/changelogs/changelogs.d.mts.map +1 -1
  11. package/resources/changelogs/changelogs.d.ts +1166 -6
  12. package/resources/changelogs/changelogs.d.ts.map +1 -1
  13. package/resources/changelogs/changelogs.js +53 -3
  14. package/resources/changelogs/changelogs.js.map +1 -1
  15. package/resources/changelogs/changelogs.mjs +53 -3
  16. package/resources/changelogs/changelogs.mjs.map +1 -1
  17. package/resources/changelogs/index.d.mts +1 -1
  18. package/resources/changelogs/index.d.mts.map +1 -1
  19. package/resources/changelogs/index.d.ts +1 -1
  20. package/resources/changelogs/index.d.ts.map +1 -1
  21. package/resources/changelogs/index.js.map +1 -1
  22. package/resources/changelogs/index.mjs.map +1 -1
  23. package/resources/feedback/comments.d.mts +4 -2
  24. package/resources/feedback/comments.d.mts.map +1 -1
  25. package/resources/feedback/comments.d.ts +4 -2
  26. package/resources/feedback/comments.d.ts.map +1 -1
  27. package/resources/feedback/custom-fields.d.mts +12 -0
  28. package/resources/feedback/custom-fields.d.mts.map +1 -1
  29. package/resources/feedback/custom-fields.d.ts +12 -0
  30. package/resources/feedback/custom-fields.d.ts.map +1 -1
  31. package/resources/feedback/posts/index.d.mts +1 -0
  32. package/resources/feedback/posts/index.d.mts.map +1 -1
  33. package/resources/feedback/posts/index.d.ts +1 -0
  34. package/resources/feedback/posts/index.d.ts.map +1 -1
  35. package/resources/feedback/posts/index.js +3 -1
  36. package/resources/feedback/posts/index.js.map +1 -1
  37. package/resources/feedback/posts/index.mjs +1 -0
  38. package/resources/feedback/posts/index.mjs.map +1 -1
  39. package/resources/feedback/posts/insights.d.mts +254 -0
  40. package/resources/feedback/posts/insights.d.mts.map +1 -0
  41. package/resources/feedback/posts/insights.d.ts +254 -0
  42. package/resources/feedback/posts/insights.d.ts.map +1 -0
  43. package/resources/feedback/posts/insights.js +269 -0
  44. package/resources/feedback/posts/insights.js.map +1 -0
  45. package/resources/feedback/posts/insights.mjs +265 -0
  46. package/resources/feedback/posts/insights.mjs.map +1 -0
  47. package/resources/feedback/posts/posts.d.mts +647 -20
  48. package/resources/feedback/posts/posts.d.mts.map +1 -1
  49. package/resources/feedback/posts/posts.d.ts +647 -20
  50. package/resources/feedback/posts/posts.d.ts.map +1 -1
  51. package/resources/feedback/posts/posts.js +199 -7
  52. package/resources/feedback/posts/posts.js.map +1 -1
  53. package/resources/feedback/posts/posts.mjs +199 -7
  54. package/resources/feedback/posts/posts.mjs.map +1 -1
  55. package/resources/index.d.mts +1 -1
  56. package/resources/index.d.mts.map +1 -1
  57. package/resources/index.d.ts +1 -1
  58. package/resources/index.d.ts.map +1 -1
  59. package/resources/index.js.map +1 -1
  60. package/resources/index.mjs.map +1 -1
  61. package/resources/support/tickets/tickets.d.mts +9 -5
  62. package/resources/support/tickets/tickets.d.mts.map +1 -1
  63. package/resources/support/tickets/tickets.d.ts +9 -5
  64. package/resources/support/tickets/tickets.d.ts.map +1 -1
  65. package/resources/support/tickets/tickets.js.map +1 -1
  66. package/resources/support/tickets/tickets.mjs.map +1 -1
  67. package/src/client.ts +2 -0
  68. package/src/resources/changelogs/changelogs.ts +2003 -51
  69. package/src/resources/changelogs/index.ts +1 -0
  70. package/src/resources/feedback/comments.ts +4 -2
  71. package/src/resources/feedback/custom-fields.ts +15 -0
  72. package/src/resources/feedback/posts/index.ts +7 -0
  73. package/src/resources/feedback/posts/insights.ts +340 -0
  74. package/src/resources/feedback/posts/posts.ts +764 -20
  75. package/src/resources/index.ts +1 -0
  76. package/src/resources/support/tickets/tickets.ts +9 -5
  77. package/src/version.ts +1 -1
  78. package/version.d.mts +1 -1
  79. package/version.d.ts +1 -1
  80. package/version.js +1 -1
  81. package/version.mjs +1 -1
@@ -0,0 +1,254 @@
1
+ import { APIResource } from "../../../core/resource.mjs";
2
+ import * as PostsAPI from "./posts.mjs";
3
+ import { PostsCursorPage } from "./posts.mjs";
4
+ import { APIPromise } from "../../../core/api-promise.mjs";
5
+ import { type CursorPageParams, PagePromise } from "../../../core/pagination.mjs";
6
+ import { RequestOptions } from "../../../internal/request-options.mjs";
7
+ /**
8
+ * User-submitted feedback and feature requests. Posts belong to boards and can be upvoted, commented on, and tracked through statuses.
9
+ */
10
+ export declare class Insights extends APIResource {
11
+ /**
12
+ * Returns the insights filed under the request `{id}` — the customer quotes kept
13
+ * as evidence for it. Newest first.
14
+ *
15
+ * Posts linked with `attachTo` are **not** listed here: they are posts, not
16
+ * insights, and they stay in `GET /v2/posts`. This endpoint lists exactly the rows
17
+ * that `POST /v2/posts/{insightId}/link-insight` filed under this request.
18
+ *
19
+ * ### Query parameters
20
+ *
21
+ * - `limit` — insights per page, 1–100. **Defaults to 100**, so most requests
22
+ * return their whole evidence set in one call.
23
+ * - `cursor` — opaque cursor from a previous response's `nextCursor`.
24
+ *
25
+ * ### Response format
26
+ *
27
+ * The standard post list envelope:
28
+ *
29
+ * - `object` — always `"list"`
30
+ * - `data` — the insights, each in the same shape as any other post object, with
31
+ * `kind: 'insight'` and `linkedIssueId` set to `{id}`
32
+ * - `nextCursor` — pass it back as `cursor` for the next page; `null` on the last
33
+ * page
34
+ *
35
+ * `pagination` is never returned by this endpoint — it is cursor-paginated only.
36
+ *
37
+ * ### Notes
38
+ *
39
+ * - Pass the **request's** id, not an insight's. An id that is not a request (an
40
+ * insight, or an unknown id in this workspace) is not an error: the list simply
41
+ * comes back empty.
42
+ * - The insights returned are not readable through `GET /v2/posts/{insightId}` —
43
+ * that endpoint serves work items only.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * // Automatically fetches more pages as needed.
48
+ * for await (const post of client.feedback.posts.insights.list(
49
+ * '507f1f77bcf86cd799439011',
50
+ * )) {
51
+ * // ...
52
+ * }
53
+ * ```
54
+ */
55
+ list(id: string, params?: InsightListParams | null | undefined, options?: RequestOptions): PagePromise<PostsCursorPage, PostsAPI.Post>;
56
+ /**
57
+ * Promotes the insight `{id}` into a request of its own — the way back from
58
+ * `link-insight`.
59
+ *
60
+ * `kind` becomes `issue`, any link to another request is cleared (that request's
61
+ * `linkedInsightCount` is recounted), and the row is a post again:
62
+ * `GET /v2/posts/{id}` answers it, and `GET /v2/posts` lists it.
63
+ *
64
+ * The promoted request is given the workspace's default status if it had none, is
65
+ * filed on the internal board (its previous board is kept as the request's source
66
+ * category), and is created **hidden from the portal** — publish it with
67
+ * `PATCH /v2/posts/{id}` when you want customers to see it. It then announces
68
+ * itself like a freshly created request: the `post.created` webhook fires and the
69
+ * workspace's tracker integrations receive it, subject to the same rules as any
70
+ * other creation. Featurebase also looks for other existing insights that support
71
+ * the new request, in the background.
72
+ *
73
+ * Calling this on a post that is already a request is a no-op and returns it
74
+ * unchanged.
75
+ *
76
+ * ### Request
77
+ *
78
+ * No body. The insight is named by the path.
79
+ *
80
+ * ### Response
81
+ *
82
+ * The resulting request, in the standard post format.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const post =
87
+ * await client.feedback.posts.insights.convertToPost(
88
+ * '507f1f77bcf86cd799439011',
89
+ * );
90
+ * ```
91
+ */
92
+ convertToPost(id: string, params?: InsightConvertToPostParams | null | undefined, options?: RequestOptions): APIPromise<PostsAPI.Post>;
93
+ /**
94
+ * An **insight** is a customer's own words kept as evidence under a request — a
95
+ * quote, not a request of its own, and never returned by `GET /v2/posts`.
96
+ *
97
+ * This endpoint turns the post `{id}` into an insight under the request `issueId`.
98
+ * Use it for the sentence a customer actually said; use `attachTo` on
99
+ * `POST /v2/posts` when the thing you are filing is a request in its own right and
100
+ * should stay one.
101
+ *
102
+ * ### What changes
103
+ *
104
+ * - The post becomes an insight: `kind` is `insight` and `linkedIssueId` is the
105
+ * request.
106
+ * - **It leaves the posts resource.** `GET /v2/posts/{id}` answers `404` from then
107
+ * on, and it no longer appears in `GET /v2/posts`. Read it back through
108
+ * `GET /v2/posts/{issueId}/insights`, which is where it now lives.
109
+ * - Its author counts as a supporter of the request: the insight's upvoters are
110
+ * rolled onto the request (deduped by user, so a customer who had already voted
111
+ * is not counted twice) and the insight's author is subscribed to the request's
112
+ * updates. The request's `upvotes` goes up accordingly.
113
+ * - The request's `linkedInsightCount` is recounted from the live set of insights
114
+ * pointing at it.
115
+ *
116
+ * Linking again to the same request is a no-op and returns the insight unchanged.
117
+ *
118
+ * An insight that is already filed under a DIFFERENT request is MOVED — but only
119
+ * if nobody has confirmed that first link by hand. The old link is dropped first,
120
+ * and the old request is remembered as "not a match" so automatic matching never
121
+ * puts it back there. An insight whose link was already confirmed by a person
122
+ * (every link made through this endpoint counts as confirmed) is refused with
123
+ * `400 Insight is already linked to another issue. Detach it first.` — call
124
+ * `POST /v2/posts/{id}/unlink-insight` first, then link it where you want it.
125
+ *
126
+ * ### Which targets are refused
127
+ *
128
+ * - `404` — no post with `{id}` in this workspace, or one the API key cannot see
129
+ * (`Insight not found.`); no request with `issueId`, or one the API key cannot
130
+ * see (`Issue not found.`).
131
+ * - `400` — `issueId` equals `{id}` (a post cannot be linked to itself); the
132
+ * target is not a request (it is itself an insight, or a record — convert or
133
+ * restore it first); the target is a processed submission (`atomizedAt` — link
134
+ * to the requests that came out of it); the post being linked is a record (link
135
+ * the record's extracted insights instead); the post is already filed under
136
+ * another request by hand (unlink it first).
137
+ * - `400 invalid_id` — `{id}` or `issueId` is not a valid object id.
138
+ *
139
+ * A merged, held-for-moderation, spam-held or closed target is **not** refused
140
+ * here: those guards apply to automatic (AI) attachment only, and a person linking
141
+ * by hand is trusted to mean it.
142
+ *
143
+ * ### Response
144
+ *
145
+ * The updated insight, in the standard post format (`kind: 'insight'`,
146
+ * `linkedIssueId` set). The request it was linked to is not returned — fetch it
147
+ * with `GET /v2/posts/{issueId}` if you need its new `upvotes` and
148
+ * `linkedInsightCount`.
149
+ *
150
+ * ### Body
151
+ *
152
+ * - `issueId` — the request to file this post under. Required.
153
+ * - `linkSource` — deprecated and ignored; a link made through the API is always a
154
+ * manual link.
155
+ *
156
+ * ### Errors
157
+ *
158
+ * Failures raised by the insight service (404 / 400 / 409) are returned as
159
+ * `{ "code": <status>, "message": "..." }` rather than in the Stripe-style
160
+ * envelope the rest of this resource uses. The status code is the contract; do not
161
+ * parse the body shape.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * const post = await client.feedback.posts.insights.link(
166
+ * '507f1f77bcf86cd799439011',
167
+ * { issueId: '507f1f77bcf86cd799439011' },
168
+ * );
169
+ * ```
170
+ */
171
+ link(id: string, params: InsightLinkParams, options?: RequestOptions): APIPromise<PostsAPI.Post>;
172
+ /**
173
+ * Detaches the insight `{id}` from the request it was filed under.
174
+ *
175
+ * **The row stays an insight** — the customer's words do not disappear, they just
176
+ * return to the unlinked pool. `linkedIssueId` becomes `null`, and
177
+ * `GET /v2/posts/{id}` still answers `404`: an unlinked insight is still not a
178
+ * post. To get a post back, call `POST /v2/posts/{id}/convert-to-issue`.
179
+ *
180
+ * ### What does NOT change
181
+ *
182
+ * The votes this insight rolled onto the request are **not** taken back, and the
183
+ * author stays subscribed to it. They are real demand that was expressed, and the
184
+ * roll-up was deduplicated against votes the customer may have cast independently
185
+ * — unwinding it would remove votes it never created. The request's `upvotes`
186
+ * therefore stays where the link left it. Its `linkedInsightCount` IS recounted
187
+ * and goes down.
188
+ *
189
+ * The request that was just unlinked is remembered as "not a match" for this
190
+ * insight, so automatic matching never files it there again.
191
+ *
192
+ * Calling this on a post that is not an insight, or on an insight that is already
193
+ * unlinked, is a no-op and returns the row unchanged.
194
+ *
195
+ * ### Request
196
+ *
197
+ * No body. The insight is named by the path.
198
+ *
199
+ * ### Response
200
+ *
201
+ * The updated insight, in the standard post format.
202
+ *
203
+ * @example
204
+ * ```ts
205
+ * const post = await client.feedback.posts.insights.unlink(
206
+ * '507f1f77bcf86cd799439011',
207
+ * );
208
+ * ```
209
+ */
210
+ unlink(id: string, params?: InsightUnlinkParams | null | undefined, options?: RequestOptions): APIPromise<PostsAPI.Post>;
211
+ }
212
+ export interface InsightListParams extends CursorPageParams {
213
+ /**
214
+ * Header param: API version for this request. Defaults to your organization's
215
+ * configured API version if not specified.
216
+ */
217
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
218
+ }
219
+ export interface InsightConvertToPostParams {
220
+ /**
221
+ * API version for this request. Defaults to your organization's configured API
222
+ * version if not specified.
223
+ */
224
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
225
+ }
226
+ export interface InsightLinkParams {
227
+ /**
228
+ * Body param: ID of the request this post becomes evidence for. Must be a request
229
+ * in this workspace that can still take evidence.
230
+ */
231
+ issueId: string;
232
+ /**
233
+ * @deprecated Body param: Deprecated and ignored. A link made through the API is
234
+ * always recorded as a manual link.
235
+ */
236
+ linkSource?: 'manual' | 'ai';
237
+ /**
238
+ * Header param: API version for this request. Defaults to your organization's
239
+ * configured API version if not specified.
240
+ */
241
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
242
+ }
243
+ export interface InsightUnlinkParams {
244
+ /**
245
+ * API version for this request. Defaults to your organization's configured API
246
+ * version if not specified.
247
+ */
248
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
249
+ }
250
+ export declare namespace Insights {
251
+ export { type InsightListParams as InsightListParams, type InsightConvertToPostParams as InsightConvertToPostParams, type InsightLinkParams as InsightLinkParams, type InsightUnlinkParams as InsightUnlinkParams, };
252
+ }
253
+ export { type PostsCursorPage };
254
+ //# sourceMappingURL=insights.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.d.mts","sourceRoot":"","sources":["../../../src/resources/feedback/posts/insights.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,mCAA+B;AACrD,OAAO,KAAK,QAAQ,oBAAgB;AACpC,OAAO,EAAE,eAAe,EAAE,oBAAgB;AAC1C,OAAO,EAAE,UAAU,EAAE,sCAAkC;AACvD,OAAO,EAAc,KAAK,gBAAgB,EAAE,WAAW,EAAE,qCAAiC;AAE1F,OAAO,EAAE,cAAc,EAAE,8CAA0C;AAGnE;;GAEG;AACH,qBAAa,QAAS,SAAQ,WAAW;IACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;IACH,IAAI,CACF,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,iBAAiB,GAAG,IAAI,GAAG,SAAc,EACjD,OAAO,CAAC,EAAE,cAAc,GACvB,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC;IAgB9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,0BAA0B,GAAG,IAAI,GAAG,SAAc,EAC1D,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;IAe5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6EG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;IAgBhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACH,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,mBAAmB,GAAG,IAAI,GAAG,SAAc,EACnD,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;CAc7B;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,CAAC,OAAO,WAAW,QAAQ,CAAC;IAChC,OAAO,EACL,KAAK,iBAAiB,IAAI,iBAAiB,EAC3C,KAAK,0BAA0B,IAAI,0BAA0B,EAC7D,KAAK,iBAAiB,IAAI,iBAAiB,EAC3C,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH;AAED,OAAO,EAAE,KAAK,eAAe,EAAE,CAAC"}
@@ -0,0 +1,254 @@
1
+ import { APIResource } from "../../../core/resource.js";
2
+ import * as PostsAPI from "./posts.js";
3
+ import { PostsCursorPage } from "./posts.js";
4
+ import { APIPromise } from "../../../core/api-promise.js";
5
+ import { type CursorPageParams, PagePromise } from "../../../core/pagination.js";
6
+ import { RequestOptions } from "../../../internal/request-options.js";
7
+ /**
8
+ * User-submitted feedback and feature requests. Posts belong to boards and can be upvoted, commented on, and tracked through statuses.
9
+ */
10
+ export declare class Insights extends APIResource {
11
+ /**
12
+ * Returns the insights filed under the request `{id}` — the customer quotes kept
13
+ * as evidence for it. Newest first.
14
+ *
15
+ * Posts linked with `attachTo` are **not** listed here: they are posts, not
16
+ * insights, and they stay in `GET /v2/posts`. This endpoint lists exactly the rows
17
+ * that `POST /v2/posts/{insightId}/link-insight` filed under this request.
18
+ *
19
+ * ### Query parameters
20
+ *
21
+ * - `limit` — insights per page, 1–100. **Defaults to 100**, so most requests
22
+ * return their whole evidence set in one call.
23
+ * - `cursor` — opaque cursor from a previous response's `nextCursor`.
24
+ *
25
+ * ### Response format
26
+ *
27
+ * The standard post list envelope:
28
+ *
29
+ * - `object` — always `"list"`
30
+ * - `data` — the insights, each in the same shape as any other post object, with
31
+ * `kind: 'insight'` and `linkedIssueId` set to `{id}`
32
+ * - `nextCursor` — pass it back as `cursor` for the next page; `null` on the last
33
+ * page
34
+ *
35
+ * `pagination` is never returned by this endpoint — it is cursor-paginated only.
36
+ *
37
+ * ### Notes
38
+ *
39
+ * - Pass the **request's** id, not an insight's. An id that is not a request (an
40
+ * insight, or an unknown id in this workspace) is not an error: the list simply
41
+ * comes back empty.
42
+ * - The insights returned are not readable through `GET /v2/posts/{insightId}` —
43
+ * that endpoint serves work items only.
44
+ *
45
+ * @example
46
+ * ```ts
47
+ * // Automatically fetches more pages as needed.
48
+ * for await (const post of client.feedback.posts.insights.list(
49
+ * '507f1f77bcf86cd799439011',
50
+ * )) {
51
+ * // ...
52
+ * }
53
+ * ```
54
+ */
55
+ list(id: string, params?: InsightListParams | null | undefined, options?: RequestOptions): PagePromise<PostsCursorPage, PostsAPI.Post>;
56
+ /**
57
+ * Promotes the insight `{id}` into a request of its own — the way back from
58
+ * `link-insight`.
59
+ *
60
+ * `kind` becomes `issue`, any link to another request is cleared (that request's
61
+ * `linkedInsightCount` is recounted), and the row is a post again:
62
+ * `GET /v2/posts/{id}` answers it, and `GET /v2/posts` lists it.
63
+ *
64
+ * The promoted request is given the workspace's default status if it had none, is
65
+ * filed on the internal board (its previous board is kept as the request's source
66
+ * category), and is created **hidden from the portal** — publish it with
67
+ * `PATCH /v2/posts/{id}` when you want customers to see it. It then announces
68
+ * itself like a freshly created request: the `post.created` webhook fires and the
69
+ * workspace's tracker integrations receive it, subject to the same rules as any
70
+ * other creation. Featurebase also looks for other existing insights that support
71
+ * the new request, in the background.
72
+ *
73
+ * Calling this on a post that is already a request is a no-op and returns it
74
+ * unchanged.
75
+ *
76
+ * ### Request
77
+ *
78
+ * No body. The insight is named by the path.
79
+ *
80
+ * ### Response
81
+ *
82
+ * The resulting request, in the standard post format.
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * const post =
87
+ * await client.feedback.posts.insights.convertToPost(
88
+ * '507f1f77bcf86cd799439011',
89
+ * );
90
+ * ```
91
+ */
92
+ convertToPost(id: string, params?: InsightConvertToPostParams | null | undefined, options?: RequestOptions): APIPromise<PostsAPI.Post>;
93
+ /**
94
+ * An **insight** is a customer's own words kept as evidence under a request — a
95
+ * quote, not a request of its own, and never returned by `GET /v2/posts`.
96
+ *
97
+ * This endpoint turns the post `{id}` into an insight under the request `issueId`.
98
+ * Use it for the sentence a customer actually said; use `attachTo` on
99
+ * `POST /v2/posts` when the thing you are filing is a request in its own right and
100
+ * should stay one.
101
+ *
102
+ * ### What changes
103
+ *
104
+ * - The post becomes an insight: `kind` is `insight` and `linkedIssueId` is the
105
+ * request.
106
+ * - **It leaves the posts resource.** `GET /v2/posts/{id}` answers `404` from then
107
+ * on, and it no longer appears in `GET /v2/posts`. Read it back through
108
+ * `GET /v2/posts/{issueId}/insights`, which is where it now lives.
109
+ * - Its author counts as a supporter of the request: the insight's upvoters are
110
+ * rolled onto the request (deduped by user, so a customer who had already voted
111
+ * is not counted twice) and the insight's author is subscribed to the request's
112
+ * updates. The request's `upvotes` goes up accordingly.
113
+ * - The request's `linkedInsightCount` is recounted from the live set of insights
114
+ * pointing at it.
115
+ *
116
+ * Linking again to the same request is a no-op and returns the insight unchanged.
117
+ *
118
+ * An insight that is already filed under a DIFFERENT request is MOVED — but only
119
+ * if nobody has confirmed that first link by hand. The old link is dropped first,
120
+ * and the old request is remembered as "not a match" so automatic matching never
121
+ * puts it back there. An insight whose link was already confirmed by a person
122
+ * (every link made through this endpoint counts as confirmed) is refused with
123
+ * `400 Insight is already linked to another issue. Detach it first.` — call
124
+ * `POST /v2/posts/{id}/unlink-insight` first, then link it where you want it.
125
+ *
126
+ * ### Which targets are refused
127
+ *
128
+ * - `404` — no post with `{id}` in this workspace, or one the API key cannot see
129
+ * (`Insight not found.`); no request with `issueId`, or one the API key cannot
130
+ * see (`Issue not found.`).
131
+ * - `400` — `issueId` equals `{id}` (a post cannot be linked to itself); the
132
+ * target is not a request (it is itself an insight, or a record — convert or
133
+ * restore it first); the target is a processed submission (`atomizedAt` — link
134
+ * to the requests that came out of it); the post being linked is a record (link
135
+ * the record's extracted insights instead); the post is already filed under
136
+ * another request by hand (unlink it first).
137
+ * - `400 invalid_id` — `{id}` or `issueId` is not a valid object id.
138
+ *
139
+ * A merged, held-for-moderation, spam-held or closed target is **not** refused
140
+ * here: those guards apply to automatic (AI) attachment only, and a person linking
141
+ * by hand is trusted to mean it.
142
+ *
143
+ * ### Response
144
+ *
145
+ * The updated insight, in the standard post format (`kind: 'insight'`,
146
+ * `linkedIssueId` set). The request it was linked to is not returned — fetch it
147
+ * with `GET /v2/posts/{issueId}` if you need its new `upvotes` and
148
+ * `linkedInsightCount`.
149
+ *
150
+ * ### Body
151
+ *
152
+ * - `issueId` — the request to file this post under. Required.
153
+ * - `linkSource` — deprecated and ignored; a link made through the API is always a
154
+ * manual link.
155
+ *
156
+ * ### Errors
157
+ *
158
+ * Failures raised by the insight service (404 / 400 / 409) are returned as
159
+ * `{ "code": <status>, "message": "..." }` rather than in the Stripe-style
160
+ * envelope the rest of this resource uses. The status code is the contract; do not
161
+ * parse the body shape.
162
+ *
163
+ * @example
164
+ * ```ts
165
+ * const post = await client.feedback.posts.insights.link(
166
+ * '507f1f77bcf86cd799439011',
167
+ * { issueId: '507f1f77bcf86cd799439011' },
168
+ * );
169
+ * ```
170
+ */
171
+ link(id: string, params: InsightLinkParams, options?: RequestOptions): APIPromise<PostsAPI.Post>;
172
+ /**
173
+ * Detaches the insight `{id}` from the request it was filed under.
174
+ *
175
+ * **The row stays an insight** — the customer's words do not disappear, they just
176
+ * return to the unlinked pool. `linkedIssueId` becomes `null`, and
177
+ * `GET /v2/posts/{id}` still answers `404`: an unlinked insight is still not a
178
+ * post. To get a post back, call `POST /v2/posts/{id}/convert-to-issue`.
179
+ *
180
+ * ### What does NOT change
181
+ *
182
+ * The votes this insight rolled onto the request are **not** taken back, and the
183
+ * author stays subscribed to it. They are real demand that was expressed, and the
184
+ * roll-up was deduplicated against votes the customer may have cast independently
185
+ * — unwinding it would remove votes it never created. The request's `upvotes`
186
+ * therefore stays where the link left it. Its `linkedInsightCount` IS recounted
187
+ * and goes down.
188
+ *
189
+ * The request that was just unlinked is remembered as "not a match" for this
190
+ * insight, so automatic matching never files it there again.
191
+ *
192
+ * Calling this on a post that is not an insight, or on an insight that is already
193
+ * unlinked, is a no-op and returns the row unchanged.
194
+ *
195
+ * ### Request
196
+ *
197
+ * No body. The insight is named by the path.
198
+ *
199
+ * ### Response
200
+ *
201
+ * The updated insight, in the standard post format.
202
+ *
203
+ * @example
204
+ * ```ts
205
+ * const post = await client.feedback.posts.insights.unlink(
206
+ * '507f1f77bcf86cd799439011',
207
+ * );
208
+ * ```
209
+ */
210
+ unlink(id: string, params?: InsightUnlinkParams | null | undefined, options?: RequestOptions): APIPromise<PostsAPI.Post>;
211
+ }
212
+ export interface InsightListParams extends CursorPageParams {
213
+ /**
214
+ * Header param: API version for this request. Defaults to your organization's
215
+ * configured API version if not specified.
216
+ */
217
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
218
+ }
219
+ export interface InsightConvertToPostParams {
220
+ /**
221
+ * API version for this request. Defaults to your organization's configured API
222
+ * version if not specified.
223
+ */
224
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
225
+ }
226
+ export interface InsightLinkParams {
227
+ /**
228
+ * Body param: ID of the request this post becomes evidence for. Must be a request
229
+ * in this workspace that can still take evidence.
230
+ */
231
+ issueId: string;
232
+ /**
233
+ * @deprecated Body param: Deprecated and ignored. A link made through the API is
234
+ * always recorded as a manual link.
235
+ */
236
+ linkSource?: 'manual' | 'ai';
237
+ /**
238
+ * Header param: API version for this request. Defaults to your organization's
239
+ * configured API version if not specified.
240
+ */
241
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
242
+ }
243
+ export interface InsightUnlinkParams {
244
+ /**
245
+ * API version for this request. Defaults to your organization's configured API
246
+ * version if not specified.
247
+ */
248
+ 'Featurebase-Version'?: '2026-08-19.orbit' | '2026-01-01.nova' | '2025-12-12.clover';
249
+ }
250
+ export declare namespace Insights {
251
+ export { type InsightListParams as InsightListParams, type InsightConvertToPostParams as InsightConvertToPostParams, type InsightLinkParams as InsightLinkParams, type InsightUnlinkParams as InsightUnlinkParams, };
252
+ }
253
+ export { type PostsCursorPage };
254
+ //# sourceMappingURL=insights.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"insights.d.ts","sourceRoot":"","sources":["../../../src/resources/feedback/posts/insights.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,kCAA+B;AACrD,OAAO,KAAK,QAAQ,mBAAgB;AACpC,OAAO,EAAE,eAAe,EAAE,mBAAgB;AAC1C,OAAO,EAAE,UAAU,EAAE,qCAAkC;AACvD,OAAO,EAAc,KAAK,gBAAgB,EAAE,WAAW,EAAE,oCAAiC;AAE1F,OAAO,EAAE,cAAc,EAAE,6CAA0C;AAGnE;;GAEG;AACH,qBAAa,QAAS,SAAQ,WAAW;IACvC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2CG;IACH,IAAI,CACF,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,iBAAiB,GAAG,IAAI,GAAG,SAAc,EACjD,OAAO,CAAC,EAAE,cAAc,GACvB,WAAW,CAAC,eAAe,EAAE,QAAQ,CAAC,IAAI,CAAC;IAgB9C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAmCG;IACH,aAAa,CACX,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,0BAA0B,GAAG,IAAI,GAAG,SAAc,EAC1D,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;IAe5B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6EG;IACH,IAAI,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;IAgBhG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OAqCG;IACH,MAAM,CACJ,EAAE,EAAE,MAAM,EACV,MAAM,GAAE,mBAAmB,GAAG,IAAI,GAAG,SAAc,EACnD,OAAO,CAAC,EAAE,cAAc,GACvB,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC;CAc7B;AAED,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,0BAA0B;IACzC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,IAAI,CAAC;IAE7B;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,qBAAqB,CAAC,EAAE,kBAAkB,GAAG,iBAAiB,GAAG,mBAAmB,CAAC;CACtF;AAED,MAAM,CAAC,OAAO,WAAW,QAAQ,CAAC;IAChC,OAAO,EACL,KAAK,iBAAiB,IAAI,iBAAiB,EAC3C,KAAK,0BAA0B,IAAI,0BAA0B,EAC7D,KAAK,iBAAiB,IAAI,iBAAiB,EAC3C,KAAK,mBAAmB,IAAI,mBAAmB,GAChD,CAAC;CACH;AAED,OAAO,EAAE,KAAK,eAAe,EAAE,CAAC"}