{
  "schemaVersion": "1.0",
  "item": {
    "slug": "tiktok-page",
    "name": "TikTok Page",
    "source": "tencent",
    "type": "skill",
    "category": "开发工具",
    "sourceUrl": "https://clawhub.ai/seph1709/tiktok-page",
    "canonicalUrl": "https://clawhub.ai/seph1709/tiktok-page",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/tiktok-page",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=tiktok-page",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "SKILL.md",
      "_meta.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-05-07T17:22:31.273Z",
      "expiresAt": "2026-05-14T17:22:31.273Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=afrexai-annual-report",
        "contentDisposition": "attachment; filename=\"afrexai-annual-report-1.0.0.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/tiktok-page"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/tiktok-page",
    "agentPageUrl": "https://openagent3.xyz/skills/tiktok-page/agent",
    "manifestUrl": "https://openagent3.xyz/skills/tiktok-page/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/tiktok-page/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "tiktok-page — Universal TikTok API Skill",
        "body": "Constructs and executes TikTok API calls inline based on what the user wants. No scripts needed.\n\nAPI base URL: https://open.tiktokapis.com/v2"
      },
      {
        "title": "STEP 1 - Load Credentials",
        "body": "Credentials are stored in ~/.config/tiktok-page/credentials.json.\n\n$cfg          = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$accessToken  = $cfg.TIKTOK_ACCESS_TOKEN\n$refreshToken = $cfg.TIKTOK_REFRESH_TOKEN\n$clientKey    = $cfg.TIKTOK_CLIENT_KEY\n$clientSecret = $cfg.TIKTOK_CLIENT_SECRET\n$openId       = $cfg.TIKTOK_OPEN_ID\n\nIf the file does not exist, guide setup:\n\nFieldPurposeTIKTOK_ACCESS_TOKENOAuth2 access token — used for all API callsTIKTOK_REFRESH_TOKENUsed to refresh access token when expiredTIKTOK_CLIENT_KEYApp Client Key from TikTok Developer PortalTIKTOK_CLIENT_SECRETApp Client Secret — for token refresh onlyTIKTOK_OPEN_IDTikTok user open_id returned during OAuth\n\nOne-time OAuth2 setup:\n\n1. Go to https://developers.tiktok.com — create or select your app\n2. Add redirect URI (e.g. https://localhost or your callback URL)\n3. Note your Client Key and Client Secret\n4. Direct user to:\n   https://www.tiktok.com/v2/auth/authorize/?client_key=CLIENT_KEY&redirect_uri=REDIRECT_URI&response_type=code&scope=user.info.basic,video.list,video.publish,video.upload,comment.list&state=random\n5. After redirect, copy the code param from the callback URL\n\n# Exchange auth code for tokens\n$clientKey   = \"<your-client-key>\"\n$clientSecret = \"<your-client-secret>\"\n$code        = \"<auth-code-from-redirect>\"\n$redirectUri = \"<your-redirect-uri>\"\n\n$body = \"client_key=$clientKey&client_secret=$clientSecret&code=$code&grant_type=authorization_code&redirect_uri=$redirectUri\"\n$r = Invoke-RestMethod \"https://open.tiktokapis.com/v2/oauth/token/\" -Method POST `\n    -Headers @{ \"Content-Type\" = \"application/x-www-form-urlencoded\" } -Body $body -ErrorAction Stop\n\nNew-Item -ItemType Directory -Force -Path \"$HOME/.config/tiktok-page\" | Out-Null\n@{\n    TIKTOK_ACCESS_TOKEN  = $r.access_token\n    TIKTOK_REFRESH_TOKEN = $r.refresh_token\n    TIKTOK_CLIENT_KEY    = $clientKey\n    TIKTOK_CLIENT_SECRET = $clientSecret\n    TIKTOK_OPEN_ID       = $r.open_id\n} | ConvertTo-Json | Set-Content \"$HOME/.config/tiktok-page/credentials.json\" -Encoding UTF8\n\nRestrict file permissions immediately after saving:\n\n# Windows\nicacls \"$HOME/.config/tiktok-page/credentials.json\" /inheritance:r /grant:r \"$($env:USERNAME):(R,W)\"\n# macOS / Linux\n# chmod 600 ~/.config/tiktok-page/credentials.json\n\nNever commit this file to version control. It contains long-lived secrets.\nThis skill makes no external calls other than to open.tiktokapis.com. No data is forwarded to third parties."
      },
      {
        "title": "STEP 2 - Token Refresh",
        "body": "TikTok access tokens expire after 24 hours. Refresh before making calls if needed:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$body = \"client_key=$($cfg.TIKTOK_CLIENT_KEY)&client_secret=$($cfg.TIKTOK_CLIENT_SECRET)&grant_type=refresh_token&refresh_token=$($cfg.TIKTOK_REFRESH_TOKEN)\"\n$r = Invoke-RestMethod \"https://open.tiktokapis.com/v2/oauth/token/\" -Method POST `\n    -Headers @{ \"Content-Type\" = \"application/x-www-form-urlencoded\" } -Body $body -ErrorAction Stop\n\n$cfg.TIKTOK_ACCESS_TOKEN  = $r.access_token\n$cfg.TIKTOK_REFRESH_TOKEN = $r.refresh_token\n$cfg | ConvertTo-Json | Set-Content \"$HOME/.config/tiktok-page/credentials.json\" -Encoding UTF8\nWrite-Host \"Tokens refreshed.\""
      },
      {
        "title": "Common Endpoints",
        "body": "What user wantsMethodEndpointGet account infoPOST/user/info/List own videosPOST/video/list/Get video detailPOST/video/query/Get commentsGET/video/comment/list/?video_id={id}Publish video from URLPOST/post/publish/video/init/ with PULL_FROM_URLUpload video from filePOST then PUT/post/publish/video/init/ then upload_urlCheck publish statusGET/post/publish/status/fetch/?publish_id={id}"
      },
      {
        "title": "API Call Patterns",
        "body": "GET account info:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ fields = \"display_name,avatar_url,follower_count,following_count,likes_count,video_count\" } | ConvertTo-Json\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/user/info/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.user\n\nList videos:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ max_count = 20; fields = \"id,title,create_time,cover_image_url,share_url,view_count,like_count,comment_count,share_count\" } | ConvertTo-Json\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/list/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.videos | Format-Table id, title, view_count, like_count, create_time\n\nGet video detail by ID:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ filters = @{ video_ids = @(\"<video_id>\") }; fields = \"id,title,view_count,like_count,comment_count,share_count,embed_html\" } | ConvertTo-Json -Depth 4\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/query/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.videos\n\nPublish video from URL:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body = @{\n    post_info = @{\n        title           = \"Your video caption\"\n        privacy_level   = \"PUBLIC_TO_EVERYONE\"\n        disable_duet    = $false\n        disable_stitch  = $false\n        disable_comment = $false\n    }\n    source_info = @{\n        source            = \"PULL_FROM_URL\"\n        video_url         = \"https://example.com/video.mp4\"\n        video_size        = 12345678\n        chunk_size        = 10000000\n        total_chunk_count = 1\n    }\n} | ConvertTo-Json -Depth 5\n$result = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/video/init/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\nWrite-Host \"Publish ID: $($result.data.publish_id)\"\n\nUpload video from local file:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$filePath  = \"C:\\path\\to\\video.mp4\"\n$fileSize  = (Get-Item $filePath).Length\n$chunkSize = 10MB\n\n$initBody = @{\n    post_info = @{\n        title           = \"Your caption\"\n        privacy_level   = \"PUBLIC_TO_EVERYONE\"\n        disable_duet    = $false\n        disable_stitch  = $false\n        disable_comment = $false\n    }\n    source_info = @{\n        source            = \"FILE_UPLOAD\"\n        video_size        = $fileSize\n        chunk_size        = $chunkSize\n        total_chunk_count = [math]::Ceiling($fileSize / $chunkSize)\n    }\n} | ConvertTo-Json -Depth 5\n$initResult = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/video/init/\" -Method POST -Headers $headers -Body $initBody -ErrorAction Stop\n$uploadUrl  = $initResult.data.upload_url\n$publishId  = $initResult.data.publish_id\n\n# Upload chunks\n$fileStream = [System.IO.File]::OpenRead($filePath)\n$buffer     = New-Object byte[] $chunkSize\n$chunkIndex = 0\nwhile (($bytesRead = $fileStream.Read($buffer, 0, $chunkSize)) -gt 0) {\n    $chunk      = $buffer[0..($bytesRead - 1)]\n    $rangeStart = $chunkIndex * $chunkSize\n    $rangeEnd   = $rangeStart + $bytesRead - 1\n    Invoke-RestMethod $uploadUrl -Method PUT -Headers @{\n        \"Content-Range\" = \"bytes $rangeStart-$rangeEnd/$fileSize\"\n        \"Content-Type\"  = \"video/mp4\"\n    } -Body $chunk | Out-Null\n    $chunkIndex++\n}\n$fileStream.Close()\nWrite-Host \"Upload complete. Publish ID: $publishId\"\n\nCheck publish status:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\" }\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/status/fetch/?publish_id=<publish_id>\" -Headers $headers -ErrorAction Stop\nWrite-Host \"Status: $($result.data.status)\"\n\nGet comments:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\" }\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/comment/list/?video_id=<video_id>&fields=id,text,create_time,like_count\" -Headers $headers -ErrorAction Stop\n$result.data.comments | Format-Table id, text, like_count, create_time"
      },
      {
        "title": "STEP 4 - Handle Errors",
        "body": "try {\n    # ... API call ...\n} catch {\n    $err     = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue\n    $code    = $err.error.code\n    $message = $err.error.message\n    Write-Host \"TikTok API Error $code: $message\"\n}\n\nCodeMeaningFixaccess_token_invalidToken revoked or invalidRe-run OAuth2 setup in STEP 1access_token_expiredAccess token expired (24h TTL)Run token refresh in STEP 2spam_risk_too_many_requestsRate limitedWait and retry; reduce request frequencyscope_not_authorizedMissing OAuth scopeRe-authorize with the required scope (see below)video_not_foundVideo ID invalid or deletedVerify the video IDprivacy_level_not_allowedPrivacy setting not permittedUse PUBLIC_TO_EVERYONE or SELF_ONLYfile_size_check_failedVideo file too largeMust be under 4GB and 60 minutesduration_check_failedVideo too short or too longMin 1 second, max 10 minutes (60 min for some accounts)"
      },
      {
        "title": "Scopes Reference",
        "body": "ScopeRequired foruser.info.basicGet account infovideo.listList own videosvideo.publishPublish videosvideo.uploadUpload video chunkscomment.listRead comments on own videoscomment.list.manageHide or delete comments\n\nIf a scope is missing:\n\nGo to https://developers.tiktok.com — select your app\nUnder Products, add the required scope\nRe-authorize (repeat STEP 1 OAuth2) with the new scope added to the URL\nSave the new tokens to credentials.json"
      },
      {
        "title": "AGENT RULES",
        "body": "Always load credentials first. If missing, guide OAuth2 setup from STEP 1.\nOnly use TIKTOK_ACCESS_TOKEN for API calls. TIKTOK_CLIENT_SECRET is for token refresh only.\nRotate TIKTOK_REFRESH_TOKEN and TIKTOK_ACCESS_TOKEN immediately if the host is ever compromised.\nNever write extra fields to the credentials file.\nAll API calls go to open.tiktokapis.com only. No external forwarding, no third-party services.\nConstruct API calls inline from user intent — do not look for script files.\nAccess tokens expire after 24 hours. If a call returns access_token_expired, run STEP 2 first then retry.\nOn any error: parse error.code, map to the table above, tell the user exactly what to do.\nIf a scope is missing: name it, link to developers.tiktok.com, say to re-authorize.\nOS detection: env:OS eq Windows_NT -> powershell; otherwise -> pwsh.\nNo hardcoded user IDs, video IDs, or tokens — all come from credentials.json."
      }
    ],
    "body": "tiktok-page — Universal TikTok API Skill\n\nConstructs and executes TikTok API calls inline based on what the user wants. No scripts needed.\n\nAPI base URL: https://open.tiktokapis.com/v2\n\nSTEP 1 - Load Credentials\n\nCredentials are stored in ~/.config/tiktok-page/credentials.json.\n\n$cfg          = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$accessToken  = $cfg.TIKTOK_ACCESS_TOKEN\n$refreshToken = $cfg.TIKTOK_REFRESH_TOKEN\n$clientKey    = $cfg.TIKTOK_CLIENT_KEY\n$clientSecret = $cfg.TIKTOK_CLIENT_SECRET\n$openId       = $cfg.TIKTOK_OPEN_ID\n\n\nIf the file does not exist, guide setup:\n\nField\tPurpose\nTIKTOK_ACCESS_TOKEN\tOAuth2 access token — used for all API calls\nTIKTOK_REFRESH_TOKEN\tUsed to refresh access token when expired\nTIKTOK_CLIENT_KEY\tApp Client Key from TikTok Developer Portal\nTIKTOK_CLIENT_SECRET\tApp Client Secret — for token refresh only\nTIKTOK_OPEN_ID\tTikTok user open_id returned during OAuth\n\nOne-time OAuth2 setup:\n\n1. Go to https://developers.tiktok.com — create or select your app\n2. Add redirect URI (e.g. https://localhost or your callback URL)\n3. Note your Client Key and Client Secret\n4. Direct user to:\n   https://www.tiktok.com/v2/auth/authorize/?client_key=CLIENT_KEY&redirect_uri=REDIRECT_URI&response_type=code&scope=user.info.basic,video.list,video.publish,video.upload,comment.list&state=random\n5. After redirect, copy the code param from the callback URL\n\n# Exchange auth code for tokens\n$clientKey   = \"<your-client-key>\"\n$clientSecret = \"<your-client-secret>\"\n$code        = \"<auth-code-from-redirect>\"\n$redirectUri = \"<your-redirect-uri>\"\n\n$body = \"client_key=$clientKey&client_secret=$clientSecret&code=$code&grant_type=authorization_code&redirect_uri=$redirectUri\"\n$r = Invoke-RestMethod \"https://open.tiktokapis.com/v2/oauth/token/\" -Method POST `\n    -Headers @{ \"Content-Type\" = \"application/x-www-form-urlencoded\" } -Body $body -ErrorAction Stop\n\nNew-Item -ItemType Directory -Force -Path \"$HOME/.config/tiktok-page\" | Out-Null\n@{\n    TIKTOK_ACCESS_TOKEN  = $r.access_token\n    TIKTOK_REFRESH_TOKEN = $r.refresh_token\n    TIKTOK_CLIENT_KEY    = $clientKey\n    TIKTOK_CLIENT_SECRET = $clientSecret\n    TIKTOK_OPEN_ID       = $r.open_id\n} | ConvertTo-Json | Set-Content \"$HOME/.config/tiktok-page/credentials.json\" -Encoding UTF8\n\n\nRestrict file permissions immediately after saving:\n\n# Windows\nicacls \"$HOME/.config/tiktok-page/credentials.json\" /inheritance:r /grant:r \"$($env:USERNAME):(R,W)\"\n# macOS / Linux\n# chmod 600 ~/.config/tiktok-page/credentials.json\n\n\nNever commit this file to version control. It contains long-lived secrets. This skill makes no external calls other than to open.tiktokapis.com. No data is forwarded to third parties.\n\nSTEP 2 - Token Refresh\n\nTikTok access tokens expire after 24 hours. Refresh before making calls if needed:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$body = \"client_key=$($cfg.TIKTOK_CLIENT_KEY)&client_secret=$($cfg.TIKTOK_CLIENT_SECRET)&grant_type=refresh_token&refresh_token=$($cfg.TIKTOK_REFRESH_TOKEN)\"\n$r = Invoke-RestMethod \"https://open.tiktokapis.com/v2/oauth/token/\" -Method POST `\n    -Headers @{ \"Content-Type\" = \"application/x-www-form-urlencoded\" } -Body $body -ErrorAction Stop\n\n$cfg.TIKTOK_ACCESS_TOKEN  = $r.access_token\n$cfg.TIKTOK_REFRESH_TOKEN = $r.refresh_token\n$cfg | ConvertTo-Json | Set-Content \"$HOME/.config/tiktok-page/credentials.json\" -Encoding UTF8\nWrite-Host \"Tokens refreshed.\"\n\nSTEP 3 - Figure Out the API Call\nCommon Endpoints\nWhat user wants\tMethod\tEndpoint\nGet account info\tPOST\t/user/info/\nList own videos\tPOST\t/video/list/\nGet video detail\tPOST\t/video/query/\nGet comments\tGET\t/video/comment/list/?video_id={id}\nPublish video from URL\tPOST\t/post/publish/video/init/ with PULL_FROM_URL\nUpload video from file\tPOST then PUT\t/post/publish/video/init/ then upload_url\nCheck publish status\tGET\t/post/publish/status/fetch/?publish_id={id}\nAPI Call Patterns\n\nGET account info:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ fields = \"display_name,avatar_url,follower_count,following_count,likes_count,video_count\" } | ConvertTo-Json\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/user/info/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.user\n\n\nList videos:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ max_count = 20; fields = \"id,title,create_time,cover_image_url,share_url,view_count,like_count,comment_count,share_count\" } | ConvertTo-Json\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/list/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.videos | Format-Table id, title, view_count, like_count, create_time\n\n\nGet video detail by ID:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body    = @{ filters = @{ video_ids = @(\"<video_id>\") }; fields = \"id,title,view_count,like_count,comment_count,share_count,embed_html\" } | ConvertTo-Json -Depth 4\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/query/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\n$result.data.videos\n\n\nPublish video from URL:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$body = @{\n    post_info = @{\n        title           = \"Your video caption\"\n        privacy_level   = \"PUBLIC_TO_EVERYONE\"\n        disable_duet    = $false\n        disable_stitch  = $false\n        disable_comment = $false\n    }\n    source_info = @{\n        source            = \"PULL_FROM_URL\"\n        video_url         = \"https://example.com/video.mp4\"\n        video_size        = 12345678\n        chunk_size        = 10000000\n        total_chunk_count = 1\n    }\n} | ConvertTo-Json -Depth 5\n$result = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/video/init/\" -Method POST -Headers $headers -Body $body -ErrorAction Stop\nWrite-Host \"Publish ID: $($result.data.publish_id)\"\n\n\nUpload video from local file:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\"; \"Content-Type\" = \"application/json; charset=UTF-8\" }\n$filePath  = \"C:\\path\\to\\video.mp4\"\n$fileSize  = (Get-Item $filePath).Length\n$chunkSize = 10MB\n\n$initBody = @{\n    post_info = @{\n        title           = \"Your caption\"\n        privacy_level   = \"PUBLIC_TO_EVERYONE\"\n        disable_duet    = $false\n        disable_stitch  = $false\n        disable_comment = $false\n    }\n    source_info = @{\n        source            = \"FILE_UPLOAD\"\n        video_size        = $fileSize\n        chunk_size        = $chunkSize\n        total_chunk_count = [math]::Ceiling($fileSize / $chunkSize)\n    }\n} | ConvertTo-Json -Depth 5\n$initResult = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/video/init/\" -Method POST -Headers $headers -Body $initBody -ErrorAction Stop\n$uploadUrl  = $initResult.data.upload_url\n$publishId  = $initResult.data.publish_id\n\n# Upload chunks\n$fileStream = [System.IO.File]::OpenRead($filePath)\n$buffer     = New-Object byte[] $chunkSize\n$chunkIndex = 0\nwhile (($bytesRead = $fileStream.Read($buffer, 0, $chunkSize)) -gt 0) {\n    $chunk      = $buffer[0..($bytesRead - 1)]\n    $rangeStart = $chunkIndex * $chunkSize\n    $rangeEnd   = $rangeStart + $bytesRead - 1\n    Invoke-RestMethod $uploadUrl -Method PUT -Headers @{\n        \"Content-Range\" = \"bytes $rangeStart-$rangeEnd/$fileSize\"\n        \"Content-Type\"  = \"video/mp4\"\n    } -Body $chunk | Out-Null\n    $chunkIndex++\n}\n$fileStream.Close()\nWrite-Host \"Upload complete. Publish ID: $publishId\"\n\n\nCheck publish status:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\" }\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/post/publish/status/fetch/?publish_id=<publish_id>\" -Headers $headers -ErrorAction Stop\nWrite-Host \"Status: $($result.data.status)\"\n\n\nGet comments:\n\n$cfg = Get-Content \"$HOME/.config/tiktok-page/credentials.json\" -Raw | ConvertFrom-Json\n$headers = @{ \"Authorization\" = \"Bearer $($cfg.TIKTOK_ACCESS_TOKEN)\" }\n$result  = Invoke-RestMethod \"https://open.tiktokapis.com/v2/video/comment/list/?video_id=<video_id>&fields=id,text,create_time,like_count\" -Headers $headers -ErrorAction Stop\n$result.data.comments | Format-Table id, text, like_count, create_time\n\nSTEP 4 - Handle Errors\ntry {\n    # ... API call ...\n} catch {\n    $err     = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue\n    $code    = $err.error.code\n    $message = $err.error.message\n    Write-Host \"TikTok API Error $code: $message\"\n}\n\nCode\tMeaning\tFix\naccess_token_invalid\tToken revoked or invalid\tRe-run OAuth2 setup in STEP 1\naccess_token_expired\tAccess token expired (24h TTL)\tRun token refresh in STEP 2\nspam_risk_too_many_requests\tRate limited\tWait and retry; reduce request frequency\nscope_not_authorized\tMissing OAuth scope\tRe-authorize with the required scope (see below)\nvideo_not_found\tVideo ID invalid or deleted\tVerify the video ID\nprivacy_level_not_allowed\tPrivacy setting not permitted\tUse PUBLIC_TO_EVERYONE or SELF_ONLY\nfile_size_check_failed\tVideo file too large\tMust be under 4GB and 60 minutes\nduration_check_failed\tVideo too short or too long\tMin 1 second, max 10 minutes (60 min for some accounts)\nScopes Reference\nScope\tRequired for\nuser.info.basic\tGet account info\nvideo.list\tList own videos\nvideo.publish\tPublish videos\nvideo.upload\tUpload video chunks\ncomment.list\tRead comments on own videos\ncomment.list.manage\tHide or delete comments\n\nIf a scope is missing:\n\nGo to https://developers.tiktok.com — select your app\nUnder Products, add the required scope\nRe-authorize (repeat STEP 1 OAuth2) with the new scope added to the URL\nSave the new tokens to credentials.json\nAGENT RULES\nAlways load credentials first. If missing, guide OAuth2 setup from STEP 1.\nOnly use TIKTOK_ACCESS_TOKEN for API calls. TIKTOK_CLIENT_SECRET is for token refresh only.\nRotate TIKTOK_REFRESH_TOKEN and TIKTOK_ACCESS_TOKEN immediately if the host is ever compromised.\nNever write extra fields to the credentials file.\nAll API calls go to open.tiktokapis.com only. No external forwarding, no third-party services.\nConstruct API calls inline from user intent — do not look for script files.\nAccess tokens expire after 24 hours. If a call returns access_token_expired, run STEP 2 first then retry.\nOn any error: parse error.code, map to the table above, tell the user exactly what to do.\nIf a scope is missing: name it, link to developers.tiktok.com, say to re-authorize.\nOS detection: env:OS eq Windows_NT -> powershell; otherwise -> pwsh.\nNo hardcoded user IDs, video IDs, or tokens — all come from credentials.json."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/seph1709/tiktok-page",
    "publisherUrl": "https://clawhub.ai/seph1709/tiktok-page",
    "owner": "seph1709",
    "version": "1.0.4",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/tiktok-page",
    "downloadUrl": "https://openagent3.xyz/downloads/tiktok-page",
    "agentUrl": "https://openagent3.xyz/skills/tiktok-page/agent",
    "manifestUrl": "https://openagent3.xyz/skills/tiktok-page/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/tiktok-page/agent.md"
  }
}