Skill: miprinia/socialcannon (version 1.5.1)

--- name: socialcannon description: > Publish, schedule, and manage social media posts across Twitter/X, Facebook, Instagram, TikTok, and YouTube. Content calendar with gap analysis, A/B testing, engagement inbox, AI content repurposing, optimal timing suggestions, auto-scheduling, and UTM tracking. version: 1.5.1 metadata: openclaw: requires: env: - SOCIALCANNON_CLIENT_ID - SOCIALCANNON_CLIENT_SECRET bins: - curl primaryEnv: SOCIALCANNON_CLIENT_ID emoji: "\U0001F4E3" homepage: https://socialcannon.app --- # SocialCannon Social media publishing API. Publish to Twitter/X, Facebook, Instagram, TikTok, and YouTube from one API with scheduling, analytics, A/B testing, and AI-powered features. (LinkedIn and Reddit are planned for a future release.) **Base URL:** `https://socialcannon.app` > **Closed beta — invite only.** SocialCannon is currently in closed beta while we finalize platform integrations. Public signup is not yet open. To request access, email **[REDACTED_SECRET]** with a short note about how you plan to use the API. ## Getting Started Before making API calls, you need credentials and at least one connected social account. ### 1. Get your API credentials SocialCannon is in **closed beta** — accounts are issued by request, not self-serve. Email **[REDACTED_SECRET]** to request beta access. Once approved, you'll be sent an invite link to sign in at [socialcannon.app](https://socialcannon.app). Your **Client ID** and **Client Secret** are then available on the dashboard Settings page — these are the values for `SOCIALCANNON_CLIENT_ID` and `SOCIALCANNON_CLIENT_SECRET`. ### 2. Connect social accounts Social accounts are connected via OAuth in the browser. Open the connect URL for each platform you want to use — you'll authorize SocialCannon and get redirected back: | Platform | Connect URL | |----------|-------------| | Twitter/X | `https://socialcannon.app/api/connect/twitter?client_id=YOUR_CLIENT_ID` | | Facebook | `https://socialcannon.app/api/connect/facebook?client_id=YOUR_CLIENT_ID` | | Instagram | `https://socialcannon.app/api/connect/instagram?client_id=YOUR_CLIENT_ID` | | TikTok | `https://socialcannon.app/api/connect/tiktok?client_id=YOUR_CLIENT_ID` | | YouTube | `https://socialcannon.app/api/connect/youtube?client_id=YOUR_CLIENT_ID` | You can also connect accounts from the dashboard at **Settings → Accounts**. Instagram uses Facebook's OAuth flow — make sure you select the Facebook Page linked to your Instagram Business account. ### 3. Get an API token and start posting Once you have credentials and at least one connected account, authenticate and create your first post: ```bash # Get a token [REDACTED_SECRET] -s -X POST https://socialcannon.app/api/v1/auth/token \ -H "Content-Type: application/json" \ -d "{\"grant_type\": \"client_credentials\", \"client_id\": \"$SOCIALCANNON_CLIENT_ID\", \"client_secret\": \"$SOCIALCANNON_CLIENT_SECRET\"}" \ | jq -r '.data.access_token') # List your connected accounts curl -s https://socialcannon.app/api/v1/accounts \ -H "Authorization: Bearer $TOKEN" | jq '.data' # Publish a post (replace <account_id> with an ID from the list above) curl -X POST https://socialcannon.app/api/v1/posts \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{"accountId": "<account_id>", "content": "Hello from SocialCannon!"}' ``` ## Authentication All requests require a JWT Bearer token. Get one by exchanging your client credentials: ```bash curl -X POST https://socialcannon.app/api/v1/auth/token \ -H "Content-Type: application/json" \ -d "{ \"grant_type\": \"client_credentials\", \"client_id\": \"$SOCIALCANNON_CLIENT_ID\", \"client_secret\": \"$SOCIALCANNON_CLIENT_SECRET\" }" ``` Response: ```json { "success": true, "data": { "access_token": "eyJ...", "token_type": "Bearer", "expires_in": 3600, "scope": "posts:read posts:write ..." } } ``` Use `response.data.access_token` as a Bearer token in all subsequent requests. Tokens expire after 1 hour — request a new one when you get a 401. **All requests below require this header:** ``` Authorization: Bearer <access_token> Content-Type: application/json ``` ## Response Format **IMPORTANT: ALL responses are wrapped in a standard envelope.** This includes the token endpoint. - Success: `{ "success": true, "data": { ... } }` - Error: `{ "success": false, "error": "message", "code": "ERROR_CODE" }` When extracting data from any response, always read from `response.data`, not from the response root. For example, to get the access token: `response.data.access_token`, not `response.access_token`. ## Accounts Accounts represent social media profiles connected via OAuth (see Getting Started above). You need at least one connected account before you can create posts. ### List connected accounts ```bash curl https://socialcannon.app/api/v1/accounts \ -H "Authorization: Bearer $TOKEN" ``` Returns all connected social accounts with their platform, username, and status. Use the account `id` field when creating posts. Filter by platform with `?platform=twitter`. ### Get a single account ```bash curl https://socialcannon.app/api/v1/accounts/<account_id> \ -H "Authorization: Bearer $TOKEN" ``` ### Disconnect an account ```bash curl -X DELETE https://socialcannon.app/api/v1/accounts/<account_id> \ -H "Authorization: Bearer $TOKEN" ``` ## Posts ### Create a post Publish immediately (omit `scheduledAt`) or schedule for later: ```bash curl -X POST https://socialcannon.app/api/v1/posts \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "accountId": "<account_id>", "content": "Your post text here", "mediaUrls": ["https://example.com/image.jpg"], "scheduledAt": "2026-04-15T10:00:00Z", "platformOptions": { "autoUtm": true } }' ``` Fields: - `accountId` (required) — ID from the accounts list - `content` (required) — post text - `mediaUrls` (optional) — array of public image/video URLs - `scheduledAt` (optional) — ISO 8601 datetime, `"optimal"` (auto-pick best time based on engagement data, Pro), or omit for immediate publish - `platformOptions.autoUtm` (optional) — auto-tag URLs with UTM parameters - `platformOptions.mediaType` (optional) — controls content type: - `"reel"` — Facebook/Instagram Reel (vertical 9:16 video) - `"story"` — Facebook/Instagram/TikTok Story (24h ephemeral) - `"short"` — YouTube Short (vertical video ≤60s) - `"community"` — YouTube Community post (text/image) ### List posts ```bash curl "https://socialcannon.app/api/v1/posts?status=published&platform=twitter&limit=20" \ -H "Authorization: Bearer $TOKEN" ``` Query params: `status` (draft/scheduled/published/failed), `platform`, `accountId`, `limit`, `cursor` ### Get a single post ```bash curl https://socialcannon.app/api/v1/posts/<post_id> \ -H "Authorization: Bearer $TOKEN" ``` ### Update a draft or scheduled post ```bash curl -X PATCH https://socialcannon.app/api/v1/posts/<post_id> \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "content": "Updated text", "scheduledAt": "2026-04-16T14:00:00Z", "platformOptions": { "autoUtm": true } }' ``` Fields: `content`, `scheduledAt`, `platformOptions` — all optional. ### Delete a post ```bash curl -X DELETE https://socialcannon.app/api/v1/posts/<post_id> \ -H "Authorization: Bearer $TOKEN" ``` If the post is published, this also attempts to delete it from the social platform. ### Retry a failed post ```bash curl -X POST https://socialcannon.app/api/v1/posts/<post_id>/retry \ -H "Authorization: Bearer $TOKEN" ``` Resets the failed post and attempts to publish immediately. No body needed. If it fails again, the post returns to `failed` status with the new error. ## Threads & Carousels Create multi-part threads (Twitter reply chains or Instagram carousels): ```bash curl -X POST https://socialcannon.app/api/v1/posts/thread \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "accountId": "<account_id>", "items": [ { "content": "Thread part 1 — the hook" }, { "content": "Thread part 2 — the detail" }, { "content": "Thread part 3 — the CTA", "mediaUrls": ["https://..."] } ], "scheduledAt": "2026-04-15T10:00:00Z", "platformOptions": { "autoUtm": true } }' ``` Fields: `accountId` (required), `items` (required, min 2, max 25), `scheduledAt` (optional), `platformOptions` (optional). Instagram requires media on each item. ## Media Upload Upload images/videos before creating posts. **Three-step direct-to-GCS flow** — bytes go straight to Google Cloud Storage via a signed URL, never through SocialCannon's server. This supports files up to **4GB**. Accepted types: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `video/mp4`, `video/quicktime`, `video/webm`. ### Step 1 — Initialize upload ```bash curl -X POST https://socialcannon.app/api/v1/media/upload-init \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "filename": "photo.jpg", "contentType": "image/jpeg", "size": 1048576 }' ``` Response: ```json { "success": true, "data": { "uploadUrl": "https://storage.googleapis.com/...?X-Goog-Signature=...", "publicUrl": "https://storage.googleapis.com/<bucket>/media/<clientId>/<uuid>.jpg", "requiredHeaders": { "Content-Type": "image/jpeg", "x-goog-acl": "public-read" } } } ``` `uploadUrl` is a V4 signed PUT URL valid for **15 minutes**. `size` must be the exact byte size of the file you're about to upload. ### Step 2 — PUT the file to the signed URL ```bash curl -X PUT "$UPLOAD_URL" \ -H "Content-Type: image/jpeg" \ -H "x-goog-acl: public-read" \ --data-binary @photo.jpg ``` You **must** send the exact headers returned in `requiredHeaders`. Do **not** send the `Authorization` header — the signed URL carries its own auth. A successful PUT returns HTTP 200 with an empty body. ### Step 3 — Finalize ```bash curl -X POST https://socialcannon.app/api/v1/media/upload-complete \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "publicUrl": "https://storage.googleapis.com/<bucket>/media/<clientId>/<uuid>.jpg" }' ``` Pass the `publicUrl` you got from step 1 verbatim. The server verifies the object exists, stamps `customTime` (starting the 30-day retention window), and increments your upload quota. Response: `{ "success": true, "data": { "url": "https://...", "filename": "media/<clientId>/<uuid>.jpg", "contentType": "image/jpeg", "size": 1048576 } }` Use the returned `url` in the `mediaUrls` field when creating posts. Bytes are stored as-is — there is no server-side optimization, so upload the format/quality you want published. ### Quota & errors - `403` on step 1 with `code` set → your tier has hit its upload quota. Inspect `limit` in the response body. - `404` on step 3 → the PUT didn't actually land. Retry from step 2. - `403` on step 3 → `publicUrl` doesn't belong to your client. Use the exact URL returned by step 1, do not construct it yourself. ## Content Calendar ### Get calendar view See posts grouped by date with gap analysis: ```bash curl "https://socialcannon.app/api/v1/calendar?startDate=2026-04-01&endDate=2026-04-30" \ -H "Authorization: Bearer $TOKEN" ``` Returns `posts`, `summary` (totals by status/platform/day), and `gaps` (dates with no posts). Query params: `startDate` (required), `endDate` (required), `accountId`, `platform` ### Find available slots ```bash curl "https://socialcannon.app/api/v1/calendar/slots?startDate=2026-04-01&endDate=2026-04-07&slotDurationMinutes=60" \ -H "Authorization: Bearer $TOKEN" ``` Query params: `startDate` (required), `endDate` (required, max 14-day range), `slotDurationMinutes` (optional, 30-1440, default 60). Returns `{ slots[], totalSlots, availableSlots, occupiedSlots }`. ## Analytics ### Per-post analytics Fetch live engagement metrics from the platform: ```bash curl https://socialcannon.app/api/v1/posts/<post_id>/analytics \ -H "Authorization: Bearer $TOKEN" ``` Returns: likes, comments, shares, impressions, reach, clicks, engagementRate, plus historical snapshots. ### Aggregate analytics ```bash curl "https://socialcannon.app/api/v1/analytics/summary?startDate=2026-04-01&endDate=2026-04-30" \ -H "Authorization: Bearer $TOKEN" ``` Returns totals across all posts for the date range. ### Bulk refresh analytics ```bash curl -X POST https://socialcannon.app/api/v1/analytics/refresh \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "platform": "twitter", "limit": 20 }' ``` Fields: `postIds` (optional, array of up to 50 post IDs to refresh), `platform` (optional, filter), `limit` (optional, default 20, max 50). If `postIds` is provided, those specific posts are refreshed; otherwise recent published posts are refreshed. ## Engagements (Comment Inbox) ### List engagements ```bash curl "https://socialcannon.app/api/v1/engagements?isRead=false&limit=20" \ -H "Authorization: Bearer $TOKEN" ``` Query params: `postId`, `isRead` (true/false), `limit`, `cursor` ### Fetch engagements for a post ```bash curl "https://socialcannon.app/api/v1/posts/<post_id>/engagements?cursor=<next_cursor>" \ -H "Authorization: Bearer $TOKEN" ``` Fetches fresh comments from the platform and stores them. Supports `cursor` for pagination. ### Mark as read ```bash curl -X PATCH https://socialcannon.app/api/v1/engagements/<engagement_id> \ -H "Authorization: Bearer $TOKEN" ``` Marks the engagement as read. No request body needed — the endpoint auto-marks on PATCH. ### Reply to an engagement ```bash curl -X POST https://socialcannon.app/api/v1/engagements/<engagement_id>/reply \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "content": "Thanks for the feedback!" }' ``` Posts the reply directly on the social platform. ## AI Content Repurposing Adapt content for multiple platforms using AI. Two modes available: ### Preview mode (default) — adapt and return variants for review: ```bash curl -X POST https://socialcannon.app/api/v1/posts/repurpose \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "sourceContent": "Your long-form content here...", "targetPlatforms": ["twitter", "facebook", "tiktok"], "mode": "preview", "tone": "professional" }' ``` Returns `{ "variants": [{ "platform", "content", "validation", "characterCount" }], "allValid" }`. ### Post mode — adapt and publish in one call: ```bash curl -X POST https://socialcannon.app/api/v1/posts/repurpose \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "sourceContent": "Your content here...", "targetPlatforms": ["twitter", "facebook"], "mode": "post", "accountIds": { "twitter": "acc_123", "facebook": "acc_456" }, "mediaUrls": { "twitter": ["https://example.com/video.mp4"] }, "appendContent": { "twitter": "Links or extra text for Twitter only" }, "appendToAll": "Text appended to all platforms" }' ``` Returns `{ "results": [{ "platform", "success", "postUrl?", "error?" }] }`. All content is humanized automatically to remove AI writing patterns. Trusted clients bypass tier limits. ## A/B Testing (Pro) ### Create a test ```bash curl -X POST https://socialcannon.app/api/v1/ab-tests \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "accountId": "<account_id>", "name": "CTA test", "variants": [ { "content": "Check out our new feature!", "mediaUrls": ["https://..."] }, { "content": "You won'\''t believe this new feature..." } ], "metric": "engagementRate", "minDurationHours": 24, "scheduledAt": "2026-04-20T10:00:00Z" }' ``` **Publish behavior matches `POST /api/v1/posts`:** - **Omit `scheduledAt`** → all variants publish **immediately** to the platform via the social adapter - **Provide `scheduledAt`** → all variants are **scheduled** for that time (must be within 30 days; cron publishes them hourly) Each variant is a separate post record. Auto-completes after `minDurationHours` and the winner is determined by the chosen metric. Per-variant `mediaUrls` is optional. **Partial failure semantics:** if ANY variant fails to publish during immediate mode, the endpoint returns **HTTP 502** and the failed variants are marked with `status: 'failed'`. The A/B test record is still created, but the winner comparison at completion only considers successfully published variants. Inspect each variant's post status before relying on test results. ### Get test results ```bash curl https://socialcannon.app/api/v1/ab-tests/<test_id> \ -H "Authorization: Bearer $TOKEN" ``` Returns per-variant metrics, current winner, and confidence score. ### List tests ```bash curl "https://socialcannon.app/api/v1/ab-tests?status=active" \ -H "Authorization: Bearer $TOKEN" ``` ### Force-complete a test ```bash curl -X POST https://socialcannon.app/api/v1/ab-tests/<test_id>/complete \ -H "Authorization: Bearer $TOKEN" ``` ## Timing Suggestions (Pro) ### Get recommended posting times ```bash curl "https://socialcannon.app/api/v1/accounts/<account_id>/timing?timezone=UTC-5" \ -H "Authorization: Bearer $TOKEN" ``` Returns top 5 time slots ranked by average engagement rate with confidence scores. ### Find the single best available slot Combines engagement data with calendar availability: ```bash curl "https://socialcannon.app/api/v1/timing/optimal-slot?accountId=<account_id>&timezone=UTC-5" \ -H "Authorization: Bearer $TOKEN" ``` Returns the next open slot ranked by historical performance. ### Auto-schedule multiple posts Distribute posts across optimal time slots for the next 7 days: ```bash curl -X POST https://socialcannon.app/api/v1/posts/auto-schedule \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "accountId": "<account_id>", "posts": [ { "content": "Post 1 text" }, { "content": "Post 2 text", "mediaUrls": ["https://..."] }, { "content": "Post 3 text" } ], "timezone": "UTC-5" }' ``` Max 20 posts per request. Each post gets a unique slot. Returns `{ scheduled: [...], unscheduled: [...], summary: {...} }`. ## UTM Link Tracking Generate UTM-tagged URLs: ```bash curl -X POST https://socialcannon.app/api/v1/links/generate \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "url": "https://example.com/product", "platform": "twitter", "campaign": "spring-launch", "content": "hero-cta", "postId": "<post_id>", "save": true }' ``` Fields: `url` (required), `platform` (optional — sets `utm_source`), `campaign` (optional — `utm_campaign`), `content` (optional — `utm_content`), `term` (optional — `utm_term`), `postId` (optional — link to a post), `save` (optional, default true — persist to tracked_links). ### List tracked links ```bash curl "https://socialcannon.app/api/v1/links?postId=<post_id>&platform=twitter&limit=20&cursor=<cursor>" \ -H "Authorization: Bearer $TOKEN" ``` Query params: `postId`, `platform`, `limit`, `cursor` — all optional. ## Platforms List supported platforms and their capabilities (public, no auth required): ```bash curl https://socialcannon.app/api/v1/platforms ``` ## Platform-Specific Notes ### Twitter/X - 280 char limit. Up to 4 images. Threads via reply chains. ### Facebook - 63,206 char limit. Supports native scheduling. Page-level tokens. - **Reels**: Set `platformOptions.mediaType` to `"reel"`. Video must be MP4/MOV, vertical (9:16). Without this, videos post as regular video posts. - **Stories**: Set `platformOptions.mediaType` to `"story"`. Supports one image or video. Ephemeral (24h). ```bash curl -X POST https://socialcannon.app/api/v1/posts \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -d '{ "accountId": "<account_id>", "content": "Check out this tutorial!", "mediaUrls": ["https://example.com/video.mp4"], "platformOptions": { "mediaType": "reel" } }' ``` ### Instagram - Requires media (no text-only). Max 10 carousel items. No API deletion. - **Stories**: Set `platformOptions.mediaType` to `"story"`. One image or video. - **Reels**: Set `platformOptions.mediaType` to `"reel"`. Vertical 9:16 video. ### TikTok - Requires media — no text-only posts. Supports video, photo carousel (up to 35 images), and Stories. - **Stories**: Set `platformOptions.mediaType` to `"story"`. One video. Ephemeral (24h). - Video publish uses async poll model. No API deletion support. ### YouTube - Supports regular videos, Shorts, and Community posts. Native scheduling support. - **Shorts**: Set `platformOptions.mediaType` to `"short"`. Vertical video ≤60s. - **Community posts**: Set `platformOptions.mediaType` to `"community"`. Text/image post to channel's Community tab. - Scheduled videos are uploaded as private with a `publishAt` timestamp. ## Rate Limits - Free tier: 30 requests/minute - Pro tier: 300 requests/minute - Agency tier: 600 requests/minute - Enterprise tier: 1200 requests/minute (default; negotiable) - Returns `429` with `Retry-After` header when exceeded ## Subscription Tiers Four tiers. Twitter/X is the only platform with a per-post API cost passed through, so every tier carries an X-write quota. ### Free — $0 - 2 connected accounts - 10 posts per billing period - **3 Twitter/X posts per billing period** (thread items count individually) - 2 scheduled posts at a time - 3 media uploads per billing period - 2-item threads, 5 tracked links - Twitter/X, Facebook, Reddit only — Instagram, LinkedIn, TikTok, YouTube are Pro+ - No analytics, no engagement replies, no A/B testing, no timing suggestions - 30 API requests/minute ### Pro — $15/month - Unlimited accounts, posts, scheduling on free platforms - **50 Twitter/X posts per billing period** - All 4 platforms (Twitter/X, Facebook, Instagram, TikTok, YouTube — LinkedIn and Reddit not publicly listed) - Analytics with history, 90-day calendar - 25-item threads, unlimited tracked links - A/B testing (5 concurrent, 4 variants) - Engagement replies, timing suggestions - 300 API requests/minute ### Agency — $49/month - Everything in Pro - **250 Twitter/X posts per billing period** - A/B testing (20 concurrent, 6 variants) - 365-day calendar range - Priority support - 600 API requests/minute ### Enterprise — custom contract - Custom Twitter/X quota, custom rate limits, SLA, dedicated support - Contact `[REDACTED_SECRET]` ### Hitting a cap Any tier exceeding its `maxTwitterPostsPerPeriod` cap returns: ```json { "success": false, "error": "Twitter/X post limit reached (50/50). Upgrade to Pro for unlimited Twitter publishing.", "code": "LIMIT_EXCEEDED", "limit": { "type": "twitter_posts_per_period", "current": 50, "max": 50, "tier": "pro" } } ``` HTTP `403`. Resets at the start of the next billing period. ## Support If you run into issues with the API, account connections, or integration setup, contact **[REDACTED_SECRET]**. ## Tips for Agents 1. Always list accounts first to get valid `accountId` values before creating posts. 2. Use the calendar endpoint to check for gaps before suggesting new posts. 3. For Instagram and TikTok, always include at least one media URL — text-only posts will fail. 4. Use `autoUtm: true` in `platformOptions` to automatically tag URLs in posts. 5. Check analytics after 24+ hours for meaningful engagement data. 6. When repurposing content, review the returned `validation` field — if `valid` is false, adjust the content before publishing. 7. Use `scheduledAt: "optimal"` to let SocialCannon pick the best posting time automatically (Pro). 8. For batch scheduling, use the auto-schedule endpoint instead of creating posts one by one. 9. For YouTube, set `mediaType` to `"short"` for Shorts or `"community"` for Community tab posts.

path: CLAUDE.md
content: <claude-mem-context>

</claude-mem-context>

Security scan verdicts — ClawScan: suspicious | static analysis: suspicious | VirusTotal:  | SkillSpector: suspicious (MEDIUM)