upload-post 2.10.0__tar.gz → 2.13.0__tar.gz
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.
- {upload_post-2.10.0 → upload_post-2.13.0}/PKG-INFO +296 -21
- {upload_post-2.10.0 → upload_post-2.13.0}/README.md +295 -20
- {upload_post-2.10.0 → upload_post-2.13.0}/setup.py +1 -1
- upload_post-2.13.0/tests/test_comments_audience.py +231 -0
- upload_post-2.13.0/tests/test_parity_fields.py +292 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post/__init__.py +1 -1
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post/api_client.py +666 -80
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post.egg-info/PKG-INFO +296 -21
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post.egg-info/SOURCES.txt +2 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/setup.cfg +0 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post/cli.py +0 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post.egg-info/dependency_links.txt +0 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post.egg-info/requires.txt +0 -0
- {upload_post-2.10.0 → upload_post-2.13.0}/upload_post.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: upload-post
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.13.0
|
|
4
4
|
Summary: Cross-platform social media upload for TikTok, Instagram, YouTube, LinkedIn, Facebook, Pinterest, Threads, Reddit, Bluesky, Discord, Telegram, and X (Twitter)
|
|
5
5
|
Home-page: https://www.upload-post.com/
|
|
6
6
|
Author: Upload-Post
|
|
@@ -76,6 +76,8 @@ print(response)
|
|
|
76
76
|
- ✅ **Posting Queue** - Add posts to your configured queue
|
|
77
77
|
- ✅ **First Comments** - Auto-post first comment after publishing
|
|
78
78
|
- ✅ **Analytics** - Get engagement metrics
|
|
79
|
+
- ✅ **Audience** - Who follows a profile, per platform
|
|
80
|
+
- ✅ **Suggestions** - Hashtags and searches to post about, per platform
|
|
79
81
|
- ✅ **Full Type Hints**
|
|
80
82
|
|
|
81
83
|
## API Reference
|
|
@@ -322,17 +324,183 @@ found = client.search_tiktok_music("my-profile", q="bad bunny", country_code="ES
|
|
|
322
324
|
locations = client.get_tiktok_locations("my-profile", "Madrid")
|
|
323
325
|
```
|
|
324
326
|
|
|
327
|
+
### Comments
|
|
328
|
+
|
|
329
|
+
The same methods cover every platform that has comments — Instagram, Facebook,
|
|
330
|
+
YouTube, LinkedIn and TikTok. There is no per-network method: the endpoint
|
|
331
|
+
answers one question and `platform` says who to ask.
|
|
332
|
+
|
|
333
|
+
```python
|
|
334
|
+
# Read the comments on a post. TikTok has no post-URL lookup: pass the video id.
|
|
335
|
+
comments = client.get_post_comments(
|
|
336
|
+
user="my-profile",
|
|
337
|
+
platform="tiktok",
|
|
338
|
+
post_id="7412345678901234567",
|
|
339
|
+
limit=20,
|
|
340
|
+
)
|
|
341
|
+
|
|
342
|
+
# Read the replies hanging from one of them — same question, one more parameter
|
|
343
|
+
replies = client.get_post_comments(
|
|
344
|
+
user="my-profile",
|
|
345
|
+
platform="tiktok",
|
|
346
|
+
post_id="7412345678901234567",
|
|
347
|
+
comment_id="7412345678909999999",
|
|
348
|
+
)
|
|
349
|
+
|
|
350
|
+
# Comment on the post, or reply to a comment
|
|
351
|
+
client.create_comment(
|
|
352
|
+
user="my-profile",
|
|
353
|
+
platform="tiktok",
|
|
354
|
+
post_id="7412345678901234567",
|
|
355
|
+
message="Thanks for watching!",
|
|
356
|
+
)
|
|
357
|
+
client.create_comment(
|
|
358
|
+
user="my-profile",
|
|
359
|
+
platform="tiktok",
|
|
360
|
+
comment_id="7412345678909999999",
|
|
361
|
+
message="Glad you liked it",
|
|
362
|
+
)
|
|
363
|
+
|
|
364
|
+
# Delete one
|
|
365
|
+
client.delete_comment(
|
|
366
|
+
user="my-profile", platform="tiktok", comment_id="7412345678909999999"
|
|
367
|
+
)
|
|
368
|
+
```
|
|
369
|
+
|
|
370
|
+
You can also have the first comment posted for you right after publishing, with
|
|
371
|
+
`first_comment` for every platform or `tiktok_first_comment` for TikTok alone.
|
|
372
|
+
|
|
373
|
+
On TikTok all of this needs the `comments` capability, which the account grants
|
|
374
|
+
when it connects — see
|
|
375
|
+
[What a TikTok connection can do](#what-a-tiktok-connection-can-do-capabilities).
|
|
376
|
+
|
|
377
|
+
#### Moderating a comment: hide, like, pin
|
|
378
|
+
|
|
379
|
+
`comment_action()` does the three and undoes them, on any platform that
|
|
380
|
+
supports it. Each action carries its own inverse, and `post_id` is only sent
|
|
381
|
+
when the platform needs it:
|
|
382
|
+
|
|
383
|
+
```python
|
|
384
|
+
client.comment_action(
|
|
385
|
+
user="my-profile", platform="tiktok", action="hide",
|
|
386
|
+
comment_id="7412345678909999999", post_id="7412345678901234567",
|
|
387
|
+
)
|
|
388
|
+
client.comment_action(
|
|
389
|
+
user="my-profile", platform="tiktok", action="like",
|
|
390
|
+
comment_id="7412345678909999999",
|
|
391
|
+
)
|
|
392
|
+
client.comment_action(
|
|
393
|
+
user="my-profile", platform="tiktok", action="unpin",
|
|
394
|
+
comment_id="7412345678909999999", post_id="7412345678901234567",
|
|
395
|
+
)
|
|
396
|
+
```
|
|
397
|
+
|
|
398
|
+
| `action` | Undo | `post_id` |
|
|
399
|
+
| --- | --- | --- |
|
|
400
|
+
| `hide` | `unhide` | required |
|
|
401
|
+
| `like` | `unlike` | not sent |
|
|
402
|
+
| `pin` | `unpin` | required |
|
|
403
|
+
|
|
404
|
+
### Audience
|
|
405
|
+
|
|
406
|
+
Where the analytics methods answer *how did my posts do*, `get_audience()`
|
|
407
|
+
answers *who is following me*. One endpoint, one `platform` parameter, like
|
|
408
|
+
every other question in the API.
|
|
409
|
+
|
|
410
|
+
```python
|
|
411
|
+
audience = client.get_audience(
|
|
412
|
+
user="my-profile",
|
|
413
|
+
platform="tiktok",
|
|
414
|
+
start_date="2026-07-01",
|
|
415
|
+
end_date="2026-07-30",
|
|
416
|
+
)
|
|
417
|
+
|
|
418
|
+
print(audience["range"]) # the window actually used
|
|
419
|
+
print(audience["audience"]["countries"]) # and "cities", "ages", "genders"
|
|
420
|
+
print(audience["activity_by_hour"]) # [{"hour": "14", "followers_online": 1494}, ...]
|
|
421
|
+
print(audience["followers_daily"]) # [{"date", "total", "new", "lost"}, ...]
|
|
422
|
+
print(audience["profile_actions"]) # bio link, address, email, phone, leads
|
|
423
|
+
print(audience["bio_description"])
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
The window is clamped on the server: at most 60 days, and `end_date` always
|
|
427
|
+
before today. A wider window is trimmed to what the platform accepts instead of
|
|
428
|
+
failing.
|
|
429
|
+
|
|
430
|
+
Ask for a `benchmark_category` and the same call also returns how the account
|
|
431
|
+
compares with the average of that category. The accepted categories come back in
|
|
432
|
+
`benchmark_categories` on every response, so a picker needs no second call:
|
|
433
|
+
|
|
434
|
+
```python
|
|
435
|
+
categories = client.get_audience(
|
|
436
|
+
user="my-profile", platform="tiktok"
|
|
437
|
+
)["benchmark_categories"]
|
|
438
|
+
|
|
439
|
+
benchmark = client.get_audience(
|
|
440
|
+
user="my-profile", platform="tiktok",
|
|
441
|
+
benchmark_category="SOFTWARE_AND_APPS",
|
|
442
|
+
)["benchmark"]
|
|
443
|
+
print(benchmark["average_engagement_rate"], benchmark["average_video_views"])
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
### Suggestions
|
|
447
|
+
|
|
448
|
+
`get_suggestions()` answers *what is worth posting about*: the hashtags or the
|
|
449
|
+
searches a platform suggests around a keyword. One endpoint for both, told apart
|
|
450
|
+
by `type`.
|
|
451
|
+
|
|
452
|
+
```python
|
|
453
|
+
hashtags = client.get_suggestions(
|
|
454
|
+
user="my-profile", platform="tiktok", type="hashtags",
|
|
455
|
+
q="pilates", country_code="ES", language="es",
|
|
456
|
+
)["hashtags"]
|
|
457
|
+
print(hashtags) # [{"name": ..., "view_count": ...}, ...]
|
|
458
|
+
|
|
459
|
+
keywords = client.get_suggestions(
|
|
460
|
+
user="my-profile", platform="tiktok", type="keywords", q="pilates",
|
|
461
|
+
)["keywords"]
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
Per-post numbers stay in `get_post_analytics()`. On TikTok that response carries
|
|
465
|
+
more than the usual counters: `retention` (the curve, second by second),
|
|
466
|
+
`impression_sources` (For You, search, profile...), `audience_types` (followers
|
|
467
|
+
vs non-followers), `new_followers`, `reach` and the watch times.
|
|
468
|
+
|
|
469
|
+
Asking a platform a question it cannot answer fails with
|
|
470
|
+
`platform_not_supported` and the list of the ones that can.
|
|
471
|
+
|
|
472
|
+
## What a TikTok connection can do (`capabilities`)
|
|
473
|
+
|
|
474
|
+
Not every TikTok connection can do the same things. `client.list_users()`
|
|
475
|
+
(`GET /api/uploadposts/users`) returns a `capabilities` array on each profile's
|
|
476
|
+
TikTok account; check it before offering a feature.
|
|
477
|
+
|
|
478
|
+
| Capability | What it unlocks |
|
|
479
|
+
| --- | --- |
|
|
480
|
+
| `music` | `tiktok_music_id` and the volume/trim fields, plus `get_tiktok_trending_music()` and `search_tiktok_music()` |
|
|
481
|
+
| `location` | `tiktok_location_id` / `tiktok_location_name`, plus `get_tiktok_locations()` |
|
|
482
|
+
| `cover_image` | `tiktok_cover_image_url` |
|
|
483
|
+
| `cover_timestamp` | `cover_timestamp` |
|
|
484
|
+
| `draft` | `tiktok_upload_to_draft` or `post_mode="MEDIA_UPLOAD"` (same draft) |
|
|
485
|
+
| `video_privacy` | `privacy_level` on video |
|
|
486
|
+
| `photo_privacy` | `privacy_level` on photo posts |
|
|
487
|
+
| `profile_analytics` | `get_audience()` and `get_suggestions(type="hashtags")` with `platform="tiktok"` |
|
|
488
|
+
| `comments` | Comments on TikTok: `get_post_comments()` (top-level and replies), `create_comment()`, `delete_comment()`, `comment_action()` and `tiktok_first_comment` |
|
|
489
|
+
| `trend_search` | `get_suggestions(type="keywords")` with `platform="tiktok"` |
|
|
490
|
+
|
|
491
|
+
> **`comments` and `trend_search` need the account to be reconnected.** TikTok
|
|
492
|
+
> grants them at connect time, so an account linked before they existed keeps
|
|
493
|
+
> working for everything else but will not list them — reconnect it from Manage
|
|
494
|
+
> Users to enable them.
|
|
495
|
+
|
|
496
|
+
If a connection lacks a capability the upload field is simply ignored: the post
|
|
497
|
+
still publishes and the response carries a per-field `warnings` string. The
|
|
498
|
+
methods above answer with an error asking for a reconnection.
|
|
499
|
+
|
|
325
500
|
## TikTok music, location, cover and drafts
|
|
326
501
|
|
|
327
|
-
>
|
|
328
|
-
>
|
|
329
|
-
> `capabilities` array on the TikTok account returned by
|
|
330
|
-
> `GET /api/uploadposts/users` (`client.list_users()`). Other values that can
|
|
331
|
-
> appear there: `cover_timestamp`, `photo_privacy`, `video_privacy`,
|
|
332
|
-
> `inbox_fallback` and `profile_analytics`. If your connection does
|
|
333
|
-
> not have the capability, the field is ignored, the post still publishes, and
|
|
334
|
-
> the response includes a per-field `warnings` string — reconnect the TikTok
|
|
335
|
-
> account to enable it.
|
|
502
|
+
> Needs the `music`, `location`, `cover_image` or `draft` capability — see
|
|
503
|
+
> [What a TikTok connection can do](#what-a-tiktok-connection-can-do-capabilities).
|
|
336
504
|
|
|
337
505
|
```python
|
|
338
506
|
# 1. Pick a track and a place
|
|
@@ -360,7 +528,7 @@ client.upload_video(
|
|
|
360
528
|
|
|
361
529
|
tiktok_cover_image_url="https://example.com/cover.jpg",
|
|
362
530
|
tiktok_is_ai_generated=False,
|
|
363
|
-
tiktok_upload_to_draft=False,
|
|
531
|
+
tiktok_upload_to_draft=False, # same draft as post_mode="MEDIA_UPLOAD"
|
|
364
532
|
)
|
|
365
533
|
```
|
|
366
534
|
|
|
@@ -376,10 +544,13 @@ client.upload_video(
|
|
|
376
544
|
| `tiktok_location_id` | str | `location` | Video + photos. `location_id` from `get_tiktok_locations()` |
|
|
377
545
|
| `tiktok_location_name` | str | `location` | Required whenever `tiktok_location_id` is set |
|
|
378
546
|
| `tiktok_cover_image_url` | str | `cover_image` | Video only. Custom cover image URL |
|
|
379
|
-
| `tiktok_is_ai_generated` | bool | — | Video + photos. AI-generated content disclosure |
|
|
380
|
-
| `tiktok_upload_to_draft` | bool | `draft` | Video
|
|
547
|
+
| `tiktok_is_ai_generated` | bool | — | Video + photos. AI-generated content disclosure (aliases: `is_ai_generated`) |
|
|
548
|
+
| `tiktok_upload_to_draft` | bool | `draft` | Video + photos. Same draft as `post_mode="MEDIA_UPLOAD"` (aliases: `upload_to_draft`, `is_draft`). TikTok ignores the rest of the post settings |
|
|
549
|
+
| `tiktok_is_ads_only` | bool | — | Video. Only show in ads (alias: `is_ads_only`) |
|
|
550
|
+
| `tiktok_tto_invite_link` | str | — | Video. TikTok One invite link; needs branded content (alias: `tto_invite_link`) |
|
|
381
551
|
| `photo_cover_index` | int | — | Cover photo index for photo posts (0-based) |
|
|
382
552
|
| `privacy_level` | str | `photo_privacy` / `video_privacy` | Accepted on video and photo posts alike; which values the account may use is decided by TikTok, see the note below |
|
|
553
|
+
| `post_mode` | str | `draft` | `DIRECT_POST` or `MEDIA_UPLOAD`. `MEDIA_UPLOAD` is the same draft as `tiktok_upload_to_draft=True` |
|
|
383
554
|
|
|
384
555
|
## Platform-Specific Options
|
|
385
556
|
|
|
@@ -389,9 +560,11 @@ client.upload_video(
|
|
|
389
560
|
- `disable_stitch` - Disable stitch
|
|
390
561
|
- `cover_timestamp` - Timestamp in ms for cover
|
|
391
562
|
- `is_aigc` - AI-generated content flag
|
|
392
|
-
- `post_mode` - DIRECT_POST or MEDIA_UPLOAD
|
|
563
|
+
- `post_mode` - DIRECT_POST or MEDIA_UPLOAD. `MEDIA_UPLOAD` is the same draft as `tiktok_upload_to_draft=True`
|
|
393
564
|
- `brand_content_toggle` - Branded content toggle
|
|
394
565
|
- `brand_organic_toggle` - Brand organic toggle
|
|
566
|
+
- `tiktok_is_ads_only` - Only show the video in ads (alias: `is_ads_only`)
|
|
567
|
+
- `tiktok_tto_invite_link` - TikTok One invite link; needs branded content (alias: `tto_invite_link`)
|
|
395
568
|
|
|
396
569
|
> **TikTok particularity:** `privacy_level` works on video and photo posts
|
|
397
570
|
> alike, but **TikTok decides per account which values are available**. A
|
|
@@ -410,17 +583,19 @@ for the music, location, cover and draft options.
|
|
|
410
583
|
|
|
411
584
|
### TikTok (Photos)
|
|
412
585
|
- `privacy_level` - PUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY
|
|
413
|
-
- `post_mode` - DIRECT_POST or MEDIA_UPLOAD
|
|
586
|
+
- `post_mode` - DIRECT_POST or MEDIA_UPLOAD. `MEDIA_UPLOAD` is the same draft as `tiktok_upload_to_draft=True`
|
|
414
587
|
- `auto_add_music` - Auto add music
|
|
415
588
|
- `photo_cover_index` - Index of photo for cover (0-based)
|
|
416
589
|
- `disable_comment` - Disable comments
|
|
417
590
|
- `tiktok_music_id` - Commercial Music Library track id
|
|
418
591
|
- `tiktok_location_id` / `tiktok_location_name` - Location tag, both required together
|
|
419
592
|
- `tiktok_is_ai_generated` - AI-generated content disclosure
|
|
593
|
+
- `tiktok_upload_to_draft` - Same draft as `post_mode="MEDIA_UPLOAD"` (aliases: `upload_to_draft`, `is_draft`)
|
|
420
594
|
|
|
421
595
|
> TikTok's photo contract takes the music track id alone: `tiktok_music_volume`,
|
|
422
|
-
> `tiktok_music_start`, `tiktok_music_end`, `tiktok_original_sound_volume
|
|
423
|
-
> `tiktok_cover_image_url`
|
|
596
|
+
> `tiktok_music_start`, `tiktok_music_end`, `tiktok_original_sound_volume` and
|
|
597
|
+
> `tiktok_cover_image_url` are video-only. `post_mode="MEDIA_UPLOAD"` and
|
|
598
|
+
> `tiktok_upload_to_draft=True` are aliases of the same draft.
|
|
424
599
|
|
|
425
600
|
### Instagram
|
|
426
601
|
- `media_type` - REELS, STORIES, IMAGE
|
|
@@ -431,6 +606,7 @@ for the music, location, cover and draft options.
|
|
|
431
606
|
- `user_tags` - Comma-separated user tags
|
|
432
607
|
- `location_id` - Location ID
|
|
433
608
|
- `thumb_offset` - Thumbnail offset
|
|
609
|
+
- `instagram_alt_text` - Alt text (string, or JSON list / one per carousel item)
|
|
434
610
|
|
|
435
611
|
### YouTube
|
|
436
612
|
- `tags` - List or comma-separated tags
|
|
@@ -448,10 +624,19 @@ for the music, location, cover and draft options.
|
|
|
448
624
|
- `hasPaidProductPlacement` - Paid placement flag
|
|
449
625
|
- `recordingDate` - Recording date (ISO 8601)
|
|
450
626
|
- `youtube_playlist_id` - Playlist ID (single string, list, or comma-separated) to add the uploaded video to after publishing
|
|
627
|
+
- `youtube_notify_subscribers` - Notify subscribers (default `true`; send `false` to skip)
|
|
628
|
+
- `youtube_publish_at` - RFC3339 time; uploads as private and schedules on YouTube
|
|
451
629
|
|
|
452
630
|
### LinkedIn
|
|
453
|
-
- `visibility` - PUBLIC, CONNECTIONS, LOGGED_IN, CONTAINER
|
|
631
|
+
- `visibility` / `linkedin_visibility` - PUBLIC, CONNECTIONS, LOGGED_IN, CONTAINER
|
|
454
632
|
- `target_linkedin_page_id` - Page ID for organization posts
|
|
633
|
+
- `linkedin_alt_text` - Alt text per image (string, JSON list, or repeated)
|
|
634
|
+
- `linkedin_disable_reshare` - Disable reshare by others
|
|
635
|
+
- `linkedin_link_title` / `linkedin_link_description` / `linkedin_thumbnail_alt_text` - Article/link-share overrides
|
|
636
|
+
- `linkedin_target_geo_locations` / `linkedin_target_industries` / `linkedin_target_seniorities` / `linkedin_target_job_functions` / `linkedin_target_staff_count_ranges` / `linkedin_target_interface_locales` / `linkedin_target_degrees` / `linkedin_target_fields_of_study` / `linkedin_target_organizations` - Page targeting (needs `target_linkedin_page_id`)
|
|
637
|
+
- `linkedin_target_entities` - Raw targeting JSON instead of the fields above
|
|
638
|
+
- `linkedin_target_check_audience` - Reject if LinkedIn reports fewer than 300 followers in the segment
|
|
639
|
+
- `linkedin_subtitles` / `linkedin_subtitles_url` / `linkedin_subtitles_text` - English SRT captions on video
|
|
455
640
|
|
|
456
641
|
### Facebook
|
|
457
642
|
- `facebook_page_id` - Facebook Page ID (required)
|
|
@@ -459,13 +644,25 @@ for the music, location, cover and draft options.
|
|
|
459
644
|
- `facebook_media_type` - REELS, STORIES, or VIDEO (normal page video)
|
|
460
645
|
- `thumbnail_url` - Thumbnail URL for normal page videos (only when `facebook_media_type` is VIDEO)
|
|
461
646
|
- `facebook_link_url` - URL for text posts
|
|
647
|
+
- `facebook_alt_text` - Alt text per photo (string, `facebook_alt_text[]`, or JSON array)
|
|
648
|
+
- `facebook_place_id` - Place id on feed/photos/videos/reels
|
|
649
|
+
- `facebook_targeting` / `facebook_feed_targeting` - JSON audience objects
|
|
650
|
+
- `facebook_call_to_action` / `facebook_child_attachments` / `facebook_multi_share_end_card` - Link post CTA and carousel
|
|
651
|
+
- `facebook_is_ai_generated` - AI-generated flag on Reels
|
|
652
|
+
- `facebook_collaborators` - Page ids to invite on Reels
|
|
653
|
+
- `facebook_unpublished_content_type` - DRAFT / INLINE_CREATED / ADS_POST on page video (`SCHEDULED` is rejected; use `scheduled_date`)
|
|
654
|
+
- `facebook_no_story` / `facebook_secret` - Page video flags
|
|
462
655
|
|
|
463
656
|
### Pinterest
|
|
464
657
|
- `pinterest_board_id` - Board ID
|
|
465
658
|
- `pinterest_link` - Destination link
|
|
466
659
|
- `pinterest_alt_text` - Alt text for photos
|
|
467
660
|
- `pinterest_cover_image_url` - Cover image URL (video)
|
|
468
|
-
- `pinterest_cover_image_key_frame_time` - Key frame time in
|
|
661
|
+
- `pinterest_cover_image_key_frame_time` - Key frame time in seconds (values larger than the video duration are treated as milliseconds)
|
|
662
|
+
- `pinterest_board_section_id` - Board section id
|
|
663
|
+
- `pinterest_ai_disclosures` - `AI_MODIFIED` and/or `SYNTHETIC_PERFORMER`
|
|
664
|
+
- `pinterest_carousel_titles` / `pinterest_carousel_descriptions` / `pinterest_carousel_links` - Per-slide carousel fields (2–5 photos)
|
|
665
|
+
- `pinterest_carousel_index` - 0-based cover slide
|
|
469
666
|
|
|
470
667
|
### X (Twitter)
|
|
471
668
|
- `reply_settings` - everyone, following, mentionedUsers, subscribers, verified
|
|
@@ -481,15 +678,30 @@ for the music, location, cover and draft options.
|
|
|
481
678
|
- `card_uri` - Card URI for Twitter Cards
|
|
482
679
|
- `x_long_text_as_post` - Post long text as single post
|
|
483
680
|
- `x_thread_image_layout` - Comma-separated image layout for thread (e.g. "4,4" or "2,3,1"). Each value 1-4, total must equal image count. Auto-chunks into groups of 4 when >4 images.
|
|
681
|
+
- `x_alt_text` - Alt text (string, `x_alt_text[]`, or JSON array; ≤1000 chars)
|
|
682
|
+
- `x_subtitles` / `x_subtitles_url` / `x_subtitles_language` / `x_subtitles_name` - Video SRT captions
|
|
683
|
+
- `x_paid_partnership` - Paid partnership flag on the first post
|
|
684
|
+
- `x_article_title` / `x_article_body` / `x_article_content_state` / `x_article_draft` / `x_article_cover_media` - X Articles (text; Premium)
|
|
484
685
|
|
|
485
686
|
### Threads
|
|
486
|
-
- `threads_long_text_as_post` - Post long text as single post (vs thread)
|
|
487
|
-
- `threads_thread_media_layout` - Comma-separated list of how many media items to include in each Threads post (e.g. "5,5" or "3,4,3"). Each value
|
|
687
|
+
- `threads_long_text_as_post` - Post long text as single post (vs thread). Over 500 UTF-8 bytes this sends an official long post instead of truncating.
|
|
688
|
+
- `threads_thread_media_layout` - Comma-separated list of how many media items to include in each Threads post (e.g. "5,5" or "3,4,3"). Each value 0-20, total must equal media count. Auto-chunks into groups of 20 when >20 items.
|
|
488
689
|
- `threads_topic_tag` - Topic tag for the Threads post (1-50 characters, no periods or ampersands). One tag per post. Helps increase reach.
|
|
690
|
+
- `threads_reply_control` - Who can reply: `everyone`, `accounts_you_follow`, `mentioned_only`, `parent_post_author_only`, `followers_only`
|
|
691
|
+
- `threads_alt_text` - Alt text per image/video (`threads_alt_text[]`)
|
|
692
|
+
- `threads_reply_to_id` / `threads_quote_post_id` - Reply or quote
|
|
693
|
+
- `threads_link_attachment` - Force link preview (text)
|
|
694
|
+
- `threads_poll_options` - 2–4 poll options (text)
|
|
695
|
+
- `threads_auto_publish_text` - Skip the second publish call on text posts
|
|
489
696
|
|
|
490
697
|
### Reddit
|
|
698
|
+
Reddit uploads currently return `error_code=reddit_unavailable` until the Reddit app is restored.
|
|
699
|
+
|
|
491
700
|
- `subreddit` - Subreddit name (without r/)
|
|
492
701
|
- `flair_id` - Flair template ID
|
|
702
|
+
- `reddit_nsfw` / `reddit_spoiler` / `reddit_resubmit` / `reddit_send_replies` - Booleans
|
|
703
|
+
- `reddit_flair_text` - Custom text for editable flairs
|
|
704
|
+
- `reddit_gallery_captions` / `reddit_gallery_urls` - Per-image gallery caption and outbound URL
|
|
493
705
|
|
|
494
706
|
### Google Business
|
|
495
707
|
- `gbp_location_id` - Location, e.g. `"accounts/123/locations/456"` (list them with `get_google_business_locations`). Required when the account has more than one location; the API only auto-selects when exactly one exists.
|
|
@@ -500,6 +712,8 @@ for the music, location, cover and draft options.
|
|
|
500
712
|
- `gbp_cta_type` / `gbp_cta_url` - Call-to-action button
|
|
501
713
|
- `gbp_event_title` / `gbp_event_start_date` / `gbp_event_start_time` / `gbp_event_end_date` / `gbp_event_end_time` - Used with `gbp_topic_type="EVENT"`
|
|
502
714
|
- `gbp_offer_coupon` / `gbp_offer_redeem_url` / `gbp_offer_terms` - Used with `gbp_topic_type="OFFER"`
|
|
715
|
+
- `gbp_coupon_code` / `gbp_redeem_url` / `gbp_terms` - Aliases of the offer fields above (legacy names still win if both are sent)
|
|
716
|
+
- `gbp_language_code` - BCP-47 language (default `en`)
|
|
503
717
|
|
|
504
718
|
```python
|
|
505
719
|
locations = client.get_google_business_locations("my-profile")
|
|
@@ -515,6 +729,66 @@ client.upload_photos(
|
|
|
515
729
|
)
|
|
516
730
|
```
|
|
517
731
|
|
|
732
|
+
### Bluesky
|
|
733
|
+
- `bluesky_link_url` - External embed link preview (text)
|
|
734
|
+
- `bluesky_alt_text` - Alt text per image/video (JSON array, `||`-separated, or string)
|
|
735
|
+
- `bluesky_langs` - Comma list, max 3 BCP-47 codes
|
|
736
|
+
- `bluesky_labels` - `porn`, `sexual`, `nudity`, `graphic-media`
|
|
737
|
+
- `bluesky_gallery` - Publish up to 20 images as a gallery (`false` keeps the first 4)
|
|
738
|
+
- `bluesky_threadgate` / `bluesky_reply_settings` - Who can reply
|
|
739
|
+
- `bluesky_postgate` / `bluesky_quote_settings` - `disable_quotes` to block quotes
|
|
740
|
+
- `bluesky_quote_uri` / `bluesky_quote_id` / `bluesky_quote_url` - Quote another post
|
|
741
|
+
|
|
742
|
+
### Discord
|
|
743
|
+
- `discord_thread_id` / `discord_thread_name` / `discord_applied_tags` - Thread or forum post
|
|
744
|
+
- `discord_embeds` / `discord_poll` / `discord_allowed_mentions` - JSON
|
|
745
|
+
- `discord_username` / `discord_avatar_url` - Per-post webhook identity
|
|
746
|
+
- `discord_alt_text` / `discord_flags` / `discord_tts` / `discord_max_file_mb`
|
|
747
|
+
|
|
748
|
+
### Telegram
|
|
749
|
+
- `telegram_parse_mode` - `MarkdownV2` or `HTML`
|
|
750
|
+
- `telegram_message_thread_id` - Forum topic
|
|
751
|
+
- `telegram_disable_notification` / `telegram_protect_content` / `telegram_has_spoiler` / `telegram_pin`
|
|
752
|
+
- `telegram_link_preview` / `telegram_reply_markup` / `telegram_as_document`
|
|
753
|
+
- `telegram_caption_overflow` - `truncate` (default) or `split`
|
|
754
|
+
- `telegram_media_urls` - Comma-separated public URLs for a mixed album
|
|
755
|
+
|
|
756
|
+
### Mastodon
|
|
757
|
+
- `mastodon_visibility` / `mastodon_sensitive` / `mastodon_spoiler_text` / `mastodon_language`
|
|
758
|
+
- `mastodon_alt_text` - `|`-separated for albums
|
|
759
|
+
- `mastodon_poll_options` / `mastodon_poll_expires_in` / `mastodon_poll_multiple`
|
|
760
|
+
- `mastodon_scheduled_at` - ISO 8601, at least 5 minutes ahead
|
|
761
|
+
|
|
762
|
+
### WordPress
|
|
763
|
+
- `wordpress_status` / `wordpress_date` - `publish`, `draft`, `pending`, `future` (`date` required for `future`)
|
|
764
|
+
- `wordpress_categories` / `wordpress_tags` / `wordpress_excerpt` / `wordpress_slug`
|
|
765
|
+
- `wordpress_alt_text` / `wordpress_media_caption` / `wordpress_block_format`
|
|
766
|
+
|
|
767
|
+
### Lemmy
|
|
768
|
+
- `lemmy_url` / `lemmy_community` / `lemmy_nsfw` / `lemmy_language_id` / `lemmy_alt_text`
|
|
769
|
+
|
|
770
|
+
### Slack
|
|
771
|
+
- `slack_markdown` / `slack_mrkdwn` / `slack_blocks` / `slack_alt_text`
|
|
772
|
+
- `slack_first_comment_mode` - `separate` (default) or `inline`
|
|
773
|
+
|
|
774
|
+
### Nostr
|
|
775
|
+
- `nostr_kind` - `1` default, `20` picture, `22` short video, `34235` video, `30023` long-form
|
|
776
|
+
- `nostr_long_form` - Shorthand for kind 30023
|
|
777
|
+
|
|
778
|
+
### Dev.to
|
|
779
|
+
- `devto_tags` / `devto_canonical_url` / `devto_description` / `devto_main_image` / `devto_series` / `devto_published`
|
|
780
|
+
|
|
781
|
+
### Hashnode
|
|
782
|
+
- `hashnode_body` / `content` - Article body
|
|
783
|
+
- `hashnode_tags` / `hashnode_original_article_url` / `hashnode_subtitle` / `hashnode_cover_image_url` / `hashnode_draft`
|
|
784
|
+
|
|
785
|
+
### Whop
|
|
786
|
+
- `whop_body` / `whop_pinned` / `whop_is_mention` / `whop_paywall_amount` / `whop_paywall_currency` / `whop_attachment_ids`
|
|
787
|
+
|
|
788
|
+
### Listmonk
|
|
789
|
+
- `listmonk_content_type` - `richtext` (default), `markdown`, `html`, `plain`
|
|
790
|
+
- `listmonk_send_at` / `listmonk_lists` / `listmonk_template_id` / `listmonk_media_ids`
|
|
791
|
+
|
|
518
792
|
## Common Options
|
|
519
793
|
|
|
520
794
|
These options work across all upload methods:
|
|
@@ -525,6 +799,7 @@ These options work across all upload methods:
|
|
|
525
799
|
| `user` | Profile name (required) |
|
|
526
800
|
| `platforms` | Target platforms list (required) |
|
|
527
801
|
| `first_comment` | First comment to post |
|
|
802
|
+
| `tiktok_first_comment` | First comment for TikTok only (needs the `comments` capability) |
|
|
528
803
|
| `alt_text` | Alt text for accessibility |
|
|
529
804
|
| `scheduled_date` | ISO date for scheduling |
|
|
530
805
|
| `timezone` | Timezone for scheduled date |
|