Social APIs

Sprout Social API: Access, Pricing, Limits, and Alternatives

Sprout Social API guide for 2026: which plan has it, tokens and OAuth, rate limits, drafts-only publishing, and the MCP server. See where PostZen fits.
October 03, 2026 by Jesse Eisenbart16 min read
Oil painting of rows of young green seedlings in a mountain valley at sunrise, beside a rustic vine-covered wooden trellis

TLDR: The Sprout Social API reads analytics, posts, inbox messages, Listening topics, and cases, and writes only draft posts and media; a person publishes from Sprout. It requires the Advanced plan at $399 per seat per month. Limits: 60 requests a minute, 250,000 a month. The MCP server is ChatGPT only, TikTok data only. It suits reporting, not products posting for users.

Does Sprout Social have an API?

Yes. The Sprout Social API, which Sprout’s pages also call the Sprout API or the Sprout Public API, is a REST API at https://api.sproutsocial.com, currently on major version 1. It exists to get data out of a Sprout account: profile analytics, post performance, inbox messages, Listening topics, and customer care cases. It writes exactly two things, draft posts and their media, and a person inside Sprout publishes the drafts. Access comes with the Advanced plan.

It gained an AI layer on November 18, 2025, when Sprout launched Sprout AI, its Trellis agent, and a remote MCP server with ChatGPT as the first client. The MCP server is narrower than that sounds; it gets its own section below.

If you searched for Sprout Social API documentation, it is in two places: the API reference, one long page covering authentication, every endpoint, the metric catalog per network, and the Tableau connector, and the shorter Sprout Public API help article, which covers use cases, permissions, and excluded data. As of October 3, 2026, the reference mentions no OpenAPI spec, sandbox, webhooks, or client library, so the HTTP calls are yours to write.

Which Sprout Social plan includes API access?

Advanced or Enterprise. Sprout’s pricing page lists the Sprout API among the things Advanced adds to Professional, and Enterprise includes everything in Advanced. Prices are per seat per month on annual billing, with a 30-day free trial and no credit card, as of October 3, 2026:

Plan Per seat per month Social profiles Sprout API
Essentials (new) $79, or $99 billed monthly 5 No
Standard $199 5 No
Professional $299 Unlimited No
Advanced $399 Unlimited Yes
Enterprise Custom Unlimited Yes, everything in Advanced

The plan is only the first of four gates:

  1. The Advanced plan for the whole account; the API is not a separate add-on.
  2. The API Permissions permission, granted by an Account Owner to each user who will manage tokens.
  3. Sprout’s Analytics API Terms of Service, accepted once under Settings, Global Features, API.
  4. Provisioning. Sprout’s blog post on the API says your Sprout account representative must authorize the account for API use before you can create tokens; the reference does not mention this step, so do not assume self-serve access.

The seat model sets the real cost of the Sprout Social API: three people on Advanced cost 3 times $399, or $1,197 a month (about $14,364 a year), by our arithmetic from Sprout’s list prices. Add-ons sit outside that figure: Premium Analytics and Listening have no list price on the pricing page (the Listening endpoints need Listening topics), and Sprout’s blog says the Tableau connector needs Premium Analytics on top of Advanced. Sprout also provides no implementation assistance for the API; Support will troubleshoot its behavior, but the integration is yours to build.

How do you get a Sprout Social API key or OAuth token?

API tokens are the quick route. Any user with API Permissions goes to Settings, Global Features, API, clicks Generate API Token, names it, and copies it; tokens are account-scoped, and the same page lists and invalidates existing ones.

OAuth 2.0 is what Sprout recommends. Under OAuth Client Management on the same page, click Generate configuration and choose a method: machine-to-machine (client credentials) for your own integrations and for partners that ask for a client ID and secret, or user-based (authorization code, with allowed redirect URIs) for an application where people log in with Sprout. Either way Sprout issues short-lived JWT access tokens whose lifetime the reference does not publish, so request fresh ones rather than caching them for long. The machine-to-machine exchange:

SPROUT_AUTH='https://identity.sproutsocial.com/oauth2/84e39c75-d770-45d9-90a9-7b79e3037d2c'
curl -X POST "$SPROUT_AUTH/v1/token" \
  -H 'Content-Type: application/x-www-form-urlencoded' \
  --data-urlencode "client_id=$SPROUT_CLIENT_ID" \
  --data-urlencode "client_secret=$SPROUT_CLIENT_SECRET" \
  --data-urlencode 'grant_type=client_credentials' \
  --data-urlencode 'scope=organization_id'

That path, identifier included, is Sprout’s authorization server as printed in its reference. Every API request then carries Authorization: Bearer <token> with either credential, plus Accept: application/json and Content-Type: application/json. Responses carry X-Sprout-Request-ID and X-Sprout-API-Version, and the body is an object with a data array plus optional paging and error fields. Only the major version goes in the path, so /v1/ survives minor additions.

One more acceptance gates X data: every user with API Permissions must accept the Sprout API X Content End User License Agreement, shown at the top of the same settings page, before X data is returned.

What can the Sprout Social API do?

Every endpoint except the first lives under your customer ID, which GET /v1/metadata/client returns, and most reads are POST requests with a JSON body of filters. As of October 3, 2026, the Sprout Social API has seven groups, all under https://api.sproutsocial.com/v1/:

Group Endpoints under /v1/ Notes
Customer metadata (GET) metadata/client, then <customer ID>/metadata/customer plus /tags, /groups, /users, /topics, /teams, /queues Profiles carry customer_profile_id, network_type, name, native_name, native_id, and groups
Analytics (POST) <customer ID>/analytics/profiles, <customer ID>/analytics/posts Filters are strings such as customer_profile_id.eq(1234, 5678), plus a reporting period or created-time range
Listening (POST) <customer ID>/listening/topics/<topic id>/messages and .../metrics Topics come from the Listening add-on
Messages (POST) <customer ID>/messages Inbox messages and sent replies, filtered by one group; read only
Publishing (POST, GET) <customer ID>/publishing/posts to create, plus /<publishing_post_id> to read one Drafts only
Media (POST, GET) <customer ID>/media/ for one request up to 50 MiB (a file or a media_url), <customer ID>/media/submission for multipart in 5 MiB parts Only for use with publishing posts
Cases (POST) <customer ID>/cases/filter Social customer care cases

Analytics, which Sprout’s blog calls its Reporting API, covers X, Facebook, Threads, Instagram, LinkedIn, Pinterest, YouTube, and TikTok, with demographics for Facebook Pages, Instagram Business, LinkedIn Pages, and TikTok.

The per-endpoint limits decide whether a backfill is feasible:

  • Profile analytics: up to 100 profiles and one year per request, 1,000 results per page by default.
  • Post analytics: up to 100 profiles per request, 50 results per page by default, and a cap of 10,000 results per query; for more, sort by guid ascending and page with a guid.gt(<last guid>) filter.
  • Messages: 50 per page by default and 100 at most, with forward-only pagination through page_cursor.
  • Cases: date-range filters cover at most one week.
  • Not included: paid or ad account data, Listening data from X, Listening message-level data from Reddit, competitor data, account or profile management, and reviews from Yelp, Trustpilot, TripAdvisor, and Glassdoor. Google My Business post data covers only the last 30 days, and media URLs in direct messages do not work (text and metadata do).
  • No replies or sends. The messages endpoint reads the inbox; nothing in the API answers it.

Our social media analytics API guide covers what each network exposes directly, without a Sprout seat in the middle.

What are the Sprout Social API rate limits?

The Sprout Social API reference devotes one short section to limits: 60 requests per minute and 250,000 requests per month. Crossing either returns HTTP 429 Too Many Requests, which the status table describes as requesting too quickly or using up the month’s allowance, with one corrective action: slow down. None of the three documented response headers reports remaining quota, and no Retry-After is documented, so count requests on your side.

In practice the monthly figure binds first. By our arithmetic, 60 a minute sustained for 30 days would be about 2.6 million requests, while 250,000 a month works out to roughly 8,333 a day, or about 5.8 a minute averaged over the month. Reporting fits easily: pulling a day’s metrics for 100 profiles takes one request. A post-analytics backfill is tighter: at the default 50 results per page, 10,000 posts is 200 requests, and anything larger needs the guid cursor pattern above, so raise limit where the endpoint accepts it.

How do you create a post with the Sprout Social API?

Only as a draft. The reference says “Only posts created in draft status are supported at this time.” Every request must carry "is_draft": true, and someone opens Sprout to publish. Drafts can target Instagram, Facebook Pages, Threads, X, LinkedIn, YouTube, TikTok, Pinterest, and Google My Business, but not Bluesky or Telegram.

The flow is four calls: customer ID, profiles that share a group, media upload, draft. Here it is in Node.js 18 or later, saved as an ES module (a .mjs file, or "type": "module" in package.json) because it uses top-level await:

const API = 'https://api.sproutsocial.com/v1';
const TOKEN = process.env.SPROUT_TOKEN; // an API token or an OAuth access token

async function sprout(path, init = {}) {
  const res = await fetch(`${API}${path}`, {
    ...init,
    headers: {
      Authorization: `Bearer ${TOKEN}`,
      Accept: 'application/json',
      ...init.headers,
    },
  });
  if (res.status === 429) {
    throw new Error('Rate limited: over 60 requests a minute or the 250,000 monthly allowance');
  }
  const body = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(`Sprout ${res.status}: ${body.error ?? 'request failed'}`);
  return body.data;
}

// 1. Every other call is scoped to your customer ID.
const [{ customer_id: customerId }] = await sprout('/metadata/client');

// 2. Pick profiles by Sprout's customer_profile_id, then a group they all share.
const wanted = process.env.SPROUT_PROFILE_IDS.split(',').map(Number);
const profiles = (await sprout(`/${customerId}/metadata/customer`)).filter((p) =>
  wanted.includes(p.customer_profile_id),
);
if (profiles.length === 0) throw new Error('No profile matched SPROUT_PROFILE_IDS');
const groupId = profiles[0].groups.find((g) => profiles.every((p) => p.groups.includes(g)));
if (groupId === undefined) throw new Error('The chosen profiles share no group');

// 3. Upload the image by URL. Do not set Content-Type: fetch adds the multipart boundary.
const form = new FormData();
form.append('media_url', 'https://cdn.example.com/fall-menu.jpg');
const [{ media_id: mediaId }] = await sprout(`/${customerId}/media/`, {
  method: 'POST',
  body: form,
});

// 4. Create the draft. is_draft must be true; Sprout fans out one draft per profile.
const drafts = await sprout(`/${customerId}/publishing/posts`, {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    group_id: groupId,
    customer_profile_ids: profiles.map((p) => p.customer_profile_id),
    is_draft: true,
    text: 'The fall menu is here: three new soups and a cider flight.',
    media: [{ media_id: mediaId, media_type: 'PHOTO' }],
    delivery: { type: 'SCHEDULED', scheduled_times: ['2026-10-13T15:00:00Z'] },
  }),
});

// 5. One object per profile, each a separate draft on the Sprout calendar.
for (const d of drafts) {
  const { publishing_post_id, perma_link } = d.internal.publishing;
  console.log(d.customer_profile_id, publishing_post_id, perma_link);
}

The same flow in Python with requests:

import os

import requests

API = "https://api.sproutsocial.com/v1"
HEADERS = {
    "Authorization": f"Bearer {os.environ['SPROUT_TOKEN']}",  # API token or OAuth access token
    "Accept": "application/json",
}


def sprout(method, path, **kwargs):
    res = requests.request(method, f"{API}{path}", headers=HEADERS, timeout=120, **kwargs)
    if res.status_code == 429:
        raise RuntimeError(
            "Rate limited: over 60 requests a minute or the 250,000 monthly allowance"
        )
    try:
        body = res.json()
    except ValueError:
        body = {}
    if not res.ok:
        raise RuntimeError(f"Sprout {res.status_code}: {body.get('error', 'request failed')}")
    return body["data"]


# 1. Every other call is scoped to your customer ID.
customer_id = sprout("GET", "/metadata/client")[0]["customer_id"]

# 2. Pick profiles by Sprout's customer_profile_id, then a group they all share.
wanted = {int(i) for i in os.environ["SPROUT_PROFILE_IDS"].split(",")}
all_profiles = sprout("GET", f"/{customer_id}/metadata/customer")
profiles = [p for p in all_profiles if p["customer_profile_id"] in wanted]
if not profiles:
    raise RuntimeError("No profile matched SPROUT_PROFILE_IDS")
shared = set.intersection(*(set(p["groups"]) for p in profiles))
if not shared:
    raise RuntimeError("The chosen profiles share no group")
group_id = min(shared)

# 3. Upload the image by URL as a multipart text part; requests sets the boundary.
image_url = "https://cdn.example.com/fall-menu.jpg"
media = sprout("POST", f"/{customer_id}/media/", files={"media_url": (None, image_url)})
media_id = media[0]["media_id"]

# 4. Create the draft. is_draft must be true; Sprout fans out one draft per profile.
drafts = sprout(
    "POST",
    f"/{customer_id}/publishing/posts",
    json={
        "group_id": group_id,
        "customer_profile_ids": [p["customer_profile_id"] for p in profiles],
        "is_draft": True,
        "text": "The fall menu is here: three new soups and a cider flight.",
        "media": [{"media_id": media_id, "media_type": "PHOTO"}],
        "delivery": {"type": "SCHEDULED", "scheduled_times": ["2026-10-13T15:00:00Z"]},
    },
)

# 5. One object per profile, each a separate draft on the Sprout calendar.
for d in drafts:
    pub = d["internal"]["publishing"]
    print(d["customer_profile_id"], pub["publishing_post_id"], pub["perma_link"])

What bites if you skip a step:

  • Profiles must share a group. Every ID in customer_profile_ids must belong to group_id, so the code picks a group present in every chosen profile’s groups.
  • Media is uploaded first and expires. The upload returns a media_id and an expiration_time; unused media is kept 24 hours. Sprout does not transcode for the networks, and a media_url upload holds the request open until the download finishes, so use the multipart endpoints for large files.
  • Fan-out. Each profile, and each scheduled time, becomes a separate draft with its own publishing_post_id and perma_link.
  • Silent drops. If the media does not suit one selected network, that profile is dropped with no error; Sprout’s own example is a PDF sent to LinkedIn and Instagram, which creates only the LinkedIn draft, so compare the response count with your request.
  • Status never changes. Retrieving a draft by publishing_post_id always shows delivery_status: PENDING, even after it is published; use the Messages endpoint to find the live post.
  • Times round down. scheduled_times must be in the future, and seconds round down to the minute. Instagram story and Mobile Publisher posts cannot be created directly; they arrive as media posts to adjust in Sprout.

Does Sprout Social have an MCP server?

Yes, with two restrictions. Sprout announced the server on November 18, 2025 in the same press release as Sprout AI and the Trellis agent. Setup is in Sprout’s ChatGPT Connection article: in ChatGPT Plus, Pro, or Enterprise with Developer Mode on, open Apps and Connectors and create a connector with the server URL https://mcp.sproutsocial.com/mcp and OAuth authentication.

The restrictions, as of October 3, 2026:

  1. ChatGPT only. Sprout’s integration overview says its AI integration is “built and supported for ChatGPT only” and that connecting Claude, Gemini, or any other tool is not built, tested, or documented and may not work.
  2. TikTok data only. Both help articles state that the connection covers TikTok published-post insights and performance metrics, nothing else. You can ask how last month’s TikTok posts performed; you cannot draft a post, read the inbox, or query Facebook analytics.

Several community-built Sprout MCP servers on GitHub wrap the Sprout API, so they inherit its gates (Advanced plan, drafts only, 60 requests a minute), and none is official.

Our MCP server takes the other approach: it fronts the same publishing API, so an agent can create and schedule live posts behind an OAuth 2.1 consent screen where the user chooses Read Only or Read and Write. The TikTok MCP page shows that for TikTok, and the agents page has setup steps for Claude, Cursor, and other clients.

Can you build a product for your users on the Sprout Social API?

Not if those users are not Sprout customers. Sprout’s Developer Terms, last updated May 9, 2024, grant access solely for your internal business purposes in developing, testing, and supporting an application that interoperates with Sprout, and require every Sprout Social user to hold a valid Sprout subscription. Four more clauses shape what is allowed:

  • No replicating or competing with Sprout, and no building or replacing its features (section 3(r)).
  • No charging end users for use of, or access to, Sprout’s functionality or APIs; a standard overall fee for your application is allowed (section 15).
  • Cached data refreshed at least every 24 hours; user data deleted within 30 days of deauthorization or a deletion request (section 5).
  • Each request must identify your application, and Sprout posts or messages shown outside Sprout must display Sprout’s permalink (section 4).

The terms also restrict the APIs to businesses, prohibit consumer use, and promise no support. Add drafts-only publishing and $399 a month per seat: fifty customer brands would each need their own Sprout subscription on Advanced, and a person at each would still press publish, which settles the question.

To be fair to Sprout, that is not the job the Sprout Social API was built for. It connects a Sprout customer’s own stack to Sprout: a CMS handing drafts to the social team, a warehouse pulling reporting data, a helpdesk receiving cases. Sprout’s blog names Slate, Opal, Optimizely, Tableau, and Chattermill among them. If you build integrations for Sprout customers, the reference links a form for becoming a Sprout tech partner.

Sprout Social API vs PostZen: which one fits?

We built PostZen for products that publish on their users’ behalf, so this table is not neutral; each Sprout row comes from the documentation linked above and each PostZen row from our API reference.

Sprout Social API PostZen API
Built for Reporting on, and drafting into, a Sprout account Publishing from your own product
Who connects social accounts Your team, inside Sprout Your users, through a hosted connect link in your product
Getting credentials Advanced plan, API Permissions, accepted terms, then a token Sign up and create an API key
Publishing Drafts only; a person publishes in Sprout Live or scheduled posts; drafts optional
Networks Drafts for nine networks, including Google My Business; no Bluesky or Telegram 10 platforms, including Bluesky and Telegram; no Google Business Profile
Media Upload first (50 MiB in one request, multipart above that), expires in 24 hours, no transcoding A URL that PostZen re-hosts up to 100 MB, or a direct upload up to 5 GB
Webhooks None documented Post published, partially failed, or failed; account needs reauth or disconnected
Analytics Profile and post metrics for 8 networks; Listening data needs the Listening add-on 8 platforms through the same API; LinkedIn pending
Comments and DMs Reads inbox messages and cases; cannot reply Comments on Instagram, Facebook Pages, and Threads; Instagram DMs; replies through the API
AI agents MCP server for ChatGPT, TikTok insights only One MCP server that can publish and schedule
Rate limits 60 per minute, 250,000 per month 60 to 2,000 per minute by plan
Pricing model Advanced plan, $399 per seat per month Plans from Free to Scale on the pricing page

Use the Sprout Social API if:

  • Your team already works in Sprout on Advanced and wants its reporting numbers in a warehouse, BI tool, or dashboard.
  • Your CMS or project tool should hand finished content to Sprout as drafts for a person to review and publish.
  • You need social listening, customer care cases, review management, or employee advocacy, none of which PostZen offers.

Use a developer API like PostZen if:

  • Posts have to go out on schedule without a person pressing publish.
  • Your users are not Sprout customers and should not need Advanced seats.
  • You need Bluesky or Telegram, or want to answer comments and Instagram DMs through an API.
  • You want an agent that publishes and schedules, from Claude, Cursor, or another MCP client.

A few honest notes on our side. PostZen has no social listening, employee advocacy, approval workflows, team seats, or review management, and no Google Business Profile publishing, which Sprout drafts support. Bluesky video and LinkedIn analytics are not live yet, LinkedIn company pages await LinkedIn’s approval, and X posts carry X’s own per-request API charges, which we pass through. Our Hootsuite API guide and Buffer API guide cover the other two schedulers in this series, and the best social media APIs for developers roundup compares the API-first options.

The shorter path: one request to every platform

The Sprout sample ends with drafts waiting for a person. Here is the same fall-menu photo going live on Facebook, Instagram, LinkedIn, and Bluesky in one request:

curl -X POST https://api.postzen.dev/v1/posts \
  -H "Authorization: Bearer $POSTZEN_API_KEY" \
  -H "Content-Type: application/json" \
  -H "x-request-id: fall-menu-launch" \
  -d '{
    "content": "The fall menu is here: three new soups and a cider flight.",
    "scheduledFor": "2026-10-13T15:00:00Z",
    "mediaItems": [{ "url": "https://cdn.example.com/fall-menu.jpg" }],
    "platforms": [
      { "platform": "facebook", "accountId": "acc_facebook" },
      {
        "platform": "instagram",
        "accountId": "acc_instagram",
        "settings": { "postType": "feed" }
      },
      { "platform": "linkedin", "accountId": "acc_linkedin" },
      { "platform": "bluesky", "accountId": "acc_bluesky" }
    ]
  }'

Line by line:

  • It publishes. At 15:00 UTC on October 13 the post goes out on all four networks; isDraft exists but is optional.
  • platforms holds one target per network with its own accountId and settings; Instagram takes a postType of feed, story, reel, or carousel, and a network with no required options can omit settings.
  • mediaItems takes a URL that PostZen downloads and re-hosts, up to 100 MB, with no upload step and no 24-hour expiry to race; POST /v1/media/presign takes direct uploads up to 5 GB.
  • x-request-id makes the create idempotent; a retry returns the original post, not a duplicate.
  • scheduledFor must be at least 60 seconds ahead; our scheduling API guide covers per-network scheduling.

Webhooks report post.published, post.partially_failed, post.failed, account.needs_reauth, and account.disconnected. Your users connect their own accounts through a hosted link (GET /v1/connect/{platform} returns an authUrl) without a PostZen account. Analytics for Instagram, Facebook, X, YouTube, TikTok, Threads, Pinterest, and Bluesky come through the same API (LinkedIn pending LinkedIn’s review; Telegram has no metrics), as do inbox replies to comments and Instagram DMs. Rate limits run from 60 requests a minute on Free to 2,000 on Scale, and two SDKs, @postzen/node and postzen-sdk for Python, wrap the same endpoints.

If you searched for a Sprout Social API alternative because your team lives in Sprout and you want its reporting data elsewhere, you do not need one; the Sprout API is the right tool. If posts need to go out without a person pressing publish, or your users should never have to buy an Advanced seat, that is the case we built our social media API for.

Frequently asked questions

Does Sprout Social have an API?

Yes. The Sprout API, which Sprout also calls the Sprout Public API, is a REST API at api.sproutsocial.com for Advanced and Enterprise plan customers. It reads owned-profile analytics, post performance, inbox messages, Listening topics, and customer care cases, and it writes two things: draft posts and the media attached to them. The reference lives at api.sproutsocial.com/docs.

How much does the Sprout Social API cost?

Sprout lists no separate API fee. API access comes with the Advanced plan, $399 per seat per month on annual billing as of October 3, 2026, and with Enterprise, which is custom priced. Essentials, Standard, and Professional do not include it. Listening and Premium Analytics are separate add-ons with no list price on the pricing page, and the Listening endpoints read topics from the Listening add-on.

How do I get a Sprout Social API key?

An Account Owner first grants you the API Permissions permission, and you accept Sprout's Analytics API Terms of Service in Settings. Then go to Settings, Global Features, API, and click Generate API Token for an account-scoped token. Sprout recommends OAuth 2.0 instead: create a machine-to-machine client under OAuth Client Management and exchange its client ID and secret for a short-lived JWT access token.

What are the Sprout Social API rate limits?

Sprout allows 60 requests per minute and 250,000 requests per month, and both ceilings return HTTP 429 Too Many Requests, which the documentation says to answer by slowing down. No rate-limit or Retry-After headers are documented, so track your own counts. Spread evenly, 250,000 a month is about 8,300 requests a day, well under what 60 a minute would allow.

Can the Sprout Social API publish posts?

Only as drafts. Every publishing request must carry is_draft set to true, and a person then publishes the draft from inside Sprout; the API cannot post live. Drafts can target Instagram Business and Creator accounts, Facebook Pages, Threads, X, LinkedIn Pages and personal profiles, YouTube, TikTok, Pinterest, and Google My Business. One request creates a separate draft per profile.

Does Sprout Social have an MCP server?

Yes, with narrow scope. Sprout announced a remote MCP server, now at mcp.sproutsocial.com/mcp, on November 18, 2025, alongside its Trellis AI agent. As of October 3, 2026, Sprout supports it for ChatGPT only (Plus, Pro, or Enterprise, with Developer Mode on), and the connection returns TikTok data only: published-post insights and performance metrics. Sprout says Claude, Gemini, and other clients are untested and may not work.