{
  "schemaVersion": "1.0",
  "item": {
    "slug": "facebook-page",
    "name": "Facebook Page",
    "source": "tencent",
    "type": "skill",
    "category": "通讯协作",
    "sourceUrl": "https://clawhub.ai/seph1709/facebook-page",
    "canonicalUrl": "https://clawhub.ai/seph1709/facebook-page",
    "targetPlatform": "OpenClaw"
  },
  "install": {
    "downloadMode": "redirect",
    "downloadUrl": "/downloads/facebook-page",
    "sourceDownloadUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=facebook-page",
    "sourcePlatform": "tencent",
    "targetPlatform": "OpenClaw",
    "installMethod": "Manual import",
    "extraction": "Extract archive",
    "prerequisites": [
      "OpenClaw"
    ],
    "packageFormat": "ZIP package",
    "includedAssets": [
      "README.md",
      "SKILL.md",
      "_meta.json"
    ],
    "primaryDoc": "SKILL.md",
    "quickSetup": [
      "Download the package from Yavira.",
      "Extract the archive and review SKILL.md first.",
      "Import or place the package into your OpenClaw setup."
    ],
    "agentAssist": {
      "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
      "steps": [
        "Download the package from Yavira.",
        "Extract it into a folder your agent can access.",
        "Paste one of the prompts below and point your agent at the extracted folder."
      ],
      "prompts": [
        {
          "label": "New install",
          "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
        },
        {
          "label": "Upgrade existing",
          "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
        }
      ]
    },
    "sourceHealth": {
      "source": "tencent",
      "status": "healthy",
      "reason": "direct_download_ok",
      "recommendedAction": "download",
      "checkedAt": "2026-04-23T16:43:11.935Z",
      "expiresAt": "2026-04-30T16:43:11.935Z",
      "httpStatus": 200,
      "finalUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
      "contentType": "application/zip",
      "probeMethod": "head",
      "details": {
        "probeUrl": "https://wry-manatee-359.convex.site/api/v1/download?slug=4claw-imageboard",
        "contentDisposition": "attachment; filename=\"4claw-imageboard-1.0.1.zip\"",
        "redirectLocation": null,
        "bodySnippet": null
      },
      "scope": "source",
      "summary": "Source download looks usable.",
      "detail": "Yavira can redirect you to the upstream package for this source.",
      "primaryActionLabel": "Download for OpenClaw",
      "primaryActionHref": "/downloads/facebook-page"
    },
    "validation": {
      "installChecklist": [
        "Use the Yavira download entry.",
        "Review SKILL.md after the package is downloaded.",
        "Confirm the extracted package contains the expected setup assets."
      ],
      "postInstallChecks": [
        "Confirm the extracted package includes the expected docs or setup files.",
        "Validate the skill or prompts are available in your target agent workspace.",
        "Capture any manual follow-up steps the agent could not complete."
      ]
    },
    "downloadPageUrl": "https://openagent3.xyz/downloads/facebook-page",
    "agentPageUrl": "https://openagent3.xyz/skills/facebook-page/agent",
    "manifestUrl": "https://openagent3.xyz/skills/facebook-page/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/facebook-page/agent.md"
  },
  "agentAssist": {
    "summary": "Hand the extracted package to your coding agent with a concrete install brief instead of figuring it out manually.",
    "steps": [
      "Download the package from Yavira.",
      "Extract it into a folder your agent can access.",
      "Paste one of the prompts below and point your agent at the extracted folder."
    ],
    "prompts": [
      {
        "label": "New install",
        "body": "I downloaded a skill package from Yavira. Read SKILL.md from the extracted folder and install it by following the included instructions. Then review README.md for any prerequisites, environment setup, or post-install checks. Tell me what you changed and call out any manual steps you could not complete."
      },
      {
        "label": "Upgrade existing",
        "body": "I downloaded an updated skill package from Yavira. Read SKILL.md from the extracted folder, compare it with my current installation, and upgrade it while preserving any custom configuration unless the package docs explicitly say otherwise. Then review README.md for any prerequisites, environment setup, or post-install checks. Summarize what changed and any follow-up checks I should run."
      }
    ]
  },
  "documentation": {
    "source": "clawhub",
    "primaryDoc": "SKILL.md",
    "sections": [
      {
        "title": "facebook-page â€” Universal Meta Graph API Skill",
        "body": "Constructs and executes Meta Graph API calls inline based on what the user wants. No scripts needed.\n\nAPI version: v25.0\nBase URL: https://graph.facebook.com/v25.0"
      },
      {
        "title": "STEP 1 â€” Load Credentials",
        "body": "Credentials are stored in ~/.config/fb-page/credentials.json.\n\n$cfg    = Get-Content \"$HOME/.config/fb-page/credentials.json\" -Raw | ConvertFrom-Json\n$token  = $cfg.FB_PAGE_TOKEN\n$pageId = $cfg.FB_PAGE_ID\n\nIf the file doesn't exist, guide setup. Required fields:\n\nFieldPurposeFB_PAGE_TOKENNever-expiring Page access token â€” used for all API callsFB_PAGE_IDNumeric Facebook Page IDFB_APP_IDMeta App ID â€” only needed during token exchangeFB_APP_SECRETMeta App Secret â€” only needed during token exchange\n\nOne-time token exchange setup:\n\n# Provide: $appId, $appSecret, $shortToken (from Graph API Explorer), $pageId\n# 1. Exchange for long-lived user token\n$r1 = Invoke-RestMethod \"https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=$appId&client_secret=$appSecret&fb_exchange_token=$shortToken\"\n# 2. Get never-expiring Page token\n$r2 = Invoke-RestMethod \"https://graph.facebook.com/v25.0/$pageId?fields=access_token&access_token=$($r1.access_token)\"\n$pageToken = $r2.access_token\n# 3. Save â€” only these four fields, nothing else\n@{\n    FB_PAGE_ID    = $pageId\n    FB_PAGE_TOKEN = $pageToken\n    FB_APP_ID     = $appId\n    FB_APP_SECRET = $appSecret\n} | ConvertTo-Json | Set-Content \"$HOME/.config/fb-page/credentials.json\" -Encoding UTF8\n\nRestrict file permissions immediately after saving:\n\n# Windows\nicacls \"$HOME/.config/fb-page/credentials.json\" /inheritance:r /grant:r \"$($env:USERNAME):(R,W)\"\n# macOS / Linux\n# chmod 600 ~/.config/fb-page/credentials.json\n\nâš ï¸ Never commit this file to version control. It contains long-lived secrets.\nThis skill makes no external calls other than to graph.facebook.com. No data is forwarded to third parties."
      },
      {
        "title": "Common Endpoints",
        "body": "What user wantsMethodEndpointPost textPOST/$pageId/feed â€” body: messagePost with imagePOST/$pageId/photos â€” multipart: source + messagePost with videoPOST/$pageId/videos â€” multipart: source + descriptionPost with linkPOST/$pageId/feed â€” body: message + linkDelete a postDELETE/{post-id}Schedule a postPOST/$pageId/feed â€” body: message + published=false + scheduled_publish_time (unix timestamp)Get recent postsGET/$pageId/published_posts?fields=id,message,created_time&limit=10Get page infoGET/$pageId?fields=name,fan_count,followers_count,aboutLike a postPOST/{post-id}/likesGet commentsGET/{post-id}/comments?fields=message,from,created_timeReply to commentPOST/{comment-id}/comments â€” body: messageHide commentPOST/{comment-id} â€” body: is_hidden=trueDelete commentDELETE/{comment-id}Get page insightsGET/$pageId/insights?metric=page_fans,page_impressions&period=dayGet post insightsGET/{post-id}/insights?metric=post_impressions,post_reactions_by_type_totalList eventsGET/$pageId/events?fields=name,start_time,descriptionCreate eventPOST/$pageId/events â€” body: name, start_time, descriptionList albumsGET/$pageId/albums?fields=name,countGet page rolesGET/$pageId/rolesPublish draft postPOST/{post-id} â€” body: is_published=true"
      },
      {
        "title": "API Call Patterns",
        "body": "GET:\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/ENDPOINT?access_token=$token\" -ErrorAction Stop\n\nPOST (form body):\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/ENDPOINT\" -Method POST `\n    -Body @{ field1=\"value1\"; field2=\"value2\"; access_token=$token } -ErrorAction Stop\n\nDELETE:\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/{id}?access_token=$token\" -Method DELETE -ErrorAction Stop\n\nMultipart (image/video upload):\n\n$boundary  = [System.Guid]::NewGuid().ToString()\n$fileBytes = [System.IO.File]::ReadAllBytes($filePath)\n$fileName  = [System.IO.Path]::GetFileName($filePath)\n$stream    = New-Object System.IO.MemoryStream\n$writer    = New-Object System.IO.StreamWriter($stream)\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"message`\"`r`n`r`n$message`r`n\")\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"access_token`\"`r`n`r`n$token`r`n\")\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"source`\"; filename=`\"$fileName`\"`r`nContent-Type: image/jpeg`r`n`r`n\")\n$writer.Flush(); $stream.Write($fileBytes, 0, $fileBytes.Length)\n$writer.Write(\"`r`n--$boundary--`r`n\"); $writer.Flush()\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/$pageId/photos\" -Method POST `\n    -ContentType \"multipart/form-data; boundary=$boundary\" -Body $stream.ToArray() -ErrorAction Stop\n\nScheduled post â€” convert local time to Unix timestamp:\n\n$runAt    = [datetime]\"2026-03-15 09:00\"\n$unixTime = [int][double]::Parse(($runAt.ToUniversalTime() - [datetime]\"1970-01-01\").TotalSeconds)\n$result   = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/$pageId/feed\" -Method POST `\n    -Body @{ message=\"text\"; published=\"false\"; scheduled_publish_time=$unixTime; access_token=$token } -ErrorAction Stop"
      },
      {
        "title": "STEP 3 â€” Handle Errors",
        "body": "try {\n    # ... API call ...\n} catch {\n    $err     = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue\n    $code    = $err.error.code\n    $subcode = $err.error.error_subcode\n    $msg     = $err.error.message\n}\n\nCodeSubcodeMeaningFix100â€”Invalid parameterCheck the parameter values102â€”Session expiredRe-run setup to get a new token190460Token expiredRe-run setup with a new short-lived token190467Invalid tokenRe-run setup200â€”Permission deniedAdd the permission listed in error.message to your app10â€”Permission denied (page)Add pages_read_engagement or pages_manage_posts230â€”Requires re-authRe-run setup368â€”Temporarily blockedWait and retry; page may be rate-limited"
      },
      {
        "title": "Permissions Reference",
        "body": "PermissionRequired forpages_manage_postsCreate, delete, schedule postspages_read_engagementRead posts, likes, comments, insightspages_show_listList pages you managepages_manage_metadataUpdate page settingspages_manage_engagementModerate comments, reply to reviewspages_read_user_contentRead visitor posts and commentspages_manage_adsManage ad campaigns on the pagepages_manage_instant_articlesManage Instant Articles\n\nIf a permission is missing:\n\nGo to Meta for Developers\nSelect your app â†’ Permissions and Features\nAdd the required permission\nRegenerate token via Graph API Explorer\nRe-run setup with the new token"
      },
      {
        "title": "AGENT RULES",
        "body": "Always load credentials first. If missing or incomplete, guide setup.\nOnly use FB_PAGE_TOKEN and FB_PAGE_ID for API calls. FB_APP_ID and FB_APP_SECRET are for token exchange only.\nNever write extra fields to the credentials file (no owner IDs, conv IDs, or third-party keys).\nRemove FB_APP_SECRET from credentials.json after token exchange â€” it is not needed for API calls.\nLeast-privilege: only request the permissions your use case needs. Do not request pages_manage_ads or pages_manage_instant_articles unless explicitly needed.\nRotate FB_PAGE_TOKEN periodically via Graph API Explorer, and immediately if the host is ever compromised.\nAll API calls go to graph.facebook.com only. No external forwarding, no third-party services.\nConstruct API calls inline from user intent â€” don't look for script files.\nOn any error: parse error.code + error.error_subcode, map to the table above, tell the user exactly what to do.\nIf a permission is missing: name it, link to Meta for Developers, say to re-run setup."
      }
    ],
    "body": "facebook-page â€” Universal Meta Graph API Skill\n\nConstructs and executes Meta Graph API calls inline based on what the user wants. No scripts needed.\n\nAPI version: v25.0 Base URL: https://graph.facebook.com/v25.0\n\nSTEP 1 â€” Load Credentials\n\nCredentials are stored in ~/.config/fb-page/credentials.json.\n\n$cfg    = Get-Content \"$HOME/.config/fb-page/credentials.json\" -Raw | ConvertFrom-Json\n$token  = $cfg.FB_PAGE_TOKEN\n$pageId = $cfg.FB_PAGE_ID\n\n\nIf the file doesn't exist, guide setup. Required fields:\n\nField\tPurpose\nFB_PAGE_TOKEN\tNever-expiring Page access token â€” used for all API calls\nFB_PAGE_ID\tNumeric Facebook Page ID\nFB_APP_ID\tMeta App ID â€” only needed during token exchange\nFB_APP_SECRET\tMeta App Secret â€” only needed during token exchange\n\nOne-time token exchange setup:\n\n# Provide: $appId, $appSecret, $shortToken (from Graph API Explorer), $pageId\n# 1. Exchange for long-lived user token\n$r1 = Invoke-RestMethod \"https://graph.facebook.com/oauth/access_token?grant_type=fb_exchange_token&client_id=$appId&client_secret=$appSecret&fb_exchange_token=$shortToken\"\n# 2. Get never-expiring Page token\n$r2 = Invoke-RestMethod \"https://graph.facebook.com/v25.0/$pageId?fields=access_token&access_token=$($r1.access_token)\"\n$pageToken = $r2.access_token\n# 3. Save â€” only these four fields, nothing else\n@{\n    FB_PAGE_ID    = $pageId\n    FB_PAGE_TOKEN = $pageToken\n    FB_APP_ID     = $appId\n    FB_APP_SECRET = $appSecret\n} | ConvertTo-Json | Set-Content \"$HOME/.config/fb-page/credentials.json\" -Encoding UTF8\n\n\nRestrict file permissions immediately after saving:\n\n# Windows\nicacls \"$HOME/.config/fb-page/credentials.json\" /inheritance:r /grant:r \"$($env:USERNAME):(R,W)\"\n# macOS / Linux\n# chmod 600 ~/.config/fb-page/credentials.json\n\n\nâš ï¸ Never commit this file to version control. It contains long-lived secrets. This skill makes no external calls other than to graph.facebook.com. No data is forwarded to third parties.\n\nSTEP 2 â€” Figure Out the API Call\nCommon Endpoints\nWhat user wants\tMethod\tEndpoint\nPost text\tPOST\t/$pageId/feed â€” body: message\nPost with image\tPOST\t/$pageId/photos â€” multipart: source + message\nPost with video\tPOST\t/$pageId/videos â€” multipart: source + description\nPost with link\tPOST\t/$pageId/feed â€” body: message + link\nDelete a post\tDELETE\t/{post-id}\nSchedule a post\tPOST\t/$pageId/feed â€” body: message + published=false + scheduled_publish_time (unix timestamp)\nGet recent posts\tGET\t/$pageId/published_posts?fields=id,message,created_time&limit=10\nGet page info\tGET\t/$pageId?fields=name,fan_count,followers_count,about\nLike a post\tPOST\t/{post-id}/likes\nGet comments\tGET\t/{post-id}/comments?fields=message,from,created_time\nReply to comment\tPOST\t/{comment-id}/comments â€” body: message\nHide comment\tPOST\t/{comment-id} â€” body: is_hidden=true\nDelete comment\tDELETE\t/{comment-id}\nGet page insights\tGET\t/$pageId/insights?metric=page_fans,page_impressions&period=day\nGet post insights\tGET\t/{post-id}/insights?metric=post_impressions,post_reactions_by_type_total\nList events\tGET\t/$pageId/events?fields=name,start_time,description\nCreate event\tPOST\t/$pageId/events â€” body: name, start_time, description\nList albums\tGET\t/$pageId/albums?fields=name,count\nGet page roles\tGET\t/$pageId/roles\nPublish draft post\tPOST\t/{post-id} â€” body: is_published=true\nAPI Call Patterns\n\nGET:\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/ENDPOINT?access_token=$token\" -ErrorAction Stop\n\n\nPOST (form body):\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/ENDPOINT\" -Method POST `\n    -Body @{ field1=\"value1\"; field2=\"value2\"; access_token=$token } -ErrorAction Stop\n\n\nDELETE:\n\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/{id}?access_token=$token\" -Method DELETE -ErrorAction Stop\n\n\nMultipart (image/video upload):\n\n$boundary  = [System.Guid]::NewGuid().ToString()\n$fileBytes = [System.IO.File]::ReadAllBytes($filePath)\n$fileName  = [System.IO.Path]::GetFileName($filePath)\n$stream    = New-Object System.IO.MemoryStream\n$writer    = New-Object System.IO.StreamWriter($stream)\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"message`\"`r`n`r`n$message`r`n\")\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"access_token`\"`r`n`r`n$token`r`n\")\n$writer.Write(\"--$boundary`r`nContent-Disposition: form-data; name=`\"source`\"; filename=`\"$fileName`\"`r`nContent-Type: image/jpeg`r`n`r`n\")\n$writer.Flush(); $stream.Write($fileBytes, 0, $fileBytes.Length)\n$writer.Write(\"`r`n--$boundary--`r`n\"); $writer.Flush()\n$result = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/$pageId/photos\" -Method POST `\n    -ContentType \"multipart/form-data; boundary=$boundary\" -Body $stream.ToArray() -ErrorAction Stop\n\n\nScheduled post â€” convert local time to Unix timestamp:\n\n$runAt    = [datetime]\"2026-03-15 09:00\"\n$unixTime = [int][double]::Parse(($runAt.ToUniversalTime() - [datetime]\"1970-01-01\").TotalSeconds)\n$result   = Invoke-RestMethod -Uri \"https://graph.facebook.com/v25.0/$pageId/feed\" -Method POST `\n    -Body @{ message=\"text\"; published=\"false\"; scheduled_publish_time=$unixTime; access_token=$token } -ErrorAction Stop\n\nSTEP 3 â€” Handle Errors\ntry {\n    # ... API call ...\n} catch {\n    $err     = $_.ErrorDetails.Message | ConvertFrom-Json -ErrorAction SilentlyContinue\n    $code    = $err.error.code\n    $subcode = $err.error.error_subcode\n    $msg     = $err.error.message\n}\n\nCode\tSubcode\tMeaning\tFix\n100\tâ€”\tInvalid parameter\tCheck the parameter values\n102\tâ€”\tSession expired\tRe-run setup to get a new token\n190\t460\tToken expired\tRe-run setup with a new short-lived token\n190\t467\tInvalid token\tRe-run setup\n200\tâ€”\tPermission denied\tAdd the permission listed in error.message to your app\n10\tâ€”\tPermission denied (page)\tAdd pages_read_engagement or pages_manage_posts\n230\tâ€”\tRequires re-auth\tRe-run setup\n368\tâ€”\tTemporarily blocked\tWait and retry; page may be rate-limited\nPermissions Reference\nPermission\tRequired for\npages_manage_posts\tCreate, delete, schedule posts\npages_read_engagement\tRead posts, likes, comments, insights\npages_show_list\tList pages you manage\npages_manage_metadata\tUpdate page settings\npages_manage_engagement\tModerate comments, reply to reviews\npages_read_user_content\tRead visitor posts and comments\npages_manage_ads\tManage ad campaigns on the page\npages_manage_instant_articles\tManage Instant Articles\n\nIf a permission is missing:\n\nGo to Meta for Developers\nSelect your app â†’ Permissions and Features\nAdd the required permission\nRegenerate token via Graph API Explorer\nRe-run setup with the new token\nAGENT RULES\nAlways load credentials first. If missing or incomplete, guide setup.\nOnly use FB_PAGE_TOKEN and FB_PAGE_ID for API calls. FB_APP_ID and FB_APP_SECRET are for token exchange only.\nNever write extra fields to the credentials file (no owner IDs, conv IDs, or third-party keys).\nRemove FB_APP_SECRET from credentials.json after token exchange â€” it is not needed for API calls.\nLeast-privilege: only request the permissions your use case needs. Do not request pages_manage_ads or pages_manage_instant_articles unless explicitly needed.\nRotate FB_PAGE_TOKEN periodically via Graph API Explorer, and immediately if the host is ever compromised.\nAll API calls go to graph.facebook.com only. No external forwarding, no third-party services.\nConstruct API calls inline from user intent â€” don't look for script files.\nOn any error: parse error.code + error.error_subcode, map to the table above, tell the user exactly what to do.\nIf a permission is missing: name it, link to Meta for Developers, say to re-run setup."
  },
  "trust": {
    "sourceLabel": "tencent",
    "provenanceUrl": "https://clawhub.ai/seph1709/facebook-page",
    "publisherUrl": "https://clawhub.ai/seph1709/facebook-page",
    "owner": "seph1709",
    "version": "1.0.16",
    "license": null,
    "verificationStatus": "Indexed source record"
  },
  "links": {
    "detailUrl": "https://openagent3.xyz/skills/facebook-page",
    "downloadUrl": "https://openagent3.xyz/downloads/facebook-page",
    "agentUrl": "https://openagent3.xyz/skills/facebook-page/agent",
    "manifestUrl": "https://openagent3.xyz/skills/facebook-page/agent.json",
    "briefUrl": "https://openagent3.xyz/skills/facebook-page/agent.md"
  }
}