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"
}'

Documentation Index

Fetch the complete documentation index at: https://docs.genviral.io/llms.txt

Use this file to discover all available pages before exploring further.

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