@acedatacloud/skills 2026.728.7 → 2026.801.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acedatacloud/skills",
3
- "version": "2026.728.7",
3
+ "version": "2026.801.1",
4
4
  "description": "Agent Skills for AceDataCloud AI services — music, image, video generation, LLM chat, web search. Compatible with Claude Code, GitHub Copilot, Gemini CLI, OpenAI Codex, and 30+ AI coding agents.",
5
5
  "keywords": [
6
6
  "agent-skills",
@@ -1,63 +1,152 @@
1
1
  ---
2
2
  name: tiktok
3
- description: Upload videos to the user's TikTok inbox/drafts and read their TikTok profile via the Content Posting API. Use when the user wants to publish or post a generated video to TikTok, send a video to their TikTok drafts, or check their TikTok account.
3
+ description: Post videos to the user's TikTok — either published directly (with caption and privacy the user chooses) or uploaded to their drafts/inbox — and read their TikTok profile, stats and video list. Use when the user wants to publish or post a generated video to TikTok, send a video to their TikTok drafts, or check their TikTok account and performance.
4
4
  when_to_use: |
5
5
  Trigger when the user wants to push a video (e.g. one generated by
6
- the video skills) to TikTok. v1 uploads to the user's **inbox /
7
- drafts** (they finish posting in the TikTok app) — the safe,
8
- pre-audit path. Confirm before uploading; the video must be a public
9
- URL on a verified domain (or a file you upload in chunks).
6
+ the video skills) to TikTok, or to read their TikTok account and
7
+ post performance. Direct Post publishes immediately with a caption
8
+ and a privacy level the user picks; Upload drops it into drafts for
9
+ them to finish in the app. Always confirm caption and privacy with
10
+ the user before posting — never post unattended.
10
11
  connections: [tiktok]
11
12
  allowed_tools: [Bash]
12
13
  license: Apache-2.0
13
14
  metadata:
14
15
  author: acedatacloud
15
- version: "1.0"
16
+ version: "2.0"
16
17
  ---
17
18
 
18
- Call the **TikTok Content Posting API** with `curl + jq`. The user's OAuth bearer
19
- token is in `$TIKTOK_TOKEN`; every call needs `Authorization: Bearer
20
- $TIKTOK_TOKEN`. Base URL: `https://open.tiktokapis.com/v2`.
21
-
22
- Responses wrap everything in `{"data":...,"error":{"code","message","log_id"}}` —
23
- `error.code == "ok"` means success; otherwise show `error.message` verbatim.
24
- `401`/`access_token_invalid` = re-connect TikTok.
19
+ Call the **TikTok API v2** with `curl + jq`. The user's OAuth bearer token is in
20
+ `$TIKTOK_TOKEN`; every call needs `Authorization: Bearer $TIKTOK_TOKEN`. Base
21
+ URL: `https://open.tiktokapis.com/v2`.
25
22
 
26
23
  ```bash
27
24
  T="https://open.tiktokapis.com/v2"; AUTH="Authorization: Bearer $TIKTOK_TOKEN"
28
- # Profile (account card)
29
- curl -sS -H "$AUTH" "$T/user/info/?fields=open_id,display_name,avatar_url" \
25
+ ```
26
+
27
+ Responses wrap everything in `{"data":…,"error":{"code","message","log_id"}}`.
28
+ **Check `error.code`, not just the HTTP status** — several real failures
29
+ (`spam_risk_too_many_posts`, `spam_risk_user_banned_from_posting`,
30
+ `reached_active_user_cap`) come back as **HTTP 200** with a non-`ok` code. Show
31
+ `error.message` verbatim. `401` / `access_token_invalid` = re-connect TikTok.
32
+
33
+ ## Read the account
34
+
35
+ ```bash
36
+ # Profile + stats (needs user.info.profile / user.info.stats)
37
+ curl -sS -H "$AUTH" "$T/user/info/?fields=open_id,display_name,avatar_url,username,is_verified,follower_count,following_count,likes_count,video_count" \
30
38
  | jq '.data.user'
31
39
  ```
32
40
 
33
- ## Upload a video to the user's inbox / drafts (v1)
41
+ ## List the user's videos
34
42
 
35
- The simplest path is `PULL_FROM_URL`: TikTok fetches the video from a public URL
36
- on a **verified domain** (AceData's `cdn.acedata.cloud` is verified for this app).
43
+ `fields` goes in the **query string**, pagination in the **body** (easy to get
44
+ wrong). `max_count` max is 20; `cursor` is a **millisecond** UTC timestamp,
45
+ while each video's `create_time` is in **seconds**.
37
46
 
38
47
  ```bash
39
- VIDEO_URL="https://cdn.acedata.cloud/...mp4" # must be on a verified domain
40
- curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" -d "$(jq -n --arg u "$VIDEO_URL" \
41
- '{source_info:{source:"PULL_FROM_URL", video_url:$u}}')" \
42
- "$T/post/publish/inbox/video/init/" | jq '{publish_id: .data.publish_id, error}'
48
+ curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
49
+ "$T/video/list/?fields=id,title,video_description,create_time,duration,cover_image_url,share_url,view_count,like_count,comment_count,share_count" \
50
+ -d '{"max_count":20}' | jq '{videos:.data.videos, cursor:.data.cursor, has_more:.data.has_more}'
43
51
  ```
44
52
 
45
- This drops the video into the user's TikTok **inbox** — they open the TikTok app
46
- to add caption / sound / privacy and post. Poll status:
53
+ Only **public** videos are returned, newest first.
54
+
55
+ ## Direct Post — publish straight to the account
56
+
57
+ Three steps, in this order. **Step 1 is mandatory** and its result drives what
58
+ you may offer the user.
59
+
60
+ ### 1. Query creator info (required before every post)
47
61
 
48
62
  ```bash
49
63
  curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
50
- -d '{"publish_id":"PUBLISH_ID"}' "$T/post/publish/status/fetch/" \
51
- | jq '.data | {status, fail_reason}'
64
+ "$T/post/publish/creator_info/query/" | jq '.data, .error.code'
52
65
  ```
53
66
 
67
+ Returns `creator_nickname`, `privacy_level_options`, `comment_disabled`,
68
+ `duet_disabled`, `stitch_disabled`, `max_video_post_duration_sec`.
69
+
70
+ Use it to:
71
+ - **Show the user `creator_nickname`** so they know which account will receive
72
+ the post.
73
+ - **Offer only the returned `privacy_level_options`** — a public account gets
74
+ `PUBLIC_TO_EVERYONE` / `MUTUAL_FOLLOW_FRIENDS` / `SELF_ONLY`; a private one
75
+ gets `FOLLOWER_OF_CREATOR` / `MUTUAL_FOLLOW_FRIENDS` / `SELF_ONLY`.
76
+ - **Reject a too-long video** against `max_video_post_duration_sec`.
77
+ - Not offer comment/duet/stitch toggles that come back disabled.
78
+ - If it returns a spam/cap error, **stop** and tell the user to try later.
79
+
80
+ ### 2. Ask the user to confirm
81
+
82
+ Before initializing, the user must explicitly confirm — this is a TikTok
83
+ requirement, not just good manners:
84
+
85
+ - the **caption** (max 2200 UTF-16 chars; `#tag` and `@mention` work),
86
+ - the **privacy level**, **chosen by them from the options above — never
87
+ default to one, never assume `PUBLIC_TO_EVERYONE`**,
88
+ - and tell them: *"By posting, you agree to TikTok's Music Usage Confirmation."*
89
+
90
+ ### 3. Initialize the post
91
+
92
+ ```bash
93
+ VIDEO_URL="https://cdn.acedata.cloud/….mp4" # verified-domain public URL
94
+ curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
95
+ -d "$(jq -n --arg t "$CAPTION" --arg p "$PRIVACY" --arg u "$VIDEO_URL" '{
96
+ post_info: {title:$t, privacy_level:$p, is_aigc:true},
97
+ source_info: {source:"PULL_FROM_URL", video_url:$u}}')" \
98
+ "$T/post/publish/video/init/" | jq '{publish_id:.data.publish_id, error}'
99
+ ```
100
+
101
+ **Set `is_aigc: true` whenever the video was AI-generated** (anything from our
102
+ video skills). TikTok labels it "Creator labeled as AI-generated" — required
103
+ disclosure, and omitting it risks the post being taken down.
104
+
105
+ Optional `post_info` fields: `disable_comment`, `disable_duet`,
106
+ `disable_stitch`, `video_cover_timestamp_ms`. If the user says the video is a
107
+ paid partnership, set `brand_content_toggle: true` (which cannot be combined
108
+ with `SELF_ONLY`); for promoting their own business use `brand_organic_toggle`.
109
+
110
+ ## Upload to drafts instead
111
+
112
+ When the user would rather finish in the app, use the inbox endpoint — no
113
+ caption or privacy, and **no `creator_info` call needed**:
114
+
115
+ ```bash
116
+ curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
117
+ -d "$(jq -n --arg u "$VIDEO_URL" '{source_info:{source:"PULL_FROM_URL", video_url:$u}}')" \
118
+ "$T/post/publish/inbox/video/init/" | jq '{publish_id:.data.publish_id, error}'
119
+ ```
120
+
121
+ ## Poll status (both flows)
122
+
123
+ ```bash
124
+ curl -sS -X POST -H "$AUTH" -H "Content-Type: application/json" \
125
+ -d "$(jq -n --arg id "$PUBLISH_ID" '{publish_id:$id}')" \
126
+ "$T/post/publish/status/fetch/" | jq '.data | {status, fail_reason, publicaly_available_post_id}'
127
+ ```
128
+
129
+ Status: `PROCESSING_DOWNLOAD` / `PROCESSING_UPLOAD` → `SEND_TO_USER_INBOX`
130
+ (drafts flow) or `PUBLISH_COMPLETE` (direct post), or `FAILED` with
131
+ `fail_reason`. Tell the user processing takes a few minutes.
132
+
133
+ Don't retry on `auth_removed`, `spam_risk_text`, `spam_risk`, or
134
+ `spam_risk_user_banned_from_posting` — those are terminal. `internal` is
135
+ retryable.
136
+
54
137
  ## Gotchas
55
138
 
56
- - **v1 = inbox upload only.** True "Direct Post" (set caption + privacy via API,
57
- posts immediately) needs the `video.publish` scope and a passed Content Posting
58
- audit — not available until then. Don't call `creator_info` /
59
- `/post/publish/video/init/` (Direct Post) here; they require that scope.
60
- - `PULL_FROM_URL` only works from a **domain verified** in the TikTok developer
61
- app. If the video isn't on a verified domain, use the chunked `FILE_UPLOAD`
62
- flow instead (init → PUT byte ranges → status).
63
- - Unaudited apps are rate-limited and may restrict visibility to `SELF_ONLY`.
139
+ - **Never hardcode `privacy_level`.** TikTok rejects values outside
140
+ `privacy_level_options` (`privacy_level_option_mismatch`) and treats a
141
+ defaulted privacy setting as a guideline violation for the whole app.
142
+ - `publicaly_available_post_id` (TikTok's own spelling — don't "fix" it) is a
143
+ **list**, and is **empty for non-public posts and for public posts still in
144
+ moderation**. Empty ≠ failure.
145
+ - `PULL_FROM_URL` needs the URL's domain verified in the developer app, HTTPS,
146
+ and **no redirects** (any 3xx fails). Verification covers subdomains
147
+ downward only. If the video isn't on a verified domain, use chunked
148
+ `FILE_UPLOAD` (init with `video_size`/`chunk_size`/`total_chunk_count`, then
149
+ `PUT` byte ranges to `upload_url`, which expires in 1 hour).
150
+ - Rate limits per user token: `creator_info/query` 20/min, `video/init/`
151
+ **6/min**, `status/fetch/` 30/min. TikTok also caps posts at roughly 15/day
152
+ per creator, shared across all apps.
@@ -31,8 +31,8 @@ A successful synchronous response:
31
31
  ```json
32
32
  {
33
33
  "token": "0.mNQ2f9uP6mQ0y3H5Q8bqO7iM...",
34
- "started_at": "2026-07-24T09:34:13+00:00",
35
- "finished_at": "2026-07-24T09:34:25+00:00",
34
+ "started_at": 1784885653.0,
35
+ "finished_at": 1784885665.0,
36
36
  "elapsed": 12.4
37
37
  }
38
38
  ```