@getlatedev/node 0.1.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.
@@ -0,0 +1,1430 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import { createClient, createConfig, type OptionsLegacyParser, formDataBodySerializer } from '@hey-api/client-fetch';
4
+ import type { GetV1ToolsYoutubeDownloadData, GetV1ToolsYoutubeDownloadError, GetV1ToolsYoutubeDownloadResponse, GetV1ToolsYoutubeTranscriptData, GetV1ToolsYoutubeTranscriptError, GetV1ToolsYoutubeTranscriptResponse, GetV1ToolsInstagramDownloadData, GetV1ToolsInstagramDownloadError, GetV1ToolsInstagramDownloadResponse, PostV1ToolsInstagramHashtagCheckerData, PostV1ToolsInstagramHashtagCheckerError, PostV1ToolsInstagramHashtagCheckerResponse, GetV1ToolsTiktokDownloadData, GetV1ToolsTiktokDownloadError, GetV1ToolsTiktokDownloadResponse, GetV1ToolsTwitterDownloadData, GetV1ToolsTwitterDownloadError, GetV1ToolsTwitterDownloadResponse, GetV1ToolsFacebookDownloadData, GetV1ToolsFacebookDownloadError, GetV1ToolsFacebookDownloadResponse, GetV1ToolsLinkedinDownloadData, GetV1ToolsLinkedinDownloadError, GetV1ToolsLinkedinDownloadResponse, GetV1ToolsBlueskyDownloadData, GetV1ToolsBlueskyDownloadError, GetV1ToolsBlueskyDownloadResponse, GetV1AnalyticsData, GetV1AnalyticsError, GetV1AnalyticsResponse, GetV1AnalyticsYoutubeDailyViewsData, GetV1AnalyticsYoutubeDailyViewsError, GetV1AnalyticsYoutubeDailyViewsResponse, GetV1AccountGroupsError, GetV1AccountGroupsResponse, PostV1AccountGroupsData, PostV1AccountGroupsError, PostV1AccountGroupsResponse, PutV1AccountGroupsByGroupIdData, PutV1AccountGroupsByGroupIdError, PutV1AccountGroupsByGroupIdResponse, DeleteV1AccountGroupsByGroupIdData, DeleteV1AccountGroupsByGroupIdError, DeleteV1AccountGroupsByGroupIdResponse, PostV1MediaPresignData, PostV1MediaPresignError, PostV1MediaPresignResponse, GetV1RedditSearchData, GetV1RedditSearchError, GetV1RedditSearchResponse, GetV1RedditFeedData, GetV1RedditFeedError, GetV1RedditFeedResponse, GetV1UsageStatsError, GetV1UsageStatsResponse, GetV1PostsData, GetV1PostsError, GetV1PostsResponse, PostV1PostsData, PostV1PostsError, PostV1PostsResponse, GetV1PostsByPostIdData, GetV1PostsByPostIdError, GetV1PostsByPostIdResponse, PutV1PostsByPostIdData, PutV1PostsByPostIdError, PutV1PostsByPostIdResponse, DeleteV1PostsByPostIdData, DeleteV1PostsByPostIdError, DeleteV1PostsByPostIdResponse, PostV1PostsBulkUploadData, PostV1PostsBulkUploadError, PostV1PostsBulkUploadResponse, PostV1PostsByPostIdRetryData, PostV1PostsByPostIdRetryError, PostV1PostsByPostIdRetryResponse, GetV1UsersError, GetV1UsersResponse, GetV1UsersByUserIdData, GetV1UsersByUserIdError, GetV1UsersByUserIdResponse, GetV1ProfilesData, GetV1ProfilesError, GetV1ProfilesResponse, PostV1ProfilesData, PostV1ProfilesError, PostV1ProfilesResponse, GetV1ProfilesByProfileIdData, GetV1ProfilesByProfileIdError, GetV1ProfilesByProfileIdResponse, PutV1ProfilesByProfileIdData, PutV1ProfilesByProfileIdError, PutV1ProfilesByProfileIdResponse, DeleteV1ProfilesByProfileIdData, DeleteV1ProfilesByProfileIdError, DeleteV1ProfilesByProfileIdResponse, GetV1AccountsData, GetV1AccountsError, GetV1AccountsResponse, GetV1AccountsFollowerStatsData, GetV1AccountsFollowerStatsError, GetV1AccountsFollowerStatsResponse, PutV1AccountsByAccountIdData, PutV1AccountsByAccountIdError, PutV1AccountsByAccountIdResponse, DeleteV1AccountsByAccountIdData, DeleteV1AccountsByAccountIdError, DeleteV1AccountsByAccountIdResponse, GetV1AccountsHealthData, GetV1AccountsHealthError, GetV1AccountsHealthResponse, GetV1AccountsByAccountIdHealthData, GetV1AccountsByAccountIdHealthError, GetV1AccountsByAccountIdHealthResponse, GetV1ApiKeysError, GetV1ApiKeysResponse, PostV1ApiKeysData, PostV1ApiKeysError, PostV1ApiKeysResponse, DeleteV1ApiKeysByKeyIdData, DeleteV1ApiKeysByKeyIdError, DeleteV1ApiKeysByKeyIdResponse, PostV1InviteTokensData, PostV1InviteTokensError, PostV1InviteTokensResponse, GetV1PlatformInvitesData, GetV1PlatformInvitesError, GetV1PlatformInvitesResponse, PostV1PlatformInvitesData, PostV1PlatformInvitesError, PostV1PlatformInvitesResponse, DeleteV1PlatformInvitesData, DeleteV1PlatformInvitesError, DeleteV1PlatformInvitesResponse, GetV1ConnectByPlatformData, GetV1ConnectByPlatformError, GetV1ConnectByPlatformResponse, PostV1ConnectByPlatformData, PostV1ConnectByPlatformError, PostV1ConnectByPlatformResponse, GetV1ConnectFacebookSelectPageData, GetV1ConnectFacebookSelectPageError, GetV1ConnectFacebookSelectPageResponse, PostV1ConnectFacebookSelectPageData, PostV1ConnectFacebookSelectPageError, PostV1ConnectFacebookSelectPageResponse, GetV1ConnectGooglebusinessLocationsData, GetV1ConnectGooglebusinessLocationsError, GetV1ConnectGooglebusinessLocationsResponse, PostV1ConnectGooglebusinessSelectLocationData, PostV1ConnectGooglebusinessSelectLocationError, PostV1ConnectGooglebusinessSelectLocationResponse, GetV1AccountsByAccountIdGmbReviewsData, GetV1AccountsByAccountIdGmbReviewsError, GetV1AccountsByAccountIdGmbReviewsResponse, GetV1ConnectLinkedinOrganizationsData, GetV1ConnectLinkedinOrganizationsError, GetV1ConnectLinkedinOrganizationsResponse, PostV1ConnectLinkedinSelectOrganizationData, PostV1ConnectLinkedinSelectOrganizationError, PostV1ConnectLinkedinSelectOrganizationResponse, GetV1ConnectPinterestSelectBoardData, GetV1ConnectPinterestSelectBoardError, GetV1ConnectPinterestSelectBoardResponse, PostV1ConnectPinterestSelectBoardData, PostV1ConnectPinterestSelectBoardError, PostV1ConnectPinterestSelectBoardResponse, GetV1ConnectSnapchatSelectProfileData, GetV1ConnectSnapchatSelectProfileError, GetV1ConnectSnapchatSelectProfileResponse, PostV1ConnectSnapchatSelectProfileData, PostV1ConnectSnapchatSelectProfileError, PostV1ConnectSnapchatSelectProfileResponse, PostV1ConnectBlueskyCredentialsData, PostV1ConnectBlueskyCredentialsError, PostV1ConnectBlueskyCredentialsResponse, GetV1ConnectTelegramData, GetV1ConnectTelegramError, GetV1ConnectTelegramResponse, PostV1ConnectTelegramData, PostV1ConnectTelegramError, PostV1ConnectTelegramResponse, PatchV1ConnectTelegramData, PatchV1ConnectTelegramError, PatchV1ConnectTelegramResponse, PutV1AccountsByAccountIdFacebookPageData, PutV1AccountsByAccountIdFacebookPageError, PutV1AccountsByAccountIdFacebookPageResponse, GetV1AccountsByAccountIdLinkedinOrganizationsData, GetV1AccountsByAccountIdLinkedinOrganizationsError, GetV1AccountsByAccountIdLinkedinOrganizationsResponse, GetV1AccountsByAccountIdLinkedinAggregateAnalyticsData, GetV1AccountsByAccountIdLinkedinAggregateAnalyticsError, GetV1AccountsByAccountIdLinkedinAggregateAnalyticsResponse, GetV1AccountsByAccountIdLinkedinPostAnalyticsData, GetV1AccountsByAccountIdLinkedinPostAnalyticsError, GetV1AccountsByAccountIdLinkedinPostAnalyticsResponse, PutV1AccountsByAccountIdLinkedinOrganizationData, PutV1AccountsByAccountIdLinkedinOrganizationError, PutV1AccountsByAccountIdLinkedinOrganizationResponse, GetV1AccountsByAccountIdLinkedinMentionsData, GetV1AccountsByAccountIdLinkedinMentionsError, GetV1AccountsByAccountIdLinkedinMentionsResponse, GetV1AccountsByAccountIdPinterestBoardsData, GetV1AccountsByAccountIdPinterestBoardsError, GetV1AccountsByAccountIdPinterestBoardsResponse, PutV1AccountsByAccountIdPinterestBoardsData, PutV1AccountsByAccountIdPinterestBoardsError, PutV1AccountsByAccountIdPinterestBoardsResponse, GetV1AccountsByAccountIdRedditSubredditsData, GetV1AccountsByAccountIdRedditSubredditsError, GetV1AccountsByAccountIdRedditSubredditsResponse, PutV1AccountsByAccountIdRedditSubredditsData, PutV1AccountsByAccountIdRedditSubredditsError, PutV1AccountsByAccountIdRedditSubredditsResponse, GetV1QueueSlotsData, GetV1QueueSlotsError, GetV1QueueSlotsResponse, PostV1QueueSlotsData, PostV1QueueSlotsError, PostV1QueueSlotsResponse, PutV1QueueSlotsData, PutV1QueueSlotsError, PutV1QueueSlotsResponse, DeleteV1QueueSlotsData, DeleteV1QueueSlotsError, DeleteV1QueueSlotsResponse, GetV1QueuePreviewData, GetV1QueuePreviewError, GetV1QueuePreviewResponse, GetV1QueueNextSlotData, GetV1QueueNextSlotError, GetV1QueueNextSlotResponse, GetV1WebhooksSettingsError, GetV1WebhooksSettingsResponse, PostV1WebhooksSettingsData, PostV1WebhooksSettingsError, PostV1WebhooksSettingsResponse, PutV1WebhooksSettingsData, PutV1WebhooksSettingsError, PutV1WebhooksSettingsResponse, DeleteV1WebhooksSettingsData, DeleteV1WebhooksSettingsError, DeleteV1WebhooksSettingsResponse, PostV1WebhooksTestData, PostV1WebhooksTestError, PostV1WebhooksTestResponse, GetV1WebhooksLogsData, GetV1WebhooksLogsError, GetV1WebhooksLogsResponse, GetV1LogsData, GetV1LogsError, GetV1LogsResponse, GetV1LogsByLogIdData, GetV1LogsByLogIdError, GetV1LogsByLogIdResponse, GetV1PostsByPostIdLogsData, GetV1PostsByPostIdLogsError, GetV1PostsByPostIdLogsResponse } from './types.gen';
5
+
6
+ export const client = createClient(createConfig());
7
+
8
+ /**
9
+ * Download YouTube video or audio
10
+ * Download YouTube videos or audio. Returns available formats or direct download URL.
11
+ *
12
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
13
+ *
14
+ */
15
+ export const getV1ToolsYoutubeDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsYoutubeDownloadData, ThrowOnError>) => {
16
+ return (options?.client ?? client).get<GetV1ToolsYoutubeDownloadResponse, GetV1ToolsYoutubeDownloadError, ThrowOnError>({
17
+ ...options,
18
+ url: '/v1/tools/youtube/download'
19
+ });
20
+ };
21
+
22
+ /**
23
+ * Get YouTube video transcript
24
+ * Extract transcript/captions from a YouTube video.
25
+ *
26
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
27
+ *
28
+ */
29
+ export const getV1ToolsYoutubeTranscript = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsYoutubeTranscriptData, ThrowOnError>) => {
30
+ return (options?.client ?? client).get<GetV1ToolsYoutubeTranscriptResponse, GetV1ToolsYoutubeTranscriptError, ThrowOnError>({
31
+ ...options,
32
+ url: '/v1/tools/youtube/transcript'
33
+ });
34
+ };
35
+
36
+ /**
37
+ * Download Instagram reel or post
38
+ * Download Instagram reels, posts, or photos.
39
+ *
40
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
41
+ *
42
+ */
43
+ export const getV1ToolsInstagramDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsInstagramDownloadData, ThrowOnError>) => {
44
+ return (options?.client ?? client).get<GetV1ToolsInstagramDownloadResponse, GetV1ToolsInstagramDownloadError, ThrowOnError>({
45
+ ...options,
46
+ url: '/v1/tools/instagram/download'
47
+ });
48
+ };
49
+
50
+ /**
51
+ * Check Instagram hashtags for bans
52
+ * Check if Instagram hashtags are banned, restricted, or safe to use.
53
+ *
54
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
55
+ *
56
+ */
57
+ export const postV1ToolsInstagramHashtagChecker = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ToolsInstagramHashtagCheckerData, ThrowOnError>) => {
58
+ return (options?.client ?? client).post<PostV1ToolsInstagramHashtagCheckerResponse, PostV1ToolsInstagramHashtagCheckerError, ThrowOnError>({
59
+ ...options,
60
+ url: '/v1/tools/instagram/hashtag-checker'
61
+ });
62
+ };
63
+
64
+ /**
65
+ * Download TikTok video
66
+ * Download TikTok videos with or without watermark.
67
+ *
68
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
69
+ *
70
+ */
71
+ export const getV1ToolsTiktokDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsTiktokDownloadData, ThrowOnError>) => {
72
+ return (options?.client ?? client).get<GetV1ToolsTiktokDownloadResponse, GetV1ToolsTiktokDownloadError, ThrowOnError>({
73
+ ...options,
74
+ url: '/v1/tools/tiktok/download'
75
+ });
76
+ };
77
+
78
+ /**
79
+ * Download Twitter/X video
80
+ * Download videos from Twitter/X posts.
81
+ *
82
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
83
+ *
84
+ */
85
+ export const getV1ToolsTwitterDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsTwitterDownloadData, ThrowOnError>) => {
86
+ return (options?.client ?? client).get<GetV1ToolsTwitterDownloadResponse, GetV1ToolsTwitterDownloadError, ThrowOnError>({
87
+ ...options,
88
+ url: '/v1/tools/twitter/download'
89
+ });
90
+ };
91
+
92
+ /**
93
+ * Download Facebook video
94
+ * Download videos and reels from Facebook.
95
+ *
96
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
97
+ *
98
+ */
99
+ export const getV1ToolsFacebookDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsFacebookDownloadData, ThrowOnError>) => {
100
+ return (options?.client ?? client).get<GetV1ToolsFacebookDownloadResponse, GetV1ToolsFacebookDownloadError, ThrowOnError>({
101
+ ...options,
102
+ url: '/v1/tools/facebook/download'
103
+ });
104
+ };
105
+
106
+ /**
107
+ * Download LinkedIn video
108
+ * Download videos from LinkedIn posts.
109
+ *
110
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
111
+ *
112
+ */
113
+ export const getV1ToolsLinkedinDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsLinkedinDownloadData, ThrowOnError>) => {
114
+ return (options?.client ?? client).get<GetV1ToolsLinkedinDownloadResponse, GetV1ToolsLinkedinDownloadError, ThrowOnError>({
115
+ ...options,
116
+ url: '/v1/tools/linkedin/download'
117
+ });
118
+ };
119
+
120
+ /**
121
+ * Download Bluesky video
122
+ * Download videos from Bluesky posts.
123
+ *
124
+ * **Rate Limits:** Build (50/day), Accelerate (500/day), Unlimited (unlimited)
125
+ *
126
+ */
127
+ export const getV1ToolsBlueskyDownload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ToolsBlueskyDownloadData, ThrowOnError>) => {
128
+ return (options?.client ?? client).get<GetV1ToolsBlueskyDownloadResponse, GetV1ToolsBlueskyDownloadError, ThrowOnError>({
129
+ ...options,
130
+ url: '/v1/tools/bluesky/download'
131
+ });
132
+ };
133
+
134
+ /**
135
+ * Unified analytics for posts
136
+ * Returns analytics for posts. If postId is provided, returns analytics for a single post.
137
+ * Otherwise returns a paginated list of posts with overview stats.
138
+ *
139
+ * **Important: Understanding Post IDs**
140
+ *
141
+ * This endpoint uses two types of posts:
142
+ * - **Late Posts** - Posts scheduled/created via the Late API (e.g., via `POST /v1/posts`)
143
+ * - **External Posts** - Posts synced from social platforms for analytics tracking
144
+ *
145
+ * When you schedule a post via Late and it gets published, **both** records exist:
146
+ * 1. The original Late Post (returned when you created the post)
147
+ * 2. An External Post (created when we sync analytics from the platform)
148
+ *
149
+ * **List endpoint behavior:**
150
+ * - Returns External Post IDs (`_id` field)
151
+ * - Use the `isExternal` field to identify post origin:
152
+ * - `isExternal: true` - Synced from platform (may have been originally scheduled via Late)
153
+ * - `isExternal: false` - Late-scheduled post (shown when querying by Late post ID)
154
+ *
155
+ * **Single post behavior (`postId` parameter):**
156
+ * - Accepts **both** Late Post IDs and External Post IDs
157
+ * - If you pass a Late Post ID, the API automatically resolves it to the corresponding External Post analytics
158
+ * - Both return the same analytics data for the same underlying social media post
159
+ *
160
+ * **Correlating posts:** Use `platformPostUrl` (e.g., `https://www.instagram.com/reel/ABC123/`) as the unique identifier - it's consistent across both Late and External post records.
161
+ *
162
+ * **Note:** For follower count history and growth metrics, use the dedicated `/v1/accounts/follower-stats` endpoint.
163
+ *
164
+ * **LinkedIn Analytics:**
165
+ * - **Personal Accounts:** Per-post analytics available for posts published through Late. External posts cannot be synced due to LinkedIn API restrictions.
166
+ * - **Organization Accounts:** Full analytics support including external post syncing.
167
+ *
168
+ * **Telegram Analytics:**
169
+ * - **Not available.** The Telegram Bot API does not provide message view counts, forwards, or engagement metrics. This is a Telegram platform limitation, not a Late limitation. View counts are only visible to channel admins in the Telegram app.
170
+ *
171
+ * **Data Freshness:** Analytics data is cached and refreshed at most once per hour. When you call this endpoint, if the cache is older than 60 minutes, a background refresh is triggered and you'll see updated data on subsequent requests. There is no rate limit on API requests.
172
+ *
173
+ */
174
+ export const getV1Analytics = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1AnalyticsData, ThrowOnError>) => {
175
+ return (options?.client ?? client).get<GetV1AnalyticsResponse, GetV1AnalyticsError, ThrowOnError>({
176
+ ...options,
177
+ url: '/v1/analytics'
178
+ });
179
+ };
180
+
181
+ /**
182
+ * YouTube daily views breakdown
183
+ * Returns historical daily view counts for a specific YouTube video.
184
+ * Uses YouTube Analytics API v2 to fetch daily breakdowns including views,
185
+ * watch time, and subscriber changes.
186
+ *
187
+ * **Required Scope:** This endpoint requires the `yt-analytics.readonly` OAuth scope.
188
+ * Existing YouTube accounts may need to re-authorize to grant this permission.
189
+ * If the scope is missing, the response will include a `reauthorizeUrl`.
190
+ *
191
+ * **Data Latency:** YouTube Analytics data has a 2-3 day delay. The `endDate`
192
+ * is automatically capped to 3 days ago.
193
+ *
194
+ * **Date Range:** Maximum 90 days of historical data available. Defaults to last 30 days.
195
+ *
196
+ */
197
+ export const getV1AnalyticsYoutubeDailyViews = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AnalyticsYoutubeDailyViewsData, ThrowOnError>) => {
198
+ return (options?.client ?? client).get<GetV1AnalyticsYoutubeDailyViewsResponse, GetV1AnalyticsYoutubeDailyViewsError, ThrowOnError>({
199
+ ...options,
200
+ url: '/v1/analytics/youtube/daily-views'
201
+ });
202
+ };
203
+
204
+ /**
205
+ * List account groups for the authenticated user
206
+ */
207
+ export const getV1AccountGroups = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<unknown, ThrowOnError>) => {
208
+ return (options?.client ?? client).get<GetV1AccountGroupsResponse, GetV1AccountGroupsError, ThrowOnError>({
209
+ ...options,
210
+ url: '/v1/account-groups'
211
+ });
212
+ };
213
+
214
+ /**
215
+ * Create a new account group
216
+ */
217
+ export const postV1AccountGroups = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1AccountGroupsData, ThrowOnError>) => {
218
+ return (options?.client ?? client).post<PostV1AccountGroupsResponse, PostV1AccountGroupsError, ThrowOnError>({
219
+ ...options,
220
+ url: '/v1/account-groups'
221
+ });
222
+ };
223
+
224
+ /**
225
+ * Update an account group
226
+ */
227
+ export const putV1AccountGroupsByGroupId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountGroupsByGroupIdData, ThrowOnError>) => {
228
+ return (options?.client ?? client).put<PutV1AccountGroupsByGroupIdResponse, PutV1AccountGroupsByGroupIdError, ThrowOnError>({
229
+ ...options,
230
+ url: '/v1/account-groups/{groupId}'
231
+ });
232
+ };
233
+
234
+ /**
235
+ * Delete an account group
236
+ */
237
+ export const deleteV1AccountGroupsByGroupId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1AccountGroupsByGroupIdData, ThrowOnError>) => {
238
+ return (options?.client ?? client).delete<DeleteV1AccountGroupsByGroupIdResponse, DeleteV1AccountGroupsByGroupIdError, ThrowOnError>({
239
+ ...options,
240
+ url: '/v1/account-groups/{groupId}'
241
+ });
242
+ };
243
+
244
+ /**
245
+ * Get a presigned URL for direct file upload (up to 5GB)
246
+ * Get a presigned URL to upload files directly to cloud storage. This is the recommended method for uploading files of any size, especially files larger than ~4MB.
247
+ *
248
+ * **How it works:**
249
+ * 1. Call this endpoint with the filename and content type
250
+ * 2. Receive an `uploadUrl` (presigned) and `publicUrl`
251
+ * 3. PUT your file directly to the `uploadUrl`
252
+ * 4. Use the `publicUrl` in your posts
253
+ *
254
+ * **Benefits:**
255
+ * - Supports files up to 5GB
256
+ * - Files upload directly to storage (faster, no server bottleneck)
257
+ * - No 413 errors from server body size limits
258
+ *
259
+ * **Example:**
260
+ * ```javascript
261
+ * // Step 1: Get presigned URL
262
+ * const response = await fetch('https://getlate.dev/api/v1/media/presign', {
263
+ * method: 'POST',
264
+ * headers: {
265
+ * 'Authorization': 'Bearer YOUR_API_KEY',
266
+ * 'Content-Type': 'application/json'
267
+ * },
268
+ * body: JSON.stringify({
269
+ * filename: 'my-video.mp4',
270
+ * contentType: 'video/mp4'
271
+ * })
272
+ * });
273
+ * const { uploadUrl, publicUrl } = await response.json();
274
+ *
275
+ * // Step 2: Upload file directly to storage
276
+ * await fetch(uploadUrl, {
277
+ * method: 'PUT',
278
+ * body: file,
279
+ * headers: { 'Content-Type': 'video/mp4' }
280
+ * });
281
+ *
282
+ * // Step 3: Use publicUrl when creating your post
283
+ * // The publicUrl is ready to use immediately after upload completes
284
+ * ```
285
+ *
286
+ */
287
+ export const postV1MediaPresign = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1MediaPresignData, ThrowOnError>) => {
288
+ return (options?.client ?? client).post<PostV1MediaPresignResponse, PostV1MediaPresignError, ThrowOnError>({
289
+ ...options,
290
+ url: '/v1/media/presign'
291
+ });
292
+ };
293
+
294
+ /**
295
+ * Search Reddit posts via a connected account
296
+ */
297
+ export const getV1RedditSearch = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1RedditSearchData, ThrowOnError>) => {
298
+ return (options?.client ?? client).get<GetV1RedditSearchResponse, GetV1RedditSearchError, ThrowOnError>({
299
+ ...options,
300
+ url: '/v1/reddit/search'
301
+ });
302
+ };
303
+
304
+ /**
305
+ * Fetch subreddit feed via a connected account
306
+ */
307
+ export const getV1RedditFeed = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1RedditFeedData, ThrowOnError>) => {
308
+ return (options?.client ?? client).get<GetV1RedditFeedResponse, GetV1RedditFeedError, ThrowOnError>({
309
+ ...options,
310
+ url: '/v1/reddit/feed'
311
+ });
312
+ };
313
+
314
+ /**
315
+ * Get plan and usage stats for current account
316
+ */
317
+ export const getV1UsageStats = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<unknown, ThrowOnError>) => {
318
+ return (options?.client ?? client).get<GetV1UsageStatsResponse, GetV1UsageStatsError, ThrowOnError>({
319
+ ...options,
320
+ url: '/v1/usage-stats'
321
+ });
322
+ };
323
+
324
+ /**
325
+ * List posts visible to the authenticated user
326
+ * **Getting Post URLs:**
327
+ * For published posts, each platform entry includes `platformPostUrl` with the public URL.
328
+ * Use `status=published` filter to fetch only published posts with their URLs.
329
+ *
330
+ * Notes and constraints by platform when interpreting the response:
331
+ * - YouTube: posts always include at least one video in mediaItems.
332
+ * - Instagram/TikTok: posts always include media; drafts may omit media until finalized in client.
333
+ * - TikTok: mediaItems will not mix photos and videos in the same post.
334
+ *
335
+ */
336
+ export const getV1Posts = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1PostsData, ThrowOnError>) => {
337
+ return (options?.client ?? client).get<GetV1PostsResponse, GetV1PostsError, ThrowOnError>({
338
+ ...options,
339
+ url: '/v1/posts'
340
+ });
341
+ };
342
+
343
+ /**
344
+ * Create a draft, scheduled, or immediate post
345
+ * **Getting Post URLs:**
346
+ * - For immediate posts (`publishNow: true`): The response includes `platformPostUrl` in each platform entry under `post.platforms[]`.
347
+ * - For scheduled posts: Fetch the post via `GET /v1/posts/{postId}` after the scheduled time; `platformPostUrl` will be populated once published.
348
+ *
349
+ * Platform constraints:
350
+ * - YouTube requires a video in mediaItems; optional custom thumbnail via MediaItem.thumbnail.
351
+ * - Instagram and TikTok require media; do not mix videos and images for TikTok.
352
+ * - Instagram carousels support up to 10 items; Stories publish as 'story'.
353
+ * - Threads carousels support up to 10 images (no videos in carousels); single posts support one image or video.
354
+ * - Facebook Stories require media (single image or video); set contentType to 'story' in platformSpecificData.
355
+ * - LinkedIn multi-image supports up to 20 images; single PDF documents supported (max 100MB, ~300 pages, cannot mix with other media).
356
+ * - Pinterest supports single image via image_url or a single video per Pin; boardId is required.
357
+ * - Bluesky supports up to 4 images per post. Images may be automatically recompressed to ≤ ~1MB to satisfy Bluesky's blob limit. When no media is attached, a link preview may be generated for URLs in the text.
358
+ * - Snapchat requires media (single image or video); set contentType to 'story', 'saved_story', or 'spotlight' in platformSpecificData. Stories are ephemeral (24h), Saved Stories are permanent, Spotlight is for video content.
359
+ *
360
+ */
361
+ export const postV1Posts = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1PostsData, ThrowOnError>) => {
362
+ return (options?.client ?? client).post<PostV1PostsResponse, PostV1PostsError, ThrowOnError>({
363
+ ...options,
364
+ url: '/v1/posts'
365
+ });
366
+ };
367
+
368
+ /**
369
+ * Get a single post
370
+ * Fetch a single post by ID. For published posts, this returns `platformPostUrl`
371
+ * for each platform - useful for retrieving post URLs after scheduled posts publish.
372
+ *
373
+ */
374
+ export const getV1PostsByPostId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1PostsByPostIdData, ThrowOnError>) => {
375
+ return (options?.client ?? client).get<GetV1PostsByPostIdResponse, GetV1PostsByPostIdError, ThrowOnError>({
376
+ ...options,
377
+ url: '/v1/posts/{postId}'
378
+ });
379
+ };
380
+
381
+ /**
382
+ * Update a post
383
+ * Update an existing post. Only draft, scheduled, failed, and partial posts can be edited.
384
+ * Published, publishing, and cancelled posts cannot be modified.
385
+ *
386
+ */
387
+ export const putV1PostsByPostId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1PostsByPostIdData, ThrowOnError>) => {
388
+ return (options?.client ?? client).put<PutV1PostsByPostIdResponse, PutV1PostsByPostIdError, ThrowOnError>({
389
+ ...options,
390
+ url: '/v1/posts/{postId}'
391
+ });
392
+ };
393
+
394
+ /**
395
+ * Delete a post
396
+ * Delete a post. Published posts cannot be deleted.
397
+ * When deleting a scheduled or draft post that consumed upload quota, the quota will be automatically refunded.
398
+ *
399
+ */
400
+ export const deleteV1PostsByPostId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1PostsByPostIdData, ThrowOnError>) => {
401
+ return (options?.client ?? client).delete<DeleteV1PostsByPostIdResponse, DeleteV1PostsByPostIdError, ThrowOnError>({
402
+ ...options,
403
+ url: '/v1/posts/{postId}'
404
+ });
405
+ };
406
+
407
+ /**
408
+ * Validate and schedule multiple posts from CSV
409
+ */
410
+ export const postV1PostsBulkUpload = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1PostsBulkUploadData, ThrowOnError>) => {
411
+ return (options?.client ?? client).post<PostV1PostsBulkUploadResponse, PostV1PostsBulkUploadError, ThrowOnError>({
412
+ ...options,
413
+ ...formDataBodySerializer,
414
+ headers: {
415
+ 'Content-Type': null,
416
+ ...options?.headers
417
+ },
418
+ url: '/v1/posts/bulk-upload'
419
+ });
420
+ };
421
+
422
+ /**
423
+ * Retry publishing a failed or partial post
424
+ */
425
+ export const postV1PostsByPostIdRetry = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1PostsByPostIdRetryData, ThrowOnError>) => {
426
+ return (options?.client ?? client).post<PostV1PostsByPostIdRetryResponse, PostV1PostsByPostIdRetryError, ThrowOnError>({
427
+ ...options,
428
+ url: '/v1/posts/{postId}/retry'
429
+ });
430
+ };
431
+
432
+ /**
433
+ * List team users (root + invited)
434
+ */
435
+ export const getV1Users = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<unknown, ThrowOnError>) => {
436
+ return (options?.client ?? client).get<GetV1UsersResponse, GetV1UsersError, ThrowOnError>({
437
+ ...options,
438
+ url: '/v1/users'
439
+ });
440
+ };
441
+
442
+ /**
443
+ * Get user by id (self or invited)
444
+ */
445
+ export const getV1UsersByUserId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1UsersByUserIdData, ThrowOnError>) => {
446
+ return (options?.client ?? client).get<GetV1UsersByUserIdResponse, GetV1UsersByUserIdError, ThrowOnError>({
447
+ ...options,
448
+ url: '/v1/users/{userId}'
449
+ });
450
+ };
451
+
452
+ /**
453
+ * List profiles visible to the authenticated user
454
+ * Returns profiles within the user's plan limit. Profiles are sorted by creation date (oldest first).
455
+ * Use `includeOverLimit=true` to include profiles that exceed the plan limit (for management/deletion purposes).
456
+ *
457
+ */
458
+ export const getV1Profiles = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1ProfilesData, ThrowOnError>) => {
459
+ return (options?.client ?? client).get<GetV1ProfilesResponse, GetV1ProfilesError, ThrowOnError>({
460
+ ...options,
461
+ url: '/v1/profiles'
462
+ });
463
+ };
464
+
465
+ /**
466
+ * Create a new profile
467
+ */
468
+ export const postV1Profiles = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ProfilesData, ThrowOnError>) => {
469
+ return (options?.client ?? client).post<PostV1ProfilesResponse, PostV1ProfilesError, ThrowOnError>({
470
+ ...options,
471
+ url: '/v1/profiles'
472
+ });
473
+ };
474
+
475
+ /**
476
+ * Get a profile by id
477
+ */
478
+ export const getV1ProfilesByProfileId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ProfilesByProfileIdData, ThrowOnError>) => {
479
+ return (options?.client ?? client).get<GetV1ProfilesByProfileIdResponse, GetV1ProfilesByProfileIdError, ThrowOnError>({
480
+ ...options,
481
+ url: '/v1/profiles/{profileId}'
482
+ });
483
+ };
484
+
485
+ /**
486
+ * Update a profile
487
+ */
488
+ export const putV1ProfilesByProfileId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1ProfilesByProfileIdData, ThrowOnError>) => {
489
+ return (options?.client ?? client).put<PutV1ProfilesByProfileIdResponse, PutV1ProfilesByProfileIdError, ThrowOnError>({
490
+ ...options,
491
+ url: '/v1/profiles/{profileId}'
492
+ });
493
+ };
494
+
495
+ /**
496
+ * Delete a profile (must have no connected accounts)
497
+ */
498
+ export const deleteV1ProfilesByProfileId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1ProfilesByProfileIdData, ThrowOnError>) => {
499
+ return (options?.client ?? client).delete<DeleteV1ProfilesByProfileIdResponse, DeleteV1ProfilesByProfileIdError, ThrowOnError>({
500
+ ...options,
501
+ url: '/v1/profiles/{profileId}'
502
+ });
503
+ };
504
+
505
+ /**
506
+ * List connected social accounts
507
+ * Returns list of connected social accounts.
508
+ * By default, only returns accounts from profiles within the user's plan limit.
509
+ * Follower count data (followersCount, followersLastUpdated) is only included if user has analytics add-on.
510
+ *
511
+ */
512
+ export const getV1Accounts = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1AccountsData, ThrowOnError>) => {
513
+ return (options?.client ?? client).get<GetV1AccountsResponse, GetV1AccountsError, ThrowOnError>({
514
+ ...options,
515
+ url: '/v1/accounts'
516
+ });
517
+ };
518
+
519
+ /**
520
+ * Get follower stats and growth metrics
521
+ * Returns follower count history and growth metrics for connected social accounts.
522
+ * **Requires analytics add-on subscription.**
523
+ *
524
+ * **Data Freshness:** Follower counts are automatically refreshed once per day.
525
+ *
526
+ */
527
+ export const getV1AccountsFollowerStats = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1AccountsFollowerStatsData, ThrowOnError>) => {
528
+ return (options?.client ?? client).get<GetV1AccountsFollowerStatsResponse, GetV1AccountsFollowerStatsError, ThrowOnError>({
529
+ ...options,
530
+ url: '/v1/accounts/follower-stats'
531
+ });
532
+ };
533
+
534
+ /**
535
+ * Update a social account
536
+ */
537
+ export const putV1AccountsByAccountId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountsByAccountIdData, ThrowOnError>) => {
538
+ return (options?.client ?? client).put<PutV1AccountsByAccountIdResponse, PutV1AccountsByAccountIdError, ThrowOnError>({
539
+ ...options,
540
+ url: '/v1/accounts/{accountId}'
541
+ });
542
+ };
543
+
544
+ /**
545
+ * Disconnect a social account
546
+ */
547
+ export const deleteV1AccountsByAccountId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1AccountsByAccountIdData, ThrowOnError>) => {
548
+ return (options?.client ?? client).delete<DeleteV1AccountsByAccountIdResponse, DeleteV1AccountsByAccountIdError, ThrowOnError>({
549
+ ...options,
550
+ url: '/v1/accounts/{accountId}'
551
+ });
552
+ };
553
+
554
+ /**
555
+ * Check health of all connected accounts
556
+ * Returns the health status of all connected social accounts, including token validity,
557
+ * permissions status, and any issues that need attention. Useful for monitoring account
558
+ * connections and identifying accounts that need reconnection.
559
+ *
560
+ */
561
+ export const getV1AccountsHealth = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1AccountsHealthData, ThrowOnError>) => {
562
+ return (options?.client ?? client).get<GetV1AccountsHealthResponse, GetV1AccountsHealthError, ThrowOnError>({
563
+ ...options,
564
+ url: '/v1/accounts/health'
565
+ });
566
+ };
567
+
568
+ /**
569
+ * Check health of a specific account
570
+ * Returns detailed health information for a specific social account, including token status,
571
+ * granted permissions, missing permissions, and actionable recommendations.
572
+ *
573
+ */
574
+ export const getV1AccountsByAccountIdHealth = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdHealthData, ThrowOnError>) => {
575
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdHealthResponse, GetV1AccountsByAccountIdHealthError, ThrowOnError>({
576
+ ...options,
577
+ url: '/v1/accounts/{accountId}/health'
578
+ });
579
+ };
580
+
581
+ /**
582
+ * List API keys for the current user
583
+ */
584
+ export const getV1ApiKeys = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<unknown, ThrowOnError>) => {
585
+ return (options?.client ?? client).get<GetV1ApiKeysResponse, GetV1ApiKeysError, ThrowOnError>({
586
+ ...options,
587
+ url: '/v1/api-keys'
588
+ });
589
+ };
590
+
591
+ /**
592
+ * Create a new API key
593
+ */
594
+ export const postV1ApiKeys = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ApiKeysData, ThrowOnError>) => {
595
+ return (options?.client ?? client).post<PostV1ApiKeysResponse, PostV1ApiKeysError, ThrowOnError>({
596
+ ...options,
597
+ url: '/v1/api-keys'
598
+ });
599
+ };
600
+
601
+ /**
602
+ * Delete an API key
603
+ */
604
+ export const deleteV1ApiKeysByKeyId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1ApiKeysByKeyIdData, ThrowOnError>) => {
605
+ return (options?.client ?? client).delete<DeleteV1ApiKeysByKeyIdResponse, DeleteV1ApiKeysByKeyIdError, ThrowOnError>({
606
+ ...options,
607
+ url: '/v1/api-keys/{keyId}'
608
+ });
609
+ };
610
+
611
+ /**
612
+ * Create a team member invite token
613
+ * Generate a secure invite link to grant team members access to your profiles.
614
+ * Invites expire after 7 days and are single-use.
615
+ *
616
+ */
617
+ export const postV1InviteTokens = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1InviteTokensData, ThrowOnError>) => {
618
+ return (options?.client ?? client).post<PostV1InviteTokensResponse, PostV1InviteTokensError, ThrowOnError>({
619
+ ...options,
620
+ url: '/v1/invite/tokens'
621
+ });
622
+ };
623
+
624
+ /**
625
+ * List platform connection invites
626
+ * Get all platform connection invites you've created
627
+ */
628
+ export const getV1PlatformInvites = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1PlatformInvitesData, ThrowOnError>) => {
629
+ return (options?.client ?? client).get<GetV1PlatformInvitesResponse, GetV1PlatformInvitesError, ThrowOnError>({
630
+ ...options,
631
+ url: '/v1/platform-invites'
632
+ });
633
+ };
634
+
635
+ /**
636
+ * Create a platform connection invite
637
+ * Generate a secure invite link for someone to connect a social account to your profile.
638
+ * Perfect for client onboarding - they connect their account without accessing your Late account.
639
+ * Invites expire after 7 days.
640
+ *
641
+ */
642
+ export const postV1PlatformInvites = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1PlatformInvitesData, ThrowOnError>) => {
643
+ return (options?.client ?? client).post<PostV1PlatformInvitesResponse, PostV1PlatformInvitesError, ThrowOnError>({
644
+ ...options,
645
+ url: '/v1/platform-invites'
646
+ });
647
+ };
648
+
649
+ /**
650
+ * Revoke a platform connection invite
651
+ * Delete an unused platform invite. Only unused invites can be deleted.
652
+ */
653
+ export const deleteV1PlatformInvites = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1PlatformInvitesData, ThrowOnError>) => {
654
+ return (options?.client ?? client).delete<DeleteV1PlatformInvitesResponse, DeleteV1PlatformInvitesError, ThrowOnError>({
655
+ ...options,
656
+ url: '/v1/platform-invites'
657
+ });
658
+ };
659
+
660
+ /**
661
+ * Start OAuth connection for a platform
662
+ * Initiate an OAuth connection flow for any supported social media platform.
663
+ *
664
+ * **Standard Flow (Hosted UI):**
665
+ * For Facebook connections, Late hosts the page selection UI:
666
+ *
667
+ * 1. Call this endpoint with your API key and `redirect_url` (optional)
668
+ * 2. Redirect your user to the returned `authUrl`
669
+ * 3. After OAuth, the user is redirected to Late’s hosted page selector at
670
+ * `/connect/facebook/select-page?profileId=X&tempToken=Y&userProfile=Z&redirect_url=YOUR_URL&connect_token=CT`
671
+ * 4. After they pick a page, Late saves the connection and finally redirects to your `redirect_url` (if provided)
672
+ *
673
+ * **Headless/Whitelabel Mode (Facebook, LinkedIn, Pinterest & Google Business Profile):**
674
+ * Build your own fully branded selection UI while Late handles OAuth:
675
+ *
676
+ * **Facebook:**
677
+ * 1. Call this endpoint with your API key and add `&headless=true`, e.g.
678
+ * `GET /v1/connect/facebook?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
679
+ * 2. Redirect your user to the returned `authUrl`
680
+ * 3. After OAuth, the user is redirected directly to **your** `redirect_url` with:
681
+ * - `profileId` – your Late profile ID
682
+ * - `tempToken` – temporary Facebook access token
683
+ * - `userProfile` – URL‑encoded JSON user profile
684
+ * - `connect_token` – short‑lived connect token (for API auth)
685
+ * - `platform=facebook`
686
+ * - `step=select_page`
687
+ * 4. Use `tempToken`, `userProfile`, and the `X-Connect-Token` header with:
688
+ * - `GET /v1/connect/facebook/select-page` to fetch pages
689
+ * - `POST /v1/connect/facebook/select-page` to save the selected page
690
+ * 5. In this mode, users never see Late's hosted page selector – only your UI.
691
+ *
692
+ * **LinkedIn:**
693
+ * 1. Call this endpoint with `&headless=true`, e.g.
694
+ * `GET /v1/connect/linkedin?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
695
+ * 2. Redirect your user to the returned `authUrl`
696
+ * 3. After OAuth, the user is redirected directly to **your** `redirect_url` with:
697
+ * - `profileId` – your Late profile ID
698
+ * - `tempToken` – temporary LinkedIn access token
699
+ * - `userProfile` – URL‑encoded JSON with `id`, `username`, `displayName`, `profilePicture`
700
+ * - `organizations` – URL‑encoded JSON array with `id`, `urn`, `name` for each org (logos not included to prevent URL length issues)
701
+ * - `connect_token` – short‑lived connect token (for API auth)
702
+ * - `platform=linkedin`
703
+ * - `step=select_organization`
704
+ * 4. The `organizations` array contains minimal data (`id`, `urn`, `name`). Use it to build your selection UI.
705
+ * 5. **Optional:** To fetch full organization details (logos, vanityName, website, industry, description), call `GET /v1/connect/linkedin/organizations?tempToken=X&orgIds=id1,id2,...`
706
+ * 6. Call `POST /v1/connect/linkedin/select-organization` with the `X-Connect-Token` header to save the selection.
707
+ * 7. In this mode, users never see Late's hosted organization selector – only your UI.
708
+ * 8. Note: If the user has no organization admin access, `step=select_organization` will NOT be present,
709
+ * and the account will be connected directly as a personal account.
710
+ *
711
+ * **Pinterest:**
712
+ * 1. Call this endpoint with `&headless=true`, e.g.
713
+ * `GET /v1/connect/pinterest?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
714
+ * 2. Redirect your user to the returned `authUrl`
715
+ * 3. After OAuth, the user is redirected directly to **your** `redirect_url` with:
716
+ * - `profileId` – your Late profile ID
717
+ * - `tempToken` – temporary Pinterest access token
718
+ * - `userProfile` – URL‑encoded JSON user profile
719
+ * - `connect_token` – short‑lived connect token (for API auth)
720
+ * - `platform=pinterest`
721
+ * - `step=select_board`
722
+ * 4. Use `tempToken`, `userProfile`, and the `X-Connect-Token` header with:
723
+ * - `GET /v1/connect/pinterest/select-board` to fetch boards
724
+ * - `POST /v1/connect/pinterest/select-board` to save the selected board
725
+ * 5. In this mode, users never see Late's hosted board selector – only your UI.
726
+ *
727
+ * **Google Business Profile:**
728
+ * 1. Call this endpoint with `&headless=true`, e.g.
729
+ * `GET /v1/connect/googlebusiness?profileId=PROFILE_ID&redirect_url=https://yourapp.com/callback&headless=true`
730
+ * 2. Redirect your user to the returned `authUrl`
731
+ * 3. After OAuth, the user is redirected directly to **your** `redirect_url` with:
732
+ * - `profileId` – your Late profile ID
733
+ * - `tempToken` – temporary Google access token
734
+ * - `userProfile` – URL‑encoded JSON user profile (includes refresh token info)
735
+ * - `connect_token` – short‑lived connect token (for API auth)
736
+ * - `platform=googlebusiness`
737
+ * - `step=select_location`
738
+ * 4. Use `tempToken`, `userProfile`, and the `X-Connect-Token` header with:
739
+ * - `GET /v1/connect/googlebusiness/locations` to fetch business locations
740
+ * - `POST /v1/connect/googlebusiness/select-location` to save the selected location
741
+ * 5. In this mode, users never see Late's hosted location selector – only your UI.
742
+ *
743
+ */
744
+ export const getV1ConnectByPlatform = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectByPlatformData, ThrowOnError>) => {
745
+ return (options?.client ?? client).get<GetV1ConnectByPlatformResponse, GetV1ConnectByPlatformError, ThrowOnError>({
746
+ ...options,
747
+ url: '/v1/connect/{platform}'
748
+ });
749
+ };
750
+
751
+ /**
752
+ * Complete OAuth token exchange manually (for server-side flows)
753
+ */
754
+ export const postV1ConnectByPlatform = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectByPlatformData, ThrowOnError>) => {
755
+ return (options?.client ?? client).post<PostV1ConnectByPlatformResponse, PostV1ConnectByPlatformError, ThrowOnError>({
756
+ ...options,
757
+ url: '/v1/connect/{platform}'
758
+ });
759
+ };
760
+
761
+ /**
762
+ * List Facebook Pages after OAuth (Headless Mode)
763
+ * **Headless Mode for Custom UI**
764
+ *
765
+ * After initiating Facebook OAuth via `/v1/connect/facebook`, you'll be redirected to
766
+ * `/connect/facebook/select-page` with query params including `tempToken` and `userProfile`.
767
+ *
768
+ * For a **headless/whitelabeled flow**, extract these params from the URL and call this
769
+ * endpoint to retrieve the list of Facebook Pages the user can manage. Then build your
770
+ * own UI to let users select a page.
771
+ *
772
+ * **Note:** Use the `X-Connect-Token` header if you initiated the connection via API key
773
+ * (rather than a browser session).
774
+ *
775
+ */
776
+ export const getV1ConnectFacebookSelectPage = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectFacebookSelectPageData, ThrowOnError>) => {
777
+ return (options?.client ?? client).get<GetV1ConnectFacebookSelectPageResponse, GetV1ConnectFacebookSelectPageError, ThrowOnError>({
778
+ ...options,
779
+ url: '/v1/connect/facebook/select-page'
780
+ });
781
+ };
782
+
783
+ /**
784
+ * Select a Facebook Page to complete the connection (Headless Mode)
785
+ * **Complete the Headless Flow**
786
+ *
787
+ * After displaying your custom UI with the list of pages from the GET endpoint, call this
788
+ * endpoint to finalize the connection with the user's selected page.
789
+ *
790
+ * The `userProfile` should be the decoded JSON object from the `userProfile` query param
791
+ * in the OAuth callback redirect URL.
792
+ *
793
+ * **Note:** Use the `X-Connect-Token` header if you initiated the connection via API key.
794
+ *
795
+ */
796
+ export const postV1ConnectFacebookSelectPage = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectFacebookSelectPageData, ThrowOnError>) => {
797
+ return (options?.client ?? client).post<PostV1ConnectFacebookSelectPageResponse, PostV1ConnectFacebookSelectPageError, ThrowOnError>({
798
+ ...options,
799
+ url: '/v1/connect/facebook/select-page'
800
+ });
801
+ };
802
+
803
+ /**
804
+ * List Google Business Locations after OAuth (Headless Mode)
805
+ * **Headless Mode for Custom UI**
806
+ *
807
+ * After initiating Google Business OAuth via `/v1/connect/googlebusiness?headless=true`, you'll be redirected
808
+ * to your `redirect_url` with query params including `tempToken` and `userProfile`.
809
+ *
810
+ * For a **headless/whitelabeled flow**, extract these params from the URL and call this
811
+ * endpoint to retrieve the list of Google Business locations the user can manage. Then build your
812
+ * own UI to let users select a location.
813
+ *
814
+ * **Note:** Use the `X-Connect-Token` header if you initiated the connection via API key
815
+ * (rather than a browser session).
816
+ *
817
+ */
818
+ export const getV1ConnectGooglebusinessLocations = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectGooglebusinessLocationsData, ThrowOnError>) => {
819
+ return (options?.client ?? client).get<GetV1ConnectGooglebusinessLocationsResponse, GetV1ConnectGooglebusinessLocationsError, ThrowOnError>({
820
+ ...options,
821
+ url: '/v1/connect/googlebusiness/locations'
822
+ });
823
+ };
824
+
825
+ /**
826
+ * Select a Google Business location to complete the connection (Headless Mode)
827
+ * **Complete the Headless Flow**
828
+ *
829
+ * After displaying your custom UI with the list of locations from the GET `/v1/connect/googlebusiness/locations`
830
+ * endpoint, call this endpoint to finalize the connection with the user's selected location.
831
+ *
832
+ * The `userProfile` should be the decoded JSON object from the `userProfile` query param
833
+ * in the OAuth callback redirect URL. It contains important token information (including refresh token).
834
+ *
835
+ * **Note:** Use the `X-Connect-Token` header if you initiated the connection via API key.
836
+ *
837
+ */
838
+ export const postV1ConnectGooglebusinessSelectLocation = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectGooglebusinessSelectLocationData, ThrowOnError>) => {
839
+ return (options?.client ?? client).post<PostV1ConnectGooglebusinessSelectLocationResponse, PostV1ConnectGooglebusinessSelectLocationError, ThrowOnError>({
840
+ ...options,
841
+ url: '/v1/connect/googlebusiness/select-location'
842
+ });
843
+ };
844
+
845
+ /**
846
+ * Get Google Business Profile reviews
847
+ * Fetches reviews for a connected Google Business Profile account.
848
+ *
849
+ * Returns all reviews for the business location, including:
850
+ * - Reviewer information (name, profile photo)
851
+ * - Star rating (1-5)
852
+ * - Review comment/text
853
+ * - Business owner's reply (if any)
854
+ * - Review timestamps
855
+ *
856
+ * Use pagination via `nextPageToken` to fetch all reviews for locations with many reviews.
857
+ *
858
+ */
859
+ export const getV1AccountsByAccountIdGmbReviews = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdGmbReviewsData, ThrowOnError>) => {
860
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdGmbReviewsResponse, GetV1AccountsByAccountIdGmbReviewsError, ThrowOnError>({
861
+ ...options,
862
+ url: '/v1/accounts/{accountId}/gmb-reviews'
863
+ });
864
+ };
865
+
866
+ /**
867
+ * Fetch full LinkedIn organization details (Headless Mode)
868
+ * **Fetch Full Organization Details for Custom UI**
869
+ *
870
+ * After LinkedIn OAuth in headless mode, the redirect URL contains organization data with only
871
+ * `id`, `urn`, and `name` fields (additional details are excluded to prevent URL length issues with many organizations).
872
+ *
873
+ * Use this endpoint to fetch full organization details including logos, vanity names, websites, and more
874
+ * if you want to display them in your custom selection UI.
875
+ *
876
+ * **Note:** This endpoint requires no authentication - just the `tempToken` from the OAuth redirect.
877
+ * Details are fetched directly from LinkedIn's API in parallel for fast response times.
878
+ *
879
+ */
880
+ export const getV1ConnectLinkedinOrganizations = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectLinkedinOrganizationsData, ThrowOnError>) => {
881
+ return (options?.client ?? client).get<GetV1ConnectLinkedinOrganizationsResponse, GetV1ConnectLinkedinOrganizationsError, ThrowOnError>({
882
+ ...options,
883
+ url: '/v1/connect/linkedin/organizations'
884
+ });
885
+ };
886
+
887
+ /**
888
+ * Select LinkedIn organization or personal account after OAuth
889
+ * **Complete the LinkedIn Connection Flow**
890
+ *
891
+ * After OAuth, the user is redirected with `organizations` in the URL params (if they have org admin access).
892
+ * The organizations array contains `id`, `urn`, and `name` fields. Use this data to build your UI,
893
+ * then call this endpoint to save the selection.
894
+ *
895
+ * Set `accountType` to `personal` to connect as the user's personal LinkedIn profile, or
896
+ * `organization` to connect as a company page (requires `selectedOrganization` object).
897
+ *
898
+ * **Personal Profile:** To connect a personal LinkedIn account, set `accountType` to `"personal"`
899
+ * and **omit** the `selectedOrganization` field entirely. This is the simplest flow.
900
+ *
901
+ * **Headless Mode:** Use the `X-Connect-Token` header if you initiated the connection via API key.
902
+ *
903
+ */
904
+ export const postV1ConnectLinkedinSelectOrganization = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectLinkedinSelectOrganizationData, ThrowOnError>) => {
905
+ return (options?.client ?? client).post<PostV1ConnectLinkedinSelectOrganizationResponse, PostV1ConnectLinkedinSelectOrganizationError, ThrowOnError>({
906
+ ...options,
907
+ url: '/v1/connect/linkedin/select-organization'
908
+ });
909
+ };
910
+
911
+ /**
912
+ * List Pinterest Boards after OAuth (Headless Mode)
913
+ * **Retrieve Pinterest Boards for Selection UI**
914
+ *
915
+ * After initiating Pinterest OAuth via `/v1/connect/pinterest` with `headless=true`, you'll be redirected to
916
+ * your `redirect_url` with query params including `tempToken` and `userProfile`.
917
+ *
918
+ * If you want to build your own fully-branded board selector (instead of Late's hosted UI), call this
919
+ * endpoint to retrieve the list of Pinterest Boards the user can post to. Then build your
920
+ * UI and call `POST /v1/connect/pinterest/select-board` to save the selection.
921
+ *
922
+ * **Authentication:** Use `X-Connect-Token` header with the `connect_token` from the redirect URL.
923
+ *
924
+ */
925
+ export const getV1ConnectPinterestSelectBoard = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectPinterestSelectBoardData, ThrowOnError>) => {
926
+ return (options?.client ?? client).get<GetV1ConnectPinterestSelectBoardResponse, GetV1ConnectPinterestSelectBoardError, ThrowOnError>({
927
+ ...options,
928
+ url: '/v1/connect/pinterest/select-board'
929
+ });
930
+ };
931
+
932
+ /**
933
+ * Select a Pinterest Board to complete the connection (Headless Mode)
934
+ * **Complete the Pinterest Connection Flow**
935
+ *
936
+ * After OAuth, use this endpoint to save the selected board and complete the Pinterest account connection.
937
+ *
938
+ * **Headless Mode:** Use the `X-Connect-Token` header if you initiated the connection via API key.
939
+ *
940
+ */
941
+ export const postV1ConnectPinterestSelectBoard = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectPinterestSelectBoardData, ThrowOnError>) => {
942
+ return (options?.client ?? client).post<PostV1ConnectPinterestSelectBoardResponse, PostV1ConnectPinterestSelectBoardError, ThrowOnError>({
943
+ ...options,
944
+ url: '/v1/connect/pinterest/select-board'
945
+ });
946
+ };
947
+
948
+ /**
949
+ * List Snapchat Public Profiles after OAuth (Headless Mode)
950
+ * **Headless Mode for Custom UI**
951
+ *
952
+ * After initiating Snapchat OAuth via `/v1/connect/snapchat?headless=true`, you'll be redirected to
953
+ * your `redirect_url` with query params including `tempToken`, `userProfile`, and `publicProfiles`.
954
+ *
955
+ * If you want to build your own fully-branded profile selector (instead of Late's hosted UI), call this
956
+ * endpoint to retrieve the list of Snapchat Public Profiles the user can post to. Then build your
957
+ * UI and call `POST /v1/connect/snapchat/select-profile` to save the selection.
958
+ *
959
+ * **Authentication:** Use `X-Connect-Token` header with the `connect_token` from the redirect URL.
960
+ *
961
+ */
962
+ export const getV1ConnectSnapchatSelectProfile = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectSnapchatSelectProfileData, ThrowOnError>) => {
963
+ return (options?.client ?? client).get<GetV1ConnectSnapchatSelectProfileResponse, GetV1ConnectSnapchatSelectProfileError, ThrowOnError>({
964
+ ...options,
965
+ url: '/v1/connect/snapchat/select-profile'
966
+ });
967
+ };
968
+
969
+ /**
970
+ * Select a Snapchat Public Profile to complete the connection (Headless Mode)
971
+ * **Complete the Snapchat Connection Flow**
972
+ *
973
+ * After OAuth, use this endpoint to save the selected Public Profile and complete the Snapchat account connection.
974
+ * Snapchat requires a Public Profile to publish Stories, Saved Stories, and Spotlight content.
975
+ *
976
+ * **Headless Mode:** Use the `X-Connect-Token` header if you initiated the connection via API key.
977
+ *
978
+ * After initiating Snapchat OAuth via `/v1/connect/snapchat?headless=true`, you'll be redirected to
979
+ * your `redirect_url` with query params including:
980
+ * - `tempToken` - Temporary access token
981
+ * - `userProfile` - URL-encoded JSON with user info
982
+ * - `publicProfiles` - URL-encoded JSON array of available public profiles
983
+ * - `connect_token` - Short-lived token for API authentication
984
+ * - `platform=snapchat`
985
+ * - `step=select_public_profile`
986
+ *
987
+ * Parse `publicProfiles` to build your custom selector UI, then call this endpoint with the selected profile.
988
+ *
989
+ */
990
+ export const postV1ConnectSnapchatSelectProfile = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectSnapchatSelectProfileData, ThrowOnError>) => {
991
+ return (options?.client ?? client).post<PostV1ConnectSnapchatSelectProfileResponse, PostV1ConnectSnapchatSelectProfileError, ThrowOnError>({
992
+ ...options,
993
+ url: '/v1/connect/snapchat/select-profile'
994
+ });
995
+ };
996
+
997
+ /**
998
+ * Connect Bluesky using app password
999
+ * Connect a Bluesky account using identifier (handle or email) and an app password.
1000
+ *
1001
+ * To get your userId for the state parameter, call `GET /v1/users` - the response includes a `currentUserId` field.
1002
+ *
1003
+ */
1004
+ export const postV1ConnectBlueskyCredentials = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectBlueskyCredentialsData, ThrowOnError>) => {
1005
+ return (options?.client ?? client).post<PostV1ConnectBlueskyCredentialsResponse, PostV1ConnectBlueskyCredentialsError, ThrowOnError>({
1006
+ ...options,
1007
+ url: '/v1/connect/bluesky/credentials'
1008
+ });
1009
+ };
1010
+
1011
+ /**
1012
+ * Generate Telegram access code
1013
+ * Generate a unique access code for connecting a Telegram channel or group.
1014
+ *
1015
+ * **Connection Flow:**
1016
+ * 1. Call this endpoint to get an access code (valid for 15 minutes)
1017
+ * 2. Add the bot (@LateScheduleBot or your configured bot) as an administrator in your Telegram channel/group
1018
+ * 3. Open a private chat with the bot
1019
+ * 4. Send: `{CODE} @yourchannel` (e.g., `LATE-ABC123 @mychannel`)
1020
+ * 5. Poll `PATCH /v1/connect/telegram?code={CODE}` to check connection status
1021
+ *
1022
+ * **Alternative for private channels:** If your channel has no public username, forward any message from the channel to the bot along with the access code.
1023
+ *
1024
+ */
1025
+ export const getV1ConnectTelegram = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1ConnectTelegramData, ThrowOnError>) => {
1026
+ return (options?.client ?? client).get<GetV1ConnectTelegramResponse, GetV1ConnectTelegramError, ThrowOnError>({
1027
+ ...options,
1028
+ url: '/v1/connect/telegram'
1029
+ });
1030
+ };
1031
+
1032
+ /**
1033
+ * Direct Telegram connection (power users)
1034
+ * Connect a Telegram channel/group directly using the chat ID.
1035
+ *
1036
+ * This is an alternative to the access code flow for power users who know their Telegram chat ID.
1037
+ * The bot must already be added as an administrator in the channel/group.
1038
+ *
1039
+ */
1040
+ export const postV1ConnectTelegram = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1ConnectTelegramData, ThrowOnError>) => {
1041
+ return (options?.client ?? client).post<PostV1ConnectTelegramResponse, PostV1ConnectTelegramError, ThrowOnError>({
1042
+ ...options,
1043
+ url: '/v1/connect/telegram'
1044
+ });
1045
+ };
1046
+
1047
+ /**
1048
+ * Check Telegram connection status
1049
+ * Poll this endpoint to check if a Telegram access code has been used to connect a channel/group.
1050
+ *
1051
+ * **Recommended polling interval:** 3 seconds
1052
+ *
1053
+ * **Status values:**
1054
+ * - `pending`: Code is valid, waiting for user to complete connection
1055
+ * - `connected`: Connection successful - channel/group is now linked
1056
+ * - `expired`: Code has expired, generate a new one
1057
+ *
1058
+ */
1059
+ export const patchV1ConnectTelegram = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PatchV1ConnectTelegramData, ThrowOnError>) => {
1060
+ return (options?.client ?? client).patch<PatchV1ConnectTelegramResponse, PatchV1ConnectTelegramError, ThrowOnError>({
1061
+ ...options,
1062
+ url: '/v1/connect/telegram'
1063
+ });
1064
+ };
1065
+
1066
+ /**
1067
+ * Update selected Facebook page for a connected account
1068
+ */
1069
+ export const putV1AccountsByAccountIdFacebookPage = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountsByAccountIdFacebookPageData, ThrowOnError>) => {
1070
+ return (options?.client ?? client).put<PutV1AccountsByAccountIdFacebookPageResponse, PutV1AccountsByAccountIdFacebookPageError, ThrowOnError>({
1071
+ ...options,
1072
+ url: '/v1/accounts/{accountId}/facebook-page'
1073
+ });
1074
+ };
1075
+
1076
+ /**
1077
+ * Get available LinkedIn organizations for a connected account
1078
+ */
1079
+ export const getV1AccountsByAccountIdLinkedinOrganizations = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdLinkedinOrganizationsData, ThrowOnError>) => {
1080
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdLinkedinOrganizationsResponse, GetV1AccountsByAccountIdLinkedinOrganizationsError, ThrowOnError>({
1081
+ ...options,
1082
+ url: '/v1/accounts/{accountId}/linkedin-organizations'
1083
+ });
1084
+ };
1085
+
1086
+ /**
1087
+ * Get aggregate analytics for a LinkedIn personal account
1088
+ * Returns aggregate analytics across ALL posts for a LinkedIn personal account.
1089
+ * Uses LinkedIn's `memberCreatorPostAnalytics` API with `q=me` finder.
1090
+ *
1091
+ * **Important:** This endpoint only works for LinkedIn **personal** accounts. Organization accounts should use the standard `/v1/analytics` endpoint for per-post analytics.
1092
+ *
1093
+ * **Required Scope:** `r_member_postAnalytics`
1094
+ *
1095
+ * If the connected account doesn't have this scope, you'll receive a 403 error with instructions to reconnect.
1096
+ *
1097
+ * **Aggregation Options:**
1098
+ * - `TOTAL` (default): Returns lifetime totals for all metrics
1099
+ * - `DAILY`: Returns daily breakdown of metrics over time
1100
+ *
1101
+ * **Available Metrics:**
1102
+ * - `IMPRESSION`: Number of times posts were displayed
1103
+ * - `MEMBERS_REACHED`: Unique members who saw posts (NOT available with DAILY aggregation)
1104
+ * - `REACTION`: Total reactions (likes, celebrates, etc.)
1105
+ * - `COMMENT`: Total comments
1106
+ * - `RESHARE`: Total reshares/reposts
1107
+ *
1108
+ * **Date Range Filtering:**
1109
+ * Use `startDate` and `endDate` parameters to filter analytics to a specific time period.
1110
+ * If omitted, returns lifetime analytics.
1111
+ *
1112
+ * **LinkedIn API Limitation:** The combination of `MEMBERS_REACHED` + `DAILY` aggregation is not supported by LinkedIn's API.
1113
+ *
1114
+ */
1115
+ export const getV1AccountsByAccountIdLinkedinAggregateAnalytics = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdLinkedinAggregateAnalyticsData, ThrowOnError>) => {
1116
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdLinkedinAggregateAnalyticsResponse, GetV1AccountsByAccountIdLinkedinAggregateAnalyticsError, ThrowOnError>({
1117
+ ...options,
1118
+ url: '/v1/accounts/{accountId}/linkedin-aggregate-analytics'
1119
+ });
1120
+ };
1121
+
1122
+ /**
1123
+ * Get analytics for a specific LinkedIn post by URN
1124
+ * Returns analytics for a specific LinkedIn post using its URN.
1125
+ * Works for both personal and organization accounts.
1126
+ *
1127
+ * This is useful for fetching analytics of posts that weren't published through Late,
1128
+ * as long as you have the post URN.
1129
+ *
1130
+ * **For Personal Accounts:**
1131
+ * - Uses `memberCreatorPostAnalytics` API + `memberCreatorVideoAnalytics` for video posts
1132
+ * - Requires `r_member_postAnalytics` scope
1133
+ * - Available metrics: impressions, reach, likes, comments, shares, video views (video posts only)
1134
+ * - **Clicks are NOT available** for personal accounts
1135
+ *
1136
+ * **For Organization Accounts:**
1137
+ * - Uses `organizationalEntityShareStatistics` API + `videoAnalytics` for video posts
1138
+ * - Requires `r_organization_social` scope
1139
+ * - Available metrics: impressions, reach, clicks, likes, comments, shares, video views (video posts only), engagement rate
1140
+ *
1141
+ */
1142
+ export const getV1AccountsByAccountIdLinkedinPostAnalytics = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdLinkedinPostAnalyticsData, ThrowOnError>) => {
1143
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdLinkedinPostAnalyticsResponse, GetV1AccountsByAccountIdLinkedinPostAnalyticsError, ThrowOnError>({
1144
+ ...options,
1145
+ url: '/v1/accounts/{accountId}/linkedin-post-analytics'
1146
+ });
1147
+ };
1148
+
1149
+ /**
1150
+ * Switch LinkedIn account type (personal/organization)
1151
+ */
1152
+ export const putV1AccountsByAccountIdLinkedinOrganization = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountsByAccountIdLinkedinOrganizationData, ThrowOnError>) => {
1153
+ return (options?.client ?? client).put<PutV1AccountsByAccountIdLinkedinOrganizationResponse, PutV1AccountsByAccountIdLinkedinOrganizationError, ThrowOnError>({
1154
+ ...options,
1155
+ url: '/v1/accounts/{accountId}/linkedin-organization'
1156
+ });
1157
+ };
1158
+
1159
+ /**
1160
+ * Resolve a LinkedIn profile or company URL to a URN for @mentions
1161
+ * Converts a LinkedIn profile URL (person) or company page URL (organization) to a URN that can be used to @mention them in posts.
1162
+ *
1163
+ * **Supports both:**
1164
+ * - **Person mentions:** `linkedin.com/in/username` or just `username`
1165
+ * - **Organization mentions:** `linkedin.com/company/company-name` or `company/company-name`
1166
+ *
1167
+ * **⚠️ Organization Admin Required for Person Mentions Only:**
1168
+ * Person mentions require the connected LinkedIn account to have admin access to at least one LinkedIn Organization (Company Page).
1169
+ * Organization mentions do NOT have this requirement - any LinkedIn account can tag companies.
1170
+ *
1171
+ * **IMPORTANT - Display Name Requirement:**
1172
+ * For **person mentions** to be clickable, the display name must **exactly match** what appears on their LinkedIn profile.
1173
+ * - Organization mentions automatically retrieve the company name from LinkedIn API
1174
+ * - Person mentions require the exact name, so provide the `displayName` parameter
1175
+ *
1176
+ * **Mention Format:**
1177
+ * Use the returned `mentionFormat` value directly in your post content:
1178
+ * ```
1179
+ * Great insights from @[Miquel Palet](urn:li:person:4qj5ox-agD) on this topic!
1180
+ * Excited to partner with @[Microsoft](urn:li:organization:1035)!
1181
+ * ```
1182
+ *
1183
+ */
1184
+ export const getV1AccountsByAccountIdLinkedinMentions = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdLinkedinMentionsData, ThrowOnError>) => {
1185
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdLinkedinMentionsResponse, GetV1AccountsByAccountIdLinkedinMentionsError, ThrowOnError>({
1186
+ ...options,
1187
+ url: '/v1/accounts/{accountId}/linkedin-mentions'
1188
+ });
1189
+ };
1190
+
1191
+ /**
1192
+ * List Pinterest boards for a connected account
1193
+ */
1194
+ export const getV1AccountsByAccountIdPinterestBoards = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdPinterestBoardsData, ThrowOnError>) => {
1195
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdPinterestBoardsResponse, GetV1AccountsByAccountIdPinterestBoardsError, ThrowOnError>({
1196
+ ...options,
1197
+ url: '/v1/accounts/{accountId}/pinterest-boards'
1198
+ });
1199
+ };
1200
+
1201
+ /**
1202
+ * Set default Pinterest board on the connection
1203
+ */
1204
+ export const putV1AccountsByAccountIdPinterestBoards = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountsByAccountIdPinterestBoardsData, ThrowOnError>) => {
1205
+ return (options?.client ?? client).put<PutV1AccountsByAccountIdPinterestBoardsResponse, PutV1AccountsByAccountIdPinterestBoardsError, ThrowOnError>({
1206
+ ...options,
1207
+ url: '/v1/accounts/{accountId}/pinterest-boards'
1208
+ });
1209
+ };
1210
+
1211
+ /**
1212
+ * List Reddit subreddits for a connected account
1213
+ */
1214
+ export const getV1AccountsByAccountIdRedditSubreddits = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1AccountsByAccountIdRedditSubredditsData, ThrowOnError>) => {
1215
+ return (options?.client ?? client).get<GetV1AccountsByAccountIdRedditSubredditsResponse, GetV1AccountsByAccountIdRedditSubredditsError, ThrowOnError>({
1216
+ ...options,
1217
+ url: '/v1/accounts/{accountId}/reddit-subreddits'
1218
+ });
1219
+ };
1220
+
1221
+ /**
1222
+ * Set default subreddit on the connection
1223
+ */
1224
+ export const putV1AccountsByAccountIdRedditSubreddits = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1AccountsByAccountIdRedditSubredditsData, ThrowOnError>) => {
1225
+ return (options?.client ?? client).put<PutV1AccountsByAccountIdRedditSubredditsResponse, PutV1AccountsByAccountIdRedditSubredditsError, ThrowOnError>({
1226
+ ...options,
1227
+ url: '/v1/accounts/{accountId}/reddit-subreddits'
1228
+ });
1229
+ };
1230
+
1231
+ /**
1232
+ * Get queue schedules for a profile
1233
+ * Retrieve queue schedules for a profile. Each profile can have multiple queues.
1234
+ * - Without `all=true`: Returns the default queue (or specific queue if queueId provided)
1235
+ * - With `all=true`: Returns all queues for the profile
1236
+ *
1237
+ */
1238
+ export const getV1QueueSlots = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1QueueSlotsData, ThrowOnError>) => {
1239
+ return (options?.client ?? client).get<GetV1QueueSlotsResponse, GetV1QueueSlotsError, ThrowOnError>({
1240
+ ...options,
1241
+ url: '/v1/queue/slots'
1242
+ });
1243
+ };
1244
+
1245
+ /**
1246
+ * Create a new queue for a profile
1247
+ * Create an additional queue for a profile. The first queue created becomes the default.
1248
+ * Subsequent queues are non-default unless explicitly set.
1249
+ *
1250
+ */
1251
+ export const postV1QueueSlots = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1QueueSlotsData, ThrowOnError>) => {
1252
+ return (options?.client ?? client).post<PostV1QueueSlotsResponse, PostV1QueueSlotsError, ThrowOnError>({
1253
+ ...options,
1254
+ url: '/v1/queue/slots'
1255
+ });
1256
+ };
1257
+
1258
+ /**
1259
+ * Create or update a queue schedule
1260
+ * Create a new queue or update an existing one.
1261
+ * - Without queueId: Creates or updates the default queue
1262
+ * - With queueId: Updates the specific queue
1263
+ * - With setAsDefault=true: Makes this queue the default for the profile
1264
+ *
1265
+ */
1266
+ export const putV1QueueSlots = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1QueueSlotsData, ThrowOnError>) => {
1267
+ return (options?.client ?? client).put<PutV1QueueSlotsResponse, PutV1QueueSlotsError, ThrowOnError>({
1268
+ ...options,
1269
+ url: '/v1/queue/slots'
1270
+ });
1271
+ };
1272
+
1273
+ /**
1274
+ * Delete a queue schedule
1275
+ * Delete a queue from a profile. Requires queueId to specify which queue to delete.
1276
+ * If deleting the default queue, another queue will be promoted to default.
1277
+ *
1278
+ */
1279
+ export const deleteV1QueueSlots = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1QueueSlotsData, ThrowOnError>) => {
1280
+ return (options?.client ?? client).delete<DeleteV1QueueSlotsResponse, DeleteV1QueueSlotsError, ThrowOnError>({
1281
+ ...options,
1282
+ url: '/v1/queue/slots'
1283
+ });
1284
+ };
1285
+
1286
+ /**
1287
+ * Preview upcoming queue slots for a profile
1288
+ */
1289
+ export const getV1QueuePreview = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1QueuePreviewData, ThrowOnError>) => {
1290
+ return (options?.client ?? client).get<GetV1QueuePreviewResponse, GetV1QueuePreviewError, ThrowOnError>({
1291
+ ...options,
1292
+ url: '/v1/queue/preview'
1293
+ });
1294
+ };
1295
+
1296
+ /**
1297
+ * Get the next available queue slot for a profile
1298
+ * Returns the next available posting slot, taking into account already scheduled posts
1299
+ * to avoid conflicts. Useful for scheduling posts via queue without manual time selection.
1300
+ *
1301
+ * If no queueId is specified, uses the profile's default queue.
1302
+ *
1303
+ */
1304
+ export const getV1QueueNextSlot = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1QueueNextSlotData, ThrowOnError>) => {
1305
+ return (options?.client ?? client).get<GetV1QueueNextSlotResponse, GetV1QueueNextSlotError, ThrowOnError>({
1306
+ ...options,
1307
+ url: '/v1/queue/next-slot'
1308
+ });
1309
+ };
1310
+
1311
+ /**
1312
+ * List all webhooks
1313
+ * Retrieve all configured webhooks for the authenticated user. Supports up to 10 webhooks per user.
1314
+ */
1315
+ export const getV1WebhooksSettings = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<unknown, ThrowOnError>) => {
1316
+ return (options?.client ?? client).get<GetV1WebhooksSettingsResponse, GetV1WebhooksSettingsError, ThrowOnError>({
1317
+ ...options,
1318
+ url: '/v1/webhooks/settings'
1319
+ });
1320
+ };
1321
+
1322
+ /**
1323
+ * Create a new webhook
1324
+ * Create a new webhook configuration. Maximum 10 webhooks per user.
1325
+ *
1326
+ * **Note:** Webhooks are automatically disabled after 10 consecutive delivery failures.
1327
+ *
1328
+ */
1329
+ export const postV1WebhooksSettings = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1WebhooksSettingsData, ThrowOnError>) => {
1330
+ return (options?.client ?? client).post<PostV1WebhooksSettingsResponse, PostV1WebhooksSettingsError, ThrowOnError>({
1331
+ ...options,
1332
+ url: '/v1/webhooks/settings'
1333
+ });
1334
+ };
1335
+
1336
+ /**
1337
+ * Update a webhook
1338
+ * Update an existing webhook configuration. All fields except `_id` are optional - only provided fields will be updated.
1339
+ *
1340
+ * **Note:** Webhooks are automatically disabled after 10 consecutive delivery failures.
1341
+ *
1342
+ */
1343
+ export const putV1WebhooksSettings = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PutV1WebhooksSettingsData, ThrowOnError>) => {
1344
+ return (options?.client ?? client).put<PutV1WebhooksSettingsResponse, PutV1WebhooksSettingsError, ThrowOnError>({
1345
+ ...options,
1346
+ url: '/v1/webhooks/settings'
1347
+ });
1348
+ };
1349
+
1350
+ /**
1351
+ * Delete a webhook
1352
+ * Permanently delete a webhook configuration.
1353
+ */
1354
+ export const deleteV1WebhooksSettings = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<DeleteV1WebhooksSettingsData, ThrowOnError>) => {
1355
+ return (options?.client ?? client).delete<DeleteV1WebhooksSettingsResponse, DeleteV1WebhooksSettingsError, ThrowOnError>({
1356
+ ...options,
1357
+ url: '/v1/webhooks/settings'
1358
+ });
1359
+ };
1360
+
1361
+ /**
1362
+ * Send test webhook
1363
+ * Send a test webhook to verify your endpoint is configured correctly.
1364
+ * The test payload includes `event: "webhook.test"` to distinguish it from real events.
1365
+ *
1366
+ */
1367
+ export const postV1WebhooksTest = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<PostV1WebhooksTestData, ThrowOnError>) => {
1368
+ return (options?.client ?? client).post<PostV1WebhooksTestResponse, PostV1WebhooksTestError, ThrowOnError>({
1369
+ ...options,
1370
+ url: '/v1/webhooks/test'
1371
+ });
1372
+ };
1373
+
1374
+ /**
1375
+ * Get webhook delivery logs
1376
+ * Retrieve webhook delivery history. Logs are automatically deleted after 7 days.
1377
+ *
1378
+ */
1379
+ export const getV1WebhooksLogs = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1WebhooksLogsData, ThrowOnError>) => {
1380
+ return (options?.client ?? client).get<GetV1WebhooksLogsResponse, GetV1WebhooksLogsError, ThrowOnError>({
1381
+ ...options,
1382
+ url: '/v1/webhooks/logs'
1383
+ });
1384
+ };
1385
+
1386
+ /**
1387
+ * Get publishing logs
1388
+ * Retrieve publishing logs for all posts. Logs show detailed information about each
1389
+ * publishing attempt including API requests, responses, and timing data.
1390
+ *
1391
+ * **Filtering:**
1392
+ * - Filter by status (success, failed, pending, skipped)
1393
+ * - Filter by platform (instagram, twitter, linkedin, etc.)
1394
+ * - Filter by action (publish, retry, rate_limit_pause, etc.)
1395
+ *
1396
+ * **Retention:** Logs are automatically deleted after 7 days.
1397
+ *
1398
+ */
1399
+ export const getV1Logs = <ThrowOnError extends boolean = false>(options?: OptionsLegacyParser<GetV1LogsData, ThrowOnError>) => {
1400
+ return (options?.client ?? client).get<GetV1LogsResponse, GetV1LogsError, ThrowOnError>({
1401
+ ...options,
1402
+ url: '/v1/logs'
1403
+ });
1404
+ };
1405
+
1406
+ /**
1407
+ * Get a single log entry
1408
+ * Retrieve detailed information about a specific log entry, including full request
1409
+ * and response bodies for debugging.
1410
+ *
1411
+ */
1412
+ export const getV1LogsByLogId = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1LogsByLogIdData, ThrowOnError>) => {
1413
+ return (options?.client ?? client).get<GetV1LogsByLogIdResponse, GetV1LogsByLogIdError, ThrowOnError>({
1414
+ ...options,
1415
+ url: '/v1/logs/{logId}'
1416
+ });
1417
+ };
1418
+
1419
+ /**
1420
+ * Get logs for a specific post
1421
+ * Retrieve all publishing logs for a specific post. Shows the complete history
1422
+ * of publishing attempts for that post across all platforms.
1423
+ *
1424
+ */
1425
+ export const getV1PostsByPostIdLogs = <ThrowOnError extends boolean = false>(options: OptionsLegacyParser<GetV1PostsByPostIdLogsData, ThrowOnError>) => {
1426
+ return (options?.client ?? client).get<GetV1PostsByPostIdLogsResponse, GetV1PostsByPostIdLogsError, ThrowOnError>({
1427
+ ...options,
1428
+ url: '/v1/posts/{postId}/logs'
1429
+ });
1430
+ };