Skip to content
Back to SkedCast

Card snapshot

skedcast.com · 2026-10-01 08:46:14 UTC · 52f2eb52a823e0fb0d510431d8e77c76aaba3483c9e6299ea00284b985a289eb

This is a frozen copy of the agent's agent-card.json as we observed it at the timestamp above. We capture a new snapshot every time the card's content hash changes. Useful for: forensic drift analysis, verifying downstream callers see the right version, reproducing routing decisions made historically.

{
  "name": "SkedCast",
  "version": "1.0.0",
  "description": "Schedule and publish social posts, manage clients + connected accounts, and read analytics across 11 platforms, on behalf of a user.",
  "url": "https://skedcast.com",
  "documentationUrl": "https://skedcast.com/developers",
  "provider": {
    "organization": "SkedCast",
    "url": "https://skedcast.com"
  },
  "supportedInterfaces": [
    {
      "transport": "mcp-streamable-http",
      "url": "https://api.skedcast.com/mcp",
      "authentication": {
        "type": "oauth2",
        "protectedResourceMetadata": "https://api.skedcast.com/.well-known/oauth-protected-resource/mcp"
      }
    }
  ],
  "capabilities": {
    "streaming": false,
    "pushNotifications": false
  },
  "defaultInputModes": [
    "application/json"
  ],
  "defaultOutputModes": [
    "application/json"
  ],
  "availability": {
    "status": "generally-available"
  },
  "skills": [
    {
      "id": "list_scheduled_posts",
      "name": "list_scheduled_posts",
      "description": "List the workspace's posts (queue, drafts, published) newest-first, with optional status / client / platform filters and free-text search (`q`) over captions, per-platform overrides, client names and account handles."
    },
    {
      "id": "list_post_targets",
      "name": "list_post_targets",
      "description": "List individual post DESTINATIONS (one row per platform account) with optional status / client / account / platform / free-text filters and a SCHEDULE-time window \u2014 the tool for \"what publishes on this date\". Carries `total` and `totalPosts`, so a caller can tell a full page from a complete set."
    },
    {
      "id": "get_post",
      "name": "get_post",
      "description": "Get one post with its per-platform variants and fan-out targets."
    },
    {
      "id": "list_clients",
      "name": "list_clients",
      "description": "List the workspace's client groups (brands / influencers)."
    },
    {
      "id": "list_accounts",
      "name": "list_accounts",
      "description": "List connected social accounts, optionally filtered by client or platform."
    },
    {
      "id": "get_analytics_overview",
      "name": "get_analytics_overview",
      "description": "Reach / impressions / engagement plus a per-platform rollup over a date window."
    },
    {
      "id": "get_post_analytics",
      "name": "get_post_analytics",
      "description": "Per-post performance (complements get_analytics_overview): one post\u2019s lifetime per-target breakdown by postId, or a keyset page of per-post rows with filters."
    },
    {
      "id": "get_account_analytics",
      "name": "get_account_analytics",
      "description": "One channel\u2019s totals and daily series, plus the two things no other tool carries: profile-level activity (profile views, link taps, video plays) and follower demographics."
    },
    {
      "id": "list_library_assets",
      "name": "list_library_assets",
      "description": "List content-library (DAM) assets with optional kind / folder / label / client / status / search filters. Filter `status: \"transcoded\"` for assets that are actually publishable; every row also carries `status`, `publishable` and `ready`."
    },
    {
      "id": "get_capabilities",
      "name": "get_capabilities",
      "description": "The per-platform composing rulebook: caption and hashtag limits, media rules per kind (counts, formats, file-size ceiling, duration bounds, aspect ratios), post types, native-scheduling window, default cadence, first-comment support, and the `variants[].overrides` keys each platform requires or accepts. Read it before composing instead of discovering a limit by failing a publish."
    },
    {
      "id": "get_agency",
      "name": "get_agency",
      "description": "The current workspace profile \u2014 name, plan, app mode, settings, and the caller\u2019s role."
    },
    {
      "id": "list_reports",
      "name": "list_reports",
      "description": "List the workspace's saved analytics report definitions."
    },
    {
      "id": "get_best_times",
      "name": "get_best_times",
      "description": "Worker-derived best posting times (strongest-first), optionally by client / platform."
    },
    {
      "id": "list_approvals",
      "name": "list_approvals",
      "description": "List the workspace's approval queue (pending and decided requests), newest-first, with optional status / post filters."
    },
    {
      "id": "get_posting_limits",
      "name": "get_posting_limits",
      "description": "Anti-ban posting limits (cadence): one account by socialAccountId, or every active channel plus the tenant bypass flag when omitted."
    },
    {
      "id": "get_quota",
      "name": "get_quota",
      "description": "Adaptive quota pool: your scarce-bucket budget (guaranteed slice, used, burst headroom, tomorrow\u2019s guarantee tonight, reset clock) \u2014 read before planning a batch."
    },
    {
      "id": "list_campaigns",
      "name": "list_campaigns",
      "description": "List the workspace's campaigns (named post groupings), optionally filtered by client / status."
    },
    {
      "id": "decide_approval",
      "name": "decide_approval",
      "description": "Approve, reject, or request changes on a pending approval request (approve releases the gated post for publishing). A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "validate_post",
      "name": "validate_post",
      "description": "Dry-run a compose request and get the per-platform verdict WITHOUT writing anything \u2014 same arguments as create_post, no post row and no draft. Returns `{ valid, platforms[], estimatedCostUsd }`. Does not run cadence or quota admission, so `valid: true` means the shape is acceptable, not that a publish cannot later be deferred."
    },
    {
      "id": "revise_post",
      "name": "revise_post",
      "description": "Change the CONTENT of an already-scheduled post \u2014 caption, media, cover, alt text, per-platform overrides \u2014 without disturbing its destinations. Send only what you are changing. Refuses, naming them, when a destination has already published or is about to. An edit to an APPROVED post returns it to review. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "create_post",
      "name": "create_post",
      "description": "Compose a post and fan it out across the selected accounts (or save it as a draft). Retry-safe: retrying with identical arguments replays the original result instead of creating a duplicate. Note: two publish-now calls with byte-identical content and targets are treated as the same post and coalesced permanently \u2014 to intentionally publish the same content twice, vary the content or use distinct scheduled times. For platform-specific settings (e.g. YouTube privacy, TikTok privacy level, Pinterest board, Telegram chat), set `variants[].overrides`. That same object carries `firstComment`: a reply posted automatically once the destination goes live, so a \"link in the comments\" post needs no manual follow-up. Supported on X, LinkedIn, YouTube, Instagram, Facebook, Threads, Telegram and Bluesky (not TikTok or Pinterest); spell it exactly `firstComment`. Overrides are free-form \u2014 an unrecognised key is accepted and silently ignored \u2014 and the comment is best-effort: if it fails the post still publishes and nothing is reported, so confirm on the published post. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "create_posts_bulk",
      "name": "create_posts_bulk",
      "description": "Create up to 50 posts in one call. Each item is exactly the arguments of create_post, so a bulk item carries every override a single post does (per-platform caption, title, cover, per-asset alt text, first comment, per-platform settings). Items are created one after another, each on its own: one failing never rolls back the others, and the result lists every item in order with its post id or its error. Retry-safe: retrying with identical arguments creates nothing twice. Pass validateOnly:true to check every item without writing anything. It counts one request-budget unit per item. This creates real outbound content \u2014 confirm with the user before calling. Requires the posts.compose scope."
    },
    {
      "id": "update_post",
      "name": "update_post",
      "description": "Replace a draft post in place \u2014 its content, media, targets, and schedule. Only draft posts can be updated, and this never publishes (use publish_draft for that). Platform-specific settings live in `variants[].overrides`, same as create_post, including `firstComment`. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "publish_draft",
      "name": "publish_draft",
      "description": "Publish or schedule an existing DRAFT post in place \u2014 same arguments as update_post plus the draft id; `schedule` decides now or later. Runs the same checks as create_post (platform validation, approval policy, quota, pacing); a client that requires approval gets the post submitted for review instead. The post keeps its id. This puts real content on connected accounts \u2014 confirm with the user before calling."
    },
    {
      "id": "import_media",
      "name": "import_media",
      "description": "Ingest an external image / video into the content library by URL \u2014 the file must already be reachable at a public URL. For bytes you already hold (an image you just rendered, or a local file) use `upload_media` instead. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "upload_media",
      "name": "upload_media",
      "description": "Upload a LOCAL image / video into the content library and get back a media id for create_post. Sends the file inline (\u226418 MiB) or returns a presigned URL for larger files. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "reschedule_post",
      "name": "reschedule_post",
      "description": "Move a pending post target to a new time (absolute scheduledAt or relative shiftMinutes). A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "bulk_post_target_action",
      "name": "bulk_post_target_action",
      "description": "Reschedule, retry or cancel up to 5000 post targets in one call \u2014 the batch form of reschedule_post / retry_post / cancel_post. Returns `{ jobId, accepted, skipped, skippedReasons? }`; a skipped target is reported, never silently dropped. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "cancel_post",
      "name": "cancel_post",
      "description": "Cancel a still-pending post target before it publishes. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "retry_post",
      "name": "retry_post",
      "description": "Re-queue a failed or rate-limited post target so it publishes again. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "set_post_recycle",
      "name": "set_post_recycle",
      "description": "Set, update, or disable a post's evergreen recycle settings (interval / times / end date / max recycles). A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "shift_campaign",
      "name": "shift_campaign",
      "description": "Move a whole campaign's pending schedule by a relative number of minutes. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "list_webhooks",
      "name": "list_webhooks",
      "description": "List the workspace's outbound webhook endpoints (url, subscribed events, active flag; secret masked)."
    },
    {
      "id": "create_webhook",
      "name": "create_webhook",
      "description": "Register an outbound webhook endpoint for HMAC-signed event deliveries. Subscribe to any subset of the full 40-event catalog \u2014 see /developers/webhooks, or the `webhooks` block in openapi.json, for the complete list with payload fields. Returns the signing secret once. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "delete_webhook",
      "name": "delete_webhook",
      "description": "Delete an outbound webhook endpoint by id (deliveries cascade). A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "create_client",
      "name": "create_client",
      "description": "Create a new client group (a brand or influencer whose accounts are managed together). A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "create_connect_invite",
      "name": "create_connect_invite",
      "description": "Mint a shareable self-connect link so a client can connect the requested platforms themselves; returns the link and its expiry. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "get_webhook",
      "name": "get_webhook",
      "description": "Read one webhook endpoint \u2014 URL, subscribed events, active state, consecutive failures, and when/why it was auto-disabled. The signing secret is never returned here."
    },
    {
      "id": "list_webhook_deliveries",
      "name": "list_webhook_deliveries",
      "description": "The delivery log for one endpoint \u2014 each attempt with its event type, response status, error and timing. How you find out WHY an endpoint stopped receiving."
    },
    {
      "id": "update_webhook",
      "name": "update_webhook",
      "description": "Change an endpoint\u2019s URL, event list, or active state \u2014 including re-enabling one auto-disabled after repeated failures. The event list REPLACES the previous one. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "test_webhook",
      "name": "test_webhook",
      "description": "Send a `webhook.test` delivery and report the outcome, proving an endpoint is reachable and verifying signatures without waiting for a real event. Performs a real outbound request \u2014 confirm with the user before calling."
    },
    {
      "id": "rotate_webhook_secret",
      "name": "rotate_webhook_secret",
      "description": "Mint a new signing secret and return it ONCE \u2014 it is not readable again. The previous secret keeps verifying for a short overlap so the customer can redeploy without dropping deliveries. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "get_campaign",
      "name": "get_campaign",
      "description": "Read one campaign in full \u2014 name, description, status, colour, date range, owning client and post counts."
    },
    {
      "id": "create_campaign",
      "name": "create_campaign",
      "description": "Create a campaign \u2014 a named group of posts with an optional client, colour and date range. Posts are added with assign_to_campaign. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "update_campaign",
      "name": "update_campaign",
      "description": "Change a campaign\u2019s name, description, status, colour or date range. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "delete_campaign",
      "name": "delete_campaign",
      "description": "Delete a campaign. The posts in it are NOT deleted \u2014 they lose the grouping and keep their own schedules. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "assign_to_campaign",
      "name": "assign_to_campaign",
      "description": "Add up to 500 existing posts to a campaign. Grouping only \u2014 no post\u2019s content or schedule changes. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "unassign_from_campaign",
      "name": "unassign_from_campaign",
      "description": "Remove posts from a campaign. Grouping only \u2014 the posts and their schedules are untouched. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "get_client",
      "name": "get_client",
      "description": "Read one client group in full \u2014 name, type, approval policy, posting rules, brand voice and default timezone."
    },
    {
      "id": "update_client",
      "name": "update_client",
      "description": "Change a client\u2019s name, type, approval policy, posting rules, brand voice or default timezone. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "delete_client",
      "name": "delete_client",
      "description": "Archive a client group. OWNER ONLY \u2014 a Manager holding the clients.manage scope cannot do this. A write action \u2014 confirm with the user before calling."
    },
    {
      "id": "get_post_target",
      "name": "get_post_target",
      "description": "Read a single fan-out destination in full \u2014 status, scheduled time, platform, account, published permalink and external id, and its failure reason when it failed."
    },
    {
      "id": "get_post_recycle",
      "name": "get_post_recycle",
      "description": "Read one post\u2019s evergreen re-posting configuration and the worker\u2019s bookkeeping. Returns null when the post is not enrolled."
    },
    {
      "id": "get_account",
      "name": "get_account",
      "description": "Read one connected social account in full \u2014 platform, handle, display name, avatar, status (including whether it needs re-authorisation) and owning client."
    },
    {
      "id": "get_approval",
      "name": "get_approval",
      "description": "Read one approval request with the gated post\u2019s preview and roll-up, so a reviewer can see what they are deciding on before calling decide_approval."
    },
    {
      "id": "get_media_asset",
      "name": "get_media_asset",
      "description": "Read one content-library asset in full \u2014 filename, kind, size, dimensions, duration, folder, labels, alt text, pipeline status, and the publishable/ready flags plus the per-platform readiness map."
    },
    {
      "id": "get_client_analytics",
      "name": "get_client_analytics",
      "description": "One client group\u2019s analytics \u2014 totals, a per-platform breakdown and a time series. A different projection from get_analytics_overview filtered by client."
    },
    {
      "id": "get_report",
      "name": "get_report",
      "description": "Read one report definition with its run history \u2014 each run\u2019s status, window, and whether an export is available."
    },
    {
      "id": "download_report_export",
      "name": "download_report_export",
      "description": "Get a time-limited download URL for one completed report run\u2019s export file. The URL expires \u2014 fetch it when you are ready to use it."
    },
    {
      "id": "clear_post_recycle",
      "name": "clear_post_recycle",
      "description": "Turn OFF evergreen re-posting for a post. Idempotent. Already-scheduled recycled copies are not retracted \u2014 cancel those separately. A write action \u2014 confirm with the user before calling."
    }
  ]
}