agentsclimarketplace

Instagram

Skill AceDataCloud/Skills/skills/instagram

Agent Skills for AceDataCloud AI services — music, image, video generation, web search, and more. Compatible with Claude Code, GitHub Copilot, Gemini CLI, and all agentskills.io-compatible agents.

Install
npx -y skills add AceDataCloud/Skills --skill instagram

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

2 things to look at

  • no licenseNo license file was found in the repository. Code published without one is not open source by default, so using it at work is a question for whoever answers licensing questions where you are.
  • 13 stars13 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.

What its author says it does

Copied from the file, not written here

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 / 轮播发布。

The file declares its own license as Apache-2.0. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

6.1 KB, as published. Nobody here has run it

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.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.