# Post Reels via API to Instagram & TikTok

Reels are short-form vertical videos. OmniSocials supports reels on Instagram, Facebook, YouTube (as Shorts), and TikTok. A single `POST /posts/create` call with `type: "reel"` can fan out a reel to all four platforms at once.

## Supported channels

| Channel ID | Platform | Format | Max duration |
|------------|----------|--------|--------------|
| `instagram` | Instagram Reels | Vertical 9:16 | 15 minutes |
| `facebook` | Facebook Reels | Vertical 9:16 | 90 seconds |
| `youtube` | YouTube Shorts | Vertical 9:16 | 3 minutes |
| `tiktok` | TikTok | Vertical 9:16 or 16:9 | 10 minutes |

Calling with `type: "reel"` and a channel that does not support reels (LinkedIn, X, Pinterest, etc.) returns `400`.

## Minimal example

```bash
curl -X POST https://api.omnisocials.com/v1/posts/create \
  -H "Authorization: Bearer $OMNISOCIALS_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "type": "reel",
    "content": { "default": "New drop 🔥" },
    "accounts": ["your-instagram-account-id"],
    "media_urls": ["https://example.com/reel.mp4"]
  }'
```

Reels always require a single video file. Image-only or multi-video reel requests return `400`.

## Cross-posting a reel across all four platforms

Include every channel ID in `accounts` and use per-platform options for each platform's specific requirements.

```json
{
  "type": "reel",
  "content": {
    "default": "Behind the scenes from today's shoot",
    "tiktok": "POV: behind the scenes 🎬",
    "youtube": "How we filmed today's shoot #shorts"
  },
  "accounts": [
    "your-instagram-account-id",
    "your-facebook-page-account-id",
    "your-youtube-account-id",
    "your-tiktok-account-id"
  ],
  "media_urls": ["https://example.com/vertical-video.mp4"],
  "instagram": {
    "share_to_feed": true,
    "thumbnail_type": "from-video",
    "thumb_offset": 3000
  },
  "youtube": {
    "title": "Behind the scenes",
    "privacy_status": "public",
    "notify_subscribers": true
  },
  "tiktok": {
    "privacy_level": "PUBLIC_TO_EVERYONE",
    "disable_duet": false,
    "disable_stitch": false
  }
}
```

Every platform-specific key only applies to its own channel. Instagram ignores the `youtube` and `tiktok` blocks. YouTube ignores the `instagram` and `tiktok` blocks. And so on.

## Platform-specific options

Each reel-capable platform has its own set of options. Pass them under the matching channel ID key.

### Instagram reel options

| Field | Type | Description |
|-------|------|-------------|
| `instagram.share_to_feed` | boolean | Also show the reel on the profile feed grid |
| `instagram.thumbnail_type` | string | `from-video` or `from-library` |
| `instagram.thumb_offset` | number | Timestamp in milliseconds, used when `thumbnail_type` is `from-video` |
| `instagram.cover_url` | string | URL of a custom cover image, used when `thumbnail_type` is `from-library` |
| `instagram.audio_id` | string | Licensed music track to attach, from [`GET /audio/search`](#instagram-reel-music) |
| `instagram.audio_volume` | integer | Music volume 0–100 (default 100). Only used with `audio_id`. |
| `instagram.video_volume` | integer | Volume of the video's own audio 0–100 (default 100). Set `0` for a music-only reel. |
| `instagram.is_trial_reel` | boolean | Publish as a [Trial Reel](#instagram-trial-reels) — shown to non-followers first to test performance. Not available on every account. |
| `instagram.trial_graduation_strategy` | string | `MANUAL` (default) or `SS_PERFORMANCE`. How a Trial Reel graduates to all followers. Only used with `is_trial_reel`. |

#### Instagram Trial Reels

A Trial Reel is shown to **non-followers first** so you can test how content performs before (optionally) sharing it with your followers. Set `instagram.is_trial_reel: true` on a reel to publish it as a trial:

```json
{
  "type": "reel",
  "content": { "default": "Testing a new format 👀" },
  "accounts": ["your-instagram-account-id"],
  "media_urls": ["https://example.com/reel.mp4"],
  "instagram": {
    "is_trial_reel": true,
    "trial_graduation_strategy": "SS_PERFORMANCE"
  }
}
```

`trial_graduation_strategy` controls how the trial graduates to all your followers:

- `MANUAL` (default) — you decide when (or whether) to share it with followers, from the Instagram app.
- `SS_PERFORMANCE` — Instagram automatically shares it with your followers if it performs well.

`GET /posts/{id}` echoes both fields back under `instagram`, so you can verify a batch of scheduled Trial Reels programmatically.

**Eligibility:** Trial Reels are **not available on every account**. Instagram requires roughly 1,000+ followers and enables the feature per account — you can check eligibility by creating a reel in the Instagram app and looking for the "Trial" toggle. Ineligible accounts fail at publish time with a clear per-platform error on the post's `errors` map.

#### Instagram reel music

Search Meta's licensed catalog with `GET /audio/search?q=...` (omit `q` for currently trending audio; add `type=original_sound` to search original sounds instead of licensed music). Pass the chosen result's `audio_id` as `instagram.audio_id` and mix levels with `audio_volume` / `video_volume`:

```json
{
  "type": "reel",
  "content": { "default": "New drop 🎵" },
  "accounts": ["your-instagram-account-id"],
  "media_urls": ["https://example.com/reel.mp4"],
  "instagram": {
    "audio_id": "587784541076604",
    "audio_volume": 80,
    "video_volume": 0
  }
}
```

Notes:

- **Reels only.** Meta's API does not support adding music to feed posts, carousels, or Stories — that remains app-only.
- Only tracks Meta has **licensed for third-party publishing** appear in search results, so the selection can differ from the native app.
- Requires a **Facebook account connected** to the workspace whose Facebook Page is linked to the same Instagram account (music publishing runs through Facebook's side of the Instagram API). If it isn't, `GET /audio/search` returns `needsFacebook: true` and publishing a reel with `audio_id` fails with a clear error before anything goes live.

### YouTube Shorts options

| Field | Type | Description |
|-------|------|-------------|
| `youtube.title` | string | Video title, max 100 characters. Defaults to `"YouTube Short"`. |
| `youtube.tags` | array | Discovery tags. Max 500 characters total. |
| `youtube.privacy_status` | string | `public`, `private`, or `unlisted` |
| `youtube.category_id` | string | YouTube category. Defaults to `"22"` (People & Blogs). |
| `youtube.made_for_kids` | boolean | COPPA disclosure. Disables comments and interactions when true. |
| `youtube.notify_subscribers` | boolean | Send the subscriber notification when published |
| `youtube.contains_synthetic_media` | boolean | Disclose AI-generated content |

### TikTok options

| Field | Type | Description |
|-------|------|-------------|
| `tiktok.privacy_level` | string | **Required.** `PUBLIC_TO_EVERYONE`, `MUTUAL_FOLLOW_FRIENDS`, `FOLLOWER_OF_CREATOR`, `SELF_ONLY` |
| `tiktok.disable_comment` | boolean | Disable comments on the reel |
| `tiktok.disable_duet` | boolean | Disable duets |
| `tiktok.disable_stitch` | boolean | Disable stitches |
| `tiktok.video_cover_timestamp_ms` | integer | Timestamp (ms) of the frame to use as the cover |
| `tiktok.is_aigc` | boolean | Disclose AI-generated content |
| `tiktok.brand_content_toggle` | boolean | Mark as a paid partnership promoting a third-party brand |
| `tiktok.brand_organic_toggle` | boolean | Mark as promoting your own business / brand |

TikTok requires `privacy_level` on every reel. Omitting it returns `400`.

### Facebook Reels

Facebook has no specific reel option fields. The default reel body works.

## Different video per platform

Sometimes you want a slightly different cut for each platform (e.g. a shorter version for Facebook Reels where the limit is 90 seconds, and a longer cut for TikTok where the limit is 10 minutes). Use the per-platform `media_urls` shape:

```json
{
  "type": "reel",
  "content": { "default": "Full tutorial" },
  "accounts": [
    "your-youtube-account-id",
    "your-tiktok-account-id"
  ],
  "media_urls": {
    "youtube": ["https://example.com/tutorial-60s.mp4"],
    "tiktok": ["https://example.com/tutorial-full.mp4"]
  },
  "youtube": {
    "title": "Quick tutorial #shorts",
    "privacy_status": "public"
  },
  "tiktok": {
    "privacy_level": "PUBLIC_TO_EVERYONE"
  }
}
```

## Media requirements

| Platform | Format | Aspect | Duration | File size |
|----------|--------|--------|----------|-----------|
| Instagram | MP4 | 9:16 | Up to 15 minutes | Up to 300 MB |
| Facebook | MP4 | 9:16 | 3 to 90 seconds | Up to 1 GB |
| YouTube Shorts | MP4 | 9:16 | Up to 3 minutes | Up to 1 GB |
| TikTok | MP4 or MOV | 9:16 or 16:9 | 3 seconds to 10 minutes | Up to 1 GB |

Videos outside these constraints are rejected at publish time. OmniSocials does not transcode, trim, or re-encode.

The safest format for cross-platform reels: MP4, H.264 codec, 1080 × 1920 vertical, under 90 seconds (Facebook Reels is the tightest), under 300 MB (Instagram is the tightest). That passes every platform's requirements.

## Thumbnails and cover images

Each platform picks the reel cover differently:

- **Instagram**: default is the first frame. Override with `instagram.thumb_offset` (pick a video frame) or `instagram.cover_url` (supply a custom image).
- **Facebook**: default is the first frame. No override currently supported through the API.
- **YouTube Shorts**: YouTube auto-selects the thumbnail. Custom thumbnails for Shorts are not supported by the YouTube API.
- **TikTok**: TikTok auto-selects a frame. Custom covers can be set under `tiktok.video_cover_timestamp_ms` (timestamp in milliseconds, pick a frame).

## Scheduling reels

Reels are schedulable the same way as feed posts. Add `scheduled_at` (ISO 8601 UTC).

```json
{
  "type": "reel",
  "content": { "default": "Friday feature" },
  "accounts": [
    "your-instagram-account-id",
    "your-tiktok-account-id"
  ],
  "media_urls": ["https://example.com/reel.mp4"],
  "tiktok": { "privacy_level": "PUBLIC_TO_EVERYONE" },
  "scheduled_at": "2026-04-18T14:00:00Z"
}
```

## Limitations

- Reels must have exactly one video. Multi-video or image reels are rejected.
- `type: "reel"` is rejected on platforms that do not support reels. Mixing reel-capable and non-reel-capable channels in the same `accounts` array returns `400`.
- YouTube Shorts require the channel to be monetization-eligible on YouTube. Non-eligible channels can still publish but the video may appear as a regular video instead of a Short.
- TikTok branded-content reels (`brand_content_toggle: true`) go through TikTok's review workflow and may take longer to publish.
- Instagram enforces a 75-day maximum lookahead for scheduled reels. Scheduling further out returns `400`.

## Related reading

- [Creating Posts](/creating-posts) for the full field reference
- [Cross-Posting](/cross-posting) for the one-request-many-platforms model
- [Creating Stories](/creating-stories) for the ephemeral story workflow
- [Instagram](/platforms/instagram), [TikTok](/platforms/tiktok), [YouTube](/platforms/youtube) for full per-platform specs
