instagram

v2026.09.24

Publish images, videos, Reels or carousels to your Instagram professional account via the Instagram Content Publishing API, and read your own recent media. Use when the user wants to post to Instagram (photo / video / reel / carousel), cross-post a visual, or review their own Instagram posts. Instagram is image/video-only (no text-only posts). Auth uses an access token (BYOC). 支持 Instagram 图片 / 视频 / Reels / 轮播发布。

GitHub
安装命令
npx skhub add acedatacloud/instagram
Markdown
SKILL.md

Call the Instagram Graph API (graph.facebook.com) with curl + jq. The connector injects $INSTAGRAM_ACCESS_TOKEN (a token with instagram_content_publish + pages_read_engagement; a Facebook Page token or an Instagram-Login user token) and optionally $INSTAGRAM_IG_USER_ID. Never echo them.

Instagram publishes only images / videos / reels to a professional (Business or Creator) account linked to a Facebook Page. There are no text-only posts.

Resolve the Instagram account id

If $INSTAGRAM_IG_USER_ID is set, use it. Otherwise derive it from the token — try the Page-token path first (/me is the Page), then fall back to the user-token path (/me/accounts → linked Page → IG account), so either token type the connector accepts resolves cleanly:

if [ -n "$INSTAGRAM_IG_USER_ID" ]; then
  IGID="$INSTAGRAM_IG_USER_ID"
else
  # Page access token: /me IS the Page, read its linked IG account directly
  IGID=$(curl -sS "https://graph.facebook.com/v21.0/me?fields=instagram_business_account&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.instagram_business_account.id // empty')
  if [ -z "$IGID" ]; then
    # User access token: list the managed Page, then its linked IG account
    PAGE=$(curl -sS "https://graph.facebook.com/v21.0/me/accounts?access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.data[0].id // empty')
    IGID=$(curl -sS "https://graph.facebook.com/v21.0/$PAGE?fields=instagram_business_account&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r '.instagram_business_account.id // empty')
  fi
fi
echo "ig_user_id=$IGID"

Errors are JSON with error.message / error.code — show them verbatim. 401 / OAuthException → token expired or missing scope; a null IGID → the token isn't linked to a professional IG account / Page (see Gotchas). Reconnect if needed.

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

Confirm the caption + image with the user first. The image_url must be a public JPEG URL (Instagram server-side cURLs it):

CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
  -d "image_url=https://cdn.acedata.cloud/xxxx.jpg" \
  --data-urlencode "caption=One endpoint → posters, cards, mockups. #AI #API" \
  -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)
echo "container=$CID"

curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
  -d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .
# → {"id":"<IG_MEDIA_ID>"}

Get the permalink to hand back to the user:

curl -sS "https://graph.facebook.com/v21.0/<IG_MEDIA_ID>?fields=permalink&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .permalink

Reels / video

Create with media_type=REELS + a public video_url, then poll the container status until FINISHED before publishing (video processing takes time):

CID=$(curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media" \
  -d "media_type=REELS" -d "video_url=https://cdn.acedata.cloud/xxxx.mp4" \
  --data-urlencode "caption=..." -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .id)

# poll until the video finishes processing (up to ~5 min) BEFORE publishing —
# publishing an IN_PROGRESS container is rejected:
for i in $(seq 1 60); do
  ST=$(curl -sS "https://graph.facebook.com/v21.0/$CID?fields=status_code&access_token=$INSTAGRAM_ACCESS_TOKEN" | jq -r .status_code)
  echo "status=$ST"; [ "$ST" = "FINISHED" ] && break
  [ "$ST" = "ERROR" ] || [ "$ST" = "EXPIRED" ] && { echo "container failed: $ST"; break; }
  sleep 5
done

curl -sS -X POST "https://graph.facebook.com/v21.0/$IGID/media_publish" \
  -d "creation_id=$CID" -d "access_token=$INSTAGRAM_ACCESS_TOKEN" | jq .

Carousel (2–10 items)

Create each child with is_carousel_item=true, then a media_type=CAROUSEL container with children=<ID1>,<ID2>,... + caption, then publish the carousel id.

Gotchas

  • No text-only posts — Instagram requires an image or video. Use a public JPEG for images (PNG/other formats are rejected; extended JPEG like MPO/JPS too).
  • Professional account required — a Business/Creator IG account linked to a Facebook Page. If instagram_business_account is null, the account isn't a professional account or isn't linked; the user must fix that in IG / Page settings.
  • Media must be a public URL on a server Instagram can reach; local files won't work. Host on cdn.acedata.cloud first.
  • Rate limit: 100 API-published posts per 24h (a carousel counts as 1). Check via GET /$IGID/content_publishing_limit.
  • Page Publishing Authorization (PPA): some Pages must complete PPA before API publishing works — surface the API error verbatim if it mentions PPA.
  • API version: keep the vXX.0 path current if you hit a version/deprecation error.

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="image", channel="instagram", 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.

发现
标签

此技能尚未发布标签。

版本
最新版本元数据

版本

v2026.09.24

发布时间

Sep 24, 2026

分类

未分类

许可证

NOASSERTION

源路径

skills/instagram

默认分支

main

最新提交

57cc298

Tree SHA

acaa402