Every API here is available over the APIs.io API and to AI agents over MCP.
MCP server
One button, every client — Claude, Cursor, VS Code and the rest.
https://apis.io/mcp
Tools for apis
7 MCP tools reach this
find_apisBrowse and filter every API in the catalog.
get_api_artifactsOne API's artifacts, grouped by type.
get_openapiThe primary OpenAPI for this API.
find_similar_apisAPIs that look like this one.
apis_io_searchSTART HERE — APIs, providers and tags for one query, each with its total.
resolveTurn a domain, URL or GitHub org into the provider it belongs to.
find_cohortsEvery scored population of providers in the catalog.
All 92 tools
Call it yourself
curl for this page
This API
curl "https://apis.io/api/v1/apis/socialcrawl-bluesky-api"
All apis
curl "https://apis.io/api/v1/apis?limit=25"
Discovery needs no key. Ratings and market analysis are Pro.
Get an API key
Free tier, no email required.
A second provider on the same verified email joins the account you already have.
openapi: 3.2.0
info:
title: SocialCrawl Bluesky API
version: 1.0.0
description: 'Unified social media data API - one API key, one consistent response format, 50 platforms, 400 endpoints. Power AI agents with clean social data.
Slim variant: inline examples removed and the shared error responses hoisted into components. The full annotated spec is at https://www.socialcrawl.dev/openapi.json.'
contact:
name: SocialCrawl
url: https://www.socialcrawl.dev
email: support@socialcrawl.dev
servers:
- url: https://www.socialcrawl.dev/v1
description: Production
security:
- ApiKeyAuth: []
tags:
- name: bluesky
description: Bluesky endpoints
paths:
/bluesky/profile:
get:
summary: Get a Bluesky profile
description: 'Returns a Bluesky user''s public profile: handle, displayName, avatar, description, followersCount, followsCount, postsCount, createdAt, and verification status.'
tags:
- bluesky
operationId: get_bluesky_profile
security:
- ApiKeyAuth: []
x-credit-tier: standard
x-credit-cost: 1
parameters:
- name: handle
in: query
required: true
description: Bluesky handle (e.g. `espn.com`).
schema:
type: string
- name: Cache-Control
in: header
required: false
description: Send `no-cache` to bypass the response cache and force a live fetch. Billed at the normal endpoint cost; the fresh result is written back to cache for the next caller. Only the `no-cache` directive triggers this. See the Response Schema guide for details.
schema:
type: string
- name: Idempotency-Key
in: header
required: false
description: 'Optional UUID that makes the request safely retriable. A replay keeps the cached payload immutable except for billing metadata: `credits_used` becomes 0, `idempotent_replay` becomes true, and `credits_remaining` is refreshed to the current balance. A known current balance appears in both the body and `X-Credits-Remaining` header; no balance row resolves to 0. On a transient lookup failure, body `credits_remaining` is null and `X-Credits-Remaining` is omitted. Scoped per account with a 24-hour TTL.'
schema:
type: string
responses:
'200':
description: Successful response
headers:
X-Credits-Used:
description: Net credits charged for this response. Idempotency replays report 0.
schema:
type: integer
minimum: 0
X-Credits-Remaining:
description: Current balance when known. On an idempotency replay, this header is omitted when the balance lookup fails; body `credits_remaining` is null instead.
schema:
type: integer
minimum: 0
X-Idempotent-Replay:
description: Present with value `true` only when this response replays a settled idempotency record.
schema:
type: string
enum:
- 'true'
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
description: Whether the request succeeded
platform:
type: string
description: Platform name
endpoint:
type: string
description: API endpoint path
data:
type: object
description: Platform-specific response data
properties:
id:
type: string
description: Platform-specific user ID (always a string; platform-specific prefixes like `did:`, `spotify:artist:`, `t2_` are stripped)
username:
type:
- string
- 'null'
description: User handle or username
display_name:
type:
- string
- 'null'
description: Display name or full name
avatar_url:
type:
- string
- 'null'
description: URL to profile picture
bio:
type:
- string
- 'null'
description: Profile biography or description
verified:
type:
- boolean
- 'null'
description: Whether the account is verified
followers:
type:
- integer
- 'null'
description: Follower or subscriber count as an integer. Exact on Instagram and on TikTok when the source exposes an unrounded figure. YouTube above 1,000 subscribers is YouTube's published three-significant-figure figure. When the integer is a published/rounded value, `author.ext.followers_approximate` is true.
following:
type:
- integer
- 'null'
description: Number of accounts followed
posts_count:
type:
- integer
- 'null'
description: Total number of posts / videos / tracks / episodes
likes_count:
type:
- integer
- 'null'
description: Total likes received across the author's content (when surfaced)
url:
type:
- string
- 'null'
description: Direct URL to the profile page
location:
type:
- string
- 'null'
description: ISO region code (e.g. `US`) or freeform location string when surfaced
external_url:
type:
- string
- 'null'
description: Bio link / external website URL when surfaced by the platform
private:
type:
- boolean
- 'null'
description: Boolean at author.private
joined_at:
type:
- string
- 'null'
description: String at author.joined_at
ext:
type:
- object
- 'null'
description: 'Nested object: author.ext'
properties:
social_context:
type:
- string
- 'null'
description: String at author.ext.social_context
account_created:
type:
- string
- 'null'
description: String at author.ext.account_created
country:
type:
- string
- 'null'
description: String at author.ext.country
former_usernames:
type:
- array
- 'null'
description: Array at author.ext.former_usernames
items:
type: string
description: String at author.ext.former_usernames
public_email:
type:
- string
- 'null'
description: String at author.ext.public_email
public_phone:
type:
- string
- 'null'
description: String at author.ext.public_phone
business_category:
type:
- string
- 'null'
description: String at author.ext.business_category
hd_avatar_url:
type:
- string
- 'null'
description: String at author.ext.hd_avatar_url
website:
type:
- string
- 'null'
description: String at author.ext.website
cover_url:
type:
- string
- 'null'
description: String at author.ext.cover_url
page_active:
type:
- boolean
- 'null'
description: Boolean at author.ext.page_active
employee_count:
type:
- integer
- 'null'
description: Numeric at author.ext.employee_count
employee_count_range:
type:
- object
- 'null'
description: 'Nested object: author.ext.employee_count_range'
properties:
start:
type:
- integer
- 'null'
description: Numeric at author.ext.employee_count_range.start
end:
type:
- integer
- 'null'
description: Numeric at author.ext.employee_count_range.end
founded_year:
type:
- integer
- 'null'
description: Numeric at author.ext.founded_year
specialities:
type:
- array
- 'null'
description: Array at author.ext.specialities
items:
type: string
description: String at author.ext.specialities
industries:
type:
- array
- 'null'
description: Array at author.ext.industries
items:
type: string
description: String at author.ext.industries
headquarters:
type:
- string
- 'null'
description: Leaf at author.ext.headquarters
locations:
type:
- array
- 'null'
description: Array at author.ext.locations
items:
type: string
description: Leaf at author.ext.locations
hashtags:
type:
- array
- 'null'
description: Array at author.ext.hashtags
items:
type: string
description: Leaf at author.ext.hashtags
funding:
type:
- string
- 'null'
description: Leaf at author.ext.funding
address:
type:
- string
- 'null'
description: String at author.ext.address
price_range:
type:
- string
- 'null'
description: String at author.ext.price_range
rating:
type:
- string
- 'null'
description: String at author.ext.rating
rating_count:
type:
- integer
- 'null'
description: Numeric at author.ext.rating_count
talking_about_count:
type:
- integer
- 'null'
description: Numeric at author.ext.talking_about_count
business_hours:
type:
- array
- 'null'
description: Array at author.ext.business_hours
items:
type: string
description: Leaf at author.ext.business_hours
links:
type:
- array
- 'null'
description: Array at author.ext.links
items:
type: string
description: Leaf at author.ext.links
ad_library_page_id:
type:
- string
- 'null'
description: String at author.ext.ad_library_page_id
ad_library_status:
type:
- string
- 'null'
description: String at author.ext.ad_library_status
urn:
type:
- string
- 'null'
description: String at author.ext.urn
is_top_voice:
type:
- boolean
- 'null'
description: Boolean at author.ext.is_top_voice
is_premium:
type:
- boolean
- 'null'
description: Boolean at author.ext.is_premium
followers_approximate:
type:
- boolean
- 'null'
description: 'True when `author.followers` is a published or rounded figure rather than an unrounded census: LinkedIn people-list display buckets, TikTok `stats.followerCount` when the exact sibling is absent, and YouTube subscriber counts at or above 1,000. Null or absent on exact counts.'
keywords:
type:
- string
- 'null'
description: String at author.ext.keywords
topicCategories:
type:
- array
- 'null'
description: Array at author.ext.topicCategories
items:
type: string
description: String at author.ext.topicCategories
bannerExternalUrl:
type:
- string
- 'null'
description: String at author.ext.bannerExternalUrl
madeForKids:
type:
- boolean
- 'null'
description: Boolean at author.ext.madeForKids
hiddenSubscriberCount:
type:
- boolean
- 'null'
description: Boolean at author.ext.hiddenSubscriberCount
related_playlists:
type:
- string
- 'null'
description: Leaf at author.ext.related_playlists
topic_ids:
type:
- array
- 'null'
description: Array at author.ext.topic_ids
items:
type: string
description: String at author.ext.topic_ids
unsubscribed_trailer:
type:
- string
- 'null'
description: String at author.ext.unsubscribed_trailer
monthly_listeners:
type:
- integer
- 'null'
description: Numeric at author.ext.monthly_listeners
total_ratings:
type:
- integer
- 'null'
description: 'Spotify podcasts only: how many listeners have rated the show. Cumulative over the show''s whole run, so it reflects longevity as well as size, and it is NOT an audience count (Spotify publishes no play, download, subscriber or follower count for a podcast)'
average_rating:
type:
- integer
- 'null'
description: 'Spotify podcasts only: mean listener rating from 0 to 5. Fractional (e.g. 4.66) despite the integer type this schema emits for every numeric leaf'
creator_username:
type:
- string
- 'null'
description: String at author.ext.creator_username
join_policy:
type:
- string
- 'null'
description: String at author.ext.join_policy
is_nsfw:
type:
- boolean
- 'null'
description: Boolean at author.ext.is_nsfw
weekly_active_users:
type:
- integer
- 'null'
description: Numeric at author.ext.weekly_active_users
weekly_contributions:
type:
- integer
- 'null'
description: Numeric at author.ext.weekly_contributions
bio_link:
type:
- string
- 'null'
description: String at author.ext.bio_link
group:
type:
- string
- 'null'
description: Leaf at author.ext.group
_warnings:
type: array
description: 'Non-fatal notices about this response (field-map drift, clamped computed values). Advisory only: its presence never means the request failed. Omitted entirely when there is nothing to report, so treat absent as ''no warnings''.'
items:
type: string
description: One advisory notice.
credits_used:
type: integer
description: Number of credits consumed
credits_remaining:
type:
- integer
- 'null'
description: Current account balance. Null only when an idempotency replay succeeds but its transient balance lookup fails.
request_id:
type: string
description: Unique request identifier for support
cached:
type: boolean
description: Whether the response was served from cache
idempotent_replay:
type: boolean
description: True only when this response is an idempotency replay
required:
- success
- platform
- endpoint
- data
- credits_used
- credits_remaining
- request_id
- cached
'400':
$ref: '#/components/responses/Error400'
'401':
$ref: '#/components/responses/Error401'
'402':
$ref: '#/components/responses/Error402'
'404':
$ref: '#/components/responses/Error404'
'405':
$ref: '#/components/responses/Error405'
'409':
$ref: '#/components/responses/Error409'
'413':
$ref: '#/components/responses/Error413'
'422':
$ref: '#/components/responses/Error422'
'429':
$ref: '#/components/responses/Error429'
'500':
$ref: '#/components/responses/Error500'
'502':
$ref: '#/components/responses/Error502'
'503':
$ref: '#/components/responses/Error503'
/bluesky/user/posts:
get:
summary: List a Bluesky user's posts
description: 'Returns a feed of posts for a Bluesky user: uri, record text, author info, embeds, replyCount, repostCount, likeCount, quoteCount, and indexedAt. Pass either `handle` or `user_id` (Bluesky calls user IDs `did`).'
tags:
- bluesky
operationId: get_bluesky_user_posts
security:
- ApiKeyAuth: []
x-credit-tier: standard
x-credit-cost: 1
x-socialcrawl-oneOf:
- - handle
- user_id
parameters:
- name: handle
in: query
required: false
description: 'Bluesky handle. (one of: handle, user_id; at least one required)'
schema:
type: string
- name: user_id
in: query
required: false
description: 'Bluesky `did` (Bluesky''s internal user ID format, e.g. `did:plc:x7d6j54pm22ufehkes6jo4jf`). (one of: handle, user_id; at least one required)'
schema:
type: string
- name: Cache-Control
in: header
required: false
description: Send `no-cache` to bypass the response cache and force a live fetch. Billed at the normal endpoint cost; the fresh result is written back to cache for the next caller. Only the `no-cache` directive triggers this. See the Response Schema guide for details.
schema:
type: string
- name: Idempotency-Key
in: header
required: false
description: 'Optional UUID that makes the request safely retriable. A replay keeps the cached payload immutable except for billing metadata: `credits_used` becomes 0, `idempotent_replay` becomes true, and `credits_remaining` is refreshed to the current balance. A known current balance appears in both the body and `X-Credits-Remaining` header; no balance row resolves to 0. On a transient lookup failure, body `credits_remaining` is null and `X-Credits-Remaining` is omitted. Scoped per account with a 24-hour TTL.'
schema:
type: string
responses:
'200':
description: Successful response
headers:
X-Credits-Used:
description: Net credits charged for this response. Idempotency replays report 0.
schema:
type: integer
minimum: 0
X-Credits-Remaining:
description: Current balance when known. On an idempotency replay, this header is omitted when the balance lookup fails; body `credits_remaining` is null instead.
schema:
type: integer
minimum: 0
X-Idempotent-Replay:
description: Present with value `true` only when this response replays a settled idempotency record.
schema:
type: string
enum:
- 'true'
content:
application/json:
schema:
type: object
properties:
success:
type: boolean
description: Whether the request succeeded
platform:
type: string
description: Platform name
endpoint:
type: string
description: API endpoint path
data:
type: object
description: Platform-specific response data
properties:
items:
type: array
description: Array of canonical post wrappers ({ post, computed })
items:
type: object
description: Canonical post wrapper
properties:
post:
type: object
description: Canonical Post object (unified across all platforms)
properties:
id:
type: string
description: Platform-specific post ID (always a string; numeric upstream IDs are stringified)
url:
type:
- string
- 'null'
description: Direct URL to the post on the source platform
content:
type: object
description: Post content fields (text, media, thumbnail, duration)
properties:
text:
type:
- string
- 'null'
description: Post caption, description, or text content
media_urls:
type:
- string
- array
- 'null'
description: URL(s) of the primary media. Single string for video/photo posts; array of strings for carousels.
items:
type: string
description: URL(s) of the primary media. Single string for video/photo posts; array of strings for carousels.
thumbnail_url:
type:
- string
- 'null'
description: URL to thumbnail image
duration_seconds:
type:
- integer
- 'null'
description: Video/clip duration in seconds (null for non-video posts)
author:
type: object
description: Subset of Author fields for the post creator
properties:
username:
type:
- string
- 'null'
description: Author username
display_name:
type:
- string
- 'null'
description: Author display name
avatar_url:
type:
- string
- 'null'
description: URL to author profile picture
verified:
type:
- boolean
- 'null'
description: Whether the author account is verified
engagement:
type: object
description: Engagement counts
properties:
views:
type:
- integer
- 'null'
description: 'View count (if available). For Instagram video/reels this is the play count: the headline ''Views'' the IG app shows. Instagram removed per-post play counts from its public web pages in August 2026, so `GET /v1/instagram/post` now fills the count automatically from a second source within the same call: videos and reels keep a numeric `views` with no extra endpoint or workaround. Note: since mid-July 2026 Instagram''s play count is Instagram-only. It no longer includes Facebook crosspost views (Meta-side change; the app UI changed identically). For combined reach, also fetch the Facebook crosspost via `/v1/facebook/post`.'
likes:
type:
- integer
- 'null'
description: Like / reaction count
comments:
type:
- integer
- 'null'
description: 'Comment count. Note: on `GET /v1/instagram/post` this is Instagram''s `edge_media_to_parent_comment.count` (top-level comments); the IG list endpoints report the mobile `comme
# --- truncated at 32 KB (100 KB total) ---
# Full source: https://raw.githubusercontent.com/api-evangelist/socialcrawl/refs/heads/main/openapi/socialcrawl-bluesky-api-openapi.yml