Skip to main content
POST
/
api
/
partner
/
v1
/
posts
curl --request POST \
  --url https://www.genviral.io/api/partner/v1/posts \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "caption": "Weekly product recap and what shipped this sprint.",
  "media": {
    "type": "video",
    "url": "https://cdn.example.com/recap.mp4",
    "duration_sec": 42
  },
  "accounts": [{ "id": "YOUR_YOUTUBE_ACCOUNT_ID" }],
  "settings": {
    "youtube": {
      "title": "Weekly product recap",
      "type": "public"
    }
  },
  "external_id": "yt-recap-2026-05-21"
}'
Schedule or publish immediately to one or more connected accounts.

Before you post

  1. Use an API key for a workspace with an active Creator, Professional, or Business subscription.
  2. Call GET /accounts and pick account UUIDs.
  3. Check each account’s capabilities.supported_content_kinds and caption_limit.
  4. Build the payload below. Only include provider settings for platforms you are actually targeting.
Omit media or set it to null only when every selected account supports text_only.

Request body

caption
string
required
Shared caption text. Final length is checked per targeted account after lookup (hosted accounts: 500 chars max).
accounts
array
required
One to ten account objects: [{ "id": "<uuid-from-/accounts>" }].
media
object | null
Optional. video, slideshow, or null/omit for text-only posts.
scheduled_at
string
ISO 8601 datetime with timezone offset (for example 2026-05-21T15:00:00Z). Omit or send a time within 30 seconds of now for immediate publish (status: pending). For true scheduled posts, the time must be at least 2 minutes in the future.
external_id
string
Recommended idempotency key (max 128 chars). Same key + same payload replays the original post (200, duplicate: true). Same key + different payload returns 409 create_failed. If omitted, the API dedupes from a SHA-256 fingerprint of the request body instead; a conflicting replay also returns 409 create_failed.
music_url
string
TikTok-only. A TikTok post URL used to resolve the track. Rejected when any non-TikTok account is selected, including Instagram.

Provider settings

Use settings.<provider> for X, Instagram, Facebook, LinkedIn, Bluesky, and YouTube. For TikTok and Pinterest on create, use the top-level tiktok and pinterest objects — not settings.tiktok or settings.pinterest. Top-level fields run the full create-time validation (BYO-only TikTok, hosted TikTok rejection, MEDIA_UPLOAD rules, and field limits). Only send settings for providers present in your accounts list. Unknown settings keys return 422 invalid_payload.
capabilities.settings_schema from GET /accounts reflects the dashboard composer, not always the Partner API field names. Use the tables below when building create payloads.

YouTube — settings.youtube

Requires a video post to a YouTube account.
FieldTypeRequiredNotes
titlestringNoMax 100 chars. If omitted, derived from settings.youtube.description, then caption (first non-empty line).
descriptionstringNoOverrides caption as the YouTube description when set.
typestringNoVisibility: public, private, or unlisted. Default public. Alias: privacy.
privacystringNoSame as type.
tagsarrayNo{ "value": "...", "label": "..." } items. Publish uses label values. Total tag length capped at publish time.
categoryIdstringNoYouTube category ID.
selfDeclaredMadeForKidsstringNoyes or no. Default no. Boolean alias: madeForKids.
thumbnailobjectNoCustom thumbnail: { "path": "<image-url>" }.

TikTok — top-level tiktok

Requires BYO TikTok accounts and media (video or slideshow). Hosted TikTok accounts cannot use TikTok-specific settings. For video posts, the merged publish text built from caption, tiktok.title, and tiktok.description must stay ≤ 2,200 characters combined.
FieldTypeNotes
titlestringVideo: max 2,200 chars. Slideshow: max 90 chars.
descriptionstringSlideshow: max 4,000 chars. Video: used as the publish body when caption is empty.
post_modestringDIRECT_POST or MEDIA_UPLOAD (slideshow drafts only). Defaults to DIRECT_POST at publish time when omitted.
privacy_levelstringPUBLIC_TO_EVERYONE, MUTUAL_FOLLOW_FRIENDS, FOLLOWER_OF_CREATOR, SELF_ONLY.
music_usage_confirmationbooleanConfirms the user has accepted TikTok’s music-usage terms for this post. Preferred Partner API field.
user_consentbooleanLegacy alias for music_usage_confirmation.
disable_commentbooleanInverted to allow/deny comments.
disable_duetbooleanVideo only.
disable_stitchbooleanVideo only.
auto_add_musicbooleanSlideshow only.
is_your_brandbooleanOwn-brand commercial content.
is_branded_contentbooleanThird-party promotion.
video_cover_timestamp_msintegerVideo DIRECT_POST only. Frame offset in milliseconds for the TikTok thumbnail.

Pinterest — top-level pinterest

Requires at least one Pinterest account and image media.
FieldTypeNotes
board_idstringPinterest board ID. Required for a successful pin publish — no account default is applied. Max 128 chars.
titlestringOptional pin title. Max 100 chars.
linkstringOptional destination URL. Max 2,048 chars.
tagsstring[]Up to 30 tags, 1–100 chars each. Appended to the pin description; total description must stay ≤ 800 chars.

X — settings.x or settings.twitter

FieldTypeRequiredNotes
who_can_reply_poststringNoeveryone (default), following, mentionedUsers, subscribers, verified.
communitystringNoX community URL: https://x.com/i/communities/<id>.
made_with_aibooleanNoDefault false.
paid_partnershipbooleanNoDefault false.

Instagram — settings.instagram or settings.instagram-standalone

Both keys map to the same stored settings. If both are sent, instagram-standalone wins.
FieldTypeRequiredNotes
post_typestringRecommendedpost (feed/reel) or story.
is_trial_reelbooleanNoTrial reel flag for video posts.
graduation_strategystringNoMANUAL or SS_PERFORMANCE when using trial reels.
collaboratorsarrayNo[{ "label": "<username>" }]. Ignored for stories.
cover_urlstringNoCustom Reel cover image URL. Takes priority over thumb_offset_ms. Video post_type: post only. Must be publicly accessible. BYO Instagram only — hosted accounts reject cover settings.
thumb_offset_msintegerNoReel thumbnail frame offset in milliseconds when cover_url is omitted. Video post_type: post only. BYO Instagram only.
share_to_feedbooleanNoShare the Reel to the main feed. Default true. Set false for Reels tab only. BYO Instagram only.

Facebook — settings.facebook

FieldTypeRequiredNotes
urlstringNoOptional link attachment URL on the post.

LinkedIn — settings.linkedin or settings.linkedin-page

Both keys map to the same stored settings. If both are sent, linkedin-page wins.
FieldTypeRequiredNotes
post_as_images_carouselbooleanNoPost multi-image content as a LinkedIn carousel/PDF.
carousel_namestringNoCarousel/PDF title. Default slides.

Bluesky — settings.bluesky

No provider-specific fields. Send {} or omit.

Settings key reference

Request keyAliasStored as
settings.xsettings.twitterxSettings
settings.instagram-standalonesettings.instagraminstagramSettings
settings.linkedin-pagesettings.linkedinlinkedinSettings
Top-level tiktoktikTokSettings
Top-level pinterestpinterestSettings

Limits (quick reference)

  • Video: MP4/MOV/M4V/AVI, under 100MB. Hosted accounts: 15–60s when duration is provided.
  • Non-premium X video: duration metadata required; max 140 seconds.
  • Slideshow: 1–35 images, each under 5MB.
  • Caption caps (BYO): X 280 (4,000 for premium accounts); Instagram 2,200; TikTok video 2,200 / photo description 4,000; LinkedIn 3,000; Pinterest 800; YouTube 5,000 bytes; Facebook 63,206.

Response

Fresh creates return 201. Idempotent replays return 200.
{
  "ok": true,
  "code": 201,
  "message": "Post scheduled",
  "data": {
    "id": "11111111-1111-1111-1111-111111111111",
    "status": "scheduled",
    "scheduled_at": "2026-05-21T15:00:00Z",
    "warnings": []
  }
}
duplicate: true appears on idempotent replays. warnings are non-blocking (for example missing video duration metadata).

Examples

curl --request POST \
  --url https://www.genviral.io/api/partner/v1/posts \
  --header 'Authorization: Bearer <token>' \
  --header 'Content-Type: application/json' \
  --data '{
  "caption": "Weekly product recap and what shipped this sprint.",
  "media": {
    "type": "video",
    "url": "https://cdn.example.com/recap.mp4",
    "duration_sec": 42
  },
  "accounts": [{ "id": "YOUR_YOUTUBE_ACCOUNT_ID" }],
  "settings": {
    "youtube": {
      "title": "Weekly product recap",
      "type": "public"
    }
  },
  "external_id": "yt-recap-2026-05-21"
}'

Errors

CodeWhen
422 invalid_payloadSchema validation failed (includes issues array)
400 invalid_jsonRequest body is not valid JSON
400 validation_failedCaption, media, music, TikTok/Pinterest, or schedule rules failed
400 unknown_accountsAccount ID outside key scope
400 media_unreachableMedia URL not reachable
400 invalid_music_urlInvalid or non-TikTok music URL
401Missing or invalid API key
402 subscription_requiredNo active Creator, Professional, or Business subscription
403 subscription_requiredHosted TikTok posting without an active TikTok virtual subscription
403 tier_not_allowedScheduler tier blocked
409 create_failedSame external_id or dedupe fingerprint reused with a different create payload
500 create_failedUnexpected upstream failure