---
title: TikTok
description: Prepare TikTok creator choices and publish verified media URLs with Social SDK, covering consent, privacy settings, drafts, and processing checks.
---

The direct TikTok adapter accepts an existing access token and creator `openId`. The server package also provides `tiktokOAuth` for TikTok Login Kit web authorization and creator discovery. OAuth consent does not replace the adapter's creator preview and publish consent requirements.

## Setup

1. **Connect the creator**

    Use `ConnectionManager` with `tiktokOAuth` to bind the callback to the authenticated tenant,
    show the discovered creator, and persist credentials through an encrypted `credentialSink`. Its
    default scopes are `user.info.basic` and `video.publish`, sent comma-delimited; refresh with
    `refreshOAuthToken("tiktok", ...)` and persist any rotated refresh token.

2. **Verify media origins**

    The adapter uses verified `PULL_FROM_URL` media origins. List every host you will publish from
    in `verifiedMediaOrigins` and verify them with TikTok.

3. **Configure the adapter**

    Construct the backend with the token, `openId`, and verified origins.

```ts
import { createSocial, connectedAccountRef } from "@opencoredev/social-sdk";
import { tiktok } from "@opencoredev/social-sdk/tiktok";

const social = createSocial({
  backend: tiktok({
    auth: {
      accessToken: process.env.TIKTOK_ACCESS_TOKEN!,
      openId: process.env.TIKTOK_OPEN_ID!,
    },
    verifiedMediaOrigins: ["https://media.example.com"],
  }),
});

const account = connectedAccountRef({
  backend: "default",
  platform: "tiktok",
  accountId: process.env.TIKTOK_OPEN_ID!,
});
```

## Examples

### Fetch creator info before publishing

TikTok requires showing the creator a preview of their current settings and letting them choose from the returned privacy levels. Creator information must be bound to the same backend and account.

```ts
const creatorInfo = await social
  .native("default", { acknowledgeUnsafe: true })
  .creatorInfo(account, {
    correlationId: "creator-preview",
    retryBudget: { maxAttempts: 1, maxElapsedMs: 10_000 },
    authorization: { tenantId: "tenant", principalId: "user" },
  });

// Render creatorInfo.privacyLevels and let the creator choose one of the returned values.
```

### Publish a video

```ts
const result = await social.posts.publish({
  targets: [
    {
      account,
      options: {
        consentGiven: true,
        creatorInfo,
        privacy: "PUBLIC_TO_EVERYONE",
        disableComments: false,
        disableDuet: false,
        disableStitch: false,
        brandedContent: false,
        ownBrand: false,
        photoCoverIndex: 0,
      },
    },
  ],
  content: {
    text: "A creator-approved caption",
    media: [
      {
        kind: "video",
        source: { kind: "https-url", url: "https://media.example.com/video.mp4" },
        durationSeconds: 8,
      },
    ],
  },
});
```

### Publish a photo carousel

The adapter supports one video or 1–35 photos. `photoCoverIndex` selects the cover image.

```ts
const result = await social.posts.publish({
  targets: [
    {
      account,
      options: {
        consentGiven: true,
        creatorInfo,
        privacy: "PUBLIC_TO_EVERYONE",
        disableComments: false,
        disableDuet: false,
        disableStitch: false,
        brandedContent: false,
        ownBrand: false,
        photoCoverIndex: 1,
      },
    },
  ],
  content: {
    text: "Photo set",
    media: [
      { kind: "image", source: { kind: "https-url", url: "https://media.example.com/1.jpg" } },
      { kind: "image", source: { kind: "https-url", url: "https://media.example.com/2.jpg" } },
    ],
  },
});
```

### Reconcile the publish ID

The initial publish call returns `accepted` with a `publish_id`. Reconcile through `posts.getDelivery`: processing states remain `processing`, a confirmed failure remains `failed`, and a public ID is required before reporting `published`.

```ts
const outcome = result.outcomes[0];
if (outcome?.delivery) {
  const delivery = await social.posts.getDelivery(outcome.delivery);
  console.log(delivery.state); // processing | published | failed | unknown
}
```

Draft/inbox and public posting have different upstream review and audit requirements; the SDK does not claim approval or silently change privacy.

### Receive webhooks

Pass the app client secret as `webhookSecret`. `adapter.webhooks.verify` checks `TikTok-Signature` and rejects timestamps more than 300 seconds old; set `webhookToleranceSeconds` to change the window, because TikTok does not publish one. Publish events decode to `publication.updated` with the `publish_id` as `backendRecordId`, and `authorization.removed` decodes to `account.updated`. See [Process webhooks](/events).

## Native operations

The typed native module adds the inbox/draft upload path, own-video listing with display fields, and an explicit publish-status query. Post metrics from `social.analytics.getPostMetrics` read like, comment, share, and view counts through the Display API video query and require `video.list`; account metrics require `user.info.stats`. Polling is caller initiated and bounded; the SDK does not run background polling. Comments and direct messages remain platform limits for standard Content Posting and Display API apps.

## Limits and requirements

:::warning
The adapter rejects missing consent, stale creator choices, unverified origins, unsupported schedules/replies/links, and unknown media duration where required.
:::

- Explicit privacy and interaction choices are required on every publish, and captions are validated against the format limit.
- Published posts cannot be edited. The [Content Posting API](https://developers.tiktok.com/doc/content-posting-api-get-started) sets the caption, privacy, and interaction settings only when a post is initialized, so `posts.update` is declared `unsupported-by-platform`.
- Keep tokens server-side and treat media URLs, creator data, and publish IDs as sensitive.
- Repository evidence is offline contract and mocked transport coverage; no TikTok app or creator account has been live-verified.

TikTok's [content sharing guidelines](https://developers.tiktok.com/doc/content-sharing-guidelines/) describe creator preview, consent, privacy, and app-audit requirements.
