Instagram brand data API

The catalogue behind Monitor Mentions, as JSON over HTTPS: 1,035 consumer brands with their Instagram followers, follower history, recent posts, share of mentions against competitors, and every ranking we publish. Read-only, GET only, one key per app.

Base URL
https://www.monitormentions.com/api/v1
Format
JSON, UTF-8, snake_case fields
Pricing
Credit packs from $19, 100 credits free to start

How do I authenticate?

Send your key on every request, in the Authorization header as a bearer token. The x-api-key header works too. Keys start with mm_live_ and are shown once, when you create them on the API dashboard; we store only a hash.

curl https://www.monitormentions.com/api/v1/brands/glossier \
  -H "Authorization: Bearer mm_live_..."

How much does the API cost?

You buy credits once and each request spends some. There is no subscription, credits never expire, and a new account gets 100 free. Only an answer that succeeds (a 2xx) spends credits: a 404, a 429 or an error costs nothing. Buy packs and see what you spent on the API dashboard.

PackPriceCreditsPer credit
Starter$192,000$0.0095
Builder$496,000$0.0082
Scale$14920,000$0.0075

What one request costs, by endpoint. At pack prices a 1-credit request is between $0.0075 and $0.0095.

EndpointCredits a request
/api/v1Free
/api/v1/meFree
/api/v1/brands1
/api/v1/brands/{slug}1
/api/v1/brands/{slug}/history2
/api/v1/brands/{slug}/posts2
/api/v1/brands/{slug}/share-of-mentions2
/api/v1/rankings1
/api/v1/rankings/{slug}1
/api/v1/categories1

Answers to a valid key carry two headers of our own:

HeaderMeans
x-credits-remainingCredits left on the account after this request.
x-credits-chargedCredits this request spent, 0 when it spent none.

When the balance cannot cover a request, the answer is a 402 that says what it needed and where to buy:

{
  "error": "This request costs 2 credits and the account has 1. Buy a credit pack to carry on.",
  "code": "insufficient_credits",
  "status": 402,
  "credits_required": 2,
  "credits_remaining": 1,
  "buy_url": "https://www.monitormentions.com/dashboard/api#packs"
}

What does an error look like?

Always the same shape: a sentence for people, a code for your program, and the HTTP status.

{
  "error": "No brand with slug 'glosier'.",
  "code": "not_found",
  "status": 404
}
StatuscodeWhen
401unauthorizedNo key, a key we do not know, or a revoked key.
402insufficient_creditsThe balance cannot cover this request. The answer says how many credits it needed and links to buy more.
403forbiddenAPI access for the account is suspended.
404not_foundNo brand or ranking with that slug, or nothing to compute (share of mentions).
429rate_limitedMore than 120 requests in a minute on one key. Wait for the retry-after seconds.
500server_errorOur fault. Retry later; tell us if it repeats.
503unavailableThe API is down for a moment. Retry with a backoff.

Why are some numbers null?

Every field is always present. A number we did not measure is null, never 0 and never an estimate. A brand we have not read yet has null followers; a post with hidden likes has null likes. Treat null as unknown.

API index

GET /api/v1 Free

Who the key belongs to, the credits left, the address of every endpoint and what each costs.

Response

{
  "api": "Monitor Mentions",
  "version": "1",
  "authenticated_as": "[email protected]",
  "credits_remaining": 1958,
  "docs": "https://www.monitormentions.com/docs/api",
  "buy_credits": "https://www.monitormentions.com/dashboard/api#packs",
  "endpoints": {
    "brands": "https://www.monitormentions.com/api/v1/brands",
    "brand": "https://www.monitormentions.com/api/v1/brands/{slug}",
    "follower_history": "https://www.monitormentions.com/api/v1/brands/{slug}/history",
    "posts": "https://www.monitormentions.com/api/v1/brands/{slug}/posts",
    "share_of_mentions": "https://www.monitormentions.com/api/v1/brands/{slug}/share-of-mentions",
    "rankings": "https://www.monitormentions.com/api/v1/rankings",
    "ranking": "https://www.monitormentions.com/api/v1/rankings/{slug}",
    "categories": "https://www.monitormentions.com/api/v1/categories",
    "balance": "https://www.monitormentions.com/api/v1/me"
  },
  "credit_costs": {
    "/api/v1": 0,
    "/api/v1/me": 0,
    "/api/v1/brands": 1,
    "/api/v1/brands/{slug}": 1,
    "/api/v1/brands/{slug}/history": 2,
    "/api/v1/brands/{slug}/posts": 2,
    "/api/v1/brands/{slug}/share-of-mentions": 2,
    "/api/v1/rankings": 1,
    "/api/v1/rankings/{slug}": 1,
    "/api/v1/categories": 1
  }
}

List brands

GET /api/v1/brands 1 credit

Every public brand in the catalogue (1,035 today) with its latest Instagram numbers, paged.

ParameterTypeWhat it does
categorystringOne category, exactly as /categories names it, e.g. Beauty. Case does not matter.
searchstringMatches the name, the Instagram handle or the slug.
sortstringname (default, A to Z), followers, engagement_rate or growth (highest first). Brands without that number come last.
limitinteger1 to 200, default 50.
offsetintegerSkip this many, default 0.

Request

curl "https://www.monitormentions.com/api/v1/brands?category=Beauty&sort=followers&limit=1" \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "total": 122,
  "limit": 1,
  "offset": 0,
  "data": [
    {
      "slug": "glossier",
      "name": "Glossier",
      "handle": "glossier",
      "category": "Beauty",
      "bio": "Glossier is the millennial beauty brand born from the Into The Gloss blog, championing skin-first, no-makeup makeup.",
      "website": null,
      "image": "https://www.monitormentions.com/api/logo/glossier?size=256",
      "instagram_url": "https://www.instagram.com/glossier/",
      "followers": 3124943,
      "following": 3618,
      "posts": 6085,
      "avg_likes": null,
      "avg_comments": null,
      "engagement_rate": null,
      "growth_percent": -0.1,
      "updated_at": "2026-11-01T15:29:48.435Z"
    }
  ]
}

The total is the number of brands that match, before paging.

One brand

GET /api/v1/brands/{slug} 1 credit

One brand's identity and its latest numbers. The slug is the one in its page address: /brand/glossier/instagram is glossier.

Request

curl https://www.monitormentions.com/api/v1/brands/glossier \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "data": {
    "slug": "glossier",
    "name": "Glossier",
    "handle": "glossier",
    "category": "Beauty",
    "bio": "Glossier is the millennial beauty brand born from the Into The Gloss blog, championing skin-first, no-makeup makeup.",
    "website": null,
    "image": "https://www.monitormentions.com/api/logo/glossier?size=256",
    "instagram_url": "https://www.instagram.com/glossier/",
    "followers": 3124943,
    "following": 3618,
    "posts": 6085,
    "avg_likes": null,
    "avg_comments": null,
    "engagement_rate": null,
    "growth_percent": -0.1,
    "updated_at": "2026-11-01T15:29:48.435Z"
  }
}
FieldMeaning
followers, following, postsThe latest profile reading. null until we have one.
avg_likes, avg_commentsAverages over the recent posts we measured. null when none were.
engagement_rateAverage likes plus comments per post, as a percentage of followers. null when not measured.
growth_percentFollower change over the last 30 days, to one decimal. null with fewer than five days between readings.
imageThe brand's logo, served by us. Safe to hotlink; it does not expire.
updated_atWhen the latest reading was taken.

Follower history

GET /api/v1/brands/{slug}/history 2 credits

Every daily follower reading we recorded for the brand, oldest first. Readings are as often as the brand is collected, so gaps between days are normal.

Request

curl https://www.monitormentions.com/api/v1/brands/glossier/history \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "slug": "glossier",
  "handle": "glossier",
  "total": 4,
  "data": [
    {
      "date": "2026-10-17",
      "followers": 3127049,
      "posts": 6072,
      "engagement_rate": null
    },
    {
      "date": "2026-10-20",
      "followers": 3127623,
      "posts": 6073,
      "engagement_rate": null
    },
    {
      "date": "2026-10-27",
      "followers": 3125932,
      "posts": 6080,
      "engagement_rate": null
    },
    {
      "date": "2026-11-01",
      "followers": 3124943,
      "posts": 6085,
      "engagement_rate": null
    }
  ]
}

Trimmed to the last four readings.

Recent posts

GET /api/v1/brands/{slug}/posts 2 credits

The brand's own recent posts, newest first, with the engagement we last measured and its follower count on the day each went up.

ParameterTypeWhat it does
limitinteger1 to 50, default 12.

Request

curl "https://www.monitormentions.com/api/v1/brands/glossier/posts?limit=1" \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "slug": "glossier",
  "handle": "glossier",
  "total": 1,
  "data": [
    {
      "id": "4020212909590921583",
      "url": "https://www.instagram.com/p/DfKqlddm0Fv/",
      "shortcode": "DfKqlddm0Fv",
      "caption": "Spooky season, but make it pink.",
      "thumbnail": "https://www.monitormentions.com/api/post-image/4020212909590921583",
      "is_video": false,
      "posted_at": "2026-10-31T17:12:26.000Z",
      "likes": null,
      "comments": 26,
      "views": null,
      "followers_at_post": 3125932,
      "engagement_rate": 0
    }
  ]
}
FieldMeaning
id, shortcode, urlInstagram's own identifiers for the post.
thumbnailThe post's image, served by us. null when we hold none.
likes, comments, viewsThe latest measurement. null when the platform did not report it, as with hidden like counts.
followers_at_postThe reading nearest the day the post went up, preferring the day before.

Share of mentions

GET /api/v1/brands/{slug}/share-of-mentions 2 credits

How much of its competitive set's Instagram conversation a brand holds over the last 30 days, as post counts and the shares worked out from them.

Request

curl https://www.monitormentions.com/api/v1/brands/glossier/share-of-mentions \
  -H "Authorization: Bearer $MM_API_KEY"

Response shape

{
  "data": {
    "brand": "glossier",
    "window_days": 30,
    "total_mentions": <integer>,
    "brands_measured": <integer>,
    "rank": <integer>,
    "brands": [
      { "slug", "name", "handle", "mentions": <integer>,
        "share_percent": <number>, "is_subject": <boolean> }
    ],
    "uncollected": [ { "slug", "name" } ]
  }
}
FieldMeaning
brandsEvery brand in the set we collect, most mentioned first. A brand we collect that nobody mentioned counts as 0.
uncollectedBrands in the set we do not collect. They are not in the total. Do not treat them as zeros and work the shares out again: the shares would come out too high.
404The brand has no curated set, fewer than two brands we collect, or no mentions across them. A share of one brand measures nothing.

List rankings

GET /api/v1/rankings 1 credit

Every ranked list we publish (54 today): mentions, followers, growth and engagement, across the catalogue and per category.

Request

curl https://www.monitormentions.com/api/v1/rankings \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "total": 54,
  "data": [
    {
      "slug": "most-mentioned",
      "title": "Most Mentioned Brands on Instagram",
      "description": "Brands ranked by the public Instagram posts our searches found mentioning them in the last 30 days.",
      "metric": "mentions"
    },
    {
      "slug": "food-and-beverage-brands",
      "title": "Top Food and Beverage Brands on Instagram",
      "description": "The most-followed food and beverage brands on Instagram, ranked by follower count.",
      "metric": "followers"
    }
  ]
}

Trimmed to the first two.

One ranking

GET /api/v1/rankings/{slug} 1 credit

One ranking in order. Each row is a brand, shaped like One brand, with its place. Only brands with that number measured are ranked.

ParameterTypeWhat it does
limitinteger1 to 200, default 50.
offsetintegerSkip this many, default 0.

Request

curl "https://www.monitormentions.com/api/v1/rankings/most-mentioned?limit=10" \
  -H "Authorization: Bearer $MM_API_KEY"

Response shape

{
  "slug": "most-mentioned",
  "title": "Most Mentioned Brands on Instagram",
  "metric": "mentions",
  "total": <integer>,
  "limit": 10,
  "offset": 0,
  "data": [ { "rank": 1, "slug": ..., "followers": ..., ... } ]
}

Categories

GET /api/v1/categories 1 credit

Every category and how many brands it holds, largest first. Use the name as the category filter on List brands.

Request

curl https://www.monitormentions.com/api/v1/categories \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "total": 16,
  "data": [
    {
      "name": "Food and Beverage",
      "brands": 425
    },
    {
      "name": "Restaurants",
      "brands": 130
    },
    {
      "name": "Beauty",
      "brands": 122
    }
  ]
}

Trimmed to the three largest.

Your balance

GET /api/v1/me Free

The address the key belongs to and the credits left. Free, so check it as often as you like.

Request

curl https://www.monitormentions.com/api/v1/me \
  -H "Authorization: Bearer $MM_API_KEY"

Response

{
  "email": "[email protected]",
  "credits_remaining": 1958,
  "buy_credits": "https://www.monitormentions.com/dashboard/api#packs"
}

Questions about the API

How do I get an API key?

Sign in and open the API dashboard. Create a key there and it works at once; a new account starts with 100 free credits to try it. When they run out, buy a credit pack on the same page.

How often does the data change?

Each brand is collected on its own schedule, from daily to every couple of weeks. A reading is stored when it is taken, and the API serves what is stored, so calling more often than daily returns the same numbers.

Why is a number null?

Because we did not measure it. The API never fills a gap with an estimate. A brand we have not read yet has null followers, and a post with hidden likes has null likes.

Do credits expire, and is there a subscription?

No to both. A pack is a one-off payment and its credits stay on the account until they are spent. The API is separate from the monitoring plans: a plan does not include credits and credits do not need a plan.

Is there a rate limit?

Each key can make 120 requests a minute. Past that it answers 429 for the rest of the minute and charges nothing. The data underneath changes daily at most, so there is little to gain from calling faster.

Can I call it from a browser?

Yes, every endpoint answers CORS requests from any origin. Keep the key out of public pages though: anyone who reads it can spend your credits. Revoke a leaked key on the API dashboard.

Getting a key

Sign in and open the API dashboard: create a key, and it works with 100 free credits. The API is separate from the monitoring plans. The same numbers are on every public brand page, for example Glossier on Instagram, and in every category.