upload-post 2.8.1 → 2.9.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.
- package/README.md +102 -2
- package/index.d.ts +113 -4
- package/index.js +42 -2
- package/package.json +5 -2
package/README.md
CHANGED
|
@@ -39,6 +39,38 @@ console.log(response);
|
|
|
39
39
|
- ✅ **Analytics** - Get engagement metrics
|
|
40
40
|
- ✅ **Full TypeScript Support**
|
|
41
41
|
|
|
42
|
+
## Using this from an AI agent? Use the MCP server instead
|
|
43
|
+
|
|
44
|
+
If you are wiring Upload-Post into ChatGPT, Claude, Cursor, Claude Code or any
|
|
45
|
+
other MCP-compatible agent, you do not need to write a client on top of this
|
|
46
|
+
SDK. The official **[Model Context Protocol server](https://github.com/Upload-Post/upload-post-mcp)**
|
|
47
|
+
already wraps the whole API as 50 tools the agent can call directly.
|
|
48
|
+
|
|
49
|
+
```jsonc
|
|
50
|
+
// Hosted (OAuth or API key) — nothing to install
|
|
51
|
+
{
|
|
52
|
+
"mcpServers": {
|
|
53
|
+
"upload-post": { "url": "https://mcp.upload-post.com/mcp" }
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
```jsonc
|
|
59
|
+
// Local stdio, built on this SDK
|
|
60
|
+
{
|
|
61
|
+
"mcpServers": {
|
|
62
|
+
"upload-post": {
|
|
63
|
+
"command": "npx",
|
|
64
|
+
"args": ["-y", "@upload-post/mcp"],
|
|
65
|
+
"env": { "UPLOAD_POST_API_KEY": "YOUR_API_KEY" }
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
See the [MCP integration guide](https://docs.upload-post.com/guides/mcp-server-integration).
|
|
72
|
+
Keep using this SDK when you are writing your own application code.
|
|
73
|
+
|
|
42
74
|
## API Reference
|
|
43
75
|
|
|
44
76
|
### Upload Video
|
|
@@ -170,9 +202,16 @@ const jwt = await client.generateJwt('my-profile', {
|
|
|
170
202
|
redirectUrl: 'https://yourapp.com/callback',
|
|
171
203
|
platforms: ['tiktok', 'instagram'],
|
|
172
204
|
// Optional: force the connection page language for this profile.
|
|
173
|
-
// Supported: 'en' | 'es' | 'de' | 'fr' | 'pt'. When omitted, the
|
|
174
|
-
// auto-detects the visitor's browser language and falls back to English.
|
|
205
|
+
// Supported: 'en' | 'es' | 'de' | 'fr' | 'pt' | 'pl' | 'tr'. When omitted, the
|
|
206
|
+
// page auto-detects the visitor's browser language and falls back to English.
|
|
175
207
|
language: 'es',
|
|
208
|
+
// Optional: override individual connection-page strings. Flat object of i18n
|
|
209
|
+
// dot-path keys to strings. Max 100 entries, keys ^[a-zA-Z0-9_.]+$, values
|
|
210
|
+
// up to 300 chars. Echoed back in the `profile` object of validateJwt.
|
|
211
|
+
uiLabels: {
|
|
212
|
+
'connect.title': 'Link your accounts',
|
|
213
|
+
'connect.subtitle': 'Publish everywhere from one place',
|
|
214
|
+
},
|
|
176
215
|
});
|
|
177
216
|
```
|
|
178
217
|
|
|
@@ -183,6 +222,34 @@ const analytics = await client.getAnalytics('my-profile', {
|
|
|
183
222
|
platforms: ['instagram', 'tiktok'],
|
|
184
223
|
});
|
|
185
224
|
console.log(analytics);
|
|
225
|
+
|
|
226
|
+
// Instagram returns two audience breakdowns with the same shape
|
|
227
|
+
// ({ age, gender, country, city }):
|
|
228
|
+
console.log(analytics.analytics.instagram.follower_demographics);
|
|
229
|
+
console.log(analytics.analytics.instagram.engaged_audience_demographics);
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
### Cached Post Analytics
|
|
233
|
+
|
|
234
|
+
Replays per-post metrics already fetched, instead of calling the platforms again. Only contains posts previously fetched through a live per-post endpoint; there is no background refresh, so captured_at is the last time that post was read live. Not subject to the live
|
|
235
|
+
calls, so it is not subject to the live post-analytics rate limit
|
|
236
|
+
(100 requests / 5 minutes). Use it to page through a profile's post history.
|
|
237
|
+
|
|
238
|
+
```javascript
|
|
239
|
+
let cursor;
|
|
240
|
+
do {
|
|
241
|
+
const page = await client.getCachedPostAnalytics('my-profile', {
|
|
242
|
+
platform: 'youtube', // optional: instagram, tiktok, youtube, facebook, linkedin, threads, pinterest, reddit
|
|
243
|
+
limit: 50, // default 50, max 200
|
|
244
|
+
since: '2026-06-01', // defaults to 30 days ago
|
|
245
|
+
until: '2026-07-01', // defaults to today
|
|
246
|
+
cursor,
|
|
247
|
+
});
|
|
248
|
+
for (const post of page.posts) {
|
|
249
|
+
console.log(post.platform, post.post_id, post.metrics);
|
|
250
|
+
}
|
|
251
|
+
cursor = page.next_cursor;
|
|
252
|
+
} while (cursor);
|
|
186
253
|
```
|
|
187
254
|
|
|
188
255
|
### Get Media
|
|
@@ -201,6 +268,22 @@ await client.getMedia('linkedin', 'my-profile', { pageUrn: 'me' });
|
|
|
201
268
|
await client.getMedia('linkedin', 'my-profile', { pageUrn: '12345' });
|
|
202
269
|
```
|
|
203
270
|
|
|
271
|
+
The response carries a `pagination` object — `{ limit, next_cursor, has_more }`,
|
|
272
|
+
with `next_cursor: null` and `has_more: false` on the last page:
|
|
273
|
+
|
|
274
|
+
```javascript
|
|
275
|
+
let cursor;
|
|
276
|
+
do {
|
|
277
|
+
const page = await client.getMedia('instagram', 'my-profile', { limit: 50, cursor });
|
|
278
|
+
console.log(page.media.length);
|
|
279
|
+
cursor = page.pagination.next_cursor;
|
|
280
|
+
} while (cursor);
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
`limit` defaults to 25 and is clamped to 1-100, with per-platform caps of 20 for
|
|
284
|
+
TikTok and 50 for YouTube. **LinkedIn, Discord and Telegram do not support
|
|
285
|
+
cursors** — they accept `limit` only, and passing a `cursor` returns HTTP 400.
|
|
286
|
+
|
|
204
287
|
### Helper Methods
|
|
205
288
|
|
|
206
289
|
```javascript
|
|
@@ -350,6 +433,22 @@ await client.uploadText({
|
|
|
350
433
|
|
|
351
434
|
Also available: `gbpTopicType: 'EVENT'` with `gbpEventTitle` / `gbpEventStartDate` / `gbpEventStartTime` / `gbpEventEndDate` / `gbpEventEndTime`, a call-to-action via `gbpCtaType` + `gbpCtaUrl`, and `gbpMediaUrl` / `gbpMediaFormat`.
|
|
352
435
|
|
|
436
|
+
### Gallery photos
|
|
437
|
+
|
|
438
|
+
Set `gbpPostType` to publish straight into the location's photo gallery instead of creating a Local Post:
|
|
439
|
+
|
|
440
|
+
```javascript
|
|
441
|
+
await client.uploadPhotos(['storefront.jpg'], {
|
|
442
|
+
user: 'myprofile',
|
|
443
|
+
platforms: ['google_business'],
|
|
444
|
+
gbpLocationId: locations[0].name,
|
|
445
|
+
gbpPostType: 'GALLERY', // MEDIA | PHOTO | GALLERY
|
|
446
|
+
gbpMediaCategory: 'EXTERIOR', // defaults to ADDITIONAL
|
|
447
|
+
});
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
Omitting `gbpPostType` (or sending any other value) keeps the existing Local Post behaviour. `gbpMediaCategory` accepts `COVER`, `PROFILE`, `LOGO`, `EXTERIOR`, `INTERIOR`, `PRODUCT`, `AT_WORK`, `FOOD_AND_DRINK`, `MENU`, `COMMON_AREA`, `ROOMS`, `TEAMS` and `ADDITIONAL`.
|
|
451
|
+
|
|
353
452
|
## Retrying an upload safely
|
|
354
453
|
|
|
355
454
|
An upload that times out may still have been accepted by the API. Retrying it without an idempotency key publishes the post a second time.
|
|
@@ -407,6 +506,7 @@ try {
|
|
|
407
506
|
- [Upload-Post Website](https://www.upload-post.com)
|
|
408
507
|
- [API Documentation](https://docs.upload-post.com)
|
|
409
508
|
- [Dashboard](https://app.upload-post.com)
|
|
509
|
+
- [MCP Server](https://www.upload-post.com/mcp) — connect ChatGPT, Claude, Cursor and any AI agent ([source](https://github.com/Upload-Post/upload-post-mcp), [npm](https://www.npmjs.com/package/@upload-post/mcp))
|
|
410
510
|
|
|
411
511
|
## License
|
|
412
512
|
|
package/index.d.ts
CHANGED
|
@@ -358,9 +358,28 @@ declare module 'upload-post' {
|
|
|
358
358
|
|
|
359
359
|
// ==================== Combined Upload Options ====================
|
|
360
360
|
|
|
361
|
+
export type GoogleBusinessMediaCategory =
|
|
362
|
+
| 'COVER'
|
|
363
|
+
| 'PROFILE'
|
|
364
|
+
| 'LOGO'
|
|
365
|
+
| 'EXTERIOR'
|
|
366
|
+
| 'INTERIOR'
|
|
367
|
+
| 'PRODUCT'
|
|
368
|
+
| 'AT_WORK'
|
|
369
|
+
| 'FOOD_AND_DRINK'
|
|
370
|
+
| 'MENU'
|
|
371
|
+
| 'COMMON_AREA'
|
|
372
|
+
| 'ROOMS'
|
|
373
|
+
| 'TEAMS'
|
|
374
|
+
| 'ADDITIONAL';
|
|
375
|
+
|
|
361
376
|
export interface GoogleBusinessOptions {
|
|
362
377
|
/** Google Business location id, e.g. "accounts/123/locations/456". Required when the account has more than one location; the API auto-selects only for single-location accounts. List them with getGoogleBusinessLocations(). */
|
|
363
378
|
gbpLocationId?: string;
|
|
379
|
+
/** Publish to the location's gallery instead of creating a Local Post. Omitting it (or sending any other value) keeps the Local Post behaviour. */
|
|
380
|
+
gbpPostType?: 'MEDIA' | 'PHOTO' | 'GALLERY';
|
|
381
|
+
/** Gallery category for the uploaded photo. Only used with gbpPostType. Defaults to ADDITIONAL. */
|
|
382
|
+
gbpMediaCategory?: GoogleBusinessMediaCategory;
|
|
364
383
|
/** Post type. Defaults to STANDARD. */
|
|
365
384
|
gbpTopicType?: 'STANDARD' | 'EVENT' | 'OFFER';
|
|
366
385
|
/** Media URL attached to the post */
|
|
@@ -496,9 +515,31 @@ declare module 'upload-post' {
|
|
|
496
515
|
[key: string]: any;
|
|
497
516
|
}
|
|
498
517
|
|
|
518
|
+
/**
|
|
519
|
+
* Instagram audience breakdown. Each key maps a bucket (age range, gender,
|
|
520
|
+
* country code, city name) to a follower/engager count.
|
|
521
|
+
*/
|
|
522
|
+
export interface DemographicsBreakdown {
|
|
523
|
+
age?: Record<string, number>;
|
|
524
|
+
gender?: Record<string, number>;
|
|
525
|
+
country?: Record<string, number>;
|
|
526
|
+
city?: Record<string, number>;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
export interface InstagramAnalytics {
|
|
530
|
+
/** Breakdown of the account's followers. */
|
|
531
|
+
follower_demographics?: DemographicsBreakdown;
|
|
532
|
+
/** Breakdown of the accounts that engaged with the profile's content. Same shape as follower_demographics. */
|
|
533
|
+
engaged_audience_demographics?: DemographicsBreakdown;
|
|
534
|
+
[key: string]: any;
|
|
535
|
+
}
|
|
536
|
+
|
|
499
537
|
export interface AnalyticsResponse {
|
|
500
538
|
success: boolean;
|
|
501
|
-
analytics?:
|
|
539
|
+
analytics?: {
|
|
540
|
+
instagram?: InstagramAnalytics;
|
|
541
|
+
[platform: string]: any;
|
|
542
|
+
};
|
|
502
543
|
[key: string]: any;
|
|
503
544
|
}
|
|
504
545
|
|
|
@@ -654,6 +695,48 @@ declare module 'upload-post' {
|
|
|
654
695
|
}>;
|
|
655
696
|
}>;
|
|
656
697
|
|
|
698
|
+
/**
|
|
699
|
+
* Replay per-post metrics already fetched, instead of querying
|
|
700
|
+
* the platforms live. Not subject to the live post-analytics rate limit
|
|
701
|
+
* (100 requests / 5 minutes), so it is the right call for paging through a
|
|
702
|
+
* profile's whole post history.
|
|
703
|
+
*
|
|
704
|
+
* @param user - Profile username
|
|
705
|
+
* @param options - Query options
|
|
706
|
+
*/
|
|
707
|
+
getCachedPostAnalytics(user: string, options?: {
|
|
708
|
+
platform?: 'instagram' | 'tiktok' | 'youtube' | 'facebook' | 'linkedin' | 'threads' | 'pinterest' | 'reddit';
|
|
709
|
+
/** Posts per page. Default 50, max 200. */
|
|
710
|
+
limit?: number;
|
|
711
|
+
/** Opaque cursor from a previous response's next_cursor. */
|
|
712
|
+
cursor?: string;
|
|
713
|
+
/** Start date, YYYY-MM-DD. Defaults to 30 days ago. */
|
|
714
|
+
since?: string;
|
|
715
|
+
/** End date, YYYY-MM-DD. Defaults to today. */
|
|
716
|
+
until?: string;
|
|
717
|
+
}): Promise<{
|
|
718
|
+
success: boolean;
|
|
719
|
+
profile_username: string;
|
|
720
|
+
platform: string | null;
|
|
721
|
+
since: string;
|
|
722
|
+
until: string;
|
|
723
|
+
source: 'snapshot_cache';
|
|
724
|
+
posts: Array<{
|
|
725
|
+
post_id: string;
|
|
726
|
+
platform: string;
|
|
727
|
+
profile_username: string;
|
|
728
|
+
date: string;
|
|
729
|
+
captured_at: string;
|
|
730
|
+
metrics: Record<string, number>;
|
|
731
|
+
post_url?: string | null;
|
|
732
|
+
media_type?: string | null;
|
|
733
|
+
upload_timestamp?: string | null;
|
|
734
|
+
}>;
|
|
735
|
+
limit: number;
|
|
736
|
+
next_cursor: string | null;
|
|
737
|
+
has_more: boolean;
|
|
738
|
+
}>;
|
|
739
|
+
|
|
657
740
|
/**
|
|
658
741
|
* Get available metrics configuration for all supported platforms
|
|
659
742
|
*/
|
|
@@ -667,11 +750,13 @@ declare module 'upload-post' {
|
|
|
667
750
|
* Get recent media from a connected social account.
|
|
668
751
|
*
|
|
669
752
|
* @param options.pageUrn - LinkedIn only. Numeric org ID, full org URN, or "me" to force the personal profile.
|
|
753
|
+
* @param options.limit - Items per page. Default 25, clamped to 1-100. Per-platform caps: TikTok 20, YouTube 50, everything else 100.
|
|
754
|
+
* @param options.cursor - Opaque cursor from a previous response's `pagination.next_cursor`. LinkedIn, Discord and Telegram do not support cursors: passing one there returns HTTP 400.
|
|
670
755
|
*/
|
|
671
756
|
getMedia(
|
|
672
757
|
platform: 'instagram' | 'tiktok' | 'youtube' | 'linkedin' | 'facebook' | 'x' | 'threads' | 'pinterest' | 'bluesky' | 'reddit' | string,
|
|
673
758
|
user: string,
|
|
674
|
-
options?: { pageUrn?: string }
|
|
759
|
+
options?: { pageUrn?: string; limit?: number; cursor?: string }
|
|
675
760
|
): Promise<{
|
|
676
761
|
success: boolean;
|
|
677
762
|
media: Array<{
|
|
@@ -683,6 +768,12 @@ declare module 'upload-post' {
|
|
|
683
768
|
timestamp: string | null;
|
|
684
769
|
thumbnail_url: string | null;
|
|
685
770
|
}>;
|
|
771
|
+
pagination?: {
|
|
772
|
+
limit: number;
|
|
773
|
+
/** null on the last page. */
|
|
774
|
+
next_cursor: string | null;
|
|
775
|
+
has_more: boolean;
|
|
776
|
+
};
|
|
686
777
|
}>;
|
|
687
778
|
|
|
688
779
|
// Scheduled Posts
|
|
@@ -736,14 +827,32 @@ declare module 'upload-post' {
|
|
|
736
827
|
readonlyCalendar?: boolean;
|
|
737
828
|
connectTitle?: string;
|
|
738
829
|
connectDescription?: string;
|
|
739
|
-
language?: 'en' | 'es' | 'de' | 'fr' | 'pt';
|
|
830
|
+
language?: 'en' | 'es' | 'de' | 'fr' | 'pt' | 'pl' | 'tr';
|
|
831
|
+
/**
|
|
832
|
+
* Flat map of i18n dot-path keys to replacement strings, e.g.
|
|
833
|
+
* `{ 'connect.title': 'Link your accounts' }`. Max 100 entries; keys must
|
|
834
|
+
* match `^[a-zA-Z0-9_.]+$` and values are strings of up to 300 characters.
|
|
835
|
+
* Returned back in the `profile` object of validateJwt.
|
|
836
|
+
*/
|
|
837
|
+
uiLabels?: Record<string, string>;
|
|
740
838
|
}): Promise<JwtResponse>;
|
|
741
839
|
|
|
742
840
|
/**
|
|
743
841
|
* Validate a JWT token
|
|
744
842
|
* @param jwt - JWT token to validate
|
|
745
843
|
*/
|
|
746
|
-
validateJwt(jwt: string): Promise<{
|
|
844
|
+
validateJwt(jwt: string): Promise<{
|
|
845
|
+
success: boolean;
|
|
846
|
+
valid?: boolean;
|
|
847
|
+
profile?: {
|
|
848
|
+
username?: string;
|
|
849
|
+
language?: 'en' | 'es' | 'de' | 'fr' | 'pt' | 'pl' | 'tr';
|
|
850
|
+
/** The ui_labels sent to generateJwt, echoed back for the connection page. */
|
|
851
|
+
ui_labels?: Record<string, string>;
|
|
852
|
+
[key: string]: any;
|
|
853
|
+
};
|
|
854
|
+
[key: string]: any;
|
|
855
|
+
}>;
|
|
747
856
|
|
|
748
857
|
/**
|
|
749
858
|
* Get user preferences (including calendar settings)
|
package/index.js
CHANGED
|
@@ -348,10 +348,16 @@ export class UploadPost {
|
|
|
348
348
|
*
|
|
349
349
|
* gbpLocationId is required for accounts with more than one location; the API
|
|
350
350
|
* only auto-selects when exactly one location exists.
|
|
351
|
+
*
|
|
352
|
+
* gbpPostType switches the call from the default Local Post to a gallery
|
|
353
|
+
* photo upload (MEDIA / PHOTO / GALLERY). Any other value, or omitting it,
|
|
354
|
+
* keeps the Local Post behaviour.
|
|
351
355
|
* @private
|
|
352
356
|
*/
|
|
353
357
|
_addGoogleBusinessParams(form, options) {
|
|
354
358
|
if (options.gbpLocationId) form.append('gbp_location_id', options.gbpLocationId);
|
|
359
|
+
if (options.gbpPostType) form.append('gbp_post_type', String(options.gbpPostType).toUpperCase());
|
|
360
|
+
if (options.gbpMediaCategory) form.append('gbp_media_category', String(options.gbpMediaCategory).toUpperCase());
|
|
355
361
|
if (options.gbpTopicType) form.append('gbp_topic_type', String(options.gbpTopicType).toUpperCase());
|
|
356
362
|
if (options.gbpMediaUrl) form.append('gbp_media_url', options.gbpMediaUrl);
|
|
357
363
|
if (options.gbpMediaFormat) form.append('gbp_media_format', String(options.gbpMediaFormat).toUpperCase());
|
|
@@ -814,6 +820,33 @@ export class UploadPost {
|
|
|
814
820
|
});
|
|
815
821
|
}
|
|
816
822
|
|
|
823
|
+
/**
|
|
824
|
+
* Replay per-post metrics already fetched, instead of querying the
|
|
825
|
+
* platforms live.
|
|
826
|
+
*
|
|
827
|
+
* Because it never calls the platform APIs it is not subject to the live
|
|
828
|
+
* post-analytics rate limit (100 requests / 5 minutes), which makes it the
|
|
829
|
+
* right method for paging through a profile's whole post history.
|
|
830
|
+
*
|
|
831
|
+
* @param {string} user - Profile username
|
|
832
|
+
* @param {Object} [options] - Query options
|
|
833
|
+
* @param {string} [options.platform] - Filter by platform (instagram, tiktok, youtube, facebook, linkedin, threads, pinterest, reddit)
|
|
834
|
+
* @param {number} [options.limit=50] - Posts per page (max 200)
|
|
835
|
+
* @param {string} [options.cursor] - Opaque cursor from a previous response's next_cursor
|
|
836
|
+
* @param {string} [options.since] - Start date in YYYY-MM-DD format (defaults to 30 days ago)
|
|
837
|
+
* @param {string} [options.until] - End date in YYYY-MM-DD format (defaults to today)
|
|
838
|
+
* @returns {Promise<Object>} Cached post metrics with next_cursor and has_more
|
|
839
|
+
*/
|
|
840
|
+
async getCachedPostAnalytics(user, options = {}) {
|
|
841
|
+
const params = { user };
|
|
842
|
+
if (options.platform) params.platform = options.platform;
|
|
843
|
+
if (options.limit !== undefined) params.limit = options.limit;
|
|
844
|
+
if (options.cursor) params.cursor = options.cursor;
|
|
845
|
+
if (options.since) params.since = options.since;
|
|
846
|
+
if (options.until) params.until = options.until;
|
|
847
|
+
return this._request('/uploadposts/post-analytics/cached', 'GET', params);
|
|
848
|
+
}
|
|
849
|
+
|
|
817
850
|
/**
|
|
818
851
|
* Get available metrics configuration for all supported platforms
|
|
819
852
|
*
|
|
@@ -840,11 +873,16 @@ export class UploadPost {
|
|
|
840
873
|
* @param {string} user - Profile username
|
|
841
874
|
* @param {Object} [options]
|
|
842
875
|
* @param {string} [options.pageUrn] - LinkedIn only. Numeric org ID, full URN, or "me" to force the personal profile.
|
|
843
|
-
* @
|
|
876
|
+
* @param {number} [options.limit=25] - Items per page, clamped to 1-100. Per-platform caps: TikTok 20, YouTube 50, everything else 100.
|
|
877
|
+
* @param {string} [options.cursor] - Opaque cursor from a previous response's `pagination.next_cursor`.
|
|
878
|
+
* LinkedIn, Discord and Telegram do not support cursors: passing one there returns HTTP 400.
|
|
879
|
+
* @returns {Promise<Object>} `{ success, media, pagination: { limit, next_cursor, has_more } }`
|
|
844
880
|
*/
|
|
845
881
|
async getMedia(platform, user, options = {}) {
|
|
846
882
|
const params = { platform, user };
|
|
847
883
|
if (options.pageUrn) params.page_urn = options.pageUrn;
|
|
884
|
+
if (options.limit !== undefined) params.limit = options.limit;
|
|
885
|
+
if (options.cursor) params.cursor = options.cursor;
|
|
848
886
|
return this._request('/uploadposts/media', 'GET', params);
|
|
849
887
|
}
|
|
850
888
|
|
|
@@ -930,7 +968,8 @@ export class UploadPost {
|
|
|
930
968
|
* @param {boolean} [options.readonlyCalendar] - Show only a read-only calendar (no editing, no account connection)
|
|
931
969
|
* @param {string} [options.connectTitle] - Custom title for the connection page
|
|
932
970
|
* @param {string} [options.connectDescription] - Custom description for the connection page
|
|
933
|
-
* @param {('en'|'es'|'de'|'fr'|'pt')} [options.language] - Force the connection page language for this profile. When omitted, the page auto-detects the visitor's browser language and falls back to English.
|
|
971
|
+
* @param {('en'|'es'|'de'|'fr'|'pt'|'pl'|'tr')} [options.language] - Force the connection page language for this profile. When omitted, the page auto-detects the visitor's browser language and falls back to English.
|
|
972
|
+
* @param {Object.<string, string>} [options.uiLabels] - Flat map of i18n dot-path keys to replacement strings, e.g. `{ 'connect.title': 'Link your accounts' }`. Max 100 entries; keys must match `^[a-zA-Z0-9_.]+$` and values are strings of up to 300 characters. Returned back in the `profile` object of validateJwt.
|
|
934
973
|
* @returns {Promise<Object>} JWT and connection URL
|
|
935
974
|
*/
|
|
936
975
|
async generateJwt(username, options = {}) {
|
|
@@ -944,6 +983,7 @@ export class UploadPost {
|
|
|
944
983
|
if (options.connectTitle) body.connect_title = options.connectTitle;
|
|
945
984
|
if (options.connectDescription) body.connect_description = options.connectDescription;
|
|
946
985
|
if (options.language) body.language = options.language;
|
|
986
|
+
if (options.uiLabels) body.ui_labels = options.uiLabels;
|
|
947
987
|
return this._request('/uploadposts/users/generate-jwt', 'POST', body);
|
|
948
988
|
}
|
|
949
989
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "upload-post",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "Official client library for Upload-Post API - Cross-platform social media upload for TikTok, Instagram, YouTube, LinkedIn, Facebook, Pinterest, Threads, Reddit, Bluesky, and X (Twitter)",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"types": "index.d.ts",
|
|
@@ -26,7 +26,10 @@
|
|
|
26
26
|
"x",
|
|
27
27
|
"api-client",
|
|
28
28
|
"social-media-api",
|
|
29
|
-
"upload-post"
|
|
29
|
+
"upload-post",
|
|
30
|
+
"mcp",
|
|
31
|
+
"model-context-protocol",
|
|
32
|
+
"ai-agent"
|
|
30
33
|
],
|
|
31
34
|
"repository": {
|
|
32
35
|
"type": "git",
|