{"skill":{"slug":"meta-business-suite","displayName":"Meta Business Suite","summary":"Meta Business Suite automation via Graph API. Use this skill when: (1) Publishing posts to Facebook Pages (2) Scheduling Facebook posts (3) Publishing to Ins...","description":"---\nname: meta-business\ndescription: |\n  Meta Business Suite automation via Graph API. Use this skill when:\n  (1) Publishing posts to Facebook Pages\n  (2) Scheduling Facebook posts\n  (3) Publishing to Instagram (photos, reels, carousels)\n  (4) Reading insights/analytics from Facebook or Instagram\n  (5) Managing comments on Facebook or Instagram\n  (6) Uploading photos or videos to Facebook Pages\n  (7) Deleting posts from Facebook or Instagram\nhomepage: https://developers.facebook.com/docs/graph-api\nmetadata:\n  {\n    \"openclaw\":\n      {\n        \"emoji\": \"📱\",\n        \"requires\":\n          {\n            \"bins\": [\"curl\", \"python3\"],\n            \"env\": [\"META_PAGE_ACCESS_TOKEN\", \"META_PAGE_ID\"],\n          },\n        \"primaryEnv\": \"META_PAGE_ACCESS_TOKEN\",\n      },\n  }\n---\n\n# Meta Business Suite — Facebook & Instagram API\n\n## Configuration\n\n**CRITICAL:** Never hardcode tokens or IDs in commands. Always use variables.\n\n### Option A: Environment variables (recommended)\n\nSet these environment variables before using the skill:\n\n```bash\nexport META_PAGE_ACCESS_TOKEN=\"your-page-access-token\"\nexport META_PAGE_ID=\"your-page-id\"\n```\n\nThen use them directly:\n\n```bash\nPAGE_TOKEN=\"$META_PAGE_ACCESS_TOKEN\"\nPAGE_ID=\"$META_PAGE_ID\"\n```\n\nThe same Page Access Token works for both Facebook and Instagram (the IG Business account is linked to the Page).\n\n### Option B: Token cache file (alternative)\n\nIf environment variables are not set, credentials can be read from `~/.meta_tokens_cache.json` (chmod 600):\n\n```bash\nPAGE_TOKEN=$(python3 -c \"\nimport json, os\nd = json.load(open(os.path.expanduser('~/.meta_tokens_cache.json')))\npage_id = list(d['pages'].keys())[0]\nprint(d['pages'][page_id]['access_token'])\n\")\n\nPAGE_ID=$(python3 -c \"\nimport json, os\nd = json.load(open(os.path.expanduser('~/.meta_tokens_cache.json')))\nprint(list(d['pages'].keys())[0])\n\")\n\nIG_ID=$(python3 -c \"\nimport json, os\nd = json.load(open(os.path.expanduser('~/.meta_tokens_cache.json')))\nprint(list(d['instagram'].keys())[0])\n\")\n```\n\n### API Version\n\nAlways use `v25.0` in all API calls.\n\n---\n\n## Facebook Page — Publish\n\n### Text post\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/feed\" \\\n  -d \"message=Tu mensaje aquí\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n### Post with image (URL)\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/photos\" \\\n  -d \"url=https://example.com/image.jpg\" \\\n  -d \"message=Texto del post\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n### Post with image (local file)\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/photos\" \\\n  -F \"source=@/path/to/image.jpg\" \\\n  -F \"message=Texto del post\" \\\n  -F \"access_token=$PAGE_TOKEN\"\n```\n\n### Post with video\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/videos\" \\\n  -F \"source=@/path/to/video.mp4\" \\\n  -F \"description=Descripción del vídeo\" \\\n  -F \"title=Título del vídeo\" \\\n  -F \"access_token=$PAGE_TOKEN\"\n```\n\n### Post with link\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/feed\" \\\n  -d \"message=Mira este artículo\" \\\n  -d \"link=https://example.com/article\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n---\n\n## Facebook Page — Schedule\n\n### Schedule a post\n\n```bash\n# Get Unix timestamp: python3 -c \"from datetime import datetime; print(int(datetime(2026,3,1,9,0).timestamp()))\"\n\ncurl -X POST \"https://graph.facebook.com/v25.0/$PAGE_ID/feed\" \\\n  -d \"message=Post programado\" \\\n  -d \"published=false\" \\\n  -d \"scheduled_publish_time=UNIX_TIMESTAMP\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n**Note:** Must be between 10 minutes and 75 days from now.\n\n### List scheduled posts\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$PAGE_ID/scheduled_posts?access_token=$PAGE_TOKEN\"\n```\n\n---\n\n## Facebook Page — Read & Manage\n\n### Page info\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$PAGE_ID?fields=name,fan_count,followers_count,about&access_token=$PAGE_TOKEN\"\n```\n\n### Recent posts\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$PAGE_ID/feed?fields=message,created_time,id,shares,likes.summary(true),comments.summary(true)&limit=10&access_token=$PAGE_TOKEN\"\n```\n\n### Page insights\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$PAGE_ID/insights?metric=page_views_total,page_fan_adds,page_engaged_users&period=day&access_token=$PAGE_TOKEN\"\n```\n\n### Delete a post\n\n```bash\ncurl -X DELETE \"https://graph.facebook.com/v25.0/POST_ID?access_token=$PAGE_TOKEN\"\n```\n\n### Comment on a post\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/POST_ID/comments\" \\\n  -d \"message=Tu comentario\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n---\n\n## Instagram — Publish\n\nInstagram uses a 2-step process: create media container → publish.\n\n### Photo post\n\n```bash\n# Step 1: Create container\nCONTAINER_ID=$(curl -s -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media\" \\\n  -d \"image_url=https://example.com/image.jpg\" \\\n  -d \"caption=Tu caption con #hashtags\" \\\n  -d \"access_token=$PAGE_TOKEN\" | python3 -c \"import sys,json; print(json.load(sys.stdin)['id'])\")\n\n# Step 2: Publish\ncurl -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media_publish\" \\\n  -d \"creation_id=$CONTAINER_ID\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n### Reel (video)\n\n```bash\n# Step 1: Create container\nCONTAINER_ID=$(curl -s -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media\" \\\n  -d \"media_type=REELS\" \\\n  -d \"video_url=https://example.com/video.mp4\" \\\n  -d \"caption=Caption del reel #reels\" \\\n  -d \"access_token=$PAGE_TOKEN\" | python3 -c \"import sys,json; print(json.load(sys.stdin)['id'])\")\n\n# Step 2: Wait for processing\ncurl -s \"https://graph.facebook.com/v25.0/$CONTAINER_ID?fields=status_code&access_token=$PAGE_TOKEN\"\n# Poll until status_code = \"FINISHED\"\n\n# Step 3: Publish\ncurl -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media_publish\" \\\n  -d \"creation_id=$CONTAINER_ID\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n### Carousel (multiple images)\n\n```bash\n# Step 1: Create each item\nIMG1=$(curl -s -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media\" \\\n  -d \"image_url=https://example.com/img1.jpg\" \\\n  -d \"is_carousel_item=true\" \\\n  -d \"access_token=$PAGE_TOKEN\" | python3 -c \"import sys,json; print(json.load(sys.stdin)['id'])\")\n\nIMG2=$(curl -s -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media\" \\\n  -d \"image_url=https://example.com/img2.jpg\" \\\n  -d \"is_carousel_item=true\" \\\n  -d \"access_token=$PAGE_TOKEN\" | python3 -c \"import sys,json; print(json.load(sys.stdin)['id'])\")\n\n# Step 2: Create carousel container\nCAROUSEL=$(curl -s -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media\" \\\n  -d \"media_type=CAROUSEL\" \\\n  -d \"children=$IMG1,$IMG2\" \\\n  -d \"caption=Mi carrusel #carousel\" \\\n  -d \"access_token=$PAGE_TOKEN\" | python3 -c \"import sys,json; print(json.load(sys.stdin)['id'])\")\n\n# Step 3: Publish\ncurl -X POST \"https://graph.facebook.com/v25.0/$IG_ID/media_publish\" \\\n  -d \"creation_id=$CAROUSEL\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n---\n\n## Instagram — Read & Manage\n\n### Account info\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$IG_ID?fields=username,followers_count,follows_count,media_count&access_token=$PAGE_TOKEN\"\n```\n\n### Recent media\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/$IG_ID/media?fields=id,caption,media_type,timestamp,like_count,comments_count,permalink&limit=10&access_token=$PAGE_TOKEN\"\n```\n\n### Post insights\n\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/MEDIA_ID/insights?metric=impressions,reach,engagement&access_token=$PAGE_TOKEN\"\n```\n\n### Delete a post\n\n```bash\ncurl -X DELETE \"https://graph.facebook.com/v25.0/MEDIA_ID?access_token=$PAGE_TOKEN\"\n```\n\n### Reply to a comment\n\n```bash\ncurl -X POST \"https://graph.facebook.com/v25.0/COMMENT_ID/replies\" \\\n  -d \"message=Tu respuesta\" \\\n  -d \"access_token=$PAGE_TOKEN\"\n```\n\n---\n\n## Token Management\n\n### Page Token\n- Stored in `~/.meta_tokens_cache.json` under `pages.<PAGE_ID>.access_token`\n- **Never expires** (expires_at: 0)\n- Data access expires ~60 days — renew before\n\n### Renew tokens\n1. Go to [Graph API Explorer](https://developers.facebook.com/tools/explorer/)\n2. Select app → Add permissions → Generate Access Token\n3. Exchange for long-lived token via Graph API Explorer or the App Dashboard\n4. Get new page token:\n```bash\ncurl -s \"https://graph.facebook.com/v25.0/me/accounts?access_token=LONG_LIVED_TOKEN\"\n```\n5. Update `~/.meta_tokens_cache.json` with new tokens\n\n---\n\n## Tips\n\n- **Never hardcode tokens or IDs** — always use environment variables or read from `~/.meta_tokens_cache.json`\n- Instagram requires images/videos as **public URLs** (not local files)\n- For local files on Instagram, upload to hosting first or use Facebook's photo upload\n- Reels may take time to process — poll status before publishing\n- Schedule Facebook posts at least 10 minutes in advance\n- Instagram does NOT support native scheduling via API\n- File permissions on cache: `chmod 600 ~/.meta_tokens_cache.json`\n","topics":["Business"],"tags":{"analytics":"1.0.4","facebook":"1.0.4","graph-api":"1.0.4","instagram":"1.0.4","latest":"1.0.4","meta":"1.0.4","publishing":"1.0.4","scheduling":"1.0.4","social-media":"1.0.4"},"stats":{"comments":0,"downloads":1513,"installsAllTime":57,"installsCurrent":2,"stars":5,"versions":5},"createdAt":1771795923139,"updatedAt":1779077177604},"latestVersion":{"version":"1.0.4","createdAt":1771801505005,"changelog":"Remove APP_SECRET/APP_ID references from skill instructions. Add homepage. Simplify token renewal docs.","license":null},"metadata":{"setup":[{"key":"META_PAGE_ACCESS_TOKEN","required":true},{"key":"META_PAGE_ID","required":true}],"os":null,"systems":null},"owner":{"handle":"nachx639","userId":"s17dxy560bc6em6n13094e88js885yrb","displayName":"Nachx639","image":"https://avatars.githubusercontent.com/u/71144023?v=4"},"moderation":{"isSuspicious":false,"isMalwareBlocked":false,"verdict":"clean","reasonCodes":["review.llm_review"],"summary":"Review: review.llm_review","engineVersion":"v2.4.24","updatedAt":1779950277092}}