TikTok Photo Post API: Official Endpoint and Examples

TikTok has an official API for photo posts and carousels. Call POST https://open.tiktokapis.com/v2/post/publish/content/init/, set media_type to PHOTO, and provide one to 35 image URLs. Use DIRECT_POST to publish or MEDIA_UPLOAD to send the content into TikTok’s editing flow.

The same endpoint handles a single photo and a carousel: one item in photo_images is a single-photo post; multiple items create a multi-photo post.

TikTok photo API requirements at a glance

Requirement Current documented value
Endpoint /v2/post/publish/content/init/
HTTP method POST
Direct-publish scope video.publish
Draft-upload scope video.upload
Media type PHOTO
Transfer method PULL_FROM_URL
Photos per request 1–35 URLs
Rate limit 6 requests/minute per user access token
Title limit 90 UTF-16 runes
Description limit 4,000 UTF-16 runes

Before Direct Post, TikTok requires the application to query current creator information and render the supported privacy choices. Do not hard-code PUBLIC_TO_EVERYONE as a default.

Direct Post request for a carousel

In short: Send an authorized access token, choose a privacy value returned by creator info, provide verified HTTPS image URLs, and save the returned publish_id so your system can poll the final status.

curl --fail-with-body \
  -X POST https://open.tiktokapis.com/v2/post/publish/content/init/ \
  -H "Authorization: Bearer $TIKTOK_ACCESS_TOKEN" \
  -H "Content-Type: application/json; charset=UTF-8" \
  -d '{
    "media_type": "PHOTO",
    "post_mode": "DIRECT_POST",
    "post_info": {
      "title": "Three launch details",
      "description": "Swipe through the release notes. #product",
      "privacy_level": "PUBLIC_TO_EVERYONE",
      "disable_comment": false,
      "auto_add_music": true,
      "brand_content_toggle": false,
      "brand_organic_toggle": true
    },
    "source_info": {
      "source": "PULL_FROM_URL",
      "photo_cover_index": 0,
      "photo_images": [
        "https://media.example.com/launch/01.webp",
        "https://media.example.com/launch/02.webp",
        "https://media.example.com/launch/03.webp"
      ]
    }
  }'

Replace the privacy value with an option returned for the actual creator. The example marks the content as promoting the creator’s own business; commercial-content fields must reflect the real post.

JavaScript example

async function createTikTokPhotoPost(accessToken, imageUrls, privacyLevel) {
  if (imageUrls.length < 1 || imageUrls.length > 35) {
    throw new Error("TikTok photo posts require 1 to 35 image URLs")
  }

  const response = await fetch(
    "https://open.tiktokapis.com/v2/post/publish/content/init/",
    {
      method: "POST",
      headers: {
        Authorization: `Bearer ${accessToken}`,
        "Content-Type": "application/json; charset=UTF-8",
      },
      body: JSON.stringify({
        media_type: "PHOTO",
        post_mode: "DIRECT_POST",
        post_info: {
          title: "Product details",
          description: "Swipe for the complete walkthrough.",
          privacy_level: privacyLevel,
          disable_comment: false,
          auto_add_music: true,
          brand_content_toggle: false,
          brand_organic_toggle: false,
        },
        source_info: {
          source: "PULL_FROM_URL",
          photo_cover_index: 0,
          photo_images: imageUrls,
        },
      }),
    },
  )

  const body = await response.json()
  if (!response.ok || body.error?.code !== "ok") {
    throw new Error(body.error?.message || `TikTok returned ${response.status}`)
  }

  return body.data.publish_id
}

Treat publish_id as durable job state—not proof that the post is already visible. Poll TikTok’s publish-status endpoint or process its status webhooks until the job is terminal.

Direct Post versus Media Upload

In short: Direct Post publishes from your application after the required user controls and consent. Media Upload sends a draft to TikTok, where the creator opens an inbox notification and completes the editing and publishing flow.

Mode Scope Result Best for
DIRECT_POST video.publish Publishing starts immediately Approved scheduling products
MEDIA_UPLOAD video.upload Draft continues in TikTok Workflows that require TikTok editing

For Media Upload, remove Direct Post-only fields such as privacy and use post_mode: "MEDIA_UPLOAD". TikTok currently requires a sufficiently recent TikTok application version for that photo-upload flow.

Required UX and compliance controls

Building the HTTP call is only part of a compliant integration. TikTok’s Direct Post guidelines require applications to:

  1. Fetch current creator info when rendering the publishing screen.
  2. Display the creator’s nickname and the privacy options TikTok returns.
  3. Require a manual privacy selection; do not preselect one.
  4. Let the creator control comments. Duet and Stitch do not apply to photo posts.
  5. Collect the correct commercial-content disclosure.
  6. Show a preview and obtain express consent before sending the content.
  7. Keep captions and hashtags editable.
  8. Avoid promotional watermarks or logos added by the integration.
  9. Show publishing status while TikTok processes the post.

Unaudited clients are limited to private viewing. TikTok also documents a five-user daily cap for unaudited clients, plus creator and application posting caps that apply more broadly.

Image hosting rules

In short: TikTok photo posts only support PULL_FROM_URL. Serve every image over HTTPS from a URL owned by your developer application, avoid redirects, and keep the resource accessible while TikTok downloads it.

The most common integration mistake is using a signed URL on an unverified host. A URL can be publicly readable and still fail because TikTok has not verified its domain or prefix for your application.

Before launch:

  • verify the base domain or exact URL prefix in TikTok for Developers;
  • use stable HTTPS URLs without redirects;
  • preserve the image order because it controls carousel order;
  • select a zero-based photo_cover_index that exists in the array;
  • test the real production hostname, not only TikTok’s sample media.

Schedule photo posts with Postqued

In short: Postqued supplies the scheduling layer that TikTok’s public endpoint does not. Upload one or more image assets, read the connected creator’s constraints, validate the target, and set dispatchAt for the future publish time.

Postqued uses a static API key for its own API, while the connected TikTok account is authorized through the product’s user flow.

1. Upload the images

For each image, call POST /v2/content/upload, send the bytes to the returned presigned URL, then call POST /v2/content/upload/complete. Save every contentId in carousel order.

2. Read creator info

GET /v2/integrations/ACCOUNT_UUID/creator-info?workspaceId=WORKSPACE_UUID

Use the returned privacy choices rather than assuming public publishing is available.

3. Validate and schedule

{
  "workspaceId": "WORKSPACE_UUID",
  "contentIds": ["IMAGE_UUID_1", "IMAGE_UUID_2", "IMAGE_UUID_3"],
  "targets": [
    {
      "platform": "tiktok",
      "accountId": "ACCOUNT_UUID",
      "intent": "publish",
      "caption": "Swipe through the launch details.",
      "dispatchAt": "2026-08-15T17:00:00Z",
      "options": {
        "privacyLevel": "PUBLIC_TO_EVERYONE",
        "disableComment": false,
        "autoAddMusic": true,
        "photoCoverIndex": 0,
        "commercialContent": false,
        "brandContentToggle": false,
        "brandOrganicToggle": false,
        "authenticContentConfirmed": true
      }
    }
  ],
  "dryRun": true
}

Send this body to POST https://api.postqued.com/v2/publish. After validation, repeat with dryRun: false and a fresh UUID in the Idempotency-Key header. The live OpenAPI document remains the source of truth for the exact schema.

Common TikTok photo API errors

url_ownership_unverified

The image host or prefix is not verified for the TikTok developer application. Verify it or serve the assets from a verified property.

privacy_level_option_mismatch

The privacy value is absent or not one of the choices returned by creator info. Refresh creator info and require a valid user selection.

scope_not_authorized

The access token does not include video.publish or video.upload for the selected flow. Re-authorize with the required approved scope.

spam_risk_too_many_posts

The creator has reached a posting cap. Stop retrying immediately and surface the provider error to the user.

rate_limit_exceeded

The user access token exceeded the documented request rate. Queue requests and back off rather than switching tokens or hiding the error.

Final checklist

  • Use the official /v2/post/publish/content/init/ endpoint.
  • Fetch creator info before every publishing flow.
  • Provide one to 35 verified HTTPS image URLs.
  • Use video.publish for Direct Post or video.upload for Media Upload.
  • Keep privacy and commercial disclosures under user control.
  • Save publish_id and monitor final status.
  • Complete TikTok’s audit before expecting public Direct Post behavior.

For a managed scheduling layer, see the Postqued TikTok scheduler. For the broader integration decision, read does TikTok have an official scheduling API?.

Official sources

Frequently Asked Questions

Does TikTok have an official photo post API?

Yes. TikTok's official Content Posting API uses POST /v2/post/publish/content/init/ for both single-photo and multi-photo posts. Set media_type to PHOTO and provide one to 35 verified, publicly accessible image URLs.

How many photos can the TikTok API publish in one carousel?

TikTok's current photo-post reference allows up to 35 photo URLs in the photo_images array. One URL produces a single-photo post; multiple URLs produce a carousel.

Which OAuth scopes are required for TikTok photo posts?

Use video.publish for Direct Post or video.upload for the draft-style Upload flow. The authorized TikTok user must grant the chosen scope.

Can an unaudited TikTok application publish public photo posts?

No. TikTok restricts unaudited Direct Post clients to private viewing and applies additional user and posting caps. The application must pass TikTok's Content Posting API audit before those restrictions can be lifted.

Can Postqued schedule TikTok photo carousels?

Yes. Upload the images as Postqued content assets, pass their content IDs to POST /v2/publish, use a TikTok target with photo options, validate with dryRun, and set an offset-bearing dispatchAt time.

Why does TikTok return url_ownership_unverified?

Photo posts use PULL_FROM_URL. Every image must be served over an accessible HTTPS URL under a domain or URL prefix verified for the TikTok developer application.