> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ugc.inc/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Slideshow Post

> Create a slideshow post from multiple images

## Endpoint

```
POST https://api.ugc.inc/post/slideshow
```

## Overview

Create and schedule a slideshow post from multiple images to be published on TikTok or Instagram. The images will be combined into a slideshow with optional music.

## Request Body

<ParamField body="accountId" type="string | null" required>
  Account ID to post from, or `null` for automatic account selection

  **Auto-Selection Behavior:**

  * Set to `null` to automatically select an account
  * With `strict: true`: Selects the least recently posted account
  * With `strict: false`: Selects the account with the closest available time slot to your requested `postTime`
  * Can be filtered using `tag`, `user_group`, and `org_group` parameters
</ParamField>

<ParamField body="tag" type="string">
  Filter accounts by tag (only used when `accountId` is `null`)
</ParamField>

<ParamField body="user_group" type="string">
  Filter accounts by user group (only used when `accountId` is `null`)
</ParamField>

<ParamField body="org_group" type="string">
  Filter accounts by organization group (only used when `accountId` is `null`)
</ParamField>

<ParamField body="post_tag" type="string">
  Custom tag stored on the created post itself (returned as `tag` on the Post object). Distinct from `tag`, which filters account auto-selection.
</ParamField>

<ParamField body="imageUrls" type="string[]" required>
  Array of image URLs (must be publicly accessible)

  **Requirements:**

  * **Minimum:** 1 image
  * **Maximum:** 35 images (platform limit)
  * **Formats:** JPG, JPEG, PNG
  * **Resolution:** 1080x1920 recommended (9:16 aspect ratio)
  * **File size:** Under 5MB per image
  * All URLs must be publicly accessible
</ParamField>

<ParamField body="caption" type="string">
  Post caption/description

  Can include hashtags and emojis

  **Limit:** Maximum 4000 characters
</ParamField>

<ParamField body="socialAudioId" type="string">
  ID of a social audio record to attach to the post

  <Note>
    **Music Support:**

    * ✅ **TikTok:** Fully supported
    * ❌ **Instagram:** Not yet supported
  </Note>

  **How to use:**

  1. First, import the audio using the [Upload Social Audio](/api-reference/endpoint/media-social-audio-upload) endpoint with a TikTok video or music URL
  2. This returns a social audio record with an `id`
  3. Use that `id` as the `socialAudioId` here

  **Example workflow:**

  ```javascript theme={null}
  // Step 1: Import audio from a TikTok video
  const audioResponse = await client.media.createSocialAudio({
    url: 'https://www.tiktok.com/@username/video/1234567890'
  });

  // Step 2: Use the returned ID in your post
  const postResponse = await client.posts.createSlideshow({
    accountId: 'acc_123456',
    imageUrls: ['https://example.com/img1.jpg'],
    socialAudioId: audioResponse.data.id
  });
  ```
</ParamField>

<ParamField body="postTime" type="string">
  When to schedule the post (ISO 8601 format)

  If omitted, the post will be published immediately

  Example: `2024-12-31T12:00:00Z`
</ParamField>

<ParamField body="strict" type="boolean" default={false}>
  Scheduling mode - controls timing behavior

  **When `strict: true`:**

  * Post must be scheduled at the exact requested time
  * If using auto-selection (`accountId: null`), picks the least recently posted account
  * Will return an error if the account cannot post at the exact time

  **When `strict: false`:**

  * Post will be scheduled at the nearest available time
  * If using auto-selection (`accountId: null`), picks the account that can post closest to the requested time
  * Automatically adjusts to the next available slot if requested time is unavailable
</ParamField>

<ParamField body="mustPostBy" type="string">
  Latest allowed scheduled time (ISO 8601 format)

  If the post cannot be scheduled before this deadline, the request will return an error.

  When using auto-selection (`accountId: null`), accounts that cannot post before this time are excluded from selection.

  Example: `2024-12-31T23:59:59Z`
</ParamField>

## Response

<ResponseField name="data" type="Post">
  The created post object

  <Expandable title="Post properties">
    <ResponseField name="id" type="string">
      Unique post identifier - use this to track the post status
    </ResponseField>

    <ResponseField name="account_id" type="string">
      ID of the account that will post this
    </ResponseField>

    <ResponseField name="type" type="'slideshow'">
      Post type (always `slideshow` for this endpoint)
    </ResponseField>

    <ResponseField name="status" type="string">
      Initial status: `scheduled` or `pending`
    </ResponseField>

    <ResponseField name="social_id" type="string | null">
      Platform post ID (null until posted)
    </ResponseField>

    <ResponseField name="caption" type="string | null">
      Post caption
    </ResponseField>

    <ResponseField name="tag" type="string | null">
      Custom tag stored on the post (from `post_tag`)
    </ResponseField>

    <ResponseField name="media_urls" type="string[]">
      Array of image URLs
    </ResponseField>

    <ResponseField name="social_audio_id" type="string | null">
      ID of the attached social audio record
    </ResponseField>

    <ResponseField name="scheduled_at" type="string | null">
      When the post is scheduled to be published (ISO 8601 format)
    </ResponseField>
  </Expandable>
</ResponseField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST https://api.ugc.inc/post/slideshow \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '{
      "accountId": "acc_123456",
      "imageUrls": [
        "https://storage.example.com/img1.jpg",
        "https://storage.example.com/img2.jpg",
        "https://storage.example.com/img3.jpg"
      ],
      "caption": "Check out these amazing photos! 📸 #photography",
      "socialAudioId": "audio_xyz789",
      "postTime": "2024-12-31T12:00:00Z"
    }'
  ```

  ```python Python theme={null}
  import requests

  response = requests.post(
      'https://api.ugc.inc/post/slideshow',
      headers={
          'Authorization': 'Bearer YOUR_API_KEY',
          'Content-Type': 'application/json'
      },
      json={
          'accountId': 'acc_123456',
          'imageUrls': [
              'https://storage.example.com/img1.jpg',
              'https://storage.example.com/img2.jpg',
              'https://storage.example.com/img3.jpg'
          ],
          'caption': 'Check out these amazing photos! 📸 #photography',
          'socialAudioId': 'audio_xyz789',
          'postTime': '2024-12-31T12:00:00Z'
      }
  )

  data = response.json()

  if data['ok']:
      print('Slideshow created:', data['data']['id'])
      print('Status:', data['data']['status'])
      print('Images:', len(data['data']['media_urls']))
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.ugc.inc/post/slideshow', {
    method: 'POST',
    headers: {
      'Authorization': 'Bearer YOUR_API_KEY',
      'Content-Type': 'application/json'
    },
    body: JSON.stringify({
      accountId: 'acc_123456',
      imageUrls: [
        'https://storage.example.com/img1.jpg',
        'https://storage.example.com/img2.jpg',
        'https://storage.example.com/img3.jpg'
      ],
      caption: 'Check out these amazing photos! 📸 #photography',
      socialAudioId: 'audio_xyz789',
      postTime: '2024-12-31T12:00:00Z'
    })
  });

  const data = await response.json();

  if (data.ok) {
    console.log('Slideshow created:', data.data.id);
    console.log('Status:', data.data.status);
    console.log('Images:', data.data.media_urls.length);
  }
  ```

  ```typescript React theme={null}
  import { UGCClient } from 'ugcinc';

  const client = new UGCClient({
    apiKey: 'YOUR_API_KEY'
  });

  // Standard: Post with specific account
  const response = await client.posts.createSlideshow({
    accountId: 'acc_123456',
    imageUrls: [
      'https://storage.example.com/img1.jpg',
      'https://storage.example.com/img2.jpg',
      'https://storage.example.com/img3.jpg'
    ],
    caption: 'Check out these amazing photos! 📸 #photography',
    socialAudioId: 'audio_xyz789',
    postTime: '2024-12-31T12:00:00Z'
  });

  // Auto-select with strict=true: picks least recently posted account
  const autoResponse1 = await client.posts.createSlideshow({
    accountId: null,  // Auto-select
    imageUrls: ['img1.jpg', 'img2.jpg', 'img3.jpg'],
    caption: 'Auto-posted at exact time',
    postTime: '2024-12-31T10:00:00Z',
    strict: true,  // Must post at exactly 10:00 AM
    tag: 'production'  // Only consider accounts with this tag
  });

  // Auto-select with strict=false: picks account with closest available slot
  const autoResponse2 = await client.posts.createSlideshow({
    accountId: null,  // Auto-select
    imageUrls: ['img1.jpg', 'img2.jpg'],
    caption: 'Auto-posted at nearest time',
    postTime: '2024-12-31T14:00:00Z',
    strict: false,  // Posts at nearest available time
    org_group: 'team-a'  // Only consider accounts in this org group
  });

  if (response.ok) {
    console.log(`Slideshow created with ID: ${response.data.id}`);
    console.log(`Account used: ${response.data.account_id}`);
    console.log(`Scheduled for: ${response.data.scheduled_at}`);
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Success Response theme={null}
  {
    "ok": true,
    "code": 200,
    "message": "Slideshow post created successfully",
    "data": {
      "id": "post_def456",
      "account_id": "acc_123456",
      "type": "slideshow",
      "status": "scheduled",
      "social_id": null,
      "caption": "Check out these amazing photos! 📸 #photography",
      "media_urls": [
        "https://storage.example.com/img1.jpg",
        "https://storage.example.com/img2.jpg",
        "https://storage.example.com/img3.jpg"
      ],
      "social_audio_id": "audio_xyz789",
      "scheduled_at": "2024-12-31T12:00:00Z"
    }
  }
  ```

  ```json Error Response theme={null}
  {
    "ok": false,
    "code": 400,
    "message": "At least one image URL is required"
  }
  ```
</ResponseExample>
