threads

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese
Call the Threads API (
graph.threads.net
) with
curl + jq
. The connector injects one credential:
$THREADS_ACCESS_TOKEN
(a long-lived Threads access token with the
threads_basic
+
threads_content_publish
scopes). Never echo it.
Resolve the caller's Threads user id once (every publish needs it):
bash
ME=$(curl -sS "https://graph.threads.net/v1.0/me?fields=id,username&access_token=$THREADS_ACCESS_TOKEN")
TID=$(echo "$ME" | jq -r .id)
echo "$ME"     # {"id":"<THREADS_USER_ID>","username":"..."}
Errors are JSON with
error.message
/
error.code
— show them verbatim.
401
/
OAuthException
→ the token expired or lacks scope; reconnect the Threads connector.
使用
curl + jq
调用Threads API
graph.threads.net
)。连接器会注入一个凭据:
$THREADS_ACCESS_TOKEN
(具有
threads_basic
+
threads_content_publish
权限的长期Threads访问令牌)。切勿回显该令牌。
先获取调用者的Threads用户ID(每次发布都需要它):
bash
ME=$(curl -sS "https://graph.threads.net/v1.0/me?fields=id,username&access_token=$THREADS_ACCESS_TOKEN")
TID=$(echo "$ME" | jq -r .id)
echo "$ME"     # {"id":"<THREADS_USER_ID>","username":"..."}
错误信息为包含
error.message
/
error.code
的JSON格式——直接显示原始信息。
401
/
OAuthException
表示令牌过期或权限不足;请重新连接Threads连接器。

Publish a post (two-step: create container → publish)

发布帖子(两步:创建容器 → 发布)

Confirm the text with the user first (it publishes as their real account). Text ≤ 500 characters (emoji counted as UTF-8 bytes).
Step 1 — create a media container. Text-only (guard the 500-byte limit first):
bash
TEXT="Shipping one API for AI images → posters, cards, mockups. https://platform.acedata.cloud #AI #API"
[ "$(printf %s "$TEXT" | wc -c)" -le 500 ] || { echo "text exceeds Threads 500-byte limit — shorten it"; }
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
  --data-urlencode "media_type=TEXT" \
  --data-urlencode "text=$TEXT" \
  -d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
echo "container=$CID"
Image post — add
media_type=IMAGE
+ a public
image_url
(Threads cURLs it server-side, so it must be on a public server); video uses
media_type=VIDEO
+
video_url
:
bash
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
  --data-urlencode "media_type=IMAGE" \
  -d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
  --data-urlencode "text=caption here" \
  -d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
Step 2 — publish the container. Text posts publish immediately; for IMAGE / VIDEO / carousel containers you MUST wait ≥30s first so Threads can fetch/process the upload — publishing too early fails or returns no id:
bash
sleep 30   # REQUIRED for IMAGE / VIDEO / carousel; skip for TEXT-only posts
curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads_publish" \
  -d "creation_id=$CID" -d "access_token=$THREADS_ACCESS_TOKEN" | jq .
请先与用户确认文本内容(帖子将以用户真实账户发布)。文本长度≤500字符(表情符号按UTF-8字节数计算)。
步骤1 — 创建媒体容器。纯文本帖子(先确保不超过500字节限制):
bash
TEXT="Shipping one API for AI images → posters, cards, mockups. https://platform.acedata.cloud #AI #API"
[ "$(printf %s "$TEXT" | wc -c)" -le 500 ] || { echo "text exceeds Threads 500-byte limit — shorten it"; }
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
  --data-urlencode "media_type=TEXT" \
  --data-urlencode "text=$TEXT" \
  -d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
echo "container=$CID"
图片帖子 — 添加
media_type=IMAGE
+ 一个公开
image_url
(Threads会通过服务器端curl获取该图片,因此图片必须存储在公开服务器上);视频帖子使用
media_type=VIDEO
+
video_url
bash
CID=$(curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads" \
  --data-urlencode "media_type=IMAGE" \
  -d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
  --data-urlencode "text=caption here" \
  -d "access_token=$THREADS_ACCESS_TOKEN" | jq -r .id)
步骤2 — 发布容器。纯文本帖子会立即发布;对于图片/视频/轮播容器,必须等待≥30秒,以便Threads获取/处理上传内容——过早发布会失败或返回空ID:
bash
sleep 30   # 图片/视频/轮播帖子必须执行此步骤;纯文本帖子可跳过
curl -sS -X POST "https://graph.threads.net/v1.0/$TID/threads_publish" \
  -d "creation_id=$CID" -d "access_token=$THREADS_ACCESS_TOKEN" | jq .

→ {"id":"<THREADS_MEDIA_ID>"}

→ {"id":"<THREADS_MEDIA_ID>"}


If `threads_publish` returns no id, the container isn't ready yet — poll
`GET /v1.0/<CID>?fields=status&access_token=$THREADS_ACCESS_TOKEN` until
`status=FINISHED`, then retry publish.

Get the public URL of the published post and hand it to the user:

```bash
curl -sS "https://graph.threads.net/v1.0/<THREADS_MEDIA_ID>?fields=id,permalink&access_token=$THREADS_ACCESS_TOKEN" | jq -r .permalink

如果`threads_publish`未返回ID,说明容器尚未准备好——轮询调用`GET /v1.0/<CID>?fields=status&access_token=$THREADS_ACCESS_TOKEN`,直到`status=FINISHED`,然后重试发布。

获取已发布帖子的公开URL并提供给用户:

```bash
curl -sS "https://graph.threads.net/v1.0/<THREADS_MEDIA_ID>?fields=id,permalink&access_token=$THREADS_ACCESS_TOKEN" | jq -r .permalink

Carousel (2–20 items)

轮播帖子(2–20个内容项)

Create each child with
is_carousel_item=true
, then a
media_type=CAROUSEL
container with
children=<ID1>,<ID2>,...
, then publish the carousel id. Links: add
link_attachment=<URL>
(text-only posts, ≤5 links). Topic tag:
topic_tag=<TAG>
.
创建每个子项时设置
is_carousel_item=true
,然后创建一个
media_type=CAROUSEL
的容器并设置
children=<ID1>,<ID2>,...
,最后发布该轮播容器的ID。添加链接:设置
link_attachment=<URL>
(仅适用于纯文本帖子,最多5个链接)。话题标签:
topic_tag=<TAG>

List my recent posts

查看我的近期帖子

bash
curl -sS "https://graph.threads.net/v1.0/$TID/threads?fields=id,text,permalink,timestamp&limit=20&access_token=$THREADS_ACCESS_TOKEN" | jq '.data'
bash
curl -sS "https://graph.threads.net/v1.0/$TID/threads?fields=id,text,permalink,timestamp&limit=20&access_token=$THREADS_ACCESS_TOKEN" | jq '.data'

Gotchas

注意事项

  • 500-char limit; emoji count as their UTF-8 byte length.
  • Media must be a public URL — Threads server-side cURLs
    image_url
    /
    video_url
    ; local files won't work. Upload to a public host / cdn.acedata.cloud first.
  • Wait ~30s before publishing media containers (text publishes instantly); if
    threads_publish
    doesn't return an id, poll
    GET /<container-id>?fields=status
    .
  • Rate limit: 250 published posts per 24h per profile (a carousel counts as 1).
  • Threads tokens differ from Facebook/Instagram tokens — they come from the Threads OAuth flow on
    graph.threads.net
    , not
    graph.facebook.com
    .
  • 500字符限制;表情符号按其UTF-8字节长度计算。
  • 媒体文件必须使用公开URL——Threads会通过服务器端curl获取
    image_url
    /
    video_url
    ;本地文件无法使用。请先上传到公开主机或cdn.acedata.cloud。
  • 发布媒体容器前需等待约30秒(纯文本帖子可立即发布);如果
    threads_publish
    未返回ID,请轮询调用
    GET /<container-id>?fields=status
  • 速率限制:每个账户每24小时最多发布250个帖子(轮播帖子算作1个)。
  • Threads令牌与Facebook/Instagram令牌不同——它们来自
    graph.threads.net
    上的Threads OAuth流程,而非
    graph.facebook.com

Record the output

记录输出

After you successfully publish and obtain the live permalink, call the built-in
publish_artifact
tool ONCE so the user can track it in My Outputs:
publish_artifact(kind="message", channel="threads", title="<title>", url="<the REAL permalink>", status="delivered")
Use the real returned URL — never fabricate one. Call it once per published item, only after delivery is confirmed; skip it (or use
status="failed"
) if publishing failed. See
_shared/artifacts.md
.
成功发布并获取到有效 permalink 后,调用内置的
publish_artifact
工具一次,以便用户在「我的输出」中跟踪该帖子:
publish_artifact(kind="message", channel="threads", title="<title>", url="<the REAL permalink>", status="delivered")
请使用实际返回的URL——切勿伪造。每个已发布的内容项仅调用一次,且仅在确认发布成功后调用;如果发布失败,请跳过该调用(或使用
status="failed"
)。详情请查看
_shared/artifacts.md