## Pages
Ayrshare website pages, in Markdown:
- [Ayrshare Social Media API](https://www.ayrshare.com/index.md): The Ayrshare API lets you post, schedule, analyze, and manage engagement across 13+ social networks through a single integration. Includes publishing, history, analytics, moderation, and MCP servers for AI agents.
- [About Ayrshare](https://www.ayrshare.com/about.md): Ayrshare is a remote software company building the compliant, unified social media API other products rely on.
- [Ayrshare for AI Agents](https://www.ayrshare.com/ai-agent.md): Give your AI agents the full social loop. Ayrshare lets an agent learn a brand's voice, validate every post against each platform's rules, and publish across 13+ networks in one call — over MCP or the REST API.
- [The Share](https://www.ayrshare.com/blog.md): Read Ayrshare API guides, platform updates, and product notes.
- [Business Plan for Multiple Users](https://www.ayrshare.com/business-plan-for-multiple-users.md): Easy-to-integrate social media APIs let you manage all of your users' social accounts right from your product. Post, auto schedule, and analytics. Great for SaaS, CMS, DAM, agencies, and apps.
- [Meet our customers](https://www.ayrshare.com/case-study.md): See how AI products, SaaS platforms, agencies, and real-estate teams ship social publishing on Ayrshare.
- [Ayrshare Comparisons](https://www.ayrshare.com/compare.md): See how Ayrshare compares with social media APIs and dashboards.
- [Ayrshare vs Zernio](https://www.ayrshare.com/compare/ayrshare-vs-zernio.md): Ayrshare vs Zernio, side by side. Compare networks, History and Validation APIs, pricing models, reliability, and developer experience for embedding social posting into your product.
- [Ayrshare vs Buffer](https://www.ayrshare.com/compare/buffer-api-alternative.md): Ayrshare is a more advanced and affordable Buffer API alternative to post to your users' social media accounts.
- [Ayrshare vs Bundle.social](https://www.ayrshare.com/compare/bundle-social-api-alternative.md): Ayrshare is a more advanced and affordable Bundle.social API alternative to post to your users' social media accounts.
- [Cloud Campaign API Alternative](https://www.ayrshare.com/compare/cloud-campaign-api-alternative.md): Looking for a Cloud Campaign API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [Ayrshare vs Data365](https://www.ayrshare.com/compare/data365-api-alternative.md): Ayrshare is a more advanced and affordable Data365 API alternative to post to your users' social media accounts.
- [Ayrshare vs Hootsuite](https://www.ayrshare.com/compare/hootsuite-api-alternative.md): Ayrshare is a more advanced and affordable Hootsuite API alternative to post to your users' social media accounts.
- [Later Social Media API Alternative](https://www.ayrshare.com/compare/later-api-alternative.md): Looking for a Later social media API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [Loomly API Alternative](https://www.ayrshare.com/compare/loomly-api-alternative.md): Looking for a Loomly API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — the most advanced and affordable option.
- [Ayrshare vs Mallary](https://www.ayrshare.com/compare/mallary-api-alternative.md): Ayrshare is a more advanced and affordable Mallary API alternative to post to your users' social media accounts.
- [Metricool API Alternative](https://www.ayrshare.com/compare/metricool-api-alternative.md): Looking for a Metricool API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [Ayrshare vs OneAll](https://www.ayrshare.com/compare/oneall-alternative.md): Ayrshare is a more advanced and affordable OneAll API alternative to post to your users' social media accounts.
- [Ayrshare vs Outstand](https://www.ayrshare.com/compare/outstand-api-alternative.md): Ayrshare is a more advanced and affordable Outstand API alternative to post to your users' social media accounts.
- [Ayrshare vs Phyllo](https://www.ayrshare.com/compare/phyllo-api-alternative.md): Ayrshare is a more advanced and affordable Phyllo API alternative to post to your users' social media accounts.
- [Ayrshare vs Publer](https://www.ayrshare.com/compare/publer-api-alternative.md): Ayrshare is a more advanced and affordable Publer API alternative to post to your users' social media accounts.
- [Sendible API Alternative](https://www.ayrshare.com/compare/sendible-api-alternative.md): Looking for a Sendible API and white label alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [SocialOomph API Alternative](https://www.ayrshare.com/compare/socialoomph-api-alternative.md): Looking for a SocialOomph API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [SocialPilot API Alternative](https://www.ayrshare.com/compare/socialpilot-api-alternative.md): Looking for a SocialPilot API and bulk upload alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [Ayrshare vs Sprout Social](https://www.ayrshare.com/compare/sprout-social-api-alternative.md): Ayrshare is a more advanced and affordable Sprout Social API alternative to post to your users' social media accounts.
- [Ayrshare vs Twilio](https://www.ayrshare.com/compare/twilio-api-alternative.md): Ayrshare is a more advanced and affordable Twilio API alternative to post to your users' social media accounts.
- [Ayrshare vs Upload-Post](https://www.ayrshare.com/compare/upload-post-api-alternative.md): Ayrshare is a more advanced and affordable Upload-Post API alternative to post to your users' social media accounts.
- [Zoho Social API Alternative](https://www.ayrshare.com/compare/zoho-alternative.md): Looking for a Zoho Social API alternative? Ayrshare's social media API lets you publish, schedule, and manage posts across every major network — more advanced and more affordable.
- [Contact Ayrshare](https://www.ayrshare.com/contact.md): Talk to Ayrshare about social media API architecture, volume pricing, compliance, and BYOK onboarding.
- [The Social Media API for Creator Data](https://www.ayrshare.com/creator-data-api.md): Access powerful influencer marketing and creator capabilities with Ayrshare's Creator Data API. Easily gather essential social media account data.
- [Data Processing Agreement](https://www.ayrshare.com/data-processing-agreement.md): Ayrshare's GDPR-compliant Data Processing Agreement, including sub-processors, security, and international data transfer terms.
- [Submit a Feature Request](https://www.ayrshare.com/feature-request.md): Have an idea to improve the Ayrshare social media API? Submit a feature request or integration idea to help us build a better developer experience.
- [The Social Media History API](https://www.ayrshare.com/history-api.md): Retrieve past posts and engagement data across 13+ social networks with one API call, including posts published outside Ayrshare. Train AI on real brand voice, no cold start.
- [Instagram Banned Hashtag Checker](https://www.ayrshare.com/instagram-banned-hashtag-checker.md): Free Instagram banned hashtag checker. Paste your hashtags to instantly see which ones are banned or restricted before they get your account shadowbanned. Updated for 2026.
- [Bubble Integration](https://www.ayrshare.com/integration/bubble.md): Add social media publishing, analytics, and account management to your Bubble app with the Ayrshare Bubble plugin and API Connector.
- [Hurl Integration](https://www.ayrshare.com/integration/hurl.md): Test every Ayrshare endpoint from your terminal with the Ayrshare Hurl scripts for images, video, analytics, and more.
- [Notion Integration](https://www.ayrshare.com/integration/notion.md): Post to your social accounts from a Notion no-code database, pick platforms and media, and schedule directly inside your workflow.
- [Oracle Integration](https://www.ayrshare.com/integration/oracle.md): Post to all your social accounts from Oracle Content Management and extend OCM with Ayrshare analytics and historical data.
- [PyPI Integration](https://www.ayrshare.com/integration/pypi.md): Use the Social-Post-API PyPI package to call Ayrshare from Python on the server-side across Premium, Business, and Enterprise plans.
- [Social Media Auto Poster WordPress Plugin](https://www.ayrshare.com/integration/wordpress.md): Automatically publish your WordPress posts to all of your social media accounts with the official Ayrshare WordPress plugin.
- [Ayrshare Integrations](https://www.ayrshare.com/integrations.md): Connect Ayrshare with the platforms your team already uses. Schedule posts, pull analytics, add comments, and more through no-code tools, SDKs, and direct social network APIs.
- [Oracle Content Management Social Media Posting Guide](https://www.ayrshare.com/oracle-content-management-social-media-posting-guide.md): Step-by-step setup for publishing to social media from Oracle Content Management (OCM) with Ayrshare: link your accounts, configure the asset type, add the webhook, and publish across every network.
- [Ayrshare Pricing](https://www.ayrshare.com/pricing.md): Embed the Ayrshare Social Media API into your product and pay for active social profiles, not users, seats, or internal team members. As your customers connect social accounts, your usage grows with them. When a customer churns, your costs go back down.
- [Privacy Policy](https://www.ayrshare.com/privacy.md): Read Ayrshare's privacy policy and data handling practices.
- [Automatically Post Your Newsletter to Your Social Media](https://www.ayrshare.com/rss-feed-substack-socialmedia.md): Automatically Post Your Substack Newsletter to Your Social Media
- [Social Media Analytics API](https://www.ayrshare.com/social-media-analytics-api.md): Get real-time social media analytics through one API. Pull likes, shares, comments, impressions, video views, historical data, and link click analytics across 13+ networks.
- [Social Media Analytics Metrics](https://www.ayrshare.com/social-media-analytics-metrics.md): Ayrshare's Analytics API returns 715 metrics across 12 networks: retention curves, reaction breakdowns, demographics, story taps. The full reference.
- [Social Media Messaging API](https://www.ayrshare.com/social-media-messenger-apis.md): Get to market fast and scale effortlessly with the Ayrshare Messaging API for social media. Enable conversations that drive sales, engagement, and customer support across Facebook Messenger, Instagram, and X.
- [API Solutions](https://www.ayrshare.com/solutions.md)
- [Cross-Platform API Error 400: Duration & Metadata Validation Failed](https://www.ayrshare.com/solutions/cross-platform-api-error-400-duration-metadata-validation-failed.md): Posting one video to Instagram, YouTube, and TikTok at once triggers different duration and metadata errors on each. Ayrshare explains why, and the exact fix.
- [Google API Error 403: Unverified App & How to Fix the Audit Pipeline](https://www.ayrshare.com/solutions/google-api-error-403-unverified-app-how-to-fix-the-audit-pipeline.md): Google API Error 403 on an unverified app? See why the OAuth audit and quota sandbox happen, and how Ayrshare's pre-verified access skips it entirely for you.
- [Google Business API Error 403: Location Not Verified & How to Fix It](https://www.ayrshare.com/solutions/google-business-api-error-403-location-not-verified-how-to-fix-it.md): Google Business Profile posts failing with a 403 PERMISSION_DENIED? See why unverified locations get blocked and how Ayrshare handles the pre-flight check.
- [Handling TikTok Rate Limits: Resolving the 429 Too Many Requests Error](https://www.ayrshare.com/solutions/handling-tiktok-rate-limits-resolving-the-429-too-many-requests-error.md): TikTok enforces a strict sliding-window rate limit that can lock out bursty traffic instantly. Ayrshare explains the mechanics and exactly how to avoid a 429.
- [How to Bypass the YouTube 10k Unit Limit: Fixing the 403 Quota Exceeded Error](https://www.ayrshare.com/solutions/how-to-bypass-the-youtube-10k-unit-limit-fixing-the-403-quota-exceeded-error.md): YouTube's default 10,000 daily quota units allow only six video uploads before a 403 quotaExceeded error. Ayrshare explains why, and how to bypass it entirely.
- [How to Fix Instagram API Error 100: "Media ID Not Found" and "Unknown Error"](https://www.ayrshare.com/solutions/how-to-fix-instagram-api-error-100-media-id-not-found-and-unknown-error.md): Instagram API Error 100 is almost always a race condition between container creation and publishing. See why it happens and how Ayrshare prevents it for good.
- [How to Fix Meta Error 200: "Permissions Error" and Insufficient Scopes](https://www.ayrshare.com/solutions/how-to-fix-meta-error-200-permissions-error-and-insufficient-scopes.md): Meta Error 200 usually means Standard Access, a User Token instead of a Page Token, or a missing scope. Ayrshare explains the causes and how to fix each one.
- [Instagram API Error 10: Application Permission Denied & How to Fix Direct Publishing](https://www.ayrshare.com/solutions/instagram-api-error-10-application-permission-denied-how-to-fix-direct-publishing.md): Instagram API Error 10 means the connected account is Personal, not Business or Creator. Ayrshare explains the account-type rule and exactly how to handle it.
- [Instagram API Error 100: Carousel Validation Failed & How to Fix It](https://www.ayrshare.com/solutions/instagram-api-error-100-carousel-validation-failed-how-to-fix-it.md): Instagram carousel posts failing with Error 100 or invalid_children? See why nested container validation fails and how Ayrshare handles it automatically today.
- [Instagram Graph API Error 9: The 25-Post Daily Limit & How to Fix It](https://www.ayrshare.com/solutions/instagram-graph-api-error-9-the-25-post-daily-limit-how-to-fix-it.md): Instagram's Graph API caps publishing at 25 posts per rolling 24-hour window. See why Error 9 triggers and how Ayrshare manages the limit automatically for you.
- [LinkedIn 403: "Unpermitted Access" (URN Mismatches & Permissions)](https://www.ayrshare.com/solutions/linkedin-403-unpermitted-access-urn-mismatches-permissions.md): LinkedIn API 403 errors usually mean a person/organization URN mismatch or missing Marketing Developer Platform access. Ayrshare explains why, and the fix.
- [LinkedIn API Error 401: Invalid Grant & How to Fix Token Expiration](https://www.ayrshare.com/solutions/linkedin-api-error-401-invalid-grant-how-to-fix-token-expiration.md): LinkedIn access tokens expire after 60 days, triggering invalid_grant errors. Ayrshare explains the refresh flow and how to avoid manual token rotation today.
- [LinkedIn API v1 to v2 (Versioned) Migration: The Developer’s Survival Guide](https://www.ayrshare.com/solutions/linkedin-api-v1-to-v2-versioned-migration-the-developers-survival-guide.md): Migrating from LinkedIn's legacy API to the Versioned API (v2/rest)? Ayrshare covers the base URL, header, and payload changes, and how to avoid them entirely.
- [LinkedIn & Meta API Error 400: Invalid Image Dimensions & How to Fix It](https://www.ayrshare.com/solutions/linkedin-meta-api-error-400-invalid-image-dimensions-how-to-fix-it.md): LinkedIn and Meta reject images that don't match a 1.91:1 aspect ratio. Ayrshare explains the Invalid Image Dimensions error and how auto-resizing fixes it.
- [Meta Graph API Versioning Survival Kit: Staying Ahead of v21, v22, and Beyond](https://www.ayrshare.com/solutions/meta-graph-api-versioning-survival-kit-staying-ahead-of-v21-v22-and-beyond.md): Meta Graph API versions sunset on a 24-month clock, and Marketing API versions even faster. Ayrshare explains what breaks and how to stop tracking it yourself.
- [Meta & LinkedIn API Error 401: Expired Token & How to Fix It](https://www.ayrshare.com/solutions/meta-linkedin-api-error-401-expired-token-how-to-fix-it.md): Meta and LinkedIn access tokens expire on a strict TTL, and manual refresh workers can hit race conditions. Ayrshare explains why, and how to avoid it entirely.
- [Meta & Stripe API Error 401: Signature Mismatch & How to Fix Webhook Security](https://www.ayrshare.com/solutions/meta-stripe-api-error-401-signature-mismatch-how-to-fix-webhook-security.md): Getting a 401 or Signature Verification Failed on your Meta webhook? See why raw-body hashing fails and how Ayrshare's unified webhook signature simplifies it.
- [Meta & X API Error 429: Polling Rate Limits & How to Fix Event Syncing](https://www.ayrshare.com/solutions/meta-x-api-error-429-polling-rate-limits-how-to-fix-event-syncing.md): Polling Meta or X for updates instead of using webhooks triggers 429 errors fast. Ayrshare explains the webhook alternative and how to secure it the right way.
- [Moving from Twitter v1.1 to v2: Bridging the “JSON Gap”](https://www.ayrshare.com/solutions/moving-from-twitter-v1-1-to-v2-bridging-the-json-gap.md): Migrating from Twitter API v1.1 to X API v2 breaks JSON structure, auth, and media uploads. Ayrshare explains the changes and how to avoid them today for you.
- [Pinterest API v5 Transition: The Complete Developer Guide](https://www.ayrshare.com/solutions/pinterest-api-v5-transition-the-complete-developer-guide.md): Everything you need to migrate from Pinterest API v4 to v5 — board access, refresh tokens, SDK setup, and how Ayrshare handles the complexity for you. Why You Need to Migrate to Pinterest API v5 If you are building or maintaining a social media scheduling tool, analytics dashboard, or any automation that touches Pinterest, you…
- [Social Media API Error 400: Media Validation Failed & How to Fix Video Encoding](https://www.ayrshare.com/solutions/social-media-api-error-400-media-validation-failed-how-to-fix-video-encoding.md): Video uploads failing with a 400 Media Validation error? See the four codec, bitrate, and resolution rules platforms enforce, and how Ayrshare auto-fixes them.
- [TikTok API 400: "Bad Request" (Encoding & Validation)](https://www.ayrshare.com/solutions/tiktok-api-400-bad-request-encoding-validation.md): TikTok API 400 errors are almost always video validation failures: bitrate, aspect ratio, duration, or codec. Ayrshare's autoResize fixes them automatically.
- [TikTok API Error 10001: The Silent Shadowban & How to Fix It](https://www.ayrshare.com/solutions/tiktok-api-error-10001-the-silent-shadowban-how-to-fix-it.md): TikTok Error 10001 means bot detection has silently shadowbanned your app. Ayrshare explains exactly why it happens and how trusted infrastructure avoids it.
- [TikTok & Meta API Error 400: Invalid Cover Asset & How to Fix Video Thumbnails](https://www.ayrshare.com/solutions/tiktok-meta-api-error-400-invalid-cover-asset-how-to-fix-video-thumbnails.md): TikTok, Meta, and YouTube each require a completely different video cover format. Ayrshare explains why, and how one thumbUrl works across all three platforms.
- [Twitter/X Error 403: "Forbidden" (Tier Access & Scopes)](https://www.ayrshare.com/solutions/twitter-x-error-403-forbidden-tier-access-scopes.md): X API 403 errors usually trace back to your paid tier, read-only app permissions, or a v1.1/v2 endpoint mismatch. Ayrshare explains each cause and the fix.
- [X & LinkedIn API Error 400: Invalid Media Metadata & How to Fix Alt-Text](https://www.ayrshare.com/solutions/x-linkedin-api-error-400-invalid-media-metadata-how-to-fix-alt-text.md): Adding image alt-text to X or LinkedIn posts triggers a 400 if the timing or JSON structure is off. Ayrshare explains the fix, or generates alt-text for you.
- [X & LinkedIn API Error 400: Text Validation Failed & How to Fix Character Limits](https://www.ayrshare.com/solutions/x-linkedin-api-error-400-text-validation-failed-how-to-fix-character-limits.md): Standard string length checks fail on X and LinkedIn because of link wrapping and URN weighting. Ayrshare explains the real character math, and the exact fix.
- [X (Twitter) API Error 403: Duplicate Post & How to Fix It](https://www.ayrshare.com/solutions/x-twitter-api-error-403-duplicate-post-how-to-fix-it.md): X blocks posts with matching content hashes for up to 12 hours. Ayrshare explains the anti-spam mechanics and exactly how to safely post repeat content again.
- [X (Twitter) API Error 429: The Monthly Tweet Cap & How to Fix It](https://www.ayrshare.com/solutions/x-twitter-api-error-429-the-monthly-tweet-cap-how-to-fix-it.md): You’re monitoring your logs and everything looks perfectly normal. Your 15-minute rate limits are completely healthy, and your OAuth tokens are fresh. Then, out of nowhere, the X (formerly Twitter) API starts rejecting every single publish request with an aggressive HTTP 429 Too Many Requests response. You haven’t breached a speed limit. You’ve slammed into…
- [Terms of Use](https://www.ayrshare.com/terms.md): Read the Ayrshare Terms of Use governing accounts, subscriptions, site access, and acceptable use.
- [Ayrshare for AI Startups](https://www.ayrshare.com/use-cases/ai-startups.md): The AI-native social media API that gives your agents everything they need to operate on social platforms: learn a brand's voice, publish across 13+ networks, measure, and stay compliant.
- [Ayrshare for Content Creator Platforms](https://www.ayrshare.com/use-cases/content-creator-platforms.md): The multi-tenant social media API behind creator platforms: let every creator publish, schedule, and analyze across 13+ networks, with isolated profiles proven at 25M+ daily API calls.
- [Ayrshare for Digital Agencies](https://www.ayrshare.com/use-cases/digital-agencies.md): The white-label social media API agencies use to launch their own branded client tools. Publish, schedule, analyze, and manage engagement across 13+ networks for hundreds of client accounts through one API.
- [Ayrshare for SaaS Platforms](https://www.ayrshare.com/use-cases/saas-platforms.md): The embedded social media API for vertical SaaS. Add publishing, scheduling, analytics, and engagement across 13+ networks for thousands of your customers' accounts, with multi-tenant architecture handled for you.
- [Ayrshare for Video Content Platforms](https://www.ayrshare.com/use-cases/video-content-platforms.md): Your platform creates the video. Ayrshare publishes it, short- and long-form, to YouTube, TikTok, Reels, and more in a single call, then pulls analytics back. One API for the full publishing and feedback lifecycle across 12 of 13 networks.
## Case Studies
Ayrshare customer case studies, in Markdown:
- [How Curbfeed Onboards a Brokerage in About a Minute Without Building a Social Platform Layer](https://www.ayrshare.com/case-study/curbfeed-real-estate.md): See how Curbfeed, a real estate marketing platform, runs its entire automated office-level publishing pipeline on Ayrshare.
- [How Quso.ai Scaled to 4M Users Without a Single Engineer on Social API Maintenance](https://www.ayrshare.com/case-study/vidyo-ai.md): Find out how Quso.ai (formerly Vidyo.ai), an AI video platform serving 4M+ users, has run its entire social publishing stack on Ayrshare since January 2022.
## Blog
Every Ayrshare blog post, in Markdown:
- [n8n Social Media Automation: Three Ways to Do It (and When You Need an AI Agent)](https://www.ayrshare.com/blog/n8n-social-media-automation.md): Three ways to run social media out of n8n: per-platform nodes, one REST call to a social media API, or an AI agent over MCP (and when each one fits)
- [Ayrshare Is Now Native in Claude Code](https://www.ayrshare.com/blog/ayrshare-claude-code-plugin.md): An AI agent can now take a social post from draft to published across 13+ networks, with no per-platform integration code.
- [Instagram Engagement Automations, Now in the Ayrshare API](https://www.ayrshare.com/blog/instagram-engagement-automations-ayrshare-api.md): The Ayrshare API now supports Instagram engagement automations: keyword-triggered DMs, webhooks, and emails that comply with Meta's policies.
- [Is Your Social Media API Compliant with X’s Developer Policies?](https://www.ayrshare.com/blog/x-api-compliance-byo-app.md): X requires every third-party social media API to operate under a BYO model. Here's what that means and what compliant implementation looks like.
- [Publish and Monetize X Video Content in One Workflow with Ayrshare](https://www.ayrshare.com/blog/monetize-x-video-with-ayrshare.md): Monetize your video content on X directly from your publishing workflow. With Ayrshare’s API, there’s no need to switch to Media Studio.
- [Instagram Analytics Data in Ayrshare: A Product Manager’s Guide](https://www.ayrshare.com/blog/instagram-analytics-data-in-ayrshare-for-product-managers.md): Everything product managers need to know about Instagram analytics in Ayrshare: what each data type does and how to build better features.
- [Coding with Multiple AI Agents to Build Scalable Rate-Limiting Infrastructure](https://www.ayrshare.com/blog/coding-with-multiple-ai-agents.md): How Ayrshare used ChatGPT, Claude Code, Gemini, and Ralph loops to refactor rate limits into a scalable, enterprise-ready policy engine.
- [Threads API Integration: Authorization, Posting, & Analytics with Ayrshare](https://www.ayrshare.com/blog/threads-api-integration-authorization-posting-analytics-with-ayrshare.md): How to integrate Meta's Threads API into your platform. Easily manage your users' Threads accounts via Ayrshare's social API.
- [Unlocking Real-Time Engagement with X Account Activity API via Ayrshare](https://www.ayrshare.com/blog/unlocking-real-time-engagement-with-x-account-activity-api-via-ayrshare.md): Unlock real-time engagement on X (formerly Twitter) using the Account Activity API, easily integrated via Ayrshare's powerful social media API.
- [Implementing Multi-User Social Account Linking with Ayrshare](https://www.ayrshare.com/blog/implementing-multi-user-social-account-linking-with-ayrshare.md): Learn how to allow your users to link their social media accounts and manage these accounts using the social media API.
- [Complete Guide to Handling API Rate Limits: Prevent 429 Errors](https://www.ayrshare.com/blog/complete-guide-to-handling-rate-limits-prevent-429-errors.md): Build robust client-side rate limiting for APIs with our 4-step JavaScript guide. Prevent 429 errors, implement retry logic, & more.
- [Complete Guide to Snapchat API Integration: Authorization, Posting, & Analytics with Ayrshare](https://www.ayrshare.com/blog/complete-guide-to-snapchat-api-integration.md): The Snapchat API guide. How to integrate with Snapchat from authorizing, to publishing, to getting analytics.
- [Make’s X (formerly Twitter) Integration Has Ended — Here’s a Better Alternative](https://www.ayrshare.com/blog/make-coms-x-integration-alternative.md): Make.com has deprecated its X (Twitter) integration. Use Ayrshare's social media API as an X automation alternative.
- [Ayrshare Social Account Linking Page Customization Demo Video](https://www.ayrshare.com/blog/ayrshare-social-account-linking-page-customization-demo-video.md): Watch a demo video on how to customize the Ayrshare Social Account Linking page. Whitelabel the experience to perfectly match your platform's brand.
- [Facebook Ads API: Boosting Facebook Posts with the Marketing API](https://www.ayrshare.com/blog/facebook-ads-api-boosting-with-the-marketing-api.md): Use the Facebook Ads API (Marketing API) to create boosted paid post directly from organic posts. Retrieve ad spend, clicks, and impressions.
- [Instagram Demographics 2025: Key Audience Insights and Statistics](https://www.ayrshare.com/blog/instagram-demographics-2025-key-audience-insights-and-statistics.md): This guide provides a deep dive into the latest demographics on Instagram, including geographic, education, income, and gender distributions.
- [How to Get Direct Download URLs from Dropbox](https://www.ayrshare.com/blog/how-to-get-direct-download-urls-from-dropbox.md): Learn how to transform Dropbox sharing links into direct download URLs for seamless integration with your applications and APIs.
- [Top 10 Social Media APIs for Developers](https://www.ayrshare.com/blog/top-10-social-media-apis-for-developers.md): The top social media APIs developers integrate with Bluesky, Facebook, Instagram, X, LinkedIn, Pinterest, Reddit, TikTok, Telegram, YouTube.
- [How to Get Direct Download URLs from Google Drive](https://www.ayrshare.com/blog/how-to-get-direct-download-urls-from-google-drive.md): Learn how to convert Google Drive sharing links into direct download URLs for programmatic access and API integrations. With code examples.
- [HTTP Compression in Node.js: A Dive into Gzip, Deflate, and Brotli](https://www.ayrshare.com/blog/http-compression-in-node-js-a-dive-into-gzip-deflate-and-brotli.md): Reduce API payload size in Node.js using Gzip, Deflate, and Brotli compression. A guide with code examples and algorithm benchmarks.
- [How to Retrieve Social Media Posts For All Your Users with an API](https://www.ayrshare.com/blog/how-to-retrieve-social-media-posts-for-all-your-users-with-an-api.md): How to Retrieve Social Media Posts For All Your Users with an API
- [Complete Guide to Bluesky API Integration: Authorization, Posting, Analytics & Comments](https://www.ayrshare.com/blog/complete-guide-to-bluesky-api-integration-authorization-posting-analytics-comments.md): Learn how to integrate social media functionality with the Bluesky API in this comprehensive guide. Explore authentication, post publishing, analytics, comment management, and more to enhance your app or business.
- [Get Social Media Post Analytics with Make & Ayrshare – A No-Code Quick Video Tutorial](https://www.ayrshare.com/blog/get-social-media-post-analytics-with-make-ayrshare-a-no-code-quick-tutorial.md): Watch this quick no-code tutorial to learn how to retrieve social media post analytics automatically using Make (Integromat) and Ayrshare.
- [Testing Your Social Posting Integration With Random Content](https://www.ayrshare.com/blog/testing-your-social-posting-integration-with-random-content.md): Learn how to test your social media posting API integration using random text and image content to ensure a seamless setup before going live.
- [Never Miss a Comment Again: How to Use Ayrshare’s Comments API Endpoint](https://www.ayrshare.com/blog/never-miss-a-comment-again-how-to-use-ayrshares-comments-api-endpoint.md): Learn how to use Ayrshare's API Comment Endpoint to publish, reply, delete, hide comments on TikTok, Facebook, Instagram, LinkedIn, YouTube.
- [Create an API Proxy Server for No-Code](https://www.ayrshare.com/blog/create-an-api-proxy-server-for-no-code.md): Create a serverless API proxy sever for your no-code application that allows you to transform the API data response.
- [10 Recent Enhancements to the Ayrshare Dashboard](https://www.ayrshare.com/blog/10-recent-enhancements-to-the-ayrshare-dashboard.md): Recent enhancements to Ayrshare Social Media API Dashboard.
- [Ayrshare Reviews](https://www.ayrshare.com/blog/ayrshare-reviews.md): What you should look for when evaluating reviews for a potential SaaS partner, including Ayrshare Reviews.
- [Top 7 Social Sign-On APIs For 2024](https://www.ayrshare.com/blog/top-7-social-login-apis.md): Reduce the friction of login, increase security with the top social sign-on APIs: Facebook, Google, X, and GitHub.
- [Ayrshare Launches Messaging API for Facebook, Instagram, and X Direct Messages](https://www.ayrshare.com/blog/ayrshare-launches-messaging-api-for-facebook-instagram-and-x-direct-messages.md): Ayrshare's social media API now included the Messaging API for Facebook Messenger, Instagram Message, and X DMs.
- [Best Practices for API Design](https://www.ayrshare.com/blog/best-practices-for-api-design.md): Learn how to create a superior API design. The best strategies for creating scalable, secure, and developer-friendly APIs.
- [Build a Social Media Posting App with No Code](https://www.ayrshare.com/blog/build-a-social-media-posting-app-with-no-code.md): Watch our step-by-step tutorial on how to build your own social media posting web app using no-code platforms and the Ayrshare API.
- [How to Query for Non-Existent Fields in Firestore](https://www.ayrshare.com/blog/how-to-query-for-non-existent-fields-in-firestore.md): How do you query Firebase's Firestore database for non-existent field? While there is no direct way, so work-arounds exist.
- [5 Tips for Great Developer API Docs](https://www.ayrshare.com/blog/5-tips-for-great-developer-api-docs.md): The 5 top tips on how to write great developer API docs. With this guide you'll learn how to get developers excited about your API.
- [Ayrshare Messaging API for Facebook, Instagram, and X/Twitter](https://www.ayrshare.com/blog/ayrshare-messaging-api-for-facebook-instagram-and-x-twitter.md): Ayrshare Messaging API for real-time direct messaging on Facebook, Instagram, and X/Twitter. Easily end and received DMs.
- [User Profile Tagging in Ayrshare](https://www.ayrshare.com/blog/user-profile-tagging-in-ayrshare.md): Learn how to enable user profile tagging in your social media posts using Ayrshare's API. Tag users across multiple social networks seamlessly.
- [Understanding the Ayrshare Auto-Schedule API Endpoint](https://www.ayrshare.com/blog/understanding-the-ayrshare-auto-schedule-api-endpoint.md): Auto schedule your social media post via an API. Automate the scheduling of posts with set pre-defined posting times and days.
- [Why Do I Have to Test Your Code? (The 5-Minute Sniff Test)](https://www.ayrshare.com/blog/why-do-i-have-to-test-your-code-the-5-minute-sniff-test.md): If you can’t spend 5 minutes testing your work, then don’t make me. Why an software engineer need to test before handing to QA.
- [The Top 5 Chakra UI Tips and Tricks for React Developers](https://www.ayrshare.com/blog/the-top-5-chakra-ui-tips-and-tricks-for-react-developers.md): If you're using Chakra UI with React, here are our top 5 tips and trick getting the most of out Chakra UI.
- [Get Public Social Media Analytics, A No Code Tutorial Video](https://www.ayrshare.com/blog/get-public-social-media-analytics-a-no-code-tutorial-video.md): Follow this no-code video tutorial to easily gather public social media analytics from multiple networks using the Ayrshare API.
- [Facebook Removes Groups API Access: Impact and Implications](https://www.ayrshare.com/blog/facebook-removes-groups-api-access-impact-and-implications.md): Facebook has announced that it will remove access to its Groups API. We discuss the impact and implications.
- [Instagram Collaborator API](https://www.ayrshare.com/blog/instagram-collaborator-api.md): Add collaborators to Instagram posts using an API. These posts will show in the collaborator's feed and be sent to their followers.
- [Best Social Media Posting and Scheduling APIs of 2024](https://www.ayrshare.com/blog/best-social-media-posting-and-scheduling-apis.md): A list of the 6 best social media APIs from 3rd party scheduling tools for posting, analytics, and comments.
- [Reviews API: Review Management with an API](https://www.ayrshare.com/blog/reviews-api-review-management-with-an-api.md): Reviews management with the Reviews API. Easily manage your Facebook Page and Google Business Profile review with an API.
- [Instagram Banned Hashtags to Avoid (Updated 2026)](https://www.ayrshare.com/blog/avoid-using-these-instagram-banned-hashtags.md): The definitive list of Instagram banned hashtags to avoid so your account isn't locked or shadow banned. Originally published February 2024, updated for 2026.
- [What is a Webhook? How They Work With Examples](https://www.ayrshare.com/blog/what-is-a-webhook-how-they-work-with-examples.md): What is a webhook and how do they work? Learn all about webhooks from registering a webhook URL to calling a webhook.
- [TikTok API : How to Post and Get Analytics Using the TikTok API](https://www.ayrshare.com/blog/tiktok-api-how-to-post-and-get-analytics.md): How to use the TikTok API to publish posts and get analytics for your users.
- [Ayrshare Quick Start Guide [video]](https://www.ayrshare.com/blog/ayrshare-quick-start-guide-video.md): We take you through the Ayrshare Quick Start Guide to explain how to get started with the Ayrshare social media API.
- [How to Use Firebase Queues](https://www.ayrshare.com/blog/how-to-use-firebase-queues.md): What are Firebase Queues? And how do we use them?
- [Streamlining Webhook Development: How a Webhook Proxy Tool Can Transform Your Workflow](https://www.ayrshare.com/blog/streamlining-webhook-development-how-a-webhook-proxy-tool-can-transform-your-workflow.md): How to use a webhook relay proxy to simplify local webhook development and testing.
- [Instagram Stories API: How to Publish a Story](https://www.ayrshare.com/blog/instagram-stories-api-how-to-post-a-story.md): We are excited to announce Ayrshare as the only API-first platform to offer direct posting to Instagram Stories via an API.
- [Automatically Import All Your Social Media Analytics | No Code Tutorial Video](https://www.ayrshare.com/blog/automatically-import-all-your-social-media-analytics-no-code-tutorial-video.md): Learn how to use no-code Parabola and Ayrshare to get Facebook and X/Twitter social media analytics into a Google Sheet.
- [How to Publish Stories with the Facebook Stories API](https://www.ayrshare.com/blog/how-to-publish-stories-with-the-facebook-stories-api.md): Learn how to publish Facebook Stories, both video and photos, using the Meta Stories API.
- [Connect Your Social Accounts and Post via the Ayrshare Dashboard [video]](https://www.ayrshare.com/blog/connect-your-social-accounts-and-post-via-the-ayrshare-dashboard-video.md): Learn how to connect your social media accounts, then create a video post which goes out to 5 social networks.
- [Google Business Profile: What is GBP, Why You Need It, and How to Use It?](https://www.ayrshare.com/blog/google-my-business-what-is-gmb-why-you-need-it-and-how-to-use-it.md): Google Business Profile is a powerful SEO tool for businesses. Find out what GBP is, why you need it, and how to use it with an API.
- [Automatically Generate Image Caption Text Using Google Cloud Vision API with JavaScript and Node.js](https://www.ayrshare.com/blog/automatically-generate-image-caption-text-using-google-cloud-vision-api-with-javascript-and-node-js.md): Learn how to use the Google Cloud Vision API to generate image captions automatically and alt text, with code examples in JavaScript.
- [Navigating the Intricacies of Social Media API Integration: Top 5 Challenges and How to Overcome Them](https://www.ayrshare.com/blog/navigating-the-intricacies-of-social-media-api-integration-top-5-challenges-and-how-to-overcome-them.md): What are the top social media API challenges? Learn how to navigate these challenges and easily integrate with the social networks.
- [Max Pack: Take Your Social Media Marketing to the Next Level](https://www.ayrshare.com/blog/max-pack-take-your-social-media-marketing-to-the-next-level.md): The Max Pack is a powerful add-on to the Ayrshare Social API with even more capabilities to automate and improve your media marketing.
- [The Importance of Alt Text: Making Images Accessible and SEO-Friendly](https://www.ayrshare.com/blog/the-unseen-importance-of-alt-text-making-images-accessible-and-seo-friendly.md): Learn why adding alt text to your website's images is crucial for accessibility and SEO + how to automatically generate alt text with an API.
- [Build a Social Media Posting App in No-Code Platform FlutterFlow](https://www.ayrshare.com/blog/build-a-social-media-posting-app-in-no-code-platform-flutterflow.md): Learn how to use no-code Flutterflow to build a social media posting app that publishes both text and images.
- [Leveraging Ayrshare: Go Beyond Basic Social Media API Integration](https://www.ayrshare.com/blog/leveraging-ayrshare-go-beyond-basic-social-media-api-integration.md): Learn why Ayrshare's social media APIs are often the right choice over directly integrating social APIs such the TikTok API or Instagram API.
- [Rewrite Your Text with AI and Post to Your Social Networks [Video]](https://www.ayrshare.com/blog/rewrite-your-text-with-ai-and-post-to-your-social-networks-video.md): Learn of to use Ayrshare and no-code Bubble.io to build a AI rewriting and social posting app.
- [How to Schedule Twitter Threads with the Twitter API](https://www.ayrshare.com/blog/how-to-schedule-twitter-threads-with-the-twitter-api.md): How to schedule your Twitter threads using the Twitter API with JavaScript and Node.js.
- [The Instagram API Just Went to 11](https://www.ayrshare.com/blog/the-instagram-api-just-went-to-11.md): Instagram just updated their API with Creator account publishing, increase posting limit, user tagging, audio naming, and cover images.
- [Artificial Intelligence Anxiety Around the U.S.](https://www.ayrshare.com/blog/ai-anxiety-around-the-us.md): The use of AI has been a hot topic since ChatGPT's release in 2022. Find out what Americans have to say about their fears surrounding AI at work here.
- [Transcribe Your Audio or Video File, Summarize it, and Post it to Social in 4 Easy API Calls [video]](https://www.ayrshare.com/blog/transcribe-your-audio-or-video-file-summarize-it-and-post-it-to-social-in-4-easy-api-calls-video.md): Transcribe Your Audio or Video File, Summarize it, and Post it to Social in 4 Easy API Calls
- [Ayrshare Unleashes Game-Changing Integrations for TikTok Direct Video Publishing & Twitter Enterprise API](https://www.ayrshare.com/blog/ayrshare-unleashes-game-changing-integrations-for-tiktok-direct-video-publishing-twitter-enterprise-api.md): Ayrshare announced 65 new features across the 10 most popular social networks including special API access to direct TikTok posting.
- [Build A Twitter Analytics App in Retool [video]](https://www.ayrshare.com/blog/build-a-twitter-analytics-app-in-retool-video.md): Build A Twitter Analytics App in Retool
- [Introducing TikTok Direct Publishing, Analytics, and Commenting](https://www.ayrshare.com/blog/introducing-tiktok-direct-publishing-analytics-and-commenting.md): Ayrshare now has automatic TikTok publishing, advanced post analytics, and managing comments with the TikTok API.
- [The Best Hashtag Generator and Research Tools](https://www.ayrshare.com/blog/the-7-best-hashtag-generator-and-research-tools.md): Hashtags help reach your target audience. These are the best tools to generate the relevant hashtags for your social media posts.
- [Creating Social Media Posts with ChatGPT API](https://www.ayrshare.com/blog/creating-social-media-posts-with-chatgpt-api.md): How to use the ChatGPT API to post to social media networks such as Instagram and Facebook. Combine AI with automated social posting.
- [Facebook API: How to Post and Get Analytics Using the Facebook API](https://www.ayrshare.com/blog/facebook-api-how-to-post-and-get-analytics-using-the-facebook-api.md): Learn how the Facebook API can enhance your business and how to post or get analytics from your platform or app on behalf of your users.
- [Understanding the Difference Between the Instagram Business, Creator, and Personal Profiles](https://www.ayrshare.com/blog/understanding-the-difference-between-the-instagram-business-creator-and-personal-profiles.md): What is the difference between the Instagram Business, Creator, and Personal Profiles, when do you want to use each, and what are the considerations when using the Instagram API.
- [Speed Up Firebase Cold Starts with Firestore REST Calls](https://www.ayrshare.com/blog/speed-up-firebase-cold-starts-with-firestore-rest-calls.md): Firestore now has the preferRest option to speed up Firebase cold start up times. Here is how to use the new feature.
- [Schedule Social Media Posts from Notion](https://www.ayrshare.com/blog/schedule-social-media-posts-from-notion.md): Discover how to automatically schedule and publish your social media posts directly from a Notion database using Ayrshare's no-code integrations.
- [Google Business Profile: Own The Search Results For Your Business](https://www.ayrshare.com/blog/google-business-profile-own-the-search-results-for-your-business.md): Understand what is a Google Business Profile and why it is important for your business, plus how to post using an API.
- [The Free Video Metadata Inspector](https://www.ayrshare.com/blog/the-free-video-metadata-inspector.md): Inspect remote video files easily with our free video metadata inspector tool. Analyze dimensions, codecs, and formats for optimal social media posting.
- [Post To Social Media From Your Website Form Using Make & Ayrshare [video]](https://www.ayrshare.com/blog/post-to-social-media-from-your-website-form-using-make-ayrshare-video.md): A no-code video tutorial which explains how you can post to your user's social media accounts using Make and Ayrshare's social API.
- [Twitter Bans Link In Bio Pages & Social Media Link Aggregators [updated]](https://www.ayrshare.com/blog/twitter-bans-link-in-bio-pages-social-media-link-aggregators.md): Twitter new policy bans social media aggregators and posting link to other social sites such as Facebook and Instagram.
- [How to Enhance Firebase Emulator Logs](https://www.ayrshare.com/blog/how-to-enhance-firebase-emulator-logs.md): Firebase emulator console logging is pretty basic. Enhance the output with color, formatting, and quiet (remove system output).
- [LinkedIn API: How to Post and Get Analytics With the LinkedIn API](https://www.ayrshare.com/blog/how-to-post-and-get-analytics-with-the-linkedin-api.md): Discover how the LinkedIn API can help your clients’ businesses by letting you post and get analytics directly from your platform or app on behalf of your clients.
- [What is a Link In Bio Page?](https://www.ayrshare.com/blog/what-is-a-link-in-bio-page.md): But what does "link in bio" mean and why has it become such a prevalent tool for social media users?
- [HURL: Run and Test HTTP API Requests](https://www.ayrshare.com/blog/hurl-run-and-test-http-api-requests.md): Hurl: run and test API request via the command line. Here is how to use Hurl with real example calling a social media API.
- [Twitter API: How to Post and Get Analytics With the Twitter API](https://www.ayrshare.com/blog/twitter-api-how-to-post-and-get-analytics-with-the-twitter-api.md): How to Post and Get Analytics With the Twitter API
- [Build A Social Profile Analytics App with Bubble and Ayrshare [video]](https://www.ayrshare.com/blog/build-a-social-profile-analytics-app-with-bubble-and-ayrshare-video.md): A no-code tutorial that explains how to build your own social media profile analytics app with the Bubble web app builder and the Ayrshare social media API.
- [What Happened to the Buffer API?](https://www.ayrshare.com/blog/what-happened-to-buffers-api.md): If you want to post to social networks, you need an API What happened to the Buffer API and what are the alternative APIs for social?
- [Getting Started with Retool: Build A Social Media Posting App With No-Code [Video]](https://www.ayrshare.com/blog/build-a-social-media-posting-app-with-retool-video.md): In this video we will show how an agency or a marketing team can build their own social media management system using Retool a no-code tool.
- [Auto Create Real Estate Social Media Images Via a Template API](https://www.ayrshare.com/blog/automatically-create-real-estate-social-media-images-via-an-api.md): With Ayrshare, you can automatically create great images and post the image to your social media accounts using a social media template API.
- [Ayrshare Reinvents Social Media Integrations With New Social Media API Features [Press Release]](https://www.ayrshare.com/blog/ayrshare-reinvents-social-media-integrations-with-new-social-media-api-features-press-release.md): Ayrshare, the leading social media API provider, announced that it has released over 50 new major features, available immediately to the thousands of businesses globally who rely on Ayrshare to power their platform.
- [Facebook Reels API: How to Post Facebook Reels Using a Social Media API](https://www.ayrshare.com/blog/facebook-reels-api-how-to-post-fb-reels-using-a-social-media-api.md): How to use the Facebook Reels API to post short form videos. Learn how a social media API can make Reels integration easy.
- [Which social media platform is best for attracting B2B clients?](https://www.ayrshare.com/blog/which-social-media-platform-is-best-for-attracting-b2b-clients.md): Let’s help you find the best social media platform for business-to-business (B2B) by weighing the pros and cons of each social media network.
- [Get All Your Users Posting To Their Social Accounts on Bubble.io [video]](https://www.ayrshare.com/blog/get-all-your-users-posting-to-their-social-accounts-on-bubble-io-video.md): If you are using the Social API Business Plan or Enterprise Plan, this video shows you how to set up Bubble.io to enable all your users to link their social accounts.
- [Automatically Post To Social Media From Airtable](https://www.ayrshare.com/blog/automatically-post-to-social-media-from-airtable.md): A demo of how to use Airtable and two additional no-code tools to build your own social media posting application, Twitter and LinkedIn.
- [10 Tips for Using Hashtags Effectively on Facebook, Twitter & Instagram](https://www.ayrshare.com/blog/10-tips-for-using-hashtags-effectively-on-facebook-twitter-instagram.md): Hashtags are an essential tool for social media marketers. Learn 10 tips for using hashtags effectively in this post!
- [What is an API? A Comprehensive Beginner’s Guide And Mini Tutorial](https://www.ayrshare.com/blog/what-is-an-api-a-comprehensive-beginners-guide-and-mini-tutorial.md): What is an API and how do you make API calls? Learn the importance of an API and how to use Postman to make API requests.
- [Instagram Reels API: How to Post Videos to Reels Using a Social Media API](https://www.ayrshare.com/blog/instagram-reels-api-how-to-post-videos-to-reels-using-a-social-media-api.md): How to post Reels to Instagram using an API. Instagram recently updated their API to allow posting reel videos to Reels.
- [How to Sequentially Resolve an Array of Promises in JavaScript](https://www.ayrshare.com/blog/how-to-sequentially-resolve-an-array-of-promises-in-javascript.md): Sometimes you need to process an array of Promises in sequence. Here is how to do it in JavaScript with a for loop.
- [Introducing Twitter Notes: Long Form Essays Up to 2,500 Words + Edits](https://www.ayrshare.com/blog/twitter-notes-long-form-essays.md): Twitter has released a new post type for long form writing. Twitter Notes long form written essays allow up to 2,500 words and editing.
- [Announcing The Ayrshare WordPress Plugin](https://www.ayrshare.com/blog/announcing-the-ayrshare-wordpress-plugin.md): Announcing the Ayrshare Wordpress plugin for posting to all your social media accounts: Instagram, Facebook, Twitter, and more.
- [5 Types of Social Media Content That Convert Traffic Into Customers](https://www.ayrshare.com/blog/5-types-of-social-media-content-that-convert-traffic-into-customers.md): How do you convert traffic into customers? Here are 5 Types of Social Media Content that will do the trick.
- [Get Social Media Analytics with the Ayrshare API (Video)](https://www.ayrshare.com/blog/get-social-media-analytics-with-the-ayrshare-api-video.md): In this one minute video see how it easy it is to get the post analytics from all of the social networks: Instagram, TikTok, and Facebook.
- [Social Media Demographics Comparison](https://www.ayrshare.com/blog/social-media-demographics-comparison.md): Social media demographics are important when you are putting your marketing strategy. Learn how to approach each social network.
- [Best Times & Frequency to Post on Social Media Networks](https://www.ayrshare.com/blog/best-times-frequency-to-post-on-social-media-networks.md): These are the best times to publish on Instagram, Twitter, Facebook and LinkedIn!
- [Proven Social Media Content Strategies With Examples from Brands](https://www.ayrshare.com/blog/proven-social-media-content-strategies-with-examples-from-brands.md): Different Approaches to Publishing Social Media Content With Examples from Brands - growing on Instagram, TikTok, and Twitter.
- [Top 7 Tips and Tricks For X/Twitter API Posting](https://www.ayrshare.com/blog/top-7-tips-and-tricks-for-twitter-api-posting.md): Top 7 Tips and Tricks For X API Posting. If you are planning to use an API for your connectivity to the social network, then you have to do things a bit differently.
- [Press Release: Ayrshare Announces 100 million API Calls as Demand for Social Media Integrations Surges](https://www.ayrshare.com/blog/press-release-ayrshare-announces-100-million-api-calls-as-demand-for-social-media-integrations-surges.md): Ayrshare Announces 100 million API Calls as Demand for Social Media Integrations Surges
- [Changelog: What’s New with Facebook Graph API and Marketing API Version 13.0](https://www.ayrshare.com/blog/whats-new-with-facebook-graph-api-version-13-0-and-marketing-api-version-13-0.md): Facebook updated their Graph and Marketing APIs to v13.0, including the Instagram API and WhatsApp API. Here's what's new in the changelogs.
- [Twitter Launches “Automated” Label for Bots](https://www.ayrshare.com/blog/twitter-launches-automated-label-for-bots.md): Twitter launches new automation rules requiring bots to add the Automated label. Here is how to enable it on your Twitter account.
- [Social Media APIs for Beginners](https://www.ayrshare.com/blog/social-media-apis-for-beginners.md): A Beginner’s Guide to Understanding What are Social Media APIs and How to Use Them.
- [How to Improve Content with Social Media APIs: 3 Tips from Marketing Pros](https://www.ayrshare.com/blog/how-to-improve-content-with-social-media-apis-3-tips-from-marketing-pros.md): How to use Social Media, Analytics, and Marketing APIs, to tap into your social audiences and improve your content.
- [How to Automatically Post to Social Media from Your Blog or Newsletter’s RSS Feed](https://www.ayrshare.com/blog/how-to-automatically-post-to-social-media-from-rss-feed.md): How to automatically post your blog or newsletter to your social media accounts, Facebook, Instagram, Twitter, using the RSS Feed.
- [YouTube API: How to Upload YouTube Shorts](https://www.ayrshare.com/blog/post-youtube-shorts-with-an-api.md): YouTube Shorts are the latest entry in the short-form video arena. See how to upload a YouTube Shorts video using the YouTube API. #Shorts
- [TikTok API: How to Post TikTok Videos Using a Social Media API](https://www.ayrshare.com/blog/tiktok-api-how-to-post-to-tiktok-using-a-social-media-api.md): How to post videos to TikTok using an API. Either share your own videos or on behalf of your users from your platform.
- [Instagram Hashtag Guide: The Best Way to Use Hashtags on Instagram](https://www.ayrshare.com/blog/instagram-hashtag-guide.md): Create an Instagram strategy to find the most popular and relevant hashtags so your posts get the most engagement.
- [Instagram and Twitter Character Counter Tool](https://www.ayrshare.com/blog/instagram-and-twitter-character-counter-tool.md): Use a character counter tool so you never go over the Instagram caption limit or Twitter's character limits
- [How To Share a Podcast on Instagram](https://www.ayrshare.com/blog/how-to-share-a-podcast-on-instagram.md): How do you share a podcast on Instagram? You can’t directly upload an audio file to Instagram stories, but you can create an Audiogram!
- [The Definitive Bubble Review: A Flexible No Code App Builder Growing Over 50%](https://www.ayrshare.com/blog/the-definitive-bubble-review-a-flexible-no-code-app-builder-growing-over-50.md): The definitive Bubble.io review. No code app builders, web and mobile apps, are hot and Bubble IO is one of the most popular, growing at 50%.
- [Pinterest API Integration on Ayrshare](https://www.ayrshare.com/blog/pinterest-api-integration-on-ayrshare.md): Our Pinterest API integration is available on Ayrshare. You can now share Pins to Pinterest's 454 million active monthly users.
- [What is Social Media?](https://www.ayrshare.com/blog/what-is-social-media.md): Social Media has become ingrained in our society, so we look at how to answer what is social media and where did it come from?
- [Why You Should Put a CDN Like Cloudflare in Front of Firebase](https://www.ayrshare.com/blog/why-you-should-put-a-cdn-like-cloudflare-in-front-of-firebase.md): There are three good reasons you should consider putting a CDN like Cloudflare in front of Firebase.
- [How to Put a CDN in Front of Firebase Cloud Storage](https://www.ayrshare.com/blog/how-to-put-a-cdn-in-front-of-firebase-cloud-storage.md): A work-around to put Firebase Cloud Storage behind a CDN such as Cloudflare to speed up access to your content.
- [Top 5 Tips To Optimize Your Instagram Posting in 2021](https://www.ayrshare.com/blog/top-5-tips-to-optimize-your-instagram-posting-in-2021.md): The top 5 tips to optimize your Instagram posts and stories to create the perfect Instagram post for maximum engagement and SEO.
- [Ayrshare Launches YouTube, Instagram, Google My Business API Enhancements for Social Media](https://www.ayrshare.com/blog/ayrshare-launches-youtube-instagram-google-my-business-api-enhancements-for-social-media.md): Ayrshare Launches YouTube, Instagram, Google My Business API Enhancements for Social Media
- [How Many Hashtags Should I Use On Social Media?](https://www.ayrshare.com/blog/how-many-hashtags-should-i-use-on-social-media.md): Hashtags and their use on social media platforms differ. Here are details on how many hashtags you should use on each.
- [A Better White Label Social Media Management Platform](https://www.ayrshare.com/blog/a-better-white-label-social-media-management-platform.md): Using a pre-built white label solution will always end up in some frustration. And you may be saving 30% to 80% by using an API solution.
- [What Is Spintax, And Why Is It Bad for SEO?](https://www.ayrshare.com/blog/what-is-spintax-and-why-is-it-bad.md): Spintax spins the syntax of social media posts to make them different. Though it sounds good, the concept doesn’t help your SEO strategy.
- [A Firebase Cloud Functions Cold Start Solution](https://www.ayrshare.com/blog/a-firebase-cloud-functions-cold-start-solution.md): Firebase Cloud Functions cold start problem finally has a solution with minimum instances. Your functions will now run fast, but at a price.
- [What’s New with Facebook Graph API and Marketing API Version 12.0](https://www.ayrshare.com/blog/whats-new-with-facebook-graph-api-and-marketing-api-version-12-0.md): On September 14th, 2021 Facebook released their latest Graph API version 12.0 and Marketing API version 12.0. Here is what is new.
- [Ayrshare Alternatives: When to use (and not use) Ayrshare for Social Media Management](https://www.ayrshare.com/blog/why-you-shouldnt-use-ayrshare.md): When to use and not to use Ayrshare's social media API for managing your users' social media accounts.
- [Emailing with Firebase: The Trigger Email Extension](https://www.ayrshare.com/blog/fireabase-email-extension-guide.md): How do you send emails from Firebase. The new Firebase extension Trigger Email makes it easy, and here's how.
- [Twitter Launches Spaces API for Live Audio Conversations](https://www.ayrshare.com/blog/twitter-launches-spaces-api-for-live-audio-conversations.md): Twitter has launched their Spaces API for live audio conversations, allowing discovery and lookup integrations for 3rd party apps.
- [Build A Social Media Posting Mobile App With No Code](https://www.ayrshare.com/blog/build-a-social-media-posting-mobile-app-with-no-code.md): In this tutorial, we show you how to make your own mobile social media scheduling app using the no-code platform AppGyver and the Ayrshare API.
- [How To Create A Social Media Scheduling App With No Code](https://www.ayrshare.com/blog/how-to-create-a-social-media-scheduling-app-with-no-code.md): How to build a no-code web app to create and schedule a post for multiple social media destinations using Bubble.io and Ayrshare's API
- [Top 3 Reasons Real Estate Social Media Video Posts Drive Business](https://www.ayrshare.com/blog/top-3-reasons-real-estate-social-media-video-posts-drive-business.md): Posting beautiful and professional videos to social media can help Real Estate agents to find new listings and engage buyers.
- [Upptime: An open-source uptime monitor for website and API uptime status](https://www.ayrshare.com/blog/upptime-monitor-status-website-api.md): I'm on the hunt for a system to monitor and show our users the website and API's uptime status - important for any SaaS or API service. I found Upptime.
- [Why did Hootsuite Raise Prices 1200%?](https://www.ayrshare.com/blog/why-did-hootsuite-raise-prices-1200.md): Hootsuite just increased their prices 1200% for a lot of their long time users. Why did they do this?
- [What Is The Most Popular Social Media Platform in 2021?](https://www.ayrshare.com/blog/what-is-the-most-popular-social-media-platform-in-2021.md): A look at the most popular social media platforms in 2021 including Instagram, Facebook, TikTok, and WhatsApp.
- [How We Got 1,000 Users by Engaging Developers](https://www.ayrshare.com/blog/how-we-got-1000-users-by-engaging-developers.md): How do you effectively market to your developer or technical audience? There are three ways to boost your lead generation efforts by 30%.
- [Ayrshare Supports Direct Posting to Instagram](https://www.ayrshare.com/blog/ayrshare-supports-direct-posting-to-instagram.md): Direct social media posting to Instagram via Ayrshare's API. Now you can post images or videos directly to Instagram.
- [The Future Of Twitter](https://www.ayrshare.com/blog/the-future-of-twitter.md): Twitter is innovating with new community features like Spaces and Ad formats like Carousel and Branded Likes. Learn what is next for Twitter.
- [Ayrshare’s YouTube API to Upload Videos](https://www.ayrshare.com/blog/ayrshare-api-posting-videos-to-youtube.md): Want to upload and share a video to YouTube via an API? Ayrshare's YouTube API integration allows you to upload and post a video a thumbnail.
- [How to Post Facebook Images as a Carousel](https://www.ayrshare.com/blog/post-a-series-of-facebook-images-as-a-carousel.md): Post a series of Facebook carousel images via Ayrshare's API with the new "carousel" feature. It is easy to setup and post beautiful images.
- [Post to Multiple Social Media Accounts from Bubble](https://www.ayrshare.com/blog/post-to-multiple-social-media-accounts-from-bubble.md): How to connect and post to social media networks like Twitter, Instagram, or Facebook from no-code tool Bubble.io.
- [Why Your Business Should Have a Telegram Strategy](https://www.ayrshare.com/blog/why-your-business-should-have-a-telegram-strategy.md): Telegram is a popular and global communications platform that helps you grow your brand and be a powerful content marketing channel.
- [The Power of Javascript Promise.all()](https://www.ayrshare.com/blog/the-power-of-javascript-promise-all.md): Javascript's Promise.all() is a powerful function that allows you to resolve multiple Promises and return the results.
- [Ayrshare Launches the API-First Social Media Management Platform](https://www.ayrshare.com/blog/ayrshare-launches-the-api-first-social-media-management-platform.md): Today we announced the global launch of the API-First Social Media Management Platform. As the first focused API-first solution in the market, we are excited with the great feedback and traction we have with our early users.
- [What are Twitter Fleets and How to Use Them](https://www.ayrshare.com/blog/what-are-twitter-fleets-and-how-to-use-them.md): Twitter Fleets are here! They are new. They are exciting. They are innovative. They are...well, kind of a copy of other social networks.
- [What’s New with Facebook Graph API 9.0?](https://www.ayrshare.com/blog/whats-new-with-facebook-graph-api-9-0.md): On November 10th, 2020 Facebook released version 9.0 of their Graph API. Here is what is new and important.
- [What Is Driving Twitter’s User Growth?](https://www.ayrshare.com/blog/what-is-driving-twitters-user-growth.md): In the most recent quarter ended June 2020, Twitter reported worldwide mDAU of 186 million, which was a 12% increase from the prior quarter. In the last few quarters, the growth of mDAU has been accelerating. This indicates that the strategy Twitter has taken to improve user engagement on the platform has been working.
- [Our Firebase Tech Stack](https://www.ayrshare.com/blog/our-firebase-tech-stack.md): How we used Firebase and Firestore to build Ayrshare: the API to automatically publish to your social media networks.
- [Automate Your Social Media Strategy](https://www.ayrshare.com/blog/automate-your-social-media-strategy.md): One way to enhance your social media strategy and presence is by automating the creation and publication of your content.
- [Automatically Publish Cryptocurrency Prices to Social Media Networks](https://www.ayrshare.com/blog/automatically-publish-cryptocurrency-prices-social-media-networks.md): Publish Cryptocurrency prices to social media networks via an API using Firebase, Coin Gecko, and Ayrshare
# Connect to the MCP Server
Source: https://www.ayrshare.com/docs/additional/mcp-action-connect
Connect any MCP client to the Ayrshare MCP Server — transport, endpoint, and authentication.
The Ayrshare [MCP Server](/docs/additional/mcp-action-server) lets an AI agent drive the Ayrshare API. This page covers how to connect to it and how authentication works.
## Endpoint and transport
The production MCP Server is available at:
`https://api.ayrshare.com/mcp`
It uses **Streamable HTTP** transport and is **stateless** — there is no session to maintain between calls.
## Authentication
Authentication is enforced by the same Ayrshare API chain that powers the REST API.
**Required:** `Authorization: Bearer YOUR_API_KEY` — your account API key (Business plan key for profiles and sub-profiles).
**Optional:** `Profile-Key: YOUR_PROFILE_KEY` — targets a sub-profile for every call on the connection.
**Optional per call:** a `profileKey` tool argument — targets a sub-profile for a single tool call.
### Precedence: argument wins over header
When a tool call includes a `profileKey` argument **and** the connection has a `Profile-Key` header, the **per-call `profileKey` argument wins**. The header is used only when no valid argument is provided.
One exception: on `get_platform_history` and `get_social_network_analytics`, an X/Twitter `userId`/`userName` lookup must use the account API key only; supplying a `profileKey` argument or `Profile-Key` header there returns Error 400.
The `initialize` and `tools/list` MCP methods are reachable **before** authentication — they return metadata only and execute nothing. **Every tool call is authenticated.**
### Authentication errors
An unauthenticated or invalid key on a tool call returns an Ayrshare **error 403 / code 102** with message **"API Key not valid"**. Per the MCP spec, tool-execution errors are returned in-band: the tool result carries `isError: true` and this message, while the MCP transport itself responds **HTTP 200**. (The `403`/`102` are Ayrshare's application error, not the transport status.)
## Connect
### Option A: Claude Code plugin
If you use Claude Code, install the Ayrshare plugin. It bundles the MCP Server configuration, a setup command, agents, skills, and a confirmation hook. See the [Claude Code Plugin](/docs/additional/mcp-claude-code-plugin) page for the full install steps.
### Option B: Any MCP client
For any MCP client that supports Streamable HTTP, register the server directly. In Claude Code:
```bash theme={"system"}
claude mcp add --transport http ayrshare https://api.ayrshare.com/mcp --header "Authorization: Bearer YOUR_API_KEY"
```
To target a sub-profile on every call, add the optional `Profile-Key` header:
```bash theme={"system"}
claude mcp add --transport http ayrshare https://api.ayrshare.com/mcp \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "Profile-Key: YOUR_PROFILE_KEY"
```
The MCP connection initializes at session start. **Restart your MCP client** after installing the server or changing your key so the new configuration takes effect.
## X/Twitter BYO credentials
Since March 31, 2026, X/Twitter operations through Ayrshare require your own OAuth 1.0a credentials. When a tool call targets X/Twitter, forward these two headers on the connection alongside your `Authorization` (and optional `Profile-Key`) headers:
| Header | Description |
| ----------------------------- | ------------------------------------------------ |
| `X-Twitter-OAuth1-Api-Key` | Your OAuth 1.0a API Key (Consumer Key) |
| `X-Twitter-OAuth1-Api-Secret` | Your OAuth 1.0a API Key Secret (Consumer Secret) |
These are the same headers used by the REST API — one OAuth 1.0a key pair per Ayrshare account, sent on every X-targeting request (the same pair applies to all sub-profiles). Ayrshare does not use OAuth 2.0 here. See the [API Overview](/docs/apis/overview#xtwitter-byo-credentials) and the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for setup, policy, and troubleshooting.
Without these headers, an X/Twitter tool call returns error `419` (`x_credentials_required`).
### Connect with the BYO headers
To set up X/Twitter BYO credentials from the start, add the server with both OAuth 1.0a headers alongside your `Authorization` header (include `Profile-Key` too if you target a sub-profile on every call):
```bash theme={"system"}
claude mcp add --transport http ayrshare https://api.ayrshare.com/mcp \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "X-Twitter-OAuth1-Api-Key: YOUR_TWITTER_CONSUMER_KEY" \
--header "X-Twitter-OAuth1-Api-Secret: YOUR_TWITTER_CONSUMER_SECRET"
```
### Add the BYO headers to an existing connection
Connection headers are fixed when the server is added, so if you already connected without the BYO headers, remove the server and re-add it with the full set (re-include any headers you were already using, such as `Profile-Key`):
```bash theme={"system"}
claude mcp remove ayrshare
claude mcp add --transport http ayrshare https://api.ayrshare.com/mcp \
--header "Authorization: Bearer YOUR_API_KEY" \
--header "X-Twitter-OAuth1-Api-Key: YOUR_TWITTER_CONSUMER_KEY" \
--header "X-Twitter-OAuth1-Api-Secret: YOUR_TWITTER_CONSUMER_SECRET"
```
Restart your MCP client after changing headers so the new configuration takes effect. Using the Claude Code plugin instead of a raw connection? See [Claude Code Plugin → X/Twitter BYO credentials](/docs/additional/mcp-claude-code-plugin#xtwitter-byo-credentials).
## Next steps
The 27 tools grouped by domain, with scope and purpose.
Install the Ayrshare plugin for Claude Code.
# MCP Server
Source: https://www.ayrshare.com/docs/additional/mcp-action-server
Let AI agents drive the Ayrshare API through the Model Context Protocol (MCP) Server.
Looking for the read-only docs-search MCP? See [Documentation MCP](/docs/additional/mcp-server). **This page documents the Action MCP** that lets an AI agent drive the Ayrshare API.
The Ayrshare **MCP Server** lets AI agents drive the Ayrshare API through [Model Context Protocol (MCP)](https://modelcontextprotocol.io) tools. Instead of writing REST calls by hand, an agent connects to the MCP Server and calls Ayrshare tools to publish posts, fetch history and analytics, manage comments and direct messages, create profiles, and more.
## How it works
Each MCP tool call is dispatched in-process through the same Ayrshare API chain that powers the REST API:
Authentication of your API key.
Rate limiting for your plan tier.
Quota and usage enforcement.
OpenAPI request validation.
The same controllers that serve the REST endpoints.
Because tools run through the real API chain, the MCP Server returns the same data and enforces the same rules as the REST API. There is no separate behavior to learn or maintain.
## Who it's for
**Agent builders** connecting an LLM agent to the Ayrshare API to publish and analyze content.
**Claude Code users** who want to post, fetch history, and manage profiles from their editor (see the [Claude Code Plugin](/docs/additional/mcp-claude-code-plugin)).
**Integrators** onboarding clients' social accounts under sub-profiles (see [Client Onboarding](/docs/additional/mcp-client-onboarding)).
Working with profiles and sub-profiles requires a **Business plan** (or Enterprise). See the [Business Plan Overview](/docs/multiple-users/business-plan-overview).
## Endpoint and transport
The production MCP Server is available at:
`https://api.ayrshare.com/mcp`
It uses **Streamable HTTP** transport and is **stateless** — there is no session to maintain between calls. See [Connect & Setup](/docs/additional/mcp-action-connect) for the full connection and authentication details.
## Relationship to the REST API and Documentation MCP
**REST API** — the [Ayrshare API](/docs/apis/overview) is the underlying interface. The MCP Server dispatches each tool call through that same API chain, so behavior, rules, and data match.
**Documentation MCP** — the separate [Documentation MCP](/docs/additional/mcp-server) is a read-only server that searches Ayrshare's API documentation. It does not perform actions. Use the MCP Server (this page) to actually drive the API.
## Next steps
Transport, endpoint, and authentication for any MCP client.
The 27 tools grouped by domain, with scope and purpose.
Install the Ayrshare plugin for Claude Code.
Mint social-linking URLs for client sub-profiles.
# MCP Tool Catalog
Source: https://www.ayrshare.com/docs/additional/mcp-action-tools
The 27 tools exposed by the Ayrshare MCP Server — posts, history, analytics, comments, direct messages, profiles, media, generation, webhooks, and errors — grouped by domain with scope and purpose.
The Ayrshare [MCP Server](/docs/additional/mcp-action-server) exposes **27 tools**, grouped below by domain. Each tool is dispatched in-process through the real Ayrshare API chain.
## Scope
Every tool is either **Profile** or **Account** scope:
**Profile** — the tool accepts a `profileKey` argument to target a sub-profile.
**Account** — the tool takes **no** `profileKey`; it operates at the account level.
The six tools that take **no** `profileKey` argument are: `create_profile`, `list_profiles`, `explain_error`, `validate_media`, `generate_post`, and `recommend_hashtags`. All other tools accept a `profileKey`; `generate_jwt_social_linking_url` **requires** one. Note: `recommend_hashtags` takes no `profileKey` argument but still reads the connection's `Profile-Key` header to pick whose linked TikTok account it draws on, so its results are profile-specific.
When both a per-call `profileKey` argument and a `Profile-Key` header are present, the argument wins. See [Connect & Setup](/docs/additional/mcp-action-connect#precedence-argument-wins-over-header) for the precedence rules.
## Posts
| Tool | Scope | Purpose |
| --------------- | ------- | ------------------------------------------------ |
| `create_post` | Profile | Publish to one or more linked platforms. |
| `validate_post` | Profile | Dry-run validation, same input as `create_post`. |
| `get_post` | Profile | Fetch a post by Ayrshare Post ID. |
| `update_post` | Profile | Update a scheduled or awaiting-approval post. |
| `retry_post` | Profile | Re-submit a failed post. |
## History
| Tool | Scope | Purpose |
| ---------------------- | ------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `get_post_history` | Profile | Posts sent via Ayrshare. |
| `get_platform_history` | Profile | Posts and analytics direct from the network, including non-Ayrshare posts. For an X/Twitter `userId`/`userName` lookup, use the account API key only; a `profileKey` argument or `Profile-Key` header there returns Error 400. |
## Analytics
| Tool | Scope | Purpose |
| --------------------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `get_post_analytics` | Profile | Per-post metrics by Ayrshare Post ID. |
| `get_post_analytics_by_social_id` | Profile | Per-post metrics by native Social Post ID. |
| `get_social_network_analytics` | Profile | Account-wide analytics and demographics for a connected social account. For an X/Twitter `userId`/`userName` lookup, use the account API key only; a `profileKey` argument or `Profile-Key` header there returns Error 400. |
## Comments
| Tool | Scope | Purpose |
| --------------- | ------- | ------------------------ |
| `get_comments` | Profile | Read comments on a post. |
| `add_comment` | Profile | Top-level comment. |
| `reply_comment` | Profile | Reply to a comment. |
## Messages / DMs
| Tool | Scope | Purpose |
| ------------------- | ------- | ------------------------------- |
| `get_messages` | Profile | Fetch DMs for a platform. |
| `send_message` | Profile | Send a DM. |
| `get_auto_response` | Profile | Read DM auto-response settings. |
| `set_auto_response` | Profile | Configure DM auto-response. |
## Profiles
| Tool | Scope | Purpose |
| --------------------------------- | ------- | ------------------------------------------------------ |
| `list_profiles` | Account | List sub-profiles. |
| `create_profile` | Account | Create a sub-profile. |
| `generate_jwt_social_linking_url` | Profile | Mint a JWT social-linking URL (requires `profileKey`). |
## Media
| Tool | Scope | Purpose |
| ---------------- | ------- | ----------------------------------------------------------- |
| `validate_media` | Account | HEAD-check a media URL is reachable; returns `contentType`. |
## Generate
| Tool | Scope | Purpose |
| -------------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `generate_post` | Account | AI-draft post copy. |
| `recommend_hashtags` | Account | Hashtag suggestions from TikTok view-count data. Uses the linked TikTok account on the profile set by the `Profile-Key` header; takes no per-call `profileKey`. |
## Webhooks
| Tool | Scope | Purpose |
| -------------------- | ------- | ------------------------- |
| `register_webhook` | Profile | Register a webhook. |
| `unregister_webhook` | Profile | Unregister a webhook. |
| `list_webhooks` | Profile | List registered webhooks. |
## Errors
| Tool | Scope | Purpose |
| --------------- | ------- | ------------------------------------------------------------------ |
| `explain_error` | Account | Decode an Ayrshare error code into cause, classification, and fix. |
This catalog is verified against the live server's `tools/list`. More tools are planned (e.g. Links tools). If in doubt, query `tools/list` for the authoritative set. The catalog is maintained by the MCP server team.
# Claude Code Plugin
Source: https://www.ayrshare.com/docs/additional/mcp-claude-code-plugin
Install the Ayrshare plugin for Claude Code to publish, schedule, and analyze social posts from your editor — with pre-publish validation, a confirm-before-publish prompt, brand-voice drafting, and analytics read-back.
The Ayrshare plugin for Claude Code bundles the [MCP Server](/docs/additional/mcp-action-server) configuration, a setup command, agents, skills, and a safety hook. With it installed, you can publish posts, fetch history and analytics, manage profiles, and more — directly from Claude Code. Before anything goes live, the agent validates each post against the target network's rules and asks you to confirm, catching avoidable rejections up front. Post history is available for matching a brand's voice, and analytics can be read back to inform the next post.
The plugin is open source. See the repository for internals: [ayrshare/ayrshare-social-media-api-claude-plugin](https://github.com/ayrshare/ayrshare-social-media-api-claude-plugin).
## Install
```bash theme={"system"}
claude plugin marketplace add ayrshare/ayrshare-social-media-api-claude-plugin
```
```bash theme={"system"}
claude plugin install ayrshare@ayrshare
```
### Install scopes
| Scope | Where it applies |
| ----------------- | ----------------------------------------------------- |
| Global (default) | Every project on this machine. |
| `--scope local` | Current project, not committed to git. |
| `--scope project` | Current project, committed and shared with your team. |
Claude Code's CLI calls the global scope `--scope user`.
## Credentials
Provide your Ayrshare API key in either of these ways:
Run `/ayrshare:setup` to configure or rotate the key.
Set the `AYRSHARE_API_KEY` environment variable.
The plugin's bundled `.mcp.json` already declares the `Authorization` header plus the optional `Profile-Key` and X BYOK headers, each with an empty default (`${VAR:-}`), so you enable a header simply by setting its environment variable (Claude Code substitutes the values at startup). To target a sub-profile on every call, set `AYRSHARE_PROFILE_KEY` (via `/ayrshare:setup` or your `settings.json` `env` block) and restart Claude Code; the bundled `Profile-Key` header carries it, and stays empty (treated as not provided) when unset. To target a sub-profile for a single call instead, pass a `profileKey` tool argument (no config change needed). You do not need to edit the bundled `.mcp.json`, and you should not, because `claude plugin update` overwrites it.
The MCP server initializes at session start. **Restart Claude Code** after installing the plugin or changing your key.
### X/Twitter BYO credentials
Posting to X/Twitter requires your own X Developer App credentials (the X BYO-key mandate, effective March 31, 2026; see the [API Overview](/docs/apis/overview#xtwitter-byo-credentials)). The bundled `.mcp.json` already declares both X BYOK headers with empty defaults, alongside `Authorization` and `Profile-Key`:
```json theme={"system"}
"headers": {
"Authorization": "Bearer ${AYRSHARE_API_KEY}",
"Profile-Key": "${AYRSHARE_PROFILE_KEY:-}",
"X-Twitter-OAuth1-Api-Key": "${X_TWITTER_OAUTH1_API_KEY:-}",
"X-Twitter-OAuth1-Api-Secret": "${X_TWITTER_OAUTH1_API_SECRET:-}"
}
```
So you only set the matching environment variables (`X_TWITTER_OAUTH1_API_KEY`, `X_TWITTER_OAUTH1_API_SECRET`) via `/ayrshare:setup` or your `settings.json` `env`, then **restart Claude Code**; you do not edit the bundled `.mcp.json` (it is overwritten on `claude plugin update`). Set **both** or neither: with neither set an X/Twitter call returns error `419` (`x_credentials_required`); with only one set it returns error `400`. This is one key pair per Ayrshare account, sent on every X-targeting request (the same pair for all sub-profiles).
Prefer a raw connection over the plugin? The same BYO headers can be passed via `claude mcp add --header` — see [Connect & Setup → X/Twitter BYO credentials](/docs/additional/mcp-action-connect#xtwitter-byo-credentials).
## What it ships
### Command
`/ayrshare:setup` — configure or rotate the Ayrshare API key.
### Agents
`social-manager`: publishes, schedules, and analyzes content across platforms.
`profile-manager`: creates and lists profiles and mints JWT social-linking URLs for client profiles under a Business account.
`insights-analyst`: read-only reporting. Pulls metrics and post history and summarizes performance; never publishes, comments, messages, or modifies anything.
### Skills
| Skill | Purpose |
| ---------------------------- | ----------------------------------------------------------- |
| `getting-started` | Orient and connect for first-time use. |
| `post` | Create, validate, update, and retry posts. |
| `history` | Retrieve post and platform history. |
| `analytics` | Pull per-post and account-level analytics. |
| `comments` | Read, add, and reply to comments. |
| `messages` | Read and send direct messages and configure auto-responses. |
| `profiles` | Create and list sub-profiles. |
| `media` | Validate that media URLs are reachable. |
| `generate` | AI-draft post copy and recommend hashtags. |
| `webhooks` | Register, unregister, and list webhooks. |
| `errors` | Decode Ayrshare error codes. |
| `draft-in-brand-voice` | Draft post copy in a consistent brand voice. |
| `plan-and-schedule-campaign` | Plan and schedule a multi-post campaign. |
### Confirmation hook
A `PreToolUse` hook asks for confirmation before any publish or send action. It covers exactly these 7 tools:
`create_post`
`update_post`
`retry_post`
`add_comment`
`reply_comment`
`send_message`
`set_auto_response`
## FAQ
Yes. The plugin runs `validate_post` to dry-run your content against each network's rules — length, format, and media requirements — before it publishes, so you catch avoidable rejections up front.
Yes. A `PreToolUse` confirmation hook prompts you to approve before any publish or send action: `create_post`, `update_post`, `retry_post`, `add_comment`, `reply_comment`, `send_message`, and `set_auto_response`.
Yes. The `draft-in-brand-voice` skill reads your post history to draft new copy in a consistent brand voice. It produces drafts only — nothing publishes without your confirmation.
Yes. The analytics tools return per-post and account-level metrics, so you can read results back and let them guide your next post.
An Ayrshare API key (a Business plan key for profiles and sub-profiles) and Claude Code. Configure the key with `/ayrshare:setup` or the `AYRSHARE_API_KEY` environment variable, then restart Claude Code.
Yes. X/Twitter requires your own OAuth 1.0a credentials, added as two connection headers (`X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret`). See [X/Twitter BYO credentials](#xtwitter-byo-credentials) above.
## Next steps
Authentication, profile targeting, and BYO credentials.
The 27 tools grouped by domain, with scope and purpose.
# Onboard Client Social Accounts
Source: https://www.ayrshare.com/docs/additional/mcp-client-onboarding
Use the MCP Server to onboard clients' social accounts under sub-profiles with a JWT social-linking URL.
Integrators on a Business or Enterprise plan can onboard their clients' social accounts under **sub-profiles**. Using the [MCP Server](/docs/additional/mcp-action-server), an agent creates a sub-profile, targets it, and mints a single sign-on linking URL the client opens to connect their accounts.
## Flow
Call `create_profile` (account-level — no `profileKey`). It returns a **profile key** for the new sub-profile.
Use the returned profile key on subsequent calls — either via the `Profile-Key` header on the connection or as a per-call `profileKey` argument. See [Connect & Setup](/docs/additional/mcp-action-connect#precedence-argument-wins-over-header) for precedence.
Call `generate_jwt_social_linking_url` to mint a single sign-on linking URL. The JWT signing key and onboarding domain are derived **server-side** — the caller supplies **no** `X-Ayrshare-*` headers and no private key or domain.
The client opens the URL and authorizes (OAuths) their social accounts. The connected accounts are linked to the sub-profile.
## Requirements
`generate_jwt_social_linking_url` **requires** a `profileKey`. If none resolves, the call returns **400** with the message **"Profile Key is required…"**.
A **social-linking domain must be provisioned** for your account. This is available on the **Business** and **Enterprise** plans.
### Error states
| Condition | Response |
| --------------------- | -------------------------------------------------------------------------------------------------------------- |
| No provisioned domain | **400** — "No social-linking domain is provisioned for this account (available on Business/Enterprise plans)." |
| No signing key | **400** — "No signing key found for this account's social-linking domain." |
## Next steps
Authentication and profile targeting.
The 27 tools grouped by domain, with scope and purpose.
# n8n
Source: https://www.ayrshare.com/docs/additional/mcp-n8n
Connect n8n's AI Agent to the Ayrshare MCP Server to publish, schedule, and analyze across 13 social networks, with no per-platform API code.
n8n is where you wire your tools together. Ayrshare is the one API that publishes to Facebook, Instagram, LinkedIn, YouTube, TikTok, Pinterest, Reddit, Threads, Bluesky, Telegram, Google Business Profile, Snapchat, and X in a single call. Connect them with the [Ayrshare MCP Server](/docs/additional/mcp-action-server) and your n8n AI Agent can run the whole loop on its own: draft a post, validate it against each network's rules, publish or schedule it, then read the analytics back.
Because the MCP Server is a hosted Streamable HTTP endpoint, you connect it with n8n's built-in **MCP Client Tool** node. There is nothing to host, no custom code, and no community node to install. You point one node at one URL and your agent gets all 27 social tools.
The workflow shown above, ready to import: Chat Trigger, AI Agent, an Anthropic chat model, and the Ayrshare MCP node pre-wired with the validate-first system prompt.
To use it: in n8n, **Workflows → Import from file**, select the JSON, then create the two credentials it expects (a **Bearer Auth** credential holding your Ayrshare key, and an **Anthropic API** credential). The two warning badges clear once the credentials are attached. Self-hosted instances need outbound access to `api.ayrshare.com` and your model provider.
This guide covers the MCP-first path end to end. If you would rather build a fixed, non-agent workflow, there is a short [REST fallback](#rest-fallback-no-agent) at the end.
## Why MCP instead of writing API calls
You can call Ayrshare's REST API directly from an HTTP Request node, which is fine for fixed, predictable workflows. The MCP Server earns its place when an LLM is in the loop:
**The agent picks the tool.** Describe the goal ("publish this to our business channels and schedule the follow-up for Tuesday") and the agent chooses `validate_post`, `create_post`, and the right parameters itself.
**Validation before anything goes live.** `validate_post` dry-runs your content against each platform's length, format, and media rules, so the agent does not ship a post a network will reject.
**One call, many networks.** A single `create_post` fans out to every linked platform.
**Platform changes are Ayrshare's problem.** When a network changes its API, Ayrshare maintains the integration and your workflow keeps working.
**Same rules as the REST API.** Every MCP tool call runs in-process through the same Ayrshare API chain: same auth, rate limits, quota, and validation. There is no separate behavior to learn.
## How it connects
The **AI Agent** node is the brain. The **MCP Client Tool** sub-node attaches to it, connects to the Ayrshare MCP Server at `https://api.ayrshare.com/mcp`, discovers the available tools, and exposes them to the agent. When the agent acts, the node dispatches the call to Ayrshare, which publishes to the networks.
```
Trigger -> AI Agent (+ Chat Model) -> MCP Client Tool -> Ayrshare MCP Server -> 13 networks
```
For the endpoint, transport, and authentication details, see [Connect & Setup](/docs/additional/mcp-action-connect). For the full tool list, see the [Tool Catalog](/docs/additional/mcp-action-tools).
## Prerequisites
An **n8n instance** (Cloud or self-hosted) on a recent version with the AI Agent and MCP Client Tool nodes. The MCP Client Tool node is built in. You do not need a community node, because the Ayrshare server speaks Streamable HTTP.
An **Ayrshare account and API key** (Dashboard → Settings → API Key), or start a [free trial](https://billing.ayrshare.com/b/9B6bJ15Oidr9fz615u1Nu0h).
**At least one social account linked** in Ayrshare. The agent can only publish where you have connected.
A **chat model credential** for the AI Agent node (Anthropic, OpenAI, etc.).
*(Optional)* A **Business or Enterprise plan** if you will manage multiple clients via sub-profiles.
## Set up the MCP Client Tool node
Open or create a workflow and add an **AI Agent** node (under the *Advanced AI* nodes).
On the AI Agent node, click the **Tool** connector and add an **MCP Client Tool** node. Configure it:
| Field | Value |
| -------------------- | --------------------------------------------------- |
| **Endpoint** | `https://api.ayrshare.com/mcp` |
| **Server Transport** | `HTTP Streamable` |
| **Authentication** | `Bearer Auth` |
| **Tools to Include** | `All` (or `Selected` to expose only specific tools) |
For **Credential**, create a new **Bearer Auth** credential and paste your Ayrshare API key as the token. n8n sends it as `Authorization: Bearer YOUR_API_KEY`. When you save, n8n connects and lists the 27 tools.
Attach a **Chat Model** sub-node and select your model credential. Give the agent a system prompt that sets the rules, for example:
> You are a social media assistant with access to Ayrshare tools. Before publishing anything, always call `validate_post` first and report any issues. Only call `create_post` after validation passes. Default to the platforms the user names; if none are named, ask. Never invent media URLs; only use URLs the user provides, and confirm them with `validate_media` when in doubt.
For testing, the **Manual Trigger** or **Chat Trigger** is easiest. For production, use whatever kicks off the workflow (schedule, webhook, form, new row in a sheet).
**Use HTTP Streamable, not SSE.** The Ayrshare MCP Server uses the modern Streamable HTTP transport and is stateless. n8n's SSE option is deprecated, and the server rejects the SSE stream. Always choose **HTTP Streamable**.
## The tool surface
Your agent sees all 27 tools through the one MCP node. You rarely call them by name; you describe intent and the agent selects. The domains are Posts, History, Analytics, Comments, Messages, Profiles, Media, Generate, Webhooks, and Errors. For the complete list with each tool's purpose and scope, see the [Tool Catalog](/docs/additional/mcp-action-tools).
Two stand out for safety: **`validate_post`** dry-runs a post with the same input as `create_post` but publishes nothing, and **`explain_error`** turns any Ayrshare error code into a plain-English cause and fix, so the agent can self-diagnose.
## Example 1: draft, validate, and publish from a chat message
The "hello world" of this integration. Trigger the workflow with a chat message or form, and let the agent do the rest.
**Trigger:** Chat Trigger (or a Form Trigger with a "what should we post?" field).
**Prompt to the agent:** *"Write a friendly launch announcement for our new analytics dashboard and publish it to LinkedIn and Facebook. Validate first."*
What the agent does on its own: it calls `validate_post` with your copy and both platforms; if anything breaks a network's rules it tells you instead of failing silently; once validation passes it calls `create_post` and returns the live post URLs. Because validation runs first, you find out about a problem before anything is public.
## Example 2: auto-publish new content across your channels
Turn a content source into multi-network posts without touching it.
**Trigger:** RSS Read node on your blog feed, a webhook from your CMS, or a new row in Google Sheets or Airtable.
**AI Agent step:** *"Summarize this article into a short social post with 2 to 3 relevant hashtags, then validate and publish to LinkedIn, Facebook, and Threads."*
Optionally add a [human-in-the-loop](#keep-a-human-in-the-loop) approval before the `create_post` step so a person signs off.
You can lean on `recommend_hashtags` for data-driven tags and `generate_post` if you want Ayrshare to draft the copy rather than your chat model.
## Example 3: weekly analytics digest
Run the loop in reverse: read performance and report it.
**Trigger:** Schedule node, for example every Monday at 8am.
**AI Agent step:** *"Pull last week's account analytics for LinkedIn, Instagram, and Facebook, and summarize the top 3 posts by engagement."*
The agent uses `get_social_network_analytics` for account-level numbers and `get_post_analytics` for individual posts, then you pipe its summary to a **Slack**, **Gmail**, or **Notion** node.
A note on cadence: most posts get the bulk of their engagement in the first 24 hours, and metrics do not update by the second. A daily or weekly schedule is plenty. Do not poll analytics every few minutes or you will hit rate limits for no new data.
## Acting on behalf of clients (multi-tenant)
If you manage social for multiple clients, Ayrshare's profiles let one account post to many separate sets of linked accounts. On a Business or Enterprise plan you have two ways to target a client from n8n:
**Per connection:** add a `Profile-Key` header to the MCP Client Tool node (use **Multiple Headers** auth so you can send both `Authorization` and `Profile-Key`). Every call on that node then acts as that client. Good when a workflow serves one client.
**Per call:** many tools accept a `profileKey` argument, which the agent can set per action. When both are present, the [per-call argument wins](/docs/additional/mcp-action-connect#precedence-argument-wins-over-header). Good when one workflow routes across clients.
To onboard a new client, the agent can call `create_profile` and then `generate_jwt_social_linking_url` to mint a hosted page where the client links their own accounts. No credentials pass through your workflow.
## Posting to X/Twitter
In n8n, switch the MCP Client Tool node's **Authentication** to **Multiple Headers** and add the two `X-Twitter-OAuth1-*` headers alongside `Authorization`. It is a one-time setup per Ayrshare account, and the same key pair applies to every profile. For everything else (Facebook, Instagram, LinkedIn, YouTube, TikTok, and the rest) no extra headers are needed. See [Connect & Setup → X/Twitter BYO credentials](/docs/additional/mcp-action-connect#xtwitter-byo-credentials).
## Keep a human in the loop
The MCP tools make it trivial for an agent to publish, which is exactly why you should gate it. Two cheap safeguards:
**Always validate first.** Bake "call `validate_post` before `create_post`" into the system prompt. Validation publishes nothing and catches platform-rule violations early.
**Add an approval step.** Insert n8n's **Send and Wait for Response** (Slack or email) node between the draft and the publish action so a person approves before anything goes live. For scheduled content, the agent can use `update_post` to revise an awaiting-approval post.
## REST fallback (no agent)
If you want a fixed, deterministic workflow with no LLM, skip MCP and call the REST API with an **HTTP Request** node:
```json theme={"system"}
{
"post": "Excited to announce our new feature!",
"platforms": ["facebook", "linkedin", "instagram"],
"mediaUrls": ["https://example.com/image.jpg"],
"scheduleDate": "2026-07-01T10:00:00Z"
}
```
Use the API host `api.ayrshare.com`, not the dashboard host `app.ayrshare.com`. (`app.ayrshare.com` will accept API calls, but it is not the documented endpoint and can return intermittent [502/504 gateway errors](/docs/help-center/technical-support/response_bad_gateway_502_or_504_error), so always use `api.ayrshare.com`.) The same pattern works for the other [REST endpoints](/docs/apis/overview). This is the right tool when the workflow is fully predictable and you do not need an agent deciding anything.
## Troubleshooting
| Symptom | Likely cause | Fix |
| --------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------- |
| Tool call returns `403` / code `102`, "API Key not valid" | Bad or missing API key | Check the Bearer Auth credential holds your exact Ayrshare key. Re-save the node after changing it. |
| n8n cannot connect to the MCP server | Wrong transport or endpoint | Endpoint must be `https://api.ayrshare.com/mcp`; transport must be **HTTP Streamable**, not SSE. |
| X/Twitter post fails with error `419` | Missing X BYO credentials | Add the two `X-Twitter-OAuth1-*` headers via Multiple Headers auth. |
| Post fails for one platform only | That network is not linked, or a required field is missing | Link it in the dashboard; add `title` for YouTube, `title` + `subreddit` for Reddit, `mediaUrls` for Instagram. |
| Instagram post rejected | No media | Instagram requires `mediaUrls` for most post types. Have the agent confirm with `validate_media`. |
| Media attached as a file or binary does not appear | MCP is JSON-only | Reference media by public `mediaUrls` URL; the MCP path does not accept file uploads. Confirm the URL with `validate_media`. |
| Calls work, but act on the wrong client | Profile targeting | Set a `Profile-Key` header (per connection) or `profileKey` argument (per call); the argument wins if both are set. |
| `429 Too Many Requests` | Polling too often | Reduce analytics and comment polling frequency; metrics do not update by the second. |
| Config change did not take effect | MCP connection initializes at session start | Re-save the node or restart the workflow after changing the key or headers. |
You can also expose the `explain_error` tool to the agent so it decodes any Ayrshare error code into a cause and fix on its own.
## Next steps
Endpoint, transport, authentication, profile targeting, and BYO credentials.
The 27 tools grouped by domain, with scope and purpose.
What the MCP Server is and how it maps to the Ayrshare API.
The same server, packaged for Claude Code.
# Documentation MCP
Source: https://www.ayrshare.com/docs/additional/mcp-server
Connect the read-only Ayrshare Documentation MCP server to your AI agent to search Ayrshare's API documentation
This is the read-only **Documentation MCP** (it searches Ayrshare's API docs). To let an AI agent **drive** the Ayrshare API, see the [MCP Server](/docs/additional/mcp-action-server) (Action MCP).
The Model Context Protocol (MCP) is an open standard that enables applications to share context and tools with Large Language Models (LLMs).
By connecting the Ayrshare API documentation MCP server to your AI development tools like Cursor or Claude Desktop, you can give your AI agent direct access to Ayrshare's documentation.
This integration allows your AI agent to:
Search through Ayrshare's API documentation
Understand available endpoints and parameters
Generate code that uses Ayrshare's APIs correctly
Provide contextually accurate suggestions when working with Ayrshare services
This means instead of manually looking up API details, your AI assistant can reference the documentation directly and help you implement Ayrshare functionality more efficiently.
## How to Get Started
Ayrshare's MCP server is available at `https://www.ayrshare.com/docs/mcp`.
### Claude Desktop
1. Navigate to the Connectors page in the Claude settings.
2. Select Add custom connector.
3. Add `Ayrshare MCP` or any name you prefer as your MCP server name and `https://www.ayrshare.com/docs/mcp` as your MCP server URL.
4. Select Add.
5. When using Claude, select the attachments button (the plus icon).
6. Select your MCP server.
### Claude Code
```bash theme={"system"}
claude mcp add --transport http ayrshare https://www.ayrshare.com/docs/mcp
```
### VS Code
[](https://insiders.vscode.dev/redirect?url=vscode:mcp/install?%7B%22type%22%3A%22http%22%2C%22name%22%3A%22Ayrshare-MCP%22%2C%22url%22%3A%22https%3A%2F%2Fwww.ayrshare.com%2Fdocs%2Fmcp%22%7D)
1. Create a .vscode/mcp.json file.
2. In mcp.json, configure your server:
```json theme={"system"}
{
"servers": {
"Ayrshare MCP": {
"type": "http",
"url": "https://www.ayrshare.com/docs/mcp"
}
}
}
```
### Cursor
[](cursor://anysphere.cursor-deeplink/mcp/install?name=Ayrshare-MCP\&config=eyJ1cmwiOiJodHRwczovL3d3dy5heXJzaGFyZS5jb20vZG9jcy9tY3AifQ==)
1. Use Command + Shift + P (Ctrl + Shift + P on Windows) to open the command palette.
2. Search for “Open MCP settings”.
3. Select Add custom MCP. This opens the mcp.json file.
4. In mcp.json, configure your server:
```json theme={"system"}
{
"mcpServers": {
"Ayrshare MCP": {
"url": "https://www.ayrshare.com/docs/mcp"
}
}
}
```
## Using MCP Server Connection
Restart the app to apply the changes.
In Cursor, you can test the MCP connector by typing `How do you publish a post in Ayrshare. Use the MCP server.`
You will see the request to "Run tool" and Cursor will access the MCP server to get the response.
# Boost Post
Source: https://www.ayrshare.com/docs/apis/ads/facebook/boost-post
POST /ads/facebook/boost
Boost a post by submitting it to Facebook's ad platform
Boost an existing Facebook post to create an ad.
This endpoint allows you to convert your organic posts into paid advertisements with custom targeting, budget, and scheduling parameters.
Budget and bid amounts must be specified in USD with up to two decimal places.
The ad must run for at least 30 hours to address the Facebook requirement.
You can use the [interests endpoint](/docs/apis/ads/facebook/get-ad-interests) to find interest IDs
for targeting.
Facebook may take up to 24 hours to review and approve boosted posts.
If using `fbPostId` directly (instead of Ayrshare `postId`), ensure it's a valid Facebook post
ID.
### Ad Goals
Each ad must have a goal. The goal determines how the ad will be optimized for display.
`engagement`: This goal seeks to increase engagement while ensuring that the ad reaches the
maximum number of unique users. It balances visibility with engagement, showing the ad to as
many different people as possible who may interact with it.
`interactions`: Designed to boost interactions, such as likes, comments, and shares, on the ad.
Facebook prioritizes showing the ad to users most likely to engage with it.
`awareness_views`: Focuses on increasing brand awareness by maximizing the number of times the
ad is displayed. It prioritizes showing the ad as many times as possible within the budget,
regardless of unique reach.
`awareness_audience`: Aims to enhance brand awareness by maximizing the number of unique people
who see the ad. It ensures that the ad reaches as many different users as possible and maximizes
the unique audience size rather than showing it multiple times to the same audience.
Learn more about integrating the Facebook Marketing API with Ayrshare in our [Facebook Marketing API Integration Guide](https://www.ayrshare.com/blog/facebook-ads-api-boosting-with-the-marketing-api/).
## Header Parameters
## Body Parameters
The ID of the Facebook ad account to boost the post on. The account ID can be retrieved from the
[ad accounts endpoint](/docs/apis/ads/facebook/get-ad-accounts).
Name for your ad (appears in Facebook Ad Manager) with the format `{adName} - {postId or fbPostId} - {current date}`.
Maximum bid amount in USD. Minimum bid amount is \$1.00.
Daily budget in USD. Minimum budget is \$1.00.
The [Facebook social post ID](/docs/apis/overview#social-post-id) of the post to boost, which allows
you to create an ad from a post created directly on Facebook. This is the ID of the [post on
Facebook](/docs/apis/history/history-platform), not Ayrshare. Required if `postId` is not set.
The goal of the ad. Values: `engagement`, `interactions`, `awareness_views`, and
`awareness_audience`. See [ad goals details](/docs/apis/ads/facebook/boost-post#ad-goals) above for
more information.
Target ad locations with an object of arrays: `countries`, `regions`, `cities`.
List of country codes.
```json theme={"system"}
{
"countries": ["US", "CA"]
}
```
Regions require Facebook's region `key` value. See the [regions endpoint](/docs/apis/ads/facebook/get-ad-regions) for more information.
```json theme={"system"}
{
"regions": [{ "key": "3886" }]
}
```
Cities require: `key` (from Facebook), `radius`, and `distance_unit`.
`radius` is the distance around the city: 10–50 miles or 17–80 kilometers.
`distance_unit` is `mile` or `kilometer`.
See the [cities endpoint](/docs/apis/ads/facebook/get-ad-cities) for more information.
```json theme={"system"}
{
"cities": [
{ "key": "2420605", "radius": 25, "distance_unit": "mile" }
]
}
```
The [Ayrshare post ID](/docs/apis/overview#ayrshare-post-id) of the post to boost. Required if
`fbPostId` is not set.
The status of the ad. Values: `active` and `paused`.
You can later change the status of the ad using the [update ad endpoint](/docs/apis/ads/facebook/put-ad-update).
Controls Meta's campaign-level ad set budget sharing.
Meta now requires this wire field on every campaign created without a campaign-level budget, so Ayrshare always sends it — defaulting to `false` for backward compatibility.
Set to `true` to let Meta share up to \~20% of an ad set's budget across other ad sets in the same campaign to optimize overall performance. See Meta's [ad campaign group reference](https://developers.facebook.com/docs/marketing-api/reference/ad-campaign-group/) for details.
Track the ad using a Facebook Pixel.
The ID of the Facebook Pixel to track the ad.
```json theme={"system"}
{
"pixelId": 1234567890
}
```
Add UTM tags to the ad URL.
```json theme={"system"}
{
"urlTags": ["utm_source=ayrshare", "utm_medium=social", "utm_campaign=ayrshare-social"]
}
```
For example if the linking URL is `https://www.mysite.com/my-post` and the URL tags added are:
`utm_source=ayrshare`, `utm_medium=social`, and `utm_campaign=ayrshare-social`.
The ad URL will be:
`https://www.mysite.com/my-post?utm_source=ayrshare&utm_medium=social&utm_campaign=ayrshare-social`.
Meta requires advertisers in [special ad categories](https://www.facebook.com/business/help/298000447747885?helpref=faq_content) to must self-identify their campaign category.
If your business is in one of these categories, you must select the appropriate category when boosting your post.
The following values are supported:
`housing`: Ads that promote or directly link to a housing opportunity or related service,
including but not limited to listings for the sale or rental of a home or apartment, homeowners
insurance, mortgage insurance, mortgage loans, housing repairs and home equity or appraisal
services.
`financial_product_services`: Ads that promote or directly link to a financial products and
services offer, including credit.
`employment`: Ads that promote or directly link to an employment opportunity, including but not
limited to part- or full-time jobs, internships or professional certification programs. Related
ads that fall within this category include promotions for job boards or fairs, aggregation
services or ads detailing perks a company may provide, regardless of a specific job offer.
`issues_elections_politics`: Ads made by, on behalf of, or about a candidate for public office,
a political figure, a political party or advocating for the outcome of an election to public
office. This also includes ads about any election, referendum or ballot initiative, including
"Go out and vote" election campaigns. Ads regulated as political advertising or about social
issues in any place where the ad is being placed. If selecting issues, elections, or politics,
you must select the country in which you want to run these ads. You are required to be
authorized to run ads about social issues, elections, or politics in the specified country.
Meta requires advertisers who have self-identified their campaign category.
Meta uses human reviewers and machine-learning to identify these kinds of ads.
If you send us an incorrect `specialAdCategory`, there is a risk your ads will be paused until the campaign is adjusted.
End date and time in ISO 8601 format (must be at least 30 hours after start), for example `2025-03-01T00:00:00Z`.
If not set, the ad will run indefinitely and have end date of `ongoing`.
Exclude locations using an object with arrays of `countries`, `regions`, and `cities`.
List of country codes to exclude.
```json theme={"system"}
{
"countries": ["US", "CA"]
}
```
Regions require Facebook's region `key` value. See the [regions endpoint](/docs/apis/ads/facebook/get-ad-regions) for more information.
```json theme={"system"}
{
"regions": [{ "key": "3886" }]
}
```
Cities require: `key` (from Facebook), `radius`, and `distance_unit`.
`radius` is the distance around the city: 10–50 miles or 17–80 kilometers.
`distance_unit` is `mile` or `kilometer`.
See the [cities endpoint](/docs/apis/ads/facebook/get-ad-cities) for more information.
```json theme={"system"}
{
"cities": [
{ "key": "2420605", "radius": 25, "distance_unit": "mile" }
]
}
```
The gender of the audience. Values: `all`, `male`, `female`.
The target interests of the ad as an array of Facebook [interest
ids](/docs/apis/ads/facebook/get-ad-interests).
Maximum age for targeting the ad (default: 65).
Minimum age for targeting the ad (default: 18).
Start date and time in ISO 8601 format, for example `2025-03-01T00:00:00Z`.
If not set, the ad will start immediately.
The beneficiary of the ad for Digital Services Act (DSA) compliance for EU countries. Must be set
together with `dsaPayor` if either is provided. Please refer to our [DSA
guide](/docs/apis/ads/facebook/get-dsa-recommendations) for more information.
The payor of the ad for Digital Services Act (DSA) compliance for EU countries. Must be set
together with `dsaBeneficiary` if either is provided.
```bash cURL theme={"system"}
curl -X POST https://api.ayrshare.com/api/ads/facebook/boost \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-d '{
"postId": "1234567890",
"accountId": "1234567890",
"adName": "My Ad",
"status": "active",
"goal": "engagement",
"minAge": 18,
"maxAge": 65,
"locations": { "countries": ["US"] },
"budget": 100,
"bidAmount": 1,
"startDate": "2025-03-01T00:00:00Z",
"endDate": "2025-03-07T23:59:59Z",
"interests": [1234567890, 1234567891]
}'
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/boost", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
postId: "1234567890",
accountId: "1234567890",
adName: "My Ad",
status: "active",
goal: "engagement",
minAge: 18,
maxAge: 65,
locations: { countries: ["US"] },
budget: 100,
bidAmount: 1,
startDate: "2025-03-01T00:00:00Z",
endDate: "2025-03-07T23:59:59Z",
interests: [1234567890, 1234567891]
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
API_KEY = "API_KEY"
url = "https://api.ayrshare.com/api/ads/facebook/boost"
payload = {
"postId": "1234567890",
"accountId": "1234567890",
"adName": "My Ad",
"status": "active",
"goal": "engagement",
"minAge": 18,
"maxAge": 65,
"locations": {"countries": ["US"]},
"budget": 100,
"bidAmount": 1,
"startDate": "2025-03-01T00:00:00Z",
"endDate": "2025-03-07T23:59:59Z",
"interests": [1234567890, 1234567891]
}
response = requests.post(url, headers={"Authorization": f"Bearer {API_KEY}", "Content-Type": "application/json"}, json=payload)
print(response.json())
```
```php PHP theme={"system"}
"1234567890",
"accountId" => "1234567890",
"adName" => "My Ad",
"status" => "active",
"goal" => "engagement",
"minAge" => 18,
"maxAge" => 65,
"locations" => ["countries" => ["US"]],
"budget" => 100,
"bidAmount" => 1,
"startDate" => "2025-03-01T00:00:00Z",
"endDate" => "2025-03-07T23:59:59Z",
"interests" => [1234567890, 1234567891]
];
$ch = curl_init("https://api.ayrshare.com/api/ads/facebook/boost");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, [
"Content-Type: application/json",
"Authorization: Bearer " . $API_KEY
]);
$response = curl_exec($ch);
$result = json_decode($response, true);
print_r($result);
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
string API_KEY = "API_KEY";
var payload = new
{
postId = "1234567890",
accountId = "1234567890",
adName = "My Ad",
status = "active",
goal = "engagement",
minAge = 18,
maxAge = 65,
locations = new { countries = new[] { "US" } },
budget = 100,
bidAmount = 1,
startDate = "2025-03-01T00:00:00Z",
endDate = "2025-03-07T23:59:59Z",
interests = new[] { 1234567890, 1234567891 }
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", API_KEY);
var content = new StringContent(
JsonSerializer.Serialize(payload),
Encoding.UTF8,
"application/json"
);
var response = await client.PostAsync("https://api.ayrshare.com/api/ads/facebook/boost", content);
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
apiKey := "API_KEY"
payload := map[string]interface{}{
"postId": "1234567890",
"accountId": "1234567890",
"adName": "My Ad",
"status": "active",
"goal": "engagement",
"minAge": 18,
"maxAge": 65,
"locations": map[string]interface{}{"countries": []string{"US"}},
"budget": 100,
"bidAmount": 1,
"startDate": "2025-03-01T00:00:00Z",
"endDate": "2025-03-07T23:59:59Z",
"interests": []int{1234567890, 1234567891},
}
jsonData, err := json.Marshal(payload)
if err != nil {
fmt.Println("Error marshaling JSON:", err)
return
}
req, err := http.NewRequest("POST", "https://api.ayrshare.com/api/ads/facebook/boost", bytes.NewBuffer(jsonData))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer "+apiKey)
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.databind.ObjectMapper;
public class BoostPost {
public static void main(String[] args) {
String API_KEY = "API_KEY";
String url = "https://api.ayrshare.com/api/ads/facebook/boost";
Map payload = new HashMap<>();
payload.put("postId", "1234567890");
payload.put("accountId", "1234567890");
payload.put("adName", "My Ad");
payload.put("status", "active");
payload.put("goal", "engagement");
payload.put("minAge", 18);
payload.put("maxAge", 65);
Map locations = new HashMap<>();
locations.put("countries", Arrays.asList("US"));
payload.put("locations", locations);
payload.put("budget", 100);
payload.put("bidAmount", 1);
payload.put("startDate", "2025-03-01T00:00:00Z");
payload.put("endDate", "2025-03-07T23:59:59Z");
payload.put("interests", Arrays.asList(1234567890, 1234567891));
try {
ObjectMapper objectMapper = new ObjectMapper();
String requestBody = objectMapper.writeValueAsString(payload);
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Content-Type", "application/json")
.header("Authorization", "Bearer " + API_KEY)
.POST(HttpRequest.BodyPublishers.ofString(requestBody))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (IOException | InterruptedException e) {
e.printStackTrace();
}
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'uri'
require 'json'
API_KEY = "API_KEY"
uri = URI.parse("https://api.ayrshare.com/api/ads/facebook/boost")
payload = {
postId: "1234567890",
accountId: "1234567890",
adName: "My Ad",
status: "active",
goal: "engagement",
minAge: 18,
maxAge: 65,
locations: { countries: ["US"] },
budget: 100,
bidAmount: 1,
startDate: "2025-03-01T00:00:00Z",
endDate: "2025-03-07T23:59:59Z",
interests: [1234567890, 1234567891]
}
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
request = Net::HTTP::Post.new(uri.request_uri)
request["Content-Type"] = "application/json"
request["Authorization"] = "Bearer #{API_KEY}"
request.body = payload.to_json
response = http.request(request)
puts response.body
```
```json 200: Post Boosted theme={"system"}
{
"status": "success",
"adId": "120217670757750410",
"adName": "API Post - DE6gpw8kxlonHy2b7Lo - 2025-03-26T23:42:43",
"adStatus": "active",
"bidAmount": 10,
"budget": 100,
"endDate": "2026-03-28T22:30:00Z",
"goal": {
"title": "Get More Engagement",
"description": "This goal seeks to increase engagement...",
"type": "engagement"
},
"interests": [
"6003195554098"
],
"locations": { "countries": ["US"] },
"maxAge": 65,
"minAge": 18,
"postId": "DE6gpw8kxlonHy2b7Lo",
"startDate": "2026-03-26T22:30:00Z"
}
```
```json 400: Invalid Account ID theme={"system"}
{
"action": "boost post",
"status": "error",
"code": 369,
"message": "Unable to boost post. Please try again or contact us if the issue persists.",
"details": "The accountId likely does not exist. Please check the accountId and try again."
}
```
```json 400: Missing Required Parameters theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. https://www.ayrshare.com/docs/apis",
"details": "Missing required fields: budget"
}
```
# Accounts
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-ad-accounts
GET /ads/facebook/accounts
Get Facebook Ad Accounts
Retrieve available Facebook ad accounts associated with the authenticated profile.
This endpoint allows you to access basic account information as well as key metrics for the ad accounts.
The `metrics` object contains aggregate performance data across all ads in
the account
Results are cached for 10 minutes to optimize performance and reduce API
calls to Facebook
Account status in the JSON response may be one of: `active`, `disabled`,
`unsettled`, `pending review`, or `closed`
Cities use Facebook's key identifier and support radius targeting.
Each city result includes its parent region as region (the region name) and regionId (the region's numeric identifier), so you can target the city's region when it is available.
If a returned city has supportsRegiontrue, the region for this city is available for targeting. If supportsCity is true, this city is available for targeting.
Some locations may be returned as subcity with additional hierarchy fields.
## Header Parameters
## Query Parameters
The search string to filter cities. Provide a partial or full city name.
Maximum number of cities to return.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.GetAsync("https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetAdCities {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan"))
.header("Authorization", "Bearer API_KEY")
.GET()
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
uri = URI('https://api.ayrshare.com/api/ads/facebook/cities?search=Manhattan')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
puts res.body
```
```json 200: Success theme={"system"}
{
"status": "success",
"cities": [
{
"key": "2447439",
"name": "Manhattan",
"type": "city",
"countryCode": "US",
"countryName": "United States",
"region": "Kansas",
"regionId": 3859,
"supportsRegion": true,
"supportsCity": true
},
{
"key": "2703980",
"name": "Manhattan",
"type": "subcity",
"countryCode": "US",
"countryName": "United States",
"region": "New York",
"regionId": 3875,
"supportsRegion": true,
"supportsCity": true,
"geoHierarchyLevel": "SUBCITY",
"geoHierarchyName": "BOROUGH"
}
],
"count": 2
}
```
```json 414: Location metadata error theme={"system"}
{
"action": "ads",
"status": "error",
"code": 414,
"message": "Error getting ad location metadata. Please try again."
}
```
# History
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-ad-history
GET /ads/facebook/history
Get Historical Daily Facebook Ad Spend & Analytics
Retrieve detailed daily ad spend and performance metrics for your Facebook ads.
This endpoint provides comprehensive analytics on your ads with daily breakdowns, goal-specific performance, and aggregated metrics.
The `dailySpend` array contains historical daily spend and performance metrics
for each ad. The data is as of 8 AM EST. If real-time spend data is needed or spend has not yet occurred,
please use the [ads endpoint](/docs/apis/ads/facebook/get-boosted-ads).
The ad will **NOT** be returned if no spend data is available or spend has not yet occurred.
Metrics are calculated from Facebook's reporting API and may have slight delays (up to 24
hours).
The `byGoalType` and `byGoalTitle` sections group performance metrics by goal objectives.
Use either `adId` or `postId` filters to narrow results to specific campaigns.
All monetary values are in the ad account's currency (typically USD).
The `goalPerformance` section highlights your best-performing ad objectives.
This endpoint only returns Facebook ads created via the [Boost Post](/docs/apis/ads/facebook/boost-post)
endpoint. Ads created in Facebook Ads Manager or other third-party tools are not returned.
## Header Parameters
## Query Parameters
Filter results to a specific account ID.
Filter results to a specific ad ID.
Filter results to ads associated with a specific [Ayrshare post
ID](/docs/apis/overview#ayrshare-post-id).
Filter results to ads associated with a specific [Facebook social post
ID](/docs/apis/overview#social-post-id).
Retrieve a maximum of `limit` ads. Maximum is 500.
Start date for the reporting period in ISO 8601 format (default: 30 days ago)
End date for the reporting period in ISO 8601 format (default: today)
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/ads/facebook/spend?accountId=1234567890
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/spend?accountId=1234567890", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/spend', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/spend",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error: " . $err;
} else {
echo $response;
}
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.GetAsync("https://api.ayrshare.com/api/ads/facebook/spend");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.ayrshare.com/api/ads/facebook/spend", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetAdSpend {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/spend"))
.header("Authorization", "Bearer API_KEY")
.GET()
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
require 'uri'
uri = URI.parse('https://api.ayrshare.com/api/ads/facebook/spend')
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
```
```json 200: Success No Param theme={"system"}
{
"status": "success",
"history": [
{
"adId": "6683876017501",
"adName": "API Post 1 - DE6gpw8kxlonHy6eb7L1 - 2025-03-30T17:11:26",
"budgetDaily": 4,
"budgetType": "daily",
"deliveryStatus": "ACTIVE",
"goal": {
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"title": "Get More Engagement",
"type": "engagement"
},
"isActive": true,
"isComplete": false,
"metrics": {
"clicks": 3,
"impressions": 1035,
"reach": 1026,
"frequency": 0,
"ctr": 0,
"cpm": 1.53,
"cpp": 1.54,
"cpc": 0
},
"network": "facebook",
"postId": "DE6gpw8kxlonHy6eb7L1",
"spend": 1.58,
"spendDate": "2025-04-02T00:00:00.000Z",
"status": "ACTIVE"
},
{
"adId": "120218167147110411",
"adName": "API Post 2 - DE6gpw8kxlonHy6eb7L1 - 2025-03-30T16:41:15",
"budgetDaily": 4,
"budgetType": "daily",
"deliveryStatus": "ACTIVE",
"goal": {
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"title": "Get More Engagement",
"type": "engagement"
},
"isActive": true,
"isComplete": false,
"metrics": {
"clicks": 4,
"impressions": 1036,
"reach": 1011,
"frequency": 0,
"ctr": 0,
"cpm": 1.61,
"cpp": 1.65,
"cpc": 0
},
"network": "facebook",
"postId": "DE6gpw8kxlonHy6eb7L1",
"spend": 1.67,
"spendDate": "2025-04-02T00:00:00.000Z",
"status": "ACTIVE"
}
],
"dateRange": {
"start": "2025-02-24T20:02:34.613Z",
"end": "2025-03-26T20:02:34.613Z",
"postId": "eSNkaAiFZVin6wm6f"
},
"metrics": {
"totalSpend": 3.25,
"totalClicks": 7,
"totalImpressions": 2071,
"totalReach": 2052,
"averageCTR": 0.1,
"averageFrequency": 0,
"cpm": 0.79,
"cpp": 0.85,
"cpc": 0.2,
"costPerResult": 1.2,
"byGoalType": {
"engagement": {
"spend": 7.62,
"impressions": 9332,
"clicks": 0,
"reach": 8502,
"count": 8,
"ctr": 0,
"cpm": 0.8165452207458208,
"cpp": 0.8962597035991532,
"cpc": 0
}
},
"byGoalTitle": {
"Get More Engagement": {
"spend": 3.25,
"impressions": 2071,
"clicks": 7,
"reach": 2052,
"count": 1,
"type": "engagement",
"ctr": 0.1,
"cpm": 0.79,
"cpp": 0.85,
"cpc": 0.2
}
},
"goalPerformance": {
"bestPerformingGoalType": {
"type": "engagement",
"clicks": 7,
"spend": 3.25,
"ctr": 0.1
},
"mostEfficientGoalType": {
"type": "engagement",
"cpc": 0.2,
"spend": 3.25
}
},
"count": 2,
"firstDay": "2025-03-17T00:00:00.000Z",
"lastDay": "2025-03-23T00:00:00.000Z"
}
}
```
```json 200: Success by Ad ID theme={"system"}
{
"status": "success",
"history": [
{
"accountId": "274948332",
"adId": "6683876017505",
"adName": "API Post 13 - DE6gpw8kxlonHy6eb7Lo - 2025-03-30T17:11:26",
"budgetDaily": 4,
"budgetType": "",
"deliveryStatus": "ACTIVE",
"fbPostId": "106638148652329_672633202087926",
"goal": {
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"title": "Get More Engagement",
"type": "engagement"
},
"isActive": true,
"isComplete": false,
"metrics": {
"clicks": 2,
"cpc": 0,
"cpp": 1.6,
"cpm": 1.55,
"ctr": 0,
"frequency": 0,
"impressions": 452,
"reach": 438
},
"network": "facebook",
"postId": "DE6gpw8kxlonHy6eb7Lo",
"spend": 0.7,
"spendDate": "2025-04-03T00:00:00.000Z",
"status": "ACTIVE"
},
{
"accountId": "274948332",
"adId": "6683876017505",
"adName": "API Post 13 - DE6gpw8kxlonHy6eb7Lo - 2025-03-30T17:11:26",
"budgetDaily": 4,
"budgetType": "daily",
"deliveryStatus": "ACTIVE",
"fbPostId": "106638148652329_672633202087926",
"goal": {
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"title": "Get More Engagement",
"type": "engagement"
},
"isActive": true,
"isComplete": false,
"metrics": {
"clicks": 1,
"cpc": 0,
"cpp": 1.5,
"cpm": 1.5,
"ctr": 0,
"frequency": 0,
"impressions": 2793,
"reach": 2793
},
"network": "facebook",
"postId": "DE6gpw8kxlonHy6eb7Lo",
"spend": 4.19,
"spendDate": "2025-04-02T00:00:00.000Z",
"status": "ACTIVE"
}
],
"dateRange": {
"start": "2025-03-04T18:49:18.159Z",
"end": "2025-04-03T18:49:18.159Z",
"adId": "6683876017505"
},
"metrics": {
"totalSpend": 4.89,
"totalClicks": 3,
"totalImpressions": 10553,
"totalReach": 10339,
"averageCTR": 0.03,
"averageFrequency": 0,
"cpm": 1.460248270633943,
"cpp": 1.49047296643776,
"cpc": 5.136666666666667,
"costPerResult": 5.14,
"byGoalType": {
"engagement": {
"spend": 4.89,
"impressions": 10553,
"clicks": 3,
"reach": 10339,
"count": 2,
"ctr": 0.03,
"cpm": 1.46,
"cpp": 1.49,
"cpc": 5.14
}
},
"byGoalTitle": {
"Get More Engagement": {
"spend": 4.89,
"impressions": 10553,
"clicks": 3,
"reach": 10339,
"count": 2,
"type": "engagement",
"ctr": 0.03,
"cpm": 1.5,
"cpp": 1.49,
"cpc": 5.14
}
},
"goalPerformance": {
"bestPerformingGoalType": {
"type": "engagement",
"clicks": 3,
"spend": 4.89,
"ctr": 0.03
},
"mostEfficientGoalType": {
"type": "engagement",
"cpc": 5.14,
"spend": 4.89
}
},
"count": 2,
"firstDay": "2025-03-30T00:00:00.000Z",
"lastDay": "2025-04-03T00:00:00.000Z"
}
}
```
```json 400: Ad spend error theme={"system"}
{
"action": "get ad spend",
"status": "error",
"code": 367,
"message": "Error getting ad spend. Please verify you have an active ad account."
}
```
# Interests
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-ad-interests
GET /ads/facebook/interests
Get Facebook Ad Interests
Search for available Facebook ad targeting interests by keyword.
Use this endpoint to look up interest IDs for the [Boost Post](/docs/apis/ads/facebook/boost-post) endpoint.
This endpoint helps you discover interest-based targeting options for your Facebook ads, along with audience size estimates.
Interest IDs can be used in the `interests` array when boosting posts.
Results are cached for 10 minutes.
Use specific, relevant search terms for best results.
Facebook may return different results based on your ad account's industry and region.
The `audienceSizeLowerBound` and `audienceSizeUpperBound` fields in the JSON response provide an
estimated range of audience size for the interest and it is useful for targeting.
## Header Parameters
## Query Parameters
The search query to retrieve Facebook ad interests.
Don't forget to escape the search query, for example `Rhythm%20and%20blues%20music`.
Limit the number of ad interests returned.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.GetAsync("https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetAdInterests {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music"))
.header("Authorization", "Bearer API_KEY")
.GET()
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
uri = URI('https://api.ayrshare.com/api/ads/facebook/interests?search=Rhythm%20and%20blues%20music')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
puts res.body
```
```json 200: Success theme={"system"}
{
"status": "success",
"interests": [
{
"id": "6003195554098",
"name": "Rhythm and blues music",
"topic": "News and entertainment",
"audienceSizeLowerBound": 669180255,
"audienceSizeUpperBound": 786955980
},
{
"id": "6003470511564",
"name": "Do it yourself (DIY)",
"topic": "Hobbies and activities",
"audienceSizeLowerBound": 418387661, // Lower bound of audience size
"audienceSizeUpperBound": 492023890 // Upper bound of audience size
},
{
"id": "6002926036121",
"name": "Italy",
"topic": "Travel, places and events",
"audienceSizeLowerBound": 279313350, // Lower bound of audience size
"audienceSizeUpperBound": 328472500 // Upper bound of audience size
}
],
"count": 3,
"lastUpdated": "2025-03-27T01:01:38.547Z",
"nextUpdate": "2025-03-27T01:12:38.547Z"
}
```
```json 400: Ad interests error theme={"system"}
{
"action": "get ad interests",
"status": "error",
"code": 368,
"message": "Error getting ad interests. Please try again or contact us if the issue persists."
}
```
# Regions
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-ad-regions
GET /ads/facebook/regions
Get Facebook Ad Regions by Name
Search for regions (states, provinces, etc.) to be used for targeting when boosting an ad.
Regions use Facebook's key identifier. Use this key when boosting ads
with region targeting.
If a returned region has supportsRegion true, you can target this region. If supportsCity is
true, the region has city codes.
To get all countries that support region targeting, call this endpoint without query parameters.
Results may vary based on Facebook data availability.
## Header Parameters
## Query Parameters
The search string to filter regions. Provide a partial or full region name.
Maximum number of regions to return.
```bash cURL theme={"system"}
# All countries that support region targeting
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/ads/facebook/regions"
```
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/ads/facebook/regions?search=al"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/regions?search=al", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/regions?search=al', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/regions?search=al",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.GetAsync("https://api.ayrshare.com/api/ads/facebook/regions?search=al");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.ayrshare.com/api/ads/facebook/regions?search=al", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetAdRegions {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/regions?search=al"))
.header("Authorization", "Bearer API_KEY")
.GET()
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
uri = URI('https://api.ayrshare.com/api/ads/facebook/regions?search=al')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
puts res.body
```
```json 200: Success theme={"system"}
{
"status": "success",
"regions": [
{
"key": "3843",
"name": "Alabama",
"type": "region",
"countryCode": "US",
"countryName": "United States",
"supportsRegion": true,
"supportsCity": true
},
{
"key": "3844",
"name": "Alaska",
"type": "region",
"countryCode": "US",
"countryName": "United States",
"supportsRegion": true,
"supportsCity": true
}
],
"count": 2
}
```
```json 414: Location metadata error theme={"system"}
{
"action": "ads",
"status": "error",
"code": 414,
"message": "Error getting ad location metadata. Please try again."
}
```
# Boosted Ads
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-boosted-ads
GET /ads/facebook/ads
Get boosted ads from your Facebook account
Retrieve ads that have been boosted for a specific Facebook post.
This boosted ads endpoint provides detailed information about the boosted ads, including status, current spend, performance metrics (analytics), and preview links.
The metrics are real-time totals for the ads. If you need historical data, use the [get ad
history endpoint](/docs/apis/ads/facebook/get-ad-history).
The `previewLink` URL allows you share the preview ad with your colleagues, so that they will
see the ad for 24-hours across the various Facebook formats. Your colleagues' views of the ad
will not be counted towards your ad spend.
## Header Parameters
## Query Parameters
Retrieve all ads under the account ID.
Required if `adId`, `fbPostId`, or `postId` is not set.
Retrieve an ad with the ad ID.
Required if `accountId`, `fbPostId`, or `postId` is not set.
Retrieve ads with the [Facebook social post ID](/docs/apis/overview#social-post-id).
Required if `accountId`, `adId`, or `postId` is not set.
Retrieve a maximum of `limit` ads. Maximum is 500.
Retrieve ads with the Ayrshare [post ID](/docs/apis/overview#ayrshare-post-id).
Required if `accountId`, `adId`, or `fbPostId` is not set.
Filter ads by status of the ad. Valid values are:
`active`
`paused`
`deleted`
`archived`
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/ads/facebook/ads?adId=1234567890
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/ads?adId=1234567890", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/ads?adId=1234567890', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HistoryGETRequest_csharp
{
class History
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/ads/facebook/ads?adId=1234567890";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success with Ad ID theme={"system"}
{
"status": "success",
"ads": [
{
"postId": "DE6gpw8kxlonHy6eb721",
"ad": {
"accountId": "274948331",
"adId": "6683876017501",
"budgetRemaining": 0,
"created": "2025-03-30T10:11:34-0700",
"creativeId": "1033490148629541",
"dailyBudget": 0,
"deliveryStatus": "ACTIVE",
"endDate": "2025-04-03T22:30:00.000Z",
"fbPostId": "106638148652329_672633202087922",
"goal": {
"title": "Get More Engagement",
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"type": "engagement"
},
"isComplete": false,
"lifetimeBudget": 0,
"metrics": {
"spend": 9.21,
"impressions": 6495,
"reach": 6272,
"clicks": 3,
"ctr": 0.046189,
"cpm": 1.418014,
"cpp": 1.468431,
"frequency": 1.035555,
"uniqueClicks": 3,
"uniqueCtr": 0.047832,
"costPerUniqueClick": 3.07,
"inlineLinkClicks": 0,
"costPerInlineLinkClick": 0,
"outboundClicks": 0,
"costPerOutboundClick": 0,
"websiteCtr": [],
"accountCurrency": "USD",
"accountName": "John Doe",
"accountId": "274948331"
},
"name": "API Post - DE6gpw8kxlonHy6eb7L1 - 2025-03-30T17:11:26",
"previewLink": "https://fb.me/22Cn31wXlzhxOC1",
"spend": 9.21,
"startDate": "2025-03-30T17:11:32.000Z",
"status": "ACTIVE",
"targeting": {
"ageMax": 65,
"ageMin": 18,
"geoLocations": {
"countries": [
"US"
],
"locationTypes": [
"home",
"recent"
]
},
"interests": [
{
"id": "6003195554098",
"name": "Rhythm and blues music"
}
]
}
}
}
],
"count": 1
}
```
```json 200: Success with Account ID theme={"system"}
{
"status": "success",
"ads": [
{
"postId": "DE6gpw8kxlonHy6eb7Lo",
"ad": {
"accountId": "274948331",
"adId": "6683876017501",
"budgetRemaining": 0,
"created": "2025-03-30T10:11:34-0700",
"creativeId": "1033490148629541",
"dailyBudget": 0,
"deliveryStatus": "ACTIVE",
"endDate": "2025-04-03T22:30:00.000Z",
"fbPostId": "106638148652329_672633202087921",
"goal": {
"title": "Get More Engagement",
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"type": "engagement"
},
"isComplete": false,
"lifetimeBudget": 0,
"metrics": {
"spend": 9.21,
"impressions": 6495,
"reach": 6272,
"clicks": 3,
"ctr": 0.046189,
"cpm": 1.418014,
"cpp": 1.468431,
"frequency": 1.035555,
"uniqueClicks": 3,
"uniqueCtr": 0.047832,
"costPerUniqueClick": 3.07,
"inlineLinkClicks": 0,
"costPerInlineLinkClick": 0,
"outboundClicks": 0,
"costPerOutboundClick": 0,
"websiteCtr": [],
"accountCurrency": "USD",
"accountName": "John Doe",
"accountId": "274948331"
},
"name": "API Post - DE6gpw8kxlonHy6eb7Lo - 2025-03-30T17:11:26",
"previewLink": "https://fb.me/22Cn31wXlzhxOC1",
"spend": 9.21,
"startDate": "2025-03-30T17:11:32.000Z",
"status": "ACTIVE",
"targeting": {
"ageMax": 65,
"ageMin": 18,
"geoLocations": {
"countries": ["US"],
"locationTypes": ["home", "recent"]
},
"interests": [
{
"id": "6003195554098",
"name": "Rhythm and blues music"
}
]
}
}
},
{
"ad": {
"accountId": "274948331",
"adId": "6685225314301",
"budgetRemaining": 0,
"created": "2025-03-30T18:36:39-0700",
"creativeId": "628434386637341",
"dailyBudget": 0,
"deliveryStatus": "PAUSED",
"endDate": "2025-04-03T22:30:00.000Z",
"fbPostId": "106638148652329_672633202087921",
"goal": {
"title": "Get More Engagement",
"description": "This goal seeks to increase engagement while ensuring that the ad reaches the maximum number of unique users. It balances visibility with engagement, showing the ad to as many different people as possible who may interact with it.",
"type": "engagement"
},
"isComplete": false,
"lifetimeBudget": 0,
"metrics": {},
"name": "API Post 14 - 106638148652329_672633202087926 - 2025-03-31T01:36:32",
"previewLink": "https://fb.me/2nPlTIZEpzrCnY1",
"spend": 0,
"startDate": "2025-03-31T01:36:37.000Z",
"status": "PAUSED",
"targeting": {
"ageMax": 65,
"ageMin": 18,
"geoLocations": {
"countries": ["US"],
"locationTypes": ["home", "recent"]
},
"interests": [
{
"id": "6003195554098",
"name": "Rhythm and blues music"
}
]
}
}
}
],
"count": 2
}
```
```json 400: Submitted ads retrieval error theme={"system"}
{
"action": "get ads",
"status": "error",
"code": 370,
"message": "Error getting ads. Please try again or contact us if the issue persists."
}
```
# DSA Recommendations
Source: https://www.ayrshare.com/docs/apis/ads/facebook/get-dsa-recommendations
GET /ads/facebook/dsaRecommendations
Get Facebook DSA Recommendations
Get Digital Services Act (DSA) recommendations for your Facebook ad account.
As part of the requirements set forth by the European Union (EU) Digital Services Act (DSA), [Facebook requires ads targeting](https://www.facebook.com/business/help/605021638170961) any part of the EU to provide string values defining the beneficiary and payor of the ad being created
This endpoint provides a list of recommended DSA beneficiaries and payors that can be used when boosting posts.
These fields may be used in [`dsaBeneficiary`](/docs/apis/ads/facebook/boost-post#param-dsa-beneficiary) and [`dsaPayor`](/docs/apis/ads/facebook/boost-post#param-dsa-payor).
Outputs a list of strings (maximum 25) that Facebook has identified to likely be the
beneficiary/payor, based on recent activity of the ad account.
These recommendations can be used as values for the `dsaBeneficiary` and `dsaPayor` parameters
in the [Boost Post](/docs/apis/ads/facebook/boost-post) endpoint.
Both `dsaBeneficiary` and `dsaPayor` must be set together if either is provided when boosting
posts.
## Header Parameters
## Query Parameters
The ID of the Facebook ad account to get DSA recommendations for. The account ID can be retrieved
from the [ad accounts endpoint](/docs/apis/ads/facebook/get-ad-accounts).
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.GetAsync("https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890");
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("GET", "https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, _ := client.Do(req)
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetDsaRecommendations {
public static void main(String[] args) throws Exception {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890"))
.header("Authorization", "Bearer API_KEY")
.GET()
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
uri = URI('https://api.ayrshare.com/api/ads/facebook/dsaRecommendations?accountId=1234567890')
req = Net::HTTP::Get.new(uri)
req['Authorization'] = 'Bearer API_KEY'
res = Net::HTTP.start(uri.hostname, uri.port, use_ssl: true) { |http|
http.request(req)
}
puts res.body
```
```json 200: Success theme={"system"}
{
"status": "success",
"dsaRecommendations": [
"Beneficiary 1",
"Beneficiary 2",
"Beneficiary 3"
],
"count": 1
}
```
```json 413: DSA Recommendations Error theme={"system"}
{
"action": "ads",
"status": "error",
"code": 413,
"message": "There was an error getting the DSA recommendations. Please try again."
}
```
# Update Ad
Source: https://www.ayrshare.com/docs/apis/ads/facebook/put-ad-update
PUT /ads/facebook/ads
Update an Ad
Update the status of a boosted ad to make it active, paused, deleted, or archived.
## Header Parameters
## Body Parameters
The boosted ad ID to update.
The status of the ad. Values: `active`, `paused`, `deleted`, or `archived`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X PUT https://api.ayrshare.com/api/ads/facebook/ads
-d '{"adId": 1234567890, "status": "active"}'
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/ads/facebook/ads", {
method: "PUT",
headers: {
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({ adId: 1234567890, status: "active" })
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.put('https://api.ayrshare.com/api/ads/facebook/ads', headers=headers, json={"adId": 1234567890, "status": "active"})
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/ads/facebook/ads",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY"
],
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode(["adId" => 1234567890, "status" => "active"])
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error: " . $err;
} else {
echo $response;
}
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
var response = await client.PutAsync("https://api.ayrshare.com/api/ads/facebook/ads", new StringContent(JsonConvert.SerializeObject(new { adId = 1234567890, status = "active" }), Encoding.UTF8, "application/json"));
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
}
}
```
```go Go theme={"system"}
package main
import (
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := &http.Client{}
req, _ := http.NewRequest("PUT", "https://api.ayrshare.com/api/ads/facebook/ads", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error:", err)
return
}
defer resp.Body.Close()
body, _ := ioutil.ReadAll(resp.Body)
fmt.Println(string(body))
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class GetAdSpend {
public static void main(String[] args) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create("https://api.ayrshare.com/api/ads/facebook/ads"))
.header("Authorization", "Bearer API_KEY")
.PUT(HttpRequest.BodyPublishers.ofString(Json.stringify(new { adId = 1234567890, status = "active" })))
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
System.out.println(response.body());
} catch (Exception e) {
e.printStackTrace();
}
}
}
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'json'
require 'uri'
uri = URI.parse('https://api.ayrshare.com/api/ads/facebook/ads')
request = Net::HTTP::Put.new(uri)
request['Authorization'] = 'Bearer API_KEY'
request.body = JSON.generate({ adId: 1234567890, status: "active" })
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
puts response.body
```
```json 200: Success theme={"system"}
{
"status": "success",
"adId": "6691084804905",
"requestedStatus": "ACTIVE"
}
```
```json 400: Ad update error theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. https://www.ayrshare.com/docs/apis",
"details": "Invalid status: actives. Status must be either 'active', 'paused', 'deleted', or 'archived'."
}
```
# Ads API Overview
Source: https://www.ayrshare.com/docs/apis/ads/overview
Boost your posts by making them into Facebook ads using Ayrshare's API.
## Introduction to the Ads API
The Ayrshare Ads API provides programmatic access to create, manage, and analyze social media ads.
Currently supporting **Facebook**, the Facebook Ads API, also known as the Facebook Marketing API, allows you to transform existing posts into paid advertisements.
This includes boosting posts (transforming a post into an ad), managing ads, tracking performance, and analyzing ad spend.
Ads created and updated via Ayrshare can always be found in the Facebook Ads Manager.
Ayrshare handles all of the settings at the ad, ad set, and campaign levels.
There is never a need to manually edit any of the settings directly in the Facebook Ads Manager.
1. The Ads capabilites require the paid Ads add-on which can be enabled on the
Account page of the [web dashboard](https://app.ayrshare.com/account).
2. The
user must have [linked a payment
method](https://business.facebook.com/billing_hub/payment_settings/?placement=ads_manager)
at Facebook (Meta) prior to creating an ad.
3. User Profiles linked with a Facebook Page prior to April 1, 2025 should be
re-linked to enable ads.
For more information, see our [Facebook Ads API guide](https://www.ayrshare.com/blog/facebook-ads-api-boosting-with-the-marketing-api/).
## Create an Ad Flow
Boosting a post on Facebook is a quick and simple way to turn one of your
existing posts into an ad. Here is a high-level flow of how to implement it in
your platform:
Your user will choose the Facebook ad account which has all the billing details already configured.
Select a post from your Facebook page. It can be a photo, video, status update, etc.
> **Tip:** Posts with good organic engagement (likes, shares, comments) tend to perform better when boosted.
Your user will click a button such as "Boost Post" in your platform to start
setting up the ad.
The user can set a number of parameters.
Choose the goal strategy for this
boosted post by selecting a goal.
Customize the audience based on age, gender,
location, interests, etc.
Choose how much to spend total.
Set the
time period to run the ad.
Double-check all the settings. If everything looks good, the user will click a button such as **"Boost Post Now"** button.
Facebook will review the ad — this usually takes anywhere from a few minutes
to a few hours. Once approved, the boosted post goes live and runs according
to the setup.
Monitor the following:
* Reach
* Engagement
* Clicks
* Spend
* Budget Remaining
## Ads API Best Practices
1. **Budget Management**: Start with small test budgets (e.g., \$5-10/day) to optimize performance before scaling.
2. **Ad Duration**: Facebook requires a minimum ad runtime of approximately 30 hours between start and end times.
3. **Interest Targeting**: Choose 2-5 relevant interests for optimal targeting precision.
4. **Creative Guidelines**: Use high-quality images and concise messaging to improve engagement rates.
5. **Performance Monitoring**: Regularly check your ad performance and adjust targeting or creative elements as needed.
For detailed information about each endpoint, including request parameters, response formats, and examples, please refer to the individual API endpoint documentation pages.
# Count of Instagram Followers Online
Source: https://www.ayrshare.com/docs/apis/analytics/instagram-follower-count
GET /analytics/getInstagramOnlineFollowers
Retrieve the total historical count of your Instagram followers
Retrieve the total historical count of your Instagram followers online per hour, which allows you to optimize posting for maximum engagement.
Not available on IG Users with fewer than 100 followers.
Analytics data only available for the last 30 days.
The time period for a requested day is the previous day at T07:00:00.000Z until the current day
at T06:59:59.999Z in UTC.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
## Header Parameters
## Query Parameters
A day with format: `YYYY-MM-DD`.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
Format the output with UTC start and end dates.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/analytics/getInstagramOnlineFollowers?date=2023-12-03
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const date = "2023-12-03";
fetch(`https://api.ayrshare.com/api/analytics/getInstagramOnlineFollowers?date=${date}`, {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/analytics/getInstagramOnlineFollowers?date=2023-12-03', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
```json 200: Success theme={"system"}
{
"status": "success",
"onlineFollowersByHour": {
"0": 120, // 12 AM
"1": 113, // 1 AM
"2": 117, // 2 AM
"3": 110, // 3 AM
"4": 129, // 4 AM
"5": 170, // 5 AM
"6": 166, // 6 AM
"7": 173, // 7 AM
"8": 177, // 8 AM
"9": 168, // 9 AM
"10": 178, // 10 AM
"11": 160, // 11 AM
"12": 154, // 12 PM
"13": 153, // 1 PM
"14": 131, // 2 PM
"15": 118, // 3 PM
"16": 109, // 4 PM
"17": 128, // 5 PM
"18": 129, // 6 PM
"19": 134, // 7 PM
"20": 123, // 8 PM
"21": 111, // 9 PM
"22": 102, // 10 PM
"23": 98 // 11 PM
},
"startTime": "2024-03-29T07:00:00.000Z",
"endTime": "2024-03-30T07:00:00.000Z"
}
```
```json 200: Success formatUTC theme={"system"}
{
"status": "success",
"onlineFollowersByHour": [
{
"start": "2024-03-29T07:00:00.000Z",
"end": "2024-03-29T07:59:59.999Z",
"onlineFollowers": 33
},
{
"start": "2024-03-29T08:00:00.000Z",
"end": "2024-03-29T08:59:59.999Z",
"onlineFollowers": 90
},
{
"start": "2024-03-29T09:00:00.000Z",
"end": "2024-03-29T09:59:59.999Z",
"onlineFollowers": 21
},
{
"start": "2024-03-29T10:00:00.000Z",
"end": "2024-03-29T10:59:59.999Z",
"onlineFollowers": 109
},
{
"start": "2024-03-29T11:00:00.000Z",
"end": "2024-03-29T11:59:59.999Z",
"onlineFollowers": 99
},
{
"start": "2024-03-29T12:00:00.000Z",
"end": "2024-03-29T12:59:59.999Z",
"onlineFollowers": 10
},
{
"start": "2024-03-29T13:00:00.000Z",
"end": "2024-03-29T13:59:59.999Z",
"onlineFollowers": 82
},
{
"start": "2024-03-29T14:00:00.000Z",
"end": "2024-03-29T14:59:59.999Z",
"onlineFollowers": 101
},
{
"start": "2024-03-29T15:00:00.000Z",
"end": "2024-03-29T15:59:59.999Z",
"onlineFollowers": 91
},
{
"start": "2024-03-29T16:00:00.000Z",
"end": "2024-03-29T16:59:59.999Z",
"onlineFollowers": 12
},
{
"start": "2024-03-29T17:00:00.000Z",
"end": "2024-03-29T17:59:59.999Z",
"onlineFollowers": 93
},
{
"start": "2024-03-29T18:00:00.000Z",
"end": "2024-03-29T18:59:59.999Z",
"onlineFollowers": 21
},
{
"start": "2024-03-29T19:00:00.000Z",
"end": "2024-03-29T19:59:59.999Z",
"onlineFollowers": 95
},
{
"start": "2024-03-29T20:00:00.000Z",
"end": "2024-03-29T20:59:59.999Z",
"onlineFollowers": 97
},
{
"start": "2024-03-29T21:00:00.000Z",
"end": "2024-03-29T21:59:59.999Z",
"onlineFollowers": 101
},
{
"start": "2024-03-29T22:00:00.000Z",
"end": "2024-03-29T22:59:59.999Z",
"onlineFollowers": 74
},
{
"start": "2024-03-29T23:00:00.000Z",
"end": "2024-03-29T23:59:59.999Z",
"onlineFollowers": 61
},
{
"start": "2024-03-30T00:00:00.000Z",
"end": "2024-03-30T00:59:59.999Z",
"onlineFollowers": 31
},
{
"start": "2024-03-30T01:00:00.000Z",
"end": "2024-03-30T01:59:59.999Z",
"onlineFollowers": 28
},
{
"start": "2024-03-30T02:00:00.000Z",
"end": "2024-03-30T02:59:59.999Z",
"onlineFollowers": 19
},
{
"start": "2024-03-30T03:00:00.000Z",
"end": "2024-03-30T03:59:59.999Z",
"onlineFollowers": 21
},
{
"start": "2024-03-30T04:00:00.000Z",
"end": "2024-03-30T04:59:59.999Z",
"onlineFollowers": 23
},
{
"start": "2024-03-30T05:00:00.000Z",
"end": "2024-03-30T05:59:59.999Z",
"onlineFollowers": 92
},
{
"start": "2024-03-30T06:00:00.000Z",
"end": "2024-03-30T06:59:59.999Z",
"onlineFollowers": 32
}
],
"startTime": "2024-03-29T07:00:00.000Z",
"endTime": "2024-03-30T07:00:00.000Z"
}
```
```json 200: Success No Data theme={"system"}
{
"status": "success",
"onlineFollowersByHour": {}
}
```
```json 400: Incorrect date theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Analytics API Overview
Source: https://www.ayrshare.com/docs/apis/analytics/overview
Get real-time analytical data for posts and social accounts, such as clicks, likes, shares, followers, and impressions
One of the key capabilities of Ayrshare is the ability to get real-time analytics on your posts and social accounts.
Specifically, you can measure and analyze your users' content performance and engagement, such as video views, likes, link clicks, and shares, and the influence of your users.
With the analytics data, you can build custom reports for your users, feed the data back into your AI model, or do analysis of post performance.
There are three main type of analytics endpoints:
1. Post Analytics: Get analytics on a post
2. Social Analytics: Get analytics on a social account
3. Link Analytics: Get analytics on a shortened link
## Post Analytics
Individual post analytics are available. This is great if you want detailed analytics on a particular post, either one sent via Ayrshare or manually published at the social network.
Post analytics are available for the following social networks:
Bluesky
Facebook
Instagram
LinkedIn
Pinterest
Reddit
Snapchat
Threads
TikTok
YouTube
X/Twitter
The analytics may be retrieved for a specific post by providing either the Ayrshare post ID or the original post's Social Post ID.
## Social Analytics
You can also get the account level social analytics, such as engagement, follower count and demographics, and account meta data.
Use this endpoint if you want to get the analytics for an entire social account, rather than a specific post.
Social account level analytics are available for the following social networks:
Facebook
Google Business Profile
Instagram
LinkedIn
Pinterest
Reddit
Snapchat
Threads
TikTok
YouTube
X/Twitter
You may also choose to get aggregated summary or daily social analytics.
## Link Analytics
You can also get analytics on a shortened link. This is great if you want to know how many clicks a link has received, either one sent via Ayrshare or manually published at the social network.
Link analytics can be found in the /links endpoint.
Get analytics on a shortened link.
# Analytics on a Post
Source: https://www.ayrshare.com/docs/apis/analytics/post
POST /analytics/post
Retrieve real-time likes, impressions, views, and reactions for a post sent via Ayrshare, with multiplatform partial-success handling.
Get real-time analytics such as likes, impressions, views, and reactions for a post that was sent via Ayrshare using the [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id).
For analytics on posts originating outside of Ayrshare, see [Analytics by Social Post ID](/docs/apis/analytics/social-by-id).
**Facebook: some reach and video metrics were retired by Meta (June 15, 2026).** Meta removed the unique-impression and 3-second video-view Insights metrics across all Graph API versions, so the Facebook `analytics` object no longer returns `impressionsUnique`, `impressionsFanUnique`, `impressionsOrganicUnique`, `impressionsPaidUnique`, or `videoViewsUnique`. Use `mediaView` for reach (a Total Unique Media Views successor is planned). Other commonly used fields such as `reactionsByType` and `videoViews` are unaffected. Reference: [Upcoming API Changes — June 15, 2026](/docs/whatsnew/upcoming-api-changes#june-15-2026).
#### Additional Information
The following platforms are currently supported: Bluesky, Facebook Pages, Instagram, X/Twitter, LinkedIn, Pinterest, Reddit, Snapchat, Threads, TikTok, and YouTube.
Facebook and Instagram comment counts shown in the API may differ from counts displayed in the social apps. This occurs for two reasons: - Some users have privacy settings that hide their comments from non-friends or users without mutual connections. These private comments are still included in the total comment count. - There may be inconsistencies in the data reported by Meta.
Instagram igReelsAggregatedAllPlaysCount and playsCount shown in the API may differ from the counts displayed in the social apps. This can occur for a couple of reasons:
The post was promoted. Only organic plays are included in the API response.
There may be inconsistencies in the data reported by Meta.
X/Twitter Threads return as an Array of objects, with each object corresponding to a Tweet in the Thread.
YouTube can take 24-48 hours to process analytics for videos with few video views or channel followers.
TikTok Analytics:
TikTok can take 24-48 hours to update their analytics data, such as video views, demographics, likes, shares, and comments.
For TikTok analytics access, account owners must: 1. Publish at least one video. 2. Tap the "[Turn On](https://www.tiktok.com/feedback?id=7133058093574806018\&lang=en\&type=)" button on the Analytics page of their mobile TikTok app. 3. Have 100 followers to receive additional insights about viewers and content engagement.
TikTok does not return post analytics if the media contains copyrighted material or has been flagged for a copyright violation. Examples of copyrighted material can include audio on reels (TikTok will mute these videos). You can check in the TikTok app under Activity -> System Notifications.
Some TikTok analytics fields may be unavailable if the video has been inactive for more than 7 days. To retrieve this data, generate new activity on the video (view, like, comment, or share) and retry after 24-48 hours. If a video is not returned in the response, the reason is likely to be that the video has been filtered out due to violations, such as music copyright violation. These fields include:
`reach`
`fullVideoWatchedRate`
`totalTimeWatched`
`averageTimeWatched`
`impressionSources`
`audienceCountries`
LinkedIn personal (member) profiles now return an expanded post analytics matrix. The available member metrics are:
`impressionCount` — Impressions on the post
`uniqueImpressionsCount` — Unique members reached (LinkedIn `MEMBERS_REACHED`)
`likeCount` — Reaction count
`commentCount` — Comments count
`shareCount` — Reshares of the post
`engagement` — Organic clicks, likes, comments, and shares over impressions
`reactions` — Per-type reaction breakdown (when reactions are present)
For video posts: `videoViews`, `videoViewers`, and `videoWatchTimeMs`
Video metrics are only returned for video posts and are unavailable more than one year after the post was created.
Instagram Story insights are only available for 24 hours, regardless of whether stories are archived or highlighted. Note:
Story media metrics with values less than `5` return as `0`.
For Stories created by users in Europe and Japan, the `replies` metric returns a value of `0`.
Facebook Story analytics are not available.
Pinterest analytics data (impressions, user followers, and clicks) becomes available after 24-72 hours.
For YouTube Shorts, views will return the number of times a Short starts to play or replay, with no minimum watch time requirement.
## Multiplatform Reads & Partial Success
A single [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id) can span several platforms. Ayrshare fans out one request ("leg") per platform and returns a **partial success** when some legs succeed and others fail — the healthy platforms' analytics are always returned, and each failed leg is enumerated in a top-level `errors[]` array.
Some platforms succeed, some fail: the response is HTTP 200 with status: "partial". The healthy per-platform `analytics` blocks are returned as usual, and a top-level errors\[] array lists every failed leg with its platform, status, code, message, and id.
Every platform fails: the response has status: "error" and the full errors\[] array. The HTTP status is mapped from the representative top-level error code. Code 485 maps to HTTP 404; other representative codes use their own mappings.
All platforms succeed: the response is unchanged — HTTP 200, status: "success", and no errors\[] key.
**Behavior change — inspect `errors[]`, don't branch on HTTP status.** Because a multiplatform read with a failing leg now returns HTTP `200` instead of collapsing the whole response to an error, integrators should always check for the presence of a top-level `errors[]` array to detect per-platform failures rather than relying on the HTTP status code alone.
### Expired or Unavailable Instagram Story Analytics
An Instagram Story analytics leg that is expired or unavailable — so its insights cannot be retrieved — surfaces in `errors[]` with code [`485`](/docs/errors/errors-ayrshare#expired-or-unavailable-story-errors). A representative message is *"Instagram Story expired or unavailable — comments/insights cannot be retrieved."* Facebook Story analytics remain unavailable and are not covered by this behavior. If another platform succeeds, its analytics are still returned and the overall response is **HTTP `200`**. For an all-fail response, representative code `485` maps to HTTP `404`; other representative codes use their own mappings. Match on the `code` (`485`), not the exact message text. (See also the note above: Instagram Story insights are only available for 24 hours.)
#### Example: Partial Success Response
```json 200: Partial Success theme={"system"}
{
"facebook": {
"id": "1397547544885713_2159201585286968",
"postUrl": "https://www.facebook.com/1397547544885713_2159201585286968",
"analytics": {
"commentsCount": 1,
"likeCount": 23,
"sharesCount": 12,
"mediaView": 450
},
"lastUpdated": "2026-07-14T18:44:29.778Z",
"nextUpdate": "2026-07-14T19:19:29.778Z"
},
"status": "partial",
"id": "IHvCLacgPc6hMU9IQ6oK",
"errors": [
{
"platform": "instagram",
"status": "error",
"code": 485,
"message": "Instagram Story expired or unavailable — comments/insights cannot be retrieved.",
"id": "17895695668004550"
}
]
}
```
## Header Parameters
## Body Parameters
[Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id) returned from the [/post
endpoint](/docs/apis/post/post). This is the top-level Ayrshare `id` returned and not the social post
ids in `postIds`.
String array of platforms to retrieve analytics. Accepts an array of strings with values:
```json theme={"system"}
{
"platforms": [
"bluesky",
"facebook",
"instagram",
"linkedin",
"pinterest",
"reddit",
"snapchat",
"threads",
"tiktok",
"twitter",
"youtube"
]
}
```
If platforms is not included, analytics will be returned for all social networks to which the post was sent.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"id": "Post ID",
"platforms": ["bluesky", "facebook", "instagram", "linkedin",
"pinterest", "snapchat", "threads", "tiktok", "twitter", "youtube"]}' \
-X POST https://api.ayrshare.com/api/analytics/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/analytics/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
id: "Post ID", // required
platforms: [
"bluesky",
"facebook",
"instagram",
"linkedin",
"pinterest",
"snapchat",
"threads",
"tiktok",
"twitter",
"youtube"
] // optional
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': 'Post ID',
'platforms': ['bluesky', 'facebook', 'instagram', 'linkedin',
'pinterest', 'snapchat', 'threads', 'tiktok', 'twitter', 'youtube']}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/analytics/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
'Post ID', // Replace with your actual Post ID
'platforms' => ['bluesky', 'facebook', 'instagram', 'linkedin',
'pinterest', 'snapchat', 'threads', 'tiktok', 'twitter', 'youtube'] // optional
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"id": "Post ID",
"platforms": []string{"bluesky", "facebook", "instagram", "linkedin",
"pinterest", "snapchat", "threads", "tiktok", "twitter", "youtube"},
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/analytics/post",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostAnalyticsPOSTRequest_csharp
{
class PostAnalytics
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/analytics/analytics/post";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"id\": \"Post ID\"," +
"\"platforms\": [\"bluesky\", \"facebook\", \"instagram\", \"linkedin\", \"pinterest\", \"snapchat\", \"tiktok\", \"twitter\", \"youtube\"]}";
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
When cumulative metrics (e.g., likes, comments, views) are temporarily unavailable from the social network, the API automatically backfills them from stored data. Two optional fields may appear in the per-platform `analytics` object:
* **`backfilledFrom`** (string, ISO 8601) — Present when one or more cumulative metrics were substituted from stored data. The timestamp indicates when the stored data was last updated.
* **`recoveredFrom`** (string, ISO 8601) — Present when the entire analytics response was recovered from stored data due to a complete API failure. The timestamp indicates when the stored data was last updated.
Stored data older than 4 days is considered stale and will not be used for backfill or recovery.
**LinkedIn personal (member) analytics — re-link required.** Personal LinkedIn profiles linked before member post analytics shipped do not have the required analytics scopes. Analytics requests for those profiles return [error code `475`](/docs/errors/errors-ayrshare#linkedin-analytics-errors) ("re-link your LinkedIn profile to enable analytics"). The account owner must re-link their LinkedIn profile on the Social Accounts page to grant the new scopes. Allow a few minutes after re-linking for code `475` to clear (Ayrshare and LinkedIn both briefly cache the permission state, typically \~5-10 minutes). Posting is unaffected.
LinkedIn member post counts are best-effort: the aggregate `shareCount` (RESHARE), `likeCount` (REACTION), and `commentCount` (COMMENT) totals may differ slightly from the numbers shown in the LinkedIn UI.
```json 200: Response {2, 24, 171, 253, 287, 331, 401, 417, 449, 463, 598, 751} theme={"system"}
{
"bluesky": {
"id": "at://did:plc:n7atrjd22xgkmgwig6dzlhzd/app.bsky.feed.post/3lez7fwx457", // Bluesky Social Post ID
"postUrl": "https://bsky.app/profile/madworlds.bsky.social/post/3lez7fwx457",
"analytics": {
"cid": "bafyreigh7nz7x6pl4atgsextqtcbh33mg66yqt3caeihutn7ojkmpdtnzm", // Bluesky Content ID
"created": "2025-01-05T18:04:28.316Z",
"id": "at://did:plc:n7atrjd22xgkmgwig6dzlhzd/app.bsky.feed.post/3lfb57nxgxs2e", // Bluesky Social Post ID
"indexedAt": "2025-01-05T18:04:29.150Z",
"labels": [],
"likeCount": 3,
"post": "The day is what you make it!",
"postUrl": "https://bsky.app/profile/madworlds.bsky.social/post/3lez7fwx45723",
"quoteCount": 2,
"replyCount": 1,
"repostCount": 1,
"viewer": { // Information about the viewing user's relationship
"threadMuted": false, // Whether the viewing user has muted the thread containing this content
"embeddingDisabled": false // Whether embedding/sharing of this content is disabled for the viewing user
}
}
},
/* If the FB page has fewer than 100 likes then not all analytics data available. */
"facebook": {
"id": "1397547544885713_2159201585286968", // Facebook Social Post ID
"postUrl": "https://www.facebook.com/1397547544885713_2159201585286968",
"analytics": {
"blueReelsPlayCount": 136, // Reels: The number of times your reel starts to play after an impression is already counted. This is defined as reels sessions with 1ms or more of playback and excludes replays.
"commentsCount": 1, // Count of comment for the post
// impressionsFanUnique / impressionsOrganicUnique / impressionsPaidUnique / impressionsUnique were retired by Meta (June 15, 2026); see the note at the top of this page.
"likeCount": 23, // Count of likes for the post
"likedBy": [ // Users who liked the post
{
"id": "7101149746568432",
"name": "John Smith"
}
],
"mediaUrls": [
{
"media": {
"image": {
"height": 405,
"src": "https://scontent-lga3-1.xx.fbcdn.net/v/t",
"width": 720
},
"source": "https://video-lga3-2.xx.fbcdn.net/o1/v/t2/f2/m69/AQN"
},
"mediaType": "video",
"type": "story"
}
],
"mediaView": 12, // The number of times this post was played or displayed. Content includes videos, posts, stories and ads.
"mediaViewIsFromAds": 0, // The number of times this post was played or displayed from ads.
"mediaViewIsFromFollowers": 0, // The number of times this post was played or displayed from followers.
"postVideoAvgTimeWatched": 4470, // Reels: The average time (in ms) your reel was played, including any time spent replaying the reel during a single instance of it playing. Because this metric includes replays, this number could be greater than the total length of the reel
"postVideoSocialActions": { // Reels: The number of comments, shares, and reactions on your reel
"share": 1
},
"postVideoViewTime": 608011, // Reels: Total time (in ms) your reel was played, including any time spent replaying your reel.
"reactions": {
"like": 1, // Like reactions - The "like" reaction counts include both "like" and "care" reactions.
"love": 1, // Love reactions
"anger": 1, // Anger reactions
"haha": 1, // Haha reactions
"wow": 1, // Wow reactions
"sorry": 1, // Sorry reactions
"total": 6 // Total number of reactions
},
"reactionsByType": 6, // The total types of reactions
"sharesCount": 34, // Total number of times post shared
/** The following fields are available for videos */
"totalVideo10SViews": 621, // Total number of times your video was viewed for 10 seconds or viewed to the end, whichever came first.
"totalVideo10SViewsAutoPlayed": 564, // Number of times people clicked to play your video and viewed it for 10 seconds or viewed it to the end, whichever came first.
"totalVideo10SViewsClickedToPlay": 46, // Number of times your video started automatically playing and people viewed it for 10 seconds, or viewed it to the end, whichever came first.
"totalVideo10SViewsOrganic": 621, // Number of times your video was viewed for 10 seconds or viewed to the end, whichever came first, without a paid promotion.
"totalVideo10SViewsPaid": 0, // Number of times your video was viewed for 10 seconds or viewed to the end, whichever came first, after a paid promotion.
"totalVideo10SViewsSoundOn": 380, // Number of times your video sound was turned on and was viewed for 10 seconds or viewed to the end, whichever came first.
"totalVideo10SViewsUnique": 621, // Number of unique people who viewed your video for 10 seconds or viewed to the end, whichever came first.
"totalVideo15SViews": 525, // Total number of times your video was viewed for at least 15 seconds.
"totalVideo60SExcludesShorterViews": 0, // Total number of times your video was viewed for 60 seconds only if the video is 60 seconds or longer.
"totalVideoAvgTimeWatched": 8494, // Lifetime: Average time video viewed
"totalVideoCompleteViews": 430, // Total number of times your video was watched at 95% of its length, including watches that skipped to this point.
"totalVideoCompleteViewsAutoPlayed": 374, // Number of times your video started automatically playing and people watched it at 95% of its length, including watches that skipped to this point.
"totalVideoCompleteViewsClickedToPlay": 56, // Number of times people clicked to play your video and watched it at 95% of its length, including watches that skipped to this point.
"totalVideoCompleteViewsOrganic": 430, // Number of times your video was watches at 95% of its length without any paid promotion, including watches that skipped to this point.
"totalVideoCompleteViewsOrganicUnique": 430, // The number of unique people who watched your video at 95% of its length without any paid promotion, including people that skipped to this point
"totalVideoCompleteViewsPaid": 0, // Number of times your video was watched at 95% of its length after paid promotion, including watches that skipped to this point.
"totalVideoCompleteViewsPaidUnique": 0, // The number of unique people who watched your video at 95% of its length after paid promotion, including people that skipped to this point.
"totalVideoCompleteViewsUnique": 430, // Total number of unique people who watched your video at 95% of its length or more, including people that skipped to this point.
// The totalVideoImpressions* family (Video Impressions) was retired by Meta (June 15, 2026); see the note at the top of this page.
"totalVideoReactionsByTypeTotal": { // The total number of reactions to your post by type.
"like": 13,
"haha": 2
},
"totalVideoStoriesByActionType": { // Number of stories created about your Page Video, by action type.
"like": 15
},
"totalVideoViewTimeByAgeBucketAndGender": { // Video view time (in ms) by age bucket and gender.
"f1317": 23521,
"m1317": 184052,
"u1824": 2774,
"f1824": 118193,
"m1824": 1340281,
"u2534": 11975,
"f2534": 407006,
"m2534": 3960750,
"u3544": 27054,
"f3544": 332576,
"m3544": 5477331,
"u4554": 41804,
"f4554": 375449,
"m4554": 3794202,
"u5564": 35717,
"f5564": 159041,
"m5564": 3582574,
"u65+": 8245,
"f65+": 423739,
"m65+": 2866201
},
"totalVideoViewTimeByDistributionType": { // Video view time (in ms) by distribution type. On asset level, there are three possible distribution types: (page_owned/shared/crossposted)
"pageOwned": 23172485
},
"totalVideoViewTimeByRegionId": { // Video view time (in ms) by region ID.
"californiaUnitedStates": 791788,
"texasUnitedStates": 480891,
"karnatakaIndia": 390297,
"uttarPradeshIndia": 368698,
"tamilNaduIndia": 359103,
"queenslandAustralia": 295491,
"newSouthWalesAustralia": 284222,
"newYorkUnitedStates": 250035,
"maharashtraIndia": 248465,
"washingtonUnitedStates": 237430
},
"totalVideoViewTotalTime": 23172485, // Total time (in ms) video has been viewed.
"totalVideoViewTotalTimeOrganic": 23172485, // Total time (in ms) video has been viewed in Feed or ticker or on your Page's Timeline.
"totalVideoViewTotalTimePaid": 0, // Total time (in ms) video has been viewed after paid promotion.
"totalVideoViews": 1283,
"totalVideoViewsAutoplayed": 1237, // Number of times your video started automatically playing and people viewed it for 3 seconds or viewed it to the end, whichever came first.
"totalVideoViewsByDistributionType": { // Video views by distribution type. On asset level, there are three possible distribution types: (page_owned/shared/crossposted)
"pageOwned": 1283
},
"totalVideoViewsClickedToPlay": 46, // Number of times people clicked to play your video and viewed it for 3 seconds or viewed it to the end, whichever came first.
"totalVideoViewsOrganic": 1283, // Number of times your video was viewed for 3 seconds or viewed to the end, whichever came first, without any paid promotion.
"totalVideoViewsPaid": 0, // Number of times your video was viewed for 3 seconds or viewed to the end, whichever came first, after paid promotion.
"totalVideoViewsSoundOn": 743, // Number of times your video sound was turned on and was viewed for 3 seconds or viewed to the end, whichever came first.
"videoViews": 3 // Times your videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds. During a single instance of a video playing, we'll exclude any time spent replaying the video. This includes live views.
// videoViewsUnique was retired by Meta (June 15, 2026); see the note at the top of this page.
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
"instagram": {
"id": "17856916804532520", // Instagram Social Post ID
"postUrl": "https://www.instagram.com/p/ChALNdaOT3G/",
"analytics": {
/* FEED Data */
"caption": "It always seems impossible until it's done. - Nelson Mandela",
"commentsCount": 1, // Comments total
"created": "2022-09-07T22:39:06Z", // Time post was created
"engagementCount": 3, // Likes, comments, and saves
"followsCount": 2, // Number of followers gained
"likeCount": 1, // Likes total - organic likes, promoted post likes not included
"mediaProductType": "FEED", // Type of IG Share: AD, FEED, STORY or REELS
"mediaType": "IMAGE", // Media type: CAROUSEL_ALBUM, IMAGE, or VIDEO
"mediaUrls": [
{
"mediaUrl": "https://scontent.cdninstagram.com/v/t51.82787-15/516601117_17872451562389336_3472858781474899926_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=107&ccb=1-7&_nc_sid=18de74&_nc_ohc=-LOY7upopXoQ7kNvwEkqUMq&_nc_oc=AdmN47ZBlmciajpv7udoP1ku6J-FBgBGIrRskGgPmIOjT5D3WI9F21_Fg1Gi60-aI70&_nc_zt=23&_nc_ht=scontent.cdninstagram.com&edm=AEQ6tj4EAAAA&_nc_gid=PZY4V4Pvo8ePuq2CfSBp1A&oh=00_AfQplZLqrCEYwXkCutbmMAGIgpcBUkKqGcfRdDLZU4QHRA&oe=6872DFF9"
}
],
"profileActivityCount": 1,// The number of actions people take when they visit your profile after engaging with your post
"profileVisitsCount": 11, // The number of times your profile was visited.
"reachCount": 71, // Unique accounts that have seen the post
"savedCount": 1, // Unique accounts have saved the post
"sharesCount": 12, // Number of times the post was shared
"username": "jackthegiant",
"viewsCount": 71, // Total number of times the post has been seen.
/* REELS Data */
"caption": "Gorgeous gifts for new Mum & Bub \n\n@mikimoocreations @romperandco @obdesigns @salusbody @enaproducts",
"clipsReplaysCount": 21, // The number of times your reel starts to play again after an initial play of your reel. This is defined as replays of 1ms or more in the same reel session.
"commentsCount": 1, // Comments total
"created": "2022-09-15T06:58:55Z",
"engagementCount": 183, // Number of likes, saves, comments, and shares on the reel, minus the number of unlikes, unsaves, and deleted comments.
"igReelsAggregatedAllPlaysCount": 42, // The number of times your reel starts to play or replay after an impression is already counted. This is defined as plays of 1ms or more. Replays are counted after the initial play in the same reel session. Organic plays only; promoted post plays are not included.
"igReelsAvgWatchTimeCount": 23, // The average amount of time spent playing the reel. This is calculated by the watch time divided by the number of plays.
"igReelsVideoViewTotalTimeCount": 21, // The total amount of time the reel was played, including any time spent replaying the reel.
"likeCount": 21, // Likes total on the reel
"mediaProductType": "REELS", // Type of IG Share: AD, FEED, STORY or REELS
"mediaType": "VIDEO", // Always "VIDEO"
"mediaUrls": [
{
"mediaUrl": "https://instagram.flis9-1.fna.fbcdn.net/o1/v...amug&oe=686ED4D3"
}
],
"playsCount": 680, // Number of times the reels starts to play after an impression is already counted. This is defined as video sessions with 1 ms or more of playback and excludes replays. Organic plays only; promoted post plays are not included.
"reachCount": 689, // Number of unique accounts that have seen the reel at least once. Reach is different from impressions, which can include multiple views of a reel by the same account.
"savedCount": 0, // Number of saves of the reel.
"sharesCount": 2, // Number of shares of the reel.
"username": "mordiallocflorist",
"viewsCount": 40, // Total number of times the reel has been seen.
/* STORY Data - Fewer than 5 insights will not show metric data. */
"commentsCount": 2,
"created": "2024-09-16T08:37:57Z",
"engagementCount": 10,
"followsCount": 0,
"likeCount": 3,
"mediaProductType": "STORY",
"mediaType": "IMAGE",
"mediaUrls": [
{
"mediaUrl": "https://scontent.cdninstagram.com/v/t51.82787-15/517935...we32"
}
],
"notEnoughViews": true, // True if fewer than 5 unique insights. If fewer than 5 unique insights, metric data not available.
"navigationCount": 15, // Total nav interactions of taps and swipes
"profileActivityCount": 3,
"profileVisitsCount": 1,
"reachCount": 10,
"repliesCount": 3,
"sharesCount": 2,
"swipeForwardCount": 1, // Swipes "Next Story" on the native interface.
"tapBackCount": 2, // Taps "Back" on the native interface.
"tapForwardCount": 9, // Taps "Forward" on the native interface.
"tapExitCount": 3, // Taps "Exit" on the native interface.
"username": "ayrshare",
"viewsCount": 10, // Total number of times the story has been seen.
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
/* Corporate LinkedIn Account Example. Past 12 months, using a rolling 12-month window. */
"linkedin": {
"id": "6783586276949000192", // LinkedIn Social Post ID
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:6783586276949000192",
"type": "corporate", // corporate or personal. Please see notes on personal analytics
"analytics": {
"clickCount": 0, // Clicks on a post - company only
"commentCount": 0, // Comments count
"comments": [ // Comment IDs - can be used to look up comments
"urn:li:comment:(urn:li:activity:7226002855806021632,7226004971362627585)"
],
"commentsState": "OPEN", // Comments allowed or not
"engagement": 0, // Organic clicks, likes, comments, and shares over impressions - company only
"impressionCount": 0, // Impressions on a post - company only
"likeBy": [
"urn:li:person:Z_yXaxh_AB" // Look up the user with the brands endpoint
],
"likeCount": 1, // Likes on a count
"reactions": { // Get reactions on a LinkedIn share
"like": 1, // "Like in the UI
"praise": 2, // "Celebrate" in the UI
"maybe": 3, // "Curious" in the UI
"empathy": 3, // "Love" in the UI
"interest": 2, // "Insightful" in the UI
"appreciation": 5 // "Support" in the UI
},
"shareCount": 0, // Shares on a post - company only
"totalFirstLevelComments": 1, // COunt of the firt level comments
"uniqueImpressionsCount": 0, // Unique impressions for a post - company only
"videoViews": 1 // Number of times video viewed - company only
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
/* Personal LinkedIn Account Example. Past 12 months, using a rolling 12-month window. */
"linkedin": {
"id": "urn:li:share:7221186087895920444",
"type": "personal",
"analytics": {
"commentCount": 12, // Comments count
"comments": [
"urn:li:comment:(urn:li:activity:7221186088390799360,7224469537784479744)"
],
"commentsState": "OPEN",
"engagement": 0.07, // Organic clicks, likes, comments, and shares over impressions
"impressionCount": 1543, // Impressions on the post
"likeBy": [
{
"from": {
"name": "John Smith",
"id": "qDyUWJx2s",
"url": "https://www.linkedin.com/in/js",
"description": "Business Analyst at Ayrshare"
},
"media": {
"id": "urn:li:image:C4D03AQG_8MpwM6tDzw",
"mediaExpiresSeconds": 1728518400000,
"url": "https://media.licdn.com/dms/image/C4D03AQG_8MpwM6tDzw"
},
"platform": "linkedin",
"profileImageUrl": "https://media.licdn.com/dms/image/C4D03AQG_8MpwM",
"userName": "js",
"originalUrn": "urn:li:like:(urn:li:person:qDyUWJxqIO,urn:li:activity:722118608839074444)",
"type": "like"
}
],
"likeCount": 87, // Reaction count
"reactions": { // Per-type reaction breakdown
"like": 60,
"praise": 15,
"maybe": 0,
"empathy": 12,
"interest": 0,
"appreciation": 0
},
"share": "urn:li:activity:7221186088390794444",
"shareCount": 9, // Reshares of the post
"totalFirstLevelComments": 1,
"uniqueImpressionsCount": 1201, // Unique members reached (MEMBERS_REACHED)
"videoViewers": 280, // Video posts only
"videoViews": 320, // Video posts only
"videoWatchTimeMs": 451000 // Video posts only
},
"lastUpdated": "2024-08-04T22:46:15.660Z",
"nextUpdate": "2024-08-04T22:57:15.660Z"
},
"pinterest": {
"id": "718464946813167315", // Pinterest Social Post ID
"postUrl": "https://www.pinterest.com/pin/718464946813167315/",
"analytics": {
"altText": "Hello",
"boardId": "480126078963936788",
"boardOwner": {
"username": "johnsmith"
},
"boardSectionId": 12232,
"createdAt": "2024-10-20T06:25:08",
"creativeType": "REGULAR",
"description": "The most amazing board",
"dominantColor": "#4e6279",
"hasBeenPromoted": false,
"id": "480126010294119688",
"impression": 26,
"isOwner": true,
"isStandard": true,
"link": "https://www.mywebsite.com",
"media": {
"media_type": "image",
"images": {
"150x150": {
"width": 150,
"height": 150,
"url": "https://i.pinimg.com/150x150/2b/86/64/2b.jpg"
},
"400x300": {
"width": 400,
"height": 300,
"url": "https://i.pinimg.com/400x300/2b/86/64/2b.jpg"
},
"600x": {
"width": 564,
"height": 296,
"url": "https://i.pinimg.com/564x/2b/86/64/2b.jpg"
},
"1200x": {
"width": 1200,
"height": 630,
"url": "https://i.pinimg.com/1200x/2b/86/64/2b.jpg"
}
}
},
"note": "",
"outboundClick": 4,
"parentPinId": 23233,
"pinClick": 2,
"pinMetrics": null,
"productTags": [],
"profileVisit": 5, // Available for images only
"quartile95PercentView": 4,
"save": 1,
"saveRate": 1,
"title": "Looking great",
"totalComments": 2,
"totalReactions": 1,
"userFollow": 1, // Available for images only
/* Available for videos */
"video10sView": 3,
"videoAvgWatchTime": 0,
"videoMrcView": 0,
"videoStart": 0,
"videoV50WatchTime": 0
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
"reddit": {
"id": "182zitr",
"postUrl": "https://www.reddit.com/r/test/comments/182zitr/reddit_post_title/",
"analytics": {
"author": "ayrshare",
"created": "2023-11-24T19:10:06.000Z",
"permalink": "/r/test/comments/182zitr/reddit_post_title/",
"subreddit": "test",
"title": "Reddit Post Title",
"ups": 2,
"upvoteRatio": 1,
"url": "https://www.reddit.com/r/test/comments/182zitr/reddit_post_title/"
},
"lastUpdated": "2023-11-24T19:10:41.635Z",
"nextUpdate": "2023-11-24T19:21:41.635Z"
},
"snapchat": {
"id": "490edf20-4068-5bab-bf65-a5882b1ezuec",
"postUrl": "https://www.snapchat.com/add/chrisalpha1980/490edf20-4068-5bab-bf65-a5882b1ezuecc",
"analytics": [
{
"avgViewTime": 5230, // Average view time in milliseconds
"completes": 187, // Number of times the post was played to completion
"interactions": 42, // Number of times a user interacted with an asset. These include: tap forwards/backwards, swipe-away
"mediaId": "490edf20-4068-5bab-bf65-a5882b1ezuec",
"replies": 8, // Number of replies to this snap/story
"shares": 12, // Number of times this post has been shared
"snapCombinedUniques": 642, // Combined total of snapPaidUniques and storyUniques
"snapCombinedViews": 829, // Combined total of snapPaidViews and views
"snapPaidUniques": 174, // The sum of paid uniques for ads promoting the snaps within the Public Story
"snapPaidViews": 203, // The sum of paid impression for ads promoting the snaps within the Public Story
"storyAvgViewTime": 4870, // The calculation of the storyViewTime divided by storyUniques (milliseconds)
"storyFavorites": 28, // Number of times the post has been liked
"storySubscribes": 5, // Number of subscribe events occuring on the story post
"storyUniques": 468, // Unique users who have viewed a story/snap within a story
"storyViewTime": 2279160, // Milliseconds a story & snap in story asset has been viewed
"storyViews": 626, // Views for Story container
"swipeDowns": 15, // Number of swipe downs on this post
"swipeUps": 23, // Number of swipe ups on this post
"uniqueSessions": 512, // Number of unique sessions an asset has been engaged in
"viewTime": 3264000, // Milliseconds this post has been viewed
"viewers": 598, // Number of unique users who have viewed this post
"views": 712 // Number of times an asset has been viewed
}
],
"lastUpdated": "2025-05-21T11:14:40.570Z",
"nextUpdate": "2025-05-21T11:25:40.570Z"
},
"threads": {
"id": "17890643139123701",
"postUrl": "https://www.threads.com/@ayrshare/post/DI4nmXrNQA1",
"analytics": {
"views": 2,
"likes": 1,
"replies": 1,
"reposts": 0,
"shares": 0,
"quotes": 0
},
"lastUpdated": "2025-04-25T22:41:05.752Z",
"nextUpdate": "2025-04-25T22:52:05.752Z"
},
"tiktok": {
"id": "7034682002927550598", // TikTok Social Post ID
"postUrl": "https://www.tiktok.com/@borneild/video/7034682002927550598?utm_campaign=tt4d_open_api&utm_source=awawnhyictaos7o",
"analytics": {
"audienceCities": [ // Available 24-48 hours after posting. City distribution of video viewers for the top 10 cities. Must be an active post. See endpoint details.
{
"city_name": "US Teton County",
"percentage": 3.1
},
{
"city_name": "US Queens",
"percentage": 6.3
}
],
"audienceCountries": [ // Available 24-48 hours after posting. Country distribution of video viewers for the top 10 countries. Must be an active post. See endpoint details.
{
"country": "GB",
"percentage": 0.0029
},
{
"country": "US",
"percentage": 0.9604
}
],
"audienceGenders": [ // Updated by TikTok every 24-48 hours.
{
"percentage": 0.25,
"gender": "Female"
},
{
"percentage": 0.5,
"gender": "Male"
},
{
"percentage": 0.25,
"gender": "Other"
}
],
"audienceTypes": [
{
"percentage": 0,
"type": "FOLLOWER_PERCENT"
},
{
"percentage": 0,
"type": "NEW_VIEWER"
},
{
"percentage": 0,
"type": "NON_FOLLOWER_PERCENT"
},
{
"percentage": 0,
"type": "RETURN_VIEWER"
}
],
"averageTimeWatched": 5.6679, // Available 24-48 hours after posting.
"commentsCount": 23, // Total number of lifetime comments. Available 24-48 hours after posting.
"created": "2022-08-09T15:08:22Z",
"embedUrl": "https://www.tiktok.com/embed/v2/7129893524253756713",
"fullVideoWatchedRate": 0.0866, // Percentage of views that completed watching the full video. Available 24-48 hours after posting.
"impressionSources": [ // Different sources for the impressions, ranked from the largest contribution to the smallest. Available 24-48 hours after posting.
{
"impression_source": "Search",
"percentage": 0.0217
},
{
"impression_source": "Sound",
"percentage": 0
},
{
"impression_source": "Follow",
"percentage": 0
},
{
"impression_source": "For You",
"percentage": 0.917
},
{
"impression_source": "Hashtag",
"percentage": 0
},
{
"impression_source": "Personal Profile",
"percentage": 0
}
],
"likeCount": 22, // Total number of lifetime likes. Available 24-48 hours after posting.
"mediaType": "video",
"musicTitle": "♬ original sound - tiff",// If available
"musicUrl": "https://www.tiktok.com/music/original-sound-6689804660171082501?refer=embed", // If available
"name": "Mackly",
"post": "Scramble up ur name & I'll try to guess it😍❤️ #foryoupage #petsoftiktok #aesthetic",
"postUrl": "https://www.tiktok.com/@tiktoktime/video/7129893524253756713?utm_campaign=tt4d_open_api&utm_source=awawnhyictaos7o7",
"reach": 252, // The number of people who watched your published content at least once. Available 24-48 hours after posting.
"shareCount": 1, // Total number of lifetime shares. Available 24-48 hours after posting.
"tags": [ // Tags included in the description
{
"tag": "#foryoupage",
"url": "https://www.tiktok.com/tag/foryoupage"
},
{
"tag": "#petsoftiktok",
"url": "https://www.tiktok.com/tag/petsoftiktok"
},
{
"tag": "#aesthetic",
"url": "https://www.tiktok.com/tag/aesthetic"
}
],
"thumbnailHeight": 576,
"thumbnailUrl": "https://p16-sign.tiktokcdn-us.com/obj/tos-useast5-p-0068-tx",
"thumbnailWidth": 1006,
"url": "https://www.tiktok.com/@tiktoktime",
"videoDuration": 13.984, // Video duration in seconds.
"videoViewRetention": [ // This metric indicates how many of your viewers are still watching after a certain amount of time.
{
"percentage": 0.1,
"second": "155"
},
{
"percentage": 0.07,
"second": "234"
}
],
/* Total number of lifetime users who viewed the video. Available 24-48 hours after posting.
If the user swipes away from the ad then swipes back, it would be counted as 2 impressions.
Therefore, a new video view will be counted again with the new impression session.
*/
"videoViews": 34
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
/* Note: if the post was sent as a Twitter Thread, the return will be an array, "twitter": [] */
"twitter": {
"id": "1313589441919827982", // Twitter Social Post ID
"postUrl": "https://www.twitter.com/myaccount/1313589441919827982",
"analytics": {
"created": "2022-09-07T22:12:10.000Z",
"entities": {
"urls": [
{
"start": 77, // Starting character position (inclusive)
"end": 96, // Ending character position (exclusive)
"url": "https://t.co/abc123", // Shortened t.co URL
"expandedUrl": "https://www.ayrshare.com/docs", // Full URL after redirect
"displayUrl": "ayrshare.com/docs", // User-friendly display version
"unwoundUrl": "https://www.ayrshare.com/docs" // Final destination URL
}
],
"hashtags": [
{
"start": 97, // Starting character position (inclusive)
"end": 112, // Ending character position (exclusive)
"tag": "SocialMediaAPI" // Hashtag text without #
}
],
"mentions": [
{
"start": 113, // Starting character position (inclusive)
"end": 122, // Ending character position (exclusive)
"username": "ayrshare" // Username without @
}
],
"cashtags": [
{
"start": 123, // Starting character position (inclusive)
"end": 128, // Ending character position (exclusive)
"tag": "META" // Stock symbol without $
}
],
"annotations": [
{
"start": 46, // Starting character position (inclusive)
"end": 54, // Ending character position (exclusive)
"probability": 0.9456, // Confidence score (0.0 to 1.0)
"type": "Product", // Entity type: Person, Place, Product, Organization, Other
"normalizedText": "Ayrshare" // Standardized entity name
}
]
},
"media": [
{
"width": 1920,
"durationMs": 28240,
"height": 1080,
"mediaKey": "7_1739849636389814272",
"previewImageUrl": "https://pbs.twimg.com/ext_tw_video_thumb/1739849636389814272/pu/img/bCkAdkD0R00-ZlkY.jpg",
"type": "video",
"mediaUrls": [ // available for videos and gifs
{
"bitRate": 256000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/480x270/4RoZCqynednVMFgy.mp4?tag=12"
},
{
"bitRate": 832000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/640x360/RYy5iHTIxu7_iyZm.mp4?tag=12"
},
{
"bitRate": 2176000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/1280x720/9UpR90ekFA-9Ucxo.mp4?tag=12"
},
{
"contentType": "application/x-mpegURL",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/pl/0AVy2xIOLQcsrEZG.m3u8?tag=12&container=fmp4"
}
]
}
],
"name": "Wonder World",
"post": "Just launched our social media campaign using Ayrshare! Check out the API at https://t.co/abc123 #SocialMediaAPI @ayrshare $META",
"publicMetrics": { // Organic and paid metrics available publicly. Use this to measure Tweet engagement.
"retweetCount": 0, // Retweets count
"quoteCount": 0, // Times the Tweet was quoted count
"likeCount": 0, // Likes for the Tweet count
"replyCount": 0, // Replies count
"quoteCount": 0, // Times the Tweet was quoted count
"bookmarkCount": 0, // Bookmarks count
"impressionCount": 23 // How many times the Tweet has been viewed (not unique by user). A view is counted if any part of the Tweet is visible on the screen.
},
"nonPublicMetrics": { // Organic and paid metrics not available publicly. Not available for Tweets older than 30 days. Use this to determine the total number of impressions generated for the Tweet.
"userProfileClicks": 1, // User profile clicks
"engagements": 1, // How many times the Tweet has been engaged with.
"impressionCount": 5, // How many times the Tweet has been viewed (not unique by user). A view is counted if any part of the Tweet is visible on the screen.
"video": { // Users who played through to each quartile in a video. This reflects the number of quartile views across all Tweets in which the given video has been posted.
"playback25Count": 4,
"playback50Count": 2,
"playback75Count": 1,
"playback0Count": 4,
"playback100Count": 1
}
},
"organicMetrics": { // Non-paid metrics. Not available for Tweets older than 30 days. Use this to measure organic engagement for the Tweet.
"likeCount": 0, // Tweet likes
"impressionCount": 5, // How many times the Tweet has been viewed (not unique by user). A view is counted if any part of the Tweet is visible on the screen.
"replyCount": 0, // Replies count
"retweetCount": 0, // R countetweets
"userProfileClicks": 1, // User profile clicks
"video": { // Users who played through to each quartile in a video. This reflects the number of quartile views across all Tweets in which the given video has been posted.
"playback25Count": 4,
"playback0Count": 4,
"playback100Count": 1,
"viewCount": 4,
"playback50Count": 2,
"playback75Count": 1
}
},
"poll": { // Present if Tweet has a poll
"durationMinutes": 5, // Duration in minutes
"endDatetime": "2023-05-29T17:28:05.000Z",
"votingStatus": "open", // "open" or "closed"
"id": "1663234520718371960",
"options": [
{
"position": 1,
"label": "yes",
"votes": 3
},
{
"position": 2,
"label": "maybe",
"votes": 1
},
{
"position": 3,
"label": "no",
"votes": 0
}
]
},
"urls": [ // Available for long Tweets only
{
"start": 866,
"end": 889,
"url": "https://t.co/3r6xz4hBnM",
"expandedUrl": "https://www.cnn.com",
"displayUrl": "cnn.com"
}
],
"username": "wondrous"
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
"youtube": {
"id": "RWJMpOUGicU", // YouTube Social Post ID
"postUrl": "https://youtu.be/RWJMpOUGicU",
"analytics": {
"averageViewDuration": 6, // The average length, in seconds, of video playbacks.
"averageViewPercentage": 92.01, // The average percentage of a video watched during a video playback.
"channelTitle": "youtubeHandle",
"comments": 22,
"created": "2022-08-15T19:14:44Z",
"description": "Doubt is not a pleasant condition, but certainty is absurd. - Voltaire",
"dislikes": 3,
"estimatedMinutesWatched": 23, // The number of minutes that users watched videos for the specified channel, content owner, video, or playlist.
"likes": 54,
"liveBroadcastDetails": { // Only present if liveBroadcast is "live" or "upcoming"
"activeLiveChatId": "Cg0KC3Ez", // The ID of the currently active live chat attached to this video. Not present if broadcast complete and chat no longer live
"actualStartTime": "2023-05-04T10:14:56Z", // The time that the broadcast actually started.
"actualEndTime": "2023-05-04T10:15:15Z", // The time that the broadcast actually ended.
"concurrentViewers": 384343, // The number of viewers currently watching the broadcast. Not present if the broadcast has ended.
"scheduledEndTime": "2023-05-04T10:15:00Z", // The time that the broadcast is scheduled to end if a scheduled end time was set.
"scheduledStartTime": "2023-05-04T10:15:00Z" // The time that the broadcast is scheduled to begin.
},
"liveBroadcast": "live", // Values: "none", "live", "upcoming"
"madeForKids": false,
"privacyStatus": "public",
"publishedAt": "2023-05-08T12:30:26Z",
"subscribersGained": 23, // The number of times that users subscribed to a channel.
"subscribersLost": 1, // The number of times that users unsubscribed from a channel.
"tags": ["sweet", "sour"], // Tags assigned to video
"thumbnailUrl": "https://i.ytimg.com/vi/RWJMpOUGicU/default.jpg",
"title": "Yo time",
"videosAddedToPlaylists": 2, // The number of times that videos were added to any YouTube playlists. The videos could have been added to the video owner's playlist or to other channels' playlists.
"views": 153
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
"status": "success",
"code": 200,
"id": "IHvCLacgPc6hMU9IQ6oK"
}
```
```json 200: Backfilled Response theme={"system"}
{
"facebook": {
"id": "104923907983682_108329000309742",
"postUrl": "https://www.facebook.com/104923907983682_108329000309742",
"analytics": {
"commentsCount": 5,
"likeCount": 23,
"sharesCount": 12,
"mediaView": 450,
"backfilledFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
},
"status": "success",
"code": 200,
"id": "IHvCLacgPc6hMU9IQ6oK"
}
```
```json 200: Recovered Response theme={"system"}
{
"facebook": {
"id": "104923907983682_108329000309742",
"postUrl": "https://www.facebook.com/104923907983682_108329000309742",
"analytics": {
"commentsCount": 5,
"likeCount": 23,
"sharesCount": 12,
"mediaView": 450,
"recoveredFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
},
"status": "success",
"code": 200,
"id": "IHvCLacgPc6hMU9IQ6oK"
}
```
```json 404 - Bad Request theme={"system"}
/* Often if manually deleted at social network */
{
"status": "error",
"code": 116,
"id": "N7GAZeJSAYcdCpHSm3xQ", // Ayrshare Post ID
"facebook": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent and the post at the social network has not been deleted.",
"id": "104619420979033_588326339980968" // Facebook Platform ID
},
"instagram": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent and the post at the social network has not been deleted.",
"id": "18349092271045074" // Instagram Platform ID
},
"linkedin": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent and the post at the social network has not been deleted.",
"id": "urn:li:share:7038277251594878976" // LinkedIn Platform ID
},
"pinterest": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent and the post at the social network has not been deleted. Pin not found."
},
"twitter": {
"action": "post",
"status": "error",
"code": 186,
"message": "Could not find tweet with id: [1632511562660433929].",
"id": "1632511562660433929" // Twitter Platform ID
},
"youtube": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent and the post at the social network has not been deleted.",
"id": "rAMFoqZeOGg" // YouTube Platform ID
},
"lastUpdated": "2023-03-06T21:59:06.064Z",
"nextUpdate": "2023-03-06T22:10:06.064Z"
}
```
```json 404 - Not Found theme={"system"}
{
"action": "analytics",
"status": "error",
"code": 186,
"message": "Post ID not found.",
"id": "7aVBe0jw27DNwFq92KZ"
}
```
# Analytics on a Social Network
Source: https://www.ayrshare.com/docs/apis/analytics/social
POST /analytics/social
Get analytics and demographics on a user's social profile, such as impressions, views, and followers
Get analytics and demographics on a user's social profile, such as impressions, views, and followers.
Currently available for Bluesky, Facebook Pages, Google My Business, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Threads, TikTok, X/Twitter, and YouTube.
**Facebook: some reach and video metrics were retired by Meta (June 15, 2026).** Meta removed the unique impression and 3-second video-view (unique) Insights metrics across all Graph API versions, so the Facebook `analytics` object no longer returns the `pagePostsImpressions*` family (`pagePostsImpressions`, `pagePostsImpressionsPaid`, `pagePostsImpressionsUnique`, `pagePostsImpressionsOrganicUnique`, `pagePostsImpressionsViral*`, `pagePostsImpressionsNonviral*`, `pagePostsServedImpressionsOrganicUnique`) or `pageVideoViewsUnique`. Use `pageMediaView` for reach (a Total Unique Media Views successor is planned). `pagePostEngagements`, `pageVideoViews`, and `pageVideoViewsPaid` are unaffected. Reference: [Upcoming API Changes — June 15, 2026](/docs/whatsnew/upcoming-api-changes#june-15-2026).
Facebook Page analytics is only available on Pages with 100 or more likes, such as demographics. Facebook typically updates their metrics once every 24 hours.
Instagram may take up to 48 hours to calculate the analytics data. Follower count analytics is not available with fewer than 100 followers. Demographic metrics only return the top 45 performers, only viewers for whom we have demographic data are used in demographic metric calculations, and demographic data is not returned if the Instagram User has fewer than 100 engagements during the last 30 days.
When retrieving Instagram social analytics, demographic information may not appear in the response for particular metrics. Demographic information will appear when the metrics have more than 100 people in each breakdown. Please see [Instagram Analytics Demographics Warning](/docs/help-center/technical-support/instagram_analytics_demographics_warning) for more information.
LinkedIn supports both Company Page analytics and personal (member) profile analytics. For personal profiles, the `analytics` object includes a lifetime `followersCount`, daily follower growth in `followersDaily[]`, and aggregate post metrics (`impressionCount`, `uniqueImpressionsCount`, `likeCount`, `commentCount`, `shareCount`). LinkedIn `count` totals are eventually consistent, but not immediately consistent, and can take up to 24-48 hours in some cases. The aggregate `shareCount`, `likeCount`, and `commentCount` for personal profiles are best-effort and may differ slightly from the numbers shown in the LinkedIn UI.
TikTok can take 24-48 hours to update their analytics data, such as video views, demographics, likes, shares, and comments.
Please see the [post analytics endpoint](/docs/apis/analytics/post) for additional info.
## Header Parameters
## Body Parameters
Social media platforms to get analytics. Accepts an array of strings with values:
```json theme={"system"}
{
"platforms": ["bluesky", "instagram", "facebook",
"gmb", "linkedin", "pinterest", "reddit",
"snapchat", "threads", "tiktok", "twitter", "youtube"]
}
```
Specifies how many quarters of historical data to return. A quarter is:
* 85 days for Facebook
* 90 days for Instagram, TikTok, and YouTube
* 90 days for Snapchat (capped at 1 quarter / 90 days max due to Snapchat API limitations)
Available for Facebook, Instagram, Snapchat, TikTok, and YouTube platforms. Valid values: 1–4.
Only values greater than 0 activate date filtering.
**Date filtering (Instagram & TikTok):** Date filtering is active when `daily=true` OR `quarters > 0`.
If neither `daily` nor `quarters` is provided, all-time data is returned with no date filter applied.
Note: `quarters: 0` is now treated as no date range (all-time data). Previously, `quarters: 0` was
treated as `quarters: 1`.
When set to `true`, returns analytics data as daily time-series values instead of aggregated
totals. This option is only available for Facebook, Instagram, Snapchat, TikTok, and YouTube platforms. Due
to the larger data size, using [compression](/docs/apis/overview#compression) is recommended.
For Instagram and TikTok, setting `daily=true` also activates date filtering using a default
shorter quarters window.
**Instagram reach:** With `daily=true`, the Instagram response returns a nested `reach` object
(containing `period` and a `values` time-series) instead of the scalar `reachCount`
field that is returned in non-daily mode.
For TikTok analytics, when set to true, this returns only the 60-day aggregate totals for comments, shares, and views (`commentCountTotal`, `shareCountTotal`, `viewCountTotal`).
This provides faster response times compared to retrieving the full analytics history.
Note: Do not use this parameter together with `daily=true` as they are incompatible.
Important: As of March 1, 2025, TikTok moved to 60-day totals. As of April 2026, TikTok uses
quarters-based date filtering — use the `quarters` parameter to control the date window (e.g., `quarters: 1` = 90 days, `quarters: 2` = 180 days). See [upcoming changes](/docs/whatsnew/upcoming-api-changes#march-1-2025) for details.
Platform-specific options for YouTube analytics.
**`lifetime`** (boolean, default: `false`): When set to `true`, includes `lifetimeLikes` in the response - the sum of likes across all public videos on the channel. This is computed by fetching all videos and summing their like counts, so it may take longer for channels with many videos.
**Threshold:** Channels with more than 1,000 videos will return `lifetimeLikes: null` and a warning in the top-level [`warnings`](#warnings) array. This prevents excessive API usage.
**Caching:** Per-channel, with shorter TTLs for non-success outcomes so retries pick up state changes promptly:
* Successful `lifetimeLikes` value: **24 hours**.
* 1,000-video bailout (warning `code: 445`): **1 hour** — short enough that a channel which deletes videos to drop below the threshold doesn't have to wait a full day for a real value.
* Transient YouTube Data API failures (warning `code: 446`): **not cached** — the next request retries.
**Note:** Deleted or private videos are excluded from the sum, so the total may differ from the "true" lifetime likes for channels that have removed videos.
**Request example:**
```json theme={"system"}
{
"platforms": ["youtube"],
"youtube": { "lifetime": true }
}
```
X/Twitter only. This parameter allows you to retrieve posts from a specific X/Twitter user by their numeric ID, rather than from your linked account.
For example, to get all posts from the handle `@Google`, you would use their numeric userId `20536157`.
You can find any X/Twitter user's numeric userId by using the [Brands Get User](/docs/apis/listen/brand-user) endpoint.
Note: Use only the API KEY in the header to make this request. Do not include the Profile Key.
X/Twitter only. This parameter allows you to retrieve posts from a specific X/Twitter user by their handle, rather than from your linked account.
For example, to get all posts from the handle `@Google`.
Note: Use only the API KEY in the header to make this request. Do not include the Profile Key.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"platforms": ["bluesky", "facebook", "gmb", "instagram", "linkedin",
"pinterest", "reddit", "snapchat", "threads", "tiktok", "twitter", "youtube"],
"quarters": 1}' \
-X POST https://api.ayrshare.com/api/analytics/social
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/analytics/social", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
platforms: [
"bluesky",
"facebook",
"gmb",
"instagram",
"linkedin",
"pinterest",
"reddit",
"snapchat",
"threads",
"tiktok",
"twitter",
"youtube"
],
quarters: 1
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'platforms': ['bluesky', 'facebook', 'gmb', 'instagram',
'linkedin', 'pinterest', 'reddit', 'snapchat',
'threads', 'tiktok', 'twitter', 'youtube']}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/analytics/social',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
['bluesky', 'facebook', 'gmb', 'instagram', 'linkedin',
'pinterest', 'reddit', 'snapchat', 'threads', 'tiktok', 'twitter', 'youtube'] // required
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"platforms": []string{"bluesky", "facebook", "gmb", "instagram", "linkedin",
"pinterest", "reddit", "snapchat", "threads", "tiktok", "twitter", "youtube"},
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/social",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace SocialPOSTRequest_csharp
{
class Social
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/analytics/social";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"platforms\": [\"bluesky\", \"facebook\", \"gmb\", \"instagram\", " +
"\"linkedin\", \"pinterest\", \"reddit\", \"snapchat\", \"threads\", \"tiktok\", \"twitter\", \"youtube\"]}";
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
When cumulative metrics (e.g., followers, likes) are temporarily unavailable from the social network, the API automatically backfills them from stored data. Two optional fields may appear in the per-platform `analytics` object:
* **`backfilledFrom`** (string, ISO 8601) — Present when one or more cumulative metrics were substituted from stored data. The timestamp indicates when the stored data was last updated.
* **`recoveredFrom`** (string, ISO 8601) — Present when the entire analytics response was recovered from stored data due to a complete API failure. The timestamp indicates when the stored data was last updated.
Stored data older than 4 days is considered stale and will not be used for backfill or recovery.
**LinkedIn `reactions`:** The post-level cumulative `reactions` metric (an object of per-type reaction counts) is subject to this empty-only backfill. When LinkedIn rate-limits the reactions fetch, the value carries forward from the last successful snapshot — and `backfilledFrom` is set to that snapshot's timestamp — instead of regressing to empty.
**LinkedIn personal (member) analytics — re-link required.** Personal LinkedIn profiles linked before member analytics shipped do not have the required analytics scopes. Social analytics requests for those profiles return [error code `475`](/docs/errors/errors-ayrshare#linkedin-analytics-errors) ("re-link your LinkedIn profile to enable analytics"). The account owner must re-link their LinkedIn profile on the Social Accounts page to grant the new scopes. Allow a few minutes after re-linking for code `475` to clear (Ayrshare and LinkedIn both briefly cache the permission state, typically \~5-10 minutes). Posting is unaffected.
**`warnings`** (array of objects, optional top-level field) — Present only when Ayrshare needs to inform the caller of a non-fatal condition (e.g., an opt-in computation was skipped). Absent from the response when there is nothing to warn about.
Each entry is a structured object, not a free-form string:
| Field | Type | Description |
| --------- | ------ | --------------------------------------------------------------------- |
| `action` | string | The operation context that produced the warning (e.g. `"analytics"`). |
| `status` | string | Always `"warning"` for entries in the `warnings` array. |
| `code` | number | Stable Ayrshare warning code. Safe to match on in client code. |
| `message` | string | Human-readable description. |
| `details` | string | Optional additional context specific to this warning instance. |
Known warning codes:
* `445` — `lifetimeLikes` skipped because the YouTube channel exceeds the 1,000-video threshold.
* `446` — `lifetimeLikes` unavailable because the YouTube Data API returned errors for the uploads playlist or every `videos.list` batch.
```json 200: Success Aggregate {3, 29, 121, 138, 203, 265, 275, 353, 390, 459, 478, 556, 596} theme={"system"}
{
"status": "success",
"bluesky": {
"analytics": {
"associated": { // Group of associated features and capabilities
"lists": 0, // Number of lists created by the user
"feedgens": 0, // Number of custom feeds generated by the user
"starterPacks": 0, // Number of starter packs created by the user
"labeler": false // Whether the user can create content labels
},
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:n7atr", // URL to user's profile picture
"created": "2024-12-14T20:39:21.343Z", // Timestamp when the account was created
"displayName": "Jumping Jack", // User's chosen display name
"followersCount": 15, // Number of users following this account
"followsCount": 5, // Number of users this account follows
"handle": "jack.bsky.social", // User's unique handle/username
"id": "did:plc:n7atrjd22xgkmgwig6dzlh", // Bluesky Social ID
"indexedAt": "2024-12-14T20:39:21.343Z", // Timestamp when this data was last indexed
"labels": [], // Array of content labels applied to the account
"postsCount": 20, // Number of posts made by the user
"viewer": { // Information about the viewing user's relationship
"muted": false, // Whether the viewing user has muted this account
"blockedBy": false // Whether this account has blocked the viewing user
}
},
"lastUpdated": "2025-01-11T20:05:05.214Z",
"nextUpdate": "2025-01-11T20:16:05.214Z"
},
"facebook": {
/* See specific time ranges - Lifetime unless otherwise noted */
"analytics": {
"about": "The best site to watch movies online.",
"birthday": "11/20/1985", // Applicable to Pages representing people
"caterory": "Movie", // The Page's category. e.g. Product/Service, Computers/Technology.
"emails": ["john@example.com"],
"engagement": { // If available, otherwise use fanCount
"count": 587, // Page like count, same as fanCount
"socialSentence": "587 people like this."
},
"fanCount": 587,
"followersCount": 587,
"id": "102619320979033",
"instagramBusinessAccount": {
"id": "17841452212707498" // Present if an Instagram account is linked with the Facebook page
},
"isPublished": true, // If the FB Page is publicly visable.
"link": "https://www.facebook.com/102619320979033",
"location": { // If a location is set
"street": "142 W 57th St",
"zip": "10019"
},
"name": "theGoodone",
"pageFollows": 2,
"pageMediaView": 929, // The number of times your content was played or displayed. Content includes videos, posts, stories and ads.
"pageMediaViewIsFromAds": 1, // The number of times your content was played or displayed from ads.
"pageMediaViewIsFromFollowers": 18, // The number of times your content was played or displayed from followers.
"pagePostEngagements": 20, // The number of interactions with your posts such as reactions, comments, shares and more.
// The pagePostsImpressions* family and pagePostsServedImpressionsOrganicUnique were retired by Meta (June 15, 2026); see the note at the top of this page.
// --- Page Video Data ---
"pageVideoCompleteViews30s": 32, // The number of times your Page's videos played for at least 30 seconds, or for nearly their total length if they're shorter than 30 seconds. During a single instance of a video playing, we'll exclude any time spent replaying the video.
"pageVideoCompleteViews30sAutoplayed": 19, // Autoplayed 30s complete.
"pageVideoCompleteViews30sClickToPlay": 5, // Click to play 30s complete.
"pageVideoCompleteViews30sOrganic": 23, // Organic 30s complete.
"pageVideoCompleteViews30sPaid": 2, // Paid 30s complete.
"pageVideoCompleteViews30sRepeatViews": 3, // Repeat 30s complete.
"pageVideoCompleteViews30sUnique": 3, // Unique 30s complete.
"pageVideoRepeatViews": 4, // The number times of repeat views.
"pageVideoViews": 31, // The number of times your Page's videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds. During a single instance of a video playing, we'll exclude any time spent replaying the video.
"pageVideoViewsAutoplayed": 115, // Number of views that autoplayed on a user's screen
"pageVideoViewsOrganic": 32, // The number of organic video views.
"pageVideoViewsPaid": 6, // The number of times your Page's promoted videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds. For each impression of a video, we'll count video views separately and exclude any time spent replaying the video.
"pageVideoViewsByPaidNonPaid": { // Breakdown of view views by paid and non-paid
"total": 32,
"unpaid": 5,
"paid": 27
},
"pageVideoViewsByUploadedHosted": { // Daily video views on a page-level broken down by all variants of page-uploaded and page-hosted variants.
"pageUploaded": 147,
"pageUploadedFromCrossposts": 0,
"pageUploadedFromShares": 3,
"pageHostedCrosspost": 0,
"pageHostedShare": 0,
"pageOwned": 144
},
"pageVideoViewsClickToPlay": 32, // The number of times your Page's videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds, after people clicked play. During a single instance of a video playing, we'll exclude any time spent replaying the video.
"pageVideoViewsOrganic": 147, // The number of times your Page's videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds, by organic reach. During a single instance of a video playing, we'll exclude any time spent replaying the video.
"pageVideoViewsPaid": 0, // The number of times your Page's promoted videos played for at least 3 seconds, or for nearly their total length if they're shorter than 3 seconds. For each impression of a video, we'll count video views separately and exclude any time spent replaying the video.
// pageVideoViewsUnique was retired by Meta (June 15, 2026); see the note at the top of this page.
"reactions": { // Total over past 180 days
"like": 1, // Like reactions - The "like" reaction counts include both "like" and "care" reactions.
"love": 1, // Love reactions
"anger": 1, // Anger reactions
"haha": 1, // Haha reactions
"wow": 1, // Wow reactions
"sorry": 1, // Sorry reactions
"total": 6 // Total number of reactions
},
"unreadMessageCount": 12, // Total unread FB Messages - if applicable
"username": "ayrshare",
"verified": true, // verified Facebook Page
"website": "https://www.theGoodone.com"
},
"quarters": 4,
"lastUpdated": "2024-04-25T21:28:10.877Z",
"nextUpdate": "2024-04-25T21:39:10.877Z"
},
/*
* Google Business Profile analytics totals are for the past 24 months.
*/
"gmb": {
"analytics":
{
"businessBookings": 0, // The number of bookings received from the business profile.
"businessConversations": 0, // The number of message conversations received on the business profile.
"businessDirectionRequests": 328, // The number of times a direction request was requested to the business location.
"businessFoodOrders": 0, // The number of food orders received from the business profile.
"businessImpressionsDesktopMaps": 153, // Business impressions on Google Maps on Desktop devices. Multiple impressions by a unique user within a single day are counted as a single impression.
"businessImpressionsDesktopSearch": 9675, // Business impressions on Google Search on Desktop devices. Multiple impressions by a unique user within a single day are counted as a single impression.
"businessImpressionsMobileMaps": 65, // Business impressions on Google Maps on Mobile devices. Multiple impressions by a unique user within a single day are counted as a single impression.
"businessImpressionsMobileSearch": 2070, // Business impressions on Google Search on Mobile devices. Multiple impressions by a unique user within a single day are counted as a single impression.
"callClicks": 2, // The number of times the business profile call button was clicked.
"websiteClicks": 134 // The number of times the business profile website was clicked.
},
"lastUpdated": "2024-04-25T21:28:10.877Z",
"nextUpdate": "2024-04-25T21:39:10.877Z"
},
"instagram": {
"analytics": {
/*
* Demographics: The following audience demographic data is only available
* for Intagram Users with at least 100 followers and engagements (last 30 days).
* Additionally, audience demographic data is only available when
* there is more than 100 people in each demographic category.
*/
"audienceCity": {
"Sydney, New South Wales": 2,
"London, England": 2,
"Bridgewater, New Jersey": 1,
"Puli, Nantou": 1
},
"audienceCityEngagedAudienceDemographics": {
"KIRKLAND, WASHINGTON": 3,
"LAKE BOSWORTH, WASHINGTON": 6,
"WASHOUGAL, WASHINGTON": 1,
"SEATTLE, WASHINGTON": 1,
"BURLINGTON, WASHINGTON": 2
},
"audienceCountry": {
"TW": 1,
"HK": 5,
"SG": 1,
"AU": 2
},
"audienceCountryEngagedAudienceDemographics": {
"DE": 0,
"GB": 0,
"US": 161
},
"audienceGenderAge": {
"F.18-24": 1,
"F.25-34": 6,
"F.35-44": 13,
"F.45-54": 16
},
"audienceGenderAgeEngagedAudienceDemographics": {
"F.13-17": 2,
"F.18-24": 11,
"F.25-34": 15,
"F.35-44": 24
},
"biography": "What to watch next? Get recommendations from your friends.",
"commentsCount": 6, // Total comments of the past 500 posts
"followersCount": 2, // Current total of followers - must have at least 100 followers to show
"followsCount": 19, // Current total of users followed
"id": "17941424040207809",
"igId": 24372260340, // legacy Instagram user ID - only available when Instagram is linked via Facebook Page
"igLoginId": "84739261504829371", // Instagram native user ID - only available when Instagram is linked via direct Instagram login
"likeCount": 116, // Total like of the past 500 posts
"mediaCount": 266, // Total media count on the account, always lifetime. Not filtered by `quarters` or `daily`.
"name": "theGoodone",
"profilePictureUrl": "https://scontent.fphl1-1.fna.fbcdn.net/v/t51.2885-15/74638883_536953567098493_7984001172816003072_n.jpg?_nc_cat=102&ccb=1-5&_nc_sid=86c713&_nc_ohc=krzDDPMjIZQAX-m1PsT&_nc_ht=scontent.fphl1-1.fna&edm=AL-3X8kEAAAA&oh=00_AT9uZhfkQyHWuThTgktvXxB8XEK_xV1_z72frRwtyGwHTA&oe=6246E46D",
"reachCount": 1, // 180 day period - Total number of unique users who have viewed at least one media. Scalar value returned in non-daily mode; when daily=true a nested `reach` object is returned instead (see the Daily success example).
"shareCount": 234, // Total number of shares on the Instagram account's content (posts, stories, reels, videos, live videos) aggregated per-day over the active date window. Follows the same 90-day rolling maximum as `viewsCount` and respects `quarters` / `daily`. Defaults to `0` for accounts where Meta does not return the `shares` metric.
"username": "thegoodone",
"viewsCount": 123212, // 90 day rolling window (maximum Meta allows on the User Metrics endpoint) - Total number of times the IG User's media have been viewed
"website": "https://www.mywebsite.com/"
},
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
},
/* LinkedIn Corporate: Lifetime analytics since start of account */
"linkedin": {
// The likeCount and commentCount fields do not count likes or comments made by companies, including the company that authored the share and are not decremented when a like or comment is deleted.
"analytics": {
"clickCount": 10,
"clicks": { // Only available for organizations that have career pages. This is a paid product.
"mobileCareersPageClicks": {
"careersPageJobsClicks": 2,
"careersPagePromoLinksClicks": 0,
"careersPageEmployeesClicks": 0
},
"careersPageClicks": {
"careersPagePromoLinksClicks": 5,
"careersPageBannerPromoClicks": 0,
"careersPageJobsClicks": 0,
"careersPageEmployeesClicks": 3
}
},
"commentCount": 12,
"engagement": 0.06060606060606061, // Number of organic clicks, likes, comments, and shares over impressions.
"followers": {
"organicFollowerCount": 7,
"paidFollowerCount": 2,
"totalFollowerCount": 12 // Total numuber might be higher than organic + paid. For total use this field.
},
"impressionCount": 264,
"likeCount": 6, // Number of likes. This field can become negative when members who liked a sponsored share later unlike it.
"shareCount": 3, // Number of mentions of the company in a share across LinkedIn
"uniqueImpressionsCount": 51,
"views": {
"aboutPageViews": 2,
"allDesktopPageViews": 8,
"allMobilePageViews": 8,
"allPageViews": 16,
"careersPageViews": 0, // Only available for organizations that have career pages
"desktopAboutPageViews": 0,
"desktopCareersPageViews": 0,
"desktopInsightsPageViews": 0,
"desktopJobsPageViews": 0,
"desktopLifeAtPageViews": 0,
"desktopOverviewPageViews": 8,
"desktopPeoplePageViews": 0,
"desktopProductsPageViews": 0,
"insightsPageViews": 0,
"jobsPageViews": 0,
"lifeAtPageViews": 0,
"mobileAboutPageViews": 2,
"mobileCareersPageViews": 0,
"mobileInsightsPageViews": 0,
"mobileJobsPageViews": 0,
"mobileLifeAtPageViews": 0,
"mobileOverviewPageViews": 6,
"mobilePeoplePageViews": 0,
"mobileProductsPageViews": 0,
"overviewPageViews": 14,
"peoplePageViews": 0,
"productsPageViews": 0
}
},
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
},
/* LinkedIn Personal (member) */
"linkedin": {
"description": "Founder",
"id": "Z_yXaxh_Et", // LinkedIn Personal ID
"name": "John Doe",
"platform": "linkedin",
"profileImageUrl": "https://media.licdn.com/dms/image/v2/C5103AQHORT70jVfKVA/profile",
"url": "https://www.linkedin.com/in/johndoe",
"userName": "johndoe",
"analytics": {
"commentCount": 410, // Aggregate comments
"followersCount": 4210, // Lifetime follower count
"followersDaily": [ // Daily follower growth (trailing 30 days)
{ "memberFollowersCount": 12, "dateRange": { "start": { "year": 2026, "month": 6, "day": 9 } } }
],
"impressionCount": 98000, // Aggregate impressions across posts
"likeCount": 2300, // Aggregate reactions
"shareCount": 190, // Aggregate reshares
"uniqueImpressionsCount": 41000 // Aggregate unique members reached
}
},
/* 90 days summary and daily details, board analytics full history */
"pinterest": {
"analytics": {
"board": {
"boardPinsModifiedAt": "2023-03-14T22:32:06Z",
"collaboratorCount": 0,
"createdAt": "2019-03-07T22:02:22Z",
"description": "",
"followerCount": 24,
"id": "4299544013183293",
"media": {
"pinThumbnailUrls": [
"https://i.pinimg.com/150x150/62/08/8b/62088b44a6152de7198efd3c2bc5c0.jpg",
"https://i.pinimg.com/150x150/ac/b7/c9/acb7c9f8096317180c20022e9b9b8a.jpg",
"https://i.pinimg.com/150x150/5a/d7/56/5ad756fb64a688934bd06853dff3a2.jpg",
"https://i.pinimg.com/150x150/5a/d7/56/5ad755db64a688934bd06853dff3a2.jpg",
"https://i.pinimg.com/150x150/a9/22/b6/a922ef5289639b617c24704d806998.jpg"
],
"imageCoverUrl": "https://i.pinimg.com/400x300/f8/ec/14/f8ec14e7770a53b2e3595773564950.jpg"
},
"name": "Places to Retire",
"pinCount": 64,
"privacy": "PUBLIC",
"username": "glueUp"
},
"clickthrough": 23,
"clickthroughRate": 0.34,
"closeup": 3,
"closeupRate": 0.43,
"engagement": 54,
"engagementRate": 0.43,
"fullScreenPlay": 23,
"fullScreenPlaytime": 42,
"impression": 12231,
"outboundClick": 256,
"outboundClickRate": 0.0.23,
"pinClick": 32,
"pinClickRate": 0.23,
"quartile95PercentView": 42,
"save": 45,
"saveRate": 23,
"video10sView": 902,
"videoAvgWatchTime": 234,
"videoMrcView": 23,
"videoStart": 34,
"videoV50WatchTime": 343,
"daily": [
{
"date": "2021-09-28",
"metrics": {
"SAVE_RATE": 0,
"OUTBOUND_CLICK_RATE": 0,
"IMPRESSION": 0,
"CLOSEUP_RATE": 0,
"ENGAGEMENT_RATE": 0,
"VIDEO_10S_VIEW": 0,
"VIDEO_AVG_WATCH_TIME": 0,
"ENGAGEMENT": 0,
"CLOSEUP": 0,
"FULL_SCREEN_PLAY": 0,
"SAVE": 0,
"PIN_CLICK_RATE": 0,
"OUTBOUND_CLICK": 0,
"VIDEO_MRC_VIEW": 0,
"VIDEO_V50_WATCH_TIME": 0,
"QUARTILE_95_PERCENT_VIEW": 0,
"VIDEO_START": 0,
"CLICKTHROUGH": 0,
"PIN_CLICK": 0,
"CLICKTHROUGH_RATE": 0,
"FULL_SCREEN_PLAYTIME": 0
}
}
]
},
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
},
/* Lifetime analytics since start of account */
"reddit": {
"analytics": {
"acceptFollowers": true, // Whether the user accepts new followers
"awardeeKarma": 125, // Karma points received from Reddit awards given by others
"awarderKarma": 45, // Karma points earned from giving awards to others
"canCreateSubreddit": true, // Whether the user has permission to create new subreddits
"coins": 250, // Number of Reddit coins the user currently has
"commentKarma": 2847, // Karma points earned from comments
"created": "2023-03-15T14:22:30.000Z", // Account creation date in ISO format
"friends": 12, // Number of Reddit friends the user has added
"hasSubscribed": true, // Whether the user has subscribed to any subreddits
"hasVerifiedEmail": true, // Whether the user has verified their email address
"hideFromRobots": false, // Whether the user has opted to hide their profile from search engines
"iconImg": "https://www.redditstatic.com/avatars/default_5.png", // URL to the user's avatar image
"id": "abc123def456", // Unique Reddit user ID
"inboxCount": 3, // Number of unread messages in the user's inbox
"isEmployee": false, // Whether the user is a Reddit employee
"isGold": false, // Whether the user has Reddit Gold/Premium subscription
"isMod": false, // Whether the user is a moderator of any subreddits
"isSponsor": false, // Whether the user is a Reddit sponsor
"isSuspended": false, // Whether the user's account is currently suspended
"linkKarma": 1567, // Karma points earned from submitted links/posts
"linkedIdentities": [ // Array of external identity providers linked to the account
"https://accounts.google.com"
],
"name": "RedditUser_Example123", // Reddit username
"over18": true, // Whether the user is over 18 (affects NSFW content visibility)
"profileImageSize": null, // Dimensions of the profile image (null if using default avatar)
"profileImageUrl": "https://i.redd.it/1234567890.png", // URL to custom profile image (empty if using default avatar)
"suspensionExpiration": null, // When account suspension expires (null if not suspended)
"totalKarma": 4414, // Total karma points (sum of link karma and comment karma)
"url": "https://www.reddit.com/user/RedditUser_Example123", // Direct URL to the user's Reddit profile
"verified": true // Whether the user has a verified Reddit account
},
"lastUpdated": "2025-07-29T00:31:47.080Z",
"nextUpdate": "2025-07-29T00:42:47.080Z"
},
"snapchat": {
"analytics": [
{
"adsSubscribes": 6, // Number of new subscribers acquired through ads
"avgViewTime": 5430, // Average view time in milliseconds per viewer
"favorites": 42, // Number of times content was favorited
"interactions": 156, // Number of times users interacted with content (taps, swipes)
"lensAvgViewTime": 8720, // Average view time in milliseconds for lens content
"lensPlays": 387, // Number of times lenses were played
"lensSubscribers": 18, // Total number of lens subscribers
"lensSubscribes": 5, // New lens subscribers
"lensUniques": 342, // Unique users who viewed lenses
"lensViewTime": 2832800, // Total lens view time in milliseconds
"lensViews": 432, // Total number of lens views
"mediaId": "43548e97-edf1-44f9-984a-0a38470875bc",
"playTime": 4268700, // Total play time in milliseconds
"profilePaidViews": 176, // Profile views from paid promotions
"profileViews": 834, // Total profile views
"replies": 23, // Number of replies to snaps/stories
"savedStoryAvgViewTime": 4950, // Average view time for saved stories in milliseconds
"savedStoryFavorites": 19, // Number of favorites on saved stories
"savedStorySnapCombinedUniques": 523, // Combined unique viewers of saved stories
"savedStorySnapCombinedViews": 712, // Combined views of saved stories
"savedStorySnapPaidUniques": 142, // Unique paid viewers of saved stories
"savedStorySnapPaidViews": 178, // Number of paid views of saved stories
"savedStorySubscribes": 8, // Number of subscribes from saved stories
"savedStoryUniques": 381, // Unique viewers of saved stories
"savedStoryViewTime": 1925850, // Total view time of saved stories in milliseconds
"savedStoryViews": 534, // Total views of saved stories
"scans": 98, // Number of Snapcode scans
"screenshots": 12, // Total number of screenshots taken
"shares": 36, // Number of times content was shared
"snapCombinedUniques": 734, // Combined unique viewers across snaps
"snapCombinedViews": 912, // Combined total views across snaps
"snapPaidUniques": 203, // Unique users who viewed snaps through paid promotion
"snapPaidViews": 267, // Number of paid snap views
"snapViewTime": 3784200, // Total snap view time in milliseconds
"socialUnlocks": 54, // Number of social unlocks
"spotlightAvgViewTime": 7230, // Average view time for Spotlight content in milliseconds
"spotlightCombinedUniques": 1247, // Combined unique viewers of Spotlight content
"spotlightCombinedViews": 1672, // Combined views of Spotlight content
"spotlightFavorites": 89, // Number of favorites on Spotlight content
"spotlightPaidUniques": 324, // Unique paid viewers of Spotlight content
"spotlightPaidViews": 412, // Number of paid views of Spotlight content
"spotlightSubscribes": 17, // Number of subscribes from Spotlight content
"spotlightUniques": 923, // Unique viewers of Spotlight content
"spotlightViewTime": 6765290, // Total view time of Spotlight content in milliseconds
"spotlightViews": 1260, // Total views of Spotlight content
"storyAvgViewTime": 5180, // Average view time for stories in milliseconds
"storyFavorites": 37, // Number of favorites on stories
"storySubscribers": 63, // Total number of story subscribers
"storySubscribes": 9, // New story subscribers
"storyUniques": 532, // Unique viewers of stories
"storyViews": 687, // Total views of stories
"subscribers": 143, // Total number of subscribers
"subscribes": 12, // New subscribers in the period
"swipeDowns": 21, // Number of swipe downs
"swipeUps": 43, // Number of swipe ups
"uniqueScreenshots": 9, // Number of unique users who took screenshots
"uniqueSessions": 672, // Number of unique sessions
"unsubscribes": 3, // Number of unsubscribes in the period
"viewTime": 4568300, // Total view time in milliseconds
"viewers": 723, // Number of unique viewers
"views": 879 // Total number of views
}
],
"lastUpdated": "2025-05-21T20:24:02.787Z",
"nextUpdate": "2025-05-21T20:35:02.787Z"
},
"threads": {
"analytics": {
"biography": "Post to social media with an API for yourself or your users: Instagram, Facebook, Twitter, TikTok, YouTube, and more",
"followersCount": 123,
"id": "92732926562",
"isEligibleForGeoRestrictions": true,
"isVerified": true,
"likes": 1121,
"name": "Ayrshare",
"profileImageUrlHttps": "https://scontent.cdninstagram.com/v/t51.2885-15/357665262_1390047998231434_3968630539537390629_n.jpg?stp=dst-jpg_e35_tt6&_nc_cat=104&ccb=1-7&_nc_sid=18de74&_nc_ohc=CHlHbGcrCaAQ7kNvwFqZTDz&_nc_oc=Adkj3ocdD7bHn5qffGIB20t1C7icONIg8CS7t4Bcf6sssxxve-k94PkCEFDXGsY6ND0&_nc_zt=23&_nc_ht=scontent.cdninstagram.com&edm=AP4hL3IEAAAA&oh=00_AfTPLboqmm2iSOGMfvS29exnVLn5U8y9QPnL6cwLQIcZ9g&oe=68915ECD",
"quotes": 2,
"replies": 196,
"reposts": 3,
"username": "ayrshare",
"views": 36721
},
"lastUpdated": "2025-04-27T15:40:28.885Z",
"nextUpdate": "2025-04-27T15:51:28.885Z"
},
"tiktok": {
"analytics": {
"addressClicks": 2, // Number of clicks collected on the Address button past 60 days
"appDownloadClicks": 1, // Number of clicks collected on the App Download button past 60 days
"audienceAges": [ // Updated by TikTok every 24-48 hours. Only available for TikTok accounts with at least 100 followers.
{
"percentage": 0.125,
"age": "45-54"
},
{
"percentage": 0.053,
"age": "55+"
},
{
"percentage": 0.138,
"age": "18-24"
},
{
"percentage": 0.36,
"age": "25-34"
},
{
"percentage": 0.324,
"age": "35-44"
}
],
"audienceCountries": [ // Updated by TikTok every 24-48 hours.
{
"percentage": 0.25,
"country": "NG"
},
{
"percentage": 0.75,
"country": "US"
}
],
"audienceGenders": [ // Updated by TikTok every 24-48 hours.
{
"percentage": 0.25,
"gender": "Female"
},
{
"percentage": 0.5,
"gender": "Male"
},
{
"percentage": 0.25,
"gender": "Other"
}
],
"bio": "My tiktok account",
"bioLinkClicks": 2, // Number of clicks collected on the Bio Link button past 60 days
"commentCountPeriod": "90 days",// quarters × 90 days when date range is active (e.g., "90 days", "180 days"); "60 days" when no date filter; "partial" when the post history could not be fully retrieved
"commentCountTotal": 1807, // TikTok caps profile-level lookback at 60 days. When `quarters` is set, this is the sum of lifetime engagement on posts created within the window (not engagement that occurred within the window).
"displayName": "Me and You",
"durationAverage": "10.72", // Deprecated. Will be removed in the future. Updated every 12 hours
"emailClicks": 0, // Number of clicks collected on the Email button past 60 days
"followerCount": 34, // Current follower count
"followingCount": 39, // Current following count
"leadSubmissions": 0, // Number of leads submitted past 60 days
"isBusinessAccount": true, // Whether the account is a business account
"isVerified": false, // Whether TikTok has provided a verified badge to the account after confirming that it belongs to the user it represents
"likeCountTotal": 2, // Genuine all-time total - the only TikTok profile metric that returns true lifetime data (sourced from TikTok's `total_likes` field).
"phoneNumberClicks": 0, // Number of clicks collected on the Phone Number button past 60 days
"profileViews": 79346, // Total profile views past 60 days
"shareCountPeriod": "90 days", // quarters × 90 days when date range is active (e.g., "90 days", "180 days"); "60 days" when no date filter; "partial" when the post history could not be fully retrieved
"shareCountTotal": 4, // TikTok caps profile-level lookback at 60 days. When `quarters` is set, this is the sum of lifetime engagement on posts created within the window (not engagement that occurred within the window).
"url": "https://vm.tiktok.com/ZTRuw5kM6/",
"userImage": "https://p16-sign-va.tiktokcdn.com/tos-maliva-avt-0068/f123c4b57351e266",
"username": "@funnyone",
"videoCountTotal": 18, // Video total video count
"viewCountPeriod": "90 days", // quarters × 90 days when date range is active (e.g., "90 days", "180 days"); "60 days" when no date filter; "partial" when the post history could not be fully retrieved
"viewCountTotal": 1493 // TikTok caps profile-level lookback at 60 days. When `quarters` is set, this is the sum of lifetime engagement on posts created within the window (not engagement that occurred within the window).
},
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
},
/* Lifetime analytics since start of handle */
"twitter": {
"analytics": {
"created": "2019-11-12T15:22:57Z",
"description": "The best X account",
"displayName": "Ayrshare",
"followersCount": 11253,
"followingCount": 4242,
"id": 11842743387998232,
"isIdentityVerified": false, // Whether the account is a verified account
"likeCount": 561, // The number of likes created by this user
"listedCount": 17, // The number of lists that include this user
"location": "New York, NY",
"mostRecentTweetId": "1848848832072667321",
"name": "ayrshare",
"parody": false, // Whether the account is a parody account
"pinnedTweet": {
"text": "Happy Days!",
"id": "184884883207266733342",
"editHistoryTweetIds": [
"18488488320726673223"
]
},
"profileBannerUrl": "https://pbs.twimg.com/profile_banners/87253/15041912",
"profileImageUrl": "http://pbs.twimg.com/profile_images/1184/lvQZPpt_normal.png",
"protected": false, // User has chosen to protect their posts (private posts)
"receivesYourDM": true, // User has chosen to receive direct messages from others
"subscription": {
"subscribesToYou": false
},
"subscriptionType": "Premium", // Premium, PremiumPlus, None
"tweetCount": 2930, // The number of Tweets (including retweets) issued by the user
"url": "https://t.co/2XqeJiBy",
"username": "ayrshare",
"verified": true, // When true, indicates that the user has a verified account
"verifiedType": "blue", // "blue", "business", "none"
"website": "https://www.wondrouswaffles.com/"
},
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
},
"youtube": {
/* Lifetime analytics since start of channel */
"analytics": {
"averageViewDuration": 99, // The average length, in seconds, of video playbacks.
"averageViewPercentage": 127.06, // The average percentage of a video watched during a video playback.
"comments": 8,
"created": "2010-01-10T15:30:57Z",
"description": "This is the channel you want",
"dislikes": 1, // The number of times that users indicated that they disliked a video by giving it a negative rating.
"estimatedMinutesWatched": 72, // The number of minutes that users watched videos for the specified channel, content owner, video, or playlist.
"hiddenSubscriberCount": false, // Indicates whether the channel's subscriber count is publicly visible.
"isLinked": true,
"likes": 3, // Sum of likes across all videos on the channel within the date window determined by `quarters` (default: last 360 days). YouTube does not expose a lifetime channel-wide like counter. For a lifetime total, pass `youtube: { lifetime: true }` to get the `lifetimeLikes` field.
"lifetimeLikes": 8750, // Opt-in lifetime sum of likes across every public video on the channel. Shown here because this sample assumes the request included `youtube: { lifetime: true }` — the broad request example at the top of this page does NOT include that flag, so `lifetimeLikes` will be absent from responses to that example request. May be `null` if channel exceeds 1,000-video threshold. Cached for 24 hours per channel. Deleted and private videos are excluded.
"longUploadsStatus": "allowed",
"playlistId": "UUsp6CnxiNbUUYKZwXQ", // Primary playlist
"playlists": [ // All playlists associated with the connected channel
{
"description": "Playlist 1",
"id": "PLcLpmVOb3fDaf7",
"publishedAt": "2022-10-21T21:05:55Z",
"title": "Super Playlist",
"url": "https://www.youtube.com/playlist?list=PLcLpmVOb3fDaf7"
},
{
"description": "Playlist 2",
"id": "FLsp6CnxiNbU",
"publishedAt": "2012-02-26T19:16:55Z",
"title": "Favorites",
"url": "https://www.youtube.com/playlist?list=FLsp6CnxiNbU"
}
],
"privacyStatus": "public", // "public", "private", or "unlisted"
"shares": 34, // The number of times that users shared a video through the Share button
"subscriberCount": "67", // The number of subscribers that the channel has.
"subscribersGained": 34, // The number of times that users subscribed to a channel.
"subscribersLost": 2, // The number of times that users unsubscribed from a channel.
"thumbnailUrl": "https://yt3.ggpht.com/ytc/AMLnZu_lgyzY2EFDAP-no-rj",
"title": "The Best Channel",
"url": "https://www.youtube.com/@youtube53", // The Channel URL using the custom handle
"videoCount": "202",
"videosAddedToPlaylists": 23,
"videosRemovedFromPlaylists": 2,
"viewCount": "5", // The sum of the number of times all the videos in all formats have been viewed for a channel for all time.
"views": 44 // The number of video views that occurred in the last time period (quarters)
},
"quarters": 4,
"lastUpdated": "2022-05-09T00:52:30.530Z",
"nextUpdate": "2022-05-09T02:07:30.530Z"
}
// The top-level `warnings` array (see the "warnings" Info block above)
// would appear here as a sibling of `youtube`/`instagram`/etc. only when
// a non-fatal condition applies — e.g. `lifetimeLikes` being skipped
// because a channel exceeds the 1,000-video threshold. It is omitted in
// this success example because `lifetimeLikes: 8750` was computed
// successfully above.
}
```
```json 200: Success Daily {4, 612, 671, 1590, 1832} theme={"system"}
// Available for Facebook, Instagram, Snapchat, TikTok, and YouTube
// Recommended: https://www.ayrshare.com/docs/apis/overview#compression
{
"facebook": {
"analytics": {
"about": "One of the best stie ever",
"category": "Local Business",
"emails": [ "hello@ayrshare.com" ],
"fanCount": 48519,
"followersCount": 48681,
"id": "885526541490222",
"instagramBusinessAccount": {
"id": "1784145407231999"
},
"isPublished": true,
"link": "https://www.facebook.com/885526541490222",
"location": { // Physical location details for the Page
"city": "Rome",
"country": "Italy",
"latitude": 41.853696407098,
"longitude": 12.573806071995,
"street": "Via Vincenzo",
"zip": "00174"
},
"name": "Super Site",
"overallStarRating": 0, // The average star rating of the page.
"pageFollows": {
"period": "day",
"values": [
{
"value": 3,
"endTime": "2025-08-12T07:00:00.000Z"
},
{
"value": 3,
"endTime": "2025-08-13T07:00:00.000Z"
},
],
"total": 3
},
"pageMediaView": {
"period": "day",
"values": [
{
"value": 100,
"endTime": "2025-08-12T07:00:00.000Z"
},
{
"value": 200,
"endTime": "2025-08-13T07:00:00.000Z"
}
],
"total": 300
},
"pageMediaViewIsFromAds": {
"period": "day",
"values": [
{
"value": 22,
"endTime": "2025-08-12T07:00:00.000Z"
},
{
"value": 41,
"endTime": "2025-08-13T07:00:00.000Z"
}
],
"total": 63
},
"pageMediaViewIsFromFollowers": {
"period": "day",
"values": [
{
"value": 67,
"endTime": "2025-08-12T07:00:00.000Z"
},
{
"value": 29,
"endTime": "2025-08-13T07:00:00.000Z"
}
],
"total": 96
},
"pagePostEngagements": { // The number of interactions with your posts such as likes, comments, shares and more
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30S": { // The number of times videos played for at least 30 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SAutoplayed": { // The number of times videos played for at least 30 seconds when autoplayed
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SClickToPlay": { // The number of times videos played for at least 30 seconds after clicking play
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SOrganic": { // The number of times videos played for at least 30 seconds through organic reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SPaid": { // The number of times videos played for at least 30 seconds through paid reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SRepeatViews": { // The number of times videos were replayed after playing for at least 30 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoCompleteViews30SUnique": { // The number of unique people who watched your videos for at least 30 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoRepeatViews": { // The number of times videos were replayed
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewTime": { // Total time in seconds that videos were viewed
"period": "day",
"total": 2.33,
"values": [
{
"value": 2.33,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews": { // The number of times your videos were viewed
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10S": { // The number of times videos played for at least 10 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SAutoplayed": { // The number of times videos played for at least 10 seconds when autoplayed
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SClickToPlay": { // The number of times videos played for at least 10 seconds after clicking play
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SOrganic": { // The number of times videos played for at least 10 seconds through organic reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SPaid": { // The number of times videos played for at least 10 seconds through paid reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SRepeatViews": { // The number of times videos were replayed after playing for at least 10 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViews10SUnique": { // The number of unique people who watched your videos for at least 10 seconds
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsAutoplayed": { // The number of times your videos autoplayed
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsByPaidNonPaid": { // Breakdown of video views by paid vs non-paid distribution
"period": "day",
"values": [
{
"value": {
"total": 0,
"unpaid": 0,
"paid": 0
},
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": {
"total": 0,
"unpaid": 0,
"paid": 0
},
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsByUploadedHosted": { // Breakdown of video views by uploaded vs hosted content
"period": "day",
"values": [
{
"value": {
"pageUploaded": 0,
"pageUploadedFromCrossposts": 0,
"pageUploadedFromShares": 0,
"pageHostedCrosspost": 0,
"pageHostedShare": 0,
"pageOwned": 0
},
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": {
"pageUploaded": 0,
"pageUploadedFromCrossposts": 0,
"pageUploadedFromShares": 0,
"pageHostedCrosspost": 0,
"pageHostedShare": 0,
"pageOwned": 0
},
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsClickToPlay": { // The number of times people clicked play to view your videos
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsOrganic": { // The number of times your videos were viewed through organic reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
"pageVideoViewsPaid": { // The number of times your videos were viewed through paid reach
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-11-03T07:00:00.000Z"
},
{
"value": 0,
"endTime": "2024-11-04T08:00:00.000Z"
}
]
},
// pageVideoViewsUnique was retired by Meta (June 15, 2026); see the note at the top of this page.
"phone": "+39067265341",
"reactions": { // Breakdown of reactions on your Page's content
"like": 142,
"love": 9,
"wow": 1,
"haha": 0,
"sorry": 0,
"anger": 0,
"total": 152
},
"unreadMessageCount": 0,
"username": "ayrshare",
"verified": false,
"website": "http://www.ayrshare.com"
},
"quarters": 1,
"lastUpdated": "2024-03-19T17:48:21.329Z",
"nextUpdate": "2024-03-19T17:59:21.329Z"
},
"instagram": {
"analytics": {
"audienceCity": {
"KIRKLAND, WASHINGTON": 7,
"LAKE BOSWORTH, WASHINGTON": 20,
"BURLINGTON, WASHINGTON": 5,
"SEATTLE, WASHINGTON": 22,
"ARLINGTON HEIGHTS, WASHINGTON": 7,
},
"audienceCountry": {
"MM": 1,
"CA": 2,
"US": 2201,
"LK": 1
},
"audienceGenderAge": {
"F.13-17": 11,
"F.18-24": 83,
"M.13-17": 9,
"M.18-24": 85,
"M.65+": 10,
"U.55-64": 25,
"U.65+": 12
},
"biography": "Official Instagram feed for the best IG account",
"commentsCount": 552,
"followersCount": 2299,
"followsCount": 26,
"id": "17841407938064444",
"igId": 79483284444, // legacy Instagram user ID - only available when Instagram is linked via Facebook Page
"igLoginId": "84739261504829371", // Instagram native user ID - only available when Instagram is linked via direct Instagram login
"likeCount": 30808,
"mediaCount": 537,
"name": "Best IG Account",
"profilePictureUrl": "https://scontent-lga3-1.xx.fbcdn.net/v/t51.2885-15",
"reach": { // Returned only when daily=true (replaces the scalar `reachCount` from non-daily mode)
"period": "day", // Granularity of the time-series buckets
"values": [ // Per-day reach time-series
{
"value": 387,
"endTime": "2024-07-23T07:00:00.000Z"
},
{
"value": 46,
"endTime": "2024-07-24T07:00:00.000Z"
},
{
"value": 4,
"endTime": "2024-07-25T07:00:00.000Z"
}
]
},
"username": "instagram",
"website": "https://www.instagram.com"
},
"lastUpdated": "2024-07-25T16:09:33.608Z",
"nextUpdate": "2024-07-25T16:20:33.608Z"
},
"snapchat": {
"analytics": [
{
"adsSubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 0
},
"avgViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 7126
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 7003
}
],
"total": 14129
},
"favorites": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 4
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 3
}
],
"total": 7
},
"interactions": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 8
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 22
}
],
"total": 30
},
"lensAvgViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3712
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 7837
}
],
"total": 11549
},
"lensDauOverMau": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0.074
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0.042
}
],
"total": 0.116
},
"lensDauOverWau": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0.194
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0.251
}
],
"total": 0.445
},
"lensPlays": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 11
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 45
}
],
"total": 56
},
"lensSubscribers": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 206
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 207
}
],
"total": 413
},
"lensSubscribersGained": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 1
}
],
"total": 4
},
"lensSubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 5
},
"lensUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 30
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 5
}
],
"total": 35
},
"lensViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 1153
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2231
}
],
"total": 3384
},
"lensViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 29
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 25
}
],
"total": 54
},
"mediaId": "6e9193cd-5013-478e-a272-d3d0e881f53f",
"playTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 5273
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 5763
}
],
"total": 11036
},
"profilePaidViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 2
},
"profileViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 25
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 44
}
],
"total": 69
},
"replies": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 2
},
"savedStoryAvgViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 5471
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 3408
}
],
"total": 8879
},
"savedStoryFavorites": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 2
},
"savedStorySnapCombinedUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 19
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 22
}
],
"total": 41
},
"savedStorySnapCombinedViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 13
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 39
}
],
"total": 52
},
"savedStorySnapPaidUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 3
},
"savedStorySnapPaidViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 8
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 4
}
],
"total": 12
},
"savedStorySubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 4
},
"savedStoryUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 16
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 23
}
],
"total": 39
},
"savedStoryViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2287
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 4385
}
],
"total": 6672
},
"savedStoryViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 14
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 12
}
],
"total": 26
},
"scans": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 4
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 5
}
],
"total": 9
},
"screenshots": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 6
}
],
"total": 6
},
"shares": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 4
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 6
},
"snapCombinedUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 39
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 32
}
],
"total": 71
},
"snapCombinedViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 88
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 111
}
],
"total": 199
},
"snapPaidUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 15
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 7
}
],
"total": 22
},
"snapPaidViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 10
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 16
}
],
"total": 26
},
"snapViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3455
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2858
}
],
"total": 6313
},
"socialUnlocks": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 2
},
"spotlightAvgViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 8990
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 5401
}
],
"total": 14391
},
"spotlightCombinedUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 44
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 25
}
],
"total": 69
},
"spotlightCombinedViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 45
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 84
}
],
"total": 129
},
"spotlightFavorites": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 5
},
"spotlightPaidUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 9
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 4
}
],
"total": 13
},
"spotlightPaidViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 13
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 4
}
],
"total": 17
},
"spotlightSubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 0
},
"spotlightUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 33
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 18
}
],
"total": 51
},
"spotlightViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 6286
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 5193
}
],
"total": 11479
},
"spotlightViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 24
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 33
}
],
"total": 57
},
"storyAvgViewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 6740
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 6862
}
],
"total": 13602
},
"storyFavorites": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 4
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 6
},
"storySubscribers": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 546
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 547
}
],
"total": 1093
},
"storySubscribersGained": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 3
}
],
"total": 6
},
"storySubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 2
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 1
}
],
"total": 3
},
"storyUniques": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 9
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 13
}
],
"total": 22
},
"storyViews": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 18
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 25
}
],
"total": 43
},
"subscribers": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 273
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 274
}
],
"total": 547
},
"subscribersGained": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 4
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 2
}
],
"total": 6
},
"subscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 3
}
],
"total": 6
},
"swipeDowns": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 6
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 4
}
],
"total": 10
},
"swipeUps": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 5
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 11
}
],
"total": 16
},
"uniqueScreenshots": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 3
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 3
},
"uniqueSessions": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 34
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 11
}
],
"total": 45
},
"unsubscribes": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 0
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 0
}
],
"total": 0
},
"viewTime": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 11140
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 7310
}
],
"total": 18450
},
"viewers": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 42
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 53
}
],
"total": 95
},
"views": {
"period": "day",
"values": [
{
"endTime": "2026-01-21T00:00:00Z",
"value": 33
},
{
"endTime": "2026-01-22T00:00:00Z",
"value": 74
}
],
"total": 107
}
}
],
"lastUpdated": "2026-04-20T13:13:47.646Z",
"nextUpdate": "2026-04-20T13:24:47.646Z"
},
"tiktok": { // TikTok Analytics with "day" period - date range window determined by quarters parameter
"analytics": {
"addressClicks": { // Number of clicks collected on the Address button past 60 days
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"appDownloadClicks": { // Number of clicks collected on the App Download button past 60 days
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"audienceActivity": { // Hourly follower activity. Updated by TikTok every 24-48 hours after posting. Only available for TikTok accounts with at least 100 followers.
"period": "day",
"total": 14824,
"values": [
{
"value": [
{
"count": 12386,
"hour": "5"
},
{
"count": 2438,
"hour": "9"
}
],
"endTime": "2025-01-21T00:00:00.000Z"
}
]
},
"audienceAges": [ // Updated by TikTok every 24-48 hours after posting. Only available for TikTok accounts with at least 100 followers.
{
"percentage": 0.125,
"age": "45-54"
},
{
"percentage": 0.053,
"age": "55+"
},
{
"percentage": 0.138,
"age": "18-24"
},
{
"percentage": 0.36,
"age": "25-34"
},
{
"percentage": 0.324,
"age": "35-44"
}
],
"audienceCountries": [
{
"country": "SV",
"percentage": 0.003
},
{
"country": "US",
"percentage": 0.808
}
],
"audienceGenders": [
{
"percentage": 0.76,
"gender": "Female"
},
{
"percentage": 0.24,
"gender": "Male"
},
{
"percentage": 0,
"gender": "Other"
}
],
"bio": "This is the bio of the TikTok account",
"bioLinkClicks": { // Number of clicks collected on the Bio Link button past 60 days
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"commentCountTotal": { // Total comment count past 60 days
"period": "day",
"values": [
{
"value": 6,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 6,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"displayName": "ayrshare",
"emailClicks": { // Number of clicks collected on the Email button past 60 days
"period": "day",
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"followerCount": { // Daily follower count snapshots (past 60 days)
"period": "day",
"values": [
{
"value": 58, // Total followers at end of this day
"endTime": "2025-01-21T00:00:00.000Z" // End of day timestamp
},
{
"value": 92,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"leadSubmissions": { // Number of leads submitted past 60 days
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"likeCountTotal": { // Total Likes across past 60 days
"period": "day",
"total": 1161,
"values": [
{
"value": 625, // Number of likes received on this date
"endTime": "2025-01-21T00:00:00.000Z" // End of the day timestamp
},
{
"value": 536,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"phoneNumberClicks": { // Number of clicks collected on the Phone Number button past 60 days
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 0,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"profileViews": { // Total profile views past 60 days
"period": "day",
"total": 713,
"values": [
{
"value": 360,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 353,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"shareCountTotal": { // Total share count past 60 days
"period": "day",
"total": 3,
"values": [
{
"value": 2,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 1,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
},
"url": "https://vm.tiktok.com/ZT2NdEX33/",
"userImage": "https://p16-pu-sign-useast8.tiktokcdn-us.com/tos-useastc",
"username": "ayrshare",
"videoCountTotal": 121, // Total video count
"viewCountTotal": { // Total view count past 60 days
"period": "day",
"total": 17808,
"values": [
{
"value": 9324,
"endTime": "2025-01-21T00:00:00.000Z"
},
{
"value": 8484,
"endTime": "2025-01-20T00:00:00.000Z"
}
]
}
},
"lastUpdated": "2025-01-24T23:33:12.678Z",
"nextUpdate": "2025-01-24T23:44:12.678Z"
},
"youtube": { // If no analytics are available for a given day, not values will be returned
"analytics": {
"averageViewDuration": {
"period": "day",
"total": 4,
"values": [
{
"value": 4,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"averageViewPercentage": {
"period": "day",
"total": 61.99,
"values": [
{
"value": 61.99,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"comments": {
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"created": "2010-01-10T15:30:57Z",
"description": "The best place to find the best products",
"dislikes": {
"period": "day",
"total": 0,
"values": [
{
"value": 0,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"estimatedMinutesWatched": {
"period": "day",
"total": 23.12,
"values": [
{
"value": 23.12,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"handle": "@helmar1066",
"hiddenSubscriberCount": false,
"id": "UCsp6CnxiNbUU0AJtuYKZwXQ",
"isChannelMonetizationEnabled": false,
"isLinked": true,
"likes": {
"period": "day",
"total": 12,
"values": [
{
"value": 12,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"longUploadsStatus": "allowed",
"playlistId": "UUsp6CnxiNbUU0AJtuYKZwXQ",
"playlists": [
{
"description": "",
"id": "PLcLpmVOb3fDaf7Mps-5GnCxRZy_FBBEv4",
"publishedAt": "2022-10-21T21:05:55Z",
"title": "Super One",
"url": "https://www.youtube.com/playlist?list=PLcLpmVOb3fDaf7Mps-5GnCxRZy_FBBEv4",
"channelId": "UCsp6CnxiNbUU0AJtuYKZwXQ"
},
{
"description": "",
"id": "FLsp6CnxiNbUU0AJtuYKZwXQ",
"publishedAt": "2012-02-26T19:16:55Z",
"title": "Favorites",
"url": "https://www.youtube.com/playlist?list=FLsp6CnxiNbUU0AJtuYKZwXQ",
"channelId": "UCsp6CnxiNbUU0AJtuYKZwXQ"
}
],
"privacyStatus": "public",
"shares": {
"period": "day",
"total": 3,
"values": [
{
"value": 3,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"subscriberCount": 0,
"subscribersGained": {
"period": "day",
"total":80,
"values": [
{
"value": 8,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"subscribersLost": {
"period": "day",
"total": 1,
"values": [
{
"value": 1,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"thumbnailUrl": "https://yt3.ggpht.com/ytc/AIdro_lIMzJl5UC7MBEnCzuMpXzai_EvIk5Xh3ErDJ_VTBk=s88-c-k-c0x00ffffff-no-rj",
"title": "helmar1066",
"url": "https://www.youtube.com/@helmar1066",
"videoCount": 5,
"videosAddedToPlaylists": {
"period": "day",
"total": 2,
"values": [
{
"value": 2,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"videosRemovedFromPlaylists": {
"period": "day",
"total": 1,
"values": [
{
"value": 1,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
},
"viewCount": 7,
"views": {
"period": "day",
"total": 3,
"values": [
{
"value": 3,
"endTime": "2024-03-18T00:00:00.000Z"
}
]
}
},
"quarters": 1,
"lastUpdated": "2024-04-25T21:24:45.433Z",
"nextUpdate": "2024-04-25T21:35:45.433Z"
}
"status": "success"
}
```
```json 200: Backfilled Response theme={"system"}
{
"status": "success",
"twitter": {
"analytics": {
"created": "2025-12-19T14:09:06Z",
"description": "",
"displayName": "Andrew Williams",
"followersCount": 1523,
"followingCount": 412,
"tweetCount": 8721,
"likeCount": 3200,
"listedCount": 5,
"username": "andrewwil1985",
"backfilledFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
}
}
```
```json 200: Recovered Response theme={"system"}
{
"status": "success",
"twitter": {
"analytics": {
"created": "2025-12-19T14:09:06Z",
"description": "",
"displayName": "Andrew Williams",
"followersCount": 1523,
"followingCount": 412,
"tweetCount": 8721,
"likeCount": 3200,
"listedCount": 5,
"username": "andrewwil1985",
"recoveredFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
}
}
```
```json 400: Bad Request theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. /rest-api/endpoints Details: One of the platforms requested in not supported."
}
```
```json 400: Social Not Linked theme={"system"}
{
"linkedin": {
"action": "post",
"status": "error",
"code": 156,
"message": "LinkedIn is not properly linked and must be re-linked. Please go to the Social Accounts ppage and re-link LinkedIn."
},
"code": 156,
"status": "error"
}
```
```json 400: Partial Error theme={"system"}
{
// A partial error response is returned if some of the data is available but there is an error.
"youtube": {
"views": 401,
"comments": 2,
"likes": 37,
"dislikes": 2,
"estimatedMinutesWatched": 102,
"averageViewDuration": 12,
"averageViewPercentage": 32.66,
"subscribersGained": 2,
"subscribersLost": 4,
"videosAddedToPlaylists": 2,
"videosRemovedFromPlaylists": 1,
"shares": 25,
"errors": [
{
"action": "authorization",
"status": "error",
"code": 193,
"message": "An error occurred connecting to YouTube. Please try your request once more or re-linking YouTube on the social linking page if the issue persists: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/youtube",
"details": "Error getting YouTube channel and playlist analytics: Insufficient Permission"
}
],
"status": "error"
},
"lastUpdated": "2025-01-27T02:59:13.119Z",
"nextUpdate": "2025-01-27T03:10:13.119Z",
"status": "error"
}
```
# Analytics on a Post by Social ID
Source: https://www.ayrshare.com/docs/apis/analytics/social-by-id
POST /analytics/post
Get real-time analytics for posts using the Social Post ID
Retrieve analytics for posts that did not originate via Ayrshare by providing the low-level [Social Post ID](/docs/apis/overview#social-post-id).
This ID is returned in the `postIds` field of the [/post endpoint](/docs/apis/post/post).
The linked account must be the owner of the post to retrieve the analytics (exception: YouTube; see below). Support platforms: `Facebook`, `Instagram`, `LinkedIn`, `Threads`, `TikTok`, `Twitter`, and `YouTube`.
The call is the same as the [Analytics on a Post endpoint](/docs/apis/analytics/post). The key
difference is you use the post id return by the social network instead of the Ayrshare ID. Also
include the `searchPlatformId: true` parameter to notify the endpoint you're searching by the
Social Post ID.
Use the [Get All Post History endpoint](/docs/apis/history/overview) to retrieve posts and IDs
originating outside of Ayrshare found in the `id` field.
Recommend to only use for posts not sent via Ayrshare. For posts sent via Ayrshare, use the
[analytics endpoint](/docs/apis/analytics/post).
Analytics on Instagram posts that were published before the user's account was converted to a
business account from a personal account have limited analytics.
If retrieving YouTube analytics for a post that doesn't belong to your channel using the social
ID method, the API will return descriptive metadata about the content while showing zeros for
all numerical metrics. Descriptive information such as title, description, tags, channel title,
privacy status, and thumbnail URLs will be correctly populated, providing context about the
video content. However, all numerical performance metrics including views, likes, comments,
shares, subscriber changes, watch time, and playlist additions will return as zero values.
When using `postIds` for X/Twitter threads, each tweet's Social Post ID must be provided
individually, thread tweets are not automatically included when querying the parent post.
## Header Parameters
## Body Parameters
Either `id` or `postIds` must be provided. Use `id` for a single post or `postIds` for retrieving analytics on multiple posts in a single request.
[Social Post ID](/docs/apis/overview#social-post-id) returned from the [/post
endpoint](/docs/apis/post/post). This is the `id` field for an individual social network found in the
`postIds` array. Either `id` or `postIds` is required.
Array of [Social Post IDs](/docs/apis/overview#social-post-id) to retrieve analytics for multiple posts in a single request. Maximum of 100 IDs allowed. Either `id` or `postIds` is required.
```json theme={"system"}
{
"postIds": ["1979851549871354062", "2011793803951137234"]
}
```
String array of platforms to retrieve analytics. Only one value is allowed.
Available values:
```json theme={"system"}
{
"platforms": ["facebook", "instagram", "linkedin", "threads",
"tiktok", "twitter", "youtube"]
}
```
Set to `true` to search by the Social Post ID.
```json Single Post theme={"system"}
{
// Facebook Social Post ID
"id": "104923907983682_108329000309742",
"platforms": [
// Select only one platform at a time:
// facebook, instagram, youtube, threads, tiktok, or twitter
"facebook"
],
"searchPlatformId": true // Required
}
```
```json Multiple Posts theme={"system"}
{
// Array of Social Post IDs (max 100)
"postIds": ["1979851549871354062", "2011793803951137234"],
"platforms": [
// Select only one platform at a time:
// facebook, instagram, youtube, threads, tiktok, or twitter
"twitter"
],
"searchPlatformId": true // Required
}
```
When cumulative metrics (e.g., likes, comments, views) are temporarily unavailable from the social network, the API automatically backfills them from stored data. Two optional fields may appear in the per-platform `analytics` object:
* **`backfilledFrom`** (string, ISO 8601) — Present when one or more cumulative metrics were substituted from stored data. The timestamp indicates when the stored data was last updated.
* **`recoveredFrom`** (string, ISO 8601) — Present when the entire analytics response was recovered from stored data due to a complete API failure. The timestamp indicates when the stored data was last updated.
Stored data older than 4 days is considered stale and will not be used for backfill or recovery.
```json 200: Single Post Response theme={"system"}
{
/**
The response is the same as Analytics on a Post.
Please see that endpoint for details.
Note: Some metrics are not available for posts not owned by the authorized account.
For example: X does not return non-public metrics or organic metrics for Tweets not sent by the authorized user.
*/
}
```
```json 200: Multiple Posts Response theme={"system"}
{
"twitter": [
{
"id": "1313589441919827982", // Twitter Social Post ID
"postUrl": "https://www.twitter.com/myaccount/1313589441919827982",
"analytics": {
"created": "2022-09-07T22:12:10.000Z",
"entities": {
"urls": [
{
"start": 77,
"end": 96,
"url": "https://t.co/abc123",
"expandedUrl": "https://www.ayrshare.com/docs",
"displayUrl": "ayrshare.com/docs",
"unwoundUrl": "https://www.ayrshare.com/docs"
}
],
"hashtags": [
{
"start": 97,
"end": 112,
"tag": "SocialMediaAPI"
}
],
"mentions": [
{
"start": 113,
"end": 122,
"username": "ayrshare"
}
]
},
"name": "Wonder World",
"post": "Just launched our social media campaign using Ayrshare! Check out the API at https://t.co/abc123 #SocialMediaAPI @ayrshare",
"publicMetrics": {
"retweetCount": 0,
"quoteCount": 0,
"likeCount": 0,
"replyCount": 0,
"bookmarkCount": 0,
"impressionCount": 23
},
"nonPublicMetrics": {
"userProfileClicks": 1,
"engagements": 1,
"impressionCount": 5
},
"organicMetrics": {
"likeCount": 0,
"impressionCount": 5,
"replyCount": 0,
"retweetCount": 0,
"userProfileClicks": 1
},
"username": "wondrous"
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
},
{
"id": "1313589441919827999", // Twitter Social Post ID
"postUrl": "https://www.twitter.com/myaccount/1313589441919827999",
"analytics": {
"created": "2022-09-08T14:30:00.000Z",
"name": "Wonder World",
"post": "Another great day for social media automation!",
"publicMetrics": {
"retweetCount": 5,
"quoteCount": 2,
"likeCount": 15,
"replyCount": 3,
"bookmarkCount": 1,
"impressionCount": 150
},
"nonPublicMetrics": {
"userProfileClicks": 8,
"engagements": 12,
"impressionCount": 145
},
"organicMetrics": {
"likeCount": 15,
"impressionCount": 145,
"replyCount": 3,
"retweetCount": 5,
"userProfileClicks": 8
},
"username": "wondrous"
},
"lastUpdated": "2022-04-23T18:44:29.778Z",
"nextUpdate": "2022-04-23T19:19:29.778Z"
}
],
"status": "success",
"code": 200
}
```
```json 200: Backfilled Response theme={"system"}
{
"twitter": [
{
"id": "1313589441919827982",
"postUrl": "https://www.twitter.com/myaccount/1313589441919827982",
"analytics": {
"created": "2022-09-07T22:12:10.000Z",
"name": "Wonder World",
"post": "Just launched our social media campaign!",
"publicMetrics": {
"retweetCount": 5,
"quoteCount": 2,
"likeCount": 15,
"replyCount": 3,
"bookmarkCount": 1,
"impressionCount": 150
},
"username": "wondrous",
"backfilledFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
}
],
"status": "success",
"code": 200
}
```
```json 200: Recovered Response theme={"system"}
{
"twitter": [
{
"id": "1313589441919827982",
"postUrl": "https://www.twitter.com/myaccount/1313589441919827982",
"analytics": {
"created": "2022-09-07T22:12:10.000Z",
"name": "Wonder World",
"post": "Just launched our social media campaign!",
"publicMetrics": {
"retweetCount": 5,
"quoteCount": 2,
"likeCount": 15,
"replyCount": 3,
"bookmarkCount": 1,
"impressionCount": 150
},
"username": "wondrous",
"recoveredFrom": "2026-04-08T14:30:00.000Z"
},
"lastUpdated": "2026-04-09T10:15:00.000Z",
"nextUpdate": "2026-04-09T10:26:00.000Z"
}
],
"status": "success",
"code": 200
}
```
```json 400: Bad Request theme={"system"}
{
"lastUpdated": "2023-12-08T03:40:31.185Z",
"nextUpdate": "2023-12-08T03:51:31.185Z",
"youtube": {
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent, the Profile Key is included if applicable, and the post at the social network has not been deleted. If you are trying to retrieve a post originating outside of Ayrshare, please use the /rest-api/endpoints/analytics#analytics-by-social-id",
"id": "dtuu-jDp4381"
}
}
```
# YouTube Playlists
Source: https://www.ayrshare.com/docs/apis/analytics/youtube-playlists
GET /analytics/youTubePlaylists
Get the YouTube playlists for the connected YouTube channel
## Header Parameters
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/analytics/youTubePlaylists
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/analytics/youTubePlaylists", {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
},
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/analytics/youTubePlaylists', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace YouTubePlaylistsGETRequest_csharp
{
class YouTubePlaylists
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/analytics/youTubePlaylists";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"channelId": "UCsp6CnxiNbUU0AJtuYKZw",
"playLists": [
{
"averageTimeInPlaylist": 2.2,
"averageViewDuration": 3.1,
"description": "A great list",
"estimatedMinutesWatched": 21,
"estimatedRedMinutesWatched": 23,
"id": "PLcLpmVOb3fDaf7Mps",
"playlistStarts": 23,
"thumbNail": {
"url": "https://i.ytimg.com/vi/default.jpg",
"width": 120,
"height": 90
},
"title": "Super Playlist",
"views": 55,
"viewsPerPlaylistStart": 32
},
{
"averageTimeInPlaylist": 2,
"averageViewDuration": 4.5,
"description": "A great list 2",
"estimatedMinutesWatched": 2,
"estimatedRedMinutesWatched": 3,
"id": "FLsp6CnxiNbUU0AJtu",
"playlistStarts": 23,
"thumbNail": {
"url": "https://i.ytimg.com/vi/default.jpg",
"width": 120,
"height": 90
},
"title": "Favorites",
"views": 20,
"viewsPerPlaylistStart": 23
}
],
"lastUpdated": "2023-01-18T03:09:59.757Z",
"nextUpdate": "2023-01-18T03:42:29.757Z"
}
```
```json 400: Error getting analytics theme={"system"}
{
"action": "analytics",
"status": "error",
"code": 294,
"message": "Error getting analytics."
}
```
# Delete Auto Schedule
Source: https://www.ayrshare.com/docs/apis/auto-schedule/delete-schedule
DELETE /auto-schedule/delete
Delete a specified auto schedule
Delete a particular auto schedule. Provide the title of the schedule or "default" is used.
## Header Parameters
## Body Parameters
The title of the schedule to delete.
This should match a schedule title that was previously created using the [Set Auto Schedule endpoint](/docs/apis/auto-schedule/set-schedule).
If no title is provided, the system will attempt to delete the "default" schedule.
Reset the schedule's starting point to the current time.
When set to `true`, this will clear the last used schedule date, causing any new posts to be scheduled starting from the current time.
Any posts that were already scheduled will remain unchanged and publish at their original times.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API Key" \
-H 'Content-Type: application/json' \
-d '{"title": "Schedule Title"}' \
-X DELETE https://api.ayrshare.com/api/auto-schedule/delete
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const title = "Schedule Title";
fetch("https://api.ayrshare.com/api/auto-schedule/delete", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({ title }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'title': 'Schedule Title'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/auto-schedule/delete',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$title
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.ayrshare.com/api/auto-schedule/delete",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE", // Set the request method to DELETE
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer " . $API_KEY
]
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$json = json_decode($response, true);
print_r($json);
}
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace AutoScheduleDELETERequest_csharp
{
class AutoScheduleDELETE
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/auto-schedule/delete";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"title\": \"Schedule Title\"}";
try
{
var request = new HttpRequestMessage
{
Method = HttpMethod.Delete,
RequestUri = new Uri(url),
Content = new StringContent(json, Encoding.UTF8, "application/json")
};
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```javascript 200: Success theme={"system"}
{
status: "success",
title: "Schedule Title"
}
```
# List Auto Schedule
Source: https://www.ayrshare.com/docs/apis/auto-schedule/list-schedule
GET /auto-schedule/list
List the active auto schedules
List the active auto schedules. Returns an array of schedules with titles, times, and last scheduled date. The `lastScheduleDate` timestamp is the next schedule date or the previously scheduled date if no pending posts.
## Header Parameters
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/auto-schedule/list
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/auto-schedule/list", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/auto-schedule/list', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/auto-schedule/list",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . $API_KEY
]
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$json = json_decode($response, true);
print_r($json);
}
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace AutoScheduleGETRequest_csharp
{
class AutoSchedule
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/auto-schedule/list";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```javascript 200: Success theme={"system"}
{
"status": "success",
"schedules": {
"Title 1": {
"lastScheduleDate": "2024-01-05T22:30:00Z",
"schedule": [
"20:03Z",
"22:34Z"
]
},
"Title 2": {
"schedule": [
"13:05Z",
"22:14Z"
],
"lastScheduleDate": "2024-01-04T22:30:00Z",
"daysOfWeek": [
2,
3,
4
]
}
}
}
```
# Auto Schedule Overview
Source: https://www.ayrshare.com/docs/apis/auto-schedule/overview
Create a schedule for future posts to automatically be published
Auto scheduling allows you to create pre-defined posting schedules.
You can set up multiple schedules, each with specific posting times on chosen days.
Auto schedule is distinct from the `scheduleDate` field in the [Publish Post endpoint](/docs/apis/post/post).
## Key Features of Auto Schedule
Create custom schedules, e.g., post at 9 AM, 2 PM, and 5 PM on Mondays and Wednesdays.
Posts are automatically queued in the next available time slot.
No limit on the number of schedules you can create.
Auto schedule is distinct from the `scheduleDate` field in the [Publish Post
endpoint](/docs/apis/post/post) and it is meant to automate scheduling. You should use either auto
schedule or `scheduleDate`, but not both.
## Example Auto Schedule Scenario
1. Current time: Monday, 10 AM (GMT).
2. You create an auto schedule for posting at 9 AM and 5 PM.
3. You add three posts to this schedule.
4. The system automatically schedules these posts for: Monday at 5 PM, Tuesday at 9 AM, and Tuesday at 5 PM.
Deleting a scheduled post doesn't free up its time slot. For example, if you delete the Monday 5
PM post and add a new post to the same schedule, it will be placed in the next available slot (in
this case, Wednesday at 9 AM).
## Publish Using Auto Schedule
The schedule may be applied with the [Publish Post endpoint](/docs/apis/post/post) using the following fields:
```json Auto Schedule theme={"system"}
"autoSchedule": {
"schedule": true, // required
"title": "Schedule Title" // optional - case-sensitive
}
```
`schedule`: (required) A Boolean value that must be set to `true` to enable auto scheduling.
`title`: (optional) A String value that specifies the name of the schedule. This `title` should
match the name of a schedule created using the [Set Auto Schedule](/docs/apis/auto-schedule/overview)
endpoint. If not provided, the default title is `default`. Note that the `title` is
case-sensitive and must be an exact match.
See your list of auto schedules by calling the [List Auto Schedules](/docs/apis/auto-schedule/list-schedule) endpoint.
Please see this article on [using the auto scheduling API](https://www.ayrshare.com/blog/understanding-the-ayrshare-auto-schedule-api-endpoint/) for more information.
## User Profile Auto Schedule
Auto schedule for a particular user profile by [adding the PROFILE\_KEY in the header](/docs/apis/overview#profile-key-format).
# Get Pending Auto Schedule Posts
Source: https://www.ayrshare.com/docs/apis/auto-schedule/pending-auto-schedule
GET /auto-schedule/pending
Get pending auto schedule posts
Retrieve all the pending (not yet published) auto schedule posts.
## Header Parameters
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/auto-schedule/pending
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/auto-schedule/pending", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/auto-schedule/pending', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://api.ayrshare.com/api/auto-schedule/pending",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => [
"Authorization: Bearer " . $API_KEY
]
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$json = json_decode($response, true);
print_r($json);
}
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace AutoSchedulePendingGETRequest_csharp
{
class AutoSchedulePending
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/auto-schedule/pending";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```javascript 200: Schedule Set theme={"system"}
{
status: "success",
message: "Auto schedule set.",
title: "Schedule title",
}
```
# Set Auto Schedule
Source: https://www.ayrshare.com/docs/apis/auto-schedule/set-schedule
POST /auto-schedule/set
Set up an auto-post schedule by providing times to send
Set up an auto-post schedule by providing times to send. Post will automatically be sent at the next available time. If no more times are available today, the first available time tomorrow will be used, and so on.
If you're looking to just schedule a post for a future date, please see the `scheduleDate`
parameter of [/post](/docs/apis/post/post)
Use the auto-schedule by setting the /post autoSchedule parameter to `true` and the `title` if you want to use a particular schedule. Example, set the times to UTC time 13:05Z and 20:14Z and `autoSchedule: true` in the post. The post will be scheduled at the next available time of 13:05Z or 20:14Z.
## Header Parameters
## Body Parameters
Array of strings of scheduled times to auto-post. The array will be treated as a set, so duplicates removed.
Format: ISO-8601 UTC. Example: `["13:05Z", "22:14Z"]`. Not required if `setStartDate` provided.
You can create multiple different posting schedules by assigning a unique title to each one. The title must contain only alphanumeric characters - special characters like `*`, `~`, `/`, `[`, or `]` are not allowed.
If you specify the `title` in /post with autoScheduleTitle, that schedule will be used.
Set a specific beginning date to start the auto schedule, provide a ISO-8601 UTC date time. E.g. `2021-07-08T12:30:00Z`. The start time will be applied to the provided "title" or will use the default title if one isn't provided.
New posts will go out from the start date onwards. Previously scheduled posts are not affected.
Specify which days of the week the post should be sent. Values 0-6 (Sunday - Saturday). For example `[1, 3]` will only publish posts on Mondays and Wednesdays.
Exclude certain dates from auto scheduling occurring. For example `["2026-01-01"]` to exclude New Years.
Note, only posts auto scheduled after the `excludeDates` has been set will be excluded.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"schedule": ["13:05Z", "20:14Z"], "title": "Instagram Schedule"}' \
-X POST https://api.ayrshare.com/api/auto-schedule/set
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const title = "Instagram Schedule";
fetch("https://api.ayrshare.com/api/auto-schedule/set", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
schedule: ["13:05Z", "20:14Z"], // required
title: title // optional
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```php PHP theme={"system"}
["13:05Z", "20:14Z"], // required
'title' => "Instagram Schedule" // optional
];
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_URL => "https://api.ayrshare.com/api/auto-schedule/set",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"Authorization: Bearer " . $API_KEY
]
]);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$json = json_decode($response, true);
print_r($json);
}
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace AutoSchedulePOSTRequest_csharp
{
class AutoSchedule
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/auto-schedule/set";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
var payload = new
{
schedule = new[] { "13:05Z", "20:14Z" },
title = "Instagram Schedule"
};
try
{
var content = new StringContent(
System.Text.Json.JsonSerializer.Serialize(payload),
System.Text.Encoding.UTF8,
"application/json"
);
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"schedule": []string{"13:05Z", "20:14Z"},
"title": "Instagram Schedule"
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/auto-schedule/set",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```javascript 200: Schedule Set theme={"system"}
{
status: "success",
message: "Auto schedule set.",
title: "Instagram Schedule",
}
```
# Create Automation
Source: https://www.ayrshare.com/docs/apis/automations/create-automation
POST /automations
Create a new engagement-triggered automation
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description, including the Beta status.
Create a new automation that fires one or more actions when any of its triggers matches. The automation activates immediately. See the [Overview](/docs/apis/automations/overview) for the full catalog of triggers, actions, template variables, and limits.
The connected Instagram account is derived server-side from the caller's linked profile — **do not pass `accountId`** in the body; the request will be rejected as a validation error if you do. Pass a `profileKey` header to operate under a child profile.
## Header Parameters
## Body Parameters
Target platform. Only `instagram` is supported in v1.
Short human-readable name. Used in the dashboard and activity logs.
Optional longer description.
One or more triggers (1–50). Each entry is a discriminated union on `type`. See [Overview / Triggers](/docs/apis/automations/overview#triggers) for the full catalog.
```json comment_keyword trigger theme={"system"}
{
"type": "comment_keyword",
"postId": "17895695668004550", // required — Instagram media id
"keywords": ["INFO", "LINK"] // required — ≥1 entry, case-insensitive
}
```
```json story_reply trigger theme={"system"}
{
"type": "story_reply",
"storyId": "17900000000000000" // optional — scope to one story
}
```
```json dm_reaction trigger theme={"system"}
{
"type": "dm_reaction",
"emoji": "❤️" // optional — scope to one emoji
}
```
```json dm_keyword trigger theme={"system"}
{
"type": "dm_keyword",
"keywords": ["help", "support"] // required — ≥1 entry, case-insensitive
}
```
One or more actions (1–50). Each entry is a discriminated union on `type`. See [Overview / Actions](/docs/apis/automations/overview#actions) for the full catalog. Every action also accepts an optional top-level `dedupWindowMinutes` overriding the default 7-day per-recipient dedup window (`0` to disable, max `525600`).
```json send_dm action theme={"system"}
{
"type": "send_dm",
"message": "Hey {{recipient_username}}, here is the link you wanted: https://example.com"
}
```
```json fire_webhook action theme={"system"}
{
"type": "fire_webhook"
// POSTs to your account-level webhook URL (configured in the dashboard).
// See Overview for the JSON payload shape.
}
```
```json send_email action theme={"system"}
{
"type": "send_email",
"to": "alerts@example.com",
"subject": "New {{platform}} engagement from @{{recipient_username}}",
"message": "
"
}
```
```json Action with per-action dedup override theme={"system"}
{
"type": "send_dm",
"message": "Thanks {{recipient_username}}!",
"dedupWindowMinutes": 1440 // 24h instead of the 7-day default
}
```
**Platform compatibility.** Each trigger and action declares which platforms it supports. The validator rejects the request when an entry's `type` is not supported on the requested `platform`. All triggers and `send_dm` are currently Instagram-only; `fire_webhook` and `send_email` are platform-agnostic.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"platform": "instagram",
"name": "Spring promo",
"triggers": [
{
"type": "comment_keyword",
"postId": "17895695668004550",
"keywords": ["INFO", "LINK"]
}
],
"actions": [
{
"type": "send_dm",
"message": "Hey {{recipient_username}}, here is the link you wanted: https://example.com"
}
]
}' \
-X POST https://api.ayrshare.com/api/automations
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/automations", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
platform: "instagram",
name: "Spring promo",
triggers: [
{
type: "comment_keyword",
postId: "17895695668004550",
keywords: ["INFO", "LINK"],
},
],
actions: [
{
type: "send_dm",
message: "Hey {{recipient_username}}, here is the link you wanted: https://example.com",
},
],
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {
"platform": "instagram",
"name": "Spring promo",
"triggers": [
{
"type": "comment_keyword",
"postId": "17895695668004550",
"keywords": ["INFO", "LINK"],
}
],
"actions": [
{
"type": "send_dm",
"message": "Hey {{recipient_username}}, here is the link you wanted: https://example.com",
}
],
}
headers = {
"Authorization": "Bearer API_KEY",
"Content-Type": "application/json",
}
r = requests.post(
"https://api.ayrshare.com/api/automations",
json=payload,
headers=headers,
)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
$data = [
"platform" => "instagram",
"name" => "Spring promo",
"triggers" => [
[
"type" => "comment_keyword",
"postId" => "17895695668004550",
"keywords" => ["INFO", "LINK"],
],
],
"actions" => [
[
"type" => "send_dm",
"message" => "Hey {{recipient_username}}, here is the link you wanted: https://example.com",
],
],
];
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY",
"Content-Type: application/json",
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "auto_9xKp2Lm4nQ"
}
```
```json 400: Validation failed — unknown template variable theme={"system"}
{
"action": "request",
"status": "error",
"code": 473,
"message": "Validation failed. Please see: https://www.ayrshare.com/docs/introduction",
"details": {
"formErrors": [],
"fieldErrors": {
"actions": ["message contains unknown template variables"]
}
}
}
```
```json 400: Validation failed — comment_keyword trigger missing keywords theme={"system"}
{
"action": "request",
"status": "error",
"code": 473,
"message": "Validation failed. Please see: https://www.ayrshare.com/docs/introduction",
"details": {
"formErrors": [],
"fieldErrors": {
"triggers": ["Invalid input: expected array, received undefined"]
}
}
}
```
```json 400: Validation failed — unrecognized field (e.g. accountId) theme={"system"}
{
"action": "request",
"status": "error",
"code": 473,
"message": "Validation failed. Please see: https://www.ayrshare.com/docs/introduction",
"details": {
"formErrors": ["Unrecognized key: \"accountId\""],
"fieldErrors": {}
}
}
```
```json 403: Plan tier required theme={"system"}
{
"action": "automation",
"status": "error",
"code": 468,
"message": "Instagram DM automations require a Business or Enterprise plan"
}
```
```json 403: Feature flag not yet enabled theme={"system"}
{
"action": "request",
"status": "error",
"code": 472,
"message": "This feature is not yet available on your account. Please contact us if you'd like early access."
}
```
```json 400: No linked social account for this platform theme={"system"}
{
"action": "automation",
"status": "error",
"code": 471,
"message": "No social account linked on the requested platform for this profile. Link the account on the Social Accounts page and try again."
}
```
```json 429: Active automation cap reached theme={"system"}
{
"action": "automation",
"status": "error",
"code": 470,
"message": "Active automation limit reached for your plan tier"
}
```
# Delete Automation
Source: https://www.ayrshare.com/docs/apis/automations/delete-automation
DELETE /automations/:id
Soft-delete an automation
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description.
Soft-deletes the automation. The master row is flagged `deleted: true, active: false`; no new dispatches occur from this point on.
Existing triggers, actions, and activity rows are **not** cascaded. The activity history remains queryable via [`GET /automations/:id/activity`](/docs/apis/automations/get-activity) for as long as the rows exist in Firestore (retention is indefinite for trace and analytics).
Soft-deleted automations no longer count against your active automation cap. They cannot be restored via the API; create a new automation instead.
## Header Parameters
## Path Parameters
The automation ID returned from `POST /automations`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X DELETE https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
fetch(`https://api.ayrshare.com/api/automations/${id}`, {
method: "DELETE",
headers: { "Authorization": `Bearer ${API_KEY}` },
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
r = requests.delete(
f"https://api.ayrshare.com/api/automations/{automation_id}",
headers=headers,
)
print(r.json())
```
```php PHP theme={"system"}
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "DELETE",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "auto_9xKp2Lm4nQ"
}
```
```json 404: Not found theme={"system"}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
```
# Get Automation Activity
Source: https://www.ayrshare.com/docs/apis/automations/get-activity
GET /automations/:id/activity
Cursor-paginated audit log for one automation
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description.
Returns every dispatch attempt for one automation, newest first. Each row records the recipient, the matched trigger, every action's result, and any error.
Rows from the last **30 days** are returned. Older rows exist in Firestore (retention is indefinite for analytics) but are excluded from this endpoint for performance.
## Activity row status
Each row has a top-level `status` plus a per-action `status` inside `actionResults[]`.
| Status | When it's recorded |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pending` | Row was just written; the worker hasn't picked it up yet |
| `in_flight` | The worker is currently dispatching |
| `sent` | Every action was **accepted** by the platform. For `send_dm` this means Instagram accepted the message — **not** that the recipient received it (see the note below) |
| `failed` | At least one action was rejected by the platform or could not run (and none hit an auth error). The reason is on `actionResults[].errorDetails` |
| `auth_error` | The Instagram access token was invalid; the DM was not retried |
| `rate_limited` | The daily DM cap (tier or per-profile) was hit. No DM was sent |
| `deduplicated` | This action already fired to this recipient inside its dedup window (default 7 days, per-action configurable) |
| `skipped` | The automation became inactive or was deleted between fan-out and dispatch |
`pending` and `in_flight` are transient; everything else is terminal.
**`sent` confirms Instagram accepted the message, not that the recipient received it.** Instagram exposes no delivery signal on any API surface, and if the recipient's **Message requests** setting blocks strangers, Meta accepts the send and silently drops it. See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
## Per-action result fields
Each entry in `actionResults[]` describes one action's outcome:
| Field | Type | Description |
| -------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `actionId` | string | The action's stable ID within the automation |
| `type` | string | The action type (`send_dm`, `fire_webhook`, `send_email`) |
| `status` | string | Per-action status, using the same vocabulary as the row `status` above |
| `errorDetails` | string \| `null` | Human-readable failure reason when the action did not succeed; `null` (or absent) on success. For a rejected `send_dm` this carries the mapped error message (e.g. the private-reply window is closed, or the comment already received a reply) |
| `completedAt` | string | ISO 8601 timestamp when the action finished |
For comment-triggered automations (`comment_keyword`), the row also carries a top-level `commentId` — the raw Instagram comment ID the DM was anchored to. It is `null` for message-driven triggers (`dm_keyword`, `story_reply`, `dm_reaction`).
## Header Parameters
## Path Parameters
The automation ID returned from `POST /automations`.
## Query Parameters
Page size. Default `25`, max `100`. Values outside `[1, 100]` are clamped; non-integer or `≤0` returns HTTP 400.
Opaque cursor from a previous response's `meta.pagination.next`. Omit on the first request.
Forward-only — passing `?previous=` returns HTTP 400.
## Response Shape
The response wraps the result list in `activity[]` and the cursor info in `meta.pagination`:
```json theme={"system"}
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [ /* …rows, newest first… */ ],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzpjb21tZW50X3JlY2VpdmVkOjE4MDEyMzQ1Njc4OTAwMDAwIn0="
}
}
}
```
`meta.pagination.next` is a base64-encoded opaque blob — treat it as a black box and pass it back unchanged in the next request's `?next=`. `meta.pagination.hasMore` is `true` when at least one more page exists.
```bash cURL — first page theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25"
```
```bash cURL — next page theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ/activity?limit=25&next=eyJ0aW1lIjoiMjAyNi0wNS0xMlQw..."
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
// Paginate through every page
let next;
do {
const url = new URL(`https://api.ayrshare.com/api/automations/${id}/activity`);
url.searchParams.set("limit", "25");
if (next) url.searchParams.set("next", next);
const res = await fetch(url, {
headers: { "Authorization": `Bearer ${API_KEY}` },
});
const json = await res.json();
console.log(json.activity);
next = json.meta?.pagination?.hasMore ? json.meta.pagination.next : undefined;
} while (next);
```
```python Python theme={"system"}
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
params = {"limit": 25}
while True:
r = requests.get(
f"https://api.ayrshare.com/api/automations/{automation_id}/activity",
params=params,
headers=headers,
).json()
print(r["activity"])
pagination = r.get("meta", {}).get("pagination", {})
if not pagination.get("hasMore"):
break
params["next"] = pagination["next"]
```
```php PHP theme={"system"}
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id . "/activity?limit=25",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"automationId": "auto_9xKp2Lm4nQ",
"activity": [
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:18012345678901234",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841401234567890",
"recipientUsername": "jane_doe",
"eventId": "18012345678901234",
"commentId": "18012345678901234",
"platform": "instagram",
"status": "sent",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "sent",
"errorDetails": null,
"completedAt": "2026-05-12T09:14:48.000Z"
}
],
"keyword": "LINK",
"commentText": "Send me the LINK please!",
"created": "2026-05-12T09:14:22.000Z",
"completedAt": "2026-05-12T09:14:48.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:18012345678905555",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841405555555555",
"recipientUsername": "late_commenter",
"eventId": "18012345678905555",
"commentId": "18012345678905555",
"platform": "instagram",
"status": "failed",
"actionResults": [
{
"actionId": "act_d4e5f6",
"type": "send_dm",
"status": "failed",
"errorDetails": "Cannot send private reply: This comment is no longer eligible for a private reply.",
"completedAt": "2026-05-12T09:12:03.000Z"
}
],
"keyword": "LINK",
"commentText": "LINK please!",
"created": "2026-05-12T09:12:01.000Z",
"completedAt": "2026-05-12T09:12:03.000Z"
},
{
"id": "auto_9xKp2Lm4nQ:trg_a1b2c3:18012345678900000",
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"triggerType": "comment_keyword",
"recipientId": "17841409876543210",
"recipientUsername": "repeat_user",
"eventId": "18012345678900000",
"commentId": "18012345678900000",
"platform": "instagram",
"status": "deduplicated",
"actionResults": [],
"keyword": "LINK",
"commentText": "LINK again please",
"created": "2026-05-12T09:00:11.000Z",
"completedAt": "2026-05-12T09:00:34.000Z"
}
],
"meta": {
"pagination": {
"hasMore": true,
"limit": 25,
"next": "eyJ0aW1lIjoiMjAyNi0wNS0xMlQwOTowMDoxMS4wMDBaIiwiaWQiOiJhdXRvXzl4S3AyTG00blE6dHJnX2ExYjJjMzoxODAxMjM0NTY3ODkwMDAwMCJ9"
}
}
}
```
```json 400: Bad limit theme={"system"}
{
"status": "error",
"message": "limit must be a positive integer"
}
```
```json 400: Backward pagination not supported theme={"system"}
{
"status": "error",
"message": "'previous' pagination is not supported by this endpoint"
}
```
```json 404: Not found theme={"system"}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
```
# Get Automation
Source: https://www.ayrshare.com/docs/apis/automations/get-automation
GET /automations/:id
Fetch one automation with its triggers and actions
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description.
Returns one automation including every attached trigger and action. Soft-deleted automations return `469` so an attacker probing for IDs gets the same response as a legitimate "not found".
## Header Parameters
## Path Parameters
The automation ID returned from `POST /automations`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
fetch(`https://api.ayrshare.com/api/automations/${id}`, {
method: "GET",
headers: { "Authorization": `Bearer ${API_KEY}` },
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {"Authorization": "Bearer API_KEY"}
automation_id = "auto_9xKp2Lm4nQ"
r = requests.get(
f"https://api.ayrshare.com/api/automations/{automation_id}",
headers=headers,
)
print(r.json())
```
```php PHP theme={"system"}
$id = "auto_9xKp2Lm4nQ";
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "auto_9xKp2Lm4nQ",
"platform": "instagram",
"accountId": "17841400000000000",
"name": "Spring promo",
"description": "",
"active": true,
"stats": {
"totalSent": 42,
"totalFailed": 1,
"lastTriggeredAt": "2026-05-12T09:14:22.000Z",
"lastSentAt": "2026-05-12T09:14:48.000Z"
},
"created": "2026-04-30T12:00:00.000Z",
"updated": "2026-05-12T09:14:48.000Z",
"triggers": [
{
"id": "trg_a1b2c3",
"type": "comment_keyword",
"active": true,
"config": {
"postId": "17895695668004550",
"keywords": ["INFO", "LINK"]
}
}
],
"actions": [
{
"id": "act_d4e5f6",
"type": "send_dm",
"active": true,
"config": {
"message": "Hey {{recipient_username}}, here is the link you wanted: https://example.com"
}
}
]
}
```
```json 404: Not found theme={"system"}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
```
# List Automations
Source: https://www.ayrshare.com/docs/apis/automations/list-automations
GET /automations
List the automations you've created
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description.
Returns every active and inactive automation for the caller. Soft-deleted automations are excluded.
## Header Parameters
## Query Parameters
Optional. Filter to automations targeting this platform. Only `instagram` is currently supported.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/automations?platform=instagram"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/automations?platform=instagram", {
method: "GET",
headers: { "Authorization": `Bearer ${API_KEY}` },
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {"Authorization": "Bearer API_KEY"}
r = requests.get(
"https://api.ayrshare.com/api/automations",
params={"platform": "instagram"},
headers=headers,
)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations?platform=instagram",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "GET",
CURLOPT_HTTPHEADER => ["Authorization: Bearer API_KEY"],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"automations": [
{
"id": "auto_9xKp2Lm4nQ",
"platform": "instagram",
"accountId": "17841400000000000",
"name": "Spring promo",
"description": "",
"active": true,
"stats": {
"totalSent": 42,
"totalFailed": 1,
"lastTriggeredAt": "2026-05-12T09:14:22.000Z",
"lastSentAt": "2026-05-12T09:14:48.000Z"
},
"created": "2026-04-30T12:00:00.000Z",
"updated": "2026-05-12T09:14:48.000Z"
}
]
}
```
```json 403: Plan tier theme={"system"}
{
"action": "automation",
"status": "error",
"code": 468,
"message": "Instagram DM automations require a Business or Enterprise plan"
}
```
# Automations API Overview
Source: https://www.ayrshare.com/docs/apis/automations/overview
Engagement-triggered Instagram automations — fire a DM, webhook, or email when an end user comments, replies to a story, reacts to a DM, or sends a DM
**Beta.** The Automations API is in beta and we are actively collecting feedback. Endpoints, payloads, and limits may change as we iterate. Please send feedback and bug reports to support so we can prioritize the right improvements.
The Automations endpoints let you define rules that automatically react to incoming Instagram engagement. Each automation pairs one or more **triggers** (the event that fires the rule) with one or more **actions** (what happens when it fires). A single rule can listen for multiple triggers and dispatch multiple actions — fire a webhook into your analytics pipeline AND send a DM from the same engagement.
The engine only reacts to engagement a user directs at you (a comment, story reply, DM, or reaction) — it never sends follow-triggered DMs, first-message DMs to strangers, or bulk outbound — and it inherits Ayrshare's per-account rate limits, per-recipient deduplication, and idempotent webhook ingestion.
**`sent` means Meta accepted the message, not that the recipient received it.** Delivery is ultimately dictated by the recipient's Instagram **Message requests** setting: if they don't allow message requests from everyone, Meta returns a success response and silently drops the message, and this is invisible at every API layer. Even a delivered comment-triggered DM arrives as a **message request the recipient must accept** (unless a conversation already exists between the two accounts). See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered) for the full explanation.
## How it works
`POST /automations` with the triggers and actions you want. The automation activates immediately.
Someone comments on your post, replies to your story, sends a DM, or reacts to a DM. Meta delivers the webhook to Ayrshare.
The engine looks up every rule matching the event, checks per-action deduplication and your daily DM cap, then runs each action. A 20–60 second jitter is applied to DM sends to stay inside Instagram's anti-spam heuristics.
`GET /automations/:id/activity` returns the audit log — every dispatch attempt, the per-action results, and any errors.
## Triggers
You can attach up to **50 triggers** to one automation. Each trigger is a discriminated union on the `type` field; type-specific fields live at the same level. All triggers are Instagram-only in v1.
| Type | Fires when | Config |
| ----------------- | ----------------------------------------------------- | ---------------------------------------------------- |
| `comment_keyword` | A comment matching a keyword lands on a specific post | `postId` (required); `keywords` (required, ≥1 entry) |
| `story_reply` | A user replies to a story via DM | `storyId` (optional) |
| `dm_reaction` | A user reacts to one of your DMs with an emoji | `emoji` (optional — omit to fire on any emoji) |
| `dm_keyword` | A user sends a DM whose text matches a keyword | `keywords` (required, ≥1 entry) |
Keyword matching is **case-insensitive** and whole-word. An event satisfies a keyword-filtered trigger if it contains any one of the configured keywords. Omit `storyId` on a story trigger to fire on every story for the connected account.
## Actions
You can attach up to **50 actions** to one automation. They run sequentially; each result is recorded on the activity row.
| Type | Effect | Config |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------- |
| `send_dm` | Sends an Instagram DM to the user who triggered the rule, using a [templated message](#template-variables). | `message` (required, templated) |
| `fire_webhook` | POSTs the automation context to your account-level webhook URL (configure via [`POST /hook/webhook`](/docs/apis/webhooks/register)). | *(none — payload shape is fixed; see [below](#fire_webhook-payload))* |
| `send_email` | Queues an email via the platform's mail pipeline. | `to` (required, email); `subject` (optional, templated); `message` (required, templated) |
### Per-action dedup window
Every action — regardless of type — additionally accepts an optional top-level `dedupWindowMinutes` field that overrides the **default 7-day** per-recipient dedup window for that action only.
* Set to `0` to **disable** dedup entirely for that action (typical for `fire_webhook` / `send_email` where the receiver expects every event).
* Capped at `525600` (one year).
```json Action with a 24h dedup override theme={"system"}
{
"type": "send_dm",
"message": "Thanks {{recipient_username}}!",
"dedupWindowMinutes": 1440
}
```
### `fire_webhook` payload
When `fire_webhook` runs it POSTs a JSON body to your account-level webhook URL:
```json theme={"system"}
{
"automationId": "auto_9xKp2Lm4nQ",
"triggerId": "trg_a1b2c3",
"trigger": "comment_keyword",
"platform": "instagram",
"recipientId": "17841401234567890",
"recipientUsername": "jane_doe",
"keyword": "LINK",
"timestamp": "2026-05-12T09:14:22.000Z"
}
```
`recipientUsername` and `keyword` are `null` when the trigger doesn't populate them (e.g. `dm_keyword` doesn't carry a username on Meta's payload; `story_reply` doesn't have a keyword).
## Template variables
`send_dm.message`, `send_email.subject`, and `send_email.message` support `{{placeholder}}` substitution. **Unknown placeholders are rejected at create/update time** (as a `473` validation error) so a typo never silently leaks the literal `{{foo}}` into a customer-facing message.
| Placeholder | Resolves to |
| ------------------------ | ------------------------------------------------------------------------- |
| `{{recipient_username}}` | The engaging user's Instagram handle (when the webhook carries it) |
| `{{recipient_id}}` | The engaging user's Instagram participant ID (IGSID) |
| `{{recipient_name}}` | Reserved; resolves to empty until a future enrichment source populates it |
| `{{sender_username}}` | Your linked Instagram username |
| `{{sender_name}}` | Your linked Instagram display name |
| `{{comment_text}}` | The text of the comment / DM / story reply that fired the trigger |
| `{{comment_id}}` | The platform id of the comment / message that fired |
| `{{comment_sent_at}}` | ISO 8601 timestamp of the event (when available) |
| `{{matched_keyword}}` | The keyword that matched (or the emoji string for `dm_reaction`) |
| `{{platform}}` | Platform identifier (e.g. `instagram`) |
| `{{trigger_type}}` | Trigger type (e.g. `comment_keyword`) |
**No `sender_email` / `recipient_email`.** These are deliberately not exposed — your billing email has no legitimate place in a DM to a stranger, and Meta does not provide the recipient's email on any IG webhook. Avoiding the placeholders prevents accidental disclosure.
Example template:
```
Hey {{recipient_username}}, thanks for the comment "{{comment_text}}" — here is the link you wanted: https://example.com
```
## Rate limits and caps
| Plan | Active automations (per profile) | Daily DM cap (per account) |
| ---------- | -------------------------------- | -------------------------- |
| Business | 10 | 1,000 |
| Enterprise | 50 | 5,000 |
The active-automation cap is counted **per [User Profile](/docs/apis/profiles/overview)**, not per parent account. Each profile under your account gets its own Business 10 / Enterprise 50, so an account with many profiles can run that many automations on each. It counts active automations and is enforced on both `POST` (create) and `PUT` re-activation (`active: false → true`), each surfacing error code `470`. Need a higher per-profile limit? [Contact support](mailto:support@ayrshare.com) to have it raised for your account.
The **daily DM cap** applies per parent Ayrshare account, shared across all your profiles, with a per-profile sub-cap so one busy profile cannot drain the whole account's quota. When a DM cap is hit, the activity row records status `rate_limited` and no DM is sent.
Structural caps on a single automation: **1–50 triggers**, **1–50 actions**.
Instagram itself caps DMs at roughly 200/hour per account. The engine paces dispatch with a 20–60 second jitter to stay safely under this.
## Activity statuses
A row in `GET /automations/:id/activity` carries a top-level `status` plus a per-action `status` inside `actionResults[]`:
| Status | Meaning |
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `pending` | Just written; the worker hasn't picked it up yet |
| `in_flight` | Worker is currently dispatching |
| `sent` | Every action was **accepted** by the platform. For `send_dm` this means Instagram accepted the message — **not** that the recipient received it (see the note below) |
| `failed` | At least one action was rejected by the platform or could not run (and none hit an auth error). The reason is on `actionResults[].errorDetails` |
| `auth_error` | The Instagram access token was invalid; the DM was not retried |
| `rate_limited` | The daily DM cap (tier or per-profile) was hit; no DM was sent |
| `deduplicated` | This action already fired to this recipient inside its dedup window |
| `skipped` | The automation became inactive or was deleted between fan-out and dispatch |
`pending` and `in_flight` are transient; everything else is terminal.
**`sent` is a platform-acceptance receipt, not a delivery receipt.** Instagram does not expose message delivery to any API. A `send_dm` action is marked `sent` the moment Instagram accepts the message; whether the recipient actually receives it depends on their Instagram **Message requests** setting, which Ayrshare cannot read or influence. See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
## Error codes
The API returns two shapes of error:
* **Business-rule errors** carry a numbered automation `code` (e.g. `{ "action": "automation", "code": 469, ... }`).
* **Validation errors** — any malformed request body (missing or invalid fields, unknown template variables, unrecognized keys) — are returned as a single **`473`** response with a `details` object that lists the offending fields. `details` is the validator's output (`formErrors` plus `fieldErrors`). Branch on `details`, not on a per-condition code. In `fieldErrors`, keys are the top-level request fields (`triggers`, `actions`): a problem inside a specific entry, such as a trigger missing its `keywords`, is reported under that field (e.g. `triggers`), while `formErrors` holds object-level issues such as unrecognized keys.
| Code | HTTP | Meaning |
| ---- | ---- | ----------------------------------------------------------------------- |
| 468 | 403 | Business or Enterprise plan required |
| 469 | 404 | Automation not found (also returned when the caller doesn't own it) |
| 470 | 429 | Active automation cap reached for your plan tier |
| 471 | 400 | No social account linked on the requested platform for this profile |
| 472 | 403 | Feature not yet available on your account — contact us for early access |
| 473 | 400 | Validation failed (malformed request body) — inspect `details` |
## What Meta does NOT allow
A few commonly-requested capabilities are not supported because Meta doesn't permit them on the public Instagram API:
* **Auto-DM on new followers.** Instagram does not publish a follow webhook.
* **First-message DMs to strangers.** Meta requires the recipient to have engaged first (comment, reply, DM, reaction) before a business account can message them. Every supported trigger is anchored to such an engagement — but note that being *allowed* to send is not the same as the message being *delivered*: the recipient's Instagram **Message requests** setting can still cause Meta to accept and then silently drop the message (see [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered)).
* **Bulk outbound campaigns.** Hourly DM caps and anti-abuse heuristics apply at the platform level.
## Multi-profile usage
The endpoints respect the `profileKey` header. Pass a child profile's key and the automation is created/managed under that profile. Rate limits split across profiles via a per-profile sub-cap so one chatty profile doesn't drain the parent account's quota.
## FAQ
No. Instagram does not publish a follow webhook, and Meta does not allow third-party apps to send a DM to a user who has not engaged first. Every supported trigger (`comment_keyword`, `story_reply`, `dm_reaction`, `dm_keyword`) is anchored to such an engagement, which is what makes the send permissible.
`sent` means Instagram **accepted** the message, not that it was delivered. Delivery depends on the recipient's Instagram **Message requests** setting — if they don't allow message requests from everyone, Meta returns a success response and silently drops the message, with no error, webhook, or other signal on any API surface. A successful comment-triggered DM also arrives as a **message request the recipient must accept** (unless a conversation already exists). This is a permanent Instagram platform limitation. See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
The activity row records status `auth_error` and the DM is not retried. Relink the account, then the next matching engagement will fire normally.
Each `send_dm` dispatch is scheduled 20–60 seconds after the engagement to look organic to Instagram's anti-spam systems. `fire_webhook` and `send_email` actions do NOT have jitter. The activity row's `created` timestamp is when the trigger matched; `completedAt` is when dispatch finished.
Activity rows are retained indefinitely for trace and analytics. The `GET /automations/:id/activity` endpoint returns rows from the last 30 days for performance. (The dedup guard uses its own per-action window — defaulting to 7 days — which is unrelated to the activity lookback.)
No. Delete is a soft-delete: the master row is flagged `deleted`, no new dispatches occur, but historical activity rows remain readable via the activity endpoint.
## Endpoints
* [`POST /automations`](/docs/apis/automations/create-automation) — create a new automation
* [`GET /automations`](/docs/apis/automations/list-automations) — list your automations
* [`GET /automations/:id`](/docs/apis/automations/get-automation) — fetch one automation with its triggers and actions
* [`PUT /automations/:id`](/docs/apis/automations/update-automation) — partial update; pause via `active: false`
* [`DELETE /automations/:id`](/docs/apis/automations/delete-automation) — soft-delete
* [`GET /automations/:id/activity`](/docs/apis/automations/get-activity) — cursor-paginated dispatch audit log
# Update Automation
Source: https://www.ayrshare.com/docs/apis/automations/update-automation
PUT /automations/:id
Update an existing automation
**Beta.** See the [Automations Overview](/docs/apis/automations/overview) for the full feature description.
Partial update. Only the listed fields are editable; sending anything else (e.g. `platform`, `accountId`) is rejected as a validation error.
Sending `triggers` or `actions` **replaces** the existing children atomically: the old set is deleted and the new set is written in a single Firestore transaction. To change only one trigger, send the full new array.
Re-activating a previously-inactive automation (`active: true`) re-checks the active-cap. If the cap is already at the limit, the update fails with code `470` and no changes are made.
## Header Parameters
## Path Parameters
The automation ID returned from `POST /automations`.
## Body Parameters
New name.
New description.
Toggle the automation on or off. Setting this from `false` to `true` re-checks the active automation cap.
Full replacement set of triggers (1–50). Same shape as the create endpoint.
Full replacement set of actions (1–50). Same shape as the create endpoint.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"name": "Spring promo (updated)",
"active": true,
"actions": [
{
"type": "send_dm",
"message": "Hey {{recipient_username}}! New link: https://example.com/spring"
}
]
}' \
-X PUT https://api.ayrshare.com/api/automations/auto_9xKp2Lm4nQ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "auto_9xKp2Lm4nQ";
fetch(`https://api.ayrshare.com/api/automations/${id}`, {
method: "PUT",
headers: {
"Authorization": `Bearer ${API_KEY}`,
"Content-Type": "application/json",
},
body: JSON.stringify({
name: "Spring promo (updated)",
active: true,
actions: [
{
type: "send_dm",
message: "Hey {{recipient_username}}! New link: https://example.com/spring",
},
],
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {
"Authorization": "Bearer API_KEY",
"Content-Type": "application/json",
}
automation_id = "auto_9xKp2Lm4nQ"
payload = {
"name": "Spring promo (updated)",
"active": True,
"actions": [
{
"type": "send_dm",
"message": "Hey {{recipient_username}}! New link: https://example.com/spring",
}
],
}
r = requests.put(
f"https://api.ayrshare.com/api/automations/{automation_id}",
json=payload,
headers=headers,
)
print(r.json())
```
```php PHP theme={"system"}
$id = "auto_9xKp2Lm4nQ";
$data = [
"name" => "Spring promo (updated)",
"active" => true,
"actions" => [
[
"type" => "send_dm",
"message" => "Hey {{recipient_username}}! New link: https://example.com/spring",
],
],
];
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.ayrshare.com/api/automations/" . $id,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer API_KEY",
"Content-Type: application/json",
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "auto_9xKp2Lm4nQ"
}
```
```json 400: Validation failed — editing platform is not allowed theme={"system"}
{
"action": "request",
"status": "error",
"code": 473,
"message": "Validation failed. Please see: https://www.ayrshare.com/docs/introduction",
"details": {
"formErrors": ["Unrecognized key: \"platform\""],
"fieldErrors": {}
}
}
```
```json 404: Not found theme={"system"}
{
"action": "automation",
"status": "error",
"code": 469,
"message": "Automation not found"
}
```
```json 429: Cap reached on reactivation theme={"system"}
{
"action": "automation",
"status": "error",
"code": 470,
"message": "Active automation limit reached for your plan tier"
}
```
# Brand API: Public Account & Competitor Data | Ayrshare Docs
Source: https://www.ayrshare.com/docs/apis/brand/overview
Use the Ayrshare Brand API to pull public profile, follower, and engagement data for any social account, to track your brand or benchmark competitors.
**These endpoints have moved.** The Brand section has been reorganized under the new [Listening](/docs/apis/listen/overview) section. All existing Brand endpoints continue to work, but new features like [Keyword Search](/docs/apis/listen/keyword/search-tweets) are available only in the Listening section.
# Delete Comments
Source: https://www.ayrshare.com/docs/apis/comments/delete-comments
DELETE /comments/:id
Delete either a single comment or all comments under a post
The delete endpoint allows you to either delete comments sent via Ayrshare or comments that were sent outside of Ayrshare.
Please see the [Comments Overview](/docs/apis/comments/overview) for more information on the different ID types.
### Delete Comments Sent from Ayrshare
Delete either a single comment or all comments under a post that were sent via Ayrshare.
Please see the [Ayrshare Post ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id) and [Ayrshare Comment ID](/docs/apis/comments/overview#comments-with-ayrshare-comment-id) for more information.
Supported platforms: Bluesky, Facebook, Instagram, LinkedIn, Reddit, TikTok, X/Twitter, and YouTube.
### Delete Comments Sent Outside of Ayrshare
Delete a comment that was not sent via Ayrshare by using the `commentId` returned for a particular social network.
This is the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id) from the social networks, not the Ayrshare ID.
Supported platforms: Facebook, Instagram, TikTok, X/Twitter, and YouTube.
**TikTok — own-authored comments only.** On TikTok, `DELETE /comments` only succeeds for comments authored by the authenticated TikTok account itself (for example, replies you posted via Ayrshare's [reply endpoint](/docs/apis/comments/reply-to-comment) or directly inside the TikTok app). Attempting to delete a comment authored by another user — even one left on a video you own — returns Ayrshare `code: 328`. If you need to moderate third-party comments on your own TikTok videos, contact support so we can confirm what's available for your linked account type.
For example, you get all the comments for a particular Instagram post using the [Get Comments](/docs/apis/comments/get-comments) endpoint with the `searchPlatformId` set to `true`.
```http theme={"system"}
GET https://api.ayrshare.com/api/comments/18231730279304111?platform=instagram&searchPlatformId=true
```
The returned JSON will have a `commentId` for each comment, which you can use to delete the comment. Remember to set the `searchPlatformId` to `true`.
```json {5} theme={"system"}
{
"instagram": [
{
"comment": "What an amazing comment",
"commentId": "17969247335804735",
"created": "2024-11-26T11:49:00Z",
"from": {
"id": "103038435208332",
"username": "john_smith"
},
"hidden": false,
"likeCount": 3,
"platform": "instagram",
"postId": "18231730279304333",
"username": "john_smith"
}
]
}
```
## Header Parameters
## Path Parameters
Delete a comments sent from Ayrshare:
Delete all comments sent via Ayrshare by providing the [Ayrshare Post ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id).
Delete a single comment by providing the [Ayrshare Comment ID](/docs/apis/comments/overview#comments-with-ayrshare-comment-id).
Delete a comment sent outside of Ayrshare:
Delete a single comment by providing the [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id) from the social network.
Must include the `searchPlatformId` set to `true`.
## Body Parameters
Required if deleting comments sent via Ayrshare. The platforms to delete comments from.
Supported platforms: `bluesky`, `facebook`, `instagram`, `linkedin`, `reddit`, `threads`, `tiktok`, `twitter`, `youtube`.
```json Deleting comments sent via Ayrshare theme={"system"}
DELETE /comments/:id // Ayrshare Post ID or Ayrshare Comment ID
{
"platforms": ["bluesky", "facebook", "instagram", "linkedin", "reddit", "threads", "tiktok", "twitter", "youtube"]
}
```
Required if deleting using the [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id), which is the `commentId` from the
social networks.
Supported platforms: `bluesky`, `facebook`, `instagram`, `threads`, `tiktok`, `twitter`, `youtube`. Only one platform is supported at a time.
Required if deleting using the [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id), which is the `commentId` from the
social networks, set to `true`.
```json Deleting comments with Social Comment ID theme={"system"}
DELETE /comments/:id // Social Comment ID
{
"searchPlatformId": true,
// bluesky, facebook, instagram, threads, tiktok, twitter, youtube
"platform": "facebook"
}
```
TikTok only. Set to `true`, together with `videoId`, to hide a TikTok comment from public viewers instead of deleting it. The success response returns `action: "hide"` and echoes the comment. Sending `hide=true` without `videoId` returns HTTP `400`.
Hidden comments remain visible to the video owner in TikTok Studio.
```json Hiding a TikTok comment theme={"system"}
DELETE /comments/:id // Social Comment ID
{
"searchPlatformId": true,
"platform": "tiktok",
"hide": true,
"videoId": "7303719953248109358"
}
```
Required when hiding a TikTok comment (`hide=true`). The TikTok video ID the comment belongs to.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X DELETE https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ", {
method: "DELETE",
headers: {
Authorization: `Bearer ${API_KEY}`,
},
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace CommentsDELETERequest_csharp
{
class CommentsDELETE
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.DeleteAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Success Single Comment theme={"system"}
{
"status": "success",
"bluesky": {
"action": "delete",
"status": "success",
"id": "at://did:plc:d/app.bsky.feed.post/3lez", // Bluesky Social Comment ID
"comment": "This is a comment"
},
"facebook": {
"action": "delete",
"status": "success",
"id": "938010233_939392023", // Facebook Social Comment ID
"comment": "This is a comment"
},
"instagram": {
"action": "delete",
"status": "success",
"id": "18010439663043269", // Instagram Social Comment ID
"comment": "This is a comment"
},
"linkedin": {
"action": "delete",
"status": "success",
"id": "7133271664032669696", // LinkedIn Social Comment ID
"comment": "This is a comment"
},
"threads": {
"action": "delete",
"status": "success",
"id": "18064102964006231" // Threads Social Comment ID
},
"tiktok": {
"action": "delete",
"status": "success",
"commentId": "7303719953248109358", // Deprecated December 1, 2023. Use the id field instead.
"id": "7303719953248109358", // TikTok Social Comment ID
"comment": "This is a comment"
},
"twitter": {
"action": "delete",
"status": "success",
"id": "1633128546494459904", // Twitter Social Comment ID
"comment": "This is a comment"
},
"youtube": {
"action": "delete",
"status": "success",
"id": "Ugy2m5u-LS9M29Gn3hd4AaABAg", // YouTub Social Comment ID
"comment": "This is a comment"
}
}
```
```json 200: Sucesss Multiple Comments theme={"system"}
{
"status": "success",
"linkedin": [
{
"action": "delete",
"status": "success",
"id": "7090782997972410368", // LinkedIn Social Comment ID
"comment": "This is a comment"
},
{
"action": "delete",
"status": "success",
"id": "7090783025164103680", // LinkedIn Social Comment ID
"comment": "This is a comment"
}
],
"twitter": [
{
"action": "delete",
"posts": [
{
"action": "delete",
"status": "success",
"id": "1685017310942134272", // Twitter Social Comment ID
"comment": "This is a comment"
}
]
},
{
"action": "delete",
"posts": [
{
"action": "delete",
"status": "success",
"id": "1685017338184146946", // Twitter Social Comment ID
"comment": "This is a comment"
}
]
}
],
"facebook": [
{
"action": "delete",
"status": "success",
"id": "676770944469840_644047184361660", // Facebook Social Comment ID
"comment": "This is a comment"
},
{
"action": "delete",
"status": "success",
"id": "676770944469840_983782432932944", // Facebook Social Comment ID
"comment": "This is a comment"
}
]
}
```
```json 200: Success Hide TikTok Comment theme={"system"}
{
"status": "success",
"tiktok": {
"action": "hide",
"status": "success",
"id": "7303719953248109358", // TikTok Social Comment ID
"comment": "This is a comment"
}
}
```
```json 400: Comment id not found theme={"system"}
{
"action": "comments",
"status": "error",
"code": 219,
"message": "Error getting comments. Please verify the comments are still available."
}
```
# Get Comments
Source: https://www.ayrshare.com/docs/apis/comments/get-comments
GET /comments/:id
Fetch comments on a post by Ayrshare Post ID, Social Post ID, or Comment ID, with multiplatform partial-success responses across networks.
Get comments for a post using the Ayrshare post ID, Social Post ID, Ayrshare Comment ID, or Social Comment ID with the Comment API.
Please see the [Comments Overview](/docs/apis/comments/overview) for more information on the different ID types.
If using the Ayrshare Post ID no query parameters are required.
## Additional Comment Details
Comment data is updated every 10 minutes for all platforms, with the exception of X. Due to
restrictions imposed by the X API, the comment data for X is refreshed using an exponential
backoff strategy, meaning the intervals between updates gradually increase over time.
In the Facebook response, comment replies to replies always have the same `parent.id`.
Retrieve LinkedIn replies to comments by setting the `"commentId": true` and
`"searchPlatformId": true` query parameters and providing the [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id) in the path parameter.
Facebook and Instagram return up to the most recent 1,000 comments on a post. Please contact us
regarding higher limits on the Enterprise plan.
For a TikTok post still being processed (its `id` is `"pending"`), get-comments returns a clear
"still processing" error ([`code: 288`](/docs/errors/errors-ayrshare#tiktok-comment-errors), HTTP `400`)
rather than a generic failure. Retry once the [`tikTokPublished`
webhook](/docs/apis/post/social-networks/tiktok#tiktok-processing) fires or
[/history](/docs/apis/history/overview) shows the resolved video id.
## Multiplatform Reads & Partial Success
When you request comments with the [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id), the post may span several platforms. Ayrshare fans out one request ("leg") per platform and returns a **partial success** if some legs succeed and others fail — the healthy platforms' comment data is always returned, and each failed leg is enumerated in a top-level `errors[]` array.
Some platforms succeed, some fail: the response is HTTP 200 with status: "partial". The healthy platform blocks are returned as usual, and a top-level errors\[] array lists every failed leg with its platform, status, code, message, and id.
Every platform fails: the response has status: "error" and the full errors\[] array. The HTTP status is mapped from the representative top-level error code. Code 485 maps to HTTP 404; other representative codes use their own mappings.
All platforms succeed: the response is unchanged — HTTP 200, status: "success", and no errors\[] key.
**Behavior change — inspect `errors[]`, don't branch on HTTP status.** Because a multiplatform read with a failing leg now returns HTTP `200` instead of collapsing the whole response to an error, integrators should always check for the presence of a top-level `errors[]` array to detect per-platform failures rather than relying on the HTTP status code alone.
### Expired or Unavailable Instagram / Facebook Story Comments
An Instagram or Facebook Story comments leg that is expired or unavailable — so its comments cannot be retrieved — surfaces in `errors[]` with code [`485`](/docs/errors/errors-ayrshare#expired-or-unavailable-story-errors). A representative Instagram message is *"Instagram Story expired or unavailable — comments/insights cannot be retrieved."* If another platform succeeds, its comments are still returned and the overall response is **HTTP `200`**. For an all-fail response, representative code `485` maps to HTTP `404`; other representative codes use their own mappings. Match on the `code` (`485`), not the exact message text.
#### Example: Partial Success Response
```json 200: Partial Success theme={"system"}
{
"facebook": [
{
"comment": "What a great comment",
"commentId": "806720068141593_1849585385469876",
"created": "2026-07-14T19:55:28Z",
"likeCount": 12,
"platform": "facebook"
}
],
"status": "partial",
"id": "Ut2fWU6XkqkMayHGnJZ7",
"lastUpdated": "2026-07-14T22:30:13.035Z",
"nextUpdate": "2026-07-14T22:41:13.035Z",
"errors": [
{
"platform": "instagram",
"status": "error",
"code": 485,
"message": "Instagram Story expired or unavailable — comments/insights cannot be retrieved.",
"id": "17895695668004550"
}
]
}
```
## Header Parameters
## Path Parameters
[Ayrshare Post ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id), [Social Post
ID](/docs/apis/comments/overview#comments-with-social-post-id), or [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id).
## Query Parameters
If getting comments on a post published via Ayrshare and using the [Ayrshare Post
ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id), do not include this field - it
defaults to `false`. If getting comments using the [Social Post
ID](/docs/apis/comments/overview#comments-with-social-post-id) or [Social Comment
ID](/docs/apis/comments/overview#comments-with-social-comment-id), which is the ID generated by the
social networks, set to `true`.
If getting comments using the [Social Comment ID](/docs/apis/overview#social-comment-id), which is the
comment ID generated by the social networks, set to `true`.
If getting comment using the Ayrshare Post ID or Social Post ID, do not include this field - it defaults to `false`.
If using the `commentId` query parameter, you must also set `searchPlatformId` to `true`.
Required if `searchPlatformId` or `commentId` is `true`.
When to use:
If using the [Social Post ID](/docs/apis/comments/overview#comments-with-social-post-id) and
`"searchPlatformId": true` field. Supported platforms: `bluesky`, `facebook`, `instagram`,
`linkedin`, `threads`, `tiktok`, `twitter`, `youtube`.
If using the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id) and
`"searchPlatformId": true` and `"commentId": true` fields. Supported platforms: `facebook`,
`instagram`, `linkedin`.
If using the [Ayrshare Post ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id), do not
include this field - comments will be returned from all platforms where the original post was
published.
## Comment GET Request Examples
```json With Ayrshare Post ID theme={"system"}
// Ayrshare Post ID
GET /comments/:id
```
```json With Social Post ID theme={"system"}
// Social Post ID
// Platforms: facebook, instagram, linkedin, tiktok, twitter, youtube
GET /comments/:id?searchPlatformId=true&platform=facebook
```
```json With Social Comment ID theme={"system"}
// Social Comment ID
// Platforms: facebook, instagram, linkedin
GET /comments/:id?commentId=true&searchPlatformId=true&platform=facebook
```
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ",
{
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
},
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace CommentsGETRequest_csharp
{
class CommentsGET
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/comments/Ut1fWU6XkqkMayHGnJZ";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Success {2, 19, 60, 99, 141, 156, 194, 229, 280} theme={"system"}
{
"bluesky": [
{
"comment": "Nice one this is",
"commentId": "at://did:plc:62musrcyanhro2lydyhlw7ci/app.bsky.feed.post/3lf4b4j3dqy2i",
"created": "2025-01-06T23:12:58.950Z",
"displayName": "Ayrshare",
"likeCount": 0,
"platform": "bluesky",
"profileImageUrl": "https://cdn.bsky.app/img/avatar/plain/did:plc:62musrcyanhro2lydyhlw7ci/bafkreiegtpqhpwgu6tww2ejsdil4ew3blmt6jh3wlq6zhanxo3wj2ib4du@jpeg",
"quoteCount": 0,
"replies": [],
"replyCount": 0,
"replyTo": "at://did:plc:n7atrjd22xgkmgwig6dzlhzd/app.bsky.feed.post/3lez7fwx45723",
"repostCount": 0,
"userName": "ayrshare.com"
}
],
"facebook": [
{ // The most recent 1,000 comments retrieved.
"comment": "What a great comment",
"commentId": "806720068141593_1849585385469876", // Facebook Social Comment ID
"commentCount": 1, // The number of replies to the comment
"commentUrl": "https://www.facebook.com/106148652329/posts/184958538876/", // URL to the comment
"created": "2024-02-27T19:55:28Z",
"from": { // If available. Facebook determines availability based on the user's security profile and settings.
"name": "John Smith",
"id": "5075334022535844"
},
"likeCount": 342,
"platform": "facebook",
"userLikes": false,
"replies": [ // Facebook replies to replies have the same parent id regardless of nesting.
{
"comment": "Nice Comment 2",
"commentId": "806720068141593_320599703877348",
"commentCount": 0,
"company": true,
"created": "2024-02-27T19:55:40Z",
"from": {
"name": "Sue Me",
"id": "5075334022535800"
},
"likeCount": 3,
"parent": {
"createdTime": "2024-02-27T19:55:28+0000",
"from": {
"name": "John Smith",
"id": "5075334022535844"
},
"message": "What a great comment",
"id": "806720068141593_1849585385469876"
},
"platform": "facebook",
"userLikes": false
}
]
}
],
"instagram": [
{ // The most recent 1,000 comments retrieved.
"comment": "Love this post.",
"commentId": "18030599567251077", // Instagram Social Comment ID
"created": "2022-10-13T00:52:47Z",
"from": { // If available. Instagram determines availability based on the user's security profile and settings.
"name": "WondrousTimes",
"id": "112775157855689"
},
"hidden": false, // Is the comment hidden
"likeCount": 1,
"parentId": "17999860012861", // The Instagram Social Post ID of the parent post. Only returned when using get by ID on a reply.
"platform": "instagram",
"postId": "18011025266302661", // The Instagram top level post ID (original post).
"replies": [
{
"comment": "@ayrshare Thanks",
"created": "2024-04-04T22:37:39Z",
"from": {
"id": "178414522127073334",
"username": "ayrshare"
},
"hidden": false,
"id": "18023114651100610", // Instagram Social Comment Id
"likeCount": 2,
"parentId": "18030599567251077",
"user": {
"id": "17841452212702234"
},
"username": "ayrshare"
}
],
"user": { // ID of Instagram user who created the comment.
"id": "112775157855689"
},
"userName": "ayrshare" // If available. Instagram determines availability based on the user's security profile and settings.
}
],
// Retrieve LinkedIn replies to comments by using the commentID with the Get Comments with Social Comment ID endpoint.
"linkedin": [
{
"comment": "New wonderful comment",
"commentId": "6961077099692445688", // LinkedIn Social Comment ID
"commentUrn": "urn:li:comment:(urn:li:activity:7141202289402236928,7141205176207503360)", // Social comment id from LinkedIn
"created": "2022-08-04T21:55:11Z",
"from": {
"name": "Sue Smith",
"id": "yb8P0Oq5l8",
"url": "https://www.linkedin.com/in/suesmith",
"description": "Co-Founder at Smiths"
},
"likeCount": 34,
"media": [
{
"type": "image",
"url": "https://media-exp1.licdn.com/dms/image/D4E2CAQH4RRMRaJSR"
}
],
"platform": "linkedin",
"profileImageUrl": "https://media-exp1.licdn.com/dms/image/C5103AQHORT70jVfK",
"userName": "suesmith"
},
{ // Comment from a company
"comment": "Love it",
"commentId": "urn:li:comment:(urn:li:activity:71860989603258818,7186100659052515329)",
"commentUrn": "urn:li:comment:(urn:li:activity:71860989603258818,7186100659052515329)",
"created": "2024-04-16T20:38:28Z",
"founded": 2020,
"from": {
"name": "Ayrshare",
"id": 22327643,
"url": "https://www.linkedin.com/company/22327643",
"description": "Social Media API"
},
"likeCount": 123,
"organizationType": "PRIVATELY_HELD",
"platform": "linkedin",
"userName": "ayrshare",
"website": "https://www.ayrshare.com"
}
],
"reddit": [
{
"comment": "Nice comment",
"commentId": "kaxeilk",
"created": "2023-11-27T03:09:06.000Z",
"from": {
"name": "suppercomment",
"id": "t2_3zaxa"
},
"commentUrl": "/r/test/comments/184szm7/reddit_post_title/kaxeilk/",
"subreddit": "test",
"ups": 1,
"isSubmitter": true
}
],
"threads": [
{
"comment": "An amazing comment!",
"commentId": "17890924860234841",
"commentUrl": "https://www.threads.com/@ayrshare/post/DI4pRHAto1",
"created": "2025-04-25T21:43:57+0000",
"hasReplies": false,
"isQuotePost": false,
"isReply": true,
"isReplyOwnedByMe": true,
"mediaType": "text_post",
"parentId": "17890643139123706",
"platform": "threads",
"postId": "17890643139123706",
"replies": [
{
"comment": "sweet",
"commentId": "17961516995911683",
"commentUrl": "https://www.threads.com/@ayrshare/post/DI4shgspzI1",
"created": "2025-04-25T22:12:22+0000",
"hasReplies": false,
"isQuotePost": false,
"isReply": true,
"isReplyOwnedByMe": true,
"mediaType": "text_post",
"parentId": "17890924860234841",
"platform": "threads",
"postId": "17890643139123706",
"replyAudience": "everyone",
"shortcode": "DI4shgspzI1",
"userName": "ayrshare"
}
],
"replyAudience": "everyone",
"shortcode": "DI4pRHAtoVu",
"userName": "ayrshare"
}
],
"tiktok": [
{
"comment": "The best comment",
"commentId": "7260964914699764523", // TikTok Social Comment ID
"created": "2023-07-28T20:12:23Z",
"displayName": "John Smith",
"liked": false, // Whether the user who posted the video has liked the comment.
"likeCount": 24,
"owner": true, // Whether the user who posted the video made the comment.
"pinned": false, // If the comment is pinned
"platform": "tiktok",
"profileImageUrl": "https://p16-sign-va.tiktokcdn.com/tos-maliva-avt-0068/f123c4b57",
"replies": [
{
"comment": "One reply",
"commentId": "72776074297628920", // TikTok Social Comment ID
"createTime": "2023-09-11 16:34:20",
"liked": false, // Whether the user who posted the video has liked the comment reply.
"likes": 0,
"owner": false, // Whether the user who posted the video made the comment reply.
"parentCommentId": "72776073973290774", // TikTok Parent Social Comment ID
"profileImageUrl": "https://p16-sign.tiktokcdn-us.com/tos-useast5-avt-0068-tx/bcc6e6778x168.jpeg",
"status": "PUBLIC",
"userId": "51e0cb95a8b14f0f1020aa017",
"username": "ayrshare",
"videoId": "7260964048362310958" // TikTok Social Post ID
}
],
"status": "success",
"userId": "fc904564301a6d383fd19bd4982ba2682404876533c04741a8c3f270376cd3dd",
"username": "helmar1066",
"videoId": "7260964048362310958", // TikTok Social Post ID
"visibility": "public"
}
],
"twitter": [
{
"bookmarkCount": 2,
"comment": "@ayrshare Congrats on this",
"commentId": "1505595871831891068", // Twitter Social Comment ID
"created": "2022-05-14T21:56:14.000Z",
"description": "Eat great!",
"id": "1552209331030036480", // Twitter Social Post ID
"impressionCount": 134,
"likeCount": 341,
"name": "waffles",
"platform": "twitter",
"profileImageUrl": "https://pbs.twimg.com/profile_images/119426890464/lvQZPpt4_normal.png",
"publicMetrics": { // X public metrics of the user who posted the comment
"followersCount": 56,
"followingCount": 2242,
"tweetCount": 32,
"listedCount": 3,
"likeCount": 459,
"mediaCount": 244
},
"quoteCount": 2,
"referencedTweets": [ // ID of the tweet that was replied to
{
"type": "replied_to",
"id": "187203972440121733"
}
],
"replyCount": 3,
"replyTo": { // Who the comment was in reply to
"createdAt": "2012-01-18T21:13:15.000Z",
"description": "Social Media API",
"id": "467793290",
"location": "New York City",
"name": "Ayrshare",
"profileImageUrl": "https://pbs.twimg.com/profile_images/1851502252/ayrshare_normal.gif",
"publicMetrics": { // X public metrics of the user who the comment was in reply to
"followersCount": 46,
"followingCount": 1242,
"tweetCount": 12,
"listedCount": 2,
"likeCount": 439,
"mediaCount": 144
},
"url": "https://t.co/GQgCqytA",
"username": "anotherone"
},
"threadNumber": 1, // If thread, number in sequence
"userName": "waffles"
}
],
"youtube": [
{
"channelUrl": "http://www.youtube.com/channel/sp0CnxiNbUU0AJtuYKZwXQ",
"comment": "Two comments",
"commentId": "Ugx0tiPuoUpXfrY0qvV4AaABAg", // YouTube Social Comment ID
"created": "2022-05-24T19:45:49Z",
"isPublic": true, // This setting indicates whether the comment, including all of its comments and comment replies, is visible to all YouTube users.
"likeCount": 34,
"platform": "youtube",
"profileImageUrl": "https://yt3.ggpht.com/ytc/AKedOLT2hOZirBUGodAg31-QXaGPd9DmrkxR48UXAw=s48-c-k-c0x00ffffff-no-rj",
"replies": [
{
"comment": "amazing reply",
"commentId": "UgzJFjmrrRUr6nsRWi14AaABAg.9ssbUo6Es1n9ssbVwRn2iz",
"created": "2023-08-01T15:59:16Z",
"likeCount": 2,
"platform": "youtube",
"userName": "uman",
"profileImageUrl": "https://yt3.ggpht.com/ytc/AOPcoUDV_W7h3ZSEcFYrcEuXUPxVCTuF4NTw=s48-c-k-c0x00ffffff-no-rj",
"channelUrl": "http://www.youtube.com/channel/sp0CnxiNbUU0AJtuYKZwXQ",
"parentId": "UgzJFjmrrRUr6nsRWi14AaABAg"
}
],
"userName": "ayrshare"
},
{
"channelUrl": "http://www.youtube.com/channel/sp0CnxiNbUU0AJtuYKZwXQ",
"comment": "One comment",
"commentId": "Ugx0tiPuoUpXfrY0qvV4AaABAa", // YouTube Social Comment ID
"created": "2022-05-24T19:00:10Z",
"isPublic": true, // This setting indicates whether the comment, including all of its comments and comment replies, is visible to all YouTube users.
"likeCount": 123,
"platform": "youtube",
"profileImageUrl": "https://yt3.ggpht.com/ytc/AAKedOLT2hOZirBUGodAg31-QXaGPd9DmrkxR48UXAw=s48-c-k-c0x00ffffff-no-rj",
"userName": "ayrshare"
}
],
"status": "success",
"id": "Ut2fWU6XkqkMayHGnJZ7",
"lastUpdated": "2023-03-26T22:30:13.035Z",
"nextUpdate": "2023-03-26T22:41:13.035Z",
}
```
```javascript 404: Comments Not Found theme={"system"}
{
"action": "post",
"status": "error",
"code": 186,
"message": "Post ID not found. Please verify the top level ID returned from the /post endpoint is being sent.",
"id": "Ut2fWU6XkqkMayHGnJZ7"
}
```
# Comments API Overview
Source: https://www.ayrshare.com/docs/apis/comments/overview
Post, reply, get, and delete comments on a social post
The Comments endpoints allow your users to post, reply, retrieve, and delete comments on their posts.
There are four types of comments IDs: Ayrshare Post ID, Social Post ID, Ayrshare Comment ID, and Social Comment ID.
Each of these IDs are used for different purposes.
## Comment ID Types
### Comments with Ayrshare Post ID
The typical flow is when you publish a post via Ayrshare, you get the Ayrshare Post ID.
You can then use this [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id) to manage comments on that post.
Supported platforms: Bluesky, Facebook Pages, Instagram, LinkedIn, Reddit, Threads, TikTok, Twitter, and YouTube.
For example:
Use the [/post](/docs/apis/post/post) endpoint to publish a post via Ayrshare, which can be sent to multiple social networks in a single call.
In the return is the top level [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id).
```json {12} theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "106638148652329_591370753547555",
"postUrl": "https://www.facebook.com/106638148652329/posts/591370753547555",
"platform": "facebook"
}
],
"id": "E4UdUr1yRbvI7qqCSlaq", // Ayrshare Post ID
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc055",
"post": "What an amazing day",
"validate": true
}
```
Use the [/comments](/docs/apis/comments/post-comment) endpoint to post a comment with the Ayrshare Post ID.
The comment will be automatically posted to every social network where the original post was published.
For example, if you published the post to Facebook and Instagram, the comment will appear on both platforms.
```http theme={"system"}
POST https://api.ayrshare.com/api/comments/:id
```
Use the [/comments](/docs/apis/comments/get-comments) endpoint to get the comments for the post with the Ayrshare Post ID.
This will return all comments from every social network where the post was published.
For example, if you posted to Facebook and Instagram, you'll get comments from both platforms.
```http theme={"system"}
GET https://api.ayrshare.com/api/comments/:id
```
### Comments with Social Post ID
Sometimes you may want to manage comments on a post that were not published via Ayrshare.
In this case you can use the [Social Post ID](/docs/apis/overview#social-post-id), which is the post ID assigned by the social network.
If the post was published via Ayrshare, use [the Ayrshare Post
ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id).
For example:
Start by getting the Instagram posts published outside of Ayrshare with the [Get All Post History endpoint](/docs/apis/history/history-platform).
The endpoint returns a list of posts with the social `id` of the post.
```json {13} theme={"system"}
{
"status": "success",
"posts": [
{
"mediaUrl": "https://scontent.cdninstagram.com/v/t51.2885-15/7531.jpg",
"permalink": "https://www.instagram.com/p/B5OBT3ygpfg/",
"commentsCount": 0,
"created": "2022-05-20T17:26:03Z",
"likeCount": 0,
"mediaProductType": "FEED",
"mediaType": "IMAGE",
"username": "thegoodone",
"id": "17833140557332933", // Instagram Social Post ID
"thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51..jpg",
"post": "The #Mandalorian is on tonight instead of Friday",
"postUrl": "https://www.instagram.com/p/B5OBT3ygpfg/"
},
]
}
```
The social post `id` is also returned in the `postIds` field of the [post endpoint](/docs/apis/post/post).
Use the returned `id` to [get all the comments](/docs/apis/comments/get-comments) for a specific Instagram post using the social `id`, `searchPlatformId` set to `true`, and `platform` set to `instagram`.
```http theme={"system"}
GET https://api.ayrshare.com/api/comments/17833140557332933?platform=instagram&searchPlatformId=true
```
The returned JSON from the previous step will have a `commentId` for each comment, which is the [social comment ID](/docs/apis/overview#social-comment-id).
```json {5} theme={"system"}
{
"instagram": [
{
"comment": "What an amazing comment",
"commentId": "17969247335804735", // Social Comment ID
"created": "2024-11-26T11:49:00Z",
"from": {
"id": "103038435208332",
"username": "john_smith"
},
"hidden": false,
"likeCount": 3,
"platform": "instagram",
"postId": "18231730279304333",
"username": "john_smith"
}
]
}
```
### Comments with Ayrshare Comment ID
Manage comments on a post that were published via Ayrshare by using the [Ayrshare Comment ID](/docs/apis/overview#ayrshare-comment-id).
The Ayrshare comment ID is the comment ID assigned from Ayrshare and can be found in the `commentId` field in the response when [posting a comment](/docs/apis/comments/post-comment).
This is often used if you want to get details on a particular comment published via Ayrshare.
### Comments with Social Comment ID
Manage comments on a post that were not published via Ayrshare by using the [Social Comment ID](/docs/apis/overview#social-comment-id).
The social comment ID is the comment ID from the social network, not the Ayrshare ID, and can be found in the `commentId` field in the response when [getting comments](/docs/apis/comments/get-comments).
```http theme={"system"}
GET https://api.ayrshare.com/api/comments/17969247335804735?platform=instagram&searchPlatformId=true&commentId=true
```
This is often used if you want to get details on a particular comment published outside of Ayrshare, such as LinkedIn replies to comments.
## Disable Comments
You can disable comments when publishing a post using the `disableComments` field in the [/post endpoint](/docs/apis/post/post). Comments will only be disabled for Instagram, LinkedIn, and TikTok.
You may also enable or disable comments on an already published post using the [update post](/docs/apis/post/update-post) endpoint and the `disableComments` field.
## Platform Limitations
**TikTok — `DELETE /comments` is own-authored only.** [`DELETE /comments`](/docs/apis/comments/delete-comments) on TikTok only succeeds for comments authored by the authenticated TikTok account itself (your own replies). Attempting to delete a comment authored by another user returns Ayrshare `code: 328`. For moderation of third-party comments on your own TikTok videos, contact support so we can confirm what's available for your linked account type.
```
```
# Post a Comment
Source: https://www.ayrshare.com/docs/apis/comments/post-comment
POST /comments
Add a comment to a published post
Add a comment to a post with an Ayrshare Post ID (posts sent via Ayrshare) or a Social Post ID (posts sent outside of Ayrshare) using the Comments API.
Comments added to an X Thread will be posted to the first Tweet.
Instagram Story comments are not yet supported by Meta.
See the `platforms` field below for supported platforms depending on the ID type.
Please see the [Comments Overview](/docs/apis/comments/overview) for more information on the different ID types.
Supported platforms: Bluesky, Facebook, Instagram, LinkedIn, Reddit, TikTok, X, and YouTube.
## Header Parameters
## Body Parameters
Ayrshare Post ID or Social Post ID from the [/post endpoint](/docs/apis/post/post).
Text of the new comment to add to the post.
Set to `true` if posting a comment using the [Social Post ID](/docs/apis/comments/overview#comments-with-social-post-id), which is the post `id` from the social networks.
Specify the platforms to add comments.
If using an [Ayrshare Post ID](/docs/apis/comments/overview#comments-with-ayrshare-post-id) the supported platforms are: `bluesky`, `facebook`, `instagram`, `linkedin`, `reddit`, `tiktok`, `twitter`, `youtube`.
If no platforms are specified, the comment will be published to all connected platforms that support comments.
```json Post a Comment with the Ayrshare Post ID theme={"system"}
{
"id": "Ut1fWU6XkqkMayHGnJZ", // Ayrshare Post ID
"comment": "An amazing comment!", // required
"platforms": [
"bluesky",
"facebook",
"instagram",
"linkedin",
"reddit",
"tiktok",
"twitter",
"youtube"
]
}
```
If using a [Social Post ID](/docs/apis/comments/overview#comments-with-social-post-id) the supported platforms are -only one platform allowed at a time : `facebook`, `instagram`, `linkedin`, `tiktok`, `twitter`.
```json Post a Comment with the Social Post ID theme={"system"}
{
"id": "1288899996423983105", // Social Post ID
"comment": "An amazing comment!", // required
"searchPlatformId": true, // required
// facebook, instagram, linkedin, tiktok, twitter
"platforms": ["facebook"] // Only specify one platform
}
```
Attach an image by providing the image URL for Facebook or X/Twitter.
Only one image is supported in the `mediaUrls` field. Supported platforms are Facebook, LinkedIn, and X/Twitter.
```json Post a Comment with an Image theme={"system"}
{
"id": "Ut1fWU6XkqkMayHGnJZ", // Ayrshare Post ID
"comment": "An amazing comment!", // required
"platforms": ["facebook"], // Facebook, LinkedIn, or X/Twitter only
"mediaUrls": ["https://img.ayrshare.com/gb.jpg"]
}
```
## @Mentions in Comments
You can include @mentions directly in the `comment` text string. There is no separate parameter for mentions. Simply add `@handle` in your comment text.
```json Comment with @Mention theme={"system"}
{
"id": "Ut1fWU6XkqkMayHGnJZ",
"comment": "Great post @CompanyName! Love this.",
"platforms": ["linkedin", "twitter", "facebook"]
}
```
**LinkedIn Mentions:** LinkedIn mentions are resolved server-side by Ayrshare. Use the [LinkedIn Search endpoint](/docs/apis/listen/search/linkedin-search) to look up the correct vanity name or member name. For organizations, use `@handle`. For members, use `@vanity_name` or `@[Full Name]`.
For detailed mention syntax and limitations per platform, see:
* [Bluesky mentions](/docs/apis/post/social-networks/bluesky#bluesky-mentions)
* [Facebook mentions](/docs/apis/post/social-networks/facebook#facebook-page-mentions)
* [Instagram mentions](/docs/apis/post/social-networks/instagram#instagram-mentions)
* [LinkedIn mentions](/docs/apis/post/social-networks/linkedin#linkedin-mentions)
* [Reddit mentions](/docs/apis/post/social-networks/reddit#reddit-mentions)
* [Threads mentions](/docs/apis/post/social-networks/threads#threads-mentions)
* [TikTok mentions](/docs/apis/post/social-networks/tiktok#tiktok-mentions)
* [X/Twitter mentions](/docs/apis/post/social-networks/x-twitter#mentions)
* [YouTube mentions](/docs/apis/post/social-networks/youtube#youtube-mentions)
See [Post Verification](/docs/testing/post-verification) for the platform-by-platform mention rules and recommendations.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id": "Ut1fWU6XkqkMayHGnJZ", "platforms": ["bluesky", "facebook", "instagram", "linkedin", "reddit", "tiktok", "twitter", "youtube"], "comment": "An amazing comment!"}' \
-X POST https://api.ayrshare.com/api/comments
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/comments", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({
id: "Ut1fWU6XkqkMayHGnJZ", // required
platforms: ["bluesky", "facebook", "instagram", "linkedin", "reddit", "tiktok", "twitter", "youtube"], // required
comment: "An amazing comment!", //required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': 'Ut1fWU6XkqkMayHGnJZ',
'platforms': ['bluesky', 'facebook', 'instagram', 'linkedin', 'reddit', 'tiktok', 'twitter', 'youtube'],
'comment': 'An amazing comment!'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/comments',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
'Ut1fWU6XkqkMayHGnJZ', // Replace with your actual post ID
'platforms' => ['bluesky', 'facebook', 'instagram', 'linkedin', 'reddit', 'tiktok', 'twitter', 'youtube'],
'comment' => 'An amazing comment!'
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"id": "Ut1fWU6XkqkMayHGnJZ", // required
"platforms": []string{"bluesky", "facebook", "instagram", "linkedin", "reddit", "tiktok", "twitter", "youtube"}, // required
"comment": []string{"An amazing comment!"} // required
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/comments",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CommentsPOSTRequest_csharp
{
class CommentsPOST
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/comments";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"id\": \"Ut1fWU6XkqkMayHGnJZ\"," +
"\"platforms\": [\"bluesky\", \"facebook\", \"instagram\", \"linkedin\", \"reddit\", \"tiktok\", \"twitter\", \"youtube\"]," +
"\"comment\": [\"An amazing comment!\"]}";
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"commentID": "IUDSCfdYfFkw_dWhW9PLI", // Ayrshare Comment ID. Used for replying to a comment.
"id": "Ut1fWU6XkqlMayHGnJZ", // Ayrshare Post ID
"bluesky": {
"status": "success",
"commentId": "at://did:plc:62musrcyanhro2lydyhlw7ci/app.bsky.feed.post/3lf4b4j3dqy2i",
"cid": "bafyreiaoivcafelkpzhbbjco23pguyqmy7wucuvfxaifgj34qoyp7nrhhy",
"comment": "Nice one this is",
"platform": "bluesky",
"postUrl": "https://bsky.app/profile/ayrshare.com/post/3lf4b4j3dqy2i"
},
"facebook": {
"status": "success",
"commentId": "358482752285927_363474831785719", // Facebook Social Comment ID
"comment": "The best comment ever!",
"platform": "facebook"
},
"instagram": {
"status": "success",
"commentId": "17060111860440276", // Instagram Social Comment ID
"comment": "The best comment ever!",
"platform": "instagram"
},
"linkedin": {
"status": "success",
"commentId": "urn:li:comment:(urn:li:activity:7141202289402236928,7141205176207503360)", // LinkedIn Social Comment ID
"comment": "Someone's sitting in the shade today because someone planted a tree a long time ago. - Warren Buffett",
"commentUrn": "urn:li:comment:(urn:li:activity:7141202289402236928,7141205176207503360)", // Social comment Id from LinkedIn
"platform": "linkedin"
},
"tiktok": {
"status": "success",
"commentId": "7260964914699764524", // TikTok Social Comment ID
"comment": "The best comment ever!",
"platform": "tiktok",
"videoId": "7260964048362310959"
},
"twitter": {
"status": "success",
"commentId": "1525632403262101648", // Twitter Social Comment ID
"comment": "The best comment ever!",
"postUrl": "https://twitter.com/ayrshare/status/1525632403262101648"
},
"youtube": {
"status": "success",
"commentId": "UgzIEZsDQKXgHsEnwTR4AaABAa", // YouTube Social Comment ID
"comment": "The best comment ever!",
"platform": "youtube"
},
}
```
```json 404: Not Linked & Success theme={"system"}
{
"commentId": "5GizKtM9TFRFFWNDgBZ",
"twitter": {
"status": "success",
"commentId": "1842266484032016",
"comment": "Having a meeting on this",
"platform": "twitter",
"postUrl": "https://twitter.com/ayrshare/status/18422664840320"
},
"action": "post",
"status": "error",
"code": 156,
"message": "Instagram is not linked. Please confirm the linkage on the Social Accounts page in the dashboard.",
"platform": "instagram",
"id": "1w3QI6bU7KE9XyxrN0u", // Ayrshare Post ID
"errors": [
{
"action": "post",
"status": "error",
"code": 156,
"message": "Facebook is not linked. Please confirm the linkage on the Social Accounts page in the dashboard.",
"platform": "facebook"
},
{
"action": "post",
"status": "error",
"code": 156,
"message": "Instagram is not linked. Please confirm the linkage on the Social Accounts page in the dashboard.",
"platform": "instagram"
}
]
}
```
```json 400: Duplicate comment theme={"system"}
{
"twitter": {
"action": "post",
"status": "error",
"code": 134,
"message": "The social network detected duplicate content and blocked this post. Please change the content and try again.",
"post": "Having a meeting on this",
"detail": "You are not allowed to create a Tweet with duplicate content."
},
"code": 134,
"status": "error",
"id": "1w3QI6bU7KE9XyxrN", // Ayrshare Post ID
"errors": [
{
"action": "post",
"status": "error",
"code": 134,
"message": "The social network detected duplicate content and blocked this post. Please change the content and try again.",
"post": "Having a meeting on this",
"detail": "You are not allowed to create a Tweet with duplicate content.",
"id": "1w3QI6bU7KE9XyxrN",
"platform": "twitter"
}
]
}
```
# Reply to a Comment
Source: https://www.ayrshare.com/docs/apis/comments/reply-to-comment
POST /comments/reply/:commentId
Comment on a comment
Reply to a comment, i.e. comment on a comment, on either an Ayrshare made comment, using the [Ayrshare Comment ID](/docs/apis/comments/overview#comments-with-ayrshare-comment-id), or a comment made outside of Ayrshare, using the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id).
Most often, you will reply to a comment made through Ayrshare, but when you want to reply to a comment made outside of Ayrshare, you can use the Social Comment ID, which you get [GET /comment](/docs/apis/comments/get-comments) endpoint.
Supported platforms: Bluesky, Facebook, Instagram, LinkedIn, TikTok, X, and YouTube.
## Header Parameters
## Path Parameters
If replying to a comment made through Ayrshare, use the [Ayrshare Comment ID](/docs/apis/comments/overview#comments-with-ayrshare-comment-id) `commentId` returned from the [POST comment endpoint](/docs/apis/comments/post-comment).
For example, the Ayrshare comment ID `commentId` returned from the [POST comment endpoint](/docs/apis/comments/post-comment) is:
```json Ayrshare Comment ID Returned from POST /comment theme={"system"}
{
"commentId": "Ut1fWU6XkqkMayHGnJZ"
}
```
If replying to a comment made outside of Ayrshare, use the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id) `commentId` from the social network.
For example, the social comment ID `commentId` returned from a Facebook [POST /comment](/docs/apis/comments/post-comment) or [GET /comment](/docs/apis/comments/get-comments) endpoint is:
```json Social Comment ID Returned from POST /comment theme={"system"}
{
"facebook": { "commentId": "8392829334_1234567890" }
}
```
## Body Parameters
If replying to a comment made through Ayrshare using the [Ayrshare Comment ID](/docs/apis/comments/overview#comments-with-ayrshare-comment-id), specify the platforms to post the reply. Supported platforms: `bluesky`, `facebook`, `instagram`, `linkedin`, `tiktok`, `twitter`, `youtube`.
If replying to a comment made outside of Ayrshare using the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id), specify the one platform to post the reply. Supported platforms: `facebook`, `instagram`, `linkedin`, `tiktok`, `twitter`.
The reply to add to the comment.
Attach an image by providing the image URL. Only one image is supported. Facebook and LinkedIn only.
Set to `true` if replying to a comment using the [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id), which is the post `commentId` from the social networks.
If replying to a LinkedIn comment with a Social Comment ID, you must also provide the full LinkedIn comment URN, which you get from the [POST /comment endpoint](/docs/apis/comments/post-comment) or [GET /comment endpoint](/docs/apis/comments/get-comments) as `commentUrn` — not the bare `commentId`. The URN has the form `urn:li:comment:(urn:li:activity:,)`.
Only required for LinkedIn and `"searchPlatformId": true`.
If replying to a TikTok comment with a Social Comment ID, you must also provide the TikTok video ID, which you get from the [POST /comment endpoint](/docs/apis/comments/post-comment) or [GET /comment endpoint](/docs/apis/comments/get-comments).
Only required for TikTok and `"searchPlatformId": true`.
Response as Object, otherwise as an Array. Default to `true`.
## @Mentions in Comments
You can include @mentions directly in the `comment` text string. There is no separate parameter for mentions. Simply add `@handle` in your comment text.
```json Reply with @Mention theme={"system"}
{
"comment": "Thanks @CompanyName! Great insight.",
"platforms": ["linkedin", "twitter", "facebook"]
}
```
**LinkedIn Mentions:** LinkedIn mentions are resolved server-side by Ayrshare. Use the [LinkedIn Search endpoint](/docs/apis/listen/search/linkedin-search) to look up the correct vanity name or member name. For organizations, use `@handle`. For members, use `@vanity_name` or `@[Full Name]`.
For detailed mention syntax and limitations per platform, see:
* [Bluesky mentions](/docs/apis/post/social-networks/bluesky#bluesky-mentions)
* [Facebook mentions](/docs/apis/post/social-networks/facebook#facebook-page-mentions)
* [Instagram mentions](/docs/apis/post/social-networks/instagram#instagram-mentions)
* [LinkedIn mentions](/docs/apis/post/social-networks/linkedin#linkedin-mentions)
* [Threads mentions](/docs/apis/post/social-networks/threads#threads-mentions)
* [TikTok mentions](/docs/apis/post/social-networks/tiktok#tiktok-mentions)
* [X/Twitter mentions](/docs/apis/post/social-networks/x-twitter#mentions)
* [YouTube mentions](/docs/apis/post/social-networks/youtube#youtube-mentions)
Reply to comment is not supported on Reddit. See [Post Verification](/docs/testing/post-verification) for the platform-by-platform mention rules and recommendations.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"platforms": ["bluesky", "facebook", "instagram", "linkedin", "twitter", "youtube"], "comment": "An amazing reply!"}' \
-X POST https://api.ayrshare.com/api/comments/reply/Ut1fWU6XkqkMayHGnJZ
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/comments/reply/Ut1fWU6XkqkMayHGnJZ", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({
platforms: ["bluesky", "facebook", "instagram", "linkedin", "twitter", "youtube"], // required
comment: "An amazing comment!", //required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'platforms': ['bluesky', 'facebook', 'instagram', 'linkedin', 'twitter', 'youtube'],
'comment': 'An amazing comment!'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/comments/reply/Ut1fWU6XkqkMayHGnJZ',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
['bluesky', 'facebook', 'instagram', 'linkedin', 'twitter', 'youtube'],
'comment' => 'An amazing comment!'
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"platforms": []string{"bluesky", "facebook", "instagram", "linkedin", "twitter", "youtube"}, // required
"comment": []string{"An amazing comment!"} // required
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/comments/reply/Ut1fWU6XkqkMayHGnJZ",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CommentsReplyPOSTRequest_csharp
{
class CommentsReply
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/comments/reply/Ut1fWU6XkqkMayHGnJZ";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
var json = @"{
""platforms"": [""bluesky"", ""facebook"", ""instagram"", ""linkedin"", ""twitter"", ""youtube""],
""comment"": [""An amazing comment!""]
}";
var content = new StringContent(
json,
Encoding.UTF8,
"application/json"
);
try
{
var response = await httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"commentId": "Eh61xHheGHvAqXqGISGVa",
"bluesky": {
"status": "success",
"commentId": "at://did:plc:62musrcyanhro2lydyhlw7ci/app.bsky.feed.post/3lf4bquqrxd2d",
"cid": "bafyreie2jt5iw6rk2ekmiq6aljyiv7nj4sjucbpkamqc73tmggh5fmrqha",
"comment": "Truth is ever to be found in simplicity.",
"platform": "bluesky",
"postUrl": "https://bsky.app/profile/ayrshare.com/post/3lf4bquqrxd2d",
"sourceCommentId": "at://did:plc:62musrcyanhro2lydyhlw7ci/app.bsky.feed.post/3lf4b4j3dqy2i"
},
"facebook": {
"status": "success",
"commentId": "729149842469573_696560159169326",
"sourceCommentId": "729149842469573_738966840899770",
"comment": "Truth is ever to be found in simplicity.",
"platform": "facebook"
},
"instagram": {
"status": "success",
"commentId": "18020060386920755",
"sourceCommentId": "17998452434360734",
"comment": "Truth is ever to be found in simplicity.",
"platform": "instagram"
},
"linkedin": {
"status": "success",
"commentId": "7140161360574713856",
"sourceCommentId": "urn:li:ugcPost:7140160850354397187",
"comment": "Truth is ever to be found in simplicity.",
"platform": "linkedin"
},
"tiktok": {
"status": "success",
"commentId": "7484295933044572922",
"sourceCommentId": "7484407021429703422",
"comment": "Truth is ever to be found in simplicity.",
"platform": "tiktok",
"videoId": "7484993689815715122"
},
"twitter": {
"status": "success",
"commentId": "1734395672961441821",
"sourceCommentId": "1734395509526155733",
"comment": "Truth is ever to be found in simplicity.",
"platform": "twitter",
"postUrl": "https://twitter.com/ayrshare/status/1734395672961441821"
},
"youtube": {
"status": "success",
"commentId": "UgxZ55j-FDri8lrTgVR4AaABAg.9yCaV71m1fo9yCaZvu7Hj4",
"sourceCommentId": "UgxZ55j-FDri8lrTgVR4AaABAg",
"comment": "Truth is ever to be found in simplicity.",
"platform": "youtube"
},
"status": "success",
"id": "ytDgi5vyz36F2yshlJka"
}
```
```json 400: Unknown commentId theme={"system"}
{
"facebook": {
"action": "post",
"status": "error",
"code": 215,
"message": "Error posting comment. Please be sure you are posting a valid comment, the original post exists, the original post is publicly available."
},
"code": 215,
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 215,
"message": "Error posting comment. Please be sure you are posting a valid comment, the original post exists, the original post is publicly available.",
"platform": "facebook"
}
],
"id": "5360106757501_178916202161"
}
```
# Add RSS Feed
Source: https://www.ayrshare.com/docs/apis/feeds/add-feed
POST /feed
Add a new RSS feed for automated posting of new articles
Add a new RSS feed for automated posting of new articles. Posts will be automatically sent to your linked social accounts: Bluesky, Facebook, LinkedIn, Telegram, and Threads. Also Instagram and Pinterest if a valid image can be found in the article, and Snapchat if `useFirstImage` is `true` and an image is found — Snapchat cannot publish without media.
Reddit, TikTok, YouTube, and Google Business Profile are not available for feeds — each needs a detail a feed entry can't supply, such as a subreddit, a video file, or a location. See [why only these networks](/docs/dashboard/automated-rss-feeds#why-only-these-networks).
**X/Twitter is no longer supported for RSS feeds.** As of March 31, 2026, X requires your own API credentials for each request, which is incompatible with automated RSS posting. Passing `twitter` in `platforms` is ignored; if it is the only platform given, the request returns error `101`. Use [scheduled posts](/docs/apis/post/overview#schedule-posts) or direct API calls with your [BYO credentials](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) instead.
## Header Parameters
## Body Parameters
URL of the RSS feed to add.
Attempt to get the first or top image in the article and add it to the post.
Automatically add up to 3 hashtags to the post text based on the most relevant keywords.
Value: `rss`, `substack`, or `youtube`.
Social network platforms to publish the article. If not provided, defaults to all connected platforms that are available for feeds. Available platforms:
```json theme={"system"}
{
"platforms": ["bluesky", "facebook",
"instagram", "linkedin", "pinterest",
"snapchat", "telegram", "threads"]
}
```
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url": "https://www.nytimes.com"}' \
-X POST https://api.ayrshare.com/api/feed
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const url = "https:///www.nytimes.com";
fetch("https://api.ayrshare.com/api/feed", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({ url })
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'url': 'https://www.nytimes.com'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/feed',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
$data = array (
'url' => 'https://www.nytimes.com'
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/feed',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "4HZhptaD5",
"title": "Pulte's Money and Life Thoughts",
"websiteLink": "https://pulte.substack.com",
"rssURL": "https://pulte.substack.com/feed"
}
```
```json 400: Feed Already Exists theme={"system"}
{
"action": "create",
"status": "error",
"code": 303,
"message": "The feed https://ruthreichl.substack.com/feed already exists.",
"id": "TDW3oMDoI"
}
```
```json 400: Invalid URL theme={"system"}
{
"action": "create",
"status": "error",
"code": 130,
"message": "Something is wrong with the RSS feed URL. Please verify it."
}
```
# Delete RSS Feed
Source: https://www.ayrshare.com/docs/apis/feeds/delete-feed
DELETE /feed
Delete an RSS Feed that was previously added
## Header Parameters
## Body Parameters
ID of the RSS Feed returned when adding.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id": "4HZhptaD5"}' \
-X DELETE https://api.ayrshare.com/api/feed
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "4HZhptaD5";
fetch("https://api.ayrshare.com/api/feed", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({ id }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': '4HZhptaD5'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/feed',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
$data = array (
'id' => '_3yhtyd88'
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/feed',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "RDFbD_fl5"
}
```
```json 400: Can't Find RSS ID theme={"system"}
{
"action": "delete",
"status": "error",
"code": 131,
"message": "Something is wrong deleting the RSS feed URL. Please try again and verify the id."
}
```
# Get RSS Feeds
Source: https://www.ayrshare.com/docs/apis/feeds/get-feeds
GET /feed
Get all registered RSS feeds
## Header Parameters
```json 200: Success theme={"system"}
{
"status": "success",
"feeds": [
{
"autoHashtag": false,
"created": "2022-05-16T23:20:03.405Z",
"description": "Social Media APIs that enable you to send social media posts effortlessly",
"id": "_3yhtyd88",
"image": {
"height": "32",
"link": "https://www.ayrshare.com",
"title": "Ayrshare",
"width": "32",
"url": "https://www.ayrshare.com/wp-content/uploads/2020/07/cropped-ayr-icon-2FKLDFB-32x32.png"
},
"link": "https://www.ayrshare.com",
"title": "Ayrshare",
"type": "rss",
"updated": "2022-05-16T23:20:17.124Z",
"url": "https://www.ayrshare.com/feed/",
"useFirstImage": true
}
]
}
```
# RSS Feeds Overview
Source: https://www.ayrshare.com/docs/apis/feeds/overview
Add and delete RSS feeds for automated posting
Manage RSS feeds for automated posting. Great for auto-posting your blog articles, YouTube videos, and podcasts.
A [webhook is available to get notified](/docs/apis/webhooks/actions#feed-action) when a new RSS feed item is available.
# Update RSS Feed
Source: https://www.ayrshare.com/docs/apis/feeds/update-feed
PUT /feed
Update an RSS feed
## Header Parameters
## Body Parameters
The RSS feed id returned from the RSS feed POST endpoint.
Attempt to get the first or top image in the article and add it to the post.
Automatically add up to 3 hashtags to the post text based on the most relevant keywords.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id": "4HZhptaD5", "useFirstImage": true, "autoHashtag": true}' \
-X PUT https://api.ayrshare.com/api/feed
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "4HZhptaD5";
fetch("https://api.ayrshare.com/api/feed", {
method: "PUT",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({ id, "useFirstImage": true, "autoHashtag": true }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.err
```
```python Python theme={"system"}
import requests
payload = {'id': '4HZhptaD5', 'useFirstImage': True, 'autoHashtag': True}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.put('https://api.ayrshare.com/api/feed',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
$data = array (
'id' => '_3yhtyd88',
'useFirstImage' => false,
'autoHashtag' => true
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/feed',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "vVYX3cgJ7"
}
```
```json 400: RSS Feed not found theme={"system"}
{
"action": "update",
"status": "error",
"code": 304,
"message": "The feed with id vVYX3cgJ does not exist."
}
```
# Generate Alt Text
Source: https://www.ayrshare.com/docs/apis/generate/image-alt-text
POST /generate/altText
Create AI-generated alt text for your images
Create AI-generated alt text for your images. Choose the language to write the alt text and keywords to include in the alt text.
## Header Parameters
## Body Parameters
Image URL of the image to create the alt text. Must start with `https://`. Supports JPEG, PNG, GIF, WEBP, and BMP.
String array of keywords or phrases to be considered when generating the alt text. Typically only one or two of the keywords from the array will be used in the alt text.
Language to output the alt text. Use one of the available [language codes](/docs/iso-codes/language).
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url": "https://img.ayrshare.com/012/gb.jpg"}' \
-X POST https://api.ayrshare.com/api/generate/altText
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/generate/altText", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
url: "https://img.ayrshare.com/012/gb.jpg", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'url': 'https://img.ayrshare.com/012/gb.jpg'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/generate/altText',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$curl = curl_init();
$data = array (
"url" => "https://img.ayrshare.com/012/gb.jpg"
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/generate/altText',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY',
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
class Program
{
// Replace 'YOUR_API_KEY' with your actual Ayrshare API key
private const string API_KEY = "YOUR_API_KEY";
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string imageUrl = "https://img.ayrshare.com/012/gb.jpg";
try
{
var result = await GenerateAltTextAsync(imageUrl);
Console.WriteLine("Generated Alt Text:");
Console.WriteLine(JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }));
}
catch (Exception e)
{
Console.WriteLine($"An error occurred: {e.Message}");
}
}
static async Task GenerateAltTextAsync(string imageUrl)
{
var url = "https://api.ayrshare.com/api/generate/altText";
var requestData = new { url = imageUrl };
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {API_KEY}");
var json = JsonSerializer.Serialize(requestData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP error! status: {response.StatusCode}");
}
var responseBody = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize(responseBody);
}
}
```
```json 200: Alt Text Generated theme={"system"}
{
"status": "success",
"altText": "A ghostbusters vehicle driving through a field.",
"url": "https://img.ayrshare.com/012/gb.jpg"
}
```
```json 500: Error with the Image File theme={"system"}
{
"action": "upload",
"status": "error",
"code": 115,
"message": "An error occurred uploading your file, such as a timeout at the social network. Please try your post again with the /retryPost endpoint."
}
```
# Generate API Overview
Source: https://www.ayrshare.com/docs/apis/generate/overview
AI Utilities for various workflows
We offer a set of AI utilities that help with creating social media posts.
## Token Limits
For every API call made to AI endpoints, a certain number of "tokens" are used. These tokens are calculated based on the data you send and receive. Every month, your Max Pack and overall Ayrshare account are allocated a total of 300,000 tokens for Business plans, 100,000 for Premium Plus plans, and 50,000 for Premium plans.
This allocation refreshes on the first day of each month. To see how many tokens a specific API call used, as well as your total usage for the month, please check the HTTP response.
# Generate Post Text
Source: https://www.ayrshare.com/docs/apis/generate/post-text
POST /generate/post
Generate a new social post using AI
Generate a new social post using AI. You can either provide text or images to create the social media post. [Token limits](/docs/apis/generate/overview#token-limits) applicable.
## Header Parameters
## Body Parameters
Description of what the post should be about. For example: "A shoe sale happening Monday with specials on red, blue, and yellow shoes". Not required if `mediaUrls` parameter is included.
An array of image URLs to base the post text on. Required if `text` parameter not included.
Add hashtags to the post.
Add emojis to the post.
Construct a post with 280 or few characters.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"text": "This beautiful new shoe is on sale now. It comes in red, blue, or purple. Check it out today."}' \
-X POST https://api.ayrshare.com/api/generate/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/generate/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
post: "This beautiful new shoe is on sale now. It comes in red, blue, or purple. Check it out today.", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'post': 'This beautiful new shoe is on sale now. It comes in red, blue, or purple. Check it out today.'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/generate/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"This beautiful new shoe is on sale now. It comes in red, blue, or purple. Check it out today."
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/generate/post',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY',
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Text theme={"system"}
{
"status": "success",
"post": "🎉🛍️ Introducing the stunning new shoes that's now on sale! You can choose from three different colors – red, blue, or purple – and trust us, they're all amazing! Don't miss out on this beauty and grab yours today! 🙌 #newshoe #onSale #fashionable #colormebeautiful 🌈",
"usage": 98, // Tokens used for this call
"totalMonthlyUsage": 733 // Total tokens used for the month
}
```
```json 200: Image theme={"system"}
{
"status": "success",
"post": ["Ventured out on a serene walk today—a path less traveled but surrounded by the lush vibrancy of nature's finest. The perfect spot to reconnect with the earth and oneself. Where do your paths lead you?\n\n#NatureWalks #ExploreOutdoors #PeacefulPath"],
"mediaUrls": ["https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg", "https://upload.wikimedia.org/wikipedia/commons/thumb/d/dd/Gfp-wisconsin-madison-the-nature-boardwalk.jpg/2560px-Gfp-wisconsin-madison-the-nature-boardwalk.jpg"],
"usage": 2295,
"totalMonthlyUsage": 6987
}
```
```json 400: Bad Request theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Rewrite Post
Source: https://www.ayrshare.com/docs/apis/generate/rewrite-post
POST /generate/rewrite
Generate variations of a social media post using AI
Generate variations of a social media post using AI. [Token limits](/docs/apis/generate/overview#token-limits) applicable.
## Header Parameters
## Body Parameters
The post text to be rewritten.
Add emojis to the post.
Add hashtags to the post.
Construct a post 280 or fewer characters.
Number of rewrites. Min: 1 and Max: 5.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"post": "Kali melts the heart, even when the rest of the day is freezing. Happy International Polar Bear Day to the largest land carnivore and the biggest, furriest part of the Zoo’s bear community! \nOur resident polar bear Kali (pronounced “Cully”) is a wild-born bear that was born off of the northwest coast of Alaska. He was named by the people of the Native Village of Point Lay, who rescued him. \"Kali\" is the Inupiaq name for Point Lay. Eventually, the U.S. Fish and Wildlife"}' \
-X POST https://api.ayrshare.com/api/generate/rewrite
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/generate/rewrite", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
post: "Kali melts the heart, even when the rest of the day is freezing. Happy International Polar Bear Day to the largest land carnivore and the biggest, furriest part of the Zoo’s bear community! \nOur resident polar bear Kali (pronounced “Cully”) is a wild-born bear that was born off of the northwest coast of Alaska. He was named by the people of the Native Village of Point Lay, who rescued him. \"Kali\" is the Inupiaq name for Point Lay. Eventually, the U.S. Fish and Wildlife", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'post': 'Kali melts the heart, even when the rest of the day is freezing. Happy International Polar Bear Day to the largest land carnivore and the biggest, furriest part of the Zoo’s bear community! \nOur resident polar bear Kali (pronounced “Cully”) is a wild-born bear that was born off of the northwest coast of Alaska. He was named by the people of the Native Village of Point Lay, who rescued him. \"Kali\" is the Inupiaq name for Point Lay. Eventually, the U.S. Fish and Wildlife'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/generate/rewrite',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"Kali melts the heart, even when the rest of the day is freezing. Happy International Polar Bear Day to the largest land carnivore and the biggest, furriest part of the Zoo’s bear community! \nOur resident polar bear Kali (pronounced “Cully”) is a wild-born bear that was born off of the northwest coast of Alaska. He was named by the people of the Native Village of Point Lay, who rescued him. \"Kali\" is the Inupiaq name for Point Lay. Eventually, the U.S. Fish and Wildlife"
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/generate/rewrite',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY',
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"post": "Kali melts the heart, even when the rest of the day is freezing. Happy International Polar Bear Day to the largest land carnivore and the biggest, furriest part of the Zoo’s bear community! \nOur resident polar bear Kali (pronounced “Cully”) is a wild-born bear that was born off of the northwest coast of Alaska. He was named by the people of the Native Village of Point Lay, who rescued him. \"Kali\" is the Inupiaq name for Point Lay. Eventually, the U.S. Fish and Wildlife",
"rewrites": [
"❄️🐻 Kali, the lovable polar bear, warms our hearts on this #InternationalPolarBearDay. Fun fact: he was named after Inupiaq village, Point Lay! #FurryZooCommunity 🐾",
"Happy #InternationalPolarBearDay to Kali, the largest land carnivore of the Zoo community! Even on freezing days, Kali steals our hearts with his adorable antics. 🐻❤️",
"Meet Kali, the wild-born polar bear with a heart-melting charm. 🐾❄️ Sending love on this #InternationalPolarBearDay to the Zoo's fluffiest resident. 🐻❤️",
"On #InternationalPolarBearDay, we celebrate Kali, the furry wonder from the largest land carnivore family of the Zoo. 🐾🐻 He was named after an Inupiaq village, Point Lay!🌟",
"Kali, the Zoo's beloved polar bear, steals our hearts with his playful spirit, as we celebrate #InternationalPolarBearDay. 🐻❤️ Born off the Alaskan coast, he's a true warrior! 💪🌟"
],
"usage": 98, // Tokens used for this call
"totalMonthlyUsage": 733 // Total tokens used for the month
}
```
```json 400: Missing parameters theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Sentiment Analysis
Source: https://www.ayrshare.com/docs/apis/generate/sentiment
POST /generate/sentiments
Generate a sentiment analysis on a social media post or comment
Generate a sentiment analysis on a social media post or comment to understand if the text is positive, negative, or neutral and recommendations on improving the text for a more positive reaction.
## Header Parameters
## Body Parameters
The string of text to generate the sentiment analysis on.
### Request Examples
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"text": "These shoes aren't the best. The color has faded and they are uncomfortable to walk in."}' \
-X POST https://api.ayrshare.com/api/generate/sentiment
```
```javascript JavaScript theme={"system"}
const API_KEY = 'YOUR_API_KEY';
const analyzeTextSentiment = async (text) => {
try {
const response = await fetch('https://api.ayrshare.com/api/generate/sentiment', {
method: 'POST',
headers: {
'Authorization': `Bearer ${API_KEY}`,
'Content-Type': 'application/json'
},
body: JSON.stringify({ text })
});
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
console.log('Sentiment Analysis Result:', data);
return data;
} catch (error) {
console.error('Error analyzing sentiment:', error.message);
throw error;
}
};
```
```python Python theme={"system"}
import requests
import json
API_KEY = 'YOUR_API_KEY'
def analyze_text_sentiment(text):
url = 'https://api.ayrshare.com/api/generate/sentiment'
headers = {
'Authorization': f'Bearer {API_KEY}',
'Content-Type': 'application/json'
}
data = {'text': text}
try:
response = requests.post(url, headers=headers, json=data)
response.raise_for_status() # Raises a HTTPError if the status is 4xx, 5xx
result = response.json()
print('Sentiment Analysis Result:', json.dumps(result, indent=2))
return result
except requests.exceptions.RequestException as e:
print('Error analyzing sentiment:', e)
raise
```
```php PHP theme={"system"}
$text]);
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if (curl_errno($ch)) {
echo 'Error analyzing sentiment: ' . curl_error($ch);
return null;
}
curl_close($ch);
if ($httpCode >= 200 && $httpCode < 300) {
$result = json_decode($response, true);
echo "Sentiment Analysis Result:\n";
print_r($result);
return $result;
} else {
echo "HTTP Error: " . $httpCode . "\n";
echo "Response: " . $response . "\n";
return null;
}
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
class Program
{
private const string API_KEY = "YOUR_API_KEY";
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string textToAnalyze = "These shoes aren't the best. The color has faded and they are uncomfortable to walk in.";
try
{
var result = await AnalyzeTextSentimentAsync(textToAnalyze);
Console.WriteLine("Sentiment Analysis Result:");
Console.WriteLine(JsonSerializer.Serialize(result, new JsonSerializerOptions { WriteIndented = true }));
}
catch (Exception e)
{
Console.WriteLine($"An error occurred: {e.Message}");
}
}
static async Task AnalyzeTextSentimentAsync(string text)
{
var url = "https://api.ayrshare.com/api/generate/sentiment";
var requestData = new { text = text };
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {API_KEY}");
var json = JsonSerializer.Serialize(requestData);
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, content);
if (!response.IsSuccessStatusCode)
{
throw new HttpRequestException($"HTTP error! status: {response.StatusCode}");
}
var responseBody = await response.Content.ReadAsStringAsync();
return JsonSerializer.Deserialize(responseBody);
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"text": "These shoes aren't the best. The color has faded and they are uncomfortable to walk in.",
"sentimentAnalysis": {
"sentiment": "negative", // positive, negative, or neutral
"opportunities": [
"Improve color durability",
"Enhance comfort level"
],
"recommendations": [
{
"opportunity": "Improve color durability",
"recommendation": "Investigate and use higher-quality dyes or materials to prevent fading over time."
},
{
"opportunity": "Enhance comfort level",
"recommendation": "Review and possibly redesign the shoe's insole and cushioning to provide better support and comfort for walking."
}
]
}
}
```
```json 400: Error theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Transcribe a Video
Source: https://www.ayrshare.com/docs/apis/generate/transcribe-video
POST /generate/transcription
Provide a transcription and title of a video file using AI
Generate a transcription and title of a video file using AI.
This transcription can then be used in the [/generate/post](/docs/apis/generate/post-text) to create a social media summary of the video.
For [YouTube](/docs/apis/post/social-networks/youtube), which requires a title, the generated title can be used.
The video must have been previously uploaded to Ayrshare with [/media](/docs/apis/media/overview).
Videos not hosted by Ayrshare will be rejected.
Maximum video file size is 500GB and maximum duration is 10 minutes.
### Transcribe Video Guide
## Header Parameters
## Body Parameters
URL encoded video URL. The video must be hosted by Ayrshare.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"videoUrl": "https://img.ayrshare.com/random/landscape5.mp4"}' \
-X POST https://api.ayrshare.com/api/generate/transcription
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/generate/transcription", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
videoUrl: "https://img.ayrshare.com/random/landscape5.mp4", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'videoUrl': 'https://img.ayrshare.com/random/landscape5.mp4'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/generate/transcription',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://img.ayrshare.com/random/landscape5.mp4"
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/generate/transcription',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY',
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```json 200: Success theme={"system"}
{
"status": "success",
"transcript": "This is your last chance. After this, there is no turning back. You take the blue pill the story ends you wake up in your bed and believe whatever you want to be. You take the red pill you stay in Wonderland. And I show you how deep the rabbit hole goes.",
"transcriptArray": [
"This is your last chance.",
"After this, there is no turning back.",
"You take the blue pill the story ends you wake up in your bed and believe whatever you want to be. You take the red pill you stay in Wonderland.",
"And I show you how deep the rabbit hole goes."
],
"videoTitle": "Choose Wisely: Blue Pill or Red Pill Adventure Awaits!",
"wordCount": 52
}
```
# Translate Post
Source: https://www.ayrshare.com/docs/apis/generate/translate-post
POST /generate/translate
Translate text for a post to another language
Translate text for a post to over 100 different [languages](/docs/iso-codes/language) using AI. The current language is automatically detected and translated to the specified language.
## Header Parameters
## Body Parameters
Text to be translated.
[Language code](/docs/iso-codes/language) to translate the text.
```json 200: Success theme={"system"}
{
"status": "success",
"translatedText": "Nos vamos a las carreras",
"originalText": "Off we go to the races",
"language": "es"
}
```
```json 400: Bad Language Submitted theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Auto Hashtags
Source: https://www.ayrshare.com/docs/apis/hashtags/auto-hashtags
POST /hashtags/auto
Add the most relevant hashtags to your post
When creating your post, add relevant hashtags by either embedding them within the text or placing them at the end.
Our advanced AI system will analyze your content to generate appropriate hashtags based on the subject matter.
Although you can use any language for your post, writing in English typically yields the best results for our hashtag generation process.
## Header Parameters
## Body Parameters
Post text to add the hashtags. Max length 1,000 characters.
validate
Integer of max number of Hashtags to add. Max value range 1 to 10. Note: Instagram allows a maximum of 5 hashtags per post.
Specify the [language code](/docs/iso-codes/language) of the language of the post to assist the hashtag algorithm.
```json theme={"system"}
{
"language": "fr"
}
```
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_Key" \
-d '{"post": "Today is a great day!", "max": 3, "position": "auto"}'
-X POST https://api.ayrshare.com/api/hashtags/auto
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch(`https://api.ayrshare.com/api/hashtags/auto`, {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
post: "Today is a great day!", // required
max: 3, // optional, range 1-5
position: "auto" // optional, "auto" or "end"
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {
'post': 'Today is a great day!',
'max': 3, # optional, range 1-5
'position': 'auto' # optional, 'auto' or 'end'
}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/hashtags/auto',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'POST',
'https://api.ayrshare.com/api/hashtags/auto',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'json' => [
'post' => 'Today is a great day!',
'max' => 3,
'position' => 'auto'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```javascript 200 Hashtagged Post Returned theme={"system"}
{
post: "Disney’s trouble with Oswald the #LuckyRabbit is a great lesson #ForStartups in a crisis"
}
```
# Check Banned Hashtags
Source: https://www.ayrshare.com/docs/apis/hashtags/check-hashtags
GET /hashtags/banned
A banned hashtag checker
A banned hashtag checker to validate if the given hashtag has been banned by Instagram or other social networks.
## Header Parameters
## Query Parameters
The hashtag to validate. Format: "hashtag" or "#hashtag"
```bash cURL theme={"system"}
curl --location --request GET 'https://api.ayrshare.com/ayrshare/api/hashtags/banned?hashtag=%23bikinibody' \
--header 'Authorization: Bearer API_KEY'
```
```javascript JavaScript theme={"system"}
const myHeaders = new Headers();
myHeaders.append("Authorization", "Bearer API_KEY");
const urlencoded = new URLSearchParams();
const requestOptions = {
method: 'GET',
headers: myHeaders,
};
fetch("https://api.ayrshare.com/api/hashtags/banned?hashtag=%23bikinibody", requestOptions)
.then(response => response.json())
.then(result => console.log(result))
.catch(error => console.log('error', error));
```
```python Python theme={"system"}
import requests
# Your API key
API_KEY = "Bearer API_KEY"
# Headers
headers = {
"Authorization": API_KEY
}
# URL
url = "https://api.ayrshare.com/api/hashtags/banned?hashtag=%23bikinibody"
# Making the GET request
response = requests.get(url, headers=headers)
# Checking if the request was successful
if response.status_code == 200:
# Parse JSON response
result = response.json()
print(result)
else:
print("Error:", response.status_code)
```
```php PHP theme={"system"}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace ConsoleApp
{
class Program
{
static async Task Main(string[] args)
{
// Your API key
string apiKey = "Bearer API_KEY";
// URL
string url = "https://api.ayrshare.com/api/hashtags/banned?hashtag=%23bikinibody";
using (var httpClient = new HttpClient())
{
// Set the Authorization header with your API key
httpClient.DefaultRequestHeaders.Add("Authorization", apiKey);
try
{
// Make the GET request
HttpResponseMessage response = await httpClient.GetAsync(url);
if (response.IsSuccessStatusCode)
{
// Read the response content as a string
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
}
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request exception: {e.Message}");
}
}
}
}
}
```
```json 200 theme={"system"}
{
"hashtag": "#bikinibody",
"banned": true
}
```
```json 400 theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Hashtags API Overview
Source: https://www.ayrshare.com/docs/apis/hashtags/overview
Generate hashtags to add to your posts
## Hashtags API Features
The Hashtags API provides powerful tools to enhance your social media content with relevant hashtags:
Intelligent Hashtag Generation: Automatically create optimized hashtags based
on your content's keywords, leveraging real-time popularity data to maximize visibility and
engagement.
Cross-Platform Support: Generate platform-specific hashtags tailored for
Facebook, Instagram, LinkedIn, Threads, TikTok, Twitter, and YouTube to optimize performance on each
network.
Instagram Hashtag Research: Search and analyze the most popular or relevant
Instagram posts for any given hashtag to inform your content strategy and identify trending
topics.
Performance Optimization: Improve post discoverability and reach by
incorporating trending, relevant hashtags that align with your content and target audience.
# Recommend Hashtags
Source: https://www.ayrshare.com/docs/apis/hashtags/recommend-hashtags
GET /hashtags/recommend
Get suggestions for hashtags based on a keyword
Get suggestions for hashtags based on a keyword. Data and view counts are generated from TikTok.
## Header Parameters
## Query Parameters
A single keyword to get recommended hashtags from TikTok. Spaces in the keyword will be removed.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/hashtags/recommend?keyword=apple
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/hashtags/recommend?keyword=apple", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/hashtags/recommend?keyword=apple', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'GET',
'https://api.ayrshare.com/api/hashtags/recommend?keyword=apple',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HashtagsRecommendGETRequest_csharp
{
class HashtagsRecommend
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/hashtags/recommend?keyword=apple";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"keyword": "apple",
"recommendations": [
{
"viewCount": 71950998550, // The number of views that the recommended hashtag has received.
"name": "apple" // Suggested hashtag
},
{
"viewCount": 6318280101,
"name": "applewatch"
},
{
"viewCount": 2486358394,
"name": "applepencil"
},
{
"viewCount": 2142842131,
"name": "applemusic"
},
{
"viewCount": 1506224079,
"name": "applesquad"
},
{
"viewCount": 1307287255,
"name": "apples"
},
{
"viewCount": 1008293028,
"name": "applepie"
},
{
"viewCount": 788388838,
"name": "applejuice"
},
{
"viewCount": 1024901638,
"name": "appletv"
},
{
"viewCount": 679033194,
"name": "applechallenge"
}
]
}
```
```json 400: Bad Request Missing keyword theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Search Hashtags
Source: https://www.ayrshare.com/docs/apis/hashtags/search-hashtags
GET /hashtags/search
Find public Instagram Media that has been tagged with specific hashtags
Search based on a hashtag keyword to get a list of Instagram media posts that have been tagged with that hashtag.
You can query a maximum of 30 unique hashtags on behalf of an Instagram Business or Creator
Account within a rolling, 7-day period. Once you query a hashtag, it will count against this
limit for 7 days. Subsequent queries on the same hashtag within this time frame will not count
against your limit, and will not reset its initial query 7-day timer.
You cannot comment on hashtagged media objects discovered through the API.
Hashtags on Stories are not supported.
Emojis in hashtag queries are not supported.
The API will return an error for any requests that include hashtags that we have deemed
sensitive or offensive.
## Header Parameters
## Query Parameters
The keyword to search for matching hashtags.
```bash Search for the hashtag "wisdom" theme={"system"}
https://api.ayrshare.com/api/hashtags/search?keyword=wisdom
```
The type of search to perform. Valid values: `top`, `recent`. Top will return the most popular
hashtags. Recent will return the most recent hashtags. Default: `top`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/hashtags/search?keyword=wisdom&searchType=top
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/hashtags/search?keyword=wisdom&searchType=top", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/hashtags/search?keyword=wisdom&searchType=top', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'GET',
'https://api.ayrshare.com/api/hashtags/search?keyword=wisdom&searchType=top',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HashtagsSearchGETRequest_csharp
{
class HashtagsSearch
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/hashtags/search?keyword=wisdom&searchType=top";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"hashtag": {
"id": "17843798701036069",
"name": "wisdom"
},
"searchResults": [
{
"caption": "🙂96% Percent of People have no clue this method exists ... For manifesting money , there is powerful a manifestation technique it changes your beliefs on reality in the deepest level of the subconscious mind it literally changed my life give it an honest try . Click the link in our bio to see if this works for you too . (worked for me )",
"children": {
"data": [
{
"id": "18364392676136006"
},
{
"id": "18008030660493382"
},
{
"id": "17866325790184001"
}
]
},
"commentsCount": 174,
"id": "17861532840277137",
"likeCount": 1389,
"mediaType": "CAROUSEL_ALBUM",
"mediaUrl": "https://scontent-sjc3-1.cdninstagram.com/v/t51.29350-15/466382723_420103424530861_7360358065352125344_n.jpg?_nc_cat=109&ccb=1-7&_nc_sid=18de74&_nc_ohc=c-_PWScwGQAQ7kNvgFPrTeK&_nc_zt=23&_nc_ht=scontent-sjc3-1.cdninstagram.com&edm=APCawUEEAAAA&_nc_gid=AT1Ax3hZh5lt3kJskGj3Hj6&oh=00_AYBDkqi4pSdedYxDfUnAm9c93AlyXabWzJM81UySCuIpDg&oe=67406A28",
"permalink": "https://www.instagram.com/p/DCdDF6_Sa31/",
"timestamp": "2024-11-17T01:22:29+0000"
},
{
"caption": "🙂96% Percent of People have no clue this method exists ... For manifesting money , there is powerful a manifestation technique it changes your beliefs on reality in the deepest level of the subconscious mind it literally changed my life give it an honest try . Click the link in our bio to see if this works for you too . (worked for me )",
"children": {
"data": [
{
"id": "17854668297321577"
},
{
"id": "17953717721743238"
}
]
},
"commentsCount": 40,
"id": "18054468655821869",
"likeCount": 371,
"mediaType": "CAROUSEL_ALBUM",
"mediaUrl": "https://scontent-sjc3-1.cdninstagram.com/v/t51.29350-15/467316183_1100515004943506_6021956524402070992_n.jpg?_nc_cat=101&ccb=1-7&_nc_sid=18de74&_nc_ohc=LQVF-7HyOE4Q7kNvgEPZ98d&_nc_zt=23&_nc_ht=scontent-sjc3-1.cdninstagram.com&edm=APCawUEEAAAA&_nc_gid=AT1Ax3hZh5lt3kJskGj3Hj6&oh=00_AYArRIS7xth-eI3rRWlvLhMklRJLBIH5rZ66akHfuSnxjg&oe=6740726A",
"permalink": "https://www.instagram.com/p/DCdDZb5SzUj/",
"timestamp": "2024-11-17T01:25:09+0000"
},
{
"caption": "Setting intentions rather than expectations is a valuable way to keep you from overthinking, help you stay closer to reality, and move with mental clarity. \n\nYou can develop this kind of mindful skill by joining my 8-week "Slow School" live online course. It starts Dec 3rd. Check the link in my bio to learn more 🖤",
"children": {
"data": [
{
"id": "18471207271027384"
},
{
"id": "17875576494200786"
}
]
},
"commentsCount": 33,
"id": "18057421303730368",
"likeCount": 5601,
"mediaType": "CAROUSEL_ALBUM",
"mediaUrl": "https://scontent-sjc3-1.cdninstagram.com/v/t51.2885-15/467022186_992465279306045_4614070861842639887_n.jpg?_nc_cat=105&ccb=1-7&_nc_sid=18de74&_nc_ohc=pchds80KU9oQ7kNvgEaCWkZ&_nc_zt=23&_nc_ht=scontent-sjc3-1.cdninstagram.com&edm=APCawUEEAAAA&oh=00_AYDqG9VA4vJzBvXw6nzFTXc7rU0xVnsTJBOpptBbCEI9Gw&oe=67408C3D",
"permalink": "https://www.instagram.com/p/DCZT369M_07/",
"timestamp": "2024-11-15T14:32:12+0000"
},
"count": 25,
"lastUpdated": "2024-11-19T20:09:02.830Z",
"nextUpdate": "2024-11-19T20:20:02.830Z"
]
}
```
```json 400: Bad Request theme={"system"}
{
"action": "hashtag search",
"status": "error",
"code": 380,
"message": "Error searching Instagram Hashtags. Could not find a matching hashtag"
}
```
# Posts History
Source: https://www.ayrshare.com/docs/apis/history/get-history
GET /history
History of Ayrshare Posts
Get a history of posts sent via Ayrshare, in descending order (most recent to oldest).
With this endpoint you can retrieve posts from a specific date range, status, social network, or the last n days.
History `status` fields values:
`awaiting approval`: Posts are awaiting to be approved via the [approval
workflow](/docs/apis/post/overview#approval-workflow).
`deleted`: Post has been deleted. Note: deleted posts are only returned with the status query
filter. Please see below.
`error`: An error occurred with one or more social networks.
`paused`: A scheduled post that has been paused.
`pending`: The post has not yet been processed. Typically a scheduled post.
`success`: The post was successfully sent to all social networks.
Additional information:
The [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-id) is returned in the response `id` field.
To retrieve posts that originated outside of Ayrshare, such as posts manually created directly
at the social network, use the [history platform](/docs/apis/history/history-platform) endpoint.
If only an individual post is required, use the [post history by
id](/docs/apis/history/get-history-id) endpoint.
The history endpoint JSON results are cached for 1 minute if the `limit` is greater than the
default value of 25.
## Header Parameters
## Query Parameters
Returns the last n number of posts. For example, if you only want the most recent post, set `limit=1`.
If not present will return all records contained within `lastDays`.
Default: `25` posts. Max value: `1000`.
Filter by social network platforms. Platform values: `bluesky`, `facebook`, `gmb`, `instagram`,
`linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`,
`youtube`. Note, uses `OR` logic: `["facebook", "instagram"]` returns posts from either.
Return posts from and including this start date. Start date for the history in ISO 8601 format.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`. Please see
[utctime](https://www.utctime.net/) for more examples.
Return posts up to and including this end date. End date for the history in ISO 8601 format. For
example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`. Please see
[utctime](https://www.utctime.net/) for more examples.
Returns the last n days of posts by the publish date, i.e. `scheduleDate`. Default 30 days.
The `lastDays` will be ignored if `startDate` and `endDate` are provided.
If the value is zero 0 will return the entire history of posts.
If the value is greater than 0, it will return the last n days of posts.
For example, `lastDays=5` returns the last 5 days of posts and `lastDays=0` returns all posts
determined by the `limit`.
Filter by current status of post. Valid values: `success`, `error`, `processing`, `pending`, `paused`, `deleted`, and `awaiting approval`.
Processing indicates the post is currently being sent. Pending indicates the post is scheduled to be posted at a future date.
Deleted posts are not returned by default. They are only returned with the status query filter set to `status=deleted`.
The type of post to retrieve, either post that were sent immediately or scheduled post using the
`scheduleDate` field. Values: `immediate` or `scheduled`.
When creating an auto repost an ID is assigned to track that series of posts.
Retrieve posts by auto repost ID or use the value of `all` to get all auto reposts.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/history?startDate=2025-01-01T12:30:00Z&endDate=2025-03-01T12:30:00&limit=100
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/history?startDate=2025-01-01T12:30:00Z&endDate=2025-03-01T12:30:00&limit=100", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/history?startDate=2025-01-01T12:30:00Z&endDate=2025-03-01T12:30:00&limit=100', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HistoryGETRequest_csharp
{
class History
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/history?startDate=2025-01-01T12:30:00Z&endDate=2025-03-01T12:30:00&limit=100";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"history": [
{
"errors": [],
"post": "This is the post I sent",
"platforms": [
"twitter",
"facebook"
],
"postIds": [
{
"status": "success",
"id": "1288968500063775749", // Twitter Social Post ID
"platform": "twitter"
},
{
"id": "104923907983682_108683297607743", // Facebook Social Post ID
"status": "success",
"platform": "facebook"
}
],
"urls": [],
"type": "now",
"notes": "Approved by John Smith", // Reference notes set via /post
"created": "2022-05-20T17:25:06Z",
"status": "deleted",
"scheduleDate": { // In a future release changed to "scheduleDate": "2020-11-05T12:21:29Z"
"_seconds": 1604578889,
"_nanoseconds": 211000000,
"utc": "2020-11-05T12:21:29Z"
},
"id": "rhn6u7wwz2WxGv6MZGK9" // Ayrshare Top-Level Post ID
},
{
"status": "success",
"platforms": [
"twitter",
"facebook"
],
"created": "2022-05-20T17:25:06Z",
"post": "Sometimes we need to take a break for lunch.",
"scheduleDate": { // In a future release changed to "scheduleDate": "2020-11-05T12:21:29Z"
"_seconds": 1604578889,
"_nanoseconds": 211000000,
"utc": "2020-11-05T12:21:29Z"
},
"type": "now",
"postIds": [
{
"platform": "twitter",
"id": "1288890036000983105", // Twitter Social Post ID
"status": "success"
},
{
"id": "104923907983682_108329970009742", // Facebook Social Post ID
"status": "success",
"platform": "facebook",
"isVideo": true // Video post
}
],
"errors": [],
"urls": [],
"id": "wWIY0OEirdNeYSJYm1Xa" // Ayrshare Post ID
},
{ // Awaiting approval post - Approved by user
"approved": true,
"approvedBy": "9abf1426d6ce9122ef11c7222e1",
"approvedDate": "2025-06-06T12:28:12Z",
"created": "2025-06-06T12:27:56Z",
"errors": [],
"id": "sujQsrXtroJU0NEOlY38",
"mediaUrls": [],
"platforms": [
"twitter"
],
"post": "I failed my way to success. - Thomas Edison",
"postIds": [
{
"status": "success",
"id": "193096515330813",
"postUrl": "https://twitter.com/RetiretyHQ/status/19309651533081",
"platform": "twitter"
}
],
"profileTitle": "Primary Profile",
"refId": "9abf1426d6ce9122ef11c7222e1",
"requiresApproval": true,
"scheduleDate": "2025-06-06T12:27:56Z",
"shortenLinks": false,
"status": "success",
"type": "now"
},
{ // Awaiting approval post - Rejected by user
"approved": false,
"created": "2025-06-06T12:23:48Z",
"id": "XL5xHeNK8HGTg07qxzmd",
"mediaUrls": [],
"platforms": [
"twitter"
],
"post": " Honesty is the first chapter in the book of wisdom. - Thomas Jefferson",
"profileTitle": "Primary Profile",
"refId": "9abf1426d6ce9122ef11c72bd62eddw2",
"rejectedBy": "9abf1426d6ce9122ef11c7222e1",
"rejectedDate": "2025-06-06T12:23:58Z",
"requiresApproval": true,
"scheduleDate": "2025-06-06T12:23:48Z",
"shortenLinks": false,
"status": "awaiting approval",
"type": "now"
}
],
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"count": 100,
"lastUpdated": "2025-04-05T22:44:14.209Z",
"nextUpdate": "2025-04-05T22:45:14.209Z"
}
```
```json 400: History not found theme={"system"}
{
"action": "history",
"status": "error",
"code": 221,
"message": "History not found for the past 30 days. Please see the docs on how to retrieve additional history. .../ayrshare.com/rest-api/endpoints/history#list-history-of-sent-and-scheduled-posts"
}
```
# Post History by ID
Source: https://www.ayrshare.com/docs/apis/history/get-history-id
GET /history/:id
Get the history for a specific post
Get the history for a specific post. Replace `:id` with the [Ayrshare Post ID](/docs/apis/overview#ayrshare-post-ids) returned from [post](/docs/apis/post/post).
## Header Parameters
## Path Parameters
Ayrshare Post ID returned from /post
## Query Parameters
Search all posts across all User Profiles for the post ID. Default: `false`
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/history/TBEAAqAMMJoweA9wKHUl
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/history/TBEAAqAMMJoweA9wKHUl", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/history/TBEAAqAMMJoweA9wKHUl', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HistoryGETByIDRequest_csharp
{
class HistoryGetById
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/history/TBEAAqAMMJoweA9wKHUl";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"tier": "business",
"status": "success",
"mediaUrls": [
"https://images.ayrshare.com/imgs/GhostBusters.jpg"
],
"postIds": [
{
"platform": "facebook",
"postUrl": "https://www.facebook.com/1105775157895689_361710168628052",
"status": "success",
"id": "105775157895689_361710168628052" // Facebook Social Post ID
}
],
"id": "TBEEAqAMMJoweA8wKHUp", // Ayrshare Post ID
"errors": [],
"platforms": [
"facebook"
],
"scheduleDate": { // In a future release changed to "scheduleDate": "2020-11-05T12:21:29Z"
"_seconds": 1604578889,
"_nanoseconds": 211000000,
"utc": "2020-11-05T12:21:29Z"
},
"createDate": { // deprecated, use created
"_seconds": 1653067506,
"_nanoseconds": 179000000,
"utc": "2022-05-20T17:25:06Z"
},
"created": "2022-05-20T17:25:06Z",
"shortenLinks": true,
"post": "Today is a great day",
"notes": "Approved by John Smith", // reference notes set via /post
"type": "scheduled"
}
```
```json 400: Post not found theme={"system"}
{
"action": "history",
"status": "error",
"code": 221,
"message": "History not found.",
"id": "4W3f3RPr6QSrw8S5Yo8"
}
```
# Get post history for a social platform
Source: https://www.ayrshare.com/docs/apis/history/history-platform
GET /history/:platform
Fetch posts and analytics from Bluesky, Facebook, Instagram, LinkedIn, Pinterest, Snapchat, Threads, TikTok, X, and YouTube, including non-Ayrshare posts.
This endpoint allows you to fetch both posts and their analytics from major social networks (Bluesky, Facebook, Instagram, LinkedIn, Pinterest, Threads, TikTok, X/Twitter, and YouTube). It works for all posts on these platforms - whether they were created using Ayrshare's API or posted directly through the social network's interface.
More detailed analytics are available with the [analytics endpoint](/docs/apis/analytics/overview).
The IDs returned in from this endpoint are the social networks' native [social post ID](/docs/apis/overview#social-post-id) and not the [Ayrshare post ID](/docs/apis/overview#ayrshare-post-id).
This allows you to get details for any post on a social network, even if it was not created through Ayrshare.
For example, you can retrieve a post that was manually published on facebook.com and use the Facebook [Social Post ID](/docs/apis/overview#social-post-id) returned to [get comments](/docs/apis/comments/get-comments) or [get analytics](/docs/apis/analytics/social-by-id).
If you do not need posts that originated outside of Ayrshare, simply use the [Ayrshare post ID](/docs/apis/overview#ayrshare-post-id) returned in a post with the [comment](/docs/apis/comments/post-comment), [analytics](/docs/apis/analytics/post), or [history](/docs/apis/history/history-social-id) endpoints.
`:platform` = `bluesky`, `facebook`, `instagram`, `linkedin`, `pinterest`, `snapchat`, `threads`, `tiktok`, `twitter`, `youtube`.
Example: `https://api.ayrshare.com/api/history/instagram`
### Copyrighted Media
Instagram and TikTok will exclude all copyrighted media in their responses.
The Instagram `mediaUrl` field is omitted from response if the media contains copyrighted material or has been flagged for a copyright violation.
Examples of copyrighted material can include audio on reels. You can check in the Instagram app under Settings -> Account Status.
TikTok does not return media if the media contains copyrighted material or has been flagged for a copyright violation.
Examples of copyrighted material can include audio on reels (TikTok will mute these videos). You can check in the TikTok app under Activity -> System Notifications.
If such a video is muted, you can add audio in the TikTok app.
Go to the post and select the option to add non-copyrighted audio.
The video will then be returned in this API response.
### Limitations
#### Facebook
Expired/archived Stories (older than 24 hours) are automatically filtered out. Only active Stories are included in the response by default.
Use the `dataType` query parameter to request only `posts` or only `stories`.
Use the `since` and `until` query parameters to filter posts by date range.
#### Instagram
Responses will not include Live Video stories.
Stories are only available for 24 hours.
New stories created when a user reshares a story will not be returned. Reshared
stories include stories created using the Add Yours Templates.
New posts created when a user accepts collaboration requests will not be returned.
Use the `dataType` query parameter to request only `posts` or only `stories`.
#### Snapchat
Story and Saved Story items include a `mediaUrls` array with the downloadable media URL of each Snap in that Story. Spotlights are single-asset and do not include `mediaUrls`.
Fetching per-Snap media requires an additional request per Story, which adds latency. Set the `media` query parameter to `false` to skip it and return Story/Saved Story items without `mediaUrls` for faster, metadata-only responses. Example: `GET https://api.ayrshare.com/api/history/snapchat?media=false`.
## Header Parameters
## Path Parameters
The platform of the posts to retrieve. Values: `bluesky`, `facebook`,
`instagram`, `linkedin`, `pinterest`, `snapchat`, `threads`, `tiktok`,
`twitter`, `youtube`.
## Query Parameters
Number of history records to return. Max limit: 500\*
High limits may result in slower response times, so we recommend using a limit of no more than 100.
\*Higher limits are available on Enterprise plans. Please contact your account manager for details.
Skip gathering full analytics for Facebook Pages and Instagram. Returns only
the Social Post ID. Should be used if analytics aren't needed (only need the
Social Post ID), for a faster return, or errors occur when limit > 100.
Facebook only. By default the posts returned are from the Facebook Page feed. You may also choose to only return posts published by the page.
Use feed (default) when you want a more comprehensive view of all content associated with the page, including interactions from other users. Use `pagePublished` when you only want to retrieve posts made by the page itself.
X/Twitter only. This parameter allows you to retrieve posts from a specific X/Twitter user by their numeric ID, rather than from your linked account.
For example, to get all posts from the handle `@Google`, you would use their numeric userId `20536157`.
You can find any X/Twitter user's numeric userId by using the [Brands Get User](/docs/apis/listen/brand-user) endpoint.
Note: Use only the API KEY in the header to make this request. Do not include the Profile Key.
X/Twitter only. This parameter allows you to retrieve posts from a specific X/Twitter user by their handle, rather than from your linked account.
For example, to get all posts from the handle `@Google`.
Note: Use only the API KEY in the header to make this request. Do not include the Profile Key.
Cursor-based pagination for retrieving the next page of results. Pass the `next` value from the previous response's `meta.pagination` object to fetch the next set of posts.
Facebook only. ISO UTC date string to filter posts created on or after this date. Use with `until` for a specific date range.
Example: `since=2026-03-17`
Facebook only. ISO UTC date string to filter posts created on or before this date. Use with `since` for a specific date range.
Example: `until=2026-03-20`
Facebook and Instagram. Filter the type of content returned. By default, both regular posts and active Stories are returned.
Values:
* `posts` — regular posts only (no Stories)
* `stories` — Stories only
Omit this parameter to return both posts and Stories (default behavior).
Note: For Facebook, expired/archived Stories (older than 24 hours) are automatically filtered out. For Instagram, Stories are only available for 24 hours.
Snapchat only. When `true` (default), Story and Saved Story history items include a `mediaUrls` array with each Snap's downloadable media URL. Fetching that media requires an extra request per Story, so set `media=false` to skip it for faster responses when you only need the Story metadata.
## Pagination Response
When using cursor-based pagination (with `next` query parameter), the response includes a `meta.pagination` object containing pagination state.
The `posts` array in each paginated response contains objects with the same structure as shown in the response examples below for each platform.
Pagination metadata for cursor-based navigation through results.
Indicates whether there are more results available beyond the current page. When `true`, use the `next` cursor to fetch additional posts.
An opaque cursor string to pass as the `next` query parameter to retrieve the next page of results. Only present when `hasMore` is `true` or when there are more results to fetch.
The number of results requested per page.
## Partial Results
Retrieving history from some platforms takes several requests behind the scenes. If one of those requests fails part-way through, the posts already retrieved are still returned — but the list is **incomplete**, and the response says so with `status: "partial"` instead of `"success"`.
`"success"` when the full requested history was retrieved, or `"partial"` when only some of it was. A `"partial"` response is not an error: the `posts` it contains are accurate, there are simply fewer of them than exist.
Treat `"partial"` as "this page is incomplete", not as "this is everything". Counting posts, or deriving totals from a `"partial"` response, will understate the real figures. Request again to get the full history — partial responses are never cached, so a retry always re-reads from the platform.
```json Partial response theme={"system"}
{
"status": "partial",
"posts": [
{ "id": "...", "postUrl": "..." }
],
"postsCount": 12,
"lastUpdated": "2026-08-12T09:14:02.118Z",
"nextUpdate": "2026-08-12T10:14:02.118Z"
}
```
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/history/instagram
```
```bash cURL Facebook with Filters theme={"system"}
# Get only regular posts (no Stories) within a date range
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/history/facebook?limit=20&since=2026-03-17&until=2026-03-20&dataType=posts"
```
```bash cURL with Pagination theme={"system"}
# First request
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/history/twitter?limit=10"
# Next page request (use 'next' cursor from previous response)
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/history/twitter?limit=10&next=eyJ0b2tlbiI6IjE3MzkyNjg1MTQ0ODU3MTUi..."
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/history/instagram", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```javascript JavaScript with Pagination theme={"system"}
const API_KEY = "API_KEY";
// Function to fetch posts with pagination (up to maxPosts or until cutoffTime)
async function fetchPosts(platform, { limit = 25, maxPosts = 100, cutoffTime = null } = {}) {
const posts = [];
let nextCursor = null;
let pagePosts = [];
do {
const url = new URL(`https://api.ayrshare.com/api/history/${platform}`);
url.searchParams.set("limit", limit);
if (nextCursor) {
url.searchParams.set("next", nextCursor);
}
const response = await fetch(url, {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
});
const data = await response.json();
pagePosts = data.posts || [];
// Filter by date if cutoffTime is specified
if (cutoffTime) {
pagePosts = pagePosts.filter(post => new Date(post.created) >= cutoffTime);
}
posts.push(...pagePosts);
// Get cursor for next page
nextCursor = data.meta?.pagination?.hasMore ? data.meta.pagination.next : null;
} while (nextCursor && pagePosts.length > 0 && posts.length < maxPosts);
return posts.slice(0, maxPosts);
}
// Fetch up to 100 Twitter posts
fetchPosts("twitter", { maxPosts: 100 }).then(posts => console.log(posts));
// Fetch posts from the last 30 days (up to 200)
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 60 * 60 * 1000);
fetchPosts("twitter", { maxPosts: 200, cutoffTime: thirtyDaysAgo }).then(posts => console.log(posts));
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/history/instagram', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HistoryPlatformGETRequest_csharp
{
class HistoryPlatform
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/history/TBEAAqAMMJoweA9wKHUl";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success {4, 23, 161, 216, 287, 367, 488, 672} theme={"system"}
{
"status": "success",
"posts": [
// Bluesky Response Example
{
"cid": "bafyreigh7nz7x6pl4atgsextqtcbh33mg66yqt3caeihutn7ojkmpdtnzm", // Bluesky Content ID
"created": "2025-01-06T21:35:08.951Z",
"id": "at://did:plc:n7atrjd22xgkmgwig6dzlhzd/app.bsky.feed.post/3lfb57nxgxs2e", // Bluesky Social Post ID
"indexedAt": "2025-01-06T21:35:09.156Z",
"labels": [],
"likeCount": 2,
"post": "What a wonderful data day!",
"postUrl": "https://bsky.app/profile/ayrshare.com/post/3lf43nl5jis24",
"quoteCount": 3,
"replyCount": 2,
"repostCount": 1,
"viewer": {
"threadMuted": false,
"embeddingDisabled": false
}
},
// Facebook Response Example
// Note: If the FB page has fewer than 100 likes then not all analytics data available.
{
"clicksUnique": 31,
"created": "2022-06-14T23:43:21Z",
"commentsCount": 13,
"engagedUsers": 3,
"fullPicture": "https://scontent.ford4-1.fna.fbcdn.net/v/t39.30808-6/287997502_758105082307121_n.jpg?stp=dst-jpg_s720x720&_nc_cat=101&ccb=1-7&_nc_sid=8024bb&_nc_ohc=EkktQTp_uWIAX_xtTxV&_nc_ht=scontent.ford4-1.fna&edm=AKK4YLsEAAAA&oh=00_AT-Y5Ht2Pl3MeY-qIBs6BC10SbZ-47Vfcc7DKiQrCnIUA&oe=62AEEECA",
"id": "104619420979033_758005082307127", // Facebook Social Post ID
"impressionsUnique": 0,
"isPopular": false,
"lastUpdated": "2022-06-14T23:43:38.359Z",
"likeCount": 38,
"likedBy": [ // Users who liked the post
{
"id": "7101149746568432",
"name": "John Smith"
}
],
"mediaUrls": [ // If attached photos or video
{
"media": {
"image": {
"height": 412,
"src": "https://scontent-lga3-1.xx.fbcdn.net/v/t15.5256-10/294978304_1014487762575117_6279324362130508123_n.jpg?stp=dst-jpg_s720x720&_nc_cat=101&ccb=1-7&_nc_sid=ad6a45&_nc_ohc=y3bYN-PGN0YAX9kO2qn&_nc_ht=scontent-lga3-1.xx&edm=AKK4YLsEAAAA&oh=00_AT9by7D4y4sjY4BW5RW53JO6BaG2UkpUCCJrrugW7GDW9w&oe=62E23000",
"width": 720
},
// Source if mediaType is video
"source": "https://video-lga3-1.xx.fbcdn.net/v/t39.25447-2/294718581_137662848672158_7246454806912028286_n.mp4?_nc_cat=111&vs=696d8a2ba08f208b&_nc_vs=HBkcFQAYJEdIVU1rUkdlb1RFaE5IMEFBSDdPNmVaQWxKQmtibWRqQUFBRhUAAsgBAEsGiBJwcm9ncmVzc2l2ZV9yZWNpcGUBMQ1zdWJzYW1wbGVfZnBzABB2bWFmX2VuYWJsZV9uc3ViACBtZWFzdXJlX29yaWdpbmFsX3Jlc29sdXRpb25fc3NpbQAoY29tcHV0ZV9zc2ltX29ubHlfYXRfb3JpZ2luYWxfcmVzb2x1dGlvbgARZGlzYWJsZV9wb3N0X3B2cXMAFQAlABwAACac%2FNfk2tKqARWQTigCQzMYC3Z0c19wcmV2aWV3HBdAGZmZmZmZmhhEZGFzaF9pNGxpdGViYXNpY19wYXNzdGhyb3VnaGFsaWduZWRfNDgwX2NyZl8yOF9tYWluXzMuMF9mcmFnXzJfdmlkZW8SABgYdmlkZW9zLnZ0cy5jYWxsYmFjay5wcm9kOBJWSURFT19WSUVXX1JFUVVFU1QbD4gVb2VtX3RhcmdldF9lbmNvZGVfdGFnBm9lcF9zZBNvZW1fcmVxdWVzdF90aW1lX21zATAMb2VtX2NmZ19ydWxlCnNkX3VubXV0ZWQTb2VtX3JvaV9yZWFjaF9jb3VudAI5OBFvZW1faXNfZXhwZXJpbWVudAAMb2VtX3JvaV9ub3RlC3Byb2dyZXNzaXZlEW9lbV9yb2lfdXNlcl90aWVyAB5vZW1fcm9pX3ByZWRpY3RlZF93YXRjaF90aW1lX3MBMBZvZW1fcm9pX3JlY2lwZV9iZW5lZml0BTAuMDAwJW9lbV9yb2lfc3RhdGljX2JlbmVmaXRfY29zdF9ldmFsdWF0b3ILcHJvZ3Jlc3NpdmUMb2VtX3ZpZGVvX2lkEDEyNjk2MTcwNzM3NzgxNTESb2VtX3ZpZGVvX2Fzc2V0X2lkDzc5ODQ2NjE3NDg0NzE4OBVvZW1fdmlkZW9fcmVzb3VyY2VfaWQPMzc1MjU0ODg3ODkwNzAyHG9lbV9zb3VyY2VfdmlkZW9fZW5jb2RpbmdfaWQPNDUwODU0MzgzNjE1MDc5DnZ0c19yZXF1ZXN0X2lkD2EyYThlNWU4OTBkNTRmMyUCHBwcFfDmFxsBVQACGwFVAAIcFQIAAAAWgLq3AwAlxAEbB4gBcwQ1ODkyAmNkCjIwMjItMDctMjQDcmNiATADYXBwBVdhdGNoAmN0GERJUkVDVEVEX1BPU1RfQVRUQUNITUVOVBNvcmlnaW5hbF9kdXJhdGlvbl9zBTYuNDE3AnRzFHByb2dyZXNzaXZlX29yZGVyaW5nAA%3D%3D&ccb=1-7&_nc_sid=a06cc9&_nc_ohc=bA3WO4Dk72QAX9TB9ag&_nc_ht=video-lga3-1.xx&edm=AKK4YLsEAAAA&oh=00_AT_CzNhlIwNxY_7UMWIGQMNOtD-Aw_LGcVHnDWvcQJVkAw&oe=62E2ADE1&_nc_rid=780575090331889"
},
"mediaType": "video", // "link" or "photo"
"url": "https://www.facebook.com/115237020273490/videos/1269617073778151",
"videoId": "1269617073778151"
}
],
"negativeFeedback": 0,
"negativeFeedbackUnique": 0,
"nextUpdate": "2022-06-15T00:18:38.359Z",
"parentId": "5764771300200609_742258953848744", // If a shared post, then the ID of the original post
"post": "What a nice one",
"postUrl": "https://www.facebook.com/104619420979033_758105082307121",
"properties": [ // for videos only
{
"name": "Length",
"text": "00:07"
}
],
"reactions": { // Total lifetime
"like": 1, // Like reactions - The "like" reaction counts include both "like" and "care" reactions.
"love": 1, // Love reactions
"anger": 1, // Anger reactions
"haha": 1, // Haha reactions
"wow": 1, // Wow reactions
"sorry": 1, // Sorry reactions
"total": 6 // Total number of reactions
},
"reactionsByType": 1,
"statusType": "added_video", // Status actions: added_photos, added_video, app_created_story, approved_friend, created_event, created_group, created_note, mobile_status_update, published_story, shared_story, tagged_in_photo, wall_post
"videoViewTime": 0,
"videoViews": 0,
"videoViewsUnique": 0
},
{
"clicksUnique": 45,
"created": "2022-06-14T14:53:01Z",
"engagedUsers": 2,
"fullPicture": "https://external.ford4-1.fna.fbcdn.net/emg1/v/t13/614683800928174083?url=https%3a%2f%2fwww.alphast.com%2fwp-content%2fuploads%2f2022%2f06%2fheadphones-scaled.jpg&fb_obo=1&utld=fbcdn.net&stp=dst-emg0_q75&ccb=13-1&oh=00_AT-MVM6lP-eWgsqCW6IhImKAJaGy71JIGIntjlVnZkJw&oe=62AAAC5C&_nc_sid=5f3a21",
"id": "104619420979033_757752962332339", // Facebook Social Post ID
"impressionsUnique": 1,
"isPopular": false,
"lastUpdated": "2022-06-14T23:40:48.453Z",
"mediaUrls": [
{
"mediaUrl": "link",
"url": "https://www.alphasht.com/finding-the-best-headphones/"
}
],
"negativeFeedback": 0,
"negativeFeedbackUnique": 0,
"nextUpdate": "2022-06-15T00:15:48.453Z",
"post": "Finding The Best Headphones: Finding the best headphones for you depends on several factors.",
"postUrl": "https://www.facebook.com/104619420979033_75775296233233",
"reactions": { // Total lifetime
"like": 1, // Like reactions - The "like" reaction counts include both "like" and "care" reactions.
"love": 1, // Love reactions
"anger": 1, // Anger reactions
"haha": 1, // Haha reactions
"wow": 1, // Wow reactions
"sorry": 1, // Sorry reactions
"total": 6 // Total number of reactions
},
"reactionsByType": 1,
"videoViewTime": 0,
"videoViews": 0,
"videoViewsUnique": 0
},
{ // Facebook Story
"clicksUnique": 0,
"commentsCount": 0,
"created": "2024-03-15T19:36:29.000Z",
"engagedUsers": 0,
"id": "1593984754722429",
"impressionsFanPaidUnique": 0,
"impressionsFanUnique": 0,
"impressionsOrganicUnique": 0,
"impressionsPaidUnique": 0,
"impressionsUnique": 0,
"likeCount": 0,
"mediaId": "1593984754722429",
"mediaType": "video",
"mediaUrls": [
{
"media": {
"image": {
"height": 720,
"src": "https://scontent-lga3-1.xx.fbcdn.net/v/t15.5256-10/451306699",
"width": 405
},
"source": "https://video-lga3-1.xx.fbcdn.net/o1/v/t2/f2/m69/An_VRpjrlZJxZEUVTHHMpd"
},
"mediaType": "video",
"type": "story"
}
],
"negativeFeedback": 0,
"negativeFeedbackUnique": 0,
"post": "",
"postId": "1433249613981178",
"postUrl": "https://facebook.com/stories/114251701259415/UzpfSVNDOjE0MzMyNDk2MTczMTQ1MTE=/?view_single=1",
"reactions": {},
"reactionsByType": 0,
"sharesCount": 0,
"statusType": "published",
"videoViewTime": 0,
"videoViews": 0,
"videoViewsUnique": 0
},
// Instagram Response Example
{
"mediaUrl": "https://scontent.cdninstagram.com/v/t51.2885-15/75317300_249468363049056_6683482523516619964_n.jpg",
"permalink": "https://www.instagram.com/p/B5OBT3ygpfg/",
"commentsCount": 0,
"created": "2022-05-20T17:26:03Z",
"likeCount": 0,
"mediaProductType": "FEED", // Media product type: AD, FEED, STORY or REELS
"mediaType": "IMAGE", // Media type: CAROUSEL_ALBUM, IMAGE, or VIDEO
"username": "thegoodone",
"id": "17833140557332933", // Instagram Social Post ID
"thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.2885-15/277243581_1136333620462129_9111753545576538669_n.jpg",
"post": "The #Mandalorian is on tonight instead of Friday",
"postUrl": "https://www.instagram.com/p/B5OBT3ygpfg/" // same as permalink
},
{
"mediaUrl": "https://scontent.cdninstagram.com/v/t51.2885-15/72719989_401282024671549_6704610247561386099_n.jpg", // The media_url field is omitted from responses if the media contains copyrighted material or has been flagged for a copyright violation. Examples of copyrighted material can include audio on reels.
"permalink": "https://www.instagram.com/p/B6_EubJFlMI/",
"commentsCount": 0,
"created": "2022-05-20T17:26:03Z",
"likeCount": 0,
"mediaProductType": "REELS", // Media product type: AD, FEED, STORY or REELS
"mediaType": "VIDEO", // Media type: CAROUSEL_ALBUM, IMAGE, or VIDEO
"username": "thegoodone",
"id": "17933140557332933", // Instagram Social Post ID
"thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.2885-15/277243581_1136333620462129_9111753545576538669_n.jpg",
"post": "And finally, number eleven of the best shows of 2019 is #Mandalorian #BabyYoda #Bestof2019",
"postUrl": "https://www.instagram.com/p/B6_EubJFlMI/" // same as permalink
},
{
"commentsCount": 3,
"created": "2024-04-29T16:10:10Z",
"id": "17998949393616",
"isPopular": false,
"lastUpdated": "2024-04-29T22:28:20.499Z",
"likeCount": 14,
"mediaProductType": "FEED",
"mediaType": "CAROUSEL_ALBUM",
"mediaUrls": [
{
"mediaUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.2885-15/441166659",
"id": "18395216701078298"
},
{
"mediaUrl": "https://scontent-lga3-2.cdninstagram.com/o1/v/t16/f1/m82/834208F324481538FE6E565772BC6B8E_video_dashinit.mp4",
"thumbnailUrl": "https://scontent-lga3-2.cdninstagram.com/v/t51.29350-15/440150892_371703612533736_7866608290099350261_n.jpg",
"id": "18041898211827161"
}
],
"nextUpdate": "2024-04-29T22:39:20.499Z",
"post": "Learn to value yourself, which means: to fight for your happiness. - Ayn Rand",
"postUrl": "https://www.instagram.com/p/C6WgGmSPn/",
"username": "johnboy"
},
// LinkedIn Response Example
{
"clickCount": 0,
"commentCount": 1,
"created": "2022-12-28T16:07:38Z",
"engagement": 0.6666666666666666,
"id": "urn:li:share:701389826709", // LinkedIn Social Post ID
"impressionCount": 3,
"lastModified": "2022-12-28T16:07:38Z",
"likeCount": 1,
"post": "left thirty pocket track flower whistle",
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:701389826709",
"publishedAt": "2022-12-28T16:07:38Z",
"reactions": { // Get reactions on a LinkedIn share
"like": 1, // "Like in the UI
"praise": 2, // "Celebrate" in the UI
"maybe": 3, // "Curious" in the UI
"empathy": 3, // "Love" in the UI
"interest": 2 // "Insightful" in the UI
"appreciation": 5 // "Support" in the UI
},
"shareCount": 0,
"status": "PUBLISHED",
"uniqueImpressionsCount": 3,
"visibility": "PUBLIC"
},
{
"clickCount": 0,
"comments": [
"urn:li:comment:(urn:li:activity:722)" // Look up using the Comments endpoint
],
"commentCount": 1,
"commentsState": "OPEN",
"created": "2022-12-28T17:05:11Z",
"engagement": 0.16, // Not available for Personal accounts
"id": "urn:li:share:70139127498", // LinkedIn Social Post ID
"impressionCount": 12, // Not available for Personal accounts
"lastModified": "2022-12-28T17:05:11Z",
"likeBy": [
"urn:li:person:Sgwlpf744" // Look up using the brands endpoint
],
"likeCount": 1,
"likedByCurrentUser": false,
"mediaUrls": [ // please see .../ayrshare.com/additional-info/upcoming-api-changes#changes-in-effect-december-1-2023
{
"id": "urn:li:video:C4E10AQHz0RMm5aAiAg",
"url": "https://media.licdn.com/dms/image/C4E10AQHz0RMm5aAiAg"
},
{
"id": "urn:li:video:C4E10AQHz0RMm5adsH2",
"url": "https://media.licdn.com/dms/image/C4E10AQHz0RMm5adsH2"
}
],
"post": "no monkey gulf organization mood choose earn",
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:70139127498",
"publishedAt": "2022-12-28T17:05:11Z",
"reactions": { // Get reactions on a LinkedIn share
"like": 1, // "Like in the UI
"praise": 2, // "Celebrate" in the UI
"maybe": 3, // "Curious" in the UI
"empathy": 3, // "Love" in the UI
"interest": 2 // "Insightful" in the UI
"appreciation": 5 // "Support" in the UI
},
"shareCount": 0, // Not available for Personal accounts
"status": "PUBLISHED",
"uniqueImpressionsCount": 9, // Not available for Personal accounts
"totalFirstLevelComments": 1,
"visibility": "PUBLIC"
},
// Pinterest Response Example
{
"altText": "",
"boardId": "955255839651522358",
"coverImageUrl": "https://i.pinimg.com/originals/7e/ea/af/7eeaaf4bce167902b06fe3370227e.jpg",
"created": "2022-08-09T22:25:12Z",
"dominantColor": "#353027", // Dominant pin color. Hex number, e.g. "#6E7874"
"duration": 6416, // Time in millisecord
"height": 1062,
"id": "7184649418547260", // Pinterest Social Post ID
"link": "",
"mediaType": "video",
"mediaUrl": "https://i.pinimg.com/originals/7e/ea/af/7eeaaf4bce167902b06fe3370227e.jpg",
"note": "What a great post",
"post": "You are what you believe yourself to be. - Paulo Coelho",
"postUrl": "https://www.pinterest.com/pin/7184649418547260",
"productTags": [],
"title": "My new post",
"username": "ayrshare",
"width": 1856
},
{
"altText": "",
"created": "2022-08-09T22:25:12Z",
"dominantColor": "#7c7c7c",
"height": 600,
"id": "7184649468512979", // Pinterest Social Post ID
"link": "",
"mediaType": "image",
"mediaUrl": "https://i.pinimg.com/originals/1b/0a/02/1b0a02123fba55042474b61bb2aa1.jpg",
"post": "Peace begins with a smile. - Mother Teresa",
"postUrl": "https://www.pinterest.com/pin/7184649468512979",
"username": "ayrshare",
"width": 600
},
{
"altText": "",
"created": "2022-10-17T12:26:05Z",
"dominantColor": "#7f805e",
"id": "36493237618990511", // Pinterest Social Post ID
"link": "",
"mediaType": "multiple_mixed",
"mediaUrls": [
{
"mediaType": "image",
"height": 442,
"width": 249,
"mediaUrl": "https://i.pinimg.com/originals/6c/e2/1f/6ce21fa3936b51cd39c34be6f60dd469.jpg"
},
{
"mediaType": "image",
"height": 589,
"width": 332,
"mediaUrl": "https://i.pinimg.com/originals/9370f0845be155b5640c0f.jpg"
},
{
"mediaType": "image",
"height": 589,
"width": 332,
"mediaUrl": "https://i.pinimg.com/originals/9370f0845be155b5640c0f.jpg"
},
{
"mediaType": "image",
"height": 589,
"width": 332,
"mediaUrl": "https://i.pinimg.com/originals/9370f0845be155b5640c0f.jpg"
},
{
"mediaType": "video",
"duration": 19600,
"height": 1280,
"width": 720,
"mediaUrl": "https://i.pinimg.com/videos/thumbnails/originals/9370f0845be155b5640c0f.jpg"
}
],
"post": " ",
"postUrl": "https://www.pinterest.com/pin/36493237618990511",
"username": "johnsmith"
},
// Snapchat Response Example
{
"id": "43d61bfe-2249-5a46-944a-d36d27c9530b",
"profileId": "43548e97-edf1-44f9-984a-0a38470133",
"thumbnailUrl": "https://cf-st.sc-cdn.net/d/fY3MDNOXp0hxLecKdr4hV",
"type": "PUBLIC_STORY", // PUBLIC_STORY, SAVED_STORY, or SPOTLIGHT
"created": "2025-05-19T19:38:36.789Z",
"ended": "2025-05-19T19:38:36.790Z",
"mediaUrls": [ // per-Snap downloadable media (returned by default; omitted when media=false). Spotlights excluded.
"https://cf-st.sc-cdn.net/d/8Yb8LJ5TWb2yVMSTuF6dg.10.IRZXSOY",
"https://cf-st.sc-cdn.net/d/AbC123dEfG456hIjK.20.IRZXSOY"
]
},
{
"id": "07c99fea-1c72-4f72-bcd9-7dacfae753e0",
"profileId": "43548e97-edf1-44f9-984a-0a3847023",
"thumbnailUrl": "https://cf-st.sc-cdn.net/d/wTf9NQ0mZ4GCDyFj7feQ8",
"type": "SAVED_STORY", // PUBLIC_STORY, SAVED_STORY, or SPOTLIGHT
"title": "A song about snaps",
"created": "2025-05-20T18:09:04.876Z",
"updated": "2025-05-20T18:09:04.876Z",
"mediaUrls": [ // per-Snap downloadable media (returned by default; omitted when media=false)
"https://cf-st.sc-cdn.net/d/wTf9NQ0mZ4GCDyFj7feQ8.30.IRZXSOY"
]
},
// TikTok Response Example
{
"audienceCities": [
{
"city_name": "US Teton County",
"percentage": 3.1
},
{
"city_name": "US Queens",
"percentage": 6.3
}
],
"audienceCountries": [
{
"country": "GB",
"percentage": 0.0029
},
{
"country": "US",
"percentage": 0.9604
}
],
"averageTimeWatched": 2.0132, // Average watch time in seconds. The average time viewers spent watching your video.
"commentsCount": 1, // Total number of lifetime comments. Available 24-48 hours after posting.
"created": "2024-02-26T18:32:00Z",
"embedUrl": "https://www.tiktok.com/static/profile-video?id=73399801580586794&",
"engagementLikes": [ // Engagement likes. The distribution of your viewers who liked your video at specific points in the video's timeline.
{
"percentage": 0,
"second": "179"
},
{
"percentage": 0,
"second": "339"
}
],
"fullVideoWatchedRate": 0.0176, // The percentage of viewers who watched the entire video.
"id": "7339980158058679594",
"impressionSources": [
{
"impression_source": "Search",
"percentage": 0
},
{
"impression_source": "Sound",
"percentage": 0
},
{
"impression_source": "other_profile_vv",
"percentage": 0
},
{
"impression_source": "Follow",
"percentage": 0
},
{
"impression_source": "For You",
"percentage": 1
},
{
"impression_source": "Hashtag",
"percentage": 0
},
{
"impression_source": "Personal Profile",
"percentage": 0
}
],
"likeCount": 2, // Total number of lifetime likes. Available 24-48 hours after posting.
"mediaType": "video",
"musicTitle": "♬ original sound - Mack",
"musicUrl": "https://www.tiktok.com/music/original-sound",
"name": "Mack",
"post": "I have failed over and over and over again in my life and that is why I succeed. - Michael Jordan",
"postUrl": "https://www.tiktok.com/@happy/video/7339980158058679594",
"reach": 653, // The number of people who watched your published content at least once.
"shareUrl": "https://www.tiktok.com/@happy/video/7339980158058679594",
"shareCount": 2, // Total number of lifetime shares. Available 24-48 hours after posting.
"tags": [],
"thumbnailHeight": 1024,
"thumbnailUrl": "https://p19-sign.tiktokcdn-us.com/obj/tos-useast5-p-85c255-tx/oIpT 9CLHAaQfuD67E3jfAFJ5eVDuF5Ibkmszg?x-expires=1709305200&x-signature=ZBTR0Q%2B4KLi8szRCir8eYEcAs1s%3D",
"thumbnailWidth": 576,
"totalTimeWatched": 1373, // Total watch time in seconds. The total time viewers spent watching your video.
"url": "https://www.tiktok.com/@happy",
"videoDuration": 11.332, // Video duration in seconds.
"videoViewRetention": [ // This metric indicates how many of your viewers are still watching after a certain amount of time.
{
"percentage": 0.1,
"second": "155"
},
{
"percentage": 0.07,
"second": "234"
}
],
/* Total number of lifetime users who viewed the video. Available 24-48 hours after posting.
If the user swipes away from the ad then swipes back, it would be counted as 2 impressions.
Therefore, a new video view will be counted again with the new impression session.
*/
"videoViews": 697
},
// Twitter Response Example
// Note: Non-public and organic metrics only available last 30-days of Tweets
{
"created": "2022-05-20T20:07:53.000Z",
"entities": {
"urls": [
{
"start": 77, // Starting character position (inclusive)
"end": 96, // Ending character position (exclusive)
"url": "https://t.co/abc123", // Shortened t.co URL
"expandedUrl": "https://www.ayrshare.com/docs", // Full URL after redirect
"displayUrl": "ayrshare.com/docs", // User-friendly display version
"unwoundUrl": "https://www.ayrshare.com/docs" // Final destination URL
}
],
"hashtags": [
{
"start": 97, // Starting character position (inclusive)
"end": 112, // Ending character position (exclusive)
"tag": "SocialMediaAPI" // Hashtag text without #
}
],
"mentions": [
{
"start": 113, // Starting character position (inclusive)
"end": 122, // Ending character position (exclusive)
"username": "ayrshare" // Username without @
}
],
"cashtags": [
{
"start": 123, // Starting character position (inclusive)
"end": 128, // Ending character position (exclusive)
"tag": "META" // Stock symbol without $
}
],
"annotations": [
{
"start": 46, // Starting character position (inclusive)
"end": 54, // Ending character position (exclusive)
"probability": 0.9456, // Confidence score (0.0 to 1.0)
"type": "Product", // Entity type: Person, Place, Product, Organization, Other
"normalizedText": "Ayrshare" // Standardized entity name
}
]
},
"id": "1187026023991603", // Twitter Social Post ID
"media": [ // Attached media
{
"mediaKey": "7_1555577959943217152",
"previewImageUrl": "https://pbs.twimg.com/ext_tw_video_thumb/1555577959943217152/pu/img/f4M9veIozFjQA_XD.jpg",
"durationMs": 2168, // Duration in milliseconds, videos only
"type": "video" // or "photo", "animated_gif"
}
],
"nonPublicMetrics": { // Use this to determine the total number of impressions generated for the Tweet. Only available for Tweets created the last 30 days.
"impressionCount": 1, // Number of times the Tweet has been viewed
"userProfileClicks": 0
},
"organicMetrics": { // Use this to measure organic engagement for the Tweet. Only available for Tweets created the last 30 days.
"userProfileClicks": 2,
"impressionCount": 4, // Number of times the Tweet has been viewed organically.
"replyCount": 3,
"retweetCount": 1,
"likeCount": 234
},
"possiblySensitive": false, // Tweet contains possibly sensitive information
"post": "Just launched our social media campaign using Ayrshare! Check out the API at https://t.co/abc123 #SocialMediaAPI @ayrshare $META",
"postUrl": "https://twitter.com/myhandle/status/1187026023991603",
"publicMetrics": { // Use this to measure Tweet engagement. Only available for Tweets created the last 30 days.
"retweetCount": 2,
"replyCount": 2,
"likeCount": 5,
"quoteCount": 1
},
"referencedTweets": [ // If a quoted or reply tweet
{
"type": "quoted", // or "replied_to"
"id": "1556718165828276224", // Quoted or replied Tweet ID
"url": "https://www.twitter.com/1556718165828276224" // Quoted or Replied Tweet URL
}
],
"source": "Ayrshare", // Determine if a Twitter user posted from the web, mobile device, or other app.
"text": "To effectively communicate, we must realize that we are all different", // Deprecated, use "post" field
"urls": [ // Available for long Tweets only
{
"start": 866,
"end": 889,
"url": "https://t.co/3r6xz4hBnM",
"expandedUrl": "https://www.cnn.com",
"displayUrl": "cnn.com"
}
],
},
{
"authorId": "1194338779881472",
"created": "2023-12-27T03:24:23.000Z",
"createdAt": "2023-12-27T03:24:23.000Z",
"editHistoryTweetIds": [
"17398682514485715"
],
"id": "17398682514485715",
"media": [ // available for videos and gifs
{
"nonPublicMetrics": {
"playback100Count": 2,
"playback0Count": 55,
"playback50Count": 4,
"playback25Count": 11,
"playback75Count": 2
},
"publicMetrics": {
"viewCount": 27
},
"durationMs": 28240,
"organicMetrics": {
"playback100Count": 2,
"playback0Count": 55,
"playback25Count": 11,
"playback75Count": 2,
"playback50Count": 4,
"viewCount": 27
},
"mediaKey": "7_1739849636389814272",
"previewImageUrl": "https://pbs.twimg.com/ext_tw_video_thumb/1739849636389814272/pu/img/bCkAdkD0R00-ZlkY.jpg",
"width": 1920,
"type": "video",
"height": 1080,
"mediaUrls": [
{
"bitRate": 256000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/480x270/4RoZCqynednVMFgy.mp4?tag=12"
},
{
"bitRate": 832000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/640x360/RYy5iHTIxu7_iyZm.mp4?tag=12"
},
{
"bitRate": 2176000,
"contentType": "video/mp4",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/vid/avc1/1280x720/9UpR90ekFA-9Ucxo.mp4?tag=12"
},
{
"contentType": "application/x-mpegURL",
"mediaUrl": "https://video.twimg.com/ext_tw_video/1739849636389814272/pu/pl/0AVy2xIOLQcsrEZG.m3u8?tag=12&container=fmp4"
}
]
}
],
"nonPublicMetrics": {
"impressionCount": 54,
"userProfileClicks": 0
},
"organicMetrics": {
"userProfileClicks": 0,
"likeCount": 0,
"replyCount": 0,
"impressionCount": 54,
"retweetCount": 0
},
"possiblySensitive": false,
"post": "Family is the most important thing in the world. - Diana, Princess of Wales https://t.co/MgYxnJDer6",
"postUrl": "https://twitter.com/superme/status/17398682514485715",
"publicMetrics": {
"retweetCount": 0,
"replyCount": 0,
"likeCount": 0,
"quoteCount": 0,
"bookmarkCount": 0,
"impressionCount": 54
},
"urls": [ // Available for long Tweets only
{
"start": 866,
"end": 889,
"url": "https://t.co/3r6xz4hBnM",
"expandedUrl": "https://www.cnn.com",
"displayUrl": "cnn.com"
}
],
},
// YouTube Response Example
{
"created": "2022-08-15T19:14:44Z",
"description": "Doubt is not a pleasant condition, but certainty is absurd. - Voltaire", // Deprecated, use "post" field
"id": "Q-4OuHCALVa", // YouTube Social Post ID
"position": 0,
"post": "Doubt is not a pleasant condition, but certainty is absurd. - Voltaire",
"postUrl": "https://www.youtube.com/watch?v=Q-4OuHCALVa",
"privacyStatus": "public",
"license": "youtube", // "youtube" or "creativeCommon"
"embeddable": true, // whether the video can be embedded on external sites
"publicStatsViewable": true, // whether the extended stats panel is publicly viewable
"published": "2025-05-07T16:27:12Z",
"thumbnailUrl": "https://i.ytimg.com/vi/Q-4OuHCALVa/default.jpg",
"title": "Yo time"
},
{
"created": "2022-08-08T22:24:42Z",
"description": "Little author little, one travels far. - J.R.R. Tolkien", // Deprecated, use "post" field
"id": "Btg4ysKnHea", // YouTube Social Post ID
"position": 1,
"post": "Little author little, one travels far. - J.R.R. Tolkien",
"postUrl": "https://www.youtube.com/watch?v=Btg4ysKnHea",
"privacyStatus": "unlisted",
"license": "creativeCommon",
"embeddable": false,
"publicStatsViewable": false,
"published": "2025-05-07T16:27:12Z",
"thumbnailUrl": "https://i.ytimg.com/vi/Btg4ysKnHea/default.jpg",
"title": "Nice one 2"
}
],
"lastUpdated": "2022-11-14T16:04:51.994Z",
"nextUpdate": "2022-11-14T16:37:21.994Z",
"meta": {
"pagination": {
"hasMore": true, // More results available
"next": "eyJ0b2tlbiI6IjE3MzkyNjg1MTQ0ODU3MTUiLCJzb3VyY2UiOiJwdWJsaWMiLCJwbGF0Zm9ybSI6InR3aXR0ZXIifQ==", // Cursor for next page
"limit": 10 // Requested page size
}
}
}
```
```json 400: Error theme={"system"}
{
"status": "error",
"code": 196,
"message": "Instagram is not connected"
}
```
```json 400: Bad Request theme={"system"}
{
// When some of the data is not available from the social networks.
// All available data is still returned
"status": "error",
"posts": [
{... valid data },
{
"action": "analytics",
"code": 187,
"commentsCount": 0,
"created": "2019-03-22T13:31:02Z",
"createdTime": "2019-03-22T13:31:02+0000",
"from": {
"name": "Ayrshare",
"id": "746346376697"
},
"fullPicture": "https://external.fphl1-1.fna.fbcdn.net/emg1/v/t13/",
"id": "746346376697_3993223", // Facebook Social Post ID
"isPopular": false,
"likeCount": 2,
"mediaUrls": [
{
"description": "Dirk Cotton's approach to retirement planning.",
"media": {
"image": {
"height": 720,
"src": "https://external.fphl1-1.fna.fbcdn.net/emg1/v/t13/608115669879219",
"width": 720
}
},
"mediaType": "link",
"title": "The Retirement Planning Regime",
"url": "https://bit.ly/2RwaH"
}
],
"message": "Error getting analytics.",
"post": "Error getting analytics.",
"status": "error",
"statusType": "shared_story"
},
{... valid data }
]
}
```
# Posts History by Social ID
Source: https://www.ayrshare.com/docs/apis/history/history-social-id
GET /history/:socialId
Retrieve history for a post that did not originate via Ayrshare.
Retrieve history for posts that did not originate via Ayrshare by providing the low-level Social post ID. This [Social Post ID ](/docs/apis/overview#social-post-id)is returned in the `postIds` field of the [post endpoint](/docs/apis/post/overview) or the `id` field from the [get all history endpoint](/docs/apis/history/get-history) or the ID from a post URL, such as from this [Facebook post](https://www.facebook.com/Ayrshare/posts/pfbid02ktEFyG8EydxNGyiytsiC4m3X8kQAfTC6inCCzZJZD9KpAZAiWPpSK5C5HS7cgD54l).
The linked account must be the owner of the post to retrieve the history.
Supported platforms: Facebook, Instagram, LinkedIn, Threads, TikTok, Twitter, and YouTube with the following `platform` values: `facebook`, `instagram`, `linkedin`, `threads`, `tiktok`, `twitter`, `youtube`.
## Header Parameters
## Path Parameters
The [Social Post ID](/docs/apis/overview#id-types) of the post.
Please see the [/post endpoint](/docs/apis/post/post) Response 200 for another example of the Facebook
Social Post ID `104923907983682_108329000309742`
## Query Parameters
Always equals `true`
Values: `facebook`, `instagram`, `linkedin`, `threads`, `tiktok`, `twitter`, `youtube`
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook
```
```javascript JavaScript theme={"system"}
const url = "https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook";
const response = await fetch(url, {
headers: {
'Authorization': 'Bearer API_KEY'
}
});
```
```python Python theme={"system"}
import requests
url = 'https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook'
headers = {'Authorization': 'Bearer API_KEY'}
response = requests.get(url, headers=headers)
```
```php PHP theme={"system"}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, 'https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook');
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'GET');
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Authorization: Bearer API_KEY'));
$response = curl_exec($ch);
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace HistorySocialIdGETRequest_csharp
{
class HistorySocialId
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```go Go theme={"system"}
client := &http.Client{}
req, err := http.NewRequest("GET", "https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook", nil)
req.Header.Add("Authorization", "Bearer API_KEY")
resp, err := client.Do(req)
```
```ruby Ruby theme={"system"}
require 'net/http'
require 'uri'
uri = URI.parse("https://api.ayrshare.com/api/history/104923907983682_108329000309742?searchPlatformId=true&platform=facebook")
request = Net::HTTP::Get.new(uri)
request['Authorization'] = 'Bearer API_KEY'
response = Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == 'https') do |http|
http.request(request)
end
```
```json 200: Success theme={"system"}
[
{
"commentsCount": 0,
"created": "2024-01-25T23:01:23Z",
"from": {
"name": "Ayrshare",
"id": "18930271191"
},
"id": "18930271191_39392923",
"mediaUrls": [
{
"media": {
"image": {
"height": 720,
"src": "https://scontent-lga3-2.xx.fbcdn.net/v/...",
"width": 405
},
"source": "https://video-lga3-2.xx.fbcdn.net/o1/..."
},
"title": "🔥 Sneaker time!"
}
],
"messageTags": [
{
"id": "434786466522",
"name": "#sneakerswap365",
"offset": 242,
"length": 15
}
],
"post": "🔥 Sneaker Time for all!",
"postUrl": "https://www.facebook.com/reel/72681340799/",
"lastUpdated": "2024-01-25T23:29:58.014Z",
"nextUpdate": "2024-01-25T23:40:58.014Z"
}
]
```
```json 400: Post Not Found theme={"system"}
{
"action": "get",
"status": "error",
"code": 221,
"message": "The ID was not found. Please verify the id, API or Profile Keys, and required parameters.",
"id": "7268134079",
"lastUpdated": "2024-01-25T23:45:14.311Z",
"nextUpdate": "2024-01-25T23:56:14.311Z"
}
```
# History API Overview
Source: https://www.ayrshare.com/docs/apis/history/overview
Get the history of a post or all posts for a social network.
The Ayrshare history endpoint allows you to retrieve posts from your connected social media accounts, whether they were published through Ayrshare's platform or posted directly on the social networks themselves.
This means you can access your social media history through a single endpoint, making it easier to analyze and track all your social content regardless of how it was originally posted.
# Create Short Link
Source: https://www.ayrshare.com/docs/apis/links/create-short-link
POST /links
Provide a URL and a shortened link will be returned.
Provide a URL and a shortened link will be returned. Analytics can then be gathered on the clicks, browser type, etc.
Submitting the same URL for shortening will always result in the same shortened link. To generate a unique shortened link for the same URL, you can add extra query parameters to it. For example, appending a unique identifier like [https://ayrshare.com?uniqueId=123](https://ayrshare.com?uniqueId=123) will create a distinct shortened link.
You may also include UTM parameters, which will be embedded in the shortened URL link.
## Header Parameters
## Body Parameters
URL to be shortened. Must be a valid URL starting with https\://
Used to identify which Google Analytics ads campaign this referral references.
Used to identify a search engine, newsletter name, or other source.
Used to identify a medium such as email or cost-per-click.
Used for keyword analysis. Used to identify a specific product promotion or strategic campaign.
Used for paid search. Used to note the keywords for this ad.
Used for A/B testing and content-targeted ads. Used to differentiate ads or links that point to the same URL.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url": "https://www.ayrshare.com", "utmSource": "google_ads"}' \
-X POST https://api.ayrshare.com/api/links
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/links", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
url: "https://www.ayrshare.com", // required
utmSource: "google_ads", // optional
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'url': 'https://www.ayrshare.com',
'utmSource': 'google_ads"}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/links',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
require 'vendor/autoload.php';// Composer auto-loader using Guzzle. See .../guzzlephp.org/en/stable/overview.html
$client = new GuzzleHttp\Client();
$res = $client->request(
'POST',
'https://api.ayrshare.com/api/links',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'json' => [
'url' => 'https://www.ayrshare.com',
'utmSource' => 'google_ads', // optional
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"url": "https://www.ayrshare.com",
"utmSource": "google_ads",
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/links",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CreateShortLinkPOSTRequest_csharp
{
class CreateShortLink
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/analytics/links";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"url\" : \"https://www.ayrshare.com\"," +
"\"utmSource\" :\"google_ads\"";
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Success theme={"system"}
{
"created": "2023-07-17T15:20:51.118Z",
"id": "yC0fTl",
"originalUrl": "https://www.ayrshare.com/?utm_source=looking",
"shortUrl": "https://ayrs.io/yC0fTl",
"status": "success",
"utmSource": "looking"
}
```
```json 400: Error Shortening Link theme={"system"}
{
"action": "request",
"status": "error",
"code": 126,
"message": "Shorten URL failed. Please verify the URL is properly formatted and the correct UTM parameters are used."
}
```
# Link Analytics
Source: https://www.ayrshare.com/docs/apis/links/link-analytics
GET /links/:id
Get analytics on shortened links
Return analytics for all shortened links or a single link for a given link ID. For example:
`https://api.ayrshare.com/api/links/yC0fTl` returns analytics for ID `yC0fTl`
`https://api.ayrshare.com/api/links` returns all link analytics.
## Header Parameters
## Path Parameters
Provide the shortened link ID returned from the POST /links request as a path parameter. For
example: `https://api.ayrshare.com/api/links/yC0fTl` If no link ID is provided, all links are
returned.
## Query Parameters
Get history of links shortened after this date. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
Get history of links shortened before this date. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
Get history of links clicked after this date. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
Get history of links clicked before this date. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_Key" \
-H 'Content-Type: application/json' \
-X GET https://api.ayrshare.com/api/links/yC0fTl
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch(`https://api.ayrshare.com/api/links/yC0fTl`, {
method: "GET",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/links/yC0fTl',
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'GET',
'https://api.ayrshare.com/api/links/yC0fTl',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace LinksGETRequest_csharp
{
class Links
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/links/yC0fTl";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200: Analytics on a Link theme={"system"}
{
"status": "success",
"analytics": {
"browserCounts": {
"chrome": 15
},
"created": "2023-06-29T00:57:12.220Z",
"id": "yC0fTl",
"originalUrl": "https://www.ayrshare.com/?utm_source=google_ads",
"refererCounts": {},
"shortUrl": "https://ayrs.io/yC0fTl",
"socialClicks": {},
"status": "success",
"totalClicks": 15,
"utmSource": "google_ads"
}
}
```
```json 200: Analytics on all Links theme={"system"}
{
"status": "success",
"analytics": [
{
"browserCounts": {
"chrome": 3
},
"created": "2023-04-07T22:33:41.126Z",
"id": "pHXlbv9JlRxrXj6rstdMu",
"originalUrl": "https://www.ayrshare.com/",
"refererCounts": {},
"shortUrl": "https://ayrs.io/pHXlbv9JlRxrXj6rstdMu",
"socialClicks": {},
"totalClicks": 3
},
{
"browserCounts": {
"edge": 13
},
"created": "2023-07-17T15:20:51.118Z",
"id": "yC0fTl",
"originalUrl": "https://www.ayrshare.com/?utm_source=looking",
"refererCounts": {},
"shortUrl": "https://ayrs.io/yC0fTl",
"socialClicks": {},
"totalClicks": 13,
"utmSource": "looking"
}
]
}
```
```json 400: Bad Request theme={"system"}
{
"status": "error",
"message": "Unable to find link ID: yC0fTl",
"code": 187
}
```
# Links API Overview
Source: https://www.ayrshare.com/docs/apis/links/overview
Link shortener and analytics endpoint
With the /links endpoint you can shorten links to include in social posts.
The Ayrshare link shortener offers several valuable benefits for social publishing.
Condenses long and complex URLs into more visually appealing, concise, and memorable links.
Analytics and tracking capabilities, allowing you to monitor link performance, engagement, and audience insights.
Save valuable character space, especially on platforms like Twitter where character limits are stringent.
Add a custom link domain with your own url.
## Custom Link Domain
A custom link domain allows you to personalize and brand the domain name used for link shortening and redirection.
Instead of using a generic link shortener domain (e.g., bit.ly, ayr.app), a custom link domain allows you to use own domain name to create shortened links.
Please contact us to set up your custom domain. Available on Business and Enterprise plans.
# Update Short Link
Source: https://www.ayrshare.com/docs/apis/links/update-short-link
PUT /links/:id
Update the destination URL of an existing short link
Update the destination URL of an existing short link. The short link ID is returned when you first create a short link via `POST /links`.
**Social Media Preview Caching:** Social media platforms cache Open Graph preview cards from the original destination URL. After updating a short link, the preview card shown on social platforms may not match the new destination until the cache expires.
## Header Parameters
## Path Parameters
The short link ID returned from `POST /links` (e.g., "TkuWEy").
## Body Parameters
The new destination URL. Must be a valid URL starting with https\://
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"url": "https://www.new-destination.com"}' \
-X PUT https://api.ayrshare.com/api/links/TkuWEy
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/links/TkuWEy", {
method: "PUT",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
url: "https://www.new-destination.com", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'url': 'https://www.new-destination.com'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.put('https://api.ayrshare.com/api/links/TkuWEy',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
require 'vendor/autoload.php';// Composer auto-loader using Guzzle. See .../guzzlephp.org/en/stable/overview.html
$client = new GuzzleHttp\Client();
$res = $client->request(
'PUT',
'https://api.ayrshare.com/api/links/TkuWEy',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'json' => [
'url' => 'https://www.new-destination.com',
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "TkuWEy",
"originalUrl": "https://www.new-destination.com",
"shortUrl": "https://ayrs.io/TkuWEy",
"created": "2023-07-17T15:20:51.118Z",
"updated": "2024-01-10T12:30:00.000Z"
}
```
```json 400: Invalid URL Format theme={"system"}
{
"action": "request",
"status": "error",
"code": 126,
"message": "Shorten URL failed. Please verify the URL is properly formatted and the correct UTM parameters are used."
}
```
```json 404: Link Not Found theme={"system"}
{
"action": "link",
"status": "error",
"code": 418,
"message": "Link not found or not owned by user."
}
```
# Get Brand Data
Source: https://www.ayrshare.com/docs/apis/listen/brand-user
GET /brand/byUser
Get a social account information by a user name
This endpoint allows you to retrieve information about any public social media profile, even if that
profile is not linked to your Ayrshare account. This feature is available for Bluesky, Facebook, Instagram, LinkedIn,
X, and YouTube.
For profiles that are linked to your Ayrshare account, we recommend using the [/analytics](/docs/apis/analytics/social) endpoint instead, as it provides more detailed analytics.
Important: To search for a profile on a specific social platform, your Ayrshare account must have that social network linked.
For example, to search for any Instagram profile, e.g. `@taylorswift`, you must have Instagram linked to your Ayrshare account.
The searched account must be public to access the data. Private social accounts are not available.
Location data is only available for business with public locations.
Tagging a location in Facebook or Instagram requires an available location.
## Header Parameters
## Query Parameters
String array of platforms: `bluesky` ,`instagram`, `facebook`, `linkedin`, `twitter`, or
`youtube`.
Bluesky handle URL encoded. For example: "@ayrshare" or "ayrshare". Required if "bluesky" in
`platforms` array.
Facebook Page name URL encoded. For example "@newyorkgiants" or "newyorkgiants".
Facebook personal accounts are not permitted by Facebook.
Required if "facebook" in `platforms` array.
Instagram handle URL encoded. For example: "@nygiants" or "nygiants".
Note: Only Instagram Business and Creator accounts can be returned.
Required if "instagram" in `platforms` array.
LinkedIn company (organization) vanity name such as `Linkedin` or `linkedin-marketing-solutions`.
You can also look up a person using their LinkedIn person ID retrieved from the history endpoint, i.e. people who liked
a post. An example ID: `urn:li:person:Z_yXaxh_Et`
Required if "linkedin" in `platforms` array.
Twitter handle URL encoded. For example: "@ayrshare" or "ayrshare".
Required if "twitter" in `platforms` array.
YouTube username URL encoded, channel ID, or playlist ID. Note, channel IDs typically begin with
"UC" and playlist IDs begin with "PL". For example, send the username "MelissaEtheridgeVEVO" or
the channel ID as "UCpSUQewzOXg1F0zLmieKCqQ".
You may also use the YouTube handle found in the YouTube URL.
For example, the handle for [https://www.youtube.com/@mkbhd](https://www.youtube.com/@mkbhd) is "@mkbhd".
Be sure to keep the `@` symbol to designate the handle.
Required if "youtube" in `platforms` array.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/brand/byUser?platforms[0]=instagram&platforms[1]=twitter&twitterUser=ayrshare&instagramUser=nygiants
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch(
"https://api.ayrshare.com/api/brand/byUser?platforms[0]=instagram&platforms[1]=twitter&twitterUser=ayrshare&instagramUser=nygiants",
{
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`
}
}
)
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/brand/byUser?platforms[0]=instagram&platforms[1]=twitter&twitterUser=ayrshare&instagramUser=nygiants', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$apiUrl = 'https://api.ayrshare.com/api/brand/byUser?platforms[0]=instagram&platforms[1]=twitter&twitterUser=ayrshare&instagramUser=nygiants';
$apiKey = 'API_KEY'; // Replace 'API_KEY' with your actual API key
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
];
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace BrandByUserGETRequest_csharp
{
class BrandByUser
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/brand/byUser?platforms[0]=instagram&platforms[1]=twitter&twitterUser=ayrshare&instagramUser=nygiants";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var response = await client.GetStringAsync(url);
Console.WriteLine(response);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"bluesky": {
"avatar": "https://cdn.bsky.app/img/avatar/plain/did:plc:62musrcyanhro2lydyhlw7ci/bafkreiegtpqhpwgu6tww2ejsdil4ew3blmt6jh3wlq6zhanxo3wj2ib4du@jpeg",
"description": "Ayrshare's Social APIs provide the core infrastructure for social media posting, management, and analytics.",
"displayName": "Ayrshare",
"handle": "ayrshare.com",
"id": "did:plc:62musrcyanhro2lydyhlw7ci",
"indexedAt": "2024-11-29T21:13:18.046Z"
},
"facebook": {
"about": "We invite you to wonder. ",
"description": "Frank Lloyd Wright's architectural masterpiece home to a world-renowned collection of modern and contemporary art.",
"fanCount": 845048,
"followersCount": 874337,
"id": "7640348500",
"isUnclaimed": false, // whether a Facebook Page that was automatically generated has been claimed by the business it represents.
"link": "https://www.facebook.com/7640348500",
"location": {
"city": "New York",
"country": "United States",
"latitude": 40.782910059774,
"longitude": -73.959075808525,
"state": "NY",
"street": "1071 5th Ave",
"zip": "10128"
},
"name": "Solomon R. Guggenheim Museum",
"picture": {
"data": {
"height": 50,
"isSilhouette": false,
"url": "https://scontent.ford4-1.fna.fbcdn.net/v/t39.30808-1/352122020_2000703126929355_7618417261219676343_n.jpg?stp=cp0_dst-jpg_p50x50&_nc_cat=104&ccb=1-7&_nc_sid=4da83f&_nc_ohc=Y1AlQn-HyvwAX8NzExq&_nc_ht=scontent.ford4-1.fna&edm=AJdBtusEAAAA&oh=00_AfD7ms2Nv0b5x1jr_uJKZsXnngQP3dmDrjQDNz_4aaBrCg&oe=65D3ACAE",
"width": 50
}
},
"username": "guggenheimmuseum",
"verificationStatus": "blue_verified", // The verification status of the Facebook Page that represents a business, blue_verified or not_verified.
"website": "http://www.guggenheim.org/"
},
"instagram": {
"biography": "4x Super Bowl Champions #TogetherBlue",
"followersCount": 2278171,
"followsCount": 228,
"id": "17841400118294090", // Instagram Id
"igId": 261763943,
"mediaCount": 8965,
"name": "New York Giants",
"profilePictureUrl": "https://scontent-lga3-2.xx.fbcdn.net/v/t51.2885-15/209249968_563247608171409_1254577321735891919_n.jpg?_nc_cat=1&ccb=1-5&_nc_sid=86c713&_nc_ohc=T673IyEiuasAX_Jj7xu&_nc_ht=scontent-lga3-2.xx&edm=AL-3X8kEAAAA&oh=00_AT8GNdOos4riN7NhrI06a6TkVKgOf5p_RUlsOQUwPRW3VQ&oe=6247F2F0",
"username": "nygiants",
"website": "http://nygnt.co/vgle2"
},
// LinkedIn using the username or handle
"linkedin": {
"localizedName": "LinkedIn",
"name": {
"localized": {
"it_IT": "LinkedIn",
"ru_RU": "LinkedIn",
"pl_PL": "LinkedIn",
"ro_RO": "LinkedIn",
"sv_SE": "LinkedIn"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"id": 1337,
"vanityName": "linkedin",
"organizationType": "PUBLIC_COMPANY",
"locations": [
{
"locationType": "HEADQUARTERS",
"address": {
"geographicArea": "CA",
"country": "US",
"city": "Sunnyvale",
"line1": "1000 W Maude",
"postalCode": "94085"
},
"streetAddressFieldState": "UNSET_OPT_OUT",
"geoLocation": "urn:li:geo:106316449",
"staffCountRange": "SIZE_1"
},
{
"locationType": "OTHER",
"address": {
"geographicArea": "Community of Madrid",
"country": "ES",
"city": "Madrid",
"postalCode": "28046"
},
"streetAddressFieldState": "OPT_OUT",
"geoLocation": "urn:li:geo:106809575",
"staffCountRange": "SIZE_1"
},
{
"locationType": "OTHER",
"address": {
"geographicArea": "ON",
"country": "CA",
"city": "Toronto",
"postalCode": "M5J 2Z2"
},
"streetAddressFieldState": "OPT_OUT",
"geoLocation": "urn:li:geo:108528311",
"staffCountRange": "SIZE_1"
}
],
"specialties": [
{
"locale": {
"country": "US",
"language": "en"
},
"tags": [
"Online Professional Network",
"Jobs",
"People Search",
"Company Search",
"Address Book",
"Advertising",
"Professional Identity",
"Group Collaboration",
"Recruiting"
]
}
],
"website": "https://careers.linkedin.com",
"description": "Founded in 2003, LinkedIn connects the world's professionals to make them more productive and successful. With more than 1 billion members worldwide, including executives from every Fortune 500 company, LinkedIn is the world's largest professional network. The company has a diversified business model with revenue coming from Talent Solutions, Marketing Solutions, Sales Solutions and Premium Subscriptions products. Headquartered in Silicon Valley, LinkedIn has offices across the globe..",
"media": {
"mediaUrl": "https://media.licdn.com/dms/image/C560BAQHaVYd13rRz3A/company-logo_400_400/0/1638831590218/linkedin_logo?e=1723680000&v=beta&t=gOk8XZWklJyh3O7qcgWRluAgbt8whoV8Kr9B0E74xYI",
"id": "urn:li:digitalmediaAsset:C560BAQHaVYd13rRz3A",
"mediaExpiresSeconds": 1723680000000
},
"lastUpdated": "2024-05-15T20:42:09.417Z",
"nextUpdate": "2024-05-15T20:53:09.417Z"
},
// LinkedIn using a person ID.
"linkedin": {
"from": {
"name": "John Doe",
"id": "Z_yXaxh",
"url": "https://www.linkedin.com/in/johndoe",
"description": "Founder"
},
"media": {
"id": "urn:li:image:C5103AQHORT70jVfKVA",
"mediaExpiresSeconds": 1728518400000,
"url": "https://media.licdn.com/dms/image/v2/C5103AQHORT70jVfKVA/profile"
},
"platform": "linkedin",
"profileImageUrl": "https://media.licdn.com/dms/image/v2/C5103AQHORT70jVfKVA/profile",
"userName": "johndoe"
},
"twitter": {
"createdAt": "2017-10-04T15:26:17.000Z",
"description": "Ayrshare's APIs provide the core infrastructure for social media posting, management, and analytics. https://t.co/UlcRGcg1X9",
"id": "92839209304423",
"location": "New York, NY",
"name": "Ayrshare",
"profileImageUrl": "https://pbs.twimg.com/profile_images/1423334467389767680/ochnivwr_normal.jpg",
"publicMetrics": {
"followersCount": 5361,
"followingCount": 39,
"tweetCount": 844,
"listedCount": 5
},
"url": "https://t.co/UlcRGcg1X9",
"username": "Ayrshare"
},
"youtube": {
"created": "2009-05-12T05:28:43Z",
"description": "",
"hiddenSubscriberCount": false,
"isLinked": true,
"longUploadsStatus": "longUploadsUnspecified",
"madeForKids": false,
"playlistId": "UU-0dv2mN6SeXwkEKtfKXJnQ",
"privacyStatus": "public",
"subscriberCount": "28200",
"thumbnailUrl": "https://yt3.ggpht.com/OwargtIRcXzB7jlHWgCmitNo-6JX2wbZGdOMg5K7rd5BnX4bSJX1WPaD2Bi4RN3X9SJi4D4h4g=s88-c-k-c0x00ffffff-no-nd-rj",
"title": "MelissaEtheridgeVEVO",
"url": "https://www.youtube.com/c/@MelissaEtheridgeVEVO",
"videoCount": "43",
"viewCount": "29872467"
}
}
```
```json 400: Bad Request Error theme={"system"}
{
"status": "error",
"code": 187,
"instagram": {
"action": "analytics",
"status": "error",
"code": 294,
"message": "Error getting analytics. The user with username: whoblhablah cannot be found.",
"platform": "instagram"
},
"twitter": {
"action": "analytics",
"status": "error",
"code": 294,
"message": "Error getting analytics. Could not find user with username: [NoDonkdfjkd]."
},
"linkedin": {
"action": "analytics",
"status": "error",
"code": 294,
"message": "Error getting analytics.",
"details": "No LinkedIn organization found for linkedinfdfd"
}
}
```
# Search Tweets by Keyword
Source: https://www.ayrshare.com/docs/apis/listen/keyword/search-tweets
GET /listen/keyword
Search X/Twitter for tweets matching keywords or hashtags
Search X/Twitter for tweets matching keywords, hashtags, and advanced search operators. Returns normalized tweet data including user info, engagement metrics, and entities.
This endpoint requires [Bring Your Own Keys (BYOK)](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for X/Twitter.
**Important Limitations**
* Only tweets from the last \~7 days are available (X API limitation).
* Default daily limit of 25 calls.
* BYOK keys for X/Twitter are required.
## Header Parameters
## Query Parameters
Keyword search query. Supports X/Twitter search operators (see table below).
Examples: `ayrshare`, `#socialmedia`, `ayrshare OR #socialmedia`, `from:ayrshare`.
Must be `twitter`.
Maximum number of tweets to return. Must be between 10 and 100.
Returns tweets with an ID greater than (newer than) this value. Useful for fetching only new tweets since a previous request.
Returns tweets with an ID less than (older than) this value. Useful for paginating backwards through results.
Pagination token from a previous response's `meta.pagination.next`. Use this to fetch the next page of results.
## Search Operators
The `query` parameter supports the following X/Twitter search operators:
| Operator | Description | Example |
| --------- | ----------------------------------------- | ------------------------- |
| `AND` | Both terms must appear (default behavior) | `social AND media` |
| `OR` | Either term must appear | `ayrshare OR socialmedia` |
| `from:` | Tweets from a specific user | `from:ayrshare` |
| `to:` | Tweets directed at a specific user | `to:ayrshare` |
| `#` | Match a hashtag | `#socialmedia` |
| `@` | Match a mention | `@ayrshare` |
| `-` | Exclude a term | `social -spam` |
| `lang:` | Filter by language | `ayrshare lang:en` |
| `filter:` | Filter by content type | `ayrshare filter:links` |
| `url:` | Match a URL | `url:ayrshare.com` |
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H "x-twitter-oauth1-api-key: YOUR_TWITTER_API_KEY" \
-H "x-twitter-oauth1-api-secret: YOUR_TWITTER_API_SECRET" \
-X GET "https://api.ayrshare.com/api/listen/keyword?query=ayrshare%20OR%20%23socialmedia&platform=twitter&limit=15"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch(
"https://api.ayrshare.com/api/listen/keyword?query=ayrshare%20OR%20%23socialmedia&platform=twitter&limit=15",
{
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`,
"x-twitter-oauth1-api-key": "YOUR_TWITTER_API_KEY",
"x-twitter-oauth1-api-secret": "YOUR_TWITTER_API_SECRET"
}
}
)
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {
'Authorization': 'Bearer API_KEY',
'x-twitter-oauth1-api-key': 'YOUR_TWITTER_API_KEY',
'x-twitter-oauth1-api-secret': 'YOUR_TWITTER_API_SECRET'
}
params = {
'query': 'ayrshare OR #socialmedia',
'platform': 'twitter',
'limit': 15
}
r = requests.get('https://api.ayrshare.com/api/listen/keyword', headers=headers, params=params)
print(r.json())
```
```json 200: Success theme={"system"}
{
"status": "success",
"platform": "twitter",
"query": "ayrshare OR #socialmedia",
"tweets": [
{
"id": "1234567890",
"text": "Just discovered @ayrshare for managing social media APIs!",
"createdAt": "2026-03-22T14:30:00.000Z",
"user": {
"id": "987654321",
"name": "Jane Doe",
"screenName": "janedoe",
"profileImageUrl": "https://pbs.twimg.com/profile_images/..."
},
"metrics": {
"retweetCount": 5,
"favoriteCount": 12
},
"entities": {
"hashtags": ["socialmedia"],
"mentions": ["ayrshare"],
"urls": []
},
"inReplyToStatusId": null,
"isRetweet": false,
"lang": "en"
}
],
"meta": {
"pagination": {
"hasMore": true,
"next": "b26v89c19zqg8o3fpds7h...",
"limit": 15
}
}
}
```
```json 400: Bad Request theme={"system"}
{
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs.",
"details": "The 'query' parameter is required."
}
```
```json 401: Unauthorized theme={"system"}
{
"status": "error",
"code": 401,
"message": "Unauthorized. BYOK keys for X/Twitter are required.",
"details": "Please set up your X/Twitter API keys. See https://docs.ayrshare.com/dashboard/connect-social-accounts/x-twitter-byo-keys"
}
```
```json 429: Rate Limit Exceeded theme={"system"}
{
"status": "error",
"code": 429,
"message": "Rate limit exceeded. Daily limit of 25 keyword search calls reached.",
"details": "Please try again tomorrow or contact support for higher limits."
}
```
# Listen API: Social Media Monitoring & Mentions | Ayrshare Docs
Source: https://www.ayrshare.com/docs/apis/listen/overview
The Ayrshare Listen API monitors social media for keywords, hashtags, and mentions in real time to track brand conversations, sentiment, and trends.
Look up users' or companies' social media public information, such as followers, profile image, and websites for competitive analysis.
Although you still need to have a linked social account, these users and companies that you look up do not need to be a linked Ayrshare user.
Also search for Facebook Page and LinkedIn Member Profiles, often used for typeahead mention completion.
If your users have linked their social accounts, use the [/analytics](/docs/apis/analytics/social) endpoint for more detailed information.
# Search Facebook Pages
Source: https://www.ayrshare.com/docs/apis/listen/search/fb-page-search
GET /brand/search/facebook
Search for Facebook Pages based on a search query
Search for Facebook Pages based on a search query.
Often used for typeahead mention completion.
The response is an array of objects with the id, link, name, and location of the Page.
The `location` field will only be returned for Pages with public locations.
## Header Parameters
## Query Parameters
Search query to find Facebook pages by name.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/brand/search/facebook?search=facebook
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/brand/search/facebook?search=facebook", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/brand/search/facebook?search=facebook', headers=headers)
print(r.json())
```
```json 200: Success theme={"system"}
{
"facebook": [
{
"id": "7640348500",
"isUnclaimed": false,
"link": "https://www.facebook.com/7640348500",
"location": {
"city": "New York",
"country": "United States",
"latitude": 40.782910059774,
"longitude": -73.959075808525,
"state": "NY",
"street": "1071 5th Ave",
"zip": "10128"
},
"name": "Solomon R. Guggenheim Museum",
"verificationStatus": "blue_verified"
}
]
}
```
# Search LinkedIn
Source: https://www.ayrshare.com/docs/apis/listen/search/linkedin-search
GET /brand/search/linkedin
Search for LinkedIn companies or people
Search for LinkedIn companies or people based on a search query.
This endpoint is commonly used for typeahead mention completion in social media posts.
**The linked account must be a LinkedIn company page to search.** Personal LinkedIn accounts can not be used to perform searches.
1. **For mentions in posts**: When implementing @mentions, use this endpoint with typeahead functionality.
2. **Company search**: The exact company vanity name is required.
3. **Person search**: Start with at least 3 characters of a name for best results.
4. **Rate limiting**: This endpoint follows standard API rate limits.
**Search Limitations**
**Companies**: You can search for any LinkedIn company page
**People**: You can only search for people who are followers of your LinkedIn account and the
Ayrshare linked account must be a LinkedIn company page to perform the search. If a person has
their LinkedIn visibility set to private, they will not be found in the search results.
## Header Parameters
## Query Parameters
Search query to find LinkedIn companies or people.
**Requirements:**
Minimum length: 3 characters for people and 1 character for companies.
Maximum length: 100 characters for both people and companies.
**Search behavior:**
For companies: Use the company's vanity name (found in the LinkedIn URL). Only **exact vanity name matches** will be returned.
Example: For `linkedin.com/company/ayrshare`, search for "ayrshare".
Searching for partial names like "ayrsh" will NOT return results.
For people: Use first name and/or last name. Partial name matches are supported.
Example: "John Smith" will find people named John Smith. Be sure to URL encode the space.
Partial matches like "Joh" or "Smi" will also return results.
Remember: Only your LinkedIn followers can be found and the Ayrshare linked account must be a LinkedIn company page to perform the search
Controls the search scope: - `false` (default): Searches for companies first, then people if no
companies are found. - `true`: Searches only for people (skips company search entirely).
## Examples
```bash Company Search theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/brand/search/linkedin?search=ayrshare"
```
```bash Person Search Only theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/brand/search/linkedin?search=John%20Smith&personOnly=true"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
// Search for company or person
fetch("https://api.ayrshare.com/api/brand/search/linkedin?search=ayrshare", {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
// Search for person only
fetch("https://api.ayrshare.com/api/brand/search/linkedin?search=John%20Smith&personOnly=true", {
method: "GET",
headers: {
Authorization: `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
# Search for company or person
r = requests.get('https://api.ayrshare.com/api/brand/search/linkedin?search=ayrshare', headers=headers)
print(r.json())
# Search for person only
r = requests.get('https://api.ayrshare.com/api/brand/search/linkedin?search=john&personOnly=true', headers=headers)
print(r.json())
```
```json Company Search Result theme={"system"}
{
"linkedin": [
{
"vanityName": "ayrshare",
"website": "https://www.ayrshare.com",
"groups": [],
"description": "Ayrshare's APIs provide the core infrastructure for social media posting, management, and analytics.\n\nThe Ayrshare API takes care of the social media infrastructure so you don't have to. Your team can focus on building your product instead of stitching together and maintaining multiple social media platforms.\n\nPost to Facebook, Twitter, Instagram, LinkedIn, Reddit, Telegram, TikTok, Google My Business, and YouTube.\n",
"defaultLocale": {
"country": "US",
"language": "en"
},
"organizationType": "PARTNERSHIP",
"alternativeNames": [],
"specialties": [
"social media",
"api",
"saas",
"social networks",
"tiktok",
"facebook",
"instagram"
],
"staffCountRange": "SIZE_10_TO_100",
"name": "Ayrshare",
"primaryOrganizationType": "NONE",
"locations": [
{
"description": {
"localized": {
"en_US": "Headquarters"
},
"preferredLocale": {
"country": "US",
"language": "en"
}
},
"locationType": "HEADQUARTERS",
"address": {
"geographicArea": "New York",
"country": "US",
"city": "New York",
"line1": "142 W 57th St",
"postalCode": "10019"
},
"localizedDescription": "Headquarters",
"streetAddressFieldState": "UNSET_OPT_OUT",
"geoLocation": "urn:li:geo:103963738"
}
],
"id": 66755333
}
]
}
```
```json Person Search Result theme={"system"}
{
"linkedin": [
{
"lastName": "Smith",
"firstName": "John",
"headline": "CTO at Ayrshare",
"id": "urn:li:person:WBwF1C23L"
}
]
}
```
```json 400: Search query too short theme={"system"}
{
"linkedin": {
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. https://www.ayrshare.com/docs/apis",
"details": "The search must be a string between 3 and 100 characters."
}
}
```
```json 404: No results found theme={"system"}
{
"linkedin": []
}
```
# Get All Media in Gallery
Source: https://www.ayrshare.com/docs/apis/media/get-media-in-gallery
GET /media
Retrieve all the images and videos uploaded to the gallery
Retrieve all the images uploaded to the image gallery including resized images.
## Header Parameters
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer [API Key]" \
-X GET https://api.ayrshare.com/api/media
```
```javascript JavaScript theme={"system"}
const API_KEY = "Your API Key";
fetch("https://api.ayrshare.com/api/media", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer [API_KEY]'}
r = requests.get('https://api.ayrshare.com/api/media', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'GET',
'https://api.ayrshare.com/api/media',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace MediaGETRequest_csharp
{
class Media
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/media";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```javascript 200: Array of images in the image gallery theme={"system"}
[
{
"id": "5553a26a-cffb-4a31-bd89-dee296d35648-jpeg",
"timeCreated": "2025-07-30T20:23:49.774Z",
"size": "223340",
"url": "https://images.ayrshare.com/LW8kx9Q5smXeJl5CujF7DxFAF1q1/5553a26a-cffb-4a31-bd89-dee296d35648.jpeg",
"fileName": "test1.jpeg",
"description": "Test1",
"expiresAt": "2025-09-05T22:00:48.000Z" // The date and time the media will expire
},
{
"id": "93383cc7-7a15-4d16-a5fa-fdda1f9bebe2-jpeg",
"timeCreated": "2025-07-30T20:24:57.421Z",
"size": "223340",
"url": "https://images.ayrshare.com/LW8kx9Q5smXeJl5CujF7DxFAF1q1/93383cc7-7a15-4d16-a5fa-fdda1f9bebe2.jpeg",
"fileName": "test2.jpeg",
"description": "Test2",
"expiresAt": "2025-09-05T22:00:48.000Z" // The date and time the media will expire
}
]
```
# Metadata on a media file
Source: https://www.ayrshare.com/docs/apis/media/get-media-metadata
GET /media/meta
Get the metadata on a media file URL
Retrieve the metadata on a media file URL to check format, dimensions, and other details.
## Header Parameters
## Query Parameters
Encoded URI of the externally accessible media file URL.
```json 200: Success theme={"system"}
{
"codec": "h264",
"duration": 28.24, // In seconds
"filename": "https://img.ayrshare.com/random/landscape16.mp4",
"format": "QuickTime / MOV",
"height": 1080,
"size": 16275959, // In bytes
"type": "video",
"width": 1920
}
```
```json 400: Bad media URL theme={"system"}
{
"action": "post",
"status": "error",
"code": 229,
"message": "Error validating video. Please check the video or URL."
}
```
# Media API Overview
Source: https://www.ayrshare.com/docs/apis/media/overview
Upload and manage your images and videos.
Manage your image and video gallery by uploading and retrieving images and videos. Please be sure to verify the media URL before using it to post.
If you already have your media accessible by an external URL, such as an S3 bucket, you can skip uploading the files to Ayrshare. Just POST to the `/post` endpoint with your externally accessible URL in the `mediaURLs` body parameter and your file will automatically be uploaded.
# Resize an Image
Source: https://www.ayrshare.com/docs/apis/media/resize
POST /media/resize
Resize an image to social media dimensions, add watermarks, or crop
The social networks have [specific requirements](/docs/media-guidelines) for social media images. The resize endpoint allows you to choose a social network compatible image size, add watermarks, change backgrounds, add effects, crop, and more.
By default resizing will change the dimensions of an image, but not crop the image. You may instead crop the image. See below for details.
## Header Parameters
## Body Parameters
URL of image to be resized. Must begin with `https://`
Social media platform for which the URL will be resized. See [platform
options](/docs/apis/media/resize#platform-options) for details.
Send the media file as a multipart form-data object. Required if `imageUrl` not present.
URL and optional position of watermark to be applied to resized image. The watermark will appear
in the lower right corner of the image by default. See [watermark](/docs/apis/media/resize#watermark)
for details.
Change opacity, colors, etc. See [effects options](/docs/apis/media/resize#effects-options) for
details.
Object specifying `width` and `height` for resizing. If cropping, you may optionally specify the center `x` and `y` coordinates.
Default is the center of the image.
```json Dimensions theme={"system"}
{
"width": 500,
"height": 500,
"xCoordinate": 35, // optional for crop mode
"yCoordinate": 50 // optional for crop mode
}
```
Width and height required if platform is not specified.
Value: `resize`, `blur`, or `crop`. See [mode](/docs/apis/media/resize#mode) for details.
Automatically convert to a JPG file, such as from a PNG to a JPG file. 75% quality will be used.
See [convert to a JPG](/docs/apis/media/resize#convert-to-a-jpg-or-webp) for details.
Automatically convert to a WebP file, such as from a PNG to a WebP file. 75% quality will be used.
See [convert to a WebP](/docs/apis/media/resize#convert-to-a-jpg-or-webp) for details.
### Platform Options
Specify a platform as a String to use predefined dimensions of the image, or you may specify your own with the `dimensions` field.
For example `"platform": "facebook"` will set the dimension of the image as width 1200px and height 630px.
Note, that resize to these dimensions will not crop the image.
If you want to crop the image, you can use the `mode` parameter set to `crop` with the `dimensions` and `xCoordinate` and `yCoordinate` fields.
### Mode
#### Resize
Resize is the default mode that will change the dimensions of an image while maintaining its aspect ratio.
Resize the image to the specified dimensions without cropping any content.
Example JSON:
```json Resize theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"platform": "instagram",
"mode": "resize"
}
```
You can also specify custom dimensions using the `dimensions` field:
```json Resize with Dimensions theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"mode": "resize",
"dimensions": {
"width": 800,
"height": 600
}
}
```
Either the `platform` or the dimensions field `width` and `height` must be specified.
#### Crop
Crop will cut off "crop" the image to the specified dimensions. By default the center coordinate will be the center of the image. You may also specify your own x/y coordinates.
Example JSON:
```json Crop theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"platform": "instagram",
"mode": "crop"
}
```
You can also specify custom dimensions and optional crop coordinates using the `dimensions` field:
```json Crop with Dimensions theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"mode": "crop",
"dimensions": {
"width": 1080,
"height": 1080,
"xCoordinate": 35,
"yCoordinate": 50
}
}
```
Either the `platform` or the dimensions field `width` and `height` must be specified.
For square crops, if `width` or `height` are less than the dimensions of the provided image, the small of the `width` or `height` will be used. For example, if the image is 1200x800 and the crop requested is 1080x1080, the image returned will be 800x800.
#### Blur
Blur effect will duplicate the image as a background and blur the image.
Example blur JSON:
```json Blur theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"platform": "instagram",
"mode": "blur"
}
```
Example blur image:
### Watermark
#### Watermark Overview
You may add a watermark to the image by providing a URL, which must begin with `https://` and an optional position.
The watermark will by default appear in the bottom right corner of the image - `southeast`.
We recommend a PNG with a transparent background.
Example watermark JSON:
```json Watermark theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/random/photo-13.jpg",
"platform": "instagram",
"watermark": {
"url": "https://img.ayrshare.com/012/100-percent.png",
"position": "northeast" // optional
}
}
```
Example watermark image in southeast position:
#### Watermark Position
The position of the watermark can be one of the following:
`north`
`northeast`
`east`
`southeast`
`south`
`southwest`
`west`
`northwest`
`center`
### Effects Options
#### Color Hexadecimal
Hexadecimal value for color of background for blur. Only applicable if `"mode": "blur"`. String value, e.g. `"#A020F0"`
Example color background JSON:
```json Color Background theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg",
"platform": "instagram",
"mode": "blur",
"effects": {
"color": "#A020F0"
}
}
```
Example color background image:
#### Color: Grayscale, Sepia, Invert
You made change the primary image color by specifying `grayscale`, `sepia`, or `invert`. The field `"blur": true` is not required and should not be used if you do not want a background.
Example grayscale JSON:
```json Grayscale theme={"system"}
{
"mediaUrl": "https://img.ayrshare.com/random/photo-13.jpg",
"platform": "instagram",
"effects": {
"color": "grayscale"
}
}
```
Example grayscale image:
#### Opacity
Set the opacity of the image. Number value range: 0 - 1.
Example opacity JSON:
```json Opacity theme={"system"}
{
"effects": {
"opacity": 0.2
}
}
```
#### Quality
For JPG or JEPG images specify the quality, or amount of compression, of the image.
The lower the number the more compressed, but lower the image quality.
The higher the number the less compressed, but the higher the image quality. Number value range: 0 - 100.
Example quality JSON:
```json Quality theme={"system"}
{
"effects": {
"quality": 20
}
}
```
### Convert to a JPG or WebP
The `convertToJpg` and `convertToWebP` options allow you to transform images from their original format (such as PNG) to JPG or WebP format respectively.
By default, the converted images will have a quality setting of 75%.
You can customize the compression level by using the [quality](/docs/apis/media/resize#quality) parameter in the effects object.
Note that if your source image is already a JPG and you use `convertToJpg`, the API will simply resize the image to your specified dimensions without changing the format.
Example convert to JPG:
```json Convert to JPG theme={"system"}
{
"convertToJpg": true
}
```
Example convert to WebP:
```json Convert to WebP theme={"system"}
{
"convertToWebP": true
}
```
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"mediaUrl": "https://img.ayrshare.com/012/gb.jpg", "platform": "instagram"' \
-X POST https://api.ayrshare.com/api/media/resize
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/media/resize", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
mediaUrl: "https://img.ayrshare.com/012/gb.jpg", // required
platform: "instagram"
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'mediaUrl': 'https://img.ayrshare.com/012/gb.jpg',
'platforms': 'instagram'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/media/resize',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"https://img.ayrshare.com/012/gb.jpg",
"platforms" => "instagram"
);
curl_setopt_array($curl, array(
CURLOPT_URL => 'https://api.ayrshare.com/api/media/resize',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => '',
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 0,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => 'POST',
CURLOPT_POSTFIELDS => http_build_query($data),
CURLOPT_HTTPHEADER => array(
'Authorization: Bearer API_KEY',
'Accept-Encoding: gzip'
),
));
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
public class AyrshareApiClient
{
private readonly HttpClient _httpClient;
private readonly string _apiKey;
private const string BaseUrl = "https://api.ayrshare.com/api";
public AyrshareApiClient(string apiKey)
{
_apiKey = apiKey ?? throw new ArgumentNullException(nameof(apiKey));
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("Authorization", $"Bearer {_apiKey}");
}
public async Task ResizeMediaAsync(string mediaUrl, string platform)
{
try
{
var requestData = new
{
mediaUrl = mediaUrl,
platform = platform
};
var content = new StringContent(
JsonSerializer.Serialize(requestData),
Encoding.UTF8,
"application/json"
);
var response = await _httpClient.PostAsync($"{BaseUrl}/media/resize", content);
response.EnsureSuccessStatusCode();
var jsonResponse = await response.Content.ReadAsStringAsync();
return jsonResponse;
}
catch (HttpRequestException ex)
{
throw new Exception($"Failed to resize media: {ex.Message}", ex);
}
}
public void Dispose()
{
_httpClient.Dispose();
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"url": "https://media.ayrshare.com/9abf1426d6ce9122ef11c72bd62e59807c5cc083/8UbyBjHTxgHkAC1I37e6O.jpg",
"platform": "instagram",
"mode": "blur",
"effects": {
"color": "#A020F0"
}
}
```
```json 400: Failed Resize theme={"system"}
{
"action": "resize",
"status": "error",
"code": 312,
"message": "Invalid extension type. Extension: null. Please verify the extension is one of the following: png, jpg, jpeg and the file is accessible."
}
```
# Upload Large Media Files
Source: https://www.ayrshare.com/docs/apis/media/upload-large-media
GET /media/uploadUrl
For file uploads greater than 10 MB, obtain a presigned URL to upload a file
For file uploads greater than 10 MB, obtain a presigned URL to upload a file.
Maximum file upload size 5 GB.
Upload presigned URL valid for 30 minutes after being generated.
Access URL available for 30 days after uploaded. All published posts are unaffected at the
social networks. Scheduled posts beyond that time frame will result in errors at time of
publishing.
If you already have your media accessible by an external URL, such as an S3 bucket, you can skip uploading the files to Ayrshare. Just POST to the `/post` endpoint with your externally accessible URL in the `mediaURLs` body parameter and your file will automatically be uploaded.
## Header Parameters
## Query Parameters
If the contentType is not present, then a full file name with extension is required.
Name of the file to be uploaded. Must include an extension such as .png, .jpg, .mov, .mp4, etc.
The content-type of the media being uploaded. Valid formats include: `mp4`, `mov`, `png`, `jpg`, or `jpeg`.
For example, if the file is a Quicktime .mov file, then the contentType should be `mov`.
If not present, application/octet-stream will be used.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer [API Key]" \
-X GET https://api.ayrshare.com/api/media/uploadUrl?fileName=test.mov&contentType=mov
```
```javascript JavaScript theme={"system"}
const API_KEY = "Your API Key";
fetch("https://api.ayrshare.com/api/media/uploadUrl?fileName=test.mov&contentType=mov", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer [API_KEY]'}
r = requests.get('https://api.ayrshare.com/api/media/uploadUrl?fileName=test.mov&contentType=mov', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'GET',
'https://api.ayrshare.com/api/media/uploadUrl?fileName=test.mov&contentType=mov',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace MediaUploadUrlGETRequest_csharp
{
class MediaUploadUrl
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string baseUrl = "https://api.ayrshare.com/api/media/uploadUrl";
// Build URL with query parameters
var uriBuilder = new UriBuilder(baseUrl);
var query = HttpUtility.ParseQueryString(string.Empty);
query["fileName"] = "test.mov";
query["contentType"] = "mov";
uriBuilder.Query = query.ToString();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(uriBuilder.Uri);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
## Response Details
`accessUrl` is the URL to access the media file after upload.
`contentType` is the content-type set for the media being upload. Use this in the *Content-Type*
header when uploading the media.
`uploadUrl` is the URL used to *PUT* the media file. Please see below.
### Additional Endpoint Examples
The process to upload larger files:
Obtain an `uploadURL` and `accessURL` via the `/media/uploadUrl` endpoint. Please see above.
Upload the file via a *PUT* with *Content-Type* set to the returned `contentType`.
Upload the media by using the `--upload-file` with a media file and the `uploadUrl`.
On a successful upload, a `200` response will be returned.
After uploading the media file, POST to the `/post` endpoint with the `accessUrl` in the
`mediaUrls` body parameter.
**The presigned upload URL may only be uploaded to once**. If you sent a bad file you must
create a new upload URL. No error response will occur if the file is not successfully uploaded.
See below of [verifying the URL exists](/docs/apis/media/verify-media-url).
```bash cURL theme={"system"}
curl -X PUT \
-H 'Content-Type: video/mp4' \
--upload-file LOCAL_FILE_PATH uploadUrl
```
```javascript JavaScript theme={"system"}
const fs = require("fs").promises;
const uploadFileToSignedUrl = async (signedUrl, filePath) => {
try {
const fileBuffer = await fs.readFile(filePath);
const response = await fetch(signedUrl, {
method: "PUT",
body: fileBuffer,
headers: {
"Content-Type": "video/mp4"
}
});
if (response.ok) {
console.log("File upload successful:", response.status);
} else {
console.error("File upload failed:", response.status);
}
} catch (error) {
console.error("Error uploading file:", error);
}
};
// Use the signed URL generated from the previous step
const signedUrl = "SIGNED_URL";
const filePath = "LOCAL_FILE_PATH";
uploadFileToSignedUrl(signedUrl, filePath);
```
```python Python theme={"system"}
import requests
def upload_file_to_signed_url(signed_url, file_path):
try:
with open(file_path, 'rb') as file:
response = requests.put(signed_url, data=file, headers={'Content-Type': 'video/mp4'})
if response.ok:
print("File upload successful:", response.status_code)
else:
print("File upload failed:", response.status_code)
except Exception as error:
print("Error uploading file:", error)
# Use the signed URL generated from the previous step
signed_url = "SIGNED_URL"
file_path = "LOCAL_FILE_PATH"
upload_file_to_signed_url(signed_url, file_path)
```
```php PHP theme={"system"}
getMessage();
}
}
// Use the signed URL generated from the previous step
$signedUrl = "SIGNED_URL";
$filePath = "LOCAL_FILE_PATH";
uploadFileToSignedUrl($signedUrl, $filePath);
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.IO;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string signedUrl = "SIGNED_URL"; // Replace with your signed URL
string filePath = "LOCAL_FILE_PATH"; // Replace with your file path
try
{
await UploadFileToSignedUrl(signedUrl, filePath);
}
catch (Exception ex)
{
Console.WriteLine("Error uploading file: " + ex.Message);
}
}
static async Task UploadFileToSignedUrl(string signedUrl, string filePath)
{
using (var client = new HttpClient())
using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
using (var content = new StreamContent(fileStream))
{
content.Headers.Add("Content-Type", "video/mp4");
var response = await client.PutAsync(signedUrl, content);
if (response.IsSuccessStatusCode)
{
Console.WriteLine("File upload successful: " + response.StatusCode);
}
else
{
Console.WriteLine("File upload failed: " + response.StatusCode);
}
}
}
}
```
```java Java theme={"system"}
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.net.http.HttpRequest.BodyPublishers;
import java.nio.file.Path;
import java.io.IOException;
import java.nio.file.Files;
public class FileUploader {
public static void main(String[] args) {
String signedUrl = "SIGNED_URL"; // Replace with your signed URL
String filePath = "LOCAL_FILE_PATH"; // Replace with your file path
try {
uploadFileToSignedUrl(signedUrl, filePath);
} catch (IOException | InterruptedException e) {
System.out.println("Error uploading file: " + e.getMessage());
}
}
private static void uploadFileToSignedUrl(String signedUrl, String filePath) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(signedUrl))
.header("Content-Type", "image/jpg")
.PUT(BodyPublishers.ofFile(Path.of(filePath)))
.build();
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
System.out.println("File upload successful: " + response.statusCode());
} else {
System.out.println("File upload failed: " + response.statusCode());
}
}
}
```
Please be sure that the `contentType` set when creating the `uploadUrl` matches the Content-Type and the file type when PUTing the file.
For example, if you set the `contentType` to "image/png" when creating the `uploadUrl`, be sure to set the `Content-Type: image/png` and the uploaded file ends in `.png`.
On a successful upload, a `200` response will be returned.
### Example Upload File Binary in Node.js
Here is an example of uploading a binary media file using Node with JavaScript:
```javascript theme={"system"}
const fs = require("fs");
const request = require("request");
const API_KEY = "Your API Key";
const fileName = "test.png";
const endpoint = `https://api.ayrshare.com/api/media/uploadUrl?fileName=${fileName}&contentType=png`;
const run = async () => {
request.get(
{
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
url: endpoint
},
(err, res, body) => {
if (err) {
return console.error(err);
}
const json = JSON.parse(body);
console.log("Upload URL:", json);
return fs.createReadStream(`./${fileName}`).pipe(
request.put(
json.uploadUrl,
{
headers: {
"Content-Type": json.contentType
}
},
(err, httpsResponse, body) => {
if (err) {
console.error("err", err);
} else {
console.log(body);
}
}
)
);
}
);
};
run();
```
### Example Upload Binary File in Postman
You may also use Postman to upload the binary file to the `uploadUrl`.
In Postman:
1. Select the HTTP Method `PUT`.
2. Paste your `uploadUrl` in the url field. Note, the url will expire after an hour and may only be used once. If you make a call and it fails, you must regenerate the `uploadUrl`.
3. In *Headers* set the `Content-Type` to be the content type returned in the /uploadUrl endpoint. For example: `Content-Type: image/png`.
4. Select *Body -> binary* and select the file to upload.
5. Press **Send**.
6. **Important**: No return response will occur, so you should check if the upload was successful by opening the `accessUrl` returned from the /uploadUrl endpoint in a browser. You may also use the [verify URL endpoint](/docs/apis/media/verify-media-url).
```javascript 200: An upload URL and access URL theme={"system"}
{
"accessUrl": "https://media.ayrshare.com/Aswmfs3dIEbwLSdhTlV2/test.mp4",
"contentType": "video/mp4",
"uploadUrl": "https://storage.googleapis.com/..."
}
```
```json 400: Bad Request Error getting signed URL theme={"system"}
{
"action": "upload",
"status": "error",
"code": 301,
"message": "The provided content-type 'movd' is not recognized."
}
```
# Upload Image or Video
Source: https://www.ayrshare.com/docs/apis/media/upload-media
POST /media/upload
Upload an image or small video file to include in your post
This endpoint allows you to upload a file or an image or small video to include in your post. Returned will be the URL to the image that can be used in the /post endpoint.
You can pass the file either as a ***multipart form data*** as a form parameter or a **Base64 encoded file** as a body parameter.
Important notes about media uploads:
1. For best performance, we recommend
Hosting media files on your own server (e.g. AWS S3).
Passing the media URL directly in the `mediaUrls` parameter of the [/post](/docs/apis/post/overview) endpoint.
This approach is faster than uploading files through this endpoint.
2. Media file retention
Uploaded files are stored for 90 days.
After 90 days:
Published posts on social networks are unaffected.
Scheduled posts will fail to publish if they reference expired media.
3. File size limits
Maximum file size: 30 MB.
For larger files, see our guide on [handling large media uploads](/docs/apis/media/upload-large-media).
If you already have your media accessible by an external URL, such as an S3 bucket, you can skip uploading the files to Ayrshare. Just POST to the `/post` endpoint with your externally accessible URL in the `mediaURLs` body parameter and your file will automatically be uploaded.
## Header Parameters
Use `multipart/form-data` if sending a multipart form data - see below. Otherwise, send the standard `application/json`.
## Body Parameters
Max 30 MB file size.
We recommend sending as a multipart form-data object instead of Base64 encoding.
The name of the file to be uploaded.
A description of the file.
### Send as Multipart Form-Data
Send the media file as a multipart form-data object. Please be sure to specify the `Content-Type` as mentioned above.
### Send as Base64
Send the media file as a Base64 encoded string as a Data URI string. The string should begin with `data:content/type;base64`
Example encoding with Output Format Data URI:
Note: The /post endpoint accepts larger files via an external URL with the `mediaUrls` parameter.
```bash cURL theme={"system"}
# Send as Multipart Form-Data
curl \
-H "Authorization: Bearer API_KEY" \
-F "file=@test.png" \
-F "fileName=test.png" \
-F "description=best image" \
-X POST https://api.ayrshare.com/api/media/upload
# Send as Base64
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"file": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...", "fileName": "test.png", "description": "best image"}' \
-X POST https://api.ayrshare.com/api/media/upload
```
```javascript JavaScript theme={"system"}
// Send as Multipart Form-Data
const FormData = require('form-data');
const fs = require('fs');
const API_KEY = "API_KEY";
const imagePath = './test.png';
const form = new FormData();
form.append('file', fs.createReadStream(imagePath));
form.append('fileName', 'test.png');
form.append('description', 'best image');
fetch("https://api.ayrshare.com/api/media/upload", {
method: "POST",
headers: {
"Authorization": `Bearer ${API_KEY}`
// Don't set Content-Type header - FormData will set it automatically with boundary
},
body: form
})
.then(res => res.json())
.then(json => console.log(json))
.catch(console.error);
// Send as Base64
const API_KEY = "API_KEY";
const base64 = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...";
fetch("https://api.ayrshare.com/api/media/upload", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
file: base64,
fileName: "test.png",
description: "best image"
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
# Send as Multipart Form-Data
import requests
# For a local file:
files = {
'file': ('test.png', open('test.png', 'rb')),
}
# Form data
data = {
'fileName': 'test.png',
'description': 'best image'
}
headers = {
'Authorization': 'Bearer API_KEY'
}
r = requests.post(
'https://api.ayrshare.com/api/media/upload',
files=files,
data=data,
headers=headers
)
print(r.json())
# Send as Base64
import requests
payload = {'file': 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...',
'fileName': "test.png",
'description': "best image"}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/media/upload',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
# Send as Multipart Form-Data
[
'method' => 'POST',
'header' => "Authorization: Bearer API_KEY\r\n" .
"Content-Type: multipart/form-data; boundary=" . $boundary . "\r\n" .
"Content-Length: " . strlen($data) . "\r\n",
'content' => $data
]
];
// Send the request
$context = stream_context_create($options);
$result = file_get_contents('https://api.ayrshare.com/api/media/upload', false, $context);
// Print the response
echo $result;
# Send as Base64
'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQ...',
'fileName' => "test.png",
'description' => "best image"
];
$ch = curl_init('https://api.ayrshare.com/api/media/upload');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, [
'Content-Type: application/json',
'Authorization: Bearer API_KEY'
]);
$response = curl_exec($ch);
curl_close($ch);
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
```
```javascript 200: Success theme={"system"}
{
"id": "1167335b-6c37-4fc6-ab8a-044e0005d335-jpeg",
"url": "https://images.ayrshare.com/q3Ls85VTsrbODnGIJHpy7PaHWwA3/1167335b-6c37-4fc6-ab8a-044ed885d.jpeg",
"fileName": "fun.jpg",
"description": "good times"
}
```
```json 400: Bad Request Error in upload theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Verify Media URL Exists
Source: https://www.ayrshare.com/docs/apis/media/verify-media-url
POST /media/urlExists
Verify that the media file exists
Verify that the media file exists when uploaded. It should be used in conjunction with the /media/uploadUrl endpoint.
## Header Parameters
## Verify Media URL Exists
`POST` `https://api.ayrshare.com/api/media/urlExists`
Verify that the media file exists when uploaded. It should be used in conjunction with the /media/uploadUrl endpoint.
You will also receive the `contentType` of the media file.
A `HEAD` request is made to the media URL to verify it exists.
Please be sure the hosting provider is not blocking the `HEAD` request.
## Body Parameters
URL of the media to verify exists.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"mediaUrl": "https://img.ayrshare.com/012/vid.mp4"}' \
-X POST https://api.ayrshare.com/api/media/urlExists
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/media/urlExists", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
mediaUrl: "https://img.ayrshare.com/012/vid.mp4"
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'mediaUrl': 'https://img.ayrshare.com/012/vid.mp4'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/media/urlExists',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'POST',
'https://api.ayrshare.com/api/media/urlExists',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'mediaUrl' => 'https://img.ayrshare.com/012/vid.mp4'
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```json 200: OK Media URL is valid theme={"system"}
{
"status": "success",
"statusCode": 200,
"contentType": "image/jpeg"
}
```
```json 404: Not Found Media file not found theme={"system"}
{
"status": "error",
"statusCode": 404,
"statusText": "Not Found"
}
```
# Get Auto Response
Source: https://www.ayrshare.com/docs/apis/messages/get-auto-response
GET /messages/autoresponse
Get the auto response setting
Get the auto response setting. If the auto response settings do not exist, no data, except a `status`, will be returned.
## Header Parameters
```json 200: Success theme={"system"}
{
"status": "success",
"autoResponseActive": true,
"autoResponseMessage": "Howdy Buckaroo!",
"autoResponseWaitSeconds": 30
}
```
```json 200: No Settings theme={"system"}
{
"status": "success"
}
```
# Get Messages
Source: https://www.ayrshare.com/docs/apis/messages/get-messages
GET /messages/:platform
Get messages or conversations for a messaging platform
Get messages or conversations for a messaging platform.
Retrieval times differ on each social network. On Facebook, Instagram, and WhatsApp, messages are available via Ayrshare in real time. On X/Twitter, there is a delay of up to 3 minutes to see new message updates. Please contact support to learn more about the Enterprise Plan if you need real-time X/Twitter message access.
**Response caching:** For **Facebook** and **Instagram**, responses are cached for **60
seconds**. For **X/Twitter**, responses are cached for **15 seconds** to better support polling.
WhatsApp reads messages already received through Meta webhooks, so a newly received message can
appear as soon as Ayrshare processes its webhook. The response still includes `lastUpdated` and
`nextUpdate` metadata.
Initial message history retrieval for Facebook and Instagram is limited to the
last 20 messages. Please see the [Message History Retrieval for Facebook and
Instagram](/docs/apis/messages/overview#message-history-retrieval-for-facebook-and-instagram)
section for more information.
WhatsApp conversations are identified by the correspondent's phone number
(digits only, E.164 without the leading `+`). A stored outbound message may include a `status`
value of `sent`, `delivered`, `read`, or `failed`.
WhatsApp messages sent through [Send Message](/docs/apis/messages/send-message) are not currently
added to Get Messages history. Incoming WhatsApp messages received through webhooks are stored
and returned here.
## Header Parameters
## Path Parameters
The platform to get the message: `facebook`, `instagram`, `twitter`, `whatsapp`
## Query Parameters
Return active conversations or archived conversations. Values: `active` or `archived`.
Only return the specific conversation.
Return all the conversations. If `true` then conversationId field ignored.
When `conversationsOnly=true`, conversation details are returned in
`converstationsDetails`. This spelling is part of the current API response.
**X/Twitter only.** Limit the number of messages returned per request (1–100). Enables efficient polling without a full history sync. Use with `next` for pagination. If omitted, the default behavior (full message retrieval) is used.
**X/Twitter only.** Encrypted pagination cursor returned from a previous request's `meta.pagination.next` field. Use with `limit` to fetch the next page of results.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/messages/facebook
```
```javascript JavaScript theme={"system"}
const apiKey = 'API_KEY';
const url = 'https://api.ayrshare.com/api/messages/facebook';
const headers = {
'Authorization': `Bearer ${apiKey}`,
};
fetch(url, {
method: 'GET',
headers: headers,
})
.then(response => {
if (response.ok) {
return response.json();
} else {
throw new Error(`Request failed. Status code: ${response.status}`);
}
})
.then(data => {
console.log('Response:', data);
})
.catch(error => {
console.error('Error:', error.message);
});
```
```python Python theme={"system"}
import requests
api_key = 'API_KEY'
url = 'https://api.ayrshare.com/api/messages/facebook'
headers = {
'Authorization': f'Bearer {api_key}',
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
data = response.json()
print('Response:', data)
else:
print(f'Request failed. Status code: {response.status_code}')
```
```php PHP theme={"system"}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using System.Text.Json;
class Program
{
static async Task Main()
{
string apiKey = "API_KEY";
string url = "https://api.ayrshare.com/api/messages/facebook";
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
try
{
var response = await client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
var responseBody = await response.Content.ReadAsStringAsync();
var responseData = JsonSerializer.Deserialize(responseBody);
Console.WriteLine("Response:");
Console.WriteLine(responseData);
}
else
{
Console.WriteLine($"Request failed. Status code: {response.StatusCode}");
}
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
```
```java Java theme={"system"}
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) {
String apiKey = "API_KEY";
String url = "https://api.ayrshare.com/api/messages/facebook";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + apiKey)
.GET()
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String responseBody = response.body();
System.out.println("Response:");
System.out.println(responseBody);
} else {
System.out.println("Request failed. Status code: " + response.statusCode());
}
} catch (IOException | InterruptedException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"messages": [
{
"senderId": "106638148652444",
"senderDetails": {
"name": "Ayrshare"
},
"conversationId": "t_10161117434308444",
"created": "2024-06-06T00:54:32.455Z",
"action": "sent",
"recipientId": "7101149746568444",
"id": "m_JH6o-yS83JoxWmQaLrmgSaHwGtfTgQ",
"message": "Howdy!",
"platform": "facebook",
"reactions": {
"7101149746568522": "😆". // Reaction by the customer on the Howdy! message
}
},
{
"recipientDetails": {
"name": "Sara Smith",
"id": "736532028017333",
"picture": "https://img.ayrshare.com/333/messages/facebook-eTZzhE2b.jpeg"
},
"senderId": "106638148652329",
"attachments": [
{
"type": "image",
"url": "https://scontent.xx.fbcdn.net/v/t1.15752-9/490986808_1193328359195158"
}
],
"conversationId": "t_3567590438533",
"created": "2024-06-06T00:54:32.455Z",
"action": "sent",
"recipientId": "736532028017333",
"id": "m_WJlfgzopxfdRM1wFTKYHKv7zh75P",
"updated": "2024-06-06T00:54:32.455Z",
"platform": "facebook",
"senderDetails": {
"name": "Ayrshare"
}
},
{
"senderId": "7101149746568444",
"senderDetails": {
"name": "John Smith",
"profileImage": "https://platform-lookaside.fbsbx.com/platform/profilepic/"
},
"conversationId": "t_10161117434308444",
"created": "2024-06-06T00:54:28.102Z",
"action": "received",
"recipientId": "106638148652329",
"id": "m_HGbotYJUmf4AzyPlJ-2uZqHwGtfTgQihX",
"message": "Look up!",
"platform": "facebook"
},
{
"senderId": "7101149746568444",
"senderDetails": {
"name": "John Smith",
"profileImage": "https://platform-lookaside.fbsbx.com/platform/profilepic/"
},
"conversationId": "t_10161117434308444",
"created": "2024-06-06T00:49:11.679Z",
"action": "received",
"recipientId": "106638148652444",
"id": "m_jXoYQIwTXaq2u06PG6Z8vaHwGtfTgQ",
"message": "How is the weather?",
"platform": "facebook"
}
],
"lastUpdated": "2024-06-09T21:46:04.233Z",
"nextUpdate": "2024-06-09T21:47:04.233Z"
}
```
```json 200: Paginated (X/Twitter) theme={"system"}
{
"status": "success",
"messages": [
{
"id": "1893410668991234567",
"conversationId": "1234567890-9876543210",
"senderId": "9876543210",
"created": "2024-06-09T21:30:00.000Z",
"message": "Hey, how are you?",
"action": "received",
"senderDetails": {
"name": "Jane Doe",
"username": "janedoe"
}
},
{
"id": "1893410668991234566",
"conversationId": "1234567890-9876543210",
"senderId": "1234567890",
"created": "2024-06-09T21:28:00.000Z",
"message": "Hello!",
"action": "sent",
"senderDetails": {
"name": "My Account",
"username": "myaccount"
}
}
],
"messagesCount": 2,
"lastUpdated": "2024-06-09T21:46:04.233Z",
"nextUpdate": "2024-06-09T21:46:19.233Z",
"meta": {
"pagination": {
"hasMore": true,
"limit": 5,
"next": "eyJwYWdpbmF0aW9uVG9rZW4iOiIxODkzNDEwNjY4OTkxMjM0NTY1In0="
}
}
}
```
```json 200: WhatsApp theme={"system"}
{
"status": "success",
"messages": [
{
"id": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBI3MEM3Q0NDQjlGRTUzMjJBNEUA",
"conversationId": "14155551234",
"senderId": "14155551234",
"recipientId": "123456789012345",
"created": "2026-05-18T17:10:02.000Z",
"message": "When is my order shipping?",
"action": "received",
"platform": "whatsapp"
},
{
"id": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBI4OUYxRkExNzE0M0EwQTYwM0EA",
"conversationId": "14155551234",
"senderId": "14155551234",
"recipientId": "123456789012345",
"created": "2026-05-18T17:08:41.000Z",
"attachments": [
{
"type": "image",
"url": "https://img.ayrshare.com/abc123/whatsapp/whatsapp_image_x9aB2pK7.jpg"
}
],
"action": "received",
"platform": "whatsapp"
}
],
"lastUpdated": "2026-05-18T17:13:00.000Z",
"nextUpdate": "2026-05-18T17:14:00.000Z"
}
```
```json 200: WhatsApp Conversations theme={"system"}
{
"status": "success",
"conversationIds": ["14155551234", "447700900123"],
"converstationsDetails": [
{
"id": "14155551234",
"participant": {
"id": "14155551234",
"name": "Jane Customer"
},
"status": "active",
"unread": 2
},
{
"id": "447700900123",
"participant": {
"id": "447700900123"
},
"status": "active",
"unread": 0
}
],
"lastUpdated": "2026-05-18T17:13:00.000Z",
"nextUpdate": "2026-05-18T17:14:00.000Z"
}
```
```json 200: Conversations theme={"system"}
{
"status": "success",
"conversationIds": ["t_10161117434308444", "t_356759043857444"],
"converstationsDetails": [
{
"id": "t_10161117434308444",
"participant": {
"name": "John Smith",
"id": "7101149746568444",
"picture": "https://platform-lookaside.fbsbx.com/platform/profilepic/"
},
"status": "active",
"watermark": 1717889607444
},
{
"id": "t_356759043857444",
"participant": {
"name": "Sara Johnson",
"id": "7365320280173444",
"picture": "https://platform-lookaside.fbsbx.com/platform/profilepic/"
},
"status": "active"
}
],
"lastUpdated": "2024-06-09T21:46:04.233Z",
"nextUpdate": "2024-06-09T21:47:04.233Z"
}
```
```json 403: Messaging Not Enabled theme={"system"}
{
"action": "messages",
"status": "error",
"code": 361,
"message": "Messaging is not enabled for this User Profile. Please subscribe to Messaging and activate Messaging for this User Profile."
}
```
```json 400: Social Account Needs Relinking theme={"system"}
{
"action": "messages",
"status": "error",
"code": 362,
"message": "The social network needs to be relinked to access Messaging. Please unlink, relink, and try again.",
"resolution": {
"relink": true,
"platform": "facebook"
}
}
```
# Messages API Overview
Source: https://www.ayrshare.com/docs/apis/messages/overview
Send and receive direct messages on Facebook, Instagram, X/Twitter, and WhatsApp
The Messaging API allows you to manage direct messages (DM) to correspondents who contact your User Profiles.
A correspondent is the person with whom your user (User Profile) is communicating with.
A conversation is a series of messages between your user (User Profile) and their correspondent.
The Messaging API is included with all Ayrshare Business Plans and as a paid add-on for Premium
plans.
For both Business and Premium plans, you must activate Messaging in the Account page of the
Ayrshare dashboard.
Messaging is available for Facebook Messenger, Instagram Direct Messenger,
X Direct Messages, and WhatsApp (Private Beta).
**WhatsApp is in Private Beta.** Send and receive WhatsApp messages through
the Messaging API. If you'd like early access, email
[lotty@ayrshare.com](mailto:lotty@ayrshare.com).
## Key Messaging Features
Manage your users' conversations with correspondents.
Sending text, image, video, and emoji messages on behalf of your users.
Retrieving complete conversation histories.
Setting up automated message responses.
Receiving real-time updates via webhooks for messages received, message reactions, read
receipts.
## Enable Messaging
### Enable Your Ayrshare Account and User Profiles
You must first enable messaging for your overall Ayrshare account to manage DMs. In the Ayrshare dashboard go to the [Account page](https://app.ayrshare.com/account) and click to "Learn More" button and then "Enable". At this point you have enabled messaging for your overall account, *but have not activated messaging for individual User Profiles*.
You can activate messaging for individual User Profiles either in the [User Profiles page](https://app.ayrshare.com/manage-profiles) by clicking "Messaging Active" checkbox for each profile or using the create or update [profiles endpoint](/docs/apis/profiles/overview).
After enabling messaging for a User Profile, you must relink the social account (Facebook and Instagram) in the Social Accounts/Social Linking page.
Once enabled you will see the "Messaging" badge on the linked social account.
The Messages endpoints report these setup steps with distinct error codes, so you can tell them apart
programmatically:
* **`403` / code `361`** — Messaging is not enabled. Either the account is not subscribed to Messaging, or this
User Profile has not been activated. Complete the steps above; relinking a social account will not help.
* **`400` / code `362`** — Messaging is active for the User Profile, but this **Facebook or Instagram** account
still needs to be relinked. This response includes `resolution: { "relink": true }`.
### Enable Messaging for WhatsApp
**WhatsApp is in Private Beta.** The setup flow and Messaging API endpoints are available to
approved beta accounts. To request access, email
[lotty@ayrshare.com](mailto:lotty@ayrshare.com).
Link a WhatsApp Business account through Meta's **embedded signup** flow directly from the
Ayrshare dashboard:
You need a **Meta Business Manager** account, a **WhatsApp Business Account (WABA)**, and an
eligible phone number. Meta verifies the account and phone number during embedded signup.
On the Social Accounts page, click **Link** on the WhatsApp tile. Ayrshare launches Meta's
embedded signup pop-up which walks the customer through selecting/creating their Business
Manager, WABA, and phone number, and accepting Meta's terms.
When signup finishes, Ayrshare verifies ownership of the selected WABA and phone number,
completes registration, and subscribes the account to WhatsApp webhooks. You do not enter a
separate registration PIN in the Ayrshare dashboard.
### Important WhatsApp-Specific Behavior
**Recipients are phone numbers, not IDs.** WhatsApp identifies correspondents by E.164
phone number (digits only, no `+`). Conversation IDs returned from Ayrshare are also the
correspondent's phone number — there are no opaque conversation IDs the way Facebook and
Instagram use.
**24-hour customer service window.** WhatsApp Business only allows free-form outbound
messages within 24 hours of the most recent message from the correspondent. Outside that
window Meta rejects the send. Templated messages outside the 24-hour window are not currently
supported through Ayrshare.
**Address a recipient directly with the API.** Pass the recipient's phone number to
[Send Message](/docs/apis/messages/send-message). Meta only delivers a free-form message when that
recipient is inside the 24-hour customer service window. Approved templates are required for
cold outreach, and Ayrshare does not currently expose template sending.
**Delivery status uses one field.** When available on a stored outbound message,
[Get Messages](/docs/apis/messages/get-messages) returns `status` as `sent`, `delivered`, `read`, or
`failed`. Delivery-status updates and WhatsApp reactions are not currently pushed to your
registered webhook URL.
**Media types and sizes** follow Meta's published WhatsApp Cloud API limits — images up to
5 MB, audio and video up to 16 MB, and documents up to 100 MB at the time of writing.
### Enable Messaging in the Instagram App
You may need to enable messaging for your Instagram account:
Go to your profile in the Instagram mobile app and tap the menu icon ≡ in the upper right corner
to go to the **Settings and activity** page.
Scroll down to the **How others can interact with you** section.
Click **Messages and story replies**.
Tap **Message requests**.
Under **Connected tool** toggle on the **Allow access to messages** switch.
The **Message requests** setting shown here also governs whether a *recipient* can be reached. If you use [comment-triggered automations](/docs/apis/automations/overview) to DM people who comment on your posts, delivery depends on each recipient's Message requests setting — a message can be accepted by Instagram (`sent`) and then silently dropped. See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
## Important Information on Messaging
**For Facebook and Instagram, a conversation must be initiated by the correspondent.** Once a
conversation is established, you may then send messages, receive messages, get reactions (e.g.
thumbs ups), or get read receipts on behalf of your users. WhatsApp follows the 24-hour customer
service window described above.
**Your user must respond to an Instagram conversation within 7 days of the last message the
correspondent sent.** If the correspondent has not sent a message in 7 days the conversation is
considered inactive and cannot be responded to.
**Comment-triggered automations use a different 7-day window.** A [`comment_keyword` automation](/docs/apis/automations/overview) replies to a *comment* via a private reply, whose 7-day window is anchored to the comment (not to a prior message), so no existing conversation is required. Delivery is still subject to the recipient's Message requests setting — see [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
### Message History Retrieval for Facebook and Instagram
When you first enable messaging for a user profile with a linked Facebook or
Instagram, there are important limitations on accessing conversation history:
#### Initial Connection Limitations
Facebook and Instagram only allow retrieval of the **last 20 messages** from existing
conversations when you first link an account for messaging
If a conversation has more than 20 messages, only the most recent 20 will be accessible
initially
#### After Initial Setup
Once messaging is enabled, **all new messages** sent and received will be fully accessible
Ayrshare maintains complete conversation history going forward
For example: If you initially retrieve 20 messages, then 100 new messages are exchanged, you'll
be able to access all 120 messages total
This limitation only applies to historical messages that existed before enabling
messaging - all future conversation activity for Facebook and Instagram will be
fully preserved and accessible.
### Conversation Limit & Pricing
Each Ayrshare User Profile can have up to **1,000 active conversations per
billing cycle**. The active conversation count is the sum across all social
networks.
**Premium plan**: Messaging is a flat **\$49 per month** add-on per account.
**Launch and Business plans**: Messaging is billed at **\$0.09 per active
conversation** via Stripe metered billing. Volume-based discounts are
available; contact your Ayrshare account representative for details.
A conversation is counted as active for the billing cycle when you send a
message to a recipient. Inbound messages from a recipient do not, on their
own, mark a conversation as active.
If the 1,000 conversation limit has been reached, you can still receive
messages, but you will not be able to respond until the start of the next
billing cycle.
The number of messages, sent or received, in an active conversation is unlimited.
If you need to increase the conversation limit, please contact your
Ayrshare account representative.
You can see the current conversation count with the [user endpoint](/docs/apis/user/overview).
### Messaging Control Issues on Facebook and Instagram
Meta (Facebook and Instagram) uses a "thread control" system for messaging conversations. This means only one app can send messages in a conversation at a time, while other apps can only receive messages.
#### What Does This Mean?
If you see the error **"Message failed to send because another app is controlling this thread now"**, it means:
* A different third-party app currently controls that conversation
* Ayrshare can only receive messages in that conversation
* Ayrshare cannot send messages until it regains control
#### How to Fix This Issue
To allow Ayrshare to send messages again, you need to remove the third-party app that's controlling the conversation.
Please note that Meta (Facebook and Instagram) may update the process for removing third-party apps, so use the following steps as a general guideline.
**For Facebook Pages:**
1. Go to [Facebook.com](https://facebook.com) and log into your account
2. Click the menu (☰) in the top right → **Settings & Privacy** → **Settings**
3. In the left sidebar, click **Apps and Websites**
4. Find the third-party app that's controlling your messaging
5. Click **Remove** next to that app
6. Confirm the removal
**For Instagram Business Accounts:**
1. Open the Instagram app on your phone
2. Go to your **Profile** → tap the menu (☰) → **Settings and Privacy**
3. Tap **Apps and Websites**
4. Find and remove the third-party app
**Alternative for Instagram:**
1. Go to [business.facebook.com](https://business.facebook.com)
2. Navigate to **Business Settings**
3. Under **Accounts**, click **Instagram Accounts**
4. Select your Instagram account
5. Check for connected apps and remove the problematic one
#### After Removal
Once you've removed the third-party app:
Thread control will automatically return to Ayrshare
You should be able to send messages normally again
No further action is required on your part
If you continue to experience issues after removing the app, please contact our support team.
## Message WebHooks
See [Messages Webhooks](/docs/apis/webhooks/actions#messages-action) to automatically receive messages, read receipts, or reactions.
# Send Message
Source: https://www.ayrshare.com/docs/apis/messages/send-message
POST /messages/:platform
Send a direct message to a recipient
Send a new direct message to a recipient.
**Pricing & Limits:** Each User Profile can have up to **1,000 active
conversations per billing cycle** across all social networks. Pricing depends
on your plan: **Premium** plans pay a flat **$49 per month** add-on, while **Launch** and **Business** plans are billed at **$0.09 per active
conversation**. A conversation is counted as
active when you send a message to a recipient during the billing cycle;
inbound messages alone do not count. The number of messages within an active
conversation is unlimited.
You can send an emoji as part of the `message` text.
Facebook and Instagram `mediaUrls` must end in a known extension. Including query parameters
will cause the media URL to fail.
**WhatsApp 24-hour customer service window.** WhatsApp Business only permits free-form
outbound messages within **24 hours** of the most recent message from the correspondent. After
that window, message sends will be rejected by Meta until the correspondent messages again.
Templated messages outside the 24-hour window are not currently supported through this endpoint.
## Header Parameters
## Path Parameters
The platform to send the message: `facebook`, `instagram`, `twitter`, `whatsapp`
## Body Parameters
The ID of the message recipient.
For **Facebook**, **Instagram**, and **X/Twitter** this is the platform-specific user ID
(PSID, IGSID, or user ID).
For **WhatsApp** this is the recipient's phone number in E.164 digits-only format (for
example `14155551234`, not `+1 (415) 555-1234`).
The message to send to the recipient.
Facebook, Instagram, and WhatsApp `message` may be an empty string or omitted entirely when
`mediaUrls` is provided.
X requires a message of at least one character even if a `mediaUrls` is provided.
Array of media URLs for attaching images, video, audio (including voice messages), or documents.
URLs of media items should end in the file extension without additional parameters appended.
Facebook and Instagram support multiple media URLs.
X only accepts a single media URL.
Voice messages are supported on Facebook and Instagram as an `aac` or `wav` file.
**WhatsApp** accepts multiple media URLs. Ayrshare fetches each URL and uses its response
`Content-Type` to select the WhatsApp media category. Meta accepts:
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"message": "What's up!", "recipientId": "283j839222"} \
-X POST https://api.ayrshare.com/api/messages/instagram
```
```javascript JavaScript theme={"system"}
const apiKey = 'API_KEY';
const url = 'https://api.ayrshare.com/api/messages/instagram';
const data = {
message: "What's up!",
recipientId: '283j839222',
};
const headers = {
'Authorization': `Bearer ${apiKey}`,
'Content-Type': 'application/json',
};
fetch(url, {
method: 'POST',
headers: headers,
body: JSON.stringify(data),
})
.then(response => response.json())
.then(data => {
console.log('Response:', data);
})
.catch(error => {
console.error('Error:', error);
});
```
```python Python theme={"system"}
import requests
api_key = 'API_KEY'
url = 'https://api.ayrshare.com/api/messages/instagram'
data = {
'message': "What's up!",
'recipientId': '283j839222',
}
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json',
}
response = requests.post(url, json=data, headers=headers)
print('Response:', response.json())
```
```php PHP theme={"system"}
"What's up!",
'recipientId' => '283j839222',
];
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json',
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
if ($response === false) {
$error = curl_error($ch);
echo 'Error: ' . $error;
} else {
$responseData = json_decode($response, true);
print_r($responseData);
}
curl_close($ch);
?>
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
string apiKey = "API_KEY";
string url = "https://api.ayrshare.com/api/messages/instagram";
var data = new
{
message = "What's up!",
recipientId = "283j839222"
};
var jsonData = JsonSerializer.Serialize(data);
using var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apiKey);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
try
{
var response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
var responseData = JsonSerializer.Deserialize(responseBody);
Console.WriteLine("Response:");
Console.WriteLine(responseData);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
```
```java Java theme={"system"}
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
public class Main {
public static void main(String[] args) {
String apiKey = "API_KEY";
String url = "https://api.ayrshare.com/api/messages/instagram";
String data = "{\"message\": \"What's up!\", \"recipientId\": \"283j839222\"}";
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.header("Authorization", "Bearer " + apiKey)
.header("Content-Type", "application/json")
.POST(HttpRequest.BodyPublishers.ofString(data))
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() == 200) {
String responseBody = response.body();
System.out.println("Response:");
System.out.println(responseBody);
} else {
System.out.println("Request failed. Status code: " + response.statusCode());
}
} catch (IOException | InterruptedException e) {
System.out.println("Error: " + e.getMessage());
}
}
}
```
```json 200: Success theme={"system"}
{ // single text message
"status": "success",
"recipientId": "72706337063589124",
"messageId": "aWdfZAG1faXRlbToxOkl",
"message": "What is up?"
}
```
```json 400: Error theme={"system"}
{
// single text message
"action": "messages",
"status": "error",
"code": 363,
"message": "The recipient ID was not found. Please confirm the recipient ID is correct."
}
```
```json 200: Media Urls theme={"system"}
{
// single image
"status": "success",
"recipientId": "761943",
"messageId": "m_EgvfBrgjaM",
"type": "image",
"mediaUrl": "https://img.ayrshare.com/012/gb.jpg"
}
```
```json 400: Media Urls theme={"system"}
{
// text and image message
"action": "send",
"status": "error",
"code": 337,
"message": "Error sending message.",
"messages": [
{
"recipientId": "727063370635",
"messageId": "aWdfZAG1faXRlbT",
"message": "What a great day"
},
{
"action": "messages",
"status": "error",
"code": 365,
"message": "An error occurred sending the message attachment. Please verify the attachment is still available and try again."
}
]
}
```
```json 200: WhatsApp Text theme={"system"}
{
"status": "success",
"messagingProduct": "whatsapp",
"contacts": [
{
"input": "14155551234",
"waId": "14155551234"
}
],
"recipientId": "14155551234",
"messageId": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBI4OUYxRkExNzE0M0EwQTYwM0EA",
"message": "Thanks — your order has shipped."
}
```
```json 200: WhatsApp Text + Media theme={"system"}
{
"status": "success",
"messages": [
{
"messagingProduct": "whatsapp",
"recipientId": "14155551234",
"messageId": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBI3MEM3Q0NDQjlGRTUzMjJBNEUA",
"message": "Here's the shipping label you requested."
},
{
"messagingProduct": "whatsapp",
"recipientId": "14155551234",
"messageId": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBJDODc3NEJBRTdGN0NGNkVCMEMA",
"type": "document",
"mediaUrl": "https://example.com/label.pdf"
}
]
}
```
# Set Auto Response
Source: https://www.ayrshare.com/docs/apis/messages/set-auto-response
POST /messages/autoresponse
Automatically send message auto responses
Automatically send message auto responses to the correspondent. This is useful if your customer service support desk is not currently available.
If active, the auto response is used for all social networks for a given User Profile.
## Header Parameters
## Body Parameters
Whether the auto response is active.
The number of seconds to wait before sending the auto response again to the correspondent. Default is 86,400 seconds (24 hours).
The auto response message.
Default: "Thank you for contacting us. A customer care agent will get back to you soon."
Send an empty "" string to reset the message to the default.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"autoResponseActive": true, "autoResponseWaitSeconds": 30, "autoResponseMessage": "Howdy!"' \
-X POST https://api.ayrshare.com/api/messages/autoresponse
```
```javascript JavaScript theme={"system"}
const url = 'https://api.ayrshare.com/api/messages/autoresponse';
const options = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
},
body: JSON.stringify({
'autoResponseActive': true,
'autoResponseWaitSeconds': 30,
'autoResponseMessage': 'Howdy!'
})
};
fetch(url, options)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```python Python theme={"system"}
import json
import requests
url = 'https://api.ayrshare.com/api/messages/autoresponse'
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
}
data = {
'autoResponseActive': True,
'autoResponseWaitSeconds': 30,
'autoResponseMessage': 'Howdy!'
}
response = requests.post(url, headers=headers, data=json.dumps(data))
try:
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.RequestException as e:
print('Error:', e)
```
```php PHP theme={"system"}
true,
'autoResponseWaitSeconds' => 30,
'autoResponseMessage' => 'Howdy!'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode >= 400) {
echo 'Error: HTTP ' . $httpCode;
} else {
$data = json_decode($response, true);
print_r($data);
}
}
curl_close($ch);
```
```csharp C# theme={"system"}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string url = "https://api.ayrshare.com/api/messages/autoresponse";
var headers = new Dictionary
{
{"Content-Type", "application/json"},
{"Authorization", "Bearer API_KEY"}
};
var data = new Dictionary
{
{"autoResponseActive", true},
{"autoResponseWaitSeconds", 30},
{"autoResponseMessage", "Howdy!"}
};
using (var client = new HttpClient())
{
var jsonData = JsonSerializer.Serialize(data);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = await client.PostAsync(url, content);
try
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
var responseData = JsonSerializer.Deserialize>(responseBody);
Console.WriteLine(JsonSerializer.Serialize(responseData, new JsonSerializerOptions { WriteIndented = true }));
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```java Java theme={"system"}
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String url = "https://api.ayrshare.com/api/messages/autoresponse";
Map headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer API_KEY");
Map data = new HashMap<>();
data.put("autoResponseActive", true);
data.put("autoResponseWaitSeconds", 30);
data.put("autoResponseMessage", "Howdy!");
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.headers(headers.entrySet().stream()
.map(entry -> entry.getKey() + ": " + entry.getValue())
.toArray(String[]::new))
.POST(HttpRequest.BodyPublishers.ofString(getJsonString(data)))
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
System.out.println("Error: HTTP " + response.statusCode());
} else {
System.out.println(response.body());
}
} catch (IOException | InterruptedException e) {
System.out.println("Error: " + e.getMessage());
}
}
private static String getJsonString(Map data) {
StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.append("{");
for (Map.Entry entry : data.entrySet()) {
jsonBuilder.append("\"").append(entry.getKey()).append("\":");
if (entry.getValue() instanceof String) {
jsonBuilder.append("\"").append(entry.getValue()).append("\"");
} else {
jsonBuilder.append(entry.getValue());
}
jsonBuilder.append(",");
}
if (jsonBuilder.length() > 1) {
jsonBuilder.setLength(jsonBuilder.length() - 1);
}
jsonBuilder.append("}");
return jsonBuilder.toString();
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"updated": {
"autoResponseActive": true,
"autoResponseMessage": "Howdy!",
"autoResponseWaitSeconds": 30
}
}
```
```json 400: Error theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Update Messages
Source: https://www.ayrshare.com/docs/apis/messages/update-messages
PUT /messages/:platform/:conversationId
Update status of a conversation
Update the status of a conversation to active or archived. You may want to archive conversations if they are no longer active or relevant.
## Header Parameters
## **Path Parameters**
The platform for status update: `facebook`, `instagram`, `twitter`, `whatsapp`
The ID of the conversation to action. For WhatsApp this is the correspondent's phone number
(digits only, E.164 without the leading `+`).
## Body Parameters
Values: `active` or `archived`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"status": "archived"}' \
-X PUT https://api.ayrshare.com/api/messages/instagram/aWdfZMTpIyzQw
```
```javascript JavaScript theme={"system"}
const url = 'https://api.ayrshare.com/api/messages/instagram/aWdfZMTpIyzQw';
const options = {
method: 'PUT',
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
},
body: JSON.stringify({
'status': 'archived'
})
};
fetch(url, options)
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```python Python theme={"system"}
import json
import requests
url = 'https://api.ayrshare.com/api/messages/instagram/aWdfZMTpIyzQw'
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
}
data = {
'status': 'archived'
}
response = requests.put(url, headers=headers, data=json.dumps(data))
try:
response.raise_for_status()
data = response.json()
print(data)
except requests.exceptions.RequestException as e:
print('Error:', e)
```
```php PHP theme={"system"}
'archived'
];
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'PUT');
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode >=
```
```csharp C# theme={"system"}
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
string url = "https://api.ayrshare.com/api/messages/instagram/aWdfZMTpIyzQw";
var headers = new Dictionary
{
{"Content-Type", "application/json"},
{"Authorization", "Bearer API_KEY"}
};
var data = new Dictionary
{
{"status", "archived"}
};
using (var client = new HttpClient())
{
var jsonData = JsonSerializer.Serialize(data);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
foreach (var header in headers)
{
client.DefaultRequestHeaders.Add(header.Key, header.Value);
}
var response = await client.PutAsync(url, content);
try
{
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
var responseData = JsonSerializer.Deserialize>(responseBody);
Console.WriteLine(JsonSerializer.Serialize(responseData, new JsonSerializerOptions { WriteIndented = true }));
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```java Java theme={"system"}
import java.io.IOException;
import java.net.URI;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class Main {
public static void main(String[] args) {
String url = "https://api.ayrshare.com/api/messages/instagram/aWdfZMTpIyzQw";
Map headers = new HashMap<>();
headers.put("Content-Type", "application/json");
headers.put("Authorization", "Bearer API_KEY");
Map data = new HashMap<>();
data.put("status", "archived");
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(url))
.headers(headers.entrySet().stream()
.map(entry -> entry.getKey() + ": " + entry.getValue())
.toArray(String[]::new))
.PUT(HttpRequest.BodyPublishers.ofString(getJsonString(data)))
.build();
try {
HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofString());
if (response.statusCode() >= 400) {
System.out.println("Error: HTTP " + response.statusCode());
} else {
System.out.println(response.body());
}
} catch (IOException | InterruptedException e) {
System.out.println("Error: " + e.getMessage());
}
}
private static String getJsonString(Map data) {
StringBuilder jsonBuilder = new StringBuilder();
jsonBuilder.append("{");
for (Map.Entry entry : data.entrySet()) {
jsonBuilder.append("\"").append(entry.getKey()).append("\":\"").append(entry.getValue()).append("\",");
}
if (jsonBuilder.length() > 1) {
jsonBuilder.setLength(jsonBuilder.length() - 1);
}
jsonBuilder.append("}");
return jsonBuilder.toString();
}
}
```
```json 200: Success theme={"system"}
{
"status": "success"
}
```
```json 400: Missing Status theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Ayrshare API Overview
Source: https://www.ayrshare.com/docs/apis/overview
Powerful Social APIs that enable you to send social media posts and get analytics effortlessly. For developers and businesses of all sizes.
The Social Media REST API provides developers with programmatic access to multiple social networks through a single unified interface.
Through Ayrshare's social API, you can manage social media activities including creating and deleting posts, retrieving analytics, engaging with comments and reviews, managing direct messages, creating Facebook ads, and performing other social media actions across platforms.
The API currently supports 13 major social networks: Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Telegram, Threads, TikTok, X (formerly Twitter), and YouTube.
By integrating with this API, developers can automate social media management tasks across all these platforms simultaneously.
API calls request and response data are in JSON format, which allow for easy parsing and processing in most programming languages.
If you are on the Launch, Business, or Enterprise Plan, see the [Business Plan Overview](/docs/multiple-users/business-plan-overview), [Launch Plan Overview](/docs/multiple-users/business-launch-overview), and [/profiles API endpoint](/docs/apis/profiles/overview).
## Key Functionality
[13 social networks supported](/docs/introduction#which-social-networks-are-supported).
Secure API access using your unique API Key.
Scheduled posting to connected social media platforms.
Automated posting based on predefined schedules.
Support for image and video content, including Reels, Stories, and Spotlight.
Delete posts on linked social networks.
Comprehensive post engagement analytics (likes, shares, etc.).
Social account metrics, including follower count and demographic data.
Comment management: view, add, and delete post comments.
Optional link shortening for all or specific URLs in posts.
Unsplash integration: add specific images or randomly select based on keywords.
Automatic hashtag generation option using relevant keywords.
Post history tracking, including non-Ayrshare posts.
Review management: retrieve, reply to, and delete review responses.
RSS feed integration for automated content posting.
Media library: upload and store photos and videos for use in posts.
[Social Post Verification System](/docs/testing/post-verification) to keep your social accounts safe.
## Business Plan and Launch Plan
[Business Plan](/docs/multiple-users/business-plan-overview) and [Launch Plan](/docs/multiple-users/business-launch-overview) features for managing multiple users and clients:
Enable users to link their own social media accounts to your platform.
Secure single sign-on using OAuth for quick account linking.
Create and remove user profiles programmatically through the API.
Access advanced user analytics.
Webhook support for real-time updates.
Direct message management across supported platforms.
Create Facebook ads from existing posts.
Contact us to learn more about the [Business Plan](https://www.ayrshare.com/business-plan-for-multiple-users/).
## Ads API
The [Ads API](/docs/apis/ads/overview) allows you to create Facebook ads from existing posts.
Boost posts to reach more people.
Manage ads and track performance.
Analyze ad spend and optimize campaigns.
Explore the Ads API
## Messages API
A unified [Messaging API](/docs/apis/messages/overview) to engage users in conversations across the major social media channels: Facebook, Instagram, and X.
Sending text, image, and video messages.
Retrieving complete conversation histories.
Setting up automated message responses.
Receiving real-time updates via webhooks for messages received, message reactions, read
receipts.
This API simplifies user engagement by centralizing messaging operations for multiple social media channels. Learn more...
Explore the unified messaging API
## Max Pack
Get even more capabilities with the [Max Pack add-on](/docs/additional/maxpack):
Unlock advanced features like AI-powered content generation, enhanced analytics, and expanded
platform support with our Max Pack add-on.
## Watch How to Use the Social API
If you're building in Node.js, check out this video on how to connect and publish posts to X and Facebook.
## Social API Demo
If you use Node.js see the social API demo code to get started building your own social API integration.
Explore our Node.js demo code to jumpstart your social API integration
## Base URL
The base URL for the Ayrshare API is the same for all endpoints.
`https://api.ayrshare.com/api`
## Authorization
Ayrshare authenticates API requests via an Authorization token passed in the HTTP header. Please be sure to send `Bearer` with the API Key. The API Key can be found in the Ayrshare Dashboard by switching to your Primary Profile.
If you are a Business or Enterprise user, you can create User Profiles with Profile Keys to manage multiple clients. The Profile Key is used in the header of your requests.
The API Key must also be used in the header of your requests for User Profiles.
Premium plans should only use the API Key in the header of their requests. Business and Enterprise
plans should use the Profile Key in the header of their requests when interacting on behalf of a
User Profile.
### API Key Format
`Authorization: Bearer API_KEY` replacing API\_KEY with your Primary Profile API Key, which can be [found in the Ayrshare Dashboard](/docs/quickstart#get-your-api-key).
```bash cURL theme={"system"}
curl -H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api
```
```javascript JavaScript theme={"system"}
headers: {"Authorization": "Bearer API_KEY"}
```
```python Python theme={"system"}
headers = {"Authorization": "Bearer API_KEY"}
```
```php PHP theme={"system"}
$headers = ["Authorization" => "Bearer API_KEY"];
```
```go Go theme={"system"}
headers := map[string]string{"Authorization": "Bearer API_KEY"}
```
```ruby Ruby theme={"system"}
headers = {"Authorization": "Bearer API_KEY"}
```
```java Java theme={"system"}
headers = {"Authorization": "Bearer API_KEY"}
```
```csharp C# theme={"system"}
headers = {"Authorization": "Bearer API_KEY"}
```
```rust Rust theme={"system"}
headers = {"Authorization": "Bearer API_KEY"}
```
Obtain your secret API Key in the Ayrshare dashboard under the API Key page found in the left navigation panel.
For example, if your API Key is 2MPXPKQ-S03M5LS-GR5RX5G-AZCK8EA
Your header should include:
`Authorization: Bearer 2MPXPKQ-S03M5LS-GR5RX5G-AZCK8EA`
### Profile Key Format
A Profile Key is used to interact on behalf of a User Profile.
This is only available for Business or Enterprise plans.
`Profile-Key: PROFILE_KEY` replacing PROFILE\_KEY with a user's [Profile Key](/docs/multiple-users/manage-user-profiles#get-the-profile-key).
**Including a Profile Key in the header is required to interact on behalf of a User Profile**.
A missing Primary Profile API Key or using the Profile Key in place of the API Key in the header will result in an error.
Here's how to structure the headers for API requests:
```bash cURL theme={"system"}
curl -H "Authorization: Bearer API_KEY" \
-H "Profile-Key: PROFILE_KEY" \
-X GET https://api.ayrshare.com/api
```
```javascript JavaScript theme={"system"}
headers: {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```python Python theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```php PHP theme={"system"}
$headers = [
"Authorization" => "Bearer API_KEY",
"Profile-Key" => "PROFILE_KEY"
];
```
```go Go theme={"system"}
headers := map[string]string{
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```ruby Ruby theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```java Java theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```csharp C# theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
```rust Rust theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY"
}
```
[Find the Profile Key](/docs/multiple-users/manage-user-profiles#get-the-profile-key) in the Ayrshare Dashboard under the Profile Key page found in the left navigation panel.
Switch to the Profile you want to use in the User Profile page.
Additionally, the Profile Key is returned in the response of the [Create a User Profile](/docs/apis/profiles/create-profile) endpoint.
You can then use the Profile Key in the header of your requests:
For example, if your Profile Key is `AX1XGG-9jK3M5LS-GR5RX5G-LLCK8EA`
Your header should include both the API and Profile Key:
`Authorization: Bearer 2MPXPKQ-S03M5LS-GR5RX5G-AZCK8EA`
`Profile-Key: AX1XGG-9jK3M5LS-GR5RX5G-LLCK8EA`
### X/Twitter BYO Credentials
Starting March 31, 2026, all X/Twitter operations through Ayrshare require your own OAuth 1.0a credentials. After linking your X account via OAuth, pass these 2 headers alongside your `Authorization` (and optional `Profile-Key`) headers for any request that targets X/Twitter:
| Header | Description |
| ----------------------------- | ------------------------------------------------ |
| `X-Twitter-OAuth1-Api-Key` | Your OAuth 1.0a API Key (Consumer Key) |
| `X-Twitter-OAuth1-Api-Secret` | Your OAuth 1.0a API Key Secret (Consumer Secret) |
These headers are required after March 31, 2026. Requests to X/Twitter endpoints without valid BYO credentials will be rejected.
**One key pair, used for every request.** You create one X Developer App per Ayrshare account and use the same `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret` values on every X-targeting request, regardless of which sub-profile (`Profile-Key`) the request is for. You do not generate or rotate keys per customer or per end-user.
See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for step-by-step instructions, code examples, and troubleshooting.
The same two headers apply when driving X/Twitter through the [MCP Server](/docs/additional/mcp-action-server) — see [Connect & Setup](/docs/additional/mcp-action-connect).
## Content Type
The Content Type should always be set as `Content-Type: "application/json"` unless the endpoint specifically specifies otherwise.
```bash cURL theme={"system"}
curl -H "Authorization: Bearer API_KEY" \
-H "Profile-Key: PROFILE_KEY" \ # Optional
-H "Content-Type: application/json" \
-X GET https://api.ayrshare.com/api
```
```javascript JavaScript theme={"system"}
headers: {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json"
}
```
```python Python theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", # Optional
"Content-Type": "application/json"
}
```
```php PHP theme={"system"}
$headers = [
"Authorization" => "Bearer API_KEY",
"Profile-Key" => "PROFILE_KEY", # Optional
"Content-Type" => "application/json"
];
```
```go Go theme={"system"}
headers := map[string]string{
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json"
}
```
```ruby Ruby theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", # Optional
"Content-Type": "application/json"
}
```
```java Java theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json"
}
```
```csharp C# theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json"
}
```
```rust Rust theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json"
}
```
## Compression
Ayrshare supports compression for all API requests.
To enable compression, set the `Accept-Encoding` header to `deflate, gzip, br`.
```bash theme={"system"}
Accept-Encoding: "deflate, gzip, br"
```
This is recommended for calling larger responses such as the [/history endpoint](/docs/apis/history/overview).
Only responses over 1024 bytes (1KB) are compressed.
The order of compress used: Brotli (br) first, then gzip, then deflate. Brotli is the most
efficient compression algorithm.
The response header contains the content encoding used. For example: `content-encoding: br` if
Brotli was used.
Learn more about compression and the benefits of using compression in the [Ayrshare
Blog](https://www.ayrshare.com/blog/http-compression-in-node-js-a-dive-into-gzip-deflate-and-brotli/).
Don't forget to properly uncompress the response using the content encoding.
```bash cURL theme={"system"}
curl -H "Authorization: Bearer API_KEY" \
-H "Profile-Key: PROFILE_KEY" \ # Optional
-H "Content-Type: application/json" \
-H "Accept-Encoding: deflate, gzip, br" \
-X GET https://api.ayrshare.com/api
```
```javascript JavaScript theme={"system"}
headers: {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```python Python theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", # Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```php PHP theme={"system"}
$headers = [
"Authorization" => "Bearer API_KEY",
"Profile-Key" => "PROFILE_KEY", # Optional
"Content-Type" => "application/json",
"Accept-Encoding" => "deflate, gzip, br"
];
```
```go Go theme={"system"}
headers := map[string]string{
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```ruby Ruby theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", # Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```java Java theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```csharp C# theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
```rust Rust theme={"system"}
headers = {
"Authorization": "Bearer API_KEY",
"Profile-Key": "PROFILE_KEY", // Optional
"Content-Type": "application/json",
"Accept-Encoding": "deflate, gzip, br"
}
```
## ID Types
There are several types of IDs returned, which can be used in various endpoints:
### Ayrshare Post ID
This ID is generated by Ayrshare and returned from the
[/post endpoint](/docs/apis/post/post) in the `id` field. This ID makes it easy
to get analytics on the post across social networks, add comments to the
post, delete the post, etc. This is the ID you will use most often.
### Social Post ID
Each social network assigns their own unique ID to posts and comments.
These IDs are returned in the `postIds` field of the /post or /comments endpoints.
You can use these IDs, or ones you get directly from the social networks, to retrieve data, such as with the [analytics social post ID](/docs/apis/analytics/social-by-id).
### Ayrshare Comment ID
This ID is generated by Ayrshare and returned from the
[/comments endpoint](/docs/apis/comments/post-comment) in the `id` field. This ID makes it easy
to get analytics on the comment across social networks, add replies to the
comment, delete the comment, etc. This is the ID you will use most often.
This is often used if you want to get details on a particular comment published via Ayrshare.
### Social Comment ID
Each social network assigns their own unique ID to comments.
These IDs are returned in the `commentId` field of the [GET /comments endpoint](/docs/apis/comments/get-comments).
This is often used if you want to get details on a particular comment published outside of Ayrshare.
## Error Codes
Errors will return with [standard HTTP status codes](https://tools.ietf.org/html/rfc2616#section-10).
For more information:
Learn more about HTTP status codes
Detailed Errors are in the REST API response specific for each type of call.
For more information:
Learn more about Ayrshare-specific error codes
## Timestamp Format
Ayrshare uses Zulu Time, also known as UTC (Coordinated Universal Time) or an ISO 8601 formatted date string, for a precise and unambiguous time references across different time zones.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
You can convert the UTC format to your local time in the programming language of your choice. For example in JavaScript:
```javascript theme={"system"}
const convertToLocalTime = (isoString) => {
// Create a new Date object from the ISO string
const date = new Date(isoString);
// Extract local time components
const localDate = date.toLocaleDateString();
const localTime = date.toLocaleTimeString();
// Combine the local date and time
const localDateTime = `${localDate} ${localTime}`;
return localDateTime;
};
```
## Postman
You can use Postman to test your REST API calls.
Learn how to use Postman with our API
## Random Posts, Images, and Videos
Check out the [quick start guide](/docs/quickstart#publish-test-posts) on how to send random posts, images, or videos when testing.
## Packages
We have both Node.js & Python packages, Bubble.io, Airtable, and Make guides available to make the RESTful calls easier.
Integrate using our NodeJS package
Integrate using our Python package
Learn how to use Ayrshare with Airtable
Learn how to use Ayrshare with Bubble.io
Learn how to use Ayrshare with Make
Learn how to use Ayrshare with Notion
Learn how to use Ayrshare with FlutterFlow
Learn how to use Ayrshare with Retool
# Bulk Post
Source: https://www.ayrshare.com/docs/apis/post/bulk-post
PUT /post/bulk
Bulk schedule posts with a CSV file
Bulk schedule posts with CSV (Comma Separated Values) file of posts data.
Content-Type must be `multipart/form-data`.
We recommend using the direct [Post endpoint](/docs/apis/post/post) instead of this bulk method for
scheduling posts. The direct endpoint provides a more comprehensive feature set and easier
debugging capabilities.
## Header Parameters
Format: `Authorization: Bearer API_KEY`. See [API overview](/docs/apis/overview#authorization) for more
information.
Profile Key of a user profile.
`Content-Type: multipart/form-data`
## Body Parameters
Multipart form-data CSV file of scheduled posts. See below for [CSV template](#csv-template).
## Request Examples
A multipart form-data containing a CSV file of posts will schedule them for a future date.
The CSV file contains the following fields (template below) and are required:
`post`: The post text.
`platforms`: Comma separated list of platforms, e.g. "twitter, facebook, instagram".
`mediaUrls`: URL of media, such as an image or video to include in the post.
`scheduleDate`: Datetime to schedule the post in UTC format. For example, use format
`YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`. Please see
[utctime](https://www.utctime.net/) for more examples.
Don't send duplicate posts less than two days apart.
If the scheduleDate of two posts with the exact same text are less than three days apart, the second post will be rejected when the scheduleDate occurs.
This is to protect your account at the networks; they can suspend or shadow-ban accounts with frequent duplicate posts.
## CSV Template
Download the template and save as a .csv file.
[Ayrshare CSV Template](https://img.ayrshare.com/012/Ayrshare_CSV_Template.csv)
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: multipart/form-data' \
-F 'file=@"./Ayrshare CSV Template.csv"' \
-X POST https://api.ayrshare.com/api/post/bulk
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const FormData = require("form-data");
const fs = require("fs");
const formData = new FormData();
formData.append("file", fs.createReadStream("./Ayrshare CSV Template.csv"));
fetch("https://api.ayrshare.com/api/post/bulk", {
method: "POST",
headers: {
Authorization: `Bearer ${API_KEY}`,
...formData.getHeaders()
},
body: formData
})
.then((res) => res.json())
.then((data) => {
console.log(JSON.stringify(data));
})
.catch((error) => {
console.log(error);
});
```
```python Python theme={"system"}
import requests
API_KEY = "API_KEY"
# Open the CSV file in binary read mode
with open('./Ayrshare CSV Template.csv', 'rb') as file:
# Prepare the files dictionary for the multipart/form-data request
files = {'file': file}
# Set up the authorization header
headers = {'Authorization': f'Bearer {API_KEY}'}
try:
# Make the POST request to the API
response = requests.post(
'https://api.ayrshare.com/api/post/bulk',
headers=headers,
files=files
)
# Parse and print the JSON response
data = response.json()
print(data)
except Exception as e:
print(f"Error: {e}")
```
```javascript 200: OK Example with two scheduled posts. theme={"system"}
{
"status": "success",
"posts": [
{
"status": "scheduled",
"scheduleDate": "4/6/21 12:50",
"id": "X3uTExuEJhyM3u8wCRsA",
"post": "A great post"
},
{
"status": "scheduled",
"scheduleDate": "4/6/21 13:00",
"id": "8RGrekuxMnVa7lVnARFm",
"post": "An even better post"
}
]
}
```
# Copy a Post
Source: https://www.ayrshare.com/docs/apis/post/copy-post
POST /post/copy
Copy an existing post to new social media platforms
Copy an existing post to new social media platforms with the same content and settings. This endpoint allows you to reuse successful posts across different platforms or with different configurations.
Please be sure to add your `API_KEY`, and the `PROFILE_KEY` if copying to a User Profile, in the [Authorization header](/docs/apis/overview#authorization).
The API Key can be found in the Ayrshare Developer Dashboard under the API Key page.
## Header Parameters
## Body Parameters
The ID of the existing post to copy. This is the Ayrshare Post ID returned from the original
`/post` endpoint.
Social media platforms to post the copied content to. Accepts an array of Strings with values: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, or `youtube`.
Please note: use `facebook` for Facebook Pages, and `gmb` for Google Business Profile.
The platforms specified here will override the original post's platforms - you must explicitly choose which platforms to copy to.
The datetime to schedule the copied post. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
If not provided, the post will be published immediately.
Override the original post's Bluesky settings. See [Bluesky
details](/docs/apis/post/social-networks/bluesky).
Override the original post's Facebook settings. See [Facebook
details](/docs/apis/post/social-networks/facebook).
Override the original post's Google Business Profile settings. See [Google Business Profile
details](/docs/apis/post/social-networks/google).
Override the original post's Instagram settings. See [Instagram
details](/docs/apis/post/social-networks/instagram).
Override the original post's LinkedIn settings. See [LinkedIn
details](/docs/apis/post/social-networks/linkedin).
Override the original post's Pinterest settings. See [Pinterest
details](/docs/apis/post/social-networks/pinterest).
Override the original post's Reddit settings. See [Reddit
details](/docs/apis/post/social-networks/reddit).
Override the original post's Snapchat settings. See [Snapchat
details](/docs/apis/post/social-networks/snapchat).
Override the original post's Telegram settings. See [Telegram
details](/docs/apis/post/social-networks/telegram).
Override the original post's Threads settings. See [Threads
details](/docs/apis/post/social-networks/threads).
Override the original post's TikTok settings. See [TikTok
details](/docs/apis/post/social-networks/tiktok).
Override the original post's X/Twitter settings. See [X/Twitter
details](/docs/apis/post/social-networks/x-twitter).
Override the original post's YouTube settings. See [YouTube
details](/docs/apis/post/social-networks/youtube).
Override the original post's link shortening setting.
[Max Pack required](/docs/additional/maxpack) for link shortening.
Override the original post's auto hashtag settings. See [auto
hashtags](/docs/apis/post/overview#auto-hashtags) for details.
Override the original post's comment settings. Only available for Instagram, LinkedIn, and TikTok.
Override the original post's first comment settings. See [first
comment](/docs/apis/post/overview#first-comment) for details.
Add new notes to the copied post. These will replace any notes from the original post. Notes are
for reference only and do not affect the post content.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"postId": "RhrbDtYh7hdSMc67zC8H",
"platforms": ["twitter", "facebook", "linkedin"],
"scheduleDate": "2026-07-08T12:30:00Z"
}' \
-X POST https://api.ayrshare.com/api/post/copy
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post/copy", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
postId: "RhrbDtYh7hdSMc67zC8H", // required
platforms: ["twitter", "facebook", "linkedin"], // required
scheduleDate: "2026-07-08T12:30:00Z", // optional
faceBookOptions: {
link: "https://example.com/new-link"
}
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {
'postId': 'RhrbDtYh7hdSMc67zC8H',
'platforms': ['twitter', 'facebook', 'linkedin'],
'scheduleDate': '2026-07-08T12:30:00Z',
'faceBookOptions': {
'link': 'https://example.com/new-link'
}
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
}
r = requests.post('https://api.ayrshare.com/api/post/copy',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"RhrbDtYh7hdSMc67zC8H",
"platforms" => ["twitter", "facebook", "linkedin"],
"scheduleDate" => "2026-07-08T12:30:00Z",
"faceBookOptions" => [
"link" => "https://example.com/new-link"
]
];
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.ayrshare.com/api/post/copy',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer API_KEY',
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"postId": "RhrbDtYh7hdSMc67zC8H",
"platforms": []string{"twitter", "facebook", "linkedin"},
"scheduleDate": "2026-07-08T12:30:00Z",
"faceBookOptions": map[string]interface{}{
"link": "https://example.com/new-link",
},
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/post/copy",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostCopyRequest_csharp
{
class PostCopy
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post/copy";
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"postId\" : \"RhrbDtYh7hdSMc67zC8H\","
+ "\"platforms\" : [ \"twitter\", \"facebook\", \"linkedin\" ],"
+ "\"scheduleDate\" : \"2026-07-08T12:30:00Z\"}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```ruby Ruby theme={"system"}
require 'httparty'
res = HTTParty.post("https://api.ayrshare.com/api/post/copy",
headers: {Authorization: "Bearer API_KEY"},
body: {
postId: "RhrbDtYh7hdSMc67zC8H",
platforms: ['twitter', 'facebook', 'linkedin'],
scheduleDate: '2026-07-08T12:30:00Z',
faceBookOptions: {
link: 'https://example.com/new-link'
}
}).body
puts res
```
```json 200: Success - Immediate Post theme={"system"}
{
"status": "success",
"copiedFrom": "RhrbDtYh7hdSMc67zC8H",
"originalPost": "Today is a great day!",
"errors": [],
"postIds": [
{
"status": "success",
"id": "1288899996423983106",
"platform": "twitter",
"postUrl": "https://x.com/handle/status/1288899996423983106"
},
{
"status": "success",
"id": "104923907983682_108329000309743",
"platform": "facebook",
"postUrl": "https://www.facebook.com/104923907983682_108329000309743"
},
{
"status": "success",
"id": "urn:li:share:7282181682126807042",
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:7282181682126807042",
"owner": "urn:li:organization:77682157",
"platform": "linkedin"
}
],
"id": "KpwxFmNj3kgQLa92vE5T"
}
```
```json 200: Success - Scheduled Post theme={"system"}
{
"status": "scheduled",
"scheduleDate": "2025-05-28T14:32:00Z",
"id": "KpwxFmNj3kgQLa92vE5T",
"refId": "7a8e2f15c94d73a6e2bf89dd4c847b9f2e3a6d18",
"copiedFrom": "RhrbDtYh7hdSMc67zC8H",
"originalPost": "Today is a great day!"
}
```
```json 400: Bad Request theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 156,
"message": "Threads is not linked. Please confirm the linkage on the Social Accounts page in the dashboard. https://www.ayrshare.com/docs/dashboard/connect-social-accounts/overview",
"platform": "threads"
}
],
"postIds": [],
"id": "KpwxFmNj3kgQLa92vE5T",
"refId": "7a8e2f15c94d73a6e2bf89dd4c847b9f2e3a6d18"
}
```
```json 400: Bad Request - Missing Platforms theme={"system"}
{
"status": "error",
"code": 163,
"message": "Missing, empty, or not valid platforms parameter. Please verify sending an array of valid platforms. https://www.ayrshare.com/docs/apis/post",
"details": "platforms parameter is required for copying posts"
}
```
```json 400: Bad Request - Duplicate or Similar Content theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 137,
"message": "Duplicate or similar content posted within the same two day period. The social networks prohibit duplicate content and ban accounts that do not comply. https://www.ayrshare.com/docs/help-center/technical-support/dealing_with_duplicate_posts#dealing-with-duplicate-posts",
"details": "Duplicate found in user profile: \"Primary Profile\", post id: e5ELaDhKjhJBU1z6dbud, and refId: 5da3de47a8e3b1d8c2bd319350aa7d4e85d4ec74",
"verifyCheck": true,
"platform": "twitter"
}
],
"postIds": [],
"id": "KpwxFmNj3kgQLa92vE5T",
"refId": "7a8e2f15c94d73a6e2bf89dd4c847b9f2e3a6d18"
}
```
# Delete a Post
Source: https://www.ayrshare.com/docs/apis/post/delete-post
DELETE /post
Delete a post using the post ID
Delete a post using the post ID returned from the [/post](/docs/apis/post/post) endpoint.
You can delete both published and scheduled posts, but there are some differences based on the social network `platform`:
Scheduled posts can be deleted for all social networks `platforms`.
Published posts can be deleted for all social networks `platforms` except
for Instagram and TikTok. Instagram and TikTok do not provide API support
for deleting published posts. If you need to delete a published post on
these platforms, you must do so manually using their respective mobile apps.
Facebook does not permit deleting image stories via their API (video stories
can be deleted). If you need to delete an image story, please go to the
Facebook mobile app and perform the deletion manually.
Instagram and TikTok do not support delete via their APIs. Please go to the
Instagram or TikTok mobile apps to delete the posts.
Facebook does not support image story deletion via its API. Please go to the
Facebook mobile app to delete stories.
## Header Parameters
## Body Parameters
Ayrshare Post ID of the post to delete.
Not required if `bulk` or `deleteAllScheduled` parameter sent.
If the post is scheduled and still `pending`, the scheduled posts will be deleted and not sent to the networks.
If the post has already been sent to the networks, the post will be deleted from the networks.
Array of Strings post Ids to bulk delete.
Required if `id` or `deleteAllScheduled` parameter not sent.
If `true` will delete all scheduled posts still in a pending state, i.e. posts that have not yet been published to the networks, for the User Profile.
The `id` or `bulk` parameters are ignored if set to `true`.
This will delete all scheduled posts, so be sure to use this with caution.
If `true`, the post will mark as deleted in Ayrshare and Ayrshare will not try to delete the post at the networks.
A common use case for this is when the post was manually deleted at the networks and you want to mark it as deleted in Ayrshare.
Prior to marking the post as deleted, please ensure that the post was already manually deleted on the social networks.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API Key" \
-H 'Content-Type: application/json' \
-d '{"id": "Post ID"}' \
-X DELETE https://api.ayrshare.com/api/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const id = "Post ID";
fetch("https://api.ayrshare.com/api/post", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({ id }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': 'Post ID'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$postId]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace DeletePOSTRequest_csharp
{
class Delete
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post";
// Set up request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
// Prepare JSON content
string json = "{\"id\" : \"Post ID\"}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
// Create and send DELETE request with content
var request = new HttpRequestMessage
{
Method = HttpMethod.Delete,
RequestUri = new Uri(url),
Content = content
};
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
// Read response
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```javascript 200: Success theme={"system"}
{
"twitter": {
"action": "delete",
"status": "success",
"id": "1288900099663775749" // Twitter Social Post ID
},
"facebook": {
"action": "delete",
"status": "success",
"id": "104920007983682_108683297607743" // Facebook Social PostID
},
"status": "success"
}
```
```json 200: Success with markManualDeleted theme={"system"}
{
"status": "success",
"id": "p8Ee6xDPx8PRxsjtDXf3" // Ayrshare Post ID
}
```
```json 400: ID Not Found theme={"system"}
{
"action": "delete",
"status": "error",
"code": 114,
"message": "Delete id not found.",
"id": "IdpUOyihLEpIx0d0N9mI" // Ayrshare Post ID used for delete, comment, analytics, etc.
}
```
```json 400: Post Already Deleted theme={"system"}
{
"action": "delete",
"status": "error",
"code": 383,
"message": "The post is already deleted.",
"id": "p8Ee6xDPx8PRxsjtDXf3" // Ayrshare Post ID
}
```
```json 400: Mark Manual Deleted Error theme={"system"}
{
"action": "delete",
"status": "error",
"code": 382,
"message": "The post was not manually deleted at the social network. By using the markManualDeleted option, you are responsible for deleting the post at the social network. Please delete the post and try again.",
"id": "DD3fA2DC4qe2T48hSdgs",
"markManualDeleted": true
}
```
# Get a Post
Source: https://www.ayrshare.com/docs/apis/post/get-post
GET /post/:id
Retrieve a post by Ayrshare Post ID
Get the history for a specific posts sent via Ayrshare. Returns the status, post parameters, and other details. Replace `:id` with the Ayrshare Post ID.
Call the [/history by id](/docs/apis/history/get-history-id) endpoint for the same data.
## Post Statuses
The following statuses are returned for a post.
| Status | Description |
| :------------------ | :----------------------------------------------------------------------------------------------------------- |
| `awaiting approval` | Posts are waiting to be approved via the [approval workflow](/docs/apis/post/overview#approval-workflow). |
| `deleted` | Post has been deleted. Note: deleted posts are only returned with the status query filter. Please see below. |
| `error` | An error occurred with one or more social networks. |
| `pending` | The post has not yet been processed. Typically a scheduled post. |
| `success` | The post was successfully sent to all social networks. |
See the [/history](/docs/apis/history/overview) endpoint for retrieving all posts, including
posts not sent via Ayrshare.
## Header Parameters
## Path Parameters
Ayrshare Post ID from /post
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/post/TBEAAqAMMJoweA9wKHUl
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post/TBEAAqAMMJoweA9wKHUl", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/post/TBEAAqAMMJoweA9wKHUl', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
```json 200: Success theme={"system"}
{
"created": "2024-11-19T19:00:14Z",
"errors": [],
"id": "8tNTr73VV8Y66bHwC2322",
"mediaUrls": [
"https://img.ayrshare.com/012/gb.jpg"
],
"platforms": [
"twitter"
],
"post": "#75304 Eighty percent of success is showing up. - John D. Rockefeller",
"postIds": [
{
"status": "success",
"id": "1858948421974925758",
"postUrl": "https://twitter.com/wondrouswaffles/status/185894842197493444",
"platform": "twitter"
}
],
"profileTitle": "Best Profile",
"refId": "b68bdcabb379be2cf1186c1e59544",
"scheduleDate": "2024-11-19T19:00:14Z",
"shortenLinks": false,
"status": "success",
"type": "now"
}
```
```json 400: Bad Request ID not found theme={"system"}
{
"action": "history",
"status": "error",
"code": 221,
"message": "History not found.",
"id": "4W3f3RPr6QSrw8S5Yo8"
}
```
# Post API Overview
Source: https://www.ayrshare.com/docs/apis/post/overview
Schedule posts, auto hashtag, auto-post schedule, and more
The post endpoint allows you to publish posts to the social networks: Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Telegram, TikTok, WhatsApp (Private Beta), X/Twitter, and YouTube.
There are many options to customize your post, such as scheduling posts, adding auto hashtag, auto-post schedule, and more.
Often this is used by agencies when multiple stakeholders need to approve a post before it is published.
**WhatsApp is in Private Beta.** If you'd like early access to publishing on
WhatsApp, email [lotty@ayrshare.com](mailto:lotty@ayrshare.com).
Start publishing posts with the [/post POST endpoint](/docs/apis/post/post).
## Approval Workflow
If your publishing workflow requires approval before sending a post, set the `requiresApproval` field to `true`.
This is equivalent to pausing the post until the `approved` parameter is set to `true`.
### Approval Workflow Example
The post will have a status of "awaiting approval" until the `approved` parameter is set to `true` via the [/post PATCH endpoint](/docs/apis/post/update-post).
Publish your post using the [/post endpoint](/docs/apis/post/post) with the `requiresApproval` field
as `true`. You may also including standard parameters such as `scheduleDate`.
The post will be in a status of "awaiting approval" and will be held until approval is granted.
Update the post with the [/post PATCH operation](/docs/apis/post/update-post) setting the `approved`
field as `true`. The post will now be sent at the scheduled time.
Optional: Set `notes` on the post for reference, such as who needs to approve the post.
```json Publish the Post with Approval theme={"system"}
{
"requiresApproval": true,
"notes": "need approval by John Smith" // optional
}
```
If the `scheduleDate` is included and the date is in the past, the post will be published
immediately upon approval.
### Approval Workflow Video
Please see the video below for an example of the approval workflow.
## Auto Hashtags
Add the most relevant hashtags to your post.
`autoHashtag` is an object, or Boolean - see below, with the following parameters:
`max`: (optional) Integer of hashtags to add, range 1-10. Default 2.
`position`: (optional) String "auto" or "end". Auto adds the hashtags within the post or to the
end. "end" adds hashtags just to the end.
*A paid plan is required.*
```json theme={"system"}
{
"hashtags": {
"max": 3, // optional: Integer range 1-10
"position": "auto" // optional: String "auto" or "end"
}
}
```
If you do not want to send any of the above options, pass the Boolean value `true` instead of an object.
```json theme={"system"}
{
"autoHashtag": true
}
```
## Auto Repost
Automatically reposts your content multiple times at regular intervals, creating evergreen content that stays fresh and visible to your audience.
A paid plan is required.
Parameters:
* `repeat`: (required) The number of times to repost the content. Must be between 1 and 10.
* `days`: (required) The number of days between each repost. Must be at least 2 days.
* `startDate`: (optional) When to start the repost schedule, in ISO-8601 UTC format. If not specified, the first post will be published immediately. You should use the `startDate` parameter in lieu of the top-level `scheduleDate` parameter.
```json Auto Repost theme={"system"}
{
"repeat": 2, // min 2, max 10
"days": 5, // min 2
"startDate": "2021-07-08T12:30:00Z"
}
```
The response will included all the future scheduled reposts and an `autoRepostId` for each repost.
```json Auto Repost Response theme={"system"}
{
"status": "scheduled",
"scheduleDate": "2025-06-13T12:30:00.000Z",
"id": "eIT96IYEodNuzU4oMmwG",
"refId": "9abf1426d6ce9122ef11c72bd",
"autoRepostId": "F5wdoaOAAGtDQVciExSxL",
"post": "The most important things are the hardest to say - Stephen King"
}
```
When creating an auto repost an ID `autoRepostId` is assigned to track that series of posts.
You may get all of the auto reposts for a post with the [History call](/docs/apis/history/get-history) with the `autoRepostId`.
If you need to delete a repost, you can use the [DELETE call](/docs/apis/post/delete-post) with the post ID.
Important: When using auto-repost, ensure you follow each social network's posting frequency guidelines to avoid account restrictions.
Note: The `autoRepost` feature cannot be used together with `scheduleDate`. If you include both parameters, the `scheduleDate` will take precedence and `autoRepost` will be ignored. Please use the `startDate` parameter instead.
## First Comment
Automatically add in a first comment, with media, after the post is published. For TikTok the comment is deferred until the video finishes processing (see [First Comment Processing Time](#first-comment-processing-time)).
Posting the first comment on your own social media post can help kickstart engagement and set the tone for the discussion that follows.
```json theme={"system"}
{
"firstComment": {
"comment": "My first comment", // required
"mediaUrls": ["https://..."] // Facebook, LinkedIn, and X/Twitter only
}
}
```
## First Comment Processing Time
For most social networks, the API response is delayed because our system must (1) wait for the original post to be fully published, then (2) add the comment to that published post. This sequential process adds an approximately 20 second delay.
**TikTok is handled differently.** TikTok processes videos asynchronously, so the post `id` is `"pending"` until TikTok's `post.publish.publicly_available` webhook resolves the real video id (see [TikTok Processing](/docs/apis/post/social-networks/tiktok#tiktok-processing)). The `/post` response therefore returns the TikTok first comment with `status: "pending"` right away, and the comment is posted automatically once TikTok finishes processing and the [`tikTokPublished` Scheduled Action webhook](/docs/apis/webhooks/actions#scheduled-action) fires. TikTok does not guarantee a processing time, so there is no fixed delay.
**Important TikTok Note**: For first comments to work properly on TikTok, the post's `visibility` parameter must be set to `public`. A non-public video never receives the `publicly_available` webhook, so its first comment cannot be posted; in that case Ayrshare returns a comment error rather than leaving it pending.
## Idempotent Posts
[Idempotency ](https://en.wikipedia.org/wiki/Idempotence) is an optional feature that ensures a request is only executed once, even if it is accidentally sent multiple times.
When posting content using the API, you can include an optional `idempotencyKey` parameter in the request body to uniquely identify the operation. This allows you to safely retry the post request without the risk of creating duplicate posts.
To use idempotency, add the `idempotencyKey` parameter to the JSON body of the `/post` POST request:
```json Idempotency Key theme={"system"}
{
"idempotencyKey": "Unique Key"
}
```
The value of `idempotencyKey` should be a unique string per User Profile. If a request is made with the same `idempotencyKey` for a given User Profile, regardless of the post's state (success, error, pending, or deleted), an error will be returned, indicating that a duplicate key was found.
The API must first accept and process the POST request to store the idempotency key and check for
duplicates. However, if multiple POST requests with the same `idempotencyKey` are sent
simultaneously or scheduled for the same posting time, the API may not detect the duplicate keys.
This is because the API processes these concurrent or simultaneously scheduled requests in
parallel, before it has a chance to register the idempotency key from any single request. As a
result, there's no guarantee that duplicate idempotent keys will be caught in these scenarios of
simultaneous submission or execution of scheduled posts.
Using idempotency helps prevent the accidental creation of duplicate posts when retrying failed requests or handling network issues. However, it's still recommended to implement appropriate error handling and retry mechanisms in your application to handle potential failures gracefully.
## Image & Video Requirements
Posting images and videos have different requirements for each network, but don't worry. Our system verifies your post before sending, so you'll get an error response if something is wrong. See the below link of details on image and video guidelines.
### Valid URL
Be sure your media URL(s) are valid and directly access the media.
A first test is trying the URL in a browser.
If the image will not load or cannot be downloaded in a browser it will likely fail.
For example, a DropBox URL that opens the DropBox web app will not work.
If you have a [Google Drive Share
URL](https://www.ayrshare.com/how-to-get-direct-download-urls-from-google-drive/) or a [Dropbox
Share URL](https://www.ayrshare.com/blog/how-to-get-direct-download-urls-from-dropbox/), you can just
use the URL in the `mediaUrls` parameter when publishing a post or comment. Ayrshare will
automatically convert the share URL to a download link.
We verify the media URL by making a `HEAD` request.
Please be sure the hosting provider is not blocking the `HEAD` request or the post will fail with a 403 error.
For example, here is a `HEAD` request to the media URL:
```javascript Fetch HEAD Request theme={"system"}
const run = async () => {
const url = "https://img.ayrshare.com/012/gb.jpg";
return await fetch(url, {
method: "HEAD"
})
.then((res) => {
if (res.ok) {
return console.log("Success:", res.status, res.statusText);
} else {
return console.error("Error:", res.status, res.statusText, res);
}
})
.catch((error) => {
return console.error("Error Catch:", error);
});
};
run();
```
#### Automated Media Protection
Ayrshare includes built-in media protection that can detect and resolve certain media delivery issues during posting. When a post succeeds but a content issue was detected and resolved, each affected entry in `postIds[]` includes an optional `contentIssues` object so you can identify and fix the underlying issue:
```json theme={"system"}
{
"postIds": [
{
"status": "success",
"platform": "instagram",
"id": "17878176260289172",
"postUrl": "https://www.instagram.com/p/CP1dI9Hp_WO/",
"contentIssues": {
"originMediaHostFailed": true,
"details": ["Media URL could not be retrieved by the social network. Successfully posted using Ayrshare automated media protection."]
}
}
]
}
```
If you see `originMediaHostFailed` in your responses, review your media hosting configuration. See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) for common causes and solutions.
#### Spaces & Special Characters
We recommend to avoid the following in your media URLs:
Spaces in the URL.
URL encoded spaces in the URL.
Special characters in the URL even if they are url encoded, such as accent marks é.
For example:
```bash theme={"system"}
https://img.ayrshare.com/012/test .webp
```
This URL fails because of the space `test .webp`. We also don't recommend using URL encoded spaces, such as `%20` in the URL - this can also cause issues with some social networks.
And this Unsplash image:
```bash theme={"system"}
https://unsplash.com/photos/a-house-in-the-middle-of-a-field-with-trees-in-the-background-znbmh2-cIj0
```
This Unsplash image fails because it isn't directly accessing the image, but showing a web app.
#### Sanitize File Names & URLs
You can sanitize your file names with a regular express such as `/[^a-z0-9\/\.]/gi`.
```javascript theme={"system"}
const sanitizeFileName = (url) => url.replace(/[^a-z0-9\/\.]/gi, "_");
sanitizeFileName("tést .webp"); // t_st_.webp
```
or sanitize a URL
```javascript theme={"system"}
const sanitizeUrl = (url) => {
const [protocol, rest] = url.split("://");
const [domain, ...path] = rest.split("/");
const sanitizedPath = path.join("/").replace(/[^a-z0-9\/\.]/gi, "_");
return `${protocol}://${domain}/${sanitizedPath}`;
};
// Output: https://img.ayrshare.com/012/t_st_.webp
sanitizeUrl("https://img.ayrshare.com/012/tést .webp");
```
### Additional Information
If you're self hosting, make sure the URL can be externally accessed and doesn't require
special permissions.
See below the how to handle videos with unknown extensions, often signed URLs such as AWS S3.
If you are using a signed URL, such as S3, we recommend to set the URL expiration to at least
7 days. This allows our team to assist with any questions you have on publishing the post.
Test if the media URL exists with our [verify media tools](/docs/apis/media/verify-media-url).
### Download Speed
Be sure your media hosting has a fast connection, especially download speed. You can test your media hosting performance at [pingdom](https://tools.pingdom.com/). We recommend at least a *B rating*.
### Video Extension
If your URL does not end in a known video extension such as `mp4`, you can use the `isVideo: true` field in the post to specify the `mediaUrl` is a video . Ayrshare will try to determine the file type, such as `MOV`. However, we recommend explicitly ending your video file with a known extension, such as `mp4`, since this has a higher success rate with the social networks.
### Image or Video Only
A few social networks support sending media without post text. If you do not want post text included, send an empty string: `post: ""`
The following social networks support no post/blank text: Facebook, Instagram, LinkedIn, Threads, TikTok, and X/Twitter.
### Testing Images and Videos
Consider using the [generate random text and random image or video](/docs/quickstart#sending-test-posts-with-a-random-quote-image-or-video) to speed up your testing. Stop trying to think up something different for each of your test posts!
## Line Breaks
If you want to line breaks (new lines) in a post, use the invisible line break `\u2063\n.`For example, `This is a new\u2063\nline.`
We also recommend trying in Postman to see how the new line break is translated in your language of choice. For example, PHP often only uses a `\n`
Some social networks do not currently support line breaks in the post text.
## Multi-Platform Posts and Media
This feature allows you to customize your post content and media for different social networks within a single API call. You can specify unique text and/or images for each platform by using objects for the `post` and `mediaUrls` fields.
1. Use an object structure for `post` and/or `mediaUrls` fields.
2. Specify platform-specific content using platform names as keys.
3. Include a `default` key for content to be used on platforms not explicitly specified.
```json theme={"system"}
{
"post": {
"instagram": "Great IG pic!",
"facebook": "Great FB pic!",
"default": "Great default pic!"
},
"platforms": ["instagram", "facebook", "linkedin"],
"mediaUrls": {
"instagram": "https://img.ayrshare.com/012/gb.jpg",
"linkedin": "https://img.ayrshare.com/012/gb.jpg",
"default": "https://img.ayrshare.com/012/gb.jpg"
}
}
```
In the example above:
Instagram will use its specific text and image URL.
Facebook will use its specific text and the default image URL.
LinkedIn will use the default text and its specific image URL.
If you need to post multiple images to different platforms, create separate posts for each
platform instead of using this multi-platform structure.
## Profile Keys
Post to on behalf of user by providing users' Profile Keys a a body parameter and the additional data in the response. *Business or Enterprise Plan required.*
## Rich Text Posts
You can add rich text such as "𝓗𝓮𝓵𝓵𝓸, how about a little 𝗯𝗼𝗹𝗱 𝘁𝗲𝘅𝘁 and 𝘪𝘵𝘢𝘭𝘪𝘤𝘴 𝘵𝘦𝘹𝘵 and an x₂?". You can use rich text on networks such as Twitter, Facebook, LinkedIn, Telegram, and Instagram.
If posting to Reddit, please use [Reddit-flavored Markdown formatting](https://www.reddit.com/wiki/markdown#wiki_new_reddit-flavored_markdown).
HTML elements are used to specify the type of rich text, which is translated into unicode. For example:
```json theme={"system"}
{
"post": "Hello, how about a little bold text and italics text and an x2?"
"platforms": ["twitter"]
}
```
### HTML Elements
| HTML | Example |
| --------------------------------------------- | --------------------------------- |
| \Nice One!\ | **Nice One!** |
| \Hello, world!\ | **Hello, world!** |
| \World\ | *World* |
| normal \italics \bold italics\\ | normal *italics **bold italics*** |
| \`\Hello\, world!\` | `Hello, world!` |
| \`\Hello\, world!\` | **`Hello`**`, world!` |
| \123\ | 𝟷𝟸𝟹 |
| \Hello\ | 𝓗𝓮𝓵𝓵𝓸 |
| x\2\ | x₂ |
| x\2\ | x² |
### CSS Codes
| Code | Example | Result |
| -------- | -------------------------- | ------------------------ |
| \u00B0 | It's 25\u00B0C today! | It's 25°C today! |
| \u2063\n | This is a new\u2063\nline. | This is a new line. |
## Schedule Posts
### Create Scheduled Posts
You can schedule future posts by specifying the `scheduleDate` parameter with the datetime in Zulu/UTC. Zulu Time, also known as Coordinated Universal Time (UTC), is the world standard for time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
```json {5} theme={"system"}
{
"post": "Hello, world!",
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["facebook", "instagram"],
"scheduleDate": "2023-07-08T12:30:00Z"
}
```
Please see [https://www.utctime.net/](https://www.utctime.net/) on how to convert your local time to Zulu/UTC time.
If the scheduled datetime is in the past, the post will immediately be sent.
If a `mediaUrl` is included with a scheduled post, the media must be available at the scheduled
publication time. For example, if the post is scheduled to be published on March 5, 2026, the
media must be available on March 5, 2026.
Error Handling for Scheduled vs Immediate Posts
There is an important difference in how validation errors are handled between immediate and scheduled posts:
* Immediate Posts
* When publishing immediately (without scheduleDate), if one platform fails validation checks, the other platforms will continue to be processed. For example, if a post exceeds Twitter's character limit but is valid for Facebook and Instagram, the post will fail on Twitter but still be published to Facebook and Instagram.
* Scheduled Posts
* When scheduling posts for future publication (with scheduleDate), all platforms must pass initial validation checks before the post is scheduled. If any platform fails these pre-validation checks, the entire scheduling operation will be rejected and an error will be returned immediately.
* However, some platform-specific errors may not be detected until the actual posting time. In these cases, the scheduled post will attempt to publish to all platforms, and individual platform failures will be reported in the final results without affecting the other platforms.
### Check a Scheduled Post Status
You can check the status of a scheduled post several ways:
Set up the [Webhook Scheduled Action](/docs/apis/webhooks/actions#scheduled-action) to automatically
receive the status of the scheduled post. This is available for the Business plan and is the
recommended method.
Get the status of a scheduled post with the [GET call](/docs/apis/post/get-post) with the post ID.
Check the status in the Ayrshare Dashboard. First switch to the User Profile the post as
published under, then go to "Posts" page and search using the Ayrhare Post ID.
### Pause Scheduled Posts
You may paused scheduled posts that have not yet been published.
Pausing a scheduled post will prevent it from being published until the post has been unpaused.
Use the [PATCH call](/docs/apis/post/update-post) to pause or unpause the scheduled post.
Please note if a post is unpaused and the `scheduleDate` is in the past the post will immediately be published. Consider updating the `scheduleDate` before unpausing.
## Shorten Links
Links in a post can be shortened using the Ayrshare [link shortner](/docs/apis/links/overview). You can turn on the automatic link shortening with the `shortenLinks` parameter when sending a post. [Max Pack required](/docs/additional/maxpack).
```json {4} theme={"system"}
{
"post": "Hello, world with a link https://www.ayrshare.com",
"platforms": ["linkedin"],
"shortenLinks": true
}
```
## Unsplash Images
The following fields are available for the `unsplash` body parameter:
Random Image: `random` returns a random Unsplash image.
Search Based Image: value String search term ; e.g. `money` will select a random image based on
money.
Image IDs: value Array of Ids; e.g. \["HubtZZb2fCM"] of image
[https://unsplash.com/photos/HubtZZb2fCM](https://unsplash.com/photos/HubtZZb2fCM)
```json {4,5,6} theme={"system"}
{
"post": "Hello, world!",
"platforms": ["instagram"],
"unsplash": "random",
"unsplash": "search term", // unsplash: "money"
"unsplash": ["unsplash image ID"] // unsplash: ["HubtZZb2fCM"]
}
```
If copying an Unsplash URL to post in `mediaUrls`, please be sure to copy the image address and
not just the URL. Please see this
[example](/docs/help-center/technical-support/get_an_unsplash_image_url) for more information.
# Publish a Post API: Post to Any Social Network | Ayrshare Docs
Source: https://www.ayrshare.com/docs/apis/post/post
POST /post
Publish to Facebook, Instagram, X, LinkedIn, TikTok, YouTube, and more with one Ayrshare API call. See parameters, code examples, and supported media.
Publish posts to the social networks you or your users have linked.
If you want to publish posts to User Profiles, please see the [/profiles endpoint](/docs/apis/profiles/overview) for more details.
Please be sure to add your `API_KEY`, and the `PROFILE_KEY` if publishing to a User Profile, in the [Authorization header](/docs/apis/overview#authorization).
The API Key can be found in the Ayrshare Developer Dashboard under the API Key page.
See the [Post API Overview](/docs/apis/post/overview) for more details on posting options.
## Header Parameters
## Body Parameters
The post text sent to the social networks specified in the platforms parameter.
See here for [advanced options](/docs/apis/post/overview), including how to include URLs and rich text.
You may send an empty string `""`to publish with no text.
Social media platforms to post. Accepts an array of Strings with values: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, or `youtube`.
Please note: use `facebook` for Facebook Pages, and `gmb` for Google Business Profile.
Use `all` to post to all linked social networks. Also include the required fields for all social network.
E.g. `title` must be included in `youTubeOptions` if `youtube` is linked.
An array of image or video URLs to include in the post. Please see [/media endpoint](/docs/apis/media/overview) to learn more.
URLs must be secure and begin with `https://`. If the URL has special characters, e.g. ñ, please encode the special characters before sending.
Videos require a paid plan.
Please see here for [Image and Video Requirements](/docs/apis/post/overview#image-%26-video-requirements) and [other advanced options](/docs/apis/post/overview).
Ayrshare will try to determine the media type based on the file extension in the URL (.mp4). You can explicitly set the media a video if the URL does not end in a known video extension, such as animated GIFs.
Please see [video extension](/docs/apis/post/overview#video-extension) for details.
The datetime to schedule a future post. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
Also see [schedule posts](/docs/apis/post/overview#schedule-posts) for details.
By default, scheduled posts are checked (pre-validated) for issues such as media requirements before they are accepted.
If any problems are found by Ayrshare checks, you will receive an immediate error response and the post will not be scheduled.
When the scheduled date is reached, the post will be published, at which time the final success or error response will be sent either via webhook or the [/history endpoint](/docs/apis/history/overview).
To skip this pre-validation step, set `validateScheduled` to `false`.
We recommend keeping validation enabled for scheduled posts to catch errors early.
Otherwise, the post will be scheduled and you will only receive an error when it is published.
Please see [scheduled webhook actions](/docs/apis/webhooks/actions#scheduled-action) for more details.
Add in a first comment automatically after posting. See [first comment](/docs/apis/post/overview#first-comment) for details.
Disable comments for the post. Only available for Instagram, LinkedIn, and TikTok.
Shorten links in the post for all platforms using [Ayrshare's link shortener](/docs/apis/links/overview).
Only URLs starting with https will be shortened.
[Max Pack required](/docs/additional/maxpack) for link shortening.
Please see here for using [3rd party link shorteners](/docs/apis/links/overview#custom-link-domain).
Please see [auto-schedule](/docs/apis/auto-schedule/overview) for details.
Automatically reposts your content multiple times at regular intervals, creating evergreen content that stays fresh and visible to your audience.
See [auto repost](/docs/apis/post/overview#auto-repost) for details.
See [auto hashtags](/docs/apis/post/overview#auto-hashtags) for details.
See [unsplash](/docs/apis/post/overview#unsplash) for details.
See [Bluesky details](/docs/apis/post/social-networks/bluesky).
See [Facebook details](/docs/apis/post/social-networks/facebook).
See [Google Business Profile details](/docs/apis/post/social-networks/google).
See [Instagram details](/docs/apis/post/social-networks/instagram).
See [LinkedIn details](/docs/apis/post/social-networks/linkedin).
See [Pinterest details](/docs/apis/post/social-networks/pinterest).
See [Reddit details](/docs/apis/post/social-networks/reddit).
See [Snapchat details](/docs/apis/post/social-networks/snapchat).
See [Telegram details](/docs/apis/post/social-networks/telegram).
See [Threads details](/docs/apis/post/social-networks/threads).
See [TikTok details](/docs/apis/post/social-networks/tiktok).
See [X/Twitter details](/docs/apis/post/social-networks/x-twitter).
See [YouTube details](/docs/apis/post/social-networks/youtube).
See [approval workflow](/docs/apis/post/overview#approval-workflow) for details.
[Generate random post text](/docs/quickstart#random-quote) for testing. `randomPost: true` will ignore the `post` field.
[Generate a random media image](/docs/quickstart#random-image) for testing. `randomMediaUrl: true` will ignore the `mediaUrls` field.
An optional unique ID associated with the post. Duplicate IDs will be rejected. Please see [idempotency](/docs/apis/post/overview#idempotent-posts) for details.
Set notes on a post that can be retrieved via the [/history endpoint](/docs/apis/history/overview). Notes are for reference only and do not affect the post.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"post": "Today is a great day!",
"platforms": ["twitter", "facebook", "instagram", "linkedin"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"]
}' \
-X POST https://api.ayrshare.com/api/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
post: "Today is a great day!", // required
platforms: ["bluesky", "facebook", "instagram", "linkedin", "twitter"], // required
mediaUrls: ["https://img.ayrshare.com/012/gb.jpg"] //optional
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'post': 'Today is a great day!',
'platforms': ['bluesky', 'facebook', 'instagram', 'linkedin', 'twitter'],
'mediaUrls': ['https://img.ayrshare.com/012/gb.jpg']}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"Today is a great day!",
"platforms" => ["bluesky", "facebook", "instagram", "linkedin", "pinterest", "twitter"],
"mediaUrls" => ["https://img.ayrshare.com/012/gb.jpg"]
];
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.ayrshare.com/api/post',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer API_KEY', // Replace 'API_KEY' with your actual API key
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"post": "Today is a great day!",
"platforms": []string{"bluesky", "facebook", "instagram", "linkedin", "twitter"},
"mediaUrls": []string{"https://img.ayrshare.com/012/gb.jpg"}
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/post",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostPOSTRequest_csharp
{
class Post
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post";
// Set up request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
// Prepare JSON content
string json = "{\"post\" : \"Today is a great day!\","
+ "\"platforms\" : [ \"bluesky\", \"facebook\", \"instagram\", \"linkedin\", \"twitter\" ],"
+ "\"mediaUrls\" : [ \"https://img.ayrshare.com/012/gb.jpg\" ]}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
// Send POST request
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
// Read response
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```ruby Ruby theme={"system"}
require 'httparty' # gem install httparty
res = HTTParty.post("https://api.ayrshare.com/api/post",
headers: {Authorization: "Bearer API_KEY"},
body: {
post: "Today is a great day!",
platforms: ['bluesky', 'facebook', 'instagram', 'linkedin', 'twitter'],
mediaUrls: ["https://img.ayrshare.com/012/gb.jpg"]
}).body
puts res
```
```json 200: Success theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/bluesky
"status": "success",
"id": "at://did:plc:n7atrjd22xgkmgwig6dzlhzd/app.bsky.feed.post/3lez7fwx452", // Bluesky Social Post ID
"cid": "bafyreie6n475cd3ynr6sfacvohu5qgjibcooxnug6zcbghkwnrwi5stafy", // Bluesky Content ID
"postUrl": "https://bsky.app/profile/madworlds.bsky.social/post/3lez7fwx4572",
"platform": "bluesky"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/facebook
"status": "success",
"id": "104923907983682_108329000309742", // Facebook Social Post ID
"platform": "facebook",
"postUrl": "https://www.facebook.com/104923907983682_108329000309742",
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/google
"status": "success",
"id": "3837985438581442258", // Google Business Profile Social Post ID
"postUrl": "https://local.google.com/place?id=5229466225881728772&use=posts&lpsid=CM",
"type": "localPosts",
"platform": "gmb"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/instagram
"status": "success",
"platform": "instagram", // Instagram Social Post ID
"id": "17878176260289172",
"postUrl": "https://www.instagram.com/p/CP1dI9Hp_WO/",
"usedQuota": 12,
"contentIssues": { // Optional — only present when Ayrshare detected and resolved a content issue
"originMediaHostFailed": true,
"details": ["Media URL could not be retrieved by the social network. Successfully posted using Ayrshare automated media protection."]
}
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/linkedin
"status": "success",
"id": "urn:li:share:7282181682126807041", // LinkedIn Social Post ID
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:7282181682126807041",
"owner": "urn:li:organization:77682157",
"platform": "linkedin"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/pinterest
"status": "success",
"id": "42995371460659062", // Pinterest Social Post ID
"postUrl": "https://www.pinterest.com/pin/429953714606062/",
"platform": "pinterest"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/reddit
"status": "success",
"id": "1hvdvof", // Reddit Social Post ID
"postUrl": "https://www.reddit.com/r/test/comments/1hvdvof/reddit_post_title/",
"platform": "reddit"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/snapchat
"status": "success",
"id": "921ed204-e123-5b08-a9ce-zx489f1f38c5", // Snapchat Social Post ID
"mediaId": "V6noC6UOQgOcABCDEgFZEwAAgd3F0cnp1eWtxZAb9PsH-MXb9PsIWAAAAAA", // Snapchat Media ID
"postUrl": "https://www.snapchat.com/add/samsmith1920/921ed204-e123-5b08-a9ce-zx489f1f38c5",
"type": "stories",
"ended": "2025-05-23T13:04:30.545Z",
"platform": "snapchat"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/telegram
"status": "success",
"id": 635, // Telegram Social Post ID
"postUrl": "https://t.me/c/1424847122/635",
"platform": "telegram"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/tiktok
"status": "success",
"idShare": "v_pub_url~v2.7456954878846683182",
"id": "pending", // TikTok Social Post ID - see https://www.ayrshare.com/docs/apis/post/social-networks/tiktok
"isVideo": true,
"platform": "tiktok"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/twitter
"status": "success",
"id": "1288899996423983105", // X/Twitter Social Post ID
"platform": "twitter",
"postUrl": "https://x.com/handle/status/1288899996423983105"
},
{
// Details at https://www.ayrshare.com/docs/apis/post/social-networks/youtube
"status": "success",
"id": "3oQeP-kTsbo", // YouTube Social Post ID
"postUrl": "https://youtu.be/3oQeP-kTo",
"platform": "youtube"
}
],
"id": "RhrbDtYh7hdSMc67zC8H" // Ayrshare Post ID used for delete, analytics, comments, etc.
}
```
```json 200: Success for Scheduled theme={"system"}
{
"status": "scheduled",
"scheduleDate": "2023-04-01T10:04:12Z",
"id": "IUiaqFkQP96UJJXYjRpv", // Ayrshare Post ID used for delete, comment, analytics, etc.
"refId": "9abf1426d6ce9122effdeeddfdfdfd",
"post": "Genius is eternal patience. - Michelangelo"
}
```
```json 200: Success with Profile Key theme={"system"}
{
"status": "success",
"posts": [
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "1869166036466991888",
"postUrl": "https://twitter.com/wondrouswaffles/status/1869",
"platform": "twitter"
},
{
"status": "success",
"id": "106638148652344_601623445855888",
"postUrl": "https://www.facebook.com/106638148652329/posts/6016",
"platform": "facebook"
}
],
"id": "bVQotNtxgXAUmLtqmw2",
"refId": "b68bdcabb379be2cf1186c1e595449804b232sa",
"profileTitle": "The Best Profile",
"post": "Formal education will make you a living. Self education will make you a fortune. - Jim Rohn"
}
]
}
```
```json 200: Success Scheduled Post and Profile Key theme={"system"}
{
"status": "success",
"posts": [
{
"status": "scheduled",
"scheduleDate": "2023-04-01T10:04:12Z",
"id": "qvu8gysraodz2WFZgRX7", // Ayrshare Post ID used for delete, comment, analytics, etc.
"refId": "9abf1426d6ce9122effdeeddfdfdfd",
"profileTitle": "Best Profile",
"post": "I never thought of myself as being handsome or good-looking or whatever. I always felt like an outsider. - Elton John"
}
]
}
```
```json 400: Bad Request theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 156,
"message": "Youtube does not seem to be linked with Ayrshare. Please confirm the linkage on the Social Accounts page in your dashboard. .../ayrshare.com/additional-info/troubleshooting",
"platform": "youtube"
},
{
"action": "post",
"status": "error",
"code": 110,
"message": "Status is a duplicate.",
"post": "Today is a great day",
"platform": "twitter"
}
],
"postIds": [],
"id": "0OGBzZssN5hxy8dMSRaD" // Ayrshare Post ID used for delete, comment, analytics, etc.
}
```
```json 400: Bad Request with Profile Key theme={"system"}
{
"status": "error",
"posts": [
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 156,
"message": "Instagram is not linked.
Please confirm the linkage on the Social Accounts page in the dashboard. https://www.ayrshare.com/docs/help-center/overview",
"platform": "instagram"
}
],
"postIds": [],
"id": "ekftQJ0hFB1Fx6bnM33",
"refId": "9abf1426d6ce9122effdeeddfdfdfd",
"profileTitle": "Best Profile",
"post": "The most common way people give up their power is by thinking they don't have any. - Alice Walker"
}
]
}
```
```javascript 500: Internal Server Error theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 107,
"message": "Facebook Error: This status update is identical to the last one you posted. Try posting something different, or delete your previous update.",
"platform": "facebook"
}
],
"postIds": [],
"id": "6APU4qqI7XO7JM3BOy6B" // Ayrshare Post ID used for delete, comment, analytics, etc.
}
```
# Retry a Post
Source: https://www.ayrshare.com/docs/apis/post/retry-post
PUT /post/retry
Retry to publish a post that failed
Retry to publish a post that failed with a `status` of `"error".` A retried post will be treated as a scheduled post, thus the final status can be obtained via the [/history](/docs/apis/history/overview) endpoint or the [scheduled action webhook](/docs/apis/webhooks/actions#scheduled-action).
While the post is being retried, the `status` will be `"pending"`. You may check on the status of the retry by calling the [GET post endpoint](/docs/apis/post/get-post).
The post can be retried *only once*. Recommend to only use if the error message indicates a retry is possible.
When retrying a failed social media post, first verify that the post hasn't already been
published. Social networks may sometimes report errors even when they've successfully processed
and published the post.
## Header Parameters
## Body Parameters
The top-level Ayrshare Post ID. The original post must have a status of "error".
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id": "s8k2jsk0pl"}' \
-X PUT https://api.ayrshare.com/api/post/retry
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post/retry", {
method: "PUT",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
},
body: JSON.stringify({
id: "s8k2jsk0pl" // required
})
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': 's8k2jsk0pl'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.put('https://api.ayrshare.com/api/post/retry',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
's8k2jsk0pl' // Replace with your actual ID
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostRetryPOSTRequest_csharp
{
class PostRetry
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post/retry";
// Set up request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
// Prepare JSON content
string json = "{\"id\": \"s8k2jsk0pl\"}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
// Send PATCH request
HttpResponseMessage response = await client.PutAsync(url, content);
response.EnsureSuccessStatusCode();
// Read response
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"id": "s8k2jsk0pl"
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("PUT", "https://api.ayrshare.com/api/post/retry",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```json 200: Success theme={"system"}
{
"status": "pending", // The post will be retried
"id": "N7kaDiZAfwc544OBKlgc" // Ayrshare Post ID
}
```
```json 400: Already Retried theme={"system"}
{
"action": "post",
"status": "error",
"code": 329,
"message": "This post was already retried and cannot be retried again."
}
```
# Bluesky API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/bluesky
Options for posting using the Bluesky API
## Posting to Bluesky
JSON for a basic post with a link, hashtag, and image/video using the Bluesky API.
Please see [Bluesky Media Guidelines](/docs/media-guidelines/bluesky) and [Bluesky Authorization](/docs/dashboard/connect-social-accounts/bluesky) for more information.:
```json Bluesky Post with Image theme={"system"}
{
"post": "The best Bluesky image post ever #best", // Max 300 characters or empty string
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["bluesky"]
}
```
```json Bluesky Post with Video theme={"system"}
{
"post": "The best Bluesky video post ever https://www.google.com", // Max 300 characters or empty string
"mediaUrls": ["https://img.ayrshare.com/012/vid.mp4"],
"platforms": ["bluesky"]
}
```
### Bluesky Supported Features
Bluesky supports text, images (up to 4), video (only 1), and posts with links or emojis.
Up to 4 images or one videos can be sent in a single post.
The post text is limited to 300 characters.
Animated GIFs are supported and sent as videos.
Bluesky does support hashtags and mentions (@handle).
Alt text on images or videos.
See [Bluesky Media Guidelines](/docs/media-guidelines/bluesky) for more information.
Link previews in posts are supported. Include a link in the post text and the Ayrshare API will
automatically add a link preview to the post.
### Bluesky Unsupported Features
Video thumbnails are not yet supported by Bluesky.
## Bluesky Mentions
Mention another Bluesky handle by adding `@handle` in the post text. For example:
```json Bluesky Post with Mention theme={"system"}
{
"post": "The best Bluesky image post ever @handle",
"platforms": ["bluesky"]
}
```
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
## Alternative Text
Add Bluesky alternative text, also known as alt text, to an image or video.
Bluesky alt text is an accessibility feature used for additional user info and screen readers.
Use the `altText` in the `blueSkyOptions` object.
```json Bluesky Alt Text theme={"system"}
{
"blueSkyOptions": {
// Array of Alt Texts
"altText": ["This is my best pic", "😃 here is the next one"]
}
}
```
Each alt text must correspond to an image or video in the `mediaUrls` array.
The alt text will be applied to each media item in order.
## Character Limits
Please see [Bluesky Character Limits](/docs/help-center/technical-support/character_limits#bluesky-character-limits) for more information.
# Facebook Page API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/facebook
Options for posting using the Facebook API
If you have issues connecting Facebook, please see the [troubleshooting
guide](/docs/help-center/technical-support/facebook_posting_issues).
If your media is hosted on a server or CDN you control, make sure Meta's publishing
crawler can fetch it. When Meta can't fetch your remotely-hosted media — including Facebook
Reels media ingested through the shared media-upload path — you may get the dedicated,
non-retryable Ayrshare error code 479. See
[Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) to resolve it.
Posting an AI-generated image? When Ayrshare converts a HEIC, HEIF, or AVIF image to JPEG it
writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI
disclosure, when the image declares one, and Facebook renders that disclosure as an "AI content"
label. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a
location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic
signature does not survive a re-encode. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Posting to Facebook
Posting using the Facebook API requires connecting a Facebook Page. Facebook does not allow personal accounts to be connected.
JSON for a basic post with a link and image to a Facebook page:
```json Facebook Post with Image theme={"system"}
{
"post": "The best FB post ever #best https://www.facebook.com", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["facebook"]
}
```
Facebook will automatically show a preview of the link in the post unless there is an image or
video included. In the above example the image will show. Removing the image will cause the link
preview to show.
If your video doesn't end in a known video extension such as mp4, please use the `isVideo`
parameter. See the [/post endpoint](/docs/apis/post/post) for details.
Facebook also supports sending media without post text. If you do not want post text included
send an empty String `post: ""`.
See [Facebook Media Guidelines](/docs/media-guidelines/facebook_pages) and [Facebook Authorization](/docs/dashboard/connect-social-accounts/facebook) for more information.
Facebook's API does not support mixing images and videos in a single post. You
can include multiple images OR a single video, but not both.
## Carousel Images
Post Facebook Carousel images through Ayrshare's API with the `carousel` body parameter.
```json Facebook Carousel Post theme={"system"}
{
"faceBookOptions": {
"carousel": {
// The URL of the "See More At" button - required
"link": "URL of See More At...",
"items": [
// 2 min, 10 max elements in the array
{
"name": "Image name", // optional
"link": "URL when image clicked", // required
"picture": "URL of image" // required
},
{
"name": "Image name",
"link": "URL when image clicked",
"picture": "URL of image"
}
]
}
}
}
```
The top-level `link` parameter is the URL at the end of the carousel.
The `items` is an array of object containing the following values. Minimum 2 elements and max 10
elements in the items array.
`picture` - URL of the carousel image.
`link` - URL when the image is clicked.
`name` - (optional) Image displayed in each image card.
**Note:** Do not use the `media_urls` with `carousel`. If `media_urls` is used, `carousels` will be ignored.
Please see our [Facebook Carousel Guide](https://www.ayrshare.com/blog/post-a-series-of-facebook-images-as-a-carousel/) for more information.
## Facebook Reels
You can post a video to Facebook Reels with the following `facebookOptions`.
Meta enforces a limit of 30 Reels per connected Facebook Page within any 24-hour period to prevent
spam and ensure platform quality. This is a rolling limit, meaning it counts the most recent 24
hours, not calendar days.
```json Facebook Reels Post theme={"system"}
{
"post": "The description of the video",
"platforms": ["facebook"],
"mediaUrls": ["https://img.ayrshare.com/012/reel.mp4"],
"faceBookOptions": {
"reels": true,
"title": "Super title for the Reel", // optional
"thumbNail": "https://img.ayrshare.com/012/reel-thumbnail.jpg" // optional
}
}
```
`reels`: Set to `true` to post the video to Reels. Required if you want to post to Facebook
Reels.
`title`: The title of the video with a maximum of 255 characters. Over 255 characters will be
truncated. Optional.
`thumbNail`: The thumbnail (cover image) of the video. The thumbnail should a URL to a JPEG or
PNG file. The thumbnail should be less than 10MB in size. Optional.
Please see the [Reels API video requirements](/docs/media-guidelines/facebook_pages#reels) or an [example of using the Facebook Reels API](https://www.ayrshare.com/blog/facebook-reels-api-how-to-post-fb-reels-using-a-social-media-api/).
Meta occasionally has issues processing Facebook Reels for some accounts. Even though an error response may be returned, the Reel might still have been published.
If you encounter errors for Facebook Reels, we recommend checking the Reel status. If the post *has not been* published you may try [posting once more](/docs/apis/post/retry-post). This is often successful.
You may use the URL contained in the `verifyReelsUrl` field to check the status. Be sure to use the same Profile Key as your original post. Wait until the time in `verifyReelsIn` to check the Reel status (10 minutes). If a HTTP error code of `400` is returned, the post failed and you may try the post one more time.
```json Facebook Reels Post Error theme={"system"}
{
"action": "post",
"status": "error",
"code": 108,
"message": "Facebook Error: Facebook cannot process your post at this time. Please try again. ",
"detailsData": {
"id": "104619420979033_36930641143",
"verifyReelsUrl": "https://api.ayrshare.com/history/36930641143?searchPlatformId=true&platform=facebook",
"verifyReelsIn": "2024-01-26T00:07:05.170Z",
"postUrl": "https://www.facebook.com/1046194209_36930641143",
"reels": true
},
"retryAvailable": true,
"platform": "facebook"
}
```
## Facebook Stories
Publish Facebook Stories to Facebook Pages either as a photo or as a video.
Facebook Stories do not support post text - any text provided in the `post` field, including
mentions, will be ignored.
A photo or video uploaded for a story cannot have been used in a previously published post.
A video story cannot exceed 60 seconds.
Turn on [Stories Archive](https://www.facebook.com/help/2058997717520567) to be able to GET
stories.
```json Facebook Stories Post theme={"system"}
{
"post": "", // Ignored by stories
"platforms": ["facebook"],
"mediaUrls": ["https://img.ayrshare.com/012/stories.mp4"],
"faceBookOptions": {
"stories": true
}
}
```
Please see the [Stories API image and video requirements](/docs/media-guidelines/facebook_pages#stories).
## Media Captions
Set a Facebook caption for each media image posted.
Accepts an array of string caption text. Each array must correspond to a media url. E.g. \["This is my best pic", "😃 here is the next one"] refers to the 1st and 2nd urls in `mediaUrls`.
```json Facebook Media Captions theme={"system"}
{
"faceBookOptions": {
"mediaCaptions": ["This is my best pic", "😃 here is the next one"]
}
}
```
## Location Tagging
A Facebook location tag is specified by a `locationId,` which is a Facebook Page ID or Facebook Page name. For example, Facebook page Id of the [Guggenheim Museum](https://www.facebook.com/guggenheimmuseum) is `7640348500` or Facebook page name `"@guggenheimmuseum"`. Pages must be associated with a physical location.
```json Facebook Location Tagging theme={"system"}
// Using the Facebook Page Id - must be associated with a location
{
"faceBookOptions": {
"locationId": 7640348500 // Guggenheim Museum Page Id
}
}
```
You can look up the `locationId` (Page Id) with the [brand endpoint](/docs/apis/listen/search/fb-page-search). Please note that the Page must have a location listed or the locationId will return an error.
Not supported on text posts, images, reels, and stories. Videos are not supported by Meta for location tagging.
## Audience Targeting
When creating a Page post on Facebook, you have the option to limit its visibility to a specific audience using two types of targeting:
1. Facebook Targeting: This allows you to define the audience for your post based on factors such as age, gender, location, and relationship. By setting these parameters, you can ensure that your post is shown only to people who meet the specified criteria.
2. Facebook Feed Targeting: This option enables you to further refine the visibility of your post within the News Feeds of your targeted audience.
You can use either targeting option individually or combine them.
### Targeting
Facebook targeting [limits the audience](https://www.facebook.com/help/352402648173466) for publishing content to specific demographics. Anyone not in these demographics will not be able to view this content. This will not override any Page-level demographic restrictions that may be in place.
Available demographic fields `targeting`:
`ageMin`: Limit the minimum age that can view the posts. Accepted values of 13, 15, 18, 21, or
25\. Other ages will be rejected.
`countries`: Also known as geofencing, you can limit the countries that can view the post. Array
of [country codes](/docs/iso-codes/country). The maximum number of countries that can be targeted is
25\. If you need to target more than 25 countries, or restrict certain countries, please see [Facebook Page Country Restrictions](/docs/help-center/technical-support/facebook_page_country_restrictions).
```json Facebook Targeting theme={"system"}
{
"faceBookOptions": {
"targeting": {
"ageMin": 18,
"countries": ["DE", "BR"]
}
}
```
### Feed Targeting
Anyone in these Facebook feed targeting groups are more likely to see this post, others are less likely, but may still see it anyway. Use targeting, see above, if you want to guarantee the restriction.
Available demographic fields for `feedTargeting`:
`ageMin`: Limit the minimum age that can view the posts.. Integer value 13 or higher. Default is
0\.
`ageMax`: Limit the maximum age that can view the posts. Integer value 65 or lower.
`countries`: Also known as geo targeting, you can indicate the countries that should be able to
view the post. Array of [country codes](/docs/iso-codes/country).
`collegeYears`: Target the college graduation age to view the post. Array of integers for
graduation year from college.
`educationStatuses`: Target the education status to view the post. Array of integers for
targeting based on education level. Use `1` for high school, `2` for undergraduate, and `3` for
alum.
`genders`: Target the gender to view the post. Array of integers for targeting specific genders.
`1` targets all male viewers and `2` females. Default is to target both.
`relationshipStatuses`: Target the relationship status to view the post. Array of integers for
targeting based on relationship status. Use `1` for single, `2` for 'in a relationship', `3` for
married, and `4` for engaged. Default is all types.
```json Facebook Feed Targeting theme={"system"}
{
"feedTargeting": {
"ageMax": 30,
"ageMin": 26,
"countries": ["DE", "BR"],
"genders": [1, 2],
"relationshipStatuses": [1, 2]
}
}
```
## Alternative Text
Add Facebook alternative text, also known as alt text, to an image or video. Facebook alt text is an accessibility feature used for additional user info and screen readers.
Use the `altText` in the `faceBookOptions` object.
```json Facebook Alt Text theme={"system"}
{
"faceBookOptions": {
// Array of Alt Texts
"altText": ["This is my best pic", "😃 here is the next one"]
}
}
```
Each alt text must correspond to an image or video in the `mediaUrls` array. The alt text will be applied to each image in order.
## Video Thumbnail
Set a Facebook video thumbnail (cover image). Send a remote URL of a PNG or JPG file that is the same dimensions as the video and less than 10 MB. URL should end in .png or .jpg.
```json Example Facebook Video Thumbnail theme={"system"}
{
"faceBookOptions": {
"thumbNail": "https://octodex.github.com/images/Fintechtocat.png"
}
}
```
## Video Title
Add a Facebook video title with the `title` parameter.
```json Facebook Video Title theme={"system"}
{
"faceBookOptions": {
"title": "The best video ever!"
}
}
```
## Animated GIFs
Only one `mediaUrls` URL is allowed in the array when posting a Facebook animated GIF.
If the media URL does not end in ".gif" or ".GIF", set the `isVideo` field to `true`.
```json Facebook Animated GIF theme={"system"}
{
"randomPost": true,
"platforms": ["facebook"],
// Set to true if the GIF URL does not end in .gif or .GIF
"isVideo": false,
// Only one URL is allowed in the array
"mediaUrls": ["https://img.ayrshare.com/012/cat.gif"]
}
```
## Facebook Page Mentions
You can mention another Facebook Page, also known as Facebook mentions or Facebook tagging, by including the Facebook Page name or Page ID in the post text.
Facebook does not allow mentions or tags of personal profiles or groups.
Include a mention with the following @mention:
`@page-name` or `@[page-id]`
### Mention with Page Name
An example post text with a Page name. You can find the Page name from the Facebook URL, e.g. [https://www.facebook.com/Ayrshare](https://www.facebook.com/Ayrshare)
```json Facebook Page Mention with Page Name theme={"system"}
{
"post": "This is the best social media api by @Ayrshare"
}
```
Ayrshare will make a best attempt to find the matching Page based on the name, but sometimes a match cannot be found. A more reliable method is using a Page ID.
### Mention with Page ID
An example post text with a Page ID; note the use of \[]. Please see below on how to find the Page ID.
```json Facebook Page Mention with Page ID theme={"system"}
{
"post": "This is the best social media api by @[738681876342836]" // Ayrshare Page ID
}
```
The Facebook Page ID will resolve to the matching page and ***notify the Page mentioned***.
Use Page mentioning with caution by only mentioning Pages you are associated. You should be careful to never spam.
When you mention a Page, **the owner of the Page will be notified via an alert and email**. If several Pages complain about you mentioning them, Facebook could ban your account. Generally you should only tag Pages that you have an established relationship with.
The Facebook Page being mentioned **must allow** other Pages to mention/tag their Page. Mentions can be enabled in the Page's general settings under "Others Tag this Page".
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
### Find a Facebook Page ID
#### Brand Endpoint
You can look up either a Facebook user or Facebook Page using the [Brand endpoints](/docs/apis/brand/overview).
#### At Facebook.com
1. From the Facebook News Feed, click **Pages** in the left side menu.
2. Click your Page name to go to your Page.
3. Click **About** at the top of your Page. If you don't see it, click **More**▼.
4. Scroll down to find your **Page ID** below **MORE INFO**.
or if you want to find the ID of a page your don't own:
If the Facebook Page has a URL such as`https://www.facebook.com/ayrshare-1234567890` then the ID
is ***1234567890***.
If the Facebook Page has a URL such as:
`https://www.facebook.com/pages/ayrshare/123466789203` then the Page ID is the number at the end, such as **123466789203**.
You can test that the Page ID is correct by going to `https://facebook.com/page-id` and it will resolve to the Page.
You can also try a 3rd party Facebook Page look up tool, which is not supported by Ayrshare, such as: [https://lookup-id.com/](https://lookup-id.com/)
If all other methods fail, you can go to the Facebook page in a browser and view the page source. In Chrome, right click to select "View Source". Then search for either `owning_profile_id` or `profile_id` to find the Page ID.
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
### Enable Page Mentions
The Page must allow mentions and tagging in posts and comments. By default this is enabled, but you can verify by logging into facebook.com and switching to your Page.
1. Viewing as your Page, click your page's **profile image** in the top right corner.
2. Click **Settings & Privacy** -> **Settings**.
3. In the Settings menu, click **Privacy**.
4. Click **Page and Tagging**.
5. Scroll down to **Reviewing**.
6. Toggle settings to allow tag and mentions.
## Meta Business Suite
### Draft Posts
Create a Facebook draft post that appears in the [Meta Business Suite Draft](https://business.facebook.com/latest/posts/draft_posts) tab. Facebook draft posts are posts that you have started writing, but have not yet published. You can save draft posts to come back to later, or you can schedule them to be published at a later date.
Add the `draft` parameter to `faceBookOptions` to send the post as a draft. Available for text, images, video, and reels posts.
```json Facebook Draft Post theme={"system"}
{
"faceBookOptions": {
"draft": true
}
}
```
### Schedule Publish Time
Set a schedule publish time for Facebook posts that appear in the [Meta Business Suite Scheduled Posts](https://business.facebook.com/latest/posts/scheduled_posts) tab. Facebook scheduled posts are posts that you have created and scheduled to be published at a later date and are managed in the Meta Business Suite. This can be useful for planning your social media posts in advance, or for publishing posts at times when you know your audience is most active.
Available for text, images, video, and reels posts.
The publish time must be greater than 10 minutes from the current time and within 29 days of the current date.
Unless you need to manage Facebook posts in Meta Business Suite, we recommend using the standard [post schedule date](/docs/apis/post/overview#schedule-posts).
Add the `scheduledPublishDate` parameter to `faceBookOptions` to schedule a post time.
```json Facebook Scheduled Post theme={"system"}
{
"faceBookOptions": {
"scheduledPublishDate": "2023-09-28T21:44:06Z" // Future date in UTC
}
}
```
## Link Preview
A Facebook post will automatically create a link preview of a link in the post body.
However, if you want to specify either a different link or force the link preview, use the `link` parameter with URL of the link.
```json Facebook Link Preview theme={"system"}
{
"faceBookOptions": {
"link": "https://www.ayrshare.com/instagram-hashtag-guide/"
}
}
```
If a `mediaUrls` field is included in the post request, the media will be displayed instead of the link preview.
## Facebook Ads
Facebook Ads are a way to promote your posts to a wider audience.
## Character Limits
Please see [Facebook Character Limits](/docs/help-center/technical-support/character_limits#facebook-character-limits) for more information.
## Additional Information
### How do I add line breaks or rich text to a Facebook post?
Facebook line breaks can be added to a post with a special [new line character](/docs/apis/post/overview#line-breaks).
Rich text, such as bold or italic lettering, can be added to a Facebook post with a few [html elements](/docs/apis/post/overview#rich-text-posts).
### Why do I see "Published by Ayrshare" on a post?
Don't worry, it only shows in the admin view. Please see the [troubleshooting guide](/docs/help-center/technical-support/facebook_shows_published_by_ayrshare) for more information.
# Google Business Profile API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/google
Options for posting using the Google Business Profile API
When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG for Google Business Profile it
preserves the image's color rendering and writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic signature
does not survive a re-encode. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Posting to Google Business Profile
There are four types of Google Business Profile, formerly known as Google My Business, posts that can be created using the Google Business Profile API.
In the below example, the `post` text is posted as an update to the user's Google business page.
[Find out more](https://www.ayrshare.com/blog/google-my-business-what-is-gmb-why-you-need-it-and-how-to-use-it/) about Google Business Profile (GBP).
You must [claim](https://support.google.com/business/answer/2911778) your Google Business Profile page before linking it with Ayrshare. Be sure to choose the Google account that is an admin of your GBP page during link authorization. The business profile must also be verified and public.
You can access your GBP manage console and check the verification status at [https://business.google.com/](https://business.google.com/)
Product posts cannot be created via the Google Business Profile API at this time.
JSON for a basic post with just text to GBP, which will appear in the "What's New" section of :
```json Google Business Profile Post theme={"system"}
{
"post": "The best GMB ever #best https://www.google.com",
"platforms": ["gmb"] // Please note to use `gmb`
}
```
or JSON for a basic post with an image to GBP:
```json Google Business Profile Post with Image theme={"system"}
{
"post": "The best GMB ever #best https://www.google.com",
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["gmb"]
}
```
If your video doesn't end in a known video extension such as mp4, please use the `isVideo`
parameter. See the [/post endpoint](/docs/apis/post/overview) for details.
See [Google Business Profile Media Guidelines](/docs/media-guidelines/google_business_profile) and [Google Business Profile Authorization](/docs/dashboard/connect-social-accounts/google-business) for more information.
more information.
## Google Business Profile Posting Requirements
Please be sure your post does not contain the following. Google will reject your post and the post will show as "This post is no longer available" or with a "Rejected" label in the Google Console:
Phone numbers. Google will reject all posts containing phone numbers.
Spam, false claims, or false representation.
Off-topic post that doesn't pertain to your business.
Duplicate content.
Inappropriate content.
Offensive language.
Please see [Google Business Profile's Content Policy](https://support.google.com/business/answer/7213077?hl=en) for more information.
## Standard Post (What's New)
A standard local post appears in the "*Posts*" GBP section and is categorized as "What's New".
It can contain post text, an image, or a Call to Action ([see below](/docs/apis/post/social-networks/google#call-to-action)).
Videos are not supported for to be published to the What's New section via the Google Business Profile API.
Please see [Image or Video Post](#image-or-video-post) for details on how to publish videos to Google Business Profile.
*These posts will appear in the "**Posts -> What's New**" section in the GMB management console.*
```json Google Business Profile Standard Post theme={"system"}
{
"post": "A wonderful post",
"platforms": ["gmb"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"], // optional - images only
"gmbOptions": {
"callToAction": {
// optional
"actionType": "learn_more",
"url": "https://www.ayrshare.com"
}
}
}
```
## Image or Video Post
You can publish Image or Video posts to Google Business Profile.
Images and videos will appear in the "**Photos**" section in the GBP management console.
### Requirements
Only one image or one video can be added to your GBP location, which will appear in the "Photos"
section of the GBP console.
Only one image or video is allowed per post.
The post text is required by the endpoint, but is not used by GBP.
Call to Action is not supported for image or video posts.
Be sure to include the `isPhotoVideo` parameter in the `gmbOptions` object.
```json Google Business Profile Image Post {6} theme={"system"}
{
"post": "What an image!",
"platforms": ["gmb"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"], // required
"gmbOptions": {
"isPhotoVideo": true, //required
"category": "product" // optional
}
}
```
### Video Processing
Google at times takes extra time to process uploaded videos.
You can view the status of the media in the Google Business Profile console:
1. Go to your [Google Business Profile console](https://business.google.com/us/business-profile/).
2. Click the button "See your profile". You will br brought to the GBP page.
3. Click on the "Photos" tab.
4. You will see a list of photos and videos.
5. Click on the photo or video you want to view.
If your video has a "pending" status, it is still being processed by Google. Please wait a few
minutes and refresh the page. Be sure your Google Business Profile has been verififed and the
profile is public.
If the video seems stuck in "pending", this may be due to a bug at Google.
Please contact [Google Business support](https://support.google.com/business/gethelp) for
assistance.
### Product Category
You can specify a product category for an image or video so the media is categorized in the "Photos" section of the GBP console. For example, if an image has the category "product", it will appear under the "Product" tab in Photos.
Some categories are not allowed for certain business types. For example, Ayrshare could not use `food_and_drink` since we are not in the food/drink industry.
Available Categories:
`cover`: Cover photo. A location has only one cover photo.
`profile`: Profile photo. A location has only one profile photo.
`logo`: Logo photo.
`exterior`: Exterior media.
`interior`: Interior media.
`product`: Product media.
`at_work`: At work media.
`food_and_drink`: Food and drink media.
`menu`: Menu media.
`common_area`: Common area media.
`rooms`: Rooms media.
`teams`: Teams media.
## Events Post
Promote an event at your business. Events require a title, start and end dates, and can include a video. For example, a real estate agent may advertise an open house showing.
Events support Call to Action.
Include an optional image with the `mediaUrls` parameter.
Videos are not supported for Events.
Event posts will appear in the "**Posts -> Events**" section in the GBP management console.
The `post` text will be used for the Event Details.
```json Google Business Profile Event Post theme={"system"}
{
"post": "A great event!", // Event Details
"platforms": ["gmb"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"], // optional
"gmbOptions": {
"event": {
"title": "Check this event out.", // required
"startDate": "2021-08-12T20:17:46.384Z", // required
"endDate": "2021-09-12T20:17:46.384Z" // required
}
}
}
```
## Offers Post
Provide promotional sales or offers from your business. Offers require a title as well as start and end dates and times. A "View offer" action button is automatically added to the post. You can also include a photo, description, coupon code, link, and terms and conditions with the post. For example, a toy store may advertise 20% off all beanie babies for a week.
Include an image with the `mediaUrls` parameter.
*Videos are not supported for Offers.*
*These posts will appear in the "**Posts -> Offers**" section in the GBP management console.*
```json Google Business Profile Offers Post theme={"system"}
{
"post": "A great offer for everyone!",
"platforms": ["gmb"],
"gmbOptions": {
"offer": {
"title": "Great Sale.", // required
"startDate": "2021-08-12T20:17:46.384Z", // required
"endDate": "2021-09-12T20:17:46.384Z", // required
"couponCode": "BOGO-JET-CODE", // required - max 58 characters
"redeemOnlineUrl": "https://www.ayrshare.com", // required
"termsConditions": "Offer only valid if you can prove you are a time traveler" // required
}
}
}
```
`couponCode` has a maximum of 58 characters.
## Call to Action
Provide general information about your business and appears as an action button. For example, a website might promote a *Learn More* button to redirect to their website.
A Call to Action can be added to a Standard post or Event. Offers cannot have Call to Actions.
Include an image with the `mediaUrls` parameter.
```json Google Business Profile Call to Action Post theme={"system"}
{
"post": "Take this action!",
"platforms": ["gmb"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"], //optional
"gmbOptions": {
"callToAction": {
"actionType": "order", // required
"url": "https://www.ayrshare.com" // required for all action types but "call"
}
}
}
```
The `actionType` is displayed as a button on the post. Possible values are:
**book**: Prompts a user to book an appointment, table, or something similar.
**order**: Prompts a user to order something.
**shop**: Prompts a user to browse a product catalog.
**learn\_more**: Prompts a user to see additional details on a website.
**sign\_up**: Prompts a user to register, sign up, or join something.
**call**: Prompts a user to call a business. The `url` field is not required for `call`.
However, you must first have set a phone number in your Google Business Profile for the call
action to appear on the post.
The `url` parameter is the URL the user will be directed to upon clicking.
Additional [Google Business Profile information](https://www.ayrshare.com/blog/google-my-business-what-is-gmb-why-you-need-it-and-how-to-use-it/).
## First Comment
Google Business Profile does not support post comments, so the `firstComment` parameter is skipped for Google Business Profile-only posts.
A `firstComment` warning/skip object is returned, but the post itself still succeeds, with no error raised.
## Google Business Profile Mentions
While you can add a `@handle` to a Google Business Profile post, Google Business Profile does not support resolving mentions in the post text.
The `@handle` will remain as plain text.
## Character Limits
Please see [Google Business Profile Character Limits](/docs/help-center/technical-support/character_limits#google-business-profile-character-limits) for more information.
# Supported Social Networks
Source: https://www.ayrshare.com/docs/apis/post/social-networks/overview
All social networks supported by the Ayrshare /post API: Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Telegram, Threads, TikTok, X/Twitter, and YouTube, each with its own publishing options and limits.
The Ayrshare [/post endpoint](/docs/apis/post/post) publishes to every social network below from a single API call.
Add one or more networks to the `platforms` array and Ayrshare handles the network-specific formatting, media conversion, and delivery.
Each network supports its own publishing options, media types, and limits. Select a network below for its full reference.
## Supported Social Networks
Text posts with up to 4 images or 1 video, alt text, and animated GIFs.
Page posts, Reels, image carousels, and automatic link previews.
Standard What's New posts, events, and offers, plus single image or video uploads.
Feed posts, Reels, Stories, and carousels of up to 10 images or videos.
Personal and company pages, documents (PDF/PPT/DOC), and up to 9 images.
Image and video Pins, carousels of up to 5 images, and board selection.
Submit image or text posts to any subreddit you have access to.
Stories and Spotlight Snaps with a single image or video per post.
Channel and group posts with an image or video, animated GIFs, and link previews.
Text posts and carousels of up to 20 combined images or videos.
Direct video publishing plus photo posts of up to 35 images.
Tweets with up to 4 images or 1 video, long video, and BYO credentials.
Publish videos with a title, description, tags, visibility, and playlists.
## Posting at a Glance
A quick reference for the most common publishing limits. See [Character Limits](/docs/help-center/technical-support/character_limits) and [Media Requirements](/docs/media-guidelines/overview) for the complete, per-network reference.
| Network | Post Characters | Max Images | Video |
| ------------------------------------------------------------ | -------------------- | ---------- | ----------------- |
| [Bluesky](/docs/apis/post/social-networks/bluesky) | 300 | 4 | 1 |
| [Facebook](/docs/apis/post/social-networks/facebook) | 63,206 | 10 | 1 |
| [Google Business Profile](/docs/apis/post/social-networks/google) | 1,500 | 1 | 1 |
| [Instagram](/docs/apis/post/social-networks/instagram) | 2,200 | 10 | 1 |
| [LinkedIn](/docs/apis/post/social-networks/linkedin) | 3,000 | 9 | 1 |
| [Pinterest](/docs/apis/post/social-networks/pinterest) | 500 | 5 | 1 |
| [Reddit](/docs/apis/post/social-networks/reddit) | 5,000 | 1 | Not yet supported |
| [Snapchat](/docs/apis/post/social-networks/snapchat) | 500 | 1 | 1 |
| [Telegram](/docs/apis/post/social-networks/telegram) | 1,024 | 1 | 1 |
| [Threads](/docs/apis/post/social-networks/threads) | 500 | 20 | 1 |
| [TikTok](/docs/apis/post/social-networks/tiktok) | 2,200 | 35 | 1 |
| [X (Twitter)](/docs/apis/post/social-networks/x-twitter) | 280 (25,000 Premium) | 4 | 1 |
| [YouTube](/docs/apis/post/social-networks/youtube) | 5,000 | Video only | 1 |
Most networks accept **either** multiple images **or** a single video in one post, not both. Instagram and Threads are the
exceptions: their carousels may combine images and videos (up to 10 and 20 items respectively). See each network's page and the
[Media Requirements](/docs/media-guidelines/overview) for the exact rules.
## Posting to Multiple Networks
Publish the same content everywhere by listing each network in the `platforms` array. Network-specific options are passed in their
own object (for example, `instagramOptions` or `youTubeOptions`) and are ignored by the other networks.
```json Post to Multiple Networks theme={"system"}
{
"post": "Launch day is here! 🚀",
"platforms": ["bluesky", "facebook", "instagram", "linkedin", "twitter"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"]
}
```
Each network must first be linked to the user profile. See [Connect Social Accounts](/docs/dashboard/connect-social-accounts/overview)
to authorize the networks you want to publish to.
# Update a Post
Source: https://www.ayrshare.com/docs/apis/post/update-post
PATCH /post
Update a scheduled post's metadata
Update the `scheduleDate` of a post, `approval` status of a post, `notes`, or `visibility` of a posted YouTube video.
The post must originally have a `scheduleDate` and be in a "pending" `status`. The `status`
can be checked with the /history or GET /post endpoints.
The YouTube video must have been successfully posted to change visibility.
The [approval workflow](/docs/apis/post/post#approval-workflow) requires the current status of the
post be in "awaiting approval".
Other parameters cannot be updated. You will need to delete the post and repost.
## Header Parameters
## Body Parameters
Ayrshare Post ID of the post to update. Ayrshare Post ID returned from [/post](/docs/apis/post/post).
The original post requires approval and has a status of "awaiting approval", set to `true` to
approve and publish the post.
Enable or disable comments on a post. Setting to `true` will disable comments. Setting to `false` will enable comments.
Supported platforms: Instagram and LinkedIn.
Enabling or disabling can be done on either a scheduled post or a published post.
Disabling comments on a published post will not delete existing comments.
Disabling LinkedIn comments will delete all existing comments on the thread.
Instagram comments will not be deleted.
TikTok comments cannot be changed after publishing.
Set notes on a post that can be retrieved via the [/history](/docs/apis/history) endpoint. Notes are
for reference only and do not affect the post.
The `datetime` to schedule a future post. Accepts a UTC date time.
For example, use format `YYYY-MM-DDThh:mm:ssZ` and send as `2026-07-08T12:30:00Z`.
Please see [utctime](https://www.utctime.net/) for more examples.
If the datetime is in the past, the post will immediately be sent.
Pause or unpause a scheduled post. If a post is unpaused and the `scheduleDate` is in the past,
the post will immediately be publish. Consider updating the `scheduleDate` before unpausing.
Update the visibility of the YouTube video with the `visibility` field and values `unlisted`, `private`, or `public`.
Update the `description`, `title`, or `categoryId`. If no `description` or `categoryId` originally set, the default values are `""` and `24` (Entertainment), respectively.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"id": "s8k2jsk0pl", "scheduleDate": "2023-07-08T12:30:00Z", scheduledPause: true}' \
-X PATCH https://api.ayrshare.com/api/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
id: "s8k2jsk0pl", // required
scheduleDate: "2023-07-08T12:30:00Z",
scheduledPause: true
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'id': 's8k2jsk0pl',
'scheduleDate': '2023-07-08T12:30:00Z'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.patch('https://api.ayrshare.com/api/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
's8k2jsk0pl', // Replace with your actual post ID
'scheduleDate' => '2023-07-08T12:30:00Z'
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PUT',
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostUpdatePOSTRequest_csharp
{
class PostUpdate
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post";
using (var httpClient = new HttpClient())
{
try
{
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string json = "{\"id\":\"s8k2jsk0pl\"," +
"\"scheduleDate\":\"2023-07-08T12:30:00Z\"}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
var response = await httpClient.PatchAsync(url, content);
var responseBody = await response.Content.ReadAsStringAsync();
response.EnsureSuccessStatusCode();
Console.WriteLine(responseBody);
}
catch (HttpRequestException ex)
{
Console.WriteLine("Error: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Error details: " + ex.InnerException.Message);
}
}
}
}
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"id": "s8k2jsk0pl",
"scheduleDate": "2023-07-08T12:30:00Z"
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("PATCH", "https://api.ayrshare.com/api/post",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"id": "ZSU1tnnuykDy25wA6kvX", // Ayrshare Post ID
"scheduleDate": "2025-07-08T12:30:00Z",
"scheduledPaused": true
}
```
```json 400: ID Not Found theme={"system"}
{
"action": "update",
"status": "error",
"code": 305,
"message": "Error updating post. Post ID not found."
}on
```
```json 400: Invalid scheduleDate theme={"system"}
{
"action": "post",
"status": "error",
"code": 104,
"message": "Invalid schedule date format for scheduleDate. .../ayrshare.com/rest-api/endpoints/post#send-a-post"
}
```
# Ayrshare Social Media API
Source: https://www.ayrshare.com/docs/introduction
Ayrshare Social Media API Introduction
Ayrshare is a unified API that lets you manage your users' social media presence across all major platforms with a single integration.
Instead of dealing with 13 different social media APIs, you use just one to schedule posts, get analytics, manage comments, send direct messages, create ads, and more.
## What is Ayrshare?
Managing multiple social media platforms is complex. Each network has its own API, approval process, error handling, and data formats. Keeping up with constant API changes across platforms is a full-time job.
Ayrshare solves this by providing a single, [unified API](/docs/apis/overview) that handles all the complexity for you. We maintain direct integrations with each social network, so you can focus on building your product instead of managing infrastructure.
With Ayrshare, you can:
* Schedule and publish posts across multiple platforms
* Retrieve analytics and engagement metrics
* Manage comments and conversations
* Send and receive direct messages
* Create and manage advertising campaigns
And with our [Launch](/docs/multiple-users/business-launch-overview) and [Business](/docs/multiple-users/business-plan-overview) plans, you can manage social media for all your users.
## See It In Action
Here's how simple it is to post to multiple platforms on behalf of your user:
```json theme={"system"}
// One API call posts to multiple platforms
POST /post
{
"post": "Check out our new product launch! 🚀",
"platforms": ["x", "facebook", "instagram", "linkedin", "tiktok"],
"mediaUrls": ["https://example.com/video.mp4"],
"scheduleDate": "2025-12-01T10:00:00Z"
}
```
That's it! And you can then make a single call to [get the analytics](/docs/apis/analytics/overview) or [add a comment](/docs/apis/comments/overview) on all of these posts.
See below for [how to get started](/docs/introduction#how-to-get-started-with-ayrshare).
## Which Social Networks Are Supported?
Ayrshare seamlessly integrates with 13 major social networks:
Ayrshare integrates directly with each social network's official APIs and partnership programs. This ensures our platform delivers the most reliable, secure, and current social media management features available, all while maintaining compliance with each network's policies and best practices.
The messaging API supports Instagram, Facebook, and X. The Ads API supports Facebook.
## API-First Platform
At Ayrshare, everything is designed with developers in mind, allowing you to quickly integrate social media features into your platform or application.
Our API-first approach means every feature is accessible programmatically, with comprehensive documentation, SDKs in multiple languages, and predictable behavior.
## How It Works
The API follows REST principles, making it intuitive for developers:
* **GET** requests retrieve information (analytics, post history, user data)
* **POST** requests create new resources (posts, comments, messages)
* **PUT** requests update existing resources
* **DELETE** requests remove resources
All data is exchanged in JSON format, ensuring easy parsing and manipulation in any programming language.
## How to Get Started with Ayrshare
Getting up and running takes just a few minutes:
Sign up for Ayrshare and find your API key in the dashboard.
Link the social media accounts you want to manage.
Test the API with our interactive documentation.
Get posting in minutes with our step-by-step guide.
Learn how to manage social media for all your users.
Have questions? Our team is here to help via chat or email.
# Quick Start Guide
Source: https://www.ayrshare.com/docs/quickstart
Link your social accounts and send your first post in a few minutes.
The guide is for setting up a single company. For Business and Enterprise Plan subscriptions with multiple users, a personalized integration guide is provided.
## Connect Your Social Media Accounts
Log in or sign up for an [Ayrshare account](https://app.ayrshare.com/).
On the Social Account page, click the social networks you want to connect.
Please be sure to grant all permissions.
## Get Your API Key
An API Key is required to authorize access to the API endpoints.
This key is used in the header of your requests, and should be preceded by the `Bearer` keyword.
Your API Key is located within the [Ayrshare Dashboard](https://app.ayrshare.com/), on the **API Key** page. If necessary, switch to your 'Primary Profile' via the **User Profiles** page.
From there, you can find the **API Key** page in the left-hand side panel.
Every API call must include the API Key in the Header using a `Bearer` Token. Also include the `Content-Type` of `application/json`.
```json Header theme={"system"}
"Authorization": "Bearer API_KEY",
"Content-Type": "application/json"
```
See the [Authorization](/docs/apis/overview#authorization) for more information.
## Send Your First API Post
### Publishing the Post
Below are code examples showing how to make a post using our API in different programming languages.
For an even easier integration, you can use one of our pre-built [SDK packages](/docs/packages-guides/overview).
To make a post, you'll need:
Your [API Key](/docs/apis/overview#authorization) for authentication.
The text content of your post.
The social media platforms you want to post to (only include platforms you've linked).
Optional: URLs of any images or videos you want to include.
All examples use the [/post](/docs/apis/post/post) endpoint. Let's look at some sample code:
**Posting to X/Twitter?** X requires your own API credentials. Add 2 BYO headers (`X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret`) to your request. This is a **one-time setup per Ayrshare account**, and the same key pair works for every sub-profile / end-user. See the [setup guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for details.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"post": "Today is a great day!",
"platforms": ["facebook", "instagram", "linkedin"],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"]
}' \
-X POST https://api.ayrshare.com/api/post
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
post: "Today is a great day!", // required
platforms: ["bluesky", "facebook", "instagram", "linkedin"], // required
mediaUrls: ["https://img.ayrshare.com/012/gb.jpg"] //optional
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'post': 'Today is a great day!',
'platforms': ['bluesky', 'facebook', 'instagram', 'linkedin'],
'mediaUrls': ['https://img.ayrshare.com/012/gb.jpg']}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/post',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
"Today is a great day!",
"platforms" => ["bluesky", "facebook", "instagram", "linkedin", "pinterest"],
"mediaUrls" => ["https://img.ayrshare.com/012/gb.jpg"]
];
curl_setopt_array($curl, [
CURLOPT_URL => 'https://api.ayrshare.com/api/post',
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Authorization: Bearer API_KEY', // Replace 'API_KEY' with your actual API key
'Content-Type: application/json'
],
]);
$response = curl_exec($curl);
curl_close($curl);
echo $response;
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"post": "Today is a great day!",
"platforms": []string{"bluesky", "facebook", "instagram", "linkedin"},
"mediaUrls": []string{"https://img.ayrshare.com/012/gb.jpg"}
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/post",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace PostPOSTRequest_csharp
{
class Post
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post";
// Set up request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
// Prepare JSON content
string json = "{\"post\" : \"Today is a great day!\","
+ "\"platforms\" : [ \"bluesky\", \"facebook\", \"instagram\", \"linkedin\" ],"
+ "\"mediaUrls\" : [ \"https://img.ayrshare.com/012/gb.jpg\" ]}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
// Send POST request
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
// Read response
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```ruby Ruby theme={"system"}
require 'httparty' # gem install httparty
res = HTTParty.post("https://api.ayrshare.com/api/post",
headers: {Authorization: "Bearer API_KEY"},
body: {
post: "Today is a great day!",
platforms: ['bluesky', 'facebook', 'instagram', 'linkedin'],
mediaUrls: ["https://img.ayrshare.com/012/gb.jpg"]
}).body
puts res
```
Congratulations! You just sent your first post.
### Post Response
You will receive a response with a `status` of "success" when our API successfully processes your post. The response includes:
`status`: Overall status of the API call ("success" or "error")
`errors`: Array of any errors encountered (empty if successful)
`postIds`: Array of objects containing platform-specific details:
Platform name
Post ID on that platform
URL to view the post
Additional platform-specific information
Each platform in the `postIds` array will have its own status, allowing you to verify which platforms successfully received your post.
Check your social media pages to ensure that the post was successfully processed and is live. Note that some platforms may have a slight delay before posts appear publicly.
Here is a sample response:
```json Post Response theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "738681876342836_1530521371228093",
"postUrl": "https://www.facebook.com/738681876342836/posts/1530521371228093",
"platform": "facebook"
},
{
"status": "success",
"id": "18008340650526653",
"postUrl": "https://www.instagram.com/p/DGf4hgZObR0/",
"usedQuota": 1,
"platform": "instagram"
},
{
"status": "success",
"id": "urn:li:share:7300150903578275840",
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:7300150903578275840",
"owner": "urn:li:organization:66755239",
"platform": "linkedin"
}
],
"id": "K0DmYRgugS5P694it",
"refId": "d93ca2784c9bf7bf83e0bf081d16c91598",
"post": "Today is a great day!"
}
```
See more code examples of calling the social media API in Node.js, Python, PHP, Golang, C#, and Ruby, plus other great capabilities:
### Diving a Little Deeper
Let's break down the process of what just happened when we made this API call.
We set the Header Authorization bearer token (API Key) and content type of
json.
Next, we created a body object:
Post containing the text "Today is a great day!".
Social network platforms of Facebook, Instagram, and LinkedIn.
You should only include the platforms you linked in the Social Linkage
Page.
Added an image in the mediaUrls.
Sent everything as an HTTP POST to the /post endpoint.
## Before You Go, Some Best Practices
### Read the Docs
We maintain extensive and up-to-date documentation. Since you are already here, take some time to check out the sections of the docs in the left navigation.
### Error Codes Are Important
You need to handle them so your users have a great experience.
### Keep Your API Key Secure
We take security very seriously, and so should you. You have full control over the connection between Ayrshare and your social media accounts. Once the accounts are connected, the Ayrshare API key becomes the way you authenticate. Please keep this key secret and secure.
### Publish Test Posts
You can publish test posts with a random quote, image, or video using the `randomPost`, `randomMediaUrl`, and `isLandscapeVideo` or `isPortraitVideo` parameters in the [/post endpoint](/docs/apis/post/post). If you use the `randomPost`, the `post` parameter is not required.
These posts are live on your social media pages, so if appropriate, delete them after testing.
#### Random Quote
Send a random quote for testing publishing a post by adding `randomPost: true`.
Used with the [/post](/docs/apis/post/post) endpoint.
```json theme={"system"}
"randomPost": true
```
#### Random Image
Send a random image by adding `randomMediaUrl: true`.
Used with the [/post](/docs/apis/post/post) endpoint.
```json theme={"system"}
"randomMediaUrl": true
```
#### Random Video
Send a random landscape video by adding `isVideo: true` and `isLandscapeVideo: true`.
The video will be standard landscape size.
Used with the [/post](/docs/apis/post/post) endpoint.
```json theme={"system"}
"randomMediaUrl": true,
"isLandscapeVideo": true
```
Send a random portrait video, required for TikTok or Facebook/Instagram Reels, by adding `isVideo: true` and `isPortraitVideo: true`.
Used with the [/post](/docs/apis/post/post) endpoint.
```json theme={"system"}
"randomMediaUrl": true,
"isPortraitVideo": true
```
#### Random Comment
Send a random comment for testing publishing a comment by adding `randomComment: true`.
Used with the [/comment](/docs/apis/comments/post-comment) endpoint.
```json theme={"system"}
"randomComment": true
```
#### Example cURL Call
Send a random quote and portrait video.
```bash theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H "Content-Type: application/json" \
-X POST \
-d '{
"randomPost": true,
"platforms": ["facebook", "instagram", "linkedin"],
"randomMediaUrl": true,
"isPortraitVideo": true
}' \
https://api.ayrshare.com/api/post
```
### **Use Postman to Test Your API Calls**
[Postman](https://www.postman.com/) is an amazing tool for testing API calls. You can even generate code in over a dozen languages.
### Demo Code
If you are looking for sample demo project in React and NodeJS, please see this GitHub repository:
### **Common Troubleshooting**
Sometimes things don't go right, so here is a little help in our help center.
### **Reach Out To Us for Help**
We are here to help, so please use the chat in the bottom right corner or [email us](mailto:support@ayrshare.com).
# Max Pack
Source: https://www.ayrshare.com/docs/additional/maxpack
The Max Pack offers additional social media API endpoints and features to power your platform.
## How to Get Started
Sign up for the Max Pack by logging into the [Ayrshare dashboard](https://app.ayrshare.com) and going to the "Account" page. Click "Learn More ->" for the details and activate the Max Pack.
## Max Pack API Features
The Max Pack provides additional endpoints and other useful utilities for building your app or platform. The Max Pack includes all of the following powerful capabilities. Details on each are below.
Multiple AI capabilities including text generation, text rewriting, video
transcription, and more.
A JWT timeout longer than the default 5 minutes allows you to email the link
to your users instead of them having to go to your app or platform.
Use the Ayrshare link shortener to condense long URLs, and get analytics and
tracking data. You can even add your own custom domain.
The resize endpoint allows you to choose a social network compatible image
size, add watermarks, change backgrounds, and more. You also have access to
the Instagram
[autoResize](/docs/apis/post/social-networks/instagram#auto-image-resize) to
automatically resize Instagram images.
Create AI-generated alt text for your images. Choose the language to write
the alt text and keywords to include in the alt text.
Choose over 100 different languages to translate your post text. For
example, translate English to French or Spanish to German.
Set up a staging server environment for your testing and release process. A
staging server has all the capabilities and characteristics of your
production environment. You can create User Profiles and connect their
social networks, register new webhooks, and make API calls. Please note
these are still live social network accounts. Your staging environment is
meant for internal use, so please don't use it with clients, users, or in a
production capacity. Create the staging server in the dashboard under User
Profiles -> Settings.
*Business Plan or Launch Plan Required.*
**Custom CSS**: Use your own CSS file to customize the look and feel of
the social accounts page including color, fonts, hiding features, and
more. The page heading, instruction text, logo, Close button and every
social network card carry [stable class
hooks](/docs/multiple-users/manage-user-profiles#css-class-hooks), so you can
restyle the connect buttons, style connected and unconnected cards
differently, target a single network, or change how the cards are laid
out.
**Favicon and Page Title**: Set your own favicon and page title on the
social account linking page.
**Social Linkage Close Button**: You can set the text of the "Close"
button on the social linkage page.
**Footer**: Set your own footer text, such as copyright with your
company name on the social linkage page. Provide either text or HTML.
You can include links to your site if you wish.
*Business Plan or Launch Plan Required.*
Generate a sentiment analysis on a social media post or comment to
understand if the text is positive, negative, or neutral and recommendations
on improving the text for a more positive reaction.
Generate a transcription and title for a video file.
# Instagram API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/instagram
Options for posting using the Instagram API
If you have issues connecting Instagram, please see the [troubleshooting
guide](/docs/help-center/technical-support/facebook_or_instagram_linking_issues).
If your media is hosted on a server or CDN you control, make sure Meta's publishing
crawler can fetch it. A hard media-fetch / crawler-block failure returns the dedicated,
non-retryable Ayrshare error code 479 ("social network could not download media from this URL"),
often with error code 138 or "Restricted by robots.txt" in the details as the underlying signal.
See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) to resolve it.
Posting an AI-generated image? When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG it
writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI
disclosure, when the image declares one, and Instagram renders that disclosure as an "AI info"
label. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a
location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic
signature does not survive a re-encode. Note that instagramOptions.autoResize resizes
through a separate step that carries no metadata, so leave it off if the disclosure needs to reach
Instagram. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
The Instagram API has the following requirements and restrictions.
Business or Creator Instagram Account connected with a Facebook Page - [see
here](/docs/dashboard/connect-social-accounts/instagram).
Only 50 Instagram posts are allowed over a 24 hour period. See below for `usedQuota`
The `post` text may contain up to *5 hashtags* (e.g. #wildtimes) and *3 username mentions*
(e.g. @natgeo).
@mention Instagram users will receive a notification.
Maximum 2,200 post characters.
Multi-image/videos posts are supported and sent as a carousel. You may send up to 10 videos and
images.
Instagram does not support deletes via an API. Deletes must occur manually using the Instagram
app.
If your Reel video doesn't end in a known video extension such as mp4, please use the `isVideo`
parameter. See the [/post endpoint](/docs/apis/post/post) for details.
Instagram also supports sending media without post text. If you do not want post text included
send an empty String `post: ""`.
See [Instagram Media Guidelines](/docs/media-guidelines/instagram) and [Instagram Authorization](/docs/dashboard/connect-social-accounts/instagram) for more information.
## Posting to Instagram
JSON for a basic post with an image and hashtags to Instagram:
```json Instagram Post theme={"system"}
{
"post": "The best IG ever #best #awesome https://www.instagram.com",
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["instagram"]
}
```
Hashtags are clickable in Instagram posts, but links are not.
The aspect ratio of images & videos and the duration of video are very important to successfully post to Instagram. If they do not meet the requirements, the post will be rejected.
[Please see the Instagram section of Image and Video Guidelines](/docs/media-guidelines/instagram).
## Instagram Business or Creator Account
Your Instagram account must be a Business or Creator Account and connected with a Facebook Page. The set up is free and easy.
See here for detailed instructions:
## Carousel of Images and Videos
You can post multiple images or Reel videos to Instagram as a carousel; up to a combined total of 10 images or videos may be used in a carousel.
Just add your additional images or videos to the `mediaUrls` array, and the carousel will automatically be created.
```json Instagram Carousel Post theme={"system"}
{
// Max 10 images or videos
"mediaUrls": ["https://url.com/image.jpg", "https://url.com/video.mp4"]
}
```
Video URLs must end in a known extension such as `mp4`. The `isVideo` parameter is not supported
for Instagram carousels.
## Instagram Reels
In Instagram a video post is called a Reel.
You can post a video to Instagram Reels API with the following optional `instagramOptions` options.
```json Instagram Reels Options theme={"system"}
{
"instagramOptions": {
"shareReelsFeed": true,
"audioName": "The Weeknd - Blinding Lights",
"thumbNail": "https://img.ayrshare.com/012/gb.jpg", // if used, thumbNailOffset will be ignored.
"thumbNailOffset": 30000
}
}
```
Please see the [Reels API video requirements](/docs/media-guidelines/instagram#reels) for details on
the video requirements.
`shareReelsFeed`: Boolean set to `true` to indicate that the Reel *can* appear in both the
**Feed** and **Reels** tabs or `false` to indicate the Reel *can* only appear in the **Reels**
tab. This value is a hint to Instagram where you would like the Reel to appear, but neither
value determines whether the Reel *actually* appears in the **Reels** or **Feed** tab because
the Reel may not meet eligibility requirements or may not be selected by Instagram's algorithm.
`audioName`: String name of the audio music of your Reels media. You can only rename once, either
while creating a reel or after from the audio page. For example, `"The Weeknd - Blinding
Lights"`.
`thumbNail`: String URL of the Reel cover image (thumbnail). Please see here for [details on
thumbNail](/docs/apis/post/social-networks/instagram#reels-thumbnails).
`thumbNailOffset`: Integer offset in milliseconds of the thumbnail frame. Please see here for
[details on thumbNailOffset.](/docs/apis/post/social-networks/instagram#reels-thumbnails)
Please see the [Reels API video requirements](/docs/media-guidelines/instagram#reels) or an [example of using the Instagram Reels API](https://www.ayrshare.com/blog/instagram-reels-api-how-to-post-videos-to-reels-using-a-social-media-api/).
You may also set a [Reels cover url](/docs/apis/post/social-networks/instagram#reels-thumbnails) and [location & user tags](/docs/apis/post/social-networks/instagram#user-tags-and-locations).
## Trial Reels
A trial reel is a Reel that is published only to non-followers when it is first posted, allowing you to test how a Reel performs with a fresh audience before it reaches your existing followers. Set `trialParams.graduationStrategy` in `instagramOptions` to publish a Reel as a trial.
```json Instagram Trial Reel theme={"system"}
{
"post": "Testing this with a fresh audience first",
"mediaUrls": ["https://img.ayrshare.com/random/portrait1.mp4"],
"platforms": ["instagram"],
"instagramOptions": {
"trialParams": {
"graduationStrategy": "MANUAL"
}
}
}
```
`graduationStrategy` controls how a trial reel later "graduates" — i.e. becomes visible to your followers as well. It is required when `trialParams` is provided and must be one of:
"MANUAL" — the post stays a trial reel until you manually graduate it from
inside the Instagram app.
"SS\_PERFORMANCE" — Meta auto-graduates the Reel based on early performance
against non-followers.
Graduation itself (promoting a published trial reel to followers) is not currently exposed by
Meta's API and must be performed manually in the Instagram app. Ayrshare will add a graduation
endpoint once Meta exposes one.
### Trial reel restrictions
The trial reel request is rejected at the Ayrshare edge — before any Meta call — when any of these conditions are not met:
Exactly one media URL ending in .mp4 or .mov (case-insensitive). Carousels are not supported.
instagramOptions.stories must not be true. Stories cannot be trial reels.
graduationStrategy must be present and exactly "MANUAL" or "SS\_PERFORMANCE" (case-sensitive).
Failures return one of three Ayrshare error codes — see [Instagram Trial Reel Errors](/docs/errors/errors-ayrshare#instagram-specific-error-codes) (447, 448, 449) for the full payloads.
## Instagram Stories
You can post a single image or video as an Instagram Story with the following `instagramOptions`. Instagram stories disappear after 24 hours.
```json Stories Post theme={"system"}
{
"post": "The description of the video",
"mediaUrls": ["https://img.ayrshare.com/random/portrait1.mp4"],
"instagramOptions": {
"stories": true
}
}
```
Please see the [Stories API requirements](/docs/media-guidelines/instagram#stories).
Instagram Stories do not support post text - any text provided in the `post` field, including
mentions, will be ignored.
Stories expire after 24 hours.
Instagram currently only supports Story publishing on Instagram Business Accounts and not
Creator Accounts.
Instagram Stories do not support collaborators.
Publishing stickers (i.e., link, poll, location) is not supported by Instagram.
## Reels Thumbnails
You may select a frame the Reel as the thumbnail image or your own cover image (thumbnail) from an external URL.
```json Instagram Thumbnail theme={"system"}
{
"instagramOptions": {
// milliseconds
"thumbNailOffset": 30000,
// If both thumbNail and thumbNailOffset includes, thumbNail will be used.
"thumbNail": "https://img.ayrshare.com/012/gb.jpg"
}
}
```
The offset is the location in milliseconds of the thumbnail frame of the video Reel. Default value is `0`, which is the first frame of the Reel.
If you specify both a thumbnail URL and a thumbnail offset, the thumbnail offset will be ignored.
The Reel thumbnail must follow the [Reels thumbnail requirements](/docs/media-guidelines/instagram#reels-thumbnails).
Signed URLs with redirects are not guaranteed to be compatible with cover URLs.
We recommend a non-signed URL or use the [/media endpoint](/docs/apis/media/overview).
## Alternative Text
Add Instagram alternative text, also known as alt text, to an image.
Instagram alt text is an accessibility feature used for additional user info and screen readers.
Alt text supports up to 1,000 characters per image.
Instagram does not support alt text for Reels or Stories.
Use the `altText` in the `instagramOptions` object.
```json Instagram Alt Text theme={"system"}
{
"instagramOptions": {
// Array of Alt Texts
"altText": ["This is my best pic", "😃 here is the next one"]
}
}
```
Each alt text must correspond to an image or video in the `mediaUrls` array.
The alt text will be applied to each image in order.
## User Tags & Locations
The Instagram user will be notified when you use their username in a post. Please be cautious to
not spam users or post with their username repeatedly. If you do, Instagram could suspend or
deactivate your account.
An image or a Reel can be tagged with Instagram users and an image, video, or a Reel can be tagged with a location using the `instagramOptions` parameter.
### Location
A location is specified by a `locationId,` which is a Facebook Page ID or Facebook Page name. For example, Facebook page Id of the [Guggenheim Museum](https://www.facebook.com/guggenheimmuseum) is `7640348500` or Facebook page name `"@guggenheimmuseum"`. Pages must be associated with a physical location.
```json Instagram Location theme={"system"}
// Using the Facebook Page Id - must be associated with a location
{
"instagramOptions": {
"locationId": 7640348500 // Guggenheim Museum Page Id
}
}
// Using the Facebook Page name - must be associated with a location
{
"instagramOptions": {
"locationId": "@guggenheimmuseum" // Guggenheim Museum Page name. Must begin with @
}
}
```
You can look up the `locationId` (Page Id) with the [brand endpoint](/docs/apis/brand/overview). Please note that the Page must have a location listed or the locationId will return an error.
Not supported on images or videos in carousels.
### User Tags
Instagram tags allow you to tag other Instagram users in your post.
Users are specified by a `userTags` containing an Array of objects with an Instagram username and x/y coordinates (image only). User tags can be added for single images or Reels, but not regular videos, multiple images, or Stories.
Usernames must be public Instagram accounts. Do not include the @ of the user handle.
`x` and `y` values must be `float` numbers that originate from the top-left of the image, with a
range of `0.0`–`1.0`. Single images. Do not include with Reels or an error will occur.
```json Instagram User Tags theme={"system"}
{
"instagramOptions": {
"userTags": [
{
"username": "ayrshare", // Required: Instagram username
"x": 0.5, // Required for Images, cannot be used with Reels
"y": 1.0 // Required for Images, cannot be used with Reels
},
{
"username": "johnboy", // Required: Instagram username
"x": 0.1, // Required for Images, cannot be used with Reels
"y": 0.9 // Required for Images, cannot be used with Reels
}
]
}
}
```
## Instagram Mentions
Mention another Instagram handle by adding @handle in the post text.
For example you can mention the @ayrshare handle in the post text:
```json Instagram Mentions theme={"system"}
{
"post": "The best social media API @Ayrshare ever!", // empty string is allowed
"mediaUrls": ["https://images.com/image.jpg"],
"platforms": ["instagram"]
}
```
The `@mentioned` user will be notified of the mention. Please review the [important
rules](/docs/testing/post-verification#mentions) on mentions.
## Collaboration
Instagram collaboration allows you to co-author content with other Instagram accounts by [tagging others as collaborators](https://www.facebook.com/help/instagram/291200585956732).
This allows you to designate other Instagram users as creators on your post.
When tagged, these users receive an invitation to collaborate in the mobile app.
If they accept, the post will also appear in their feed and be visible to their followers, extending the post’s reach and engagement potential.
### Collaborators
The public original author can tag another public account as an Instagram collaborator.
The other account will receive a message, which allows them to either accept or deny the request.
If the other account accepts, the post will also show on their profile and be distributed to their followers in Instagram feed.
The post’s header will attribute the content to both accounts.
You may add collaborators to a Reel, image, or carousel.
Tagging a private collaborator is not permitted via the Instagram API. While
such a functionality exists within the Instagram app, platforms and their APIs
are often not at [feature parity](/docs/help-center/product/are_social_networks_native_apps_and_the_apis_at_parity).
Instagram Stories do not support collaborators.
**Only invite collaborators you expect to `accept` your invite**.
If the [collaborator
responds](/docs/apis/post/social-networks/instagram#get-collaborator-request-status) with a
`declined` collaboration request, **do not re-invite them** until you contact them to
understand the reason for the decline.
Repeated declines from the same or multiple users will put your Instagram and Ayrshare account
at risk of cancelation.
The original author can add or remove a collaborator at any time.
Invite *up to three* collaborators by with an array public Instagram usernames.
```json Instagram Collaborators theme={"system"}
{
"instagramOptions": {
"collaborators": ["ayrshare", "therock", "taylorswift"] // Up to three
}
}
```
These three collaborators will receive a message invitation in their Instagram mobile app and can accept or decline the invite, and then you may [check the invited user request status](/docs/apis/post/social-networks/instagram#get-collaborator-request-status).
Please only invite collaborator who you know will accept your request or you Instagram account may be negatively affected.
Note about invited collaborators: With a few exceptions, data on or about co-authored media can
only be accessed through the API by the user who published the media; collaborators are unable to
access this data via the API.
### Get Collaborator Request Status
After inviting a Instagram collaborator, you can check the status of the request using the [Get Collaborator Request Status API](/docs/apis/utils/instagram-get-collaborator).
AI Content Label
Self-disclose AI-generated media so Instagram applies its **AI info** label to the published post.
```json Instagram AI Content Label theme={"system"}
{
"post": "Generated with a little help from a model",
"platforms": ["instagram"],
"mediaUrls": ["https://img.ayrshare.com/random/portrait1.mp4"],
"instagramOptions": {
"isAIGenerated": true
}
}
```
isAIGenerated: Boolean set to true to add Instagram's AI info label to
the post. Default false — omitting the parameter publishes the post with no label.
Instagram shows the label as AI info beneath the account name. Opening it reads
"\[account] added an AI label to this content".
Accepted values are true, "true", false, and
"false". Any other value — "yes" or 1, for example —
never fails the request: the post publishes normally without the label, and the response adds a
non-fatal warnings entry (code: 497,
feature: "isAIGenerated") listing the accepted values.
Applies to single images, single videos, Reels, Stories, and carousels.
For a [carousel](/docs/apis/post/social-networks/instagram#carousel-of-images-and-videos), the label
applies to the carousel as a whole. Individual carousel items cannot be labeled separately.
This is a self-disclosure only. Ayrshare does not detect or infer whether your media is
AI-generated. Instagram may separately label content its own systems detect as AI-generated.
The Ayrshare [MCP Server](/docs/additional/mcp-action-server) takes `isAIGenerated` as a strict
boolean — pass `true`, not `"true"`. The REST API accepts both.
The label cannot be added or removed after a post publishes. Set `isAIGenerated` at post time.
## Auto Image Resize
Max Pack Required
Images are automatically resized to 1080 x 1080 px to work with Instagram with the `autoResize` parameter. Please note, this will resize the image for all included platforms, so we recommend making one call for Instagram and a different /post call for additional platforms.
```json Instagram Auto Image Resize theme={"system"}
{
"post": "Let it go!",
"platforms": ["instagram"],
"mediaUrls": ["https://images.ayrshare.com/imgs/GhostBusters.jpg"],
"instagramOptions": {
"autoResize": true, // Max Pack
"locationId": 7640348500,
"userTags": [
{
"username": "ayrshare",
"x": 0.5,
"y": 0.5
},
{
"username": "ayrshare",
"x": 0.3,
"y": 0.2
}
]
}
}
```
## Used Quota
The Instagram response will include the current `usedQuota` for the number of Instagram posts done over a rolling 24 hours period. Only 50 Instagram posts are permitted by Instagram in a 24-rolling-hour period.
```json Instagram Used Quota theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "17823977408036085",
"postUrl": "https://www.instagram.com/p/CeBrkQuN1Kv/",
"usedQuota": 15,
"platform": "instagram"
}
],
"id": "l4FaPHSXWJNdmMfm3dIE",
"refId": "65806e8d9efd78a58c05566a887043329dcdc76b",
"post": "Luckily for Alice, the little magic bottle had now had its full effect."
}
```
If the quota has been reached, an error message will be returned.
## Content Issues
Ayrshare includes built-in media protection that can detect and resolve certain media delivery issues during posting. When a post succeeds but a content issue was detected and resolved, the response includes an optional `contentIssues` object. This allows you to identify and fix issues with your media hosting proactively.
The `contentIssues` object is only present when an issue was detected and resolved — normal successful posts do not include it.
| Field | Type | Description |
| ----------------------- | ---------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `originMediaHostFailed` | boolean | The social network could not retrieve the media from the provided URL. Ayrshare's automated media protection resolved the issue and completed the post successfully. Consider reviewing your media hosting configuration — see [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) for common causes. |
| `details` | array of strings | Human-readable descriptions of each detected issue. |
```json Content Issues Response Example theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "17878176260289172",
"postUrl": "https://www.instagram.com/p/CP1dI9Hp_WO/",
"usedQuota": 12,
"platform": "instagram",
"contentIssues": {
"originMediaHostFailed": true,
"details": [
"Media URL could not be retrieved by the social network. Successfully posted using Ayrshare automated media protection."
]
}
}
],
"id": "abc123",
"refId": "65806e8d9efd78a58c05566a887043329dcdc76b",
"post": "Your post text here"
}
```
If you see `originMediaHostFailed` in your responses, there may be an issue with your media hosting that prevents social networks from accessing your media. See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) for detailed troubleshooting steps.
## Error Details
When an Instagram media publish fails, the error object now surfaces Meta's underlying error text in the `details` field, alongside the Ayrshare `code` and `message`. This lets you distinguish between different root causes (for example, an aspect-ratio rejection versus a media-download failure) without contacting support.
```json Instagram Publish Error theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"platform": "instagram",
"code": 156,
"message": "An error occurred while posting to Instagram.",
"details": "The submitted image was not found. The aspect ratio is not supported. Please see https://developers.facebook.com/docs/instagram-api for more information."
}
]
}
```
The `message` is Ayrshare's stable, human-readable summary, while `details` echoes the raw text returned by Meta for the failed publish.
## Adding line breaks or rich text to an Instagram post
Instagram line breaks can be added to a post with a special [new line character](/docs/apis/post/post#line-breaks).
Rich text, such as bold or italic lettering, can be added to a Instagram post with a few [html elements](/docs/apis/post/overview#rich-text-posts).
## Character Limits
Please see [Instagram Character Limits](/docs/help-center/technical-support/character_limits#instagram-character-limits) for more information.
## Additional endpoints
# LinkedIn API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/linkedin
Options for posting using the LinkedIn API
Relying on embedded image metadata for AI disclosure? LinkedIn strips embedded metadata when it
ingests an image, so an Iptc4xmpExt:DigitalSourceType disclosure does not survive
LinkedIn's image processing and no AI label is applied. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
The LinkedIn API has the following requirements and restrictions:
The `post` field accepts up to 3,000 characters.
LinkedIn will automatically preview the link in the post unless there is an image or video
included. In the above example the image will show. Removing the image will cause the link
preview to show. If the link preview cannot be retrieved, the post will still be published and a
`linkPreviewFailed: true` field will be returned in the /post response.
Hashtags are clickable in LinkedIn. Use the # symbol to specify a LinkedIn hashtag.
If publishing a video and doesn't end in a known video extension such as mp4, please use the
`isVideo` parameter. See the [/post endpoint](/docs/apis/post/post) for details.
LinkedIn video processing takes several minutes to complete. Please wait before trying the share
URL or getting video analytics.
LinkedIn limits 150 posts per day per LinkedIn account.
Posting to LinkedIn Groups is not supported.
LinkedIn also supports sending media without post text. If you do not want post text included
send an empty String `post: ""`.
You may link either a company page or a personal LinkedIn account.
See [LinkedIn Media Guidelines](/docs/media-guidelines/linkedin) and [LinkedIn
Authorization](/docs/dashboard/connect-social-accounts/linkedin) for more information.
You must be a "Super Admin" or a "Content Admin" to connect a LinkedIn company page.
## Posting to LinkedIn
JSON for a basic post with a link and image to LinkedIn:
```json LinkedIn Post theme={"system"}
{
"post": "The best LinkedIn post ever #best https://www.linkedin.com", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["linkedin"]
}
```
## LinkedIn Options
You can set additional options for a post by using the `linkedInOptions` parameter.
```json LinkedIn Options theme={"system"}
{
"linkedInOptions": {
"altText": ["This is my best pic", "😃 here is the next one"],
"disableShare": true,
"targeting": {
"countries": ["US", "IN", "DE", "GB"],
"seniorities": ["Senior", "VP"],
"degrees": ["Master of Digital Design", "Bachelor of Engineering"],
"fieldsOfStudy": ["Consumer Economics", "Computer Games and Programming Skills"],
"industries": ["Telecommunications Carriers", "Banking"],
"jobFunctions": ["Information Technology", "Entrepreneurship"],
"staffCountRanges": ["size_51_to_200", "size_5001_to_10000"]
},
"thumbNail": "https://example.com/thumbnail.jpg",
"title": "Sample PPTX",
"titles": ["This is an amazing video", "😃 here is the next one"],
"visibility": "public"
}
}
```
LinkedIn options are optional fields that can be used to control the post.
The alternative text of images for accessibility and screen readers.
See [LinkedIn Alternative Text](/docs/apis/post/social-networks/linkedin#alternative-text) for more information.
Disable the ability for users to reshare the LinkedIn post.
See [LinkedIn Disable Share](/docs/apis/post/social-networks/linkedin#disable-share) for more information.
Target your organic posts to specific groups by countries, industry, job title, and more.
Requires at least 300 followers in the targeted audience.
See [LinkedIn Audience Targeting](/docs/apis/post/social-networks/linkedin#audience-targeting) for more information.
The thumbnail of a video. Must be PNG or JPG, same dimensions as video, under 10MB. URL should end in .png or .jpg.
See [LinkedIn Video Thumbnail](/docs/apis/post/social-networks/linkedin#video-thumbnail) for more information.
The title of a document when posting PPT, PPTX, DOC, DOCX, or PDF files. Maximum length: 400 characters.
If not specified, the filename is used.
See [LinkedIn Documents](/docs/apis/post/social-networks/linkedin#documents) for more information.
Title or media captions to LinkedIn images or videos.
Each title corresponds to a media URL in order.
See [LinkedIn Media Titles](/docs/apis/post/social-networks/linkedin#media-titles) for more information.
The visibility of the post.
Values: `public`, `connections`, or `loggedin`.
See [LinkedIn Post Visibility](/docs/apis/post/social-networks/linkedin#post-visibility) for more information.
## Alternative Text
Add LinkedIn alternative text, also known as LinkedIn alt text, to a LinkedIn image. LinkedIn alt text is an accessibility feature used for additional user info and screen readers. LinkedIn does not support altText on videos or documents.
Use the `altText` in the `linkedInOptions` object.
```json LinkedIn Alt Text theme={"system"}
{
"linkedInOptions": {
"altText": ["This is my best pic", "😃 here is the next one"] // Array of Alt Texts
}
}
```
Each alt text must correspond to an image in the `mediaUrls` array. The alt text will be applied to each image in order.
## Audience Targeting
LinkedIn allows you to target your organic posts to specific groups of users. You can target by countries, industry, job title, and more.
LinkedIn targeting requires at least **300 followers in the targeted audience**. For example if
you have 400 followers and target just users in the country US, but only 200 of your followers are
in the US, the targeting will fail since the audience is too small.
Use the `targeting` object in the `linkedInOptions` object:
```json LinkedIn Audience Targeting theme={"system"}
{
"linkedInOptions": {
"targeting": {
"countries": ["US", "IN", "DE", "GB"],
"seniorities": ["Senior", "VP"],
"degrees": ["Master of Digital Design", "Bachelor of Engineering"],
"fieldsOfStudy": ["Consumer Economics", "Computer Games and Programming Skills"],
"industries": ["Telecommunications Carriers", "Banking"],
"jobFunctions": ["Information Technology", "Entrepreneurship"],
"staffCountRanges": ["size_51_to_200", "size_5001_to_10000"]
}
}
}
```
The available targeting options are listed in the following JSON files:
## Authorization Refresh
LinkedIn must be reauthorized *every year* via the Social Accounts page.
An email and webhook social action notification will be sent 15 days in advance of authorization
expiration.
The refresh required date and remaining days can be retrieved from the
[/user](/docs/apis/user/overview) endpoint.
The user will see on their social account linkage page an alert and a refresh button 30 days
prior to expiration.
## Character Limits
Please see [LinkedIn Character Limits](/docs/help-center/technical-support/character_limits#linkedin-character-limits) for more information.
## Disable Share
You can disable the ability for users to reshare the LinkedIn post by setting the `disableShare` field to `true` in the `linkedInOptions` object:
```json LinkedIn Disable Share theme={"system"}
{
"linkedInOptions": {
"disableShare": true
}
}
```
## Documents
Use the API to post a document on LinkedIn. Supported file formats include: PPT, PPTX, DOC, DOCX, and PDF. Ensure the document is under 100MB in size and does not exceed 300 pages.
Below is a code sample demonstrating how to post a PPTX document with a title:
```json LinkedIn Document Post theme={"system"}
{
"post": "What a great document",
"platforms": ["linkedin"],
"linkedInOptions": {
"title": "Sample PPTX" // optional. If not specified, the file name used.
},
"mediaUrls": ["https://scholar.harvard.edu/files/torman_personal/files/samplepptx.pptx"]
}
```
The media URL provided must end in a known document extension: ppt, pptx, doc, docx, or pdf.
## LinkedIn Mentions
You may mention other LinkedIn organizations, i.e. company pages, or member profiles, i.e. individual profile pages, in your posts.
Ayrshare makes an attempt to resolve the @mention by doing a lookup on the handle.
If the @mention is not found, the @ will be removed from the post since LinkedIn will not accept posts with unresolved mentions.
Individual LinkedIn profiles cannot be mentioned.
If any mention in a LinkedIn post cannot be resolved (due to privacy settings,
account restrictions, or other platform limitations), LinkedIn may fail to
render all mentions in that post as clickable links. This is LinkedIn's platform
behavior and not an API issue. To avoid this, ensure all mentioned users and
organizations allow mentions from your organization or consider posting mentions
separately to isolate any problematic mentions.
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
### Organization Profiles
Mention another LinkedIn organization handle by adding `@handle` in the post text. The `@handle` is the name of the company or organization.
You can mention in posts, comments, and reply to comments.
For example,
Ayrshare's LinkedIn company profile is
[https://www.linkedin.com/company/ayrshare](https://www.linkedin.com/company/ayrshare) and the
handle used would be *@ayrshare*.
Zara's LinkedIn company profile is
[https://www.linkedin.com/company/zara-sa/](https://www.linkedin.com/company/zara-sa/) and the
handle used would be *@zara-sa*.
```json LinkedIn Mention theme={"system"}
{
"post": "The best social media API @ayrshare ever!",
"platforms": ["linkedin"]
}
```
### Member Profiles
Mention another LinkedIn member profile by adding `@vanity_name` or `@[John Smith]` in the post text.
1. `@vanity_name` is the vanity name of the member profile. For example in the member's profile URL `https://www.linkedin.com/in/vanity_name/`, the vanity name is `vanity_name`.
2. `@[John Smith]` is the person's full name. For example if the person's full name is `John Smith`, the mention would be `@[John Smith]`.
You can mention in posts, comments, and reply to comments.
```json LinkedIn Mention theme={"system"}
{
"post": "The best social media API @[John Smith] and @ava_smith ever!",
"platforms": ["linkedin"]
}
```
In the above example, John Smith and Ava Smith will be mentioned in the post - the first using their full name and the second using their vanity name.
**Important Notes:**
1. You must have a LinkedIn company page connected to your Ayrshare account to mention member
profiles. If you connect your own personal LinkedIn account, you will not be able to mention other
people's profiles.
2. LinkedIn only allows mentioning people who follow your organization / company page.
## Media Titles
Add title or media captions to LinkedIn images or videos.
Use the `titles` in the `linkedInOptions` object.
```json LinkedIn Media Titles theme={"system"}
{
"linkedInOptions": {
"titles": ["This is an amazing video", "😃 here is the next one"] // Array of Alt Texts
}
}
```
Each title must correspond to an image or video in the `mediaUrls` array. The title will be applied to each image or video in order.
## Multi Image Posts
You may post up to *9 image URLs* in the `mediaUrls` to LinkedIn.
```json LinkedIn Multi Image Post theme={"system"}
{
"mediaUrls": ["https://url1", ..., "https://url9"]
}
```
LinkedIn does not yet support carousel images for organic posts.
## Post Visibility
LinkedIn allows you to control the visibility of your posts.
You can set the visibility to public, connections only, or loggedin users only.
If no visibility is specified, the post will be "public" and visible to all LinkedIn users.
`public`: The post will be visible to all LinkedIn users. Available for both company pages and
personal LinkedIn connected accounts. Default if no visibility is specified.
`connections`: The post will be visible to the 1st degree network of the owner (user profile).
Available for personal LinkedIn connected accounts only.
`loggedin`: The post will be visible to logged in LinkedIn users only. Available for both
company pages and personal LinkedIn connected accounts.
Use the `visibility` field in the `linkedInOptions` object:
```json LinkedIn Post Visibility theme={"system"}
{
"linkedInOptions": {
"visibility": "public" // "public", "connections", or "loggedin"
}
}
```
## Video Publishing Permissions
On LinkedIn, only users with specific permissions can publish videos to company pages:
1. Users with Admin permissions.
2. Users with Direct Sponsored Content (DSC) permissions.
Content Administrators do not have the ability to publish videos to LinkedIn company pages.
## Video Thumbnail
Set a LinkedIn thumbnail for a video. Send a remote URL of a PNG or JPG file that is the same dimensions as the video and less than 10 MB. URL should end in .png or .jpg.
Use the `thumbNail` in the `linkedInOptions` object.
```json LinkedIn Video Thumbnail theme={"system"}
{
"linkedInOptions": {
"thumbNail": "https://octodex.github.com/images/Fintechtocat.png"
}
}
```
Please see here for more [examples of using the LinkedIn API](https://www.ayrshare.com/how-to-post-and-get-analytics-with-the-linkedin-api#linkedin-api-examples).
# Pinterest API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/pinterest
Options for posting using the Pinterest API
## Posting an Image Pin to Pinterest
The Pinterest API requires an image to be included in the post. Other parameters are optional.
Please see [Pinterest Media Guidelines](/docs/media-guidelines/pinterest) and [Pinterest Authorization](/docs/dashboard/connect-social-accounts/pinterest) for more information.
```json Pinterest Post theme={"system"}
{
"post": "The best Pinterest API ever!", // Maximum 500 characters or empty string
"platforms": ["pinterest"],
"mediaUrls": ["https://images.ayrshare.com/imgs/GhostBusters.jpg"]
}
```
## Pinterest Options
You can set additional options for a post by using the `pinterestOptions` parameter.
```json Pinterest Post theme={"system"}
{
"post": "The best Pinterest API ever!", // Maximum 500 characters or empty string
"platforms": ["pinterest"],
"mediaUrls": ["https://images.ayrshare.com/imgs/GhostBusters.jpg"],
"pinterestOptions": {
"altText": ["This is my best pic", "😃 here is the next one"], // maximum 500 characters
"boardId": "93383204522",
"carouselOptions": [
{
"title": "Image 1",
"link": "https://www.cnn.com",
"description": "Super Image 1"
},
{
"title": "Image 2",
"link": "https://www.google.com",
"description": "Super Image 2"
}
],
"link": "https://www.ayrshare.com", // maximum 2048 characters
"note": "Private note", // maximum 1000 characters
"thumbNail": "https://images.ayrshare.com/imgs/GhostBusters.jpg",
"title": "A Pinterest Board for You" // maximum 100 characters
}
}
```
Pinterest options are optional fields that can be used to control the post.
The alternative text for images and videos for accessibility and screen readers. Maximum 500 characters.
See [Pinterest Alternative Text](/docs/apis/post/social-networks/pinterest#alternative-text) for more information.
Post to another one of the user's Pinterest Boards by specifying the ID from the /user/details endpoint.
If not specified, posts to the default linked board.
See [Pinterest Board ID](/docs/apis/post/social-networks/pinterest#board-id) for more information.
Add up to 5 images as a Pinterest carousel with optional titles, links, and descriptions.
Each object can contain: `title`, `link`, and `description`.
See [Pinterest Image Carousel](/docs/apis/post/social-networks/pinterest#pinterest-image-carousel) for more information.
The destination URL users will be directed to when clicking the pin image. Maximum 2048 characters.
Creates a clickable link attached to your pin.
See [Pin Link](/docs/apis/post/social-networks/pinterest#pin-link) for more information.
Add private notes to individual Pins that only you and board collaborators can see. Maximum 1000 characters.
See [Pin Note](/docs/apis/post/social-networks/pinterest#pin-note) for more information.
Set a thumbnail for video pins. Must be PNG or JPG, same dimensions as video, under 10MB.
Required for video pins.
See [Video Pin (Thumbnail)](/docs/apis/post/social-networks/pinterest#video-pin-thumbnail) for more information.
The title of the pin to display in the "Add your title" section. Maximum 100 characters.
See [Pin Title](/docs/apis/post/social-networks/pinterest#pin-title) for more information.
\*Links in the `post` field are not clickable. Please use the `link` field to add a
clickable link to the Pin.
See [Pinterest Media Guidelines](/docs/media-guidelines/pinterest) for more information.
## Alternative Text
Add alternative text, also known as alt text, to a Pinterest image or video. Pinterest alt text is an accessibility feature used for additional user info and screen readers.
Use the `altText` in the `pinterestOptions` object.
```json Pinterest Alt Text theme={"system"}
{
"pinterestOptions": {
"altText": ["This is my best pic", "😃 here is the next one"]
}
}
```
The alt text is limited to 500 characters.
## Board ID
Post to another one of the user's Pinterest Boards by specifying the ID obtained from the [/user/details](/docs/apis/user/pinterest-board) endpoint. Otherwise post to the default linked board.
Use the `boardId` in the `pinterestOptions` object.
```json Pinterest Board ID theme={"system"}
{
"pinterestOptions": {
"boardId": "93383204522"
}
}
```
## Character Limits
Please see [Pinterest Character Limits](/docs/help-center/technical-support/character_limits#pinterest-character-limits) for more information.
## Pin Link
The destination URL that users will be directed to when they click on your pin image. This creates a clickable link attached to your pin. Maximum length is 2048 characters.
Use the `link` in the `pinterestOptions` object.
```json Pin Link theme={"system"}
{
"pinterestOptions": {
"link": "https://www.ayrshare.com"
}
}
```
## Pin Note
You can add private notes to individual Pins on your boards. Only you and board collaborators will be able to see them.
Use the `note` in the `pinterestOptions` object.
```json Pin Note theme={"system"}
{
"pinterestOptions": {
"note": "Private note for collaborators"
}
}
```
## Pinterest Image Carousel
Post up to five images as a Pinterest carousel. By adding more than one media URL, a carousel is automatically created. You can also add in optional carousel parameter. Please see below.
```json Pinterest Carousel Post theme={"system"}
{
"post": "Carousel Time",
"platforms": ["pinterest"],
"mediaUrls": [
"https://img.ayrshare.com/random/photo-1.jpg",
"https://img.ayrshare.com/random/photo-2.jpg"
],
"pinterestOptions": {
"carouselOptions": [
// optional
{
"title": "Image 1",
"link": "https://www.cnn.com",
"description": "Super Image 1"
},
{
"title": "Image 2",
"link": "https://www.google.com",
"description": "Super Image 2"
}
]
}
}
```
The optional `carouselOptions` field takes an array of objects. Each carousel object corresponds to the equivalent media URL string, e.g. the first carousel object refers to the first `mediaUrl` string.
`title`: The image title.
`link`: The external destination link for the image.
`description`: The image description.
## Pinterest Mentions
While you can add a @handle to a Pinterest post, Pinterest does not support resolving mentions in the post text.
The @handle will remain as plain text.
## Pin Title
The title of the pin to display. This appears in the "Add your title" section of a new pin. Maximum 100 characters.
Use the `title` in the `pinterestOptions` object.
```json Pin Title theme={"system"}
{
"pinterestOptions": {
"title": "A Pinterest Board for You"
}
}
```
## Video Pin (Thumbnail)
A video may be posted as a Pin using the standard `mediaUrls` field in the [/post endpoint](/docs/apis/post/post). Additionally, a thumbnail image URL **must be included** with the video with a valid media Content-Type such as `image/jpeg`.
Please see [requirements](/docs/media-guidelines/pinterest).
```json Video Pin with Thumbnail theme={"system"}
{
"pinterestOptions": {
// required
"thumbNail": "https://images.unsplash.com/photo-1513093496871-0a81425386e5?crop=entropy&cs=tinysrgb&fit=max&fm=jpg&ixid=MnwxNjQ1ODN8MHwxfHJhbmRvbXx8fHx8fHx8fDE2Mzg0ODAzNDA&ixlib=rb-1.2.1&q=80&w=400"
}
}
```
Additional information on [posting Pins using the API](https://www.ayrshare.com/blog/pinterest-api-integration-on-ayrshare/).
If your video doesn't end in a known video extension such as mp4, please use the `isVideo` parameter. See the [/post endpoint](/docs/apis/post/post) for details.
# Reddit API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/reddit
Options for posting using the Reddit API
## Posting to Reddit
The following are required body parameters for posting using the Reddit API. Please be sure the subreddit allows automated posting.
Please see [Reddit Media Guidelines](/docs/media-guidelines/reddit) and [Reddit Authorization](/docs/dashboard/connect-social-accounts/reddit) for more information.
```json Reddit Post theme={"system"}
{
"post": "Reddit post", // empty string is allowed
"platforms": ["reddit"], // required
"redditOptions": {
"title": "Reddit Post Title", // required
"subreddit": "test", // required (no "/r/" needed)
"link": "https://www.website.com" // optional: post a link
}
}
```
`title` (required): The title of the post on Reddit.
`subreddit` (required): The subreddit to send the post. Please be sure to follow the subreddit's
posting guidelines. A good subreddit to use for testing is */r/test/* and can be viewed at:
[https://www.reddit.com/r/test/](https://www.reddit.com/r/test/)
`link` (optional): If posting to Reddit and you want to post a link instead of text to the
subreddit. While the `post` parameter text is still required, it is not included in the post
since Reddit links can't have a text body.
Always check the rules of the subreddit before posting. Some subreddits have a karma threshold,
require membership for a time period, limit the frequency of posting, don't allow images, or
require flair to be added. Also, most subreddits have specific rules on spam and self-promotion.
Not following these rules can result in being banned by the subreddit or Reddit.
## Posting an Image to Reddit
Post an image to Reddit either by including the image URL in the `mediaUrl` parameter or the `link` parameter of `redditOptions`. Images posted as a `link` will resolve to the full image.
The `post` parameter text is ignored, but is still required to successfully submit the post. Reddit restricts posting images and text together to their online "fancy pants" editor. This means either an image or text can be posted, but not both at the same time.
```json Reddit Post with Image theme={"system"}
{
"post": "Reddit post", // required, but not added to the post
"platforms": ["reddit"], // required
"mediaUrls": "https://my-media-url.com",
"redditOptions": {
"title": "Reddit Post Title", // required
"subreddit": "test" // required (no "/r/" needed)
}
}
```
## Add Reddit Flair
Some subreddits require flair. Subreddit moderators pre-define the flair and each flair has a unique ID. In the Reddit post to Ayrshare add the flair ID and an optional flair text if the text can be overridden.
```json Reddit Post with Flair theme={"system"}
{
"redditOptions": {
"flairId": "jM8nH92enjswas", // Id of the flair
"flairText": "My New Flair text" // Override the flair text if allowed by flair
}
}
```
You can find the flair ID of a subreddit by calling the [/post/redditFlair](/docs/apis/utils/reddit-get-flair) endpoint.
## Check if a Subreddit Exists
Check if a subreddit exists with the [/validate endpoint](/docs/apis/validate/check-subreddit).
## Add rich text formatting to Reddit posts
If you want to add bold, italic, or superscript text to a Reddit post, use [Reddit-flavored Markdown](https://www.reddit.com/wiki/markdown#wiki_new_reddit-flavored_markdown).
```json Reddit Post with Rich Text theme={"system"}
{
"post": "For example, this can be *italic* or **bold** or ^super ",
"platforms": ["reddit"],
"redditOptions": {
"title": "Rich Text Post",
"subreddit": "test"
}
}
```
## Reddit Mentions
Mention another Reddit user or subreddit.
Mention a Reddit user by adding `@subreddit` or `u/username` in the post text.
Mention a subreddit by adding `r/subreddit` in the post text.
For example:
```json Reddit Post with Mention theme={"system"}
{
"post": "The best Reddit post ever for user @ayrshare and subreddit r/SiliconValleyHBO",
"platforms": ["reddit"]
}
```
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
## Character Limits
Please see [Reddit Character Limits](/docs/help-center/technical-support/character_limits#reddit-character-limits) for more information.
## Additional Endpoints
# Snapchat API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/snapchat
Options for posting using the Snapchat API
When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG for Snapchat it preserves the image's color rendering and writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic signature
does not survive a re-encode. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Posting to Snapchat
The Snapchat API enables direct publishing of content to both Stories and Spotlight.
Stories are temporary posts that disappear after 24 hours, while Spotlight posts are permanent and can help creators and businesses reach a wider audience.
There are three types of posts you can create on Snapchat:
Snapchat accepts either video or image media. Only one media item is allowed per post.
You can learn more using Snapchat's API:
[Snapchat Media Guidelines](/docs/media-guidelines/snapchat) and [Snapchat Authorization](/docs/dashboard/connect-social-accounts/snapchat).
[Snapchat API integration guide](https://www.ayrshare.com/blog/complete-guide-to-snapchat-api-integration/) to learn more about how to post or get analytics on Snapchat.
## Stories
Stories are ephemeral Snaps viewable by friends, subscribers, and non-subscribers in the Snapchat app's 4th tab Discover feed for up to 24-hours.
Publish a Snapchat story as you would any other post:
```json Publish a Snapchat story theme={"system"}
{
"post": "An amazing story", // empty string is allowed
"platforms": ["snapchat"],
"mediaUrl": ["https://img.ayrshare.com/video.mp4"]
}
```
## Saved Stories
Saved Stories are permanent Stories that are viewable on a Public Profile indefinitely.
Publish a Snapchat story with `snapChatOptions` and the `savedStory` option:
```json Publish a Snapchat saved story theme={"system"}
{
"post": "An amazing saved story",
"platforms": ["snapchat"],
"mediaUrl": ["https://img.ayrshare.com/video.mp4"],
"snapChatOptions": {
"savedStory": true
}
}
```
## Spotlight
Spotlights are permanent video Snaps that are distributed and viewable on Spotlight, Snapchat's entertainment platform for user-generated content.
Spotlight offers a channel for creators and businesses to grow their audience on Snapchat.
Publish a Snapchat story with `snapChatOptions` and the `spotlight` option:
```json Publish a Snapchat spotlight theme={"system"}
{
"post": "An amazing spotlight",
"platforms": ["snapchat"],
"mediaUrl": ["https://img.ayrshare.com/video.mp4"],
"snapChatOptions": {
"spotlight": true
}
}
```
## Snapchat Mentions
Currently, user mentions (@username) in Spotlight posts don't resolve as interactive mentions through the API. The text will appear as plain text in your Spotlight posts rather than creating clickable user links.
```json Example with mentions (displays as plain text) theme={"system"}
{
"post": "Check out this awesome content from @johndoe and @janedoe!",
"platforms": ["snapchat"],
"mediaUrl": ["https://img.ayrshare.com/image.jpg"],
"snapChatOptions": {
"spotlight": true
}
}
```
## Snapchat Hashtags
Hashtags are fully supported in Spotlight posts and help increase discoverability. You can include multiple hashtags in your post content to categorize your content and reach relevant audiences. Hashtags are also clickable.
```json Example with hashtags theme={"system"}
{
"post": "Just launched our new product! 🚀 #ayrshare #tech #exciting",
"platforms": ["snapchat"],
"mediaUrl": ["https://img.ayrshare.com/product-launch.mp4"],
"snapChatOptions": {
"spotlight": true
}
}
```
## Character Limits
Please see [Snapchat Character Limits](/docs/help-center/technical-support/character_limits#snapchat-character-limits) for more information.
# Telegram API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/telegram
Options for posting using the Telegram API
## Posting to Telegram
JSON for a basic post with a link and image using the Telegram API:
```json Telegram Post theme={"system"}
{
"post": "The best Telegram message ever #best https://www.telegram.com", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["telegram"]
}
```
Telegram will automatically preview the link in the channel or group unless there is an image or video included. In the above example the image will show. Removing the image will cause the link preview to show.
If your video doesn't end in a known video extension such as mp4, please use the `isVideo` parameter. See the [/post endpoint](/docs/apis/post/post) for details.
See [Telegram Media Guidelines](/docs/media-guidelines/telegram) and [Telegram Authorization](/docs/dashboard/connect-social-accounts/telegram) for more information.
## Animated GIFs
Only one URL is allowed with a Telegram animated GIF. If the media URL does not end in ".gif" or ".GIF", set the `isVideo` field to `true`.
```json Telegram Animated GIF theme={"system"}
{
"randomPost": true,
"platforms": [
"telegram"
],
"isVideo": true, // Set to true if the mediaURL does not end in .gif or .GIF
"mediaUrls": ["https://img.ayrshare.com/012/cat.gif"]
}
```
## Telegram Mentions
Mention another Telegram handle by adding `@handle` in the post text. For example:
```json Telegram Post with Mention theme={"system"}
{
"post": "The best Telegram image post ever @handle",
"platforms": ["telegram"]
}
```
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
## Character Limits
Please see [Telegram Character Limits](/docs/help-center/technical-support/character_limits#telegram-character-limits) for more information.
# Threads API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/threads
Options for posting using the Threads API
Threads publishing fetches media from your URL via Meta's server-side crawler.
If you see Ayrshare error code 379 — especially alongside an Instagram error 440 or 138 in the same
publish — see [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked).
Posting an AI-generated image? When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG it
writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI disclosure, when the image declares one. Threads stores the disclosure but does not render an AI label
today. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic signature does not survive a re-encode. See [Image
Metadata and Content Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Posting to Threads
JSON for a basic post with a link and image using the Threads API:
```json Threads Post theme={"system"}
{
"post": "The best Threads post ever #best #awesome https://www.threads.net", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["threads"]
}
```
The Threads API has the following requirements and restrictions:
Threads will automatically preview the link in the post unless there is an image or video
included. In the above example the image will show. Removing the image will cause the link
preview to show.
Threads profiles are limited to 250 API-published posts within a 24-hour moving period.
Threads only allows 1 hashtag per post.
@mention Threads users will receive a notification.
Maximum 500 post characters.
Multi-image/videos posts are supported and sent as a carousel. You may send up to 20 videos and
images.
Threads does not support deletes via an API. Deletes must occur manually using the Threads app.
If your video doesn't end in a known video extension such as mp4, please use the `isVideo`
parameter. See the [/post endpoint](/docs/apis/post/post) for details.
Threads also supports sending media without post text. If you do not want post text included
send an empty String `post: ""`.
See [Threads Media Guidelines](/docs/media-guidelines/threads) and [Threads
Authorization](/docs/dashboard/connect-social-accounts/threads) for more information.
## Threads Options
You can set additional options for a post by using the `threadsOptions` parameter.
```json Threads Options theme={"system"}
{
"threadsOptions": {
"allowCountries": ["US", "CA"],
"thread": true,
"threadNumber": true,
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"] // used when sending as a thread of threads
}
}
```
Threads options are optional fields that can be used to control the post.
Restrict posts to specific countries using country codes. Use [country codes](/docs/iso-codes/country).
Only available if Meta has enabled geo restrictions for your account.
See [Threads Geo Restrictions](/docs/apis/post/social-networks/threads#geo-restrictions) for more information.
Break long posts into a connected thread series with optional numbering and media.
See [Thread](/docs/apis/post/social-networks/threads#thread) for more information.
Automatically add numbers at the end of each thread in the format of 1/n.
Requires `thread: true`.
Add media objects to a thread of threads. One media object will be added to each thread in order.
Use `null` to skip media for a specific thread. Use objects with multiple URLs for multiple media per thread.
See [Thread Media](/docs/apis/post/social-networks/threads#thread-media) for more information.
## Adding line breaks or rich text to an Threads post
Threads line breaks can be added to a post with a special [new line character](/docs/apis/post/post#line-breaks).
Rich text, such as bold or italic lettering, can be added to a Threads post with a few [html elements](/docs/apis/post/overview#rich-text-posts).
## Carousel of Images and Videos
You can post multiple images or videos to Threads as a carousel; up to a combined total of 20 images or videos may be use in a carousel. Just add your additional images or videos to the `mediaUrls` array and the carousel will automatically be created.
```json theme={"system"}
"mediaUrls": ["https://url.com/image.jpg", "https://url.com/video.mp4" ...]; // Max 20 images or videos
```
Video URLs must end in a known extension such as mp4.
## Character Limits
Please see [Threads Character Limits](/docs/help-center/technical-support/character_limits#threads-character-limits) for more information.
## Geo Restrictions
You can restrict a post to a specific country or countries by using the `allowCountries` array.
```json theme={"system"}
{
"threadsOptions": {
"allowCountries": ["US", "CA"]
}
}
```
`allowCountries`: An array of country codes to allow. See [country codes](/docs/iso-codes/country).
Geo restrictions (geo-gating) on Threads are only available if Meta has enabled this feature for your account.
Meta decides which Threads accounts are eligible for geo restrictions based on factors such as account verification, follower count, or content creator status.
If your account is eligible, you will see the geographic settings (globe icon) in the post composer when creating a new Threads post.
You can check if a user profile is eligible for Threads geo restrictions by checking the `isEligibleForGeoRestrictions` property in the [/user](/docs/apis/user/profile-details) endpoint.
## Threads Mentions
Mention another Threads handle by adding @handle in the post text. For example:
```json theme={"system"}
{
"post": "The best social media API @Ayrshare ever!",
"mediaUrls": ["https://images.com"],
"platforms": ["threads"]
}
```
The @mentioned user will be notified of the mention. Please review the [important
rules](/docs/testing/post-verification#mentions) on mentions.
If the quota has been reached, an error message will be returned.
## Thread
A Threads thread, also known as a threadstorm, is a connected series of posts on Threads that allows you to share longer ideas beyond a single post's character limit, appearing as one continuous narrative when viewed together.
### Posting a Thread
A Threads thread can be posted via the API. A thread is a post broken up into a set of reply posts associated together in Threads. You can either automatically break up the post or specify the [thread breaks](/docs/apis/post/social-networks/threads#thread-breaks) in the post text.
```json Threads Thread theme={"system"}
{
"threadsOptions": {
"thread": true, // required for threadstorm
"threadNumber": true, // optional to add numbers to each thread
"mediaUrls": ["https://site.com/image1.png", "https://site.com/image2.png", ...] // optional one media object is added to a thread in order
}
}
```
`thread: true` to automatically break apart the post text into threads based on line breaks.
`threadNumber: true` to automatically add numbers at the end of threads in the format of 1/n.
For example, the 2nd of 5 threads will have appended: 2/5
`mediaUrls: [array of urls]` to add each media object, an image or video, to a thread in order.
Only one media object will be added to a thread in order.
#### Thread Media
##### Skip Media
Skip media for a thread by using `null` in the array. For example:
`["https://site.com/image1.png", null, "https://site.com/image2.png"]`
This will place image1 on the first post, no image on the second post, and image2 on the third post.
##### Multiple Media
Multiple media objects can be added to a single post within a thread by adding an object `{}` with the media URLs in the `mediaUrls` array. Any unique object keys can be used. For example:
```json Threads Thread with Multiple Media URLs theme={"system"}
{
"threadsOptions": {
"thread": true,
"threadNumber": true,
"mediaUrls": [
"https://img.ayrshare.com/random/photo-1.jpg",
{
"1": "https://img.ayrshare.com/random/photo-2.jpg",
"2": "https://img.ayrshare.com/random/photo-3.jpg"
},
"https://img.ayrshare.com/random/photo-4.jpg"
]
}
}
```
In this example, the first post will contain photo-1.jpg, the second post photo-2.jpg and photo-3.jpg, and the third post photo-4.jpg.
#### Thread Breaks
Ayrshare automatically breaks up the post text into appropriate length posts (> 500 characters) for Threads. When creating threads, we prioritize keeping complete sentences in one post when possible. If a sentence won't fit, we split between sentences. For very long sentences, we split between words. In rare cases where a word is too long, we split the word itself.
You may also manually add paragraphs with `\n\n` to the post text to indicate a unique thread should be created. If you have `\n\n` in the post text, we will not automatically break the post into threads.
For example:
```json Example Threads Thread theme={"system"}
{
"post": "This is post 1\n\nThis is post 2.",
"platforms": ["threads"],
"threadsOptions": {
"thread": true
}
}
```
will result in two posts in the thread.
If you want to add paragraphs, but not break into posts, use `\u2063\n\u2063\n`.
```json Threads Thread with Paragraphs theme={"system"}
{
"post": "This is paragraph 1\u2063\n\u2063\nThis is paragraph 2.",
"platforms": ["threads"],
"threadsOptions": {
"thread": true
}
}
```
will result in one post with two paragraphs since the post is below 500 characters.
### Delete a Thread
Threads does not support deletes via an API. Deletes must occur manually using the Threads app.
# TikTok API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/tiktok
Options for posting using the TikTok API
Ayrshare offers [direct publishing of TikTok videos](https://www.ayrshare.com/blog/introducing-tiktok-direct-publishing-analytics-and-commenting/), comment management, and retrieval of advanced analytics for either your personal or business TikTok account using the TikTok API.
TikTok asynchronously processes video and photos, so the JSON response will be status: "pending" for both immediate and scheduled posts. Once TikTok has completed processing, your registered [Scheduled Action webhook](/docs/apis/webhooks/actions#scheduled-action) will be called.
When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG for a photo post it preserves the image's color rendering and writes a small XMP packet carrying only the Iptc4xmpExt:DigitalSourceType AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA cryptographic signature
does not survive a re-encode. This is independent of the video-only isAIGenerated
toggle documented below. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## TikTok Video Post
JSON for a basic TikTok video post that is directly published:
```json TikTok Video Post theme={"system"}
{
"post": "The best TikTok \n video ever #bestvideo", // Max 2,200 characters with a line break
"mediaUrls": ["https://img.ayrshare.com/012/tiktok.mp4"],
"platforms": ["tiktok"]
}
```
Example JSON post response:
```json TikTok Video Post Response theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"idShare": "video.7088122496758679353.nzLqBWbf",
"id": "pending",
"isVideo": true,
"platform": "tiktok"
}
],
"id": "lb42orDhySAZmLWtj6b6",
"refId": "23a9da9e0df1184a7a6a1fc2c60b8023aa9a32a1",
"post": "The best TikTok video ever #bestvideo"
}
```
TikTok does not currently support line breaks in the post text. Included line breaks will be
ignored.
Either one video or up to 35 images may be published. TikTok does not support a combination of
video and images. Please see below for more details.
If the video does not end in a known extension, use
[isVideo](/docs/apis/post/overview#video-extension).
TikTok also supports sending media without post text. If you do not want post text included send
an empty String `post: ""`.
See [TikTok Media Guidelines](/docs/media-guidelines/tiktok) and [TikTok
Authorization](/docs/dashboard/connect-social-accounts/tiktok) for more information.
### TikTok Video Requirements
Please see [TikTok Video Requirements](/docs/media-guidelines/tiktok#video).
The video must end in a known video extension such as mp4. Please either reverse proxy the URL,
add on a [vanity URL with a
CDN](https://www.ayrshare.com/blog/how-to-put-a-cdn-in-front-of-firebase-cloud-storage/), or use the
[/media](/docs/apis/media/overview) endpoint.
TikTok's post text character limit is 2,200.
TikTok limits the API video publishing to 6 videos per minute with an upper limit of 15 videos per
day.
## TikTok Image Post
JSON for a basic TikTok image (photo) post that is directly published:
```json TikTok Image Post theme={"system"}
{
"post": "The best TikTok \n video ever #bestvideo", // Max 2,200 characters with a line break
"mediaUrls": [
"https://img.ayrshare.com/012/gb.jpg",
"https://img.ayrshare.com/random/photo-1.jpg"
], // Up to 35 images
"platforms": ["tiktok"]
}
```
Example JSON response:
```json TikTok Image Post Response theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"idShare": "p_pub_url~v2.7408974036430047275",
"id": "pending",
"isVideo": false,
"platform": "tiktok"
}
],
"id": "8815mJ5bWApEebWjE233",
"tikTokId": "p_pub_url~v2.7408974036430047333",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc333",
"post": "Opportunity is missed by most people because it is dressed in overalls and looks like work - Thomas Edison"
}
```
TikTok does not currently support line breaks in the post text. Included line breaks will be
ignored.
Either one video or up to 35 images may be published.
TikTok does not support a combination of video and images. Please see below for more details.
The images must be of type JPG, JPEG, or WEBP. TikTok does not accept PNG media files.
You may also select one of the images as the cover photo with the `imageCoverIndex`. By default,
the first image is used. Please see below for details.
### TikTok Image Requirements
Please see [TikTok Image Requirements](/docs/media-guidelines/tiktok#images).
Up to 35 images may be included in a post, at 20 MB per image.
The images must be of type JPG, JPEG, or WEBP. TikTok does not accept PNG media files.
TikTok's post text character limit is 2,200.
TikTok limits the API video publishing to 6 photos per minute with an upper limit of 15 photos per
day.
## TikTok Processing
TikTok does asynchronous processing of videos and images, so the response will have the `id` field set to `"pending"`.
After TikTok completes their processing, usually within 1 - 2 minutes, the `id` field will be updated with the TikTok video `id` and a `postUrl` will be added.
You can retrieve the final status of the TikTok post using
[webhooks](/docs/apis/webhooks/actions#tiktok-publishing-webhook) or the
[/history](/docs/apis/history/overview) endpoint and usually takes up to 1-2 minutes to be available.
When the user publishes the video in the TikTok mobile app, a "scheduled" webhook will be sent
with the `subAction: "tikTokPublished"`.
A [first comment](/docs/apis/post/overview#first-comment) on a TikTok post is deferred: it is posted
automatically once the `tikTokPublished` webhook resolves the real video `id`, not at publish
time. The video `visibility` must be `public`, otherwise the first comment cannot be posted and a
comment error is returned.
If an error occurs, such as TikTok was unable to process the video or Ayrshare internal tests
failed, the `id` field will be set to "failed" and the `errors` field will contain the error
details.
The `idShare` is used for internal referencing the pending video.
## TikTok Options
When publishing a TikTok video or images [additional options](/docs/apis/post/social-networks/tiktok#available-tiktok-options) are available.
Video Publishing Example:
```json TikTok Video Publishing theme={"system"}
{
"tikTokOptions": {
"disableComments": true, // Default false. Disable comments on the published video.
"disableDuet": true, // Default false. Disable duets on the published video.
"disableStitch": true // Default false. Disable stitches on the published video.
}
}
```
Image Publishing Example:
```json TikTok Image Publishing theme={"system"}
{
"tikTokOptions": {
"imageCoverIndex": 1, // Use the second image in the mediaUrls.
"title": "Amazing images"
}
}
```
### Options
The following options are available for TikTok posts.
They should be added to the `tikTokOptions` object.
Please see below for more details on each option.
```json TikTok Options theme={"system"}
{
"post": "The best TikTok video ever #bestvideo",
"mediaUrls": ["https://img.ayrshare.com/012/tiktok.mp4"],
"platforms": ["tiktok"],
"tikTokOptions": {
"autoAddMusic": true,
"disableComments": true,
"disableDuet": true,
"disableStitch": true,
"draft": true,
"isAIGenerated": true,
"isBrandedContent": true,
"isBrandOrganic": true,
"imageCoverIndex": 1,
"title": "Amazing images",
"thumbNailOffset": 30000,
"visibility": "public"
}
}
```
Whether to automatically add recommended music to the post.
If you set this field to `true`, you can change the music later in the TikTok app.
Media type: image
Whether to disable comments on the published post.
Media type: video, image
Disable duets on the published video.
Media type: video
Disable stitch on the published video.
Media type: video
Whether to create a draft post.
See [draft options](/docs/apis/post/social-networks/tiktok#tiktok-video-draft-post) for more information.
Media type: video or image
Whether to enable the AI-generated content toggle for the video post.
If you enable the toggle, your video will be labeled as "Creator labeled as AI-generated" once posted and can't be changed.
The "Creator labeled as AI-generated" label indicates that the content was completely AI-generated or significantly edited with AI.
Turning on the AI-generated content setting won't affect the distribution of your video as long as
it doesn't violate TikTok's [Community
Guidelines](https://www.tiktok.com/community-guidelines/en/).
Media type: video
Whether to enable the Branded Content toggle. If this field is set to `true`, the video will be labeled as Branded Content, indicating you are in a paid partnership with a brand. A "Paid partnership" label will be attached to the video.
Media type: video, image
Whether to enable the Brand Organic Content toggle. If this field is set to `true`, the video will be labeled as Brand Organic Content, indicating you are promoting yourself or your own business. A "Promotional content" label will be attached to the video.
Media type: video, image
The index of the `mediaUrls` to be used as the cover for the post.
Media type: image
The title of the post.
Media type: image
The frame to use for the video cover.
See [video thumbnail options](/docs/apis/post/social-networks/tiktok#video-thumbnail) for more information.
Media type: video
How the post is shared and who can see it.
Values: `public`, `private`, `followers`, or `friends`.
See [visibility options](/docs/apis/post/social-networks/tiktok#visibility-options) for more information.
Media type: video, image
### Visibility Options
| Visibility | Description |
| :--------- | :--------------------------------------------------------------------------- |
| public | Visible to all TikTok users. |
| private | Private, only visible to the account itself. |
| followers | Only visible to followers of the account. Requires a private TikTok account. |
| friends | Only visible to mutual followers. |
TikTok only offers the `followers` option on private TikTok accounts. If the
account is public, TikTok accepts the post without an error and publishes it
visible to everyone. TikTok Business accounts are always public, so they can't
use `followers`. Switching an account from private to public also changes
existing followers-only posts to be visible to everyone.
Private posts will remain in a status `pending` and no TikTok webhook will be sent until the post is made public.
## Video Thumbnail
There are two ways to set a thumbnail, also known as a cover photo, for a TikTok video:
1. Using the `thumbNailOffset` parameter to set a thumbnail frame.
2. Using the `thumbNail` parameter to set a thumbnail image from a URL.
Only videos are supported for setting a thumbnail.
### Thumbnail Offset
Set a thumbnail for a TikTok video by selecting an offset frame.
```json TikTok Video Thumbnail Offset theme={"system"}
{
"tikTokOptions": {
"thumbNailOffset": 30000 // milliseconds of offset image
}
}
```
The offset is the location in milliseconds of the thumbnail frame. Default value is `0`, which is the first frame of the video.
### Thumbnail URL
Set a thumbnail for a TikTok video by uploading an image from a URL.
```json TikTok Video Thumbnail URL theme={"system"}
{
"tikTokOptions": {
"thumbNail": "https://img.ayrshare.com/012/gb.jpg"
}
}
```
If you use the `thumbNail` parameter, the `thumbNailOffset` parameter will be ignored.
Please see [TikTok Thumbnail Requirements](/docs/media-guidelines/tiktok#video-thumbnail) for more information.
## TikTok Mentions
Mention another TikTok handle by adding `@handle` in the post text. For example:
```json TikTok Mention theme={"system"}
{
"post": "Love the @ayrshare social media api"
}
```
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
## TikTok Draft Post
Create a draft post for a TikTok video or image, allowing you to edit the video or image before publishing.
```json TikTok Video Draft Post theme={"system"}
{
"post": "The best TikTok video ever #bestvideo", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/tiktok.mp4"],
"platforms": ["tiktok"],
"tikTokOptions": {
"draft": true
}
}
```
The draft video or image post will be found under the notifications **Inbox** in bottom row of the TikTok app.
Look for a **System notifications** message and then click the top **Your content from Ayrshare is ready** message.
The Ayrshare `postUrl` will remain in `pending` status until the video is published. First comment not supported on draft posts.
## Authorization Refresh
TikTok must be reauthorized *every year* via the Social Accounts page.
An email and webhook social action notification will be sent 15 days in advance of authorization
expiration.
The refresh required date and remaining days can be retrieved from the
[/user](/docs/apis/user/overview) endpoint.
## Character Limits
Please see [TikTok Character Limits](/docs/help-center/technical-support/character_limits#tiktok-character-limits) for more information.
## Additional Information
Additional [examples on using the TikTok API](https://www.ayrshare.com/blog/tiktok-api-how-to-post-to-tiktok-using-a-social-media-api/).
# X API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/x-twitter
Options for posting using the X API
## X BYO API Keys
Starting March 31, 2026, all X/Twitter operations require your own API credentials. After linking your X account via OAuth, include these 2 headers in every request that targets X:
| Header | Value |
| ----------------------------- | ------------------------------------- |
| `X-Twitter-OAuth1-Api-Key` | Your API Key (Consumer Key) |
| `X-Twitter-OAuth1-Api-Secret` | Your API Key Secret (Consumer Secret) |
Not linked yet? See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) to connect your X account.
Ayrshare no longer imposes its own monthly or daily X/Twitter rate limits. Because X requests use
your own credentials (BYO), your usage is governed solely by your own X Developer App limits. See
the [X API rate limits
documentation](https://developer.x.com/en/docs/x-api/rate-limits) for details.
## Posting to X (Twitter)
JSON for a basic post with a link and image using the X API, formerly known as the Twitter API:
```json X Post theme={"system"}
{
"post": "The best Tweet ever #best https://www.twitter.com", // empty string is allowed
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
"platforms": ["twitter"]
}
```
X will automatically preview the link in the Tweet unless there is an image or video included.
In the above example the image will show. Removing the image will cause the link preview to
show.
If your video doesn't end in a known video extension such as mp4, please use the `isVideo`
parameter. See the [/post endpoint](/docs/apis/post/post) for details.
X also supports sending media without post text. If you do not want post text included send an
empty String `post: ""`.
You may upload up to 4 images or videos in a single Tweet. Please see the important guidelines
and restrictions [posting Twitter videos](/docs/media-guidelines/x_twitter).
See [X Media Guidelines](/docs/media-guidelines/x_twitter) and [X
Authorization](/docs/dashboard/connect-social-accounts/x-twitter) for more information.
## X Options
You can set additional options for a post by using the `twitterOptions` parameter.
```json X Options theme={"system"}
{
"twitterOptions": {
"altText": ["This is my best pic", "😃 here is the next one"],
"blockCountries": ["US", "CA"], // or "allowCountries": ["GB", "IE"]
"longPost": true,
"longVideo": true,
"poll": {
"duration": 5, // required. Number in minutes
"options": ["yes", "maybe", "no"] // required
},
"quoteTweetId": "651601430669664256",
"replySettings": "mentioned",
"subscribersOnly": true,
"isAIGenerated": true,
"thumbNail": "https://img.ayrshare.com/012/gb.jpg",
// Video Metadata
"videoTitle": "My Product Demo",
"videoDescription": "A short walkthrough of our latest release.",
// Subtitles / Captions for Videos
"subTitleUrl": "https://img.ayrshare.com/012/captions.srt",
"subTitleLanguage": "en",
"subTitleName": "English",
// Thread Options
"thread": true,
"threadNumber": true,
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"],
}
}
```
X options are optional fields that can be used to control the post.
Alternative text for images to help with accessibility and screen readers. Maximum 1,000 characters per alt text.
See [Alt Text](/docs/apis/post/social-networks/x-twitter#alt-text) for more information.
Restrict media to specific countries by blocking certain regions. Use [country codes](/docs/iso-codes/country).
Cannot be used with `allowCountries`. See [Geo Restrictions](/docs/apis/post/social-networks/x-twitter#geo-restrictions) for more information.
Restrict media to specific countries by allowing certain regions. Use [country codes](/docs/iso-codes/country).
Cannot be used with `blockCountries`. See [Geo Restrictions](/docs/apis/post/social-networks/x-twitter#geo-restrictions) for more information.
Enable posting of longer posts up to 25,000 characters for Premium users.
See [Long Post](/docs/apis/post/social-networks/x-twitter#long-post) for more information.
Allow posting videos longer than 2 minutes 20 seconds for approved accounts.
See [Long Video](/docs/apis/post/social-networks/x-twitter#long-video) for more information.
Conduct polls with custom options and duration.
Required fields: `duration` (number in minutes), `options` (array of strings).
See [Polls](/docs/apis/post/social-networks/x-twitter#polls) for more information.
Quote another tweet by specifying the Tweet ID.
See [Quote Tweet](/docs/apis/post/social-networks/x-twitter#quote-tweet) for more information.
Control who can reply to the post.
Values: `following`, `mentioned`, `subscribers`, or `verified`.
See [Reply Settings](/docs/apis/post/social-networks/x-twitter#reply-settings) for more information.
Make the post visible only to subscribers.
See [Subscribers Only](/docs/apis/post/social-networks/x-twitter#subscribers-only) for more information.
Apply X's "Made with AI" label to disclose that the post contains AI-generated media.
Both `true` and `"true"` apply the label. Any other value leaves the label off — the post still
publishes and the response adds a `warnings` entry explaining why.
The label applies only to posts that include media, and cannot be changed after posting. Applies to
immediate, scheduled, and threaded posts.
Media type: image, video
See [Made with AI](/docs/apis/post/social-networks/x-twitter#made-with-ai) for more information.
Add subtitles/captions to videos using SRT files. Must be a valid SRT file URL ending in `.srt`.
See [Subtitles / Captions for Videos](/docs/apis/post/social-networks/x-twitter#subtitles-captions-for-videos) for more information.
The language of the subtitles. Must be a valid [language code](/docs/iso-codes/language).
The name of the caption track. Maximum 150 characters.
Set a thumbnail (cover image) for videos. Must be a URL to a JPEG, PNG, BMP, or WebP image file.
See [Video Thumbnail](/docs/apis/post/social-networks/x-twitter#video-thumbnail) for more information and [X Media Guidelines](/docs/media-guidelines/x_twitter#video-thumbnail) for image requirements.
Set the title for a video. Maps to the title field in X Media Studio.
See [Video Metadata](/docs/apis/post/social-networks/x-twitter#video-metadata) for more information.
Set the description for a video. Maps to the description field in X Media Studio.
See [Video Metadata](/docs/apis/post/social-networks/x-twitter#video-metadata) for more information.
Break long posts into connected thread series with optional numbering and media.
See [Threads](/docs/apis/post/social-networks/x-twitter#thread) for more information.
Automatically add numbers at the end of threads in the format of 1/n.
Requires `thread: true`.
Add media objects to threads. One media object will be added to each thread in order.
Use `null` to skip media for a specific thread. Use objects with multiple URLs for multiple media per thread.
## Alt Text
Add alternative text, also known as alt text, to a Tweet's image. X alt text is an accessibility feature used for additional user info and screen readers.
Use the `altText` in the `twitterOptions` object.
```json X Alt Text theme={"system"}
{
"twitterOptions": {
"altText": ["This is my best pic", "😃 here is the next one"] // Array of Alt Texts
}
}
```
Each alt text must correspond to an image in the `mediaUrls` array. The alt text will be applied to each image in order.
Alt text cannot be applied to videos. If a video is included in the `mediaUrls` with `altText`,
the video will not be posted. Alt text must be 1,000 characters or less.
## Geo Restrictions
You can restrict X media, such as an image or video, to a specific countries by using the `blockCountries` and `allowCountries` parameters with [country codes](/docs/iso-codes/country).
The post will still show in all countries, but the media will not be available in the countries specified.
```json Block Countries theme={"system"}
{
"twitterOptions": {
"blockCountries": ["US", "CA"]
}
}
```
```json Allow Countries theme={"system"}
{
"twitterOptions": {
"allowCountries": ["GB", "IE"]
}
}
```
`blockCountries`: An array of country codes to block. See [country codes](/docs/iso-codes/country).
`allowCountries`: An array of country codes to allow. See [country codes](/docs/iso-codes/country).
You must only use one of the parameters `blockCountries` or `allowCountries` at a time.
If both parameters are used or a country is not supported by X, the geo restrictions will be ignored.
## Long Post
Users with Premium X accounts, such as Premium or Premium Plus, have the ability to post longer posts of up to 25,000 characters. Ayrshare automatically allows long from posts for users with Premium X accounts.
If the user changes their X Premium status, please wait 24 hours for it to reflect in Ayrshare. You can check the Premium subscription status of a user with the [/user](/docs/apis/user/overview) or [/analytics](/docs/apis/analytics/social) endpoints.
You may also force a long form post to be accepted with the `longPost` body parameter. This can be done by including the following JSON in your request:
```json X Long Post theme={"system"}
{
"twitterOptions": {
"longPost": true
}
}
```
However, if a user without a Premium account attempts to post a long tweet, the system will return a `code: 111` error.
## Long Video
*Business or Enterprise Plan required.*
X requires videos have a [maximum video length](/docs/media-guidelines/x_twitter#video) of 2 minutes and 20 seconds.
However, if you have been approved by X to upload longer videos, such if ther user's X account is Premium account or in the [Amplify Partner Program](https://media.twitter.com/en/articles/products/2018/in-stream-video-ads-for-publishers), you can post videos up to 10+ minutes in length.
Please verify that your user's X account is Premium or in the [Amplify Partner
Program](https://media.twitter.com/en/articles/products/2018/in-stream-video-ads-for-publishers)
before using the `longVideo` parameter. If your user's X account is not authorized to post long
videos, the system will return an error.
Use the `longVideo` twitterOptions parameter when posting a long video:
```json X Long Video theme={"system"}
{
"twitterOptions": {
"longVideo": true
}
}
```
## Mentions
Mention another X handle by adding `@handle` in the post text. For example:
```json X Mention theme={"system"}
{
"post": "The best social media API @Ayrshare ever!",
"platforms": ["twitter"]
}
```
Please review the [important rules](/docs/testing/post-verification#mentions) on mentions.
## Polls
Conduct an X Poll with the `twitterOptions` `poll` parameter.
```json X Poll theme={"system"}
{
"twitterOptions": {
"poll": {
"duration": 5, // required. Number in minutes
"options": ["yes", "maybe", "no"] // required
}
}
}
```
`duration`: A number of minutes specifying the duration the poll will be conducted.
`options`: An array of strings of the poll options.
## Quote Tweet
You can quote another Tweet by specifying the low-level Tweet ID. The ID can be retrieved via the [`/post`](/docs/apis/post/post) response in the `postIds` field, [get history](/docs/apis/history/get-history), or directly from the Tweet URL: [https://twitter.com/Ayrshare/status/**1651601430669664256**](https://twitter.com/Ayrshare/status/1651601430669664256)
```json X Quote Tweet theme={"system"}
{
"twitterOptions": {
"quoteTweetId": "651601430669664256" // low-level Tweet Id
}
}
```
## Reply Settings
You can set the reply settings for a post to only allow replies by certian types of users.
```json X Reply Settings theme={"system"}
{
"twitterOptions": {
"replySettings": "mentioned"
}
}
```
The `replySettings` parameter can be one of the following values:
`following`: Only users who the X account is following can reply.
`mentioned`: Only users who are mentioned in the post can reply.
`subscribers`: Only users who are subscribers to the X account who posted the post can reply.
`verified`: Only users who are verified on X can reply to the post.
## Subscribers Only
You can set a post to only be visible to subscribers by using the `subscribersOnly` parameter.
```json X Subscribers Only theme={"system"}
{
"twitterOptions": {
"subscribersOnly": true
}
}
```
## Made with AI
Apply X's native "Made with AI" label to disclose that a post contains AI-generated media. Set the `isAIGenerated` field in the `twitterOptions` object to `true`.
```json X Made with AI theme={"system"}
{
"twitterOptions": {
"isAIGenerated": true
}
}
```
### Accepted Values
Both the boolean `true` and the string `"true"` apply the label; `false` and `"false"` leave it off.
Any other value — `"yes"` or `1`, for example — also leaves the label off, but never fails the
request: the post publishes normally and the response adds a `warnings` entry listing the accepted
values.
The Ayrshare [MCP Server](/docs/additional/mcp-action-server) takes `isAIGenerated` as a strict boolean —
pass `true`, not `"true"`.
The label applies only to posts that include media (image or video). It has no effect on text-only
posts, and it cannot be changed after the post is published.
Applies to immediate, scheduled, and threaded posts — a scheduled post publishes with the same "Made
with AI" label it would have received if posted immediately. On a thread, each part that includes
media is labeled.
## Subtitles / Captions for Videos
You can add X subtitles, also known as X captions, to videos by including an [SRT file](https://en.wikipedia.org/wiki/SubRip). Use the `subTitleUrl` field in the `twitterOptions` object to specify the URL to your SRT file.
```json X Subtitles theme={"system"}
{
"twitterOptions": {
"subTitleUrl": "https://img.ayrshare.com/012/captions.srt",
"subTitleLanguage": "en",
"subTitleName": "English"
}
}
```
`subTitleUrl`: A valid SRT file. The URL must start with `https://` and end in `.srt` and be a
valid SRT file.
`subTitleLanguage`: Optional: The language of the subtitles. Must be a valid [language
code](/docs/iso-codes/language). Default: "en".
`subTitleName`: Optional: The name of the caption track. The name is intended to be visible to
the user as an option during playback. The maximum name length supported is 150 characters.
Default: "English".
## Video Thumbnail
Set a thumbnail (cover image) for Twitter/X videos. The thumbnail is displayed before the video plays and helps users understand the video content. Use the `thumbNail` in the `twitterOptions` object.
```json Twitter/X Video Thumbnail theme={"system"}
{
"twitterOptions": {
"thumbNail": "https://img.ayrshare.com/012/gb.jpg"
}
}
```
"thumbNail": A URL to the thumbnail image. Supported image formats are JPEG, PNG, BMP, and WebP.
The thumbnail image should represent the video content and be visually appealing to encourage engagement.
See [X Media Guidelines](/docs/media-guidelines/x_twitter#video-thumbnail) for image requirements.
## Video Metadata
Set a title and description for a video posted to X. These map to the title and description fields in X Media Studio. Use the `videoTitle` and `videoDescription` fields in the `twitterOptions` object.
```json X Video Metadata theme={"system"}
{
"twitterOptions": {
"videoTitle": "My Product Demo",
"videoDescription": "A short walkthrough of our latest release."
}
}
```
`videoTitle`: The title for the video, mapped to the X Media Studio title field.
`videoDescription`: The description for the video, mapped to the X Media Studio description
field.
## Video Monetization (Pro Media)
Ayrshare supports X (Twitter) video monetization for eligible accounts through X's Pro Media program. This is a limited-access capability — [contact us](mailto:support@ayrshare.com) if you'd like access.
## Thread
An X Thread, also known as a tweetstorm, is a connected series of posts on X (formerly Twitter) that allows you to share longer ideas beyond a single post's character limit, appearing as one continuous narrative when viewed together.
### Posting a Thread
A X Thread can be posted via the API.
A thread is a post broken up into a set of reply threads and associated in X with a line.
You cna either automatically break up the post or specify the [thread breaks](/docs/apis/post/social-networks/x-twitter#thread-breaks) in the post text.
```json X Thread theme={"system"}
{
"twitterOptions": {
"thread": true, // required for TweetStorm
"threadNumber": true, // optional to add numbers to each thread
"mediaUrls": ["https://site.com/image1.png", "https://site.com/image2.png", ...] // optional one media object is added to a thread in order
}
}
```
`thread: true` to automatically break apart the post text into threads based on line breaks.
`threadNumber: true` to automatically add numbers at the end of threads in the format of 1/n.
For example the 2nd of 5 threads will have appended: 2/5
`mediaUrls: [array of urls]` to add each media object, an image or video, to a thread in order.
Only one media object will be added to a thread in order.
If the post is sent as a X Thread, the returned post analytics will be an array of Tweets, `"twitter": []`. See [Post Analytics 200 Response](/docs/apis/analytics/post) for more information.
#### Thread Media
##### Skip Media
Skip media for the thread by using `null` in the array. For example:
`["https://site.com/image1.png", null, "https://site.com/image2.png"]`
This will place image1 on the first Tweet, no image on the second Tweet, and image2 on the third Tweet.
##### Multiple Media
Multiple media objects can be added to a Tweet in a Thread by adding an object `{}` with the media URLs in the `mediaUrls` array. Any unique object keys can be used. For example:
```json X Thread with Multiple Media URLs theme={"system"}
{
"twitterOptions": {
"thread": true,
"threadNumber": true,
"mediaUrls": [
"https://img.ayrshare.com/random/photo-1.jpg",
{
"1": "https://img.ayrshare.com/random/photo-2.jpg",
"2": "https://img.ayrshare.com/random/photo-3.jpg"
},
"https://img.ayrshare.com/random/photo-4.jpg"
]
}
}
```
In this example, the first Tweet will contain photo-1.jpg, the second Tweet photo-2.jpg and photo-3.jpg, and the third Tweet photo-4.jpg.
#### Thread Breaks
Ayrshare automatically breaks up the post text into appropriate length tweet (> 280 characters).
When creating threads, we prioritize keeping complete sentences in one post when possible.
If a sentence won't fit, we split between sentences.
For very long sentences, we split between words.
In rare cases where a word is too long, we split the word itself.
You may also manually add paragraphs with `\n\n` to the post text to indicate a unique thread should be created.
If you have `\n\n` in the post text, we will not automatically break the post into threads.
For example:
```json Example X Thread theme={"system"}
{
"post": "This is tweet 1\n\nThis is tweet 2.",
"platforms": ["twitter"],
"twitterOptions": {
"thread": true
}
}
```
will result in two Tweets in the thread.
If you want to add paragraphs, but not break into Tweets, use `\u2063\n\u2063\n`
```json X Thread with Paragraphs theme={"system"}
{
"post": "This is paragraph 1\u2063\n\u2063\nThis is paragraph 2.",
"platforms": ["twitter"],
"twitterOptions": {
"thread": true
}
}
```
will result in one Tweet with two paragraphs since the post is below 280 characters.
### Delete a Thread
To delete a Tweet Storm, call the [/post delete endpoint](/docs/apis/post/delete-post) with the top level post ID returned in the response. All threads will be deleted.
## Character Limits
Please see [X/Twitter Character Limits](/docs/help-center/technical-support/character_limits#x%2Ftwitter-character-limits) for more information.
## X Video Compatibility
Some video software creates MP4 files that are not compatible with X. For example, Camtasia versions older than 2019.0.9 create MP4 files that X rejects. Also more than one audio track often causes problems.
If you receive back the following message while posting, it indicates the video is not compatible with Twitter and needs to be re-encoded.
`"file is currently unsupported"`
Please check your video software for compatibility. For example, Adobe Media Encoder has an export preset for Twitter 1080p Full HD.
Please see here for [more X API examples](https://www.ayrshare.com/twitter-api-how-to-post-and-get-analytics-with-the-twitter-api#twitter-api-examples).
## Subscribers Only
You can set a post to only be visible to subscribers by using the `subscribersOnly` parameter.
```json X Subscribers Only theme={"system"}
{
"twitterOptions": {
"subscribersOnly": true
}
}
```
## Reply Settings
You can set the reply settings for a post to only allow replies by certian types of users.
```json X Reply Settings theme={"system"}
{
"twitterOptions": {
"replySettings": "mentioned"
}
}
```
The `replySettings` parameter can be one of the following values:
`following`: Only users who the X account is following can reply.
`mentioned`: Only users who are mentioned in the post can reply.
`subscribers`: Only users who are subscribers to the X account who posted the post can reply.
`verified`: Only users who are verified on X can reply to the post.
# YouTube API
Source: https://www.ayrshare.com/docs/apis/post/social-networks/youtube
Options for posting using the YouTube API
YouTube posting requires your YouTube account to have at least one Channel and be an owner on the Channel.
To create a YouTube Channel, click on your profile in the YouTube Dashboard and choose "Create a Channel".
You may also use this direct link to create a YouTube Channel: [http://m.youtube.com/create\_channel](http://m.youtube.com/create_channel)
If you're having issues viewing YouTube channels please see the [YouTube channel troubleshooting guide](/docs/help-center/technical-support/youtube_channels_not_showing).
YouTube upload failures may return error codes **453** (timeout) or **454**
(service unavailable) with `retryAvailable: true`. Your integration can branch
on this flag to retry transient failures automatically with backoff. See the
[error codes reference](/docs/errors/errors-ayrshare) for the full list.
Please see [YouTube Media Guidelines](/docs/media-guidelines/youtube) and [YouTube Authorization](/docs/dashboard/connect-social-accounts/youtube) for more information.
## Posting to YouTube
### Posting Overview
Posting using the YouTube API requires the `youTubeOptions` object with at a `title` parameter - max 100 characters.
The `title` is the only required field and can use autogenerated with the [transcribe endpoint](/docs/apis/generate/transcribe-video).
For example, to post a YouTube video with default settings:
```json YouTube Post theme={"system"}
{
// Required: Video description
"post": "My Best YouTube Description", // empty string is allowed
// Required: Platform to post to
"platforms": ["youtube"],
// Required: URL of video (only 1 allowed)
"mediaUrls": ["https://img.ayrshare.com/012/vid.mp4"],
"youTubeOptions": {
// Required: Video title (max 100 characters)
"title": "Your Best Title"
}
}
```
YouTube videos are `private` by default, but the visibility can be set to `public` or `unlisted`.
Please see the optional fields below for more details.
### YouTube Post Optional Fields
There are several other optional fields listed below, including the video `visibility`, `tags`, and `publishAt` date. Please see the comments for requirements and descriptions.
```json YouTube Post Optional Fields theme={"system"}
{
// Required fields
"post": "My Best YouTube Description", // Video description, up to 5,000 characters
"platforms": ["youtube"], // Platform to post to
"mediaUrls": ["https://img.ayrshare.com/012/vid.mp4"], // URL of video (1 allowed)
"youTubeOptions": {
// Required fields
"title": "Your Best Title", // Video Title (max 100 characters)
/** Optional Fields **/
// Visibility: "public", "unlisted", or "private" (default: "private")
"visibility": "private",
// Thumbnail settings - JPEG/PNG URL under 2MB, must end in png/jpg/jpeg
"thumbNail": "https://img.ayrshare.com/012/gb.jpg",
// Video organization
"playListId": "PLrav6EfwgDX5", // Playlist ID to add the video
"tags": ["dancing", "dogs"], // Tag array (400 chars total, 2+ chars each)
// Video settings
"madeForKids": false, // Self-declared kids content (default: false)
"license": "youtube", // "youtube" (default) or "creativeCommon"
"embeddable": true, // default: true
"publicStatsViewable": true, // default: true
"shorts": true, // Post as YouTube Short (max 3 minutes, adds #shorts)
"notifySubscribers": true, // Send notification to subscribers (default: true)
"categoryId": 24, // Video category (24 = Entertainment)
"containsSyntheticMedia": true, // Disclose that a video contains realistic Altered or Synthetic (A/S) content
// YouTube controlled publishing - UTC publish time. See below for details.
"publishAt": "2022-10-08T21:18:36Z",
}
}
```
The `title` must be 100 characters or less. The `post` must be 5,000 characters or less. The `post` and `title` may contain any characters except \< and >.
The Playlist Id can be found by opening the playlist in a browser and copying the value after `list=`. The authenticated user and channel must be the owner of the playlist to add videos.
If your video doesn't end in a known video extension such as mp4, please use the `isVideo` parameter. See the [/post endpoint](/docs/apis/post/post) for details.
The `publishAt` field will allow YouTube to control the publishing time.
The video will be to private until the publish time when it will be made public.
If the publish time is in the past, the video will be made public immediately.
Do not use the post `scheduleDate` field when using the `publishAt` field.
The `containsSyntheticMedia` field is used to disclose that a video contains realistic Altered or Synthetic (A/S) content: Make a real person appear to say or do something they didn't actually say or do, alter footage of a real event or place, generate a realistic-looking scene that did not actually occur.
`license` - Sets the video license type. Accepted values: `"youtube"` (Standard YouTube License, default) or `"creativeCommon"` (Creative Commons - Attribution).
`embeddable` - Boolean (or the strings `"true"` / `"false"`). Controls whether the video can be embedded on third-party websites. Default: `true`.
`publicStatsViewable` - Boolean (or the strings `"true"` / `"false"`). Controls whether the **extended statistics panel** on the video's watch page is publicly viewable. The basic view count and like count remain publicly visible regardless of this setting. Default: `true`. See [`status.publicStatsViewable` in the YouTube Data API reference](https://developers.google.com/youtube/v3/docs/videos#status.publicStatsViewable) for details.
See [YouTube Media Guidelines](/docs/media-guidelines/youtube) for more information.
**Monetization & Content Controls**
The fields `madeForKids`, `license`, `embeddable`, and `publicStatsViewable` are settable via the Ayrshare API at upload time. However, direct monetization toggles (enabling/disabling ads), ad type selection (pre-roll, mid-roll, post-roll), revenue sharing, and Content ID require YouTube CMS credentials — available only to MCNs and enterprise content owners — and are **not** available through standard YouTube OAuth or the Ayrshare API.
## YouTube Shorts
A YouTube Short is a short-form vertical video that can be up to three minutes long.
These are similar to TikTok videos and Instagram or Facebook Reels.
### Posting YouTube Shorts
You can post a YouTube Shorts video of up to 3 minutes by adding the `shorts` parameter to the `youTubeOptions` object.
```json YouTube Shorts Post theme={"system"}
{
"youTubeOptions": {
"shorts": true
}
}
```
The #shorts hashtag will be added to the YouTube description.
### Important Information on YouTube Shorts
Sending a video as a Short is an indication to YouTube that you would like the video to appear
as a Short, but does not guarantee it will appear as a Short. The video must meet the [Short
video](/docs/media-guidelines/youtube#shorts) requirements, such as being 3 minutes or less and
vertical aspect ratio of 9:16 to be considered a Short by YouTube.
YouTube Shorts do not support thumbnails.
Additional information on using the [API to post YouTube
Shorts](https://www.ayrshare.com/blog/post-youtube-shorts-with-an-api/).
## YouTube Thumbnails
Custom thumbnails require a **verified YouTube channel**. The most common reason a thumbnail fails to apply (while the video still posts) is an unverified channel — verify at [https://www.youtube.com/verify](https://www.youtube.com/verify) (phone verification). Your `thumbNail` must also be a **PNG or JPG/JPEG**, **2MB or less**, and served from a **reachable URL**; Ayrshare validates these before publishing where possible. When a video posts but the thumbnail fails, the YouTube result keeps `status: "success"` and adds a `warnings` array (`feature: "thumbnail"`, `code: 307`) describing the failure. See [YouTube Thumbnail Not Applied (Unverified Channel)](/docs/help-center/technical-support/youtube_thumbnail_unverified_channel) for the full fix.
### Adding YouTube Thumbnails
YouTube Thumbnails and other features, such as uploading 15 minute videos, require verification of your phone number.
A `thumbNail` is a URL of a JPEG or PNG and less than 2MB in size. The file extension must end in png, jpg, or jpeg.
```json YouTube Thumbnail theme={"system"}
{
"youTubeOptions": {
"thumbNail": "https://img.ayrshare.com/012/gb.jpg"
}
}
```
YouTube Shorts do not currently support thumbnails.
### Enable Thumbnails in YouTube Studio
You must be granted YouTube permissions to post thumbnails. In [YouTube Studio](https://studio.youtube.com/) go to *Settings->Channel*. Select "*Feature Eligibility*" and click "*Features that require phone verification*". Enter your phone number to enable.
YouTube may take up to 24 hours to enable thumbnails after you verify your phone number. Please note, YouTube determines eligibility for adding thumbnails. "Enabled" phone verification does not guarantee YouTube will allow thumbnail uploads.
If you have been verified for 24 hours and still have issues check that:
1. You are able to manually upload thumbnails in YouTube Studio.
2. If you're working with a Brand Content Owner Account (often used for business or organization channels), make sure you have the necessary permissions. We recommend "Owner" rights.
3. If you are still having issues, please see this video on [solving the Thumbnail issue](https://www.youtube.com/watch?v=1bFmX2uQk0Y).
## Video: Posting to YouTube via the API
## Upload Limits
YouTube limits how many videos a channel can upload in a 24-hour period via the YouTube API.
Depending on a creator's location, a channel might be able to increase their daily limit by
getting access to advanced features. To learn more visit this
[article](https://notifications.google.com/g/p/ACnX6LbjUElgT-OfRLVjenkpdldv6pIJ5JYGZyPGTdJwRYmo3fXFkfXJsPGnswgns0BjJ6Bjxn2bqpqfBt6gBdkLoqESKA7mqLNllzcR2qnYUJn5KlJN5jPqCWl6DGr58cZEt94mMvxXATN6_PaBR1RYEpNMTYWN).
Limits may vary by country/region or channel history. Copyright strikes may impact channel
history eligibility and [Community Guidelines
strikes](https://support.google.com/youtube/answer/2802032) will affect how much a channel can
upload.
If you receive and upload limit error please wait and try again in 24 hours.
## Description Links
You must activate **Advanced Features** in YouTube Studio to have clickable links in the YouTube video description.
Go to **YouTube Studio -> Settings -> Channel -> Feature Eligibility -> Advanced Features -> Access Features** to activate the advanced features.
## Playlists
You can add videos to a YouTube playlist by including the `playListId` in the `youTubeOptions` object.
Be sure that the authenticated user and channel are the owner of the playlist.
```json YouTube Playlist theme={"system"}
{
"youTubeOptions": {
"playListId": "PLrav6EfwgDX5"
}
}
```
## Subtitles / Captions for Videos
You can add YouTube subtitles, also known as YouTube captions, to videos by including an [SRT file](https://en.wikipedia.org/wiki/SubRip) or a YouTube [SBV file](https://support.google.com/youtube/answer/2734698). Use the `subTitleUrl` field in the `youTubeOptions` object to specify the URL to your SRT or SBV file.
```json YouTube Subtitles theme={"system"}
{
"youTubeOptions": {
"title": "My new post from Ayrshare to Youtube",
"subTitleUrl": "https://img.ayrshare.com/012/captions.srt",
"subTitleLanguage": "en",
"subTitleName": "English"
}
}
```
`subTitleUrl`: A valid SRT or SBV file. The URL must start with `https://` and end in `.srt` or
`.sbv` and be a valid SRT or SBV file. The file must be under 100 MB.
`subTitleLanguage`: Optional: The language of the subtitles. Much be a valid [language
code](/docs/iso-codes/language). Default: "en".
`subTitleName`: Optional: The name of the caption track. The name is intended to be visible to
the user as an option during playback. The maximum name length supported is 150 characters.
Default: "English".
**What are SRT and SBV files?**
SRT (SubRip Subtitle) and SBV (YouTube SubViewer) are subtitle file formats used for displaying
timed text in videos. The main difference is that SRT uses timestamps in HH:MM:SS,MS format with
arrow separators, while SBV uses HH:MM:SS.MS format with commas.
```text theme={"system"}
## SRT Format Example
1
00:00:01,000 --> 00:00:04,000
Welcome to our tutorial on subtitle formats.
2
00:00:04,500 --> 00:00:08,000
Today we'll learn about SRT and SBV files.
## SBV Format Example
0:00:01.000,0:00:04.000
Welcome to our tutorial on subtitle formats.
0:00:04.500,0:00:08.000
Today we'll learn about SRT and SBV files.
```
## Tags
You can add YouTube tags to your videos by including the `tags` array in the `youTubeOptions` object.
Tags must be at least 2 characters in length each and the total length of all tags must be 500 characters or less.
```json YouTube Tags theme={"system"}
{
"youTubeOptions": {
"tags": ["dancing", "dogs"]
}
}
```
## YouTube Mentions
While you can add a `@handle` to a YouTube post, YouTube does not support resolving mentions in the post text.
The `@handle` will remain as plain text.
## Character Limits
Please see [YouTube Character Limits](/docs/help-center/technical-support/character_limits#youtube-character-limits) for more information.
## Additional Endpoints
# Create a User Profile
Source: https://www.ayrshare.com/docs/apis/profiles/create-profile
POST /profiles
Create a new User Profile under your Primary Profile.
Create a new profile under your Primary Profile. Upon successful creation of the User Profile, the API response will include the Profile Key associated with the newly created profile. Securely store the Profile Key in your system, as it will be required to make API calls on behalf of your user.
Please note that for security reasons, the Profile Keys are only returned in two specific cases:
1. User Profile Creation: When a new User Profile is created.
2. In the Ayrshare Dashboard: You can find the Profile Key for each profile within the Ayrshare Dashboard. Switch to the User Profile and then navigate to the Profile Key page.
We recommend you securely store the Profile Key in your system.
## Manage Social Networks
Use the disableSocial field to manage (add/remove) social networks from display. Please see [Manage Social Accounts](/docs/apis/profiles/overview#enable-or-disable-social-networks) for more information.
## Manage Active User Profiles
Please see here for some recommendations on [managing active User Profiles](/docs/multiple-users/manage-user-profiles#managing-active-user-profiles).
## Important Security Considerations
Avoid sharing Profile Keys publicly or exposing them in client-side code or public repositories.
Profile Keys are sensitive credentials used to authenticate and authorize access to User Profiles.
It is crucial to store Profile Keys securely in your system with appropriate access controls to maintain the integrity and confidentiality of your users' data.
For security reasons, the Profile Key can't be retrieved again using the API. However, you can retrieve the Profile Key from the [dashboard](/docs/multiple-users/manage-user-profiles#get-the-profile-key).
The `refId` should also be stored to associate a profile to an endpoint return.
## Header Parameters
## Body Parameters
Title of the new profile. Must be unique. This title will be displayed on the social account linking page.
Set to true to activate messaging for this user profile. Messaging must first be enabled for your Ayrshare account.
Hide the top header on the social accounts linkage page.
Hide the company logo on the social accounts linkage page for this user profile only. The account-wide logo on other profiles is unaffected. Useful for white-labeling individual partner profiles while keeping branding on the rest.
Change the header on the social accounts linkage page. If not set, then displays: "Social Accounts for "title" where "title" is the profile title.
Array of social networks that are disabled for this user's profile. The primary profile's list of disabled social networks takes precedence.
Available networks: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, and `youtube`.
See [enable or disable social networks](/docs/apis/profiles/overview#enable-or-disable-social-networks) for more information.
Create a new user profile as a team member by setting `team: true`. The `email` field will be used to send an invite email. See [inviting a team member](/docs/multiple-users/manage-user-profiles#invite-a-team-member) for details on the requirements.
A valid email address where the team member invite will be sent. Required if `team: true`
Change the sub header on the social accounts linkage page. Currently displays "Click an icon to link a social network". Set to an empty string to remove.
See how to change the [help link](/docs/multiple-users/manage-user-profiles#help-links-visible).
Tag user profiles using an array of strings. These tags serve as an internal organizational tool to categorize and manage your user profiles effectively.
Create the profile as a [Demo User Profile](/docs/apis/profiles/overview#demo-user-profiles) — a 30-day evaluation profile that automatically converts to a standard User Profile after 30 days.
Demo User Profiles are available on the Enterprise plan and must be enabled for your account — [contact us](mailto:support@ayrshare.com) if you'd like to learn more. Returns HTTP 403 with error code 480 if not enabled.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"title": "ACME Profile"}' \
-X POST https://api.ayrshare.com/api/profiles
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/profiles", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
title: "ACME Profile", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'title': 'ACME Profile'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/profiles',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'POST',
'https://api.ayrshare.com/api/profiles',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'title' => ['ACME Profile'],
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"log"
"net/http"
)
func main() {
message := map[string]interface{}{
"title": "ACME Profile"
}
bytesRepresentation, err := json.Marshal(message)
if err != nil {
log.Fatalln(err)
}
req, _ := http.NewRequest("POST", "https://api.ayrshare.com/api/profiles",
bytes.NewBuffer(bytesRepresentation))
req.Header.Add("Content-Type", "application/json; charset=UTF-8")
req.Header.Add("Authorization", "Bearer API_KEY")
res, err := http.DefaultClient.Do(req)
if err != nil {
log.Fatal("Error:", err)
}
res.Body.Close()
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CreateProfilePOSTRequest_csharp
{
class CreateProfile
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/profiles";
string json = "{\"title\": \"ACME Profile\"}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"title": "Digg It",
"refId": "140b8709bd6ade099b242d895e268fb886130c53",
"profileKey": "7TVRLEZ-24A43C0-NJW0Z82-F11984N",
"messagingActive": true // true if messaging for this user profile is active
}
```
```json 400: Profile Title Already Exists theme={"system"}
{
"action": "create",
"status": "error",
"code": 146,
"message": "Profile title already exists."
}
```
```json 403: Demo Profiles Not Enabled theme={"system"}
{
"action": "create profiles",
"status": "error",
"code": 480,
"message": "Demo profiles are not enabled for this account. Demo profiles require an Enterprise plan and must be enabled by Ayrshare."
}
```
# Delete a User Profile
Source: https://www.ayrshare.com/docs/apis/profiles/delete-profile
DELETE /profiles
Delete a user profile you are the owner of.
Delete a user profile you are the owner of. The Profile Key in the header parameter is the User Profile to be deleted.
Deleting a user profile permanently removes the profile and all associated posts—this action is
irreversible and cannot be undone. You can delete up to 8 user profiles per second, so please
stagger your API calls when performing bulk deletions to stay within rate limits.
## Header Parameters
## Body Parameters
Title of the User Profile to delete. Must be present if `profileKey` is not passed. `title` is
case-sensitive and must match the User Profile title.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-H 'Profile-Key: PROFILE_KEY' \
-X DELETE https://api.ayrshare.com/api/profiles
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const profileKey = "PROFILE_KEY";
fetch("https://api.ayrshare.com/api/profiles", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
"Profile-Key": profileKey
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY', 'Profile-Key': 'PROFILE_KEY'}
r = requests.delete('https://api.ayrshare.com/api/profiles',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
'Profile-Key: ' . $profileKey
],
]);
$response = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Error:' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
using var client = new HttpClient();
var requestUri = "https://api.ayrshare.com/api/profiles";
var bearerToken = "Bearer API_KEY";
var profileKey = "PROFILE_KEY";
using var request = new HttpRequestMessage(HttpMethod.Delete, requestUri);
request.Headers.Add("Authorization", bearerToken);
request.Headers.Add("Profile-Key", profileKey);
try
{
using var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
```
```javascript 200: Success theme={"system"}
{
"status": "success",
"refId": "823nd82nd92jsnn2932"
}
```
```javascript 500: Error Deleting theme={"system"}
{
"action": "delete",
"status": "error",
"code": 147,
"message": "Error deleting profile."
}
```
```javascript 403: Profile Key Not Found theme={"system"}
{
"action": "post",
"status": "error",
"code": 144,
"message": "Some profiles not found. Please verify the Profile Keys."
}
```
# Generate a JWT
Source: https://www.ayrshare.com/docs/apis/profiles/generate-jwt
POST /profiles/generateJWT
Generate a JSON Web Token (JWT) for use with single sign on.
Generate a JSON Web Token (JWT) for use with single sign on.
See the [Generate JWT Overview](/docs/apis/profiles/generate-jwt-overview) for more details.
The JWT URL is valid for **5 minutes**. After 5 minutes you must generate a new JWT URL.
See the Max Pack `expiresIn` for [additional options](/docs/apis/profiles/generate-jwt-overview#jwt-expires-in).
## Header Parameters
Your X API Key (Consumer Key) from the X Developer Portal. Alternative to the `twitterApiKey` body parameter. When provided, the generated JWT URL will use your X Developer App for OAuth linking.
Your X API Secret (Consumer Secret) from the X Developer Portal. Alternative to the `twitterApiSecret` body parameter. Required when `X-Twitter-OAuth1-Api-Key` is provided.
**Recommended:** Pass your X credentials via headers (`X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret`) for consistency with all other Ayrshare API endpoints. The `twitterApiKey` and `twitterApiSecret` body parameters are still supported for backward compatibility.
## Body Parameters
Domain of app. Please use the exact domain given during onboarding.
Private Key used for encryption.
User Profile Key. The API Key cannot be used in this field.
Automatically logout the current session. Recommend not to use in production since it affects the performance.
See [Automatic Logout of a Profile Session](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session) for more information.
Specify a URL to redirect to when the "Done" button or logo image is clicked. The URL will be automatically shortened in the returned JWT url. [Redirect the origin ](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url)opener window by adding the query parameter `origin=true` to the redirect URL.
Specify the social networks to display in the linking page. This will override the social networks configured in the [Social Networks](/docs/multiple-users/manage-user-profiles#set-social-networks-access) page.
```json Only display Facebook, X/Twitter, LinkedIn, and TikTok theme={"system"}
{
"allowedSocial": ["facebook", "twitter", "linkedin", "tiktok"]
}
```
Override which Instagram linking flow is used when a user clicks the Instagram button on the social linking page for this URL. Valid values:
* `instagram`: Direct Instagram Login, no Facebook Page required.
* `facebook`: Link Instagram via a connected Facebook Page.
```json Force direct Instagram Login for this linking session theme={"system"}
{
"instagramLinkMethod": "instagram"
}
```
When omitted, the linking page uses your account-wide [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) setting.
See [Instagram Link Method](/docs/apis/profiles/generate-jwt-overview#instagram-link-method) for more information.
Verify that the generated token is valid. Recommend to only use in non-production environment.
See [Opening and Closing the Social Linking URL](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url) for more information.
If the private key is base64 encoded, set to `true`.
Encode the private.key file in base64 and pass the single line String in the `privateKey` field.
E.g in Linux: `cat private.key | base64`
Set the longevity of the token in minutes. Range: 1 minute to 2880 minutes.
See [JWT Expires In](/docs/apis/profiles/generate-jwt-overview#jwt-expires-in) for more information.
Send a Connect Accounts email with a link for users to directly access their social linkage page.
See [Connect Accounts Email](/docs/apis/profiles/generate-jwt-overview#connect-accounts-email) for more information.
When you include your X API credentials, the generated JWT URL will initiate OAuth linking using your own X Developer App. Your end-users will see your app name on the X consent screen.
**Required:** Before using this feature, you must add these callback URLs to your X Developer App settings (under Authentication settings > Callback URI / Redirect URL):
* `https://profile.ayrshare.com/social-accounts`
* `https://app.ayrshare.com/social-accounts`
Without these, the OAuth flow will fail with a `403 Callback URL not approved` error.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-H "X-Twitter-OAuth1-Api-Key: YOUR_CONSUMER_KEY" \
-H "X-Twitter-OAuth1-Api-Secret: YOUR_CONSUMER_SECRET" \
-d '{"domain": "ACME", "privateKey": "-----BEGIN RSA PRIVATE KEY...", "profileKey": "PROFILE_KEY"}' \
-X POST https://api.ayrshare.com/api/profiles/generateJWT
```
```javascript JavaScript theme={"system"}
const fs = require('fs');
const API_KEY = "API_KEY";
const PROFILE_KEY = "PROFILE_KEY";
// Read in local private.key files - also can read from a DB
const privateKey = fs.readFileSync('private.key', 'utf8');
fetch("https://api.ayrshare.com/api/profiles/generateJWT", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
"X-Twitter-OAuth1-Api-Key": "YOUR_CONSUMER_KEY",
"X-Twitter-OAuth1-Api-Secret": "YOUR_CONSUMER_SECRET"
},
body: JSON.stringify({
domain: "ACME", // required
privateKey, // required
profileKey: PROFILE_KEY, // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
# Read in local private.key files - also can read from a DB
with open('.private.key') as f:
profileKey = f.read()
payload = {'domain': 'ACME',
'privateKey': profileKey,
'profileKey': 'PROFILE_KEY' }
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY',
'X-Twitter-OAuth1-Api-Key': 'YOUR_CONSUMER_KEY',
'X-Twitter-OAuth1-Api-Secret': 'YOUR_CONSUMER_SECRET'}
r = requests.post('https://api.ayrshare.com/api/profiles/generateJWT',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'POST',
'https://api.ayrshare.com/api/post',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'json' => [
'domain' => 'ACME',
'privateKey' => '-----BEGIN RSA PRIVATE KEY...', // required
'profileKey' => 'PROFILE_KEY', // requires
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using Newtonsoft.Json;
namespace GenerateJWTRequest_csharp
{
class GenerateJWT
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/profiles/generateJWT";
try
{
string privateKey = await File.ReadAllTextAsync("./private.key");
var sendData = new
{
domain = "domain",
privateKey = privateKey,
profileKey = "PROFILE_KEY"
};
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
string jsonData = JsonConvert.SerializeObject(sendData);
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
}
catch (FileNotFoundException e)
{
Console.WriteLine($"Private key file not found: {e.Message}");
}
catch (HttpRequestException e)
{
Console.WriteLine($"HTTP request error: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"Unexpected error: {e.Message}");
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"title": "User Profile Title",
"token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlLZXkiOiJBSjNQR1cxLThIWk04UjQtR0NXVFZKVy1ZRTE1M1BFIiwicHJvZmlsZUtleSI6IjhKNDY4UFktSjM5TVlXRC1IWEpLVlIyLVBRMjBQUlMiLCJpYXQiOjE2MTQyMjYwNDksImV4cCI6MTYxNDIyNjM0OSwiYXVkIjoiaHR0cHM6Ly9hcHAuYXlyc2hhcmUuY29tIiwiaXNzIjoiYm9uZGJyYW5kbG95YWx0eS5jb20iLCJzdWIiOiJzdXBwb3J0QGF5cnNoYXJlLmNvbSJ9.Se387OyhJIdaDkFkvAe0Dwo3pQrHBwdg2bbjqKYn7BZuVDxPboJmTsd7rra8N-Z6b9_fJOtwlRFGBLW1CvgLGU4RSisTVqjqhAkb3KNhpA7cZ673IJbRX-ST7tYadKKzmd9GNrZW9rhxHOlgMJ9uOboc4dcaDbNmzb_yCrfLY-E"
"url": "https://profile.ayrshare.com?domain=PROVIDED_DOMAIN&jwt=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJhcGlLZXkiOiJBSjNQR1cxLThIWk04UjQtR0NXVFZKVy1ZRTE1M1BFIiwicHJvZmlsZUtleSI6IjhKNDY4UFktSjM5TVlXRC1IWEpLVlIyLVBRMjBQUlMiLCJpYXQiOjE2MTQyMjYwNDksImV4cCI6MTYxNDIyNjM0OSwiYXVkIjoiaHR0cHM6Ly9hcHAuYXlyc2hhcmUuY29tIiwiaXNzIjoiYm9uZGJyYW5kbG95YWx0eS5jb20iLCJzdWIiOiJzdXBwb3J0QGF5cnNoYXJlLmNvbSJ9.Se387OyhJIdaDkFkvAe0Dwo3pQrHBwdg2bbjqKYn7BZuVDxPboJmTsd7rra8N-Z6b9_fJOtwlRFGBLW1CvgLGU4RSisTVqjqhAkb3KNhpA7cZ673IJbRX-ST7tYadKKzmd9GNrZW9rhxHOlgMJ9uOboc4dcaDbNmzb_yCrfLY-E",
"emailSent": true,
"expiresIn": "30m"
}
```
```json 400: Private Key Formatted Incorrectly theme={"system"}
{
"action": "JWT",
"status": "error",
"code": 189,
"message": "Error generating JWT. Check the sent parameters, such as the privateKey has no extra tabs, spaces, or newlines. Error: error:0909006C:PEM routines:get_name:no start line"
}
```
```json 400: Partial Twitter API Keys theme={"system"}
{
"action": "JWT",
"status": "error",
"code": 188,
"message": "Both twitterApiKey and twitterApiSecret are required. You provided only one."
}
```
```json 400: Duplicate X/Twitter Credentials theme={"system"}
{
"action": "JWT",
"status": "error",
"code": 434,
"message": "X/Twitter API credentials were provided in both the request headers and the request body. Please use the headers only. See https://www.ayrshare.com/docs/apis/profiles/generate-jwt"
}
```
# Generate JWT Overview
Source: https://www.ayrshare.com/docs/apis/profiles/generate-jwt-overview
Generate a social network linking URL for a user profile.
The [generateJWT endpoint](/docs/apis/profiles/generate-jwt) generates a social network linking URL for a single User Profile.
See the [Business Plan and Launch Plan API integration](/docs/multiple-users/api-integration-business) for more details.
## Switching Profiles
To switch between different profile sessions (for example, when testing with multiple profiles), you'll need to log out the current profile first. See [Automatic Logout of a Profile Session](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session) for instructions on how to properly handle profile switching.
## Private Key and Profile Key
### Where to Get the Private Key
The Private Key file (private.key) and a sample Postman JSON file is included with your [Integration Package](/docs/multiple-users/api-integration-business#integration-package) received during onboarding.
The Integration Package may also be retrieved in the Ayrshare developer dashboard in the API Page -> Integration Package.
### Using the Private Key
We recommend reading the Private Key private.key from a file and sending it as a string in the `privateKey` field, which allows you to preserve all characters including newlines.
The Private Key must be precise, meaning preserving all characters including newlines.
If you paste the key into your code, you might need to manually replace newlines with a `\n` character or URL encode the string.
Pasting the key directly into code often causes issues.
## Generate a JSON Web Token
1 minute video explaining how to generate a JSON Web Token (JWT):
The JWT URL is valid for **5 minutes**. After 5 minutes you must generate a new JWT URL.
See the [Max Pack `expiresIn`](/docs/apis/profiles/generate-jwt-overview#jwt-expires-in) for additional options.
## Opening the JWT URL
Open the JWT URL in a new browser tab, browser window, or View Controller on iOS.
You may control the [closing or redirecting](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url) of the new window or tab.
The social networks do not allow opening the URL in an iFrame or obfuscating the approved partner
origin domain profile.ayrshare.com.
## Verify the JWT URL
The `generateJWT` endpoint does not validate the returned JWT URL by default.
For example, if a corrupt Private Key is passed into `generateJWT` a URL will still be returned and the URL result in a 401 error.
You can verify the returned JWT URL by including `verify: true` in the `generateJWT` body parameters. If the JWT URL cannot be validated an error will be returned. For example, if the Private Key had a character removed the following would be returned:
```json JWT Error theme={"system"}
{
"action": "JWT",
"status": "error",
"code": 189,
"message": "Error generating JWT. Check the sent parameters, such as the privateKey has no extra tabs, spaces, or newlines. Also the entire private.key file including -----BEGIN RSA PRIVATE KEY----- and -----END RSA PRIVATE KEY-----. Error: secretOrPrivateKey must be an asymmetric key when using RS256"
}
```
We recommend using `verify: true` only in a non-production environment since the validation takes additional processing time.
## Testing in Postman
It is **recommended** to first test the JWT URL creation in [Postman](/docs/testing/postman).
Included in the Integration Package, found in the Primary Profile API Key page of the dashboard, is a sample Postman config JSON file that included everything you need to verify your the JWT URL creation.
Just import the config file into Postman, fill in your Profile Key (found in the Ayrshare developer dashboard by switching to the profile you want to test) in the `profileKey` *body* field, and click the blue *Send* button.
All other required fields are already filled in.
You can also [generate the code from Postman](/docs/testing/postman#auto-generate-api-code-with-postman), or read the key file from a directory or database.
## Instagram Link Method
Instagram accounts can be linked in [two ways](/docs/dashboard/connect-social-accounts/instagram): directly with **Instagram Login**, or via a **connected Facebook Page**.
Which flow starts when a user clicks the Instagram button on the social linking page is normally controlled by the account-wide [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) setting in the dashboard.
The `instagramLinkMethod` body parameter of the [generateJWT endpoint](/docs/apis/profiles/generate-jwt) lets you override that setting for a single linking URL:
| Value | Instagram Linking Flow |
| ----------- | -------------------------------------------------- |
| `instagram` | Direct Instagram Login. No Facebook Page required. |
| `facebook` | Link via a connected Facebook Page. |
For example, if your account default is Facebook Page linking, the following forces direct Instagram Login for just this linking session:
```json Instagram Link Method theme={"system"}
{
"instagramLinkMethod": "instagram"
}
```
The generated JWT URL will include the override, and clicking the Instagram button on the linking page will start the requested flow for the duration of that session — including across the Instagram/Facebook authorization redirect.
A few things to know:
* The override only applies to the linking page opened from the returned URL. It does not change your account-wide Instagram Login setting or affect other linking sessions.
* If `instagramLinkMethod` is omitted, the linking page uses your account-wide setting, exactly as before.
* If an invalid value is sent, a `400` error is returned listing the valid values (`instagram`, `facebook`).
* Review the [feature differences](/docs/multiple-users/manage-user-profiles#direct-instagram-login-vs-facebook-page-authentication) between the two flows before choosing an override — some Instagram features, such as hashtag search and collaborations, are only available with Facebook Page authentication.
## JWT Expires In
If you want a longer JWT timeout than the default 5 minutes, include the `expiresIn` field.
For example, send the following JSON to set the JWT URL valid for 30 minutes:
```json JWT Expires In theme={"system"}
{
"expiresIn": 30
}
```
This allows you to [email the link](/docs/apis/profiles/generate-jwt-overview#connect-accounts-email) to your users instead of them having to go to your app or platform.
A common use case is when your user needs to reconnect a social account, you can email them the JWT link to directly re-link the social account instead of having to navigate to your platform.
Be sure to review with your security team how long your business wants to keep the JWT alive.
Longer expire times create additional risk of an unauthorized party accessing the link.
## Integrations
### Bubble.io JWT
If you are a Bubble user, please see *Generate JWT Token* in the Bubble.io section for instructions:
### Mobile JWT
The following Swift, Flutter, and React Native [mobile code examples](/docs/apis/profiles/generate-jwt-overview#mobile-code-examples) show how to launch the social linking page on an iOS device.
Replace the `jwtURL` String variable with the return from the [/generateJWT endpoint](/docs/apis/profiles/generate-jwt).
#### Swift (iOS)
In Swift, use a `UIViewController` and `SFSafariViewControllerDelegate`.
We don't recommend using a `WebView` since some social networks such as Facebook and Google block authentication.
#### Flutter (Dart)
In Flutter (Dart), there is no direct equivalent to a `UIViewController` or the `SFSafariViewController`.
However, you can achieve a similar functionality by using the `url_launcher` package to open web URLs.
#### React Native
React Native also doesn't have a direct equivalent to `SFSafariViewController`, but you can achieve a similar result with the `WebBrowser` API provided by `expo-web-browser`, which opens a URL in a modal browser window that shares cookies with the system browser. Otherwise, you can use the built-in React Native `Linking` function to open Safari: `await Linking.canOpenURL(jwtURL);`
#### Mobile Code Examples
```swift Swift theme={"system"}
import UIKit
import SafariServices
class ViewController: UIViewController, SFSafariViewControllerDelegate {
var jwtURL = "https://profile.ayrshare.com?domain=acme&jwt=eyJhbGciOiJ"
override func viewDidLoad() {
super.viewDidLoad()
setupButton()
}
func setupButton() {
let button = UIButton(type: .system)
button.frame = CGRect(x: (view.bounds.width - 200) / 2, y: (view.bounds.height - 50) / 2, width: 200, height: 50)
button.setTitle("Open URL", for: .normal)
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
view.addSubview(button)
}
@objc func buttonTapped() {
openURLInInAppBrowser()
}
func openURLInInAppBrowser() {
if let url = URL(string: jwtURL) {
let safariVC = SFSafariViewController(url: url)
safariVC.delegate = self
present(safariVC, animated: true, completion: nil)
}
}
// Optional: If you want to handle when the in-app browser is closed
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
```
```dart Flutter theme={"system"}
/** yaml dependencies
dependencies:
flutter:
sdk: flutter
url_launcher: ^6.2.1
*/
import 'package:flutter/material.dart';
import 'package:url_launcher/url_launcher.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'URL Launcher Example',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatelessWidget {
final String jwtURL = "https://profile.ayrshare.com?domain=acme&jwt=eyJhbGciOiJ";
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('URL Launcher Example'),
),
body: Center(
child: ElevatedButton(
onPressed: () {
openURLInBrowser(context);
},
child: Text('Open URL'),
),
),
);
}
void openURLInBrowser(BuildContext context) async {
if (await canLaunch(jwtURL)) {
await launch(jwtURL);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Could not launch $jwtURL'),
),
);
}
}
}
```
```jsx React Native theme={"system"}
/**
• Using the API provided by expo-web-browser,
• which opens a URL in a modal browser window that shares cookies
• with the system browser.
• Learn more about expo: https://reactnative.dev/docs/environment-setup?guide=quickstart
• and running the following command:
• expo install expo-web-browser
*/
import React from 'react';
import { StyleSheet, Button, View } from 'react-native';
import * as WebBrowser from 'expo-web-browser';
export default function App() {
const jwtURL = 'https://profile.ayrshare.com?domain=acme&jwt=eyJhbGciOiJ';
const openURLInBrowser = async () => {
try {
await WebBrowser.openBrowserAsync(jwtURL);
// Optional: WebBrowser.openBrowserAsync returns a promise that resolves with an object containing
// 'type' that can be 'cancelled' or 'dismissed'. You can use this to handle when the browser is closed.
} catch (error) {
console.error(error);
}
};
return (
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
```
## Connect Accounts Email
In conjunction with the longer expire time option, you can also automatically have Ayrshare email your users a link to the social linkage page.
### Connect Accounts JSON
For example the following JSON will send an email to `john@user.com` with the company name ACME, contact email `support@mycompany.com`, and links to the terms and privacy policy:
```json Example Contact Email Request theme={"system"}
/**
All fields are in the email object required.
Missing fields will cause the email to fail.
*/
{
"email": {
"to": "john@user.com",
"contactEmail": "support@mycompany.com",
"company": "ACME",
"termsUrl": "https://www.ayrshare.com/terms",
"privacyUrl": "https://www.ayrshare.com/privacy",
"expiresIn": 60
}
}
```
The response will include the following if the email and expire time was set:
```json Example Contact Email Response theme={"system"}
{
"emailSent": true,
"expiresIn": "30m"
}
```
### JWT Connect Accounts Email Example
Here is an example of an email with the Connect Account link that opens social linkage page:
The email will come from the address:
`Social Connect Hub `
# Get User Profiles
Source: https://www.ayrshare.com/docs/apis/profiles/get-profiles
GET /profiles
Get all the profiles associated with the primary profile.
Get all the profiles associated with the primary profile. The Primary Profile is not returned in the results.
For security, the Profile Keys are not returned via this GET call. Please see [here](/docs/apis/profiles/create-profile) for more information.
## Header Parameters
## Query Parameters
Return only the profile associated with the URL encoded title.
Return only the profile associated with the given `refId`. The refId was returned during the
profile creation or from the /user endpoint.
If `true` return only profiles that have at least one connected social account
(`activeSocialAccounts` length greater than zero). If `false` return only profiles with zero
connected social accounts (`activeSocialAccounts` length is zero).
Filter profiles to include those whose `activeSocialAccounts` contain all of the social media platforms specified in the `includesActiveSocialAccounts` list. Profiles can have additional platforms in their `activeSocialAccounts` beyond those listed in `includesActiveSocialAccounts` and still be included in the filtered results.
Values: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, `youtube`.
Filter profiles by BYOK (Bring Your Own Key) migration status. If `true`, return only profiles that have completed BYOK migration. If `false`, return only profiles that have a BYOK-eligible platform connected but have not yet migrated. Profiles without a BYOK-eligible platform are excluded when this filter is set. When omitted, all profiles are returned regardless of BYOK status. Currently applies to [X/Twitter BYOK](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys).
Return the User Profile create and delete action log history for the past 60 days and the active user count used for billing for the past 60 days. Note:
Action Log: Title and tags will not be returned for action log history prior to March 2025.
User Profile Report: The time period might not correspond to your billing period. For example, your billing period might start and end on the 10th of the month.
Please see your invoices for the billing period and other details.
You may specify a different time period by setting the actionLog to a number of days. For example,
`actionLog=10` query parameter will return the action log for the past 10 days and the reported active user count
for the past 10 days. The time period allowed is 1 day to 365 days.
Limit the number of profiles returned. The default and maximum is 5000.
If there are additional profiles to return and the `hasMore` flag is `true`, the `nextCursor` will be returned in the response.
Pass this cursor to the `cursor` query parameter to return the next set of profiles.
Return extended profile data for troubleshooting. Requires `refId` parameter (single profile lookup).
Values (comma-separated string or array): `suspension`, `socialHealth`, `linkingErrors`, `activity`, `quota`, `unlinkHistory`, `actionLog`.
`unlinkHistory` - Last unlink: platform, source (user/system), details, createdAt
`actionLog` - Profile action history (create/update/delete)
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/profiles
```
```javascript cURL (with include) theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET "https://api.ayrshare.com/api/profiles?refId=160c8700bd6ade&include=suspension,socialHealth,activity,quota"
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/profiles", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/profiles', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPGET => true,
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey
],
]);
$response = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Error:' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace ProfilesGETRequest_csharp
{
class Profiles
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/profiles";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```javascript 200: Success theme={"system"}
{
"profiles": [
{
"status": "active",
"title": "Digg It Title",
"displayTitle": "Your title",
"created": {
"_seconds": 1604094099,
"_nanoseconds": 530000000
},
"createdUTC": "2022-03-02T16:11:00.839Z",
"refId": "160c8700bd6ade099b242d845e268fb986130c53",
"activeSocialAccounts": [
"twitter",
"facebook",
"linkedin",
"instagram"
],
"isByokLinked": true
},
{
"status": "active",
"title": "Super Profile",
"created": {
"_seconds": 1604377627,
"_nanoseconds": 252000000
},
"createdUTC": "2022-03-02T16:11:00.839Z",
"refId": "170a8700bd6ade099b242d845e268fb986130c53"
},
{
"status": "suspended",
"title": "Good Fun Title",
"created": {
"_seconds": 1605107864,
"_nanoseconds": 96000000
},
"createdUTC": "2022-03-02T16:11:00.839Z",
"refId": "180s8700bd6ade099b242d845e268fb986130c53",
"activeSocialAccounts": [
"facebook",
"linkedin",
"youtube"
],
"suspended": true
}
],
"count": 100,
"lastUpdated": "2025-06-14T15:53:26.016Z",
"nextUpdate": "2025-06-14T15:58:26.016Z",
"pagination": {
"hasMore": true,
"nextCursor": "eyJjcmVhdGVkIjoiMjAyNS0wNi0xNFQwMjo1",
"limit": 100
}
}
```
```json 200: Action Log theme={"system"}
{
"profiles": {
"actionLog": [
{
"action": "create",
"refId": "2d83hd839282ehd892d2999912d1dsdgldfkepw",
"title": "Profile 1",
"created": "2025-05-29T14:10:33.709Z"
},
{
"action": "create",
"refId": "fmm02nd9c3nm9djjffdfsfshfihvp848jcsf222s",
"title": "Profile 2",
"created": "2025-05-28T20:33:32.186Z"
}
],
"userProfilesReport": [
{
"reported": "2025-03-31T08:00:22.651Z",
"userProfileCount": 135
},
{
"reported": "2025-04-01T08:00:16.632Z",
"userProfileCount": 135
}
],
"lastUpdated": "2025-06-14T15:56:02.260Z",
"nextUpdate": "2025-06-14T16:01:02.260Z"
}
```
```json 200: Include Extended Data theme={"system"}
{
"profiles": [
{
"title": "Brand Marketing",
"refId": "160c8700bd6ade099b242d845e268fb986130c53",
"status": "suspended",
"activeSocialAccounts": ["twitter", "instagram"],
"suspension": {
"isSuspended": true,
"reason": "Too many duplicate posts",
"suspendedAt": "2026-03-01T10:00:00.000Z",
"unsuspendAt": "2026-03-03T10:00:00.000Z",
"suspensionCount": 2
},
"socialHealth": {
"twitter": {
"linked": true,
"linkedAt": "2026-01-15T10:30:00.000Z",
"relinkRecommended": false,
"messagingEnabled": true,
"tokenExpiresAt": null
},
"instagram": {
"linked": true,
"linkedAt": "2026-02-01T08:00:00.000Z",
"relinkRecommended": true,
"messagingEnabled": false,
"tokenExpiresAt": "2026-04-01T08:00:00.000Z"
}
},
"activity": {
"lastApiCall": "2026-03-05T09:15:00.000Z",
"lastPost": "2026-03-04T14:30:00.000Z"
},
"quota": {
"used": 450,
"limit": 1000
}
}
],
"count": 1,
"pagination": {
"hasMore": false,
"nextCursor": null,
"limit": 5000
}
}
```
# Profiles API Overview
Source: https://www.ayrshare.com/docs/apis/profiles/overview
Create and manage multiple user profiles.
Specify a User Profile in an API call by [adding the Profile Key in the header](/docs/apis/overview#profile-key-format).
User Profiles are one of the core concepts of Ayrshare that allows you to create and manage multiple users. Each one of the users of your platform will have one or more Ayrshare User Profiles. Each User Profile can have one connection to every supported social network.
## Profile Key
Many endpoints, such as /user, /analytics, or /delete, can be called on behalf of a Profile account by [adding the "Profile-Key" parameter](/docs/apis/overview#profile-key-format) in the Header.
For example, the /delete endpoint can be called to delete a Profile account's post for the given *post* *id* for the provided *Profile Key*.
```javascript theme={"system"}
const API_KEY = "API_KEY";
const PROFILE_KEY = "PROFILE_KEY";
const id = "Post ID";
fetch("https://api.ayrshare.com/api/delete", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
"Profile-Key": PROFILE_KEY
},
body: JSON.stringify({
id: id
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
## Enable or Disable Social Networks
You can disable and enable social networks at either the global level or at the User Profile level.
[Globally manage social account access](/docs/multiple-users/manage-user-profiles#set-social-networks-access) in the dashboard.
Manage social account access for a User Profile when [creating](/docs/apis/profiles/create-profile) or [updating](/docs/apis/profiles/update-profile).
It is important to note that disabled social networks in the global setting, set via the dashboard, override User Profile settings.
For example, if you disable TikTok access in the dashboard, then no User Profile can access TikTok. On the other hand, if you turn on TikTok access in the dashboard but disable it for a specific User Profile, all User Profiles will have access to TikTok except that particular one.
## Get the Linked Social Accounts
Retrieve the social accounts a User Profile has linked with either the [/profiles endpoint](/docs/apis/profiles/get-profiles) or the [/user endpoint](/docs/apis/user/profile-details).
## Post to a User Profile
With the [/post](/docs/apis/post/post) endpoint, you can post to a User Profile by adding the Profile Key in the header. The return will be an array of posts or error results, with an overall status. If all posts successful, "success", or if any post failed, "error".
You may obtain a user's Profile Key when the profile is created with the [/create-profile](/docs/apis/profiles/create-profile) endpoint or in Ayrshare's Web Dashboard GUI by switching to the profile and going to **Profile Key** page.
## Demo User Profiles
Demo User Profiles let you offer a prospective end user a 30-day evaluation of your platform's social features before committing them to a standard User Profile.
Create one by setting `demo: true` when [creating a profile](/docs/apis/profiles/create-profile). A Demo User Profile works just like a standard User Profile — your user can link social accounts, post, and retrieve analytics using its Profile Key.
After 30 days, the Demo User Profile automatically converts to a standard User Profile. If you have a `demo` [webhook](/docs/apis/webhooks/overview) registered, you'll receive an `upgradeWarning` event two days before the conversion and an `upgrade` event when the conversion happens, so you can prompt your user (or remove the profile) beforehand.
Demo User Profiles are available on the Enterprise plan and must be enabled for your account. Please [contact us](mailto:support@ayrshare.com) if you'd like to learn more.
# Unlink a Social Network
Source: https://www.ayrshare.com/docs/apis/profiles/unlink-social-network
DELETE /profiles/social
Unlink a social network for a given user profile.
Unlink a social network for a given user profile. For example, if a user profile is linked to TikTok, unlink TikTok by making this endpoint request. A successful 200 response will be returned even if the platform is not linked. If the `Profile-Key` is not provided the Primary Profile's social account will be unlinked.
## Header Parameters
## Body Parameters
Allow platforms to unlink: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `reddit`, `telegram`, `threads`, `tiktok`, `twitter`, `youtube`.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-H 'Profile-Key: PROFILE_KEY' \
-d '{"platform": "twitter"}' \
-X DELETE https://api.ayrshare.com/api/profiles/social
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/profiles/social", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`,
"Profile-Key": PROFILE_KEY
},
body: JSON.stringify({ platform: "twitter" }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'platform': 'twitter' }
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY',
'Profile-Key': PROFILE_KEY }
r = requests.delete('https://api.ayrshare.com/api/profiles/social',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
'twitter']; // Data to be sent
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'DELETE',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
'Profile-Key: ' . $profileKey
],
]);
$response = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Error:' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace UnlinkSocialPOSTRequest_csharp
{
class UnlinkSocial
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string PROFILE_KEY = "PROFILE_KEY"; // Make sure this is defined
string url = "https://api.ayrshare.com/api/profiles/social";
string json = "{\"platform\": \"twitter\"}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
client.DefaultRequestHeaders.Add("Profile-Key", PROFILE_KEY);
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage
{
Method = HttpMethod.Delete,
RequestUri = new Uri(url),
Content = content
};
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: OK Successful unlink theme={"system"}
{
"status": "success",
"platform": "twitter",
"refId": "13a9wa9e0df1183b7a6a1fc2c61b8023fa9a32a1"
}
```
```json 400: Bad Request Error response theme={"system"}
{
"action": "post",
"status": "error",
"code": 163,
"message": "Missing, empty, or not valid platforms parameter. Please verify sending an array of valid platforms. .../ayrshare.com/rest-api/endpoints/post"
}
```
# Update a User Profile
Source: https://www.ayrshare.com/docs/apis/profiles/update-profile
PATCH /profiles
Update an existing profile.
Update an existing profile's title, hide title, list of disabled social platforms, or display the title.
The Profile Key in the header parameter is the User Profile to be updated.
## Header Parameters
## Body Parameters
Array of social networks that are disabled for this user's profile. The primary profile's list of disabled social networks takes precedence.
Available networks: `bluesky`, `facebook`, `gmb`, `instagram`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitter`, and `youtube`.
See [here](/docs/apis/profiles/overview#enable-or-disable-social-networks) for more information.
Title of the profile. Must be unique. This title will be displayed on the social account linking page.
Set to true to activate messaging for this user profile. Messaging must first be enabled for your Ayrshare account.
Hide the top header on the social accounts linkage page.
Hide the company logo on the social accounts linkage page for this user profile only. The account-wide logo on other profiles is unaffected. Useful for white-labeling individual partner profiles while keeping branding on the rest.
Change the header on the social accounts linkage page. If not set, then displays: "Social Accounts for "title" where "title" is the profile title.
Tag user profiles using an array of strings. These tags serve as an internal organizational tool to categorize and manage your user profiles effectively.
```javascript cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"profileKey": "Jokdf-903Js-j9sd0-Pow02-QS9n3", "title": "ACME Profile"}' \
-X PATCH https://api.ayrshare.com/api/profiles
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/profiles", {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
"Profile-Key": "PROFILE_KEY";
},
body: JSON.stringify({
title: "ACME Profile"
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'title': 'ACME Profile'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY',
'Profile-Key': 'PROFILE_KEY'}
r = requests.patch('https://api.ayrshare.com/api/profiles',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
'ACME Profile']; // Your data to be sent
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => $url,
CURLOPT_RETURNTRANSFER => true,
CURLOPT_CUSTOMREQUEST => 'PATCH',
CURLOPT_POSTFIELDS => json_encode($data),
CURLOPT_HTTPHEADER => [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
'Profile-Key: ' . $profileKey
],
]);
$response = curl_exec($curl);
if (curl_errno($curl)) {
echo 'Error:' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace UpdateProfilePOSTRequest_csharp
{
class UpdateProfile
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string PROFILE_KEY = "PROFILE_KEY"; // Make sure this is defined
string url = "https://api.ayrshare.com/api/profiles";
string json = "{\"title\": \"ACME Profile\"}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
client.DefaultRequestHeaders.Add("Profile-Key", PROFILE_KEY);
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
var request = new HttpRequestMessage
{
Method = new HttpMethod("PATCH"),
RequestUri = new Uri(url),
Content = content
};
HttpResponseMessage response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"refId": "b1eb30ce50607a40000b220c01c20a88a49fe76f"
}
```
```json 400: Profile Key not found theme={"system"}
{
"action": "post",
"status": "error",
"code": 144,
"message": "Some profiles not found. Please verify the Profile Keys."
}
```
# Delete a Review Reply
Source: https://www.ayrshare.com/docs/apis/reviews/delete-review-reply
DELETE /reviews
Delete a reply on a review
Delete a reply you made on a review. You must be the owner of the reply to delete.
Currently only Google Business Profile reviews are supported.
## Header Parameters
## Body Parameters
Values: `gmb`
The review id of the reply to delete.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-d '{"reviewId": "Ut1fWU6XkqkMayHGnJZ", "platform": "gmb"}' \
-X DELETE https://api.ayrshare.com/api/reviews
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/reviews", {
method: "DELETE",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
reviewId: "Ut1fWU6XkqkMayHGnJZ", // required
platform: "gmb", // required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'reviewId': 'Ut1fWU6XkqkMayHGnJZ',
'platform': 'gmb'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.delete('https://api.ayrshare.com/api/reviews',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$apiUrl = 'https://api.ayrshare.com/api/reviews';
$apiKey = 'API_KEY'; // Replace 'API_KEY' with your actual API key
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
];
$data = json_encode([
'reviewId' => 'Ut1fWU6XkqkMayHGnJZ', // Replace with your actual review ID
'platform' => 'gmb'
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_DELETE => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace DeleteReviewReplyPOSTRequest_csharp
{
class DeleteReviewReply
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/reviews";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
var json = @"{
""reviewId"": ""Ut1fWU6XkqkMayHGnJZ"",
""platform"": ""gmb""
}";
var content = new StringContent(
json,
Encoding.UTF8,
"application/json"
);
try
{
var response = await httpClient.DeleteAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Reply Deleted theme={"system"}
{
"gmb": {
"action": "delete",
"status": "success",
"id": "AbFvOqmQJ4xMTl2mjZl0h83TcOj_tbjK742M9xobS_MCTLgDjplzi4dBGAsn-71ASv_RGwO5JQOtRA"
}
}
```
```json 400: Delete Error theme={"system"}
{
"gmb": {
"action": "reviews",
"status": "error",
"code": 349,
"message": "Error adding review. Please verify the review is still available.",
"details": "Requested entity was not found."
}
}
```
# Get a Single Review
Source: https://www.ayrshare.com/docs/apis/reviews/get-one-review
GET /reviews/:id
Retrieve a single review
Retrieve a single review. Currently only Google Business Profile reviews.
## Header Parameters
## Path Parameters
The review ID.
## Query Parameters
Values: `gmb`
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/reviews/AbFvOqmQJ4xMTl2mjZl0h83TcOj?platform=gmb
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/reviews/AbFvOqmQJ4xMTl2mjZl0h83TcOj?platform=gmb", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/reviews/AbFvOqmQJ4xMTl2mjZl0h83TcOj?platform=gmb', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace ReviewsGetOne_csharp
{
class ReviewsGetOne
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string reviewId = "AbFvOqmQJ4xMTl2mjZl0h83TcOj";
// Build URL with query parameters
var uriBuilder = new UriBuilder("https://api.ayrshare.com/api/reviews/" + reviewId);
var query = HttpUtility.ParseQueryString(string.Empty);
query["platform"] = "gmb";
uriBuilder.Query = query.ToString();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(uriBuilder.Uri);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Retrieved Review theme={"system"}
{
"gmb": [
{
"created": "2023-07-11T21:23:57.707819Z",
"rating": "FIVE", // Rating ONE, TWO, THREE, FOUR, FIVE
"review": "Been a great experience - like the documentation, example coding, and help desk.",
"reviewReply": {
"reply": "Thank you for the great thoughts.",
"updated": "2024-02-05T22:36:17.989625Z"
},
"reviewer": {
"name": "Mads Max",
"profile": "https://lh3.googleusercontent.com/a-/ALV-UjV-MlTLJh9CdosuaS"
},
"updated": "2023-07-11T21:23:57.707819Z"
}
],
"lastUpdated": "2024-02-05T23:27:03.147Z",
"nextUpdate": "2024-02-05T23:38:03.147Z"
}
```
```json 400: Bad Request theme={"system"}
{
"action": "analytics",
"status": "error",
"code": 323,
"message": "Error getting Google Business Profile analytics. Please try again later or contact us."
}
```
# Get All Reviews
Source: https://www.ayrshare.com/docs/apis/reviews/get-reviews
GET /reviews
Retrieve all the reviews for the specified platform
Retrieve all the reviews for the specified platform. Currently only Facebook Page rating reviews and Google Business Profile reviews.
## Header Parameters
## Query Parameters
Values: `facebook`, `gmb`
### Request Examples
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/reviews?platform=gmb
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/reviews?platform=gmb", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/reviews?platform=gmb', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
namespace ReviewsGETRequest_csharp
{
class Reviews
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
// Build URL with query parameters
var uriBuilder = new UriBuilder("https://api.ayrshare.com/api/reviews");
var query = HttpUtility.ParseQueryString(string.Empty);
query["platform"] = "gmb";
uriBuilder.Query = query.ToString();
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(uriBuilder.Uri);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Retrieved Reviews theme={"system"}
{
"facebook": [
{
"created": "2023-07-11T21:14:41.000Z",
"id": "376602035206384",
"rating": "positive", // Rating positive, negative
"review": "Makes things easy for connecting social accounts and publishing.",
"reviewer": {
"name": "Sue Smith",
"id": "7283511115003",
"profile": {
"height": 50,
"isSilhouette": false,
// The URL of the profile picture valid for at least 7 days
"url": "https://platform-lookaside.fbsbx.com/platform/profilepic/",
"width": 50
}
}
},
{
"created": "2023-04-19T02:45:05.000Z",
"id": "376602035206385",
"rating": "positive", // Rating positive, negative
"review": "What an amazing product",
"reviewer": {
"name": "John Smith",
"id": "7501289573254",
"profile": {
"height": 50,
"isSilhouette": false,
// The URL of the profile picture valid for at least 7 days
"url": "https://platform-lookaside.fbsbx.com/platform/profilepic/",
"width": 50
}
}
}
],
"lastUpdated": "2024-02-05T22:47:42.996Z",
"nextUpdate": "2024-02-05T22:58:42.996Z"
},
{
"gmb": [
{
"created": "2023-07-11T21:23:57.707819Z",
"id": "AbFvOqkkVAAQYEe2o5asfICQAGTTG",
"rating": "FIVE", // Rating ONE, TWO, THREE, FOUR, FIVE
"review": "Been a great experience - like the documentation, example coding, and help desk.",
"reviewReply": {
"reply": "Thank you for the great thoughts.",
"updated": "2024-02-05T22:36:17.989625Z"
},
"reviewer": {
"name": "Mads Max",
"profile": "https://lh3.googleusercontent.com/a-/ALV-UjV-MlTLJh9CdosuaS_28Dx2aOZi"
},
"updated": "2023-07-11T21:23:57.707819Z"
},
{
"created": "2023-05-09T19:27:04.839089Z",
"id": "FFFvOqkkVAAQYEe2o5asfICQAGTTG",
"rating": "FIVE", // Rating ONE, TWO, THREE, FOUR, FIVE
"review": "Great service, really useful product, well-crafted",
"reviewReply": {},
"reviewer": {
"name": "V the Man",
"profile": "https://lh3.googleusercontent.com/a-/ALV-UjULaIDBWwT"
},
"updated": "2023-05-09T19:27:04.839089Z"
},
{
"created": "2023-05-02T19:04:54.814104Z",
"id": "BBBOqkkVAAQYEe2o5asfICQAGTTG",
"rating": "FIVE",
"review": "Ayrshare has been a top-notch product and much needed for CRM. We integrated the API a while back and the code samples in the docs provided by the team have been great. I've also been happy with the new features they've added like on TikTok and Instagram as well as with their support during the integration process.",
"reviewReply": {},
"reviewer": {
"name": "David Manning",
"profile": "https://lh3.googleusercontent.com/a-/ALV-UjXph_y96HMlmDJMJaEHJ1vGkFseinq1UasKOy"
},
"updated": "2023-05-02T19:04:54.814104Z"
},
{
"created": "2023-04-16T22:30:14.481018Z",
"id": "CCCvOqkkVAAQYEe2o5asfICQAGTTG",
"rating": "FIVE",
"review": "I've been using Ayrshare's API for my real estate SaaS platform for a while now and it has been great. Appreciated the help on my coding bug and really excited try the TikTok direct publishing with my users.",
"reviewReply": {
"reply": "Thank you.",
"updated": "2023-04-16T22:41:10.885472Z"
},
"reviewer": {
"name": "Jason Gould",
"profile": "https://lh3.googleusercontent.com/a-/ALV-UjUnpfGdErOQUC4zz6Bg3HwFHZz4Lly9gMOJA"
},
"updated": "2023-04-16T22:30:14.481018Z"
}
],
"averageRating": 4.12, // Facebook will be 1, 0, or -1 corresponding to positive, neutral, or negative
"totalReviewCount": 5,
"lastUpdated": "2024-02-05T23:05:10.091Z",
"nextUpdate": "2024-02-05T23:16:10.091Z"
}
```
```json 400: Reviews Not Found theme={"system"}
{
"action": "reviews",
"status": "error",
"code": 350,
"message": "Error getting reviews. Please verify there are reviews for this social network."
}
```
# Reviews API Overview
Source: https://www.ayrshare.com/docs/apis/reviews/overview
Get, reply, and delete reviews on your connected social accounts
Get, reply, and delete reviews on your connected social accounts including Facebook page ratings and Google Business Profile reviews.
See here for [Review API implementation details.](https://www.ayrshare.com/blog/reviews-api-review-management-with-an-api/)
# Reply to a Review
Source: https://www.ayrshare.com/docs/apis/reviews/reply-review
POST /reviews
Add a reply to a review
Add a reply to a review. Currently only Facebook and Google Business Profile reviews are supported.
## Header Parameters
#### Body Parameters
Values: `gmb` or `facebook`
The review ID.
The String text for the review reply.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{"reviewId": "Ut1fWU6XkqkMayHGnJZ", "platform": "gmb", "reply": "An amazing review!"}' \
-X POST https://api.ayrshare.com/api/reviews
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/reviews", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
reviewId: "Ut1fWU6XkqkMayHGnJZ", // required
platform: "gmb", // required
reply: "An amazing review!", //required
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'reviewId': 'Ut1fWU6XkqkMayHGnJZ',
'platform': 'gmb',
'reply': 'An amazing review!'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/reviews',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
'Ut1fWU6XkqkMayHGnJZ', // Replace with your actual review ID
'platform' => 'gmb',
'reply' => 'An amazing review!'
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace ReplyReviewPOSTRequest_csharp
{
class ReplyReview
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/reviews";
// Create JSON payload with proper formatting
string json = @"{
""reviewId"": ""Ut1fWU6XkqkMayHGnJZ"",
""platform"": ""gmb"",
""reply"": [""An amazing review!""]
}";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: Added Reply theme={"system"}
{
"gmb": {
"action": "reply",
"status": "success",
"id": "AbFvOqmQJ4xMTl2mjZl0h83TcOj",
"reply": "This one is great",
"platform": "gmb",
}
},
{
"facebook": {
"status": "success",
"platform": "facebook",
"id": "376602035206384_737529881909727",
"reply": "This one is great too",
"action": "reply"
}
}
```
```json 400: Bad Request theme={"system"}
{
"gmb": {
"action": "reviews",
"status": "error",
"code": 349,
"message": "Error adding review. Please verify the review is still available.",
"details": "Requested entity was not found."
}
}
```
# Batch Get All
Source: https://www.ayrshare.com/docs/apis/user/batch-all-users
GET /user/batch
Retrieve the user data for all user profiles
Retrieve the user data for all user profiles. Use the batch endpoint as an alternative to calling the /user endpoint for each of your users in rapid succession, which may be restricted by rate-limits.
The endpoint will return a pre-signed URL for the file containing all the user profile data. Please note the `urlAvailable` field time for when the file will be accessible.
The pre-signed URL will expire in 7 days after creation. A new file may be generated every 3 hours.
You may also be notified when the file is ready via the [Batch Action webhook](/docs/apis/webhooks/actions#batch-action).
## Header Parameters
```json 200: Success theme={"system"}
{
"success": true,
"url": "https://storage.googleapis.com/batch.ayrshare.com/users/9iskiedwtOddd/users-batch-2024-01-11-22-42.json",
"urlAvailable": "2024-01-11T22:47:36Z",
"urlExpires": "2024-01-18T22:42:36Z",
"lastUpdated": "2024-01-11T22:42:36.808Z",
"nextUpdate": "2024-01-11T22:54:36.808Z"
}
```
```json 403: Forbidden theme={"system"}
{
"action": "authorization",
"status": "error",
"code": 102,
"message": "API Key not valid. Please be sure to send a Header Authorization containing 'Bearer API_KEY'. .../ayrshare.com/rest-api/overview#authorization"
}
```
# User Profile API Overview
Source: https://www.ayrshare.com/docs/apis/user/overview
Get details on a user profile including linked social networks and social usernames
The user endpoint gives you details on all your users' social media accounts. You can also manage user profiles in the Ayrshare [dashboard](/docs/multiple-users/manage-user-profiles).
# Pinterest Boards
Source: https://www.ayrshare.com/docs/apis/user/pinterest-board
GET /user/details/pinterest
Get Details for Pinterest User Boards
Get the details of a connected platform. Current support for Pinterest Boards.
Currently supported platform values: `pinterest`
## Header Parameters
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/user/details/pinterest
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/user/details/pinterest", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/user/details/pinterest', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace PinterestBoardGETRequest_csharp
{
class PinterestBoard
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/user/details/pinterest";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```javascript 200: Pinterest Boards theme={"system"}
{
"pinterest": [
{
"privacy": "PUBLIC",
"owner": {
"username": "ayrshare"
},
"id": "718465015493014420",
"name": "Coworking",
"description": ""
},
{
"privacy": "PUBLIC",
"owner": {
"username": "ayrshare"
},
"id": "718465015493634450",
"name": "Social Media Networks",
"description": ""
}
]
}
```
# User Profile Details
Source: https://www.ayrshare.com/docs/apis/user/profile-details
GET /user
Get information on the user or user profile
This endpoint retrieves detailed information about the authenticated user or user profile, including:
A comprehensive list of all linked social media accounts
Social media usernames and profile information
Account status and usage metrics
The returned data reflects the state of connected social networks as of the last refresh, and updates whenever users connect or disconnect their social media accounts.
**Response caching.** Responses are cached for up to **60 seconds**. The `lastUpdated` and `nextUpdate` fields describe that cache window: `lastUpdated` is when the snapshot was built, `nextUpdate` is when it expires.
`nextUpdate` is a **cache-expiry marker, not a readiness signal.** It is stamped on every response, including one whose `displayNames` does not yet list an account you were just notified about, so it cannot tell you when a newly linked account has finished propagating.
If you are reconciling a [`social` webhook](/docs/apis/webhooks/actions) for a brand-new link, poll until the account you expect actually appears in `displayNames` — do not treat a single response, or the arrival of `nextUpdate`, as confirmation that the link is absent or complete.
If no social accounts are linked, `activeSocialAccounts` will not be returned.
Get data for a particular User Profile by adding the [Profile-Key in the header](/docs/apis/overview#profile-key-format).
If your business requires gathering all of your user profile data at once, please use the [/user/batch endpoint](/docs/apis/user/batch-all-users).
If you need a notification when a user links and unlinks a social account, please see the [/webhooks endpoint](/docs/apis/webhooks/overview).
## Header Parameters
## Query Parameters
Returns additional Instagram details such as account type (business or creator) and used quota.
Not recommended unless you need the additional data since it will slow down the response time.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-X GET https://api.ayrshare.com/api/user
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/user", {
method: "GET",
headers: {
"Authorization": `Bearer ${API_KEY}`
}
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
headers = {'Authorization': 'Bearer API_KEY'}
r = requests.get('https://api.ayrshare.com/api/user', headers=headers)
print(r.json())
```
```php PHP theme={"system"}
$apiUrl = 'https://api.ayrshare.com/api/user';
$apiKey = 'API_KEY'; // Replace 'API_KEY' with your actual API key
$headers = [
'Content-Type: application/json',
'Authorization: Bearer ' . $apiKey,
];
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespace UserGETRequest_csharp
{
class User
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/user";
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
try
{
HttpResponseMessage response = await client.GetAsync(url);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```javascript 200: Response theme={"system"}
{
"activeSocialAccounts": [
"bluesky",
"facebook",
"gmb",
"instagram",
"linkedin",
"pinterest",
"reddit",
"snapchat",
"telegram",
"threads",
"tiktok",
"twitter",
"youtube"
],
"created": {
"_seconds": 1667351022,
"_nanoseconds": 814000000,
"utc": "2022-11-02T01:03:42Z"
},
"displayNames": [
{ // Bluesky
"created": "2025-01-06T21:30:19.756Z",
"description": "Ayrshare's Social APIs provide the core infrastructure for social media posting, management, and analytics.",
"displayName": "Ayrshare",
"id": "did:plc:62musrcyanhro2lydyhl", // Bluesky Id
"platform": "bluesky",
"userImage": "https://cdn.bsky.app/img/avatar/plain/did:plc:62musrcyanhro2lydyhlw7ci/bafkreie",
"username": "ayrshare.com"
},
{ // Facebook
"created": "2022-11-14T16:18:49.110Z",
"displayName": "Ayrshare",
"id": "106638152329", // Facebook Page Id
"messagingActive": true, // Messaging active for the social network
"pageName": "Ayrshare",
"platform": "facebook",
"profileUrl": "https://www.facebook.com/ayrshare",
"userId": "283748192833", // Facebook User Id
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/facebook.jpeg" // The image at the time of linking
},
{ // Google Business Profile
"created": "2024-03-27T20:47:46.251Z",
"description": "Easy to integrate Social Media APIs allow you to manage all your users' social accounts right from your product. Post, Auto Schedule, and Analytics. Great for SaaS, CMS, DAM, Agencies, and Apps.",
"displayName": "Ayrshare",
"mapsUrl": "https://maps.google.com/maps?cid=5229466225881728772",
"placeId": "ChIJN53jw8BZwokRBEeVVtPLkkg",
"platform": "gmb",
"profileUrl": "https://www.ayrshare.com/",
"reviewUrl": "https://search.google.com/local/writereview?placeid=ChIJN53jw8BZwokRBEeVVtPLkkg"
},
{ // Instagram
"created": "2022-11-09T20:36:58.659Z",
"displayName": "Ayrshare",
"id": "1784144322", // Associate Facebook Page Id
"igId": "62938492293422", // Instagram User Id
"messagingActive": true, // Messaging active for the social network
"pageName": "Social Media API",
"platform": "instagram",
"profileUrl": "https://www.instagram.com/ayrshare",
"type": "business", // "business" returned for both business and creator account types. Only returned if instagramQuota: true
"usedQuota": 34, // Instagram quota. 50 posts per rolling 24-hour period. Returned if instagramQuota: true
"userId": "2938492293422", // Instagram User Id
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/instagram.jpeg", // The image at the time of linking
"username": "ayrshare",
// Additional Instagram details with instagramDetails=true
"type": "business", // business or creator
"usedQuota": 20 // daily quota used - Instagram allows 50 posts per rolling 24-hour period
},
{ // LinkedIn
"created": "2022-11-17T18:52:29.830Z",
"displayName": "Ayrshare",
"id": "72157",
"platform": "linkedin",
"profileUrl": "https://www.linkedin.com/company/ayrshare",
"refreshDaysRemaining": 364, // Days until link auth must be refreshed
"refreshRequired": "2023-11-17T18:52:29.830Z", // Date and time when link auth must be refreshed
"type": "corporate", // corporate or personal
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/linkedin.jpeg", // The image at the time of linking
"username": "ayrshare" // logged in username
},
{ // Pinterest
"created": "2022-12-06T03:16:52.642Z",
"displayName": "Ayrshare",
"id": "42995790741",
"platform": "pinterest",
"profileUrl": "https://www.pinterest.com/ayrshare",
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/pinterest.jpeg", // The image at the time of linking
"username": "ayrshare"
},
{ // Reddit
"created": "2022-11-17T18:55:34.419Z",
"displayName": "funone",
"platform": "reddit",
"profileUrl": "https://www.reddit.com/user/funone",
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/reddit.png", // The image at the time of linking
"username": "funone"
},
{ // Snapchat
"created": "2025-05-19T19:23:40.925Z",
"displayName": "ayrshare",
"id": "43548e97-edf1-44f9-984a-0a384703333",
"platform": "snapchat",
"profileUrl": "https://www.snapchat.com/add/username",
"userImage": "https://img.ayrshare.com/EuMQpMIgcPZYuwHnWeVBCXyftb52/social/snapchat",
"username": "ayrshare"
},
{ // Telegram
"created": "2022-11-17T18:55:16.320Z",
"displayName": "Ayrshare",
"id": -10017122,
"platform": "telegram",
"profileUrl": "https://web.telegram.org/z/#-17122",
"type": "channel",
"userImage": "https://img.ayrshare.com/nclMLxaIzmXHxOi4KEggA5gQ1T82/social/telegram.octo-stream" // The image at the time of linking
},
{ // Threads
"created": "2025-04-24T20:26:28.311Z",
"displayName": "ayrshare",
"id": "9273292656113202",
"isEligibleForGeoRestrictions": false,
"isVerified": false,
"platform": "threads",
"profileUrl": "https://www.threads.com/@ayrshare",
"userImage": "https://scontent-dfw5-2.cdninstagram.com/v/t51.2885-15/357665262", // The image at the time of linking
"username": "ayrshare"
},
{ // TikTok
"created": "2022-11-02T02:11:53.452Z",
"displayName": "Ayrshare",
"id": "5ebc6f39-7900-421e-bf9",
"platform": "tiktok",
"profileUrl": "https://www.tiktok.com/@ayrshare",
"refreshDaysRemaining": 234, // Days until link auth must be refreshed
"refreshRequired": "2026-04-24T15:25:32.344Z", // Date and time when link auth must be refreshed
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/tiktok.jpeg", // The image at the time of linking
"username": "@ayrshare"
},
{ // Twitter
"created": "2022-11-02T01:38:42.326Z",
"displayName": "ayrshare",
"id": "1194881472",
"messagingActive": true,
"platform": "twitter", // Messaging active for the social network
"profileUrl": "https://twitter.com/ayrshare",
"subscriptionType": "Premium", // Premium, PremiumPlus, None
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/twitter.png", // The image at the time of linking
"username": "ayrshare",
"verifiedType": "blue" // Values "blue", "business", or "none". Both "blue" and "business" are considered Premium. This will be updated when an X post is done via Ayrshare.
},
{ // YouTube
"created": "2022-11-17T18:54:09.954Z",
"displayName": "@ayrshare",
"id": "106891058521430758565",
"platform": "youtube",
"profileUrl": "https://www.youtube.com/@ayrshare",
"userImage": "https://img.ayrshare.com/ndfdfJ239s/social/youtube.png", // The image at the time of linking
"username": "@ayrshare"
}
],
"email": "me@ayrshare.com", // null if a User Profile
"lastApiCall": "2024-08-14T15:18:11Z", // Time of the last recorded API call for this user
"messagingConversationMonthlyCount": 7, // Monthly conversation count out of 100 - contact us if you need more per user profile
"messagingEnabled": true, // Messaging enabled for the account
"monthlyApiCalls": 49, // Current number of Posts, but starting Feb 1, 2025, this will include all types of API calls
"monthlyPostCount": 49, // Count of monthly posts
"monthlyPostQuota": 500, // Quota of monthly API post calls. Not present for Business Plans.
"monthlyApiCallsQuota": 500, // Deprecated Feb 1, 2025. Use monthlyPostQuota instead.
"refId": "13a9da9e0df1183a7a6a1fc2c60b8023fa9a32a0", // User Profile reference ID
"title": "Primary Profile", // User Profile Title - Business Plan only
"lastUpdated": "2024-01-04T15:51:17.775Z", // When this cached snapshot was built
"nextUpdate": "2024-01-04T15:52:17.775Z" // When the cache expires. Not a readiness signal — see Response caching above
}
```
```json 403: Profile Key Not Found theme={"system"}
{
"action": "post",
"status": "error",
"code": 144,
"message": "Some profiles not found. Please verify the Profile Keys."
}
```
# Update User
Source: https://www.ayrshare.com/docs/apis/user/update-user
PATCH /user/:platform
Update the account or user data of the social network
Update the account or user data of the social network. Currently only Google Business Profile is supported.
Google limits updating some Google Business Profile location fields to being updated 5 times
within a rolling 24-hour period. For example updating `phoneNumbers` more than 5 times in a
rolling 24-hour period will return a 400 Response.
## Header Parameters
## Path Parameters
Values: `gbp`
## Body Parameters
Object containing the different phone numbers that customers can use to get in touch with the business.
```json theme={"system"}
"phoneNumbers": {
"primaryPhone": "212-123-4567",
"additionalPhones": [
"212-432-2342"
]
}
```
Google identifier for this location in the form.
An alternate phone number to display on AdWords location extensions instead of the location's
primary phone number.
External identifier for this location, which must be unique within a given account. This is a
means of associating the location with your own records.
Location name should reflect your business's real-world name, as used consistently on your storefront, website, and stationery, and as known to customers.
A URL for this business.
A collection of free-form strings to allow you to tag your business. These labels are not user facing; only you can see them. Must be between 1-255 characters per label.
An object that represents a latitude/longitude pair. This is expressed as a pair of doubles to represent degrees latitude and degrees longitude. Unless specified otherwise, this object must conform to the WGS84 standard.
```json theme={"system"}
{
"latitude": number,
"longitude": number
}
```
Values must be within normalized ranges.
The latitude in degrees. It must be in the range \[-90.0, +90.0].
The longitude in degrees. It must be in the range \[-180.0, +180.0].
This field contains a description of the location in your own voice. The description is not editable by anyone else.
```json theme={"system"}
{
"description": string
}
```
```json 200: Success theme={"system"}
{
"gmb": {
"status": "success",
"data": {
"name": "locations/4913369732395328466",
"languageCode": "en",
"title": "Ayrshare",
"phoneNumbers": {},
"categories": {
"primaryCategory": {
"name": "categories/gcid:software_company",
"displayName": "Software company",
"serviceTypes": [
{
"serviceTypeId": "job_type_id:application_development",
"displayName": "Application development"
},
{
"serviceTypeId": "job_type_id:big_data_consulting_and_implementation",
"displayName": "Big data consulting & implementation"
},
{
"serviceTypeId": "job_type_id:data_center_management",
"displayName": "Data center management"
},
{
"serviceTypeId": "job_type_id:data_quality_management",
"displayName": "Data quality management"
},
{
"serviceTypeId": "job_type_id:enterprise_software_development",
"displayName": "Enterprise software development"
},
{
"serviceTypeId": "job_type_id:it_consulting",
"displayName": "It consulting"
},
{
"serviceTypeId": "job_type_id:mobile_app_development",
"displayName": "Mobile app development"
},
{
"serviceTypeId": "job_type_id:platform_consulting",
"displayName": "Platform consulting"
},
{
"serviceTypeId": "job_type_id:security_services_management",
"displayName": "Security services management"
},
{
"serviceTypeId": "job_type_id:software_consulting",
"displayName": "Software consulting"
},
{
"serviceTypeId": "job_type_id:software_development",
"displayName": "Software development"
},
{
"serviceTypeId": "job_type_id:software_development_outsourcing",
"displayName": "Software development outsourcing"
},
{
"serviceTypeId": "job_type_id:solution_consulting",
"displayName": "Solution consulting"
}
],
"moreHoursTypes": [
{
"hoursTypeId": "ACCESS",
"displayName": "Access",
"localizedDisplayName": "Access"
},
{
"hoursTypeId": "BREAKFAST",
"displayName": "Breakfast",
"localizedDisplayName": "Breakfast"
},
{
"hoursTypeId": "BRUNCH",
"displayName": "Brunch",
"localizedDisplayName": "Brunch"
},
{
"hoursTypeId": "DELIVERY",
"displayName": "Delivery",
"localizedDisplayName": "Delivery"
},
{
"hoursTypeId": "DINNER",
"displayName": "Dinner",
"localizedDisplayName": "Dinner"
},
{
"hoursTypeId": "DRIVE_THROUGH",
"displayName": "Drive through",
"localizedDisplayName": "Drive through"
},
{
"hoursTypeId": "HAPPY_HOUR",
"displayName": "Happy hours",
"localizedDisplayName": "Happy hours"
},
{
"hoursTypeId": "KITCHEN",
"displayName": "Kitchen",
"localizedDisplayName": "Kitchen"
},
{
"hoursTypeId": "LUNCH",
"displayName": "Lunch",
"localizedDisplayName": "Lunch"
},
{
"hoursTypeId": "ONLINE_SERVICE_HOURS",
"displayName": "Online service hours",
"localizedDisplayName": "Online service hours"
},
{
"hoursTypeId": "PICKUP",
"displayName": "Pickup",
"localizedDisplayName": "Pickup"
},
{
"hoursTypeId": "TAKEOUT",
"displayName": "Takeout",
"localizedDisplayName": "Takeout"
},
{
"hoursTypeId": "SENIOR_HOURS",
"displayName": "Senior hours",
"localizedDisplayName": "Senior hours"
}
]
},
"additionalCategories": [
{
"name": "categories/gcid:automation_company",
"displayName": "Automation company",
"moreHoursTypes": [
{
"hoursTypeId": "ACCESS",
"displayName": "Access",
"localizedDisplayName": "Access"
},
{
"hoursTypeId": "BREAKFAST",
"displayName": "Breakfast",
"localizedDisplayName": "Breakfast"
},
{
"hoursTypeId": "BRUNCH",
"displayName": "Brunch",
"localizedDisplayName": "Brunch"
},
{
"hoursTypeId": "DELIVERY",
"displayName": "Delivery",
"localizedDisplayName": "Delivery"
},
{
"hoursTypeId": "DINNER",
"displayName": "Dinner",
"localizedDisplayName": "Dinner"
},
{
"hoursTypeId": "DRIVE_THROUGH",
"displayName": "Drive through",
"localizedDisplayName": "Drive through"
},
{
"hoursTypeId": "HAPPY_HOUR",
"displayName": "Happy hours",
"localizedDisplayName": "Happy hours"
},
{
"hoursTypeId": "KITCHEN",
"displayName": "Kitchen",
"localizedDisplayName": "Kitchen"
},
{
"hoursTypeId": "LUNCH",
"displayName": "Lunch",
"localizedDisplayName": "Lunch"
},
{
"hoursTypeId": "ONLINE_SERVICE_HOURS",
"displayName": "Online service hours",
"localizedDisplayName": "Online service hours"
},
{
"hoursTypeId": "PICKUP",
"displayName": "Pickup",
"localizedDisplayName": "Pickup"
},
{
"hoursTypeId": "TAKEOUT",
"displayName": "Takeout",
"localizedDisplayName": "Takeout"
},
{
"hoursTypeId": "SENIOR_HOURS",
"displayName": "Senior hours",
"localizedDisplayName": "Senior hours"
}
]
}
]
},
"storefrontAddress": {
"regionCode": "US",
"languageCode": "en",
"postalCode": "10019",
"administrativeArea": "NY",
"locality": "New York",
"addressLines": [
"142 W 57th St"
]
},
"websiteUri": "https://www.ayrshare.com/",
"regularHours": {
"periods": [
{
"openDay": "SUNDAY",
"openTime": {},
"closeDay": "SUNDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "MONDAY",
"openTime": {},
"closeDay": "MONDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "TUESDAY",
"openTime": {},
"closeDay": "TUESDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "WEDNESDAY",
"openTime": {},
"closeDay": "WEDNESDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "THURSDAY",
"openTime": {},
"closeDay": "THURSDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "FRIDAY",
"openTime": {},
"closeDay": "FRIDAY",
"closeTime": {
"hours": 24
}
},
{
"openDay": "SATURDAY",
"openTime": {},
"closeDay": "SATURDAY",
"closeTime": {
"hours": 24
}
}
]
},
"serviceArea": {
"businessType": "CUSTOMER_AND_BUSINESS_LOCATION",
"places": {
"placeInfos": [
{
"placeName": "United States",
"placeId": "ChIJCzYy5IS16lQRQrfeQ5K5Oxw"
}
]
},
"regionCode": "US"
},
"openInfo": {
"status": "OPEN",
"canReopen": true
},
"metadata": {
"hasPendingEdits": true,
"canDelete": true,
"canModifyServiceList": true,
"placeId": "ChIJN53jw8BZwokRBEeVVtPLkkg",
"mapsUri": "https://maps.google.com/maps?cid=5229466225881728772",
"newReviewUri": "https://search.google.com/local/writereview?placeid=ChIJN53jw8BZwokRBEeVVtPLkkg",
"hasVoiceOfMerchant": true
},
"profile": {
"description": "Easy to integrate Social Media APIs allow you to manage all your users' social accounts right from your product. Post, Auto Schedule, and Analytics. Great for SaaS, CMS, DAM, Agencies, and Apps."
}
}
}
}
```
```json 400: Too Many Updates theme={"system"}
{
"action": "authorization",
"status": "error",
"code": 227,
"message": "Error updating GBP location data. This can occur if you attempt more than 5 updates within a rolling 24 hours period. Please wait and try again."
}
```
# Instagram Collaborator Request Status
Source: https://www.ayrshare.com/docs/apis/utils/instagram-get-collaborator
GET /post/collaborators/:id
Get the status of a request to a collaborator
When you [invite a collaborator to a post](/docs/apis/post/social-networks/instagram#collaboration), you can check the status of the request using this endpoint.
Only Instagram users who have enabled collaborator tagging will be returned in the response.
## Header Parameters
## Path Parameters
In the path parameter, use an [ID Type](/docs/apis/overview#id-types)
## Query Parameters
Set to `true`. Required if using a Social Post ID.
```json 200 theme={"system"}
{
"collaborators": [
{
"id": "17841401319910272",
"username": "ayrshare",
"inviteStatus": "accepted"
},
{
"id": "17841401319910273",
"username": "ayrshare1",
"inviteStatus": "declined"
},
{
"id": "17841401319910274",
"username": "ayrshare2",
"inviteStatus": "pending"
}
],
"lastUpdated": "2024-03-08T04:08:18.979Z",
"nextUpdate": "2024-03-08T04:09:18.979Z"
}
```
```json 400 theme={"system"}
{
"action": "analytics",
"status": "error",
"code": 294,
"message": "Error getting analytics."
}
```
# Reddit Flair
Source: https://www.ayrshare.com/docs/apis/utils/reddit-get-flair
GET /post/redditFlair/:subreddit
Retrieve the flair id for a subreddit to be used with a Reddit post
Some subreddits require flair to be added to posts. Retrieve the flair id for a subreddit to be used with a Reddit post.
## Header Parameters
## Path Parameters
A valid subreddit name.
```json 200: OK Subreddit flair theme={"system"}
{
"flairs": [
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "General",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "General"
}
],
"backgroundColor": "#24a0ed",
"id": "835693e2-f4c6-11e8-9b68-0ef1d31d47f4"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Model S",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Model S"
}
],
"backgroundColor": "#ff5c52",
"id": "d65a3bf8-2e3f-11ea-b1df-0e48b758f1d1"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Model 3",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Model 3"
}
],
"backgroundColor": "#ff5c52",
"id": "dcd4dfba-2e3f-11ea-ae0a-0e08fd0921a5"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Model X",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Model X"
}
],
"backgroundColor": "#ff5c52",
"id": "e3b80334-2e3f-11ea-9319-0ef0666f4955"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Model Y",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Model Y"
}
],
"backgroundColor": "#ff5c52",
"id": "e8d3c3e4-2e3f-11ea-8503-0e7d8ba95ee7"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Roadster",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Roadster"
}
],
"backgroundColor": "#ff5c52",
"id": "9b5a153c-2fe8-11ea-84b3-0e3dc676291d"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Cybertruck",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Cybertruck"
}
],
"backgroundColor": "#ff5c52",
"id": "f7bd2d96-2e3f-11ea-8af4-0e84bb2efd99"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Vehicles - Semi",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Vehicles - Semi"
}
],
"backgroundColor": "#ff5c52",
"id": "08e0e25c-2e40-11ea-8503-0e7d8ba95ee7"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Energy - General",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Energy - General"
}
],
"backgroundColor": "#349e48",
"id": "300915fc-2e40-11ea-bf20-0e5f8d7121e9"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Energy - Charging",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Energy - Charging"
}
],
"backgroundColor": "#349e48",
"id": "26c0bde0-4ada-11ea-a6c2-0e37bd75c65b"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Energy - Residential",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Energy - Residential"
}
],
"backgroundColor": "#349e48",
"id": "3c552d28-2e40-11ea-91af-0efac8321a7d"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Energy - Commercial",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Energy - Commercial"
}
],
"backgroundColor": "#349e48",
"id": "6c3da4e4-3f71-11ed-bf3a-e2b38500a359"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "$TSLA Investing - Financials/Earnings",
"maxEmojis": 10,
"textColor": "dark",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "$TSLA Investing - Financials/Earnings"
}
],
"backgroundColor": "#94e044",
"id": "260deb6a-fb68-11ed-b8f9-fe172b851044"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "$TSLA Investing - Bullish",
"maxEmojis": 10,
"textColor": "dark",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "$TSLA Investing - Bullish"
}
],
"backgroundColor": "#94e044",
"id": "35318c0a-fb68-11ed-ac39-ae5f0d523a9a"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "$TSLA Investing - Bearish",
"maxEmojis": 10,
"textColor": "dark",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "$TSLA Investing - Bearish"
}
],
"backgroundColor": "#94e044",
"id": "4739d7ea-fb68-11ed-825c-dee75c150cc6"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - General",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - General"
}
],
"backgroundColor": "#646d73",
"id": "971ac264-3f71-11ed-a80d-be048f065daa"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Fremont, California",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Fremont, California"
}
],
"backgroundColor": "#646d73",
"id": "9f03fc98-3f71-11ed-a464-22492ba9dd17"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Austin, Texas",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Austin, Texas"
}
],
"backgroundColor": "#646d73",
"id": "a3cfad80-3f71-11ed-a86b-b6b3d0e0d7bd"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Buffalo, New York",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Buffalo, New York"
}
],
"backgroundColor": "#646d73",
"id": "a941fe4e-3f71-11ed-8f4f-6ef3febda094"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Sparks, Nevada",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Sparks, Nevada"
}
],
"backgroundColor": "#646d73",
"id": "aeabb0d2-3f71-11ed-97b0-22ecff9f5113"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Shanghai, China",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Shanghai, China"
}
],
"backgroundColor": "#646d73",
"id": "b65cf386-3f71-11ed-a39c-c293bd1546c0"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Berlin, Germany",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Berlin, Germany"
}
],
"backgroundColor": "#646d73",
"id": "155d7b10-578e-11ed-a0d2-d2bc46bf7da2"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Lathrop, California",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Lathrop, California"
}
],
"backgroundColor": "#646d73",
"id": "f15c7f0a-8874-11ed-ab66-96069cfc53e3"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Factories - Monterrey, Mexico",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Factories - Monterrey, Mexico"
}
],
"backgroundColor": "#646d73",
"id": "097e95ca-b9d3-11ed-94a1-7a457264f9ca"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Software - General",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Software - General"
}
],
"backgroundColor": "#0079d3",
"id": "e1df8ffa-3f71-11ed-bc64-2aaa808ece5c"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Software - Tesla App",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Software - Tesla App"
}
],
"backgroundColor": "#0079d3",
"id": "f5d33e68-2197-11ee-97e0-9e68d8ed8435"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Software - Autopilot",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Software - Autopilot"
}
],
"backgroundColor": "#0079d3",
"id": "e71da20e-3f71-11ed-a4ea-d2f3dc1b4cf7"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Software - Full Self-Driving",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Software - Full Self-Driving"
}
],
"backgroundColor": "#0079d3",
"id": "fa5e9a58-3f71-11ed-b0e0-1a8e6d6659f3"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Software - AI / Optimus / Dojo",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Software - AI / Optimus / Dojo"
}
],
"backgroundColor": "#0079d3",
"id": "00b3b44c-3f72-11ed-911c-ea0c960aabdf"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Hardware - General",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Hardware - General"
}
],
"backgroundColor": "#005ba1",
"id": "4d9ddd0a-3f72-11ed-9dcb-362c5016d5b6"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Hardware - Autopilot",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Hardware - Autopilot"
}
],
"backgroundColor": "#005ba1",
"id": "56876012-3f72-11ed-a892-2271fd05c94a"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Hardware - Full Self-Driving",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Hardware - Full Self-Driving"
}
],
"backgroundColor": "#005ba1",
"id": "5c26f334-3f72-11ed-a350-7acd016cd487"
},
{
"type": "richtext",
"textEditable": false,
"allowableContent": "all",
"text": "Hardware - AI / Optimus / Dojo",
"maxEmojis": 10,
"textColor": "light",
"modOnly": false,
"cssClass": "",
"richtext": [
{
"e": "text",
"t": "Hardware - AI / Optimus / Dojo"
}
],
"backgroundColor": "#005ba1",
"id": "70f05e86-3f72-11ed-8307-d25f6730a03f"
}
],
"lastUpdated": "2023-11-06T21:35:11.119Z",
"nextUpdate": "2023-11-06T21:46:11.119Z"
}
```
```json 400: Bad Request No flair found theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints",
"details": "The subreddit does not exist or is private.",
"subreddit": "teslamotors12",
"lastUpdated": "2023-11-06T21:58:42.392Z",
"nextUpdate": "2023-11-06T22:09:42.392Z"
}
```
# Remove YouTube Watermark
Source: https://www.ayrshare.com/docs/apis/utils/remove-youtube-watermark
DELETE /post/youTubeWatermark
Remove the watermark from your YouTube channel
Remove the existing watermark from your YouTube channel. This will remove the
watermark from all existing and future videos uploaded to the channel.
## Header Parameters
## Body Parameters
No body parameters required for this endpoint.
```json 200 theme={"system"}
{
"status": "success",
"message": "Watermark removed successfully"
}
```
```json 403 - Insufficient Permissions theme={"system"}
{
"status": "error",
"code": 250,
"message": "Insufficient permissions to remove watermark from this channel",
"details": "Original YouTube API error message"
}
```
```json 403 - Channel Not Found or No Watermark Exists theme={"system"}
{
"status": "error",
"code": 226,
"message": "Channel not found or no watermark exists to remove",
"details": "Requested entity was not found."
}
```
# Set YouTube Watermark
Source: https://www.ayrshare.com/docs/apis/utils/set-youtube-watermark
POST /post/youTubeWatermark
Set a watermark on your YouTube channel
Set a watermark image on your YouTube channel that will appear on all your videos. The watermark can be configured to appear at specific times during video playback.
Position is automatically set to bottom-right corner (YouTube API default)
All timing parameters `timingType`, `offsetMs`, and `durationMs` are required when setting a watermark
Watermarks apply to all videos on the channel (existing and future)
The watermark image must meet YouTube's [watermark media guidelines](/docs/media-guidelines/youtube#watermark)
You must have proper permissions to manage the YouTube channel
## Header Parameters
## Body Parameters
Array containing the watermark image URL. Only the first URL will be used.
When to show the watermark during video playback.
Available timingType options:
* `offsetFromStart` - Show watermark starting from a specific time after video begins
* `offsetFromEnd` - Show watermark starting from a specific time before video ends
Time offset in milliseconds. Must be a positive number.
* For `offsetFromStart`: Time after video starts to show watermark
* For `offsetFromEnd`: Time before video ends to show watermark
How long to display the watermark in milliseconds. Must be a positive number.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API_KEY" \
-H 'Content-Type: application/json' \
-d '{
"mediaUrls": ["https://example.com/watermark.png"],
"timingType": "offsetFromStart",
"offsetMs": 15000,
"durationMs": 30000
}' \
-X POST https://api.ayrshare.com/api/post/youTubeWatermark
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
fetch("https://api.ayrshare.com/api/post/youTubeWatermark", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${API_KEY}`
},
body: JSON.stringify({
mediaUrls: ["https://example.com/watermark.png"],
timingType: "offsetFromStart",
offsetMs: 15000,
durationMs: 30000
}),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {
'mediaUrls': ['https://example.com/watermark.png'],
'timingType': 'offsetFromStart',
'offsetMs': 15000,
'durationMs': 30000
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
}
r = requests.post('https://api.ayrshare.com/api/post/youTubeWatermark',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
['https://example.com/watermark.png'],
'timingType' => 'offsetFromStart',
'offsetMs' => 15000,
'durationMs' => 30000
]);
$curl = curl_init($apiUrl);
curl_setopt_array($curl, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_POSTFIELDS => $data
]);
$response = curl_exec($curl);
if ($response === false) {
echo 'Curl error: ' . curl_error($curl);
} else {
echo json_encode(json_decode($response), JSON_PRETTY_PRINT);
}
curl_close($curl);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace SetYouTubeWatermark_csharp
{
class SetYouTubeWatermark
{
private static readonly HttpClient client = new HttpClient();
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post/youTubeWatermark";
// Set up request headers
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
// Prepare JSON content
string json = @"{
""mediaUrls"": [""https://example.com/watermark.png""],
""timingType"": ""offsetFromStart"",
""offsetMs"": 15000,
""durationMs"": 30000
}";
var content = new StringContent(json, Encoding.UTF8, "application/json");
try
{
// Send POST request
HttpResponseMessage response = await client.PostAsync(url, content);
response.EnsureSuccessStatusCode();
// Read response
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
```
```json 200 theme={"system"}
{
"status": "success",
"message": "Watermark set successfully",
"mediaUrls": [
"https://example.com/watermark.png"
],
"timingType": "offsetFromStart",
"offsetMs": 1000,
"durationMs": 5000
}
```
```json 400 - Invalid Image Dimensions theme={"system"}
{
"action": "post",
"status": "error",
"code": 140,
"message": "The image aspect ratio must be between 1 and 1. Current image aspect ratio: 1085/723 (1.50). https://www.ayrshare.com/docs/media-guidelines/youtube "
}
```
```json 400 - Unsupported Format theme={"system"}
{
"status": "error",
"code": 307,
"message": "Media type 'image/webp' is not supported. "
}
```
```json 403 - Permission Error theme={"system"}
{
"status": "error",
"code": 250,
"message": "The watermark cannot be set for this channel. Please check that you have proper permissions and the channel is valid."
}
```
# User Lookups
Source: https://www.ayrshare.com/docs/apis/utils/user-lookups
GET /user/lookups
Retrieve the users (handles) looked up for the current month.
Retrieve the users (handles) looked up for the current month.
Users tracked when using the `userId` or `userName` fields for the analytics or history endpoints.
## Header Parameters
```json 200: Current Month User Lookups theme={"system"}
{
"x": [
{
"userId": "1322691",
"userName": "neilpatel",
"name": "Neil Patel"
},
{
"userId": "20536157",
"userName": "Google",
"name": "Google"
}
]
}
```
```json 403: Unauthorized theme={"system"}
{
"action": "request",
"status": "error",
"code": 3,
"message": "You do not have permission to access this resource. Please contact us to get access."
}
```
# YouTube Categories
Source: https://www.ayrshare.com/docs/apis/utils/youtube-categories
GET /post/youtubeCategories/:region
Retrieve the YouTube categories ids for a given region
Retrieve the YouTube categories ids for a given region. The category ID can be set in the POST or PATCH /post endpoints.
For example, `GET https://api.ayrshare.com/api/post/youtubeCategories/US` for the U.S. video categories.
YouTube only allows certainly categories to be assigned by a user.
Only categories where assignable is `true` can be set in the POST or PATCH /post endpoints when creating a YouTube post.
Other categories, which are not assignable and have `assignable: false`, will result in an error.
## Header Parameters
## Path Parameters
Two letter [country code](/docs/iso-codes/country) of the region.
```json 200: OK Retrieved Categories theme={"system"}
{
"region": "US",
"categories": [
{
"id": "1",
"title": "Film & Animation",
"assignable": true
},
{
"id": "10",
"title": "Music",
"assignable": true
},
{
"id": "15",
"title": "Pets & Animals",
"assignable": true
},
{
"id": "17",
"title": "Sports",
"assignable": true
},
{
"id": "18",
"title": "Short Movies",
"assignable": false
},
{
"id": "19",
"title": "Travel & Events",
"assignable": true
},
{
"id": "2",
"title": "Autos & Vehicles",
"assignable": true
},
{
"id": "20",
"title": "Gaming",
"assignable": true
},
{
"id": "21",
"title": "Videoblogging",
"assignable": false
},
{
"id": "22",
"title": "People & Blogs",
"assignable": true
},
{
"id": "23",
"title": "Comedy",
"assignable": true
},
{
"id": "24",
"title": "Entertainment",
"assignable": true
},
{
"id": "25",
"title": "News & Politics",
"assignable": true
},
{
"id": "26",
"title": "Howto & Style",
"assignable": true
},
{
"id": "27",
"title": "Education",
"assignable": true
},
{
"id": "28",
"title": "Science & Technology",
"assignable": true
},
{
"id": "29",
"title": "Nonprofits & Activism",
"assignable": true
},
{
"id": "30",
"title": "Movies",
"assignable": false
},
{
"id": "31",
"title": "Anime/Animation",
"assignable": false
},
{
"id": "32",
"title": "Action/Adventure",
"assignable": false
},
{
"id": "33",
"title": "Classics",
"assignable": false
},
{
"id": "34",
"title": "Comedy",
"assignable": false
},
{
"id": "35",
"title": "Documentary",
"assignable": false
},
{
"id": "36",
"title": "Drama",
"assignable": false
},
{
"id": "37",
"title": "Family",
"assignable": false
},
{
"id": "38",
"title": "Foreign",
"assignable": false
},
{
"id": "39",
"title": "Horror",
"assignable": false
},
{
"id": "40",
"title": "Sci-Fi/Fantasy",
"assignable": false
},
{
"id": "41",
"title": "Thriller",
"assignable": false
},
{
"id": "42",
"title": "Shorts",
"assignable": false
},
{
"id": "43",
"title": "Shows",
"assignable": false
},
{
"id": "44",
"title": "Trailers",
"assignable": false
}
]
}.
.
```
```json 400: Incorrect Region Code theme={"system"}
{
"action": "request",
"status": "error",
"code": 101,
"message": "Missing or incorrect parameters. Please verify with the docs. .../ayrshare.com/rest-api/endpoints"
}
```
# Check Post Length
Source: https://www.ayrshare.com/docs/apis/validate/check-post-length
POST /validate/postLength
Calculate the weighted length, or character count, of a post string
Calculate the weighted length, or character count, of a post string for Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Threads, TikTok, X/Twitter, and YouTube. Checks if the post length is valid and returns the maximum length allowed for each social network.
Special characters, such as ü, ø, or 😊, have a higher character count value (unicode).
This check is automatically done with the /post endpoint.
The weighted length is an estimate calculated by Ayrshare. Social networks may have slightly different character counts based on their own calculation methods.
## Header Parameters
## Body Parameters
Post string to calculate the length.
```bash cURL theme={"system"}
curl \
-H "Authorization: Bearer API Key" \
-H 'Content-Type: application/json' \
-d '{"post": "🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩"}' \
-X POST https://api.ayrshare.com/api/post/checkPostWeight
```
```javascript JavaScript theme={"system"}
const API_KEY = "API_KEY";
const post = "🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩";
fetch("https://api.ayrshare.com/api/post/checkPostWeight", {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`,
},
body: JSON.stringify({ post }),
})
.then((res) => res.json())
.then((json) => console.log(json))
.catch(console.error);
```
```python Python theme={"system"}
import requests
payload = {'post': '🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩'}
headers = {'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'}
r = requests.post('https://api.ayrshare.com/api/post/checkPostWeight',
json=payload,
headers=headers)
print(r.json())
```
```php PHP theme={"system"}
request(
'POST',
'https://api.ayrshare.com/api/post/checkPostWeight',
[
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer API_KEY'
],
'json' => [
'post' => ['🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩']
]
]
);
echo json_encode(json_decode($res->getBody()), JSON_PRETTY_PRINT);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
namespace CheckPostWeightRequest_csharp
{
class CheckPostWeight
{
static async Task Main(string[] args)
{
string API_KEY = "API_KEY";
string url = "https://api.ayrshare.com/api/post/checkPostWeight";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Add("Authorization", "Bearer " + API_KEY);
var content = new StringContent(
"{\"post\" : \"🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩🍩\"}",
Encoding.UTF8,
"application/json"
);
try
{
var response = await httpClient.PostAsync(url, content);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine(responseBody);
}
catch (HttpRequestException e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
}
```
```json 200: OK Character length results theme={"system"}
{
"twitterWeightedLength": 2932,
"blueskyWeightedLength": 199,
"instagramWeightedLength": 3015,
"tikTokWeightedLength": 3017,
"linkedInWeightedLength": 3015,
"facebookWeightedLength": 3015,
"pinterestWeightedLength": 3015,
"youtubeWeightedLength": 3015,
"gmbWeightedLength": 3015,
"twitterValid": false,
"twitterLongValid": true,
"facebookValid": true,
"gmbValid": false,
"instagramValid": false,
"linkedInValid": false,
"pinterestValid": false,
"redditValid": true,
"tikTokValid": false,
"youtubeValid": true,
"maxCharLimits": {
"bluesky": 300,
"facebook": 63206,
"gmb": 1500,
"instagram": 2200,
"linkedin": 3000,
"pinterest": 500,
"reddit": 10000,
"tiktok": 2200,
"twitter": 280,
"twitterLong": 25000,
"youtube": 5000
}
}
```
# Check Subreddit Exists
Source: https://www.ayrshare.com/docs/apis/validate/check-subreddit
GET /validate/redditExists/:subreddit
Check if a subreddit exists
## Header Parameters
## Path Parameters
The name of the subReddit to check if exists.
```json 200: Exists theme={"system"}
{
"status": "success",
"subReddit": "tesla",
"exists": true
}
```
```json 200: Does Not Exist theme={"system"}
{
"status": "success",
"subReddit": "jkhjkhjkhkjhj",
"exists": false
}
```
# Content Moderation
Source: https://www.ayrshare.com/docs/apis/validate/moderation
POST /validate/moderation
Check content to ensure it is not harmful or inappropriate
The content moderation API is designed to help developers identify potentially harmful or inappropriate text content.
This endpoint analyzes text input and categorizes it based on various types of concerning content.
## Key Features
Automatic detection of harmful content.
Multiple categories of problematic text.
Easy integration for content filtering.
## How It Works
When you submit text to the moderation endpoint, it uses OpenAI models to analyze the content. The API then returns results indicating whether the text falls into any of the defined problematic categories.
## Categories of Harmful Content
The API classifies text into the following categories:
| CATEGORY | DESCRIPTION |
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| hate | Content that expresses, incites, or promotes hate based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. Hateful content aimed at non-protected groups (e.g., chess players) is harassment. |
| hate/threatening | Hateful content that also includes violence or serious harm towards the targeted group based on race, gender, ethnicity, religion, nationality, sexual orientation, disability status, or caste. |
| harassment | Content that expresses, incites, or promotes harassing language towards any target. |
| harassment/threatening | Harassment content that also includes violence or serious harm towards any target. |
| self-harm | Content that promotes, encourages, or depicts acts of self-harm, such as suicide, cutting, and eating disorders. |
| self-harm/intent | Content where the speaker expresses that they are engaging or intend to engage in acts of self-harm, such as suicide, cutting, and eating disorders. |
| self-harm/instructions | Content that encourages performing acts of self-harm, such as suicide, cutting, and eating disorders, or that gives instructions or advice on how to commit such acts. |
| sexual | Content meant to arouse sexual excitement, such as the description of sexual activity, or that promotes sexual services (excluding sex education and wellness). |
| sexual/minors | Sexual content that includes an individual who is under 18 years old. |
| violence | Content that depicts death, violence, or physical injury. |
| violence/graphic | Content that depicts death, violence, or physical injury in graphic detail. |
## Usage and Best Practices
1. **Optimal Text Length**: For best results, we recommend splitting long text into smaller chunks. Aim for segments of less than 2,000 characters each.
2. **Integration**: Use this API to automatically flag potentially problematic content in your applications, forums, or user-generated content platforms.
3. **Action on Results**: Based on the API's output, you can implement appropriate actions such as content filtering, user warnings, or further review processes.
## Header Parameters
## Body Parameters
The text to analyze for moderation.
The URL of the image. Must begin with `https://`.
```bash cURL theme={"system"}
curl --location 'https://api.ayrshare.com/api/validate/moderation' \
--header 'Authorization: Bearer API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"text": "Let'\''s kill '\''em all"
}'
```
```javascript JavaScript theme={"system"}
const url = "https://api.ayrshare.com/api/validate/moderation";
const apiKey = "API_KEY"; // Replace with your actual API key
const data = {
text: "Let's kill 'em all",
};
fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${apiKey}`,
"Content-Type": "application/json",
},
body: JSON.stringify(data),
})
.then((response) => response.json())
.then((result) => console.log(result))
.catch((error) => console.error("Error:", error));
```
```python Python theme={"system"}
import requests
url = 'https://api.ayrshare.com/api/validate/moderation'
api_key = 'API_KEY' # Replace with your actual API key
headers = {
'Authorization': f'Bearer {api_key}',
'Content-Type': 'application/json'
}
data = {
'text': "Let's kill 'em all"
}
response = requests.post(url, json=data, headers=headers)
if response.status_code == 200:
result = response.json()
print(result)
else:
print(f"Error: {response.status_code}")
print(response.text)
```
```php PHP theme={"system"}
"Let's kill 'em all"
];
$headers = [
'Authorization: Bearer ' . $apiKey,
'Content-Type: application/json'
];
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_POST, true);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
$response = curl_exec($ch);
if (curl_errno($ch)) {
echo 'Error: ' . curl_error($ch);
} else {
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
if ($httpCode == 200) {
$result = json_decode($response, true);
print_r($result);
} else {
echo "Error: HTTP Code " . $httpCode . "\n";
echo $response;
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
url := "https://api.ayrshare.com/api/validate/moderation"
apiKey := "API_KEY" // Replace with your actual API key
// Create the request body
requestBody, err := json.Marshal(map[string]string{
"text": "Let's kill 'em all",
})
if err != nil {
fmt.Println("Error creating request body:", err)
return
}
// Create a new request
req, err := http.NewRequest("POST", url, bytes.NewBuffer(requestBody))
if err != nil {
fmt.Println("Error creating request:", err)
return
}
// Set headers
req.Header.Set("Authorization", "Bearer "+apiKey)
req.Header.Set("Content-Type", "application/json")
// Send the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
// Read the response
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response:", err)
return
}
// Check the status code
if resp.StatusCode == http.StatusOK {
fmt.Println("Response:")
fmt.Println(string(body))
} else {
fmt.Printf("Error: Status Code %d\n", resp.StatusCode)
fmt.Println(string(body))
}
}
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;
class Program
{
static async Task Main(string[] args)
{
string url = "https://api.ayrshare.com/api/validate/moderation";
string apiKey = "API_KEY"; // Replace with your actual API key
var data = new
{
text = "Let's kill 'em all"
};
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", $"Bearer {apiKey}");
var content = new StringContent(JsonSerializer.Serialize(data), Encoding.UTF8, "application/json");
try
{
HttpResponseMessage response = await client.PostAsync(url, content);
if (response.IsSuccessStatusCode)
{
string result = await response.Content.ReadAsStringAsync();
Console.WriteLine("Response:");
Console.WriteLine(result);
}
else
{
Console.WriteLine($"Error: {response.StatusCode}");
Console.WriteLine(await response.Content.ReadAsStringAsync());
}
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
Console.WriteLine($"InnerException: {e.InnerException?.Message}"); // Include inner exception details for more information
}
}
}
}
```
```json 200: Response theme={"system"}
{
"status": "success",
"text": "Let's kill 'em all",
"moderation": [
{
"flagged": true,
"categories": {
"sexual": false,
"hate": false,
"harassment": false,
"self-harm": false,
"sexual/minors": false,
"hate/threatening": false,
"violence/graphic": false,
"self-harm/intent": false,
"self-harm/instructions": false,
"harassment/threatening": false,
"violence": true
},
"categoryScores": {
"sexual": 0.00002128273445123341,
"hate": 0.027735227718949318,
"harassment": 0.08523011207580566,
"self-harm": 0.0000021838018255948555,
"sexual/minors": 1.924875903114298e-7,
"hate/threatening": 0.0063302298076450825,
"violence/graphic": 0.00024857991957105696,
"self-harm/intent": 7.833968993509188e-7,
"self-harm/instructions": 8.686130570367823e-8,
"harassment/threatening": 0.07459623366594315,
"violence": 0.9833663702011108
}
}
]
}
```
```json 400: Bad Request theme={"system"}
{
"action": "generate",
"status": "error",
"code": 331,
"message": "There was an issue with the AI processing. Please try again and if the issue persists, contact us."
}
```
# Validate API Overview
Source: https://www.ayrshare.com/docs/apis/validate/overview
Validate Social Posts and JSON
The Validate endpoints validate social posts and a JSON object.
The validate endpoints allow developers to check posts for potential issues or violations before publishing them to social media platforms.
This helps prevent failed posts by validating text length, media formats, and platform-specific rules.
For example, the endpoints can verify if a post passes validation, check if images meet size requirements, or see if there is a moderation issue.
This pre-validation helps improve post success rates and provides early feedback about potential issues.
# Validate JSON
Source: https://www.ayrshare.com/docs/apis/validate/validate-json
POST /validate/json
Send JSON to validate if correctly formatted
Send JSON to validate if correctly formatted.
You can validate your JSON by using either an online linter, such as [https://jsonlint.com/](https://jsonlint.com/) or using [Postman](/docs/testing/postman).
If you use a no-code tool such as Bubble or Make or receive a 500 "Bad Request" response, this endpoint is useful to debug the JSON request.
## Header Parameters
Send data as text. If using Postman, please be sure to select "Text" as the type.
Set the `"Content-Type": "text/plain"`.
## Request Examples
Send any json to this endpoint to validate it.
Below is an example of invalid JSON using Postman. Can you spot it? A missing comma at the end on the second parameter `platforms`.
Be sure to set the `Content-Type` in the header as `text/plain` and select "Text" when sending.
```json 200: OK Valid JSON theme={"system"}
{
"status": "success",
"message": "Valid JSON. Nice Job!"
}
```
```json 400: Bad Request Invalid JSON theme={"system"}
{
"status": "error",
"message": "JSON is not valid. Unexpected end of JSON input while parsing near '{\"test\": \"happy}'"
}
```
# Validate Media
Source: https://www.ayrshare.com/docs/apis/validate/validate-media
Check if a media URL is valid or get metadata about a media file
Please see here for more information on media URLs:
Verify that the media file exists and is accessible
Get metadata about a media file
# Validate a Post
Source: https://www.ayrshare.com/docs/apis/validate/validate-post
POST /validate/post
Validate a post before publishing
Before publishing a post, you can verify the content and parameters are correct.
Send the exact same JSON you normally send to the `/post` endpoint to the `/validate/post` endpoint and it will return a response with any issues found.
Validation tests based on Ayrshare's own internal algorithms.
Posts are not sent to the social networks.
Posts may still return an error by the social networks at the time of publishing, even with a
passed validation.
Please see the [/post endpoint](/docs/apis/post/overview) for sending a post.
## Header Parameters
## Body Parameters
Send the same body as you would send to the [/post endpoint](/docs/apis/post/post).
```bash cURL theme={"system"}
curl --location "https://api.ayrshare.com/api/validate/post" \
--header "Content-Type: application/json" \
--header "Authorization: Bearer API_KEY" \
--data '{
"post": "This is amazing",
"platforms": [
"facebook"
],
"mediaUrls": ["https://img.ayrshare.com/012/gb.jpg"]
}'
```
```javascript JavaScript theme={"system"}
const apiKey = 'API_KEY'; // Replace with your actual API key
const requestData = {
post: "This is amazing",
platforms: ["facebook"],
mediaUrls: ["https://img.ayrshare.com/012/gb.jpg"]
};
fetch('https://api.ayrshare.com/api/validate/post', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${apiKey}`
},
body: JSON.stringify(requestData)
})
.then(response => response.json())
.then(data => console.log(data))
.catch(error => console.error('Error:', error));
```
```python Python theme={"system"}
import requests
payload = {
'post': 'This is amazing',
'platforms': ['facebook'],
'mediaUrls': ['https://img.ayrshare.com/012/gb.jpg']
}
headers = {
'Content-Type': 'application/json',
'Authorization': 'Bearer API_KEY'
}
r = requests.post(
'https://api.ayrshare.com/api/validate/post',
json=payload,
headers=headers
)
print(r.json())
```
```php PHP theme={"system"}
'This is amazing',
'platforms' => ['facebook'],
'mediaUrls' => ['https://img.ayrshare.com/012/gb.jpg']
];
$headers = [
'Content-Type: application/json',
'Authorization: Bearer API_KEY'
];
$ch = curl_init('https://api.ayrshare.com/api/validate/post');
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload));
curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
$result = json_decode($response, true);
print_r($result);
```
```csharp C# theme={"system"}
using System;
using System.Net.Http;
using System.Net.Http.Json;
using System.Text.Json;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var payload = new
{
post = "This is amazing",
platforms = new[] { "facebook" },
mediaUrls = new[] { "https://img.ayrshare.com/012/gb.jpg" }
};
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("Authorization", "Bearer API_KEY");
try
{
var response = await client.PostAsJsonAsync(
"https://api.ayrshare.com/api/validate/post",
payload
);
response.EnsureSuccessStatusCode();
var result = await response.Content.ReadAsStringAsync();
Console.WriteLine(result);
}
catch (HttpRequestException ex)
{
Console.WriteLine($"Error: {ex.Message}");
}
}
}
```
```go Go theme={"system"}
package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"log"
"net/http"
)
type PostRequest struct {
Post string `json:"post"`
Platforms []string `json:"platforms"`
MediaUrls []string `json:"mediaUrls"`
}
func main() {
// Create the request payload
payload := PostRequest{
Post: "This is amazing",
Platforms: []string{"facebook"},
MediaUrls: []string{"https://img.ayrshare.com/012/gb.jpg"},
}
// Convert payload to JSON
jsonData, err := json.Marshal(payload)
if err != nil {
log.Fatalf("Error marshaling JSON: %v", err)
}
// Create the request
req, err := http.NewRequest(
"POST",
"https://api.ayrshare.com/api/validate/post",
bytes.NewBuffer(jsonData),
)
if err != nil {
log.Fatalf("Error creating request: %v", err)
}
// Set headers
req.Header.Set("Content-Type", "application/json")
req.Header.Set("Authorization", "Bearer API_KEY")
// Make the request
client := &http.Client{}
resp, err := client.Do(req)
if err != nil {
log.Fatalf("Error making request: %v", err)
}
defer resp.Body.Close()
// Read the response
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("Error reading response: %v", err)
}
// Print the response
fmt.Println(string(body))
}
```
```json 200: Success theme={"system"}
{
"status": "success",
"message": "No validation issues were found with this post. This is only an Ayrshare validation test and the post may still return an error by the social networks.",
}
```
```json 200: Successful Post with Non-Fatal Warnings theme={"system"}
{
"status": "success",
"message": "No validation issues were found with this post. This is only an Ayrshare validation test and the post may still return an error by the social networks.",
"warnings": [
{
"action": "post",
"status": "error",
"code": 156,
"message": "Twitter is not linked with Ayrshare. Please confirm the linkage on the Social Accounts page in your dashboard."
}
]
}
```
```json 400: Error Post theme={"system"}
{
"action": "post",
"status": "error",
"code": 136,
"message": "Media URLs invalid. Please verify the media is an externally accessible URL."
}
```
# Webhook Actions
Source: https://www.ayrshare.com/docs/apis/webhooks/actions
Webhook Actions and Events
There are several types of webhooks available and categorized by Action type.
For example, a scheduled post will trigger a `scheduled` action webhook.
Please see the [webhook overview](/docs/apis/webhooks/overview) for more details.
After registering a webhook URL, you will receive an POST request to your URL when an event occurs.
The POST request will include a JSON payload with the event details.
Scheduled Action
You will receive this webhook notification when a scheduled post is processed — whether it succeeds or fails — and published to the selected social networks.
For example, if you schedule a post for 12:00 PM on August 1, 2026, the webhook will be sent at the exact time the post is published.
Webhook notifications are only sent for posts scheduled in the future using the `scheduleDate` field in the [/post](/docs/apis/post/post) endpoint.
### Scheduled Event
```json theme={"system"}
{
"action": "scheduled", // The action taken
"subAction": "tikTokPublished", // Only present when TikTok video publishing complete
"created": "2023-01-05T01:18:47Z",
"code": 200, // HTTP response code
"refId": "140b8700bd6ade089b242d845e268fb886130c53", // User Reference ID
"status": "success", // success or error
"id": "TBAAAqAMMpoweA9wKHUp", // Ayrshare id of post
"errors": [], // List of errors if any occurred
"postIds": [
// Individual successful posts status
{
"postUrl": "https://www.facebook.com/102775127855689_361718068618052",
"platform": "facebook",
"status": "success",
"id": "102775127855689_361718068618052"
}
],
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
You will not receive a webhook notification for immediate posts, because the API returns the success or failure response instantly in the JSON reply.
Webhook notifications are only sent for scheduled posts, since these are processed asynchronously and require a separate notification to inform you of their status.
TikTok Publishing Webhook
When working with TikTok via Ayrshare, you might receive two different webhooks for a scheduled post.
If your post was scheduled rather than immediate, you'll receive the standard **Scheduled Action** webhook first.
This indicates that the media has been successfully sent to TikTok for processing and posting.
Afterwards, you will receive the `subAction: tikTokPublished` webhook.
This is triggered once TikTok has completed processing the media and the media is made public.
This webhook is activated for both immediate posts and scheduled posts.
In the Ayrshare dashboard, this event is labeled as **tikTok (pub)**.
The `tikTokPublished` webhook is not sent until the [media is made public](/docs/apis/post/social-networks/tiktok#visibility-options).
If the media is set to private, followers, or friends, the webhook will not be sent.
If you do not receive the `tikTokPublished` webhook and the post status remains `pending`, check the TikTok mobile app to ensure the media has been accepted by TikTok.
Social Action
Notification when a user's profile links or unlinks a social network.
### Social Action Event
```json theme={"system"}
{
"action": "social", // The action taken
"created": "2023-01-05T01:18:47Z",
"code": 200, // HTTP response code
"details": {
// Optional: if details available
"status": "error",
"code": 349,
"message": "Account locked"
},
"displayName": "Instagram Title", // If a user account name is present at the social network
"hookId": "TKLc30192HLGw5UeJ46",
"platform": "instagram", // The social platform the action occured
"refId": "140b8700bd6ade089b242d845e268fb886130c53", // User Reference ID
"refreshBy": "2022-11-05T12:21:29Z", // Optional: If type is refresh, the date the social network authorization must be refreshed on the social account linkage page
"source": "system", // Initiated by "system" or "user".
"title": "User Profile Name", // The user profile's account title
"type": "link", // Type of action: link, unlink, or refresh
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
A `source` of `system` means Ayrshare automatically unlinked the account, such as when the social network connection is no longer valid. We recommend you notify your user so they can continue posting. Details of the unlinking found `details` field. An email will also be sent to the Primary Account email address, or [alt emails](/docs/multiple-users/manage-user-profiles#alternative-emails-for-alerts) if they have been set up.
A `source` of `user` means the user initiated the action themselves, such as they manually unlinked an account. An email will not be sent when a user initiated action occurs.
Messages Action
The Messaging Add-On is required to access all messages endpoints and webhooks.
For Facebook and Instagram, receive notifications when a direct message arrives, is read, or has
a reaction created or deleted. WhatsApp currently sends a notification to your registered webhook
URL only when a new incoming message is stored.
X/Twitter webhooks are available as an option for Enterprise clients.
Please contact your account representative for more information about becoming an Enterprise client.
WhatsApp does not emit reaction or delivery-status webhooks to your registered URL today. Stored
outbound messages can have a `status` value of `sent`, `delivered`, `read`, or `failed` — see
[WhatsApp Message Status](#whatsapp-message-status) below.
### Standby coverage for Facebook Pages with multiple apps
Ayrshare subscribes to Facebook's `standby` webhook field in addition to the standard messaging fields. This means Messenger events are delivered to your webhook **even when another app on the same Facebook Page is currently holding thread control** — for example, when a chatbot platform is set as your Page's primary receiver, or when Meta's Page Inbox is actively handling a conversation.
There is no schema change for these events. They arrive as the same `messageCreated` / `messageRead` / `reactionCreated` / `messageEdited` payloads documented in the sections below. Two things to be aware of for Pages with a competing Messenger app installed:
* **Inbound message volume may increase** compared to the previous behavior, where standby events were silently dropped before being subscribed to. The new traffic represents messages your Page received that were being handled by the other app.
* **You may receive `messageCreated` events with `type: "sent"` that do not correspond to messages you sent through Ayrshare.** These are echoes of messages sent by the other Messenger app on your Page (Meta delivers a copy of every send to every subscribed app). If your integration reconciles outbound traffic against your own send history, you can use that history to distinguish your sends from a competing app's sends.
For Pages with only Ayrshare installed (no competing Messenger app), the only observable change is the new [Message Edit Event](#message-edit-event) — everything else looks identical to the previous behavior.
New Message Events
Notification when a new message is sent or received.
```json Facebook New Message theme={"system"}
{
"action": "messages",
"conversationId": "t_10161117434308936",
"created": "2024-06-07T11:58:44Z",
"hookId": "JC6IgqFjvDliTJ8MLqzE",
"id": "m_aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyMjEyNzA",
"mediaUrls": [],
"message": "This is an amazing message",
"platform": "facebook",
"recipientId": "7270633706358444",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"scheduleDate": "2024-06-07T11:58:44Z",
"senderDetails": {
// recipientDetails if type is sent
"id": "7270633706358444",
"picture": "https://scontent-ord5-2.cdninstagram.com/v/t51.jpg",
"username": "SweetMessage",
"name": "Sweet"
},
"senderId": "17841452212707444",
"subAction": "messageCreated",
"timeStamp": 1735189325, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "received", // received, sent, or deleted
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
```json Instagram New Message theme={"system"}
{
"action": "messages",
"conversationId": "aWdfZAG06MTpJR01lc3NhZA2VUaHJlYWQ6MTc4",
"created": "2024-06-07T11:58:44Z",
"hookId": "JC6IgqFjvDliTJ8MLqzE",
"id": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEOjE3ODQxNDUyMjEyNzA",
"mediaUrls": [],
"message": "This is an amazing message",
"platform": "instagram",
"recipientId": "7270633706358444",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"scheduleDate": "2024-06-07T11:58:44Z",
"senderDetails": {
// recipientDetails if type is sent
"id": "7270633706358444",
"picture": "https://scontent-ord5-2.cdninstagram.com/v/t51.jpg",
"username": "SweetMessage",
"name": "Sweet"
},
"senderId": "17841452212707444",
"subAction": "messageCreated",
"timeStamp": 1735189325, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "received", // received, sent, or deleted
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
```json WhatsApp New Message theme={"system"}
{
"action": "messages",
"attachments": [
{
"type": "image",
"url": "https://images.ayrshare.com/abc123/whatsapp_image_x9aB2pK7.jpg"
}
],
"conversationId": "14155551234",
"created": "2026-05-18T17:08:41Z",
"hookId": "JC6IgqFjvDliTJ8MLqzE",
"id": "wamid.HBgLMTQxNTU1NTEyMzQVAgARGBI4OUYxRkExNzE0M0EwQTYwM0EA",
"message": "Here's the photo you asked for.",
"platform": "whatsapp",
"recipientId": "123456789012345",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"senderDetails": {
"id": "14155551234",
"name": "Jane Customer"
},
"senderId": "14155551234",
"timeStamp": 1747588121,
"title": "Primary Profile",
"url": "https://mysite.com/webhook"
}
```
For WhatsApp, `conversationId` and `senderId` are the correspondent's phone number in E.164
digits-only format. `recipientId` is Meta's phone-number ID for your linked WhatsApp account.
`timeStamp` is present when Webhook Security is enabled. Media messages use `attachments` rather
than `mediaUrls`; attachment types can be `image`, `video`, `audio`, `document`, or `sticker`.
### Message Read Event
Notification when a message is read by the recipient.
```json Facebook Read theme={"system"}
{
"action": "messages",
"conversationId": "t_10161117434308936",
"created": "2024-06-08T23:33:30Z",
"hookId": "CviPBMXEy3cdJnK0EESd",
"platform": "facebook",
"read": 1717889607802, // UNIX timestamp of when the message was read
"readerDetails": {
"name": "John Smith",
"id": "7101149746568444",
"picture": "https://platform-lookaside.fbsbx.com/platform/profilepic"
},
"recipientId": "106638148652329",
"refId": "9abf1426d6ce9122ef11c8932",
"scheduleDate": "2024-06-08T23:33:30Z",
"senderId": "7101149746568522",
"subAction": "messageRead",
"timeStamp": 1717889610, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "read",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
```json Instagram Read theme={"system"}
{
"action": "messages",
"conversationId": "t_10161117434308938",
"created": "2024-06-08T23:33:30Z",
"hookId": "CviPBMXEy3cdJnK0EESd",
"platform": "instagram",
"read": {
"mid": "aWdfZAG1faXRlbToxOkl" // Instagram message ID
},
"readerDetails": {
"name": "John Smith",
"id": "7101149746568444",
"picture": "https://platform-lookaside.fbsbx.com/platform/profilepic",
"username": "johnsmith"
},
"recipientId": "106638148652329",
"refId": "9abf1426d6ce9122ef11c8932",
"scheduleDate": "2024-06-08T23:33:30Z",
"senderId": "7101149746568522",
"subAction": "messageRead",
"timeStamp": 1717889610, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "read",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
When a message is read on Instagram, the webhook payload includes an `mid` field that uniquely identifies which specific message was read.
For Facebook messages, message reads are tracked at the conversation level using the `conversationId`.
When a read event occurs, all messages in that conversation with timestamps before the `created` (or `read`) timestamp should be considered read by the user.
### Reaction Created and Deleted Events
Notification when a reaction, such as a like, is created or deleted on a message.
```json Facebook Reaction theme={"system"}
{
"action": "messages",
"conversationId": "t_10161117434308936",
"created": "2024-06-06T00:49:18Z",
"hookId": "LcgLuXzZki15lqBNt69h",
"mediaUrls": [],
"platform": "facebook",
"reaction": "😮",
"recipientId": "106638148652444",
"refId": "9abf1426d6ce9432",
"scheduleDate": "2024-06-06T00:49:18Z",
"senderId": "7101149746568444",
"subAction": "reactionCreated", // reactionDeleted if deleted
"timeStamp": 1717634958, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "reaction",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
```json Instagram Reaction theme={"system"}
{
"action": "messages",
"conversationId": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEO",
"created": "2024-06-06T00:49:18Z",
"hookId": "LcgLuXzZki15lqBNt69h",
"mediaUrls": [],
"platform": "instagram",
"reaction": "😮",
"recipientId": "106638148652444",
"refId": "9abf1426d6ce9432",
"scheduleDate": "2024-06-06T00:49:18Z",
"senderId": "7101149746568444",
"subAction": "reactionCreated", // reactionDeleted if deleted
"timeStamp": 1717634958, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "reaction",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
### Message Edit Event
Notification when a user edits a message they previously sent. Available for Facebook and Instagram direct messages.
The `messageEdit.mid` field matches the `id` of the original `messageCreated` event, so consumers can correlate the edit with the original message. The `messageEdit.text` field carries the new, edited message text.
```json Facebook Message Edit theme={"system"}
{
"action": "messages",
"conversationId": "t_10161117434308936",
"created": "2024-06-06T00:49:18Z",
"hookId": "LcgLuXzZki15lqBNt69h",
"id": "m_xyz...", // Message ID — matches the original messageCreated event
"messageEdit": {
"mid": "m_xyz...",
"text": "the edited message text"
},
"platform": "facebook",
"recipientId": "106638148652444",
"refId": "9abf1426d6ce9432",
"senderId": "7101149746568444",
"subAction": "messageEdited",
"timeStamp": 1717634958, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "edit",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
```json Instagram Message Edit theme={"system"}
{
"action": "messages",
"conversationId": "aWdfZAG1faXRlbToxOklHTWVzc2FnZAUlEO",
"created": "2024-06-06T00:49:18Z",
"hookId": "LcgLuXzZki15lqBNt69h",
"id": "aWdfZAG1faXRlbToxOkl",
"messageEdit": {
"mid": "aWdfZAG1faXRlbToxOkl",
"text": "the edited message text"
},
"platform": "instagram",
"recipientId": "106638148652444",
"refId": "9abf1426d6ce9432",
"senderId": "7101149746568444",
"subAction": "messageEdited",
"timeStamp": 1717634958, // Present if Webhook Security enabled
"title": "Primary Profile",
"type": "edit",
"url": "https://mysite.com/webhook" // Your webhook URL
}
```
### WhatsApp Message Status
WhatsApp tracks per-message delivery state on stored outbound messages using one `status` field:
`sent`, `delivered`, `read`, or `failed`. These updates are **not currently delivered to your
registered webhook URL** as separate events. If you need real-time delivery state, please contact
your Ayrshare account representative.
Batch Action
Notification when a batch has completed processing and the file is available, such as [get all user profiles](/docs/apis/user/batch-all-users). You may access the file with the pre-signed URL in the `url` field.
### Batch Event
```json theme={"system"}
{
"action": "batch",
"batchType": "users",
"created": "2024-01-11T22:00:30Z",
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"source": "user",
"timeStamp": 1705010424, // Present with Webhook Security
"title": "Primary Profile",
"type": "batch",
"url": "https://storage.googleapis.com/batch.ayrshare.com/users/dfdf92jskd933r/users-batch-2024-01-11-22-00.json",
"urlExpires": "2024-01-18T22:00:04Z",
"userCount": 73
}
```
Feed Action
Notification when a new RSS feed item is found for registered RSS feeds. Note: if the Webhook is active, new RSS items will not be automatically posted to the social networks.
### Feed Event
```json theme={"system"}
{
"action": "feed",
"created": "2023-01-05T01:18:47Z",
"code": 200, // HTTP response code
"refId": "140b8700bd6ade089b242d845e268fb886130c53", // User Reference ID
"title": "Title of profile if available", // optional, only if available
"data": { ... },
"url": "https://api.myapp.com/Webhook/Ayrshare/Feed" // Your webhook URL
}
```
Mentions Action
Notification when your connected account is mentioned. Available for Facebook and Instagram.
For Instagram, registering the `mentions` webhook is all that is required to receive mention events. The Messaging Add-On, messaging enablement, and relinking the social account are **not** needed.
Ayrshare relays Meta's native mention payload unchanged, adding only the standard envelope fields (`action`, `refId`, `hookId`, `url`, and `timeStamp` with Webhook Security) and `subAction`. The example below is the **Instagram** shape: `media_id`, plus `comment_id` when the mention is in a comment. **Facebook** Page mention events are **not currently delivered** — Ayrshare acknowledges them from Meta and does not forward them to your webhook. Only Instagram mentions are delivered today.
### Mention Event (Instagram)
```json theme={"system"}
{
"action": "mentions",
"subAction": "mention",
"media_id": "17900000000000000", // Meta media the mention occurred on
"comment_id": "17900000000000001", // Present when the mention is in a comment
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083", // User Reference ID
"timeStamp": 1705010424, // Present with Webhook Security
"url": "https://api.myapp.com/Webhook/Ayrshare/Mentions" // Your webhook URL
}
```
Comments Action
Notification when a comment is created on your connected content. Available for Facebook and Instagram.
For Instagram, registering the `comments` webhook is all that is required to receive comment events. The Messaging Add-On, messaging enablement, and relinking the social account are **not** needed.
Ayrshare relays Meta's native comment payload unchanged, adding only the standard envelope fields (`action`, `refId`, `hookId`, `url`, and `timeStamp` with Webhook Security) and `subAction`. The example below is the **Instagram** shape. **Facebook** comments arrive as a Page `feed` change with different field names (for example `comment_id`, `post_id`, `message`, and `from.name`); consult Meta's webhooks reference for the Facebook field set.
### Comment Event (Instagram)
```json theme={"system"}
{
"action": "comments",
"subAction": "comment",
"id": "17900000000000002", // Comment ID
"text": "Great post!",
"from": {
"id": "1234567890",
"username": "alice"
},
"media": {
"id": "17900000000000000", // ID of the commented media
"media_product_type": "FEED" // e.g. FEED, REELS, STORY
},
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083", // User Reference ID
"timeStamp": 1705010424, // Present with Webhook Security
"url": "https://api.myapp.com/Webhook/Ayrshare/Comments" // Your webhook URL
}
```
## Automations Action
Notification when an automation fires a webhook action for a user, such as a comment or DM auto-reply trigger.
### Automation Event
```json theme={"system"}
{
"action": "automations",
"automationId": "a1B2c3D4",
"triggerId": "t9X8y7Z6",
"trigger": "comment_keyword", // The trigger type that fired the automation (varies by automation)
"platform": "instagram",
"recipientId": "17841400000000000",
"recipientUsername": "alice", // null if unavailable
"keyword": "INFO", // null if not keyword-triggered
"timestamp": "2026-05-27T22:00:30Z", // When the automation fired (ISO 8601)
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083", // User Reference ID
"timeStamp": 1705010424, // Unix timestamp, present with Webhook Security
"url": "https://api.myapp.com/Webhook/Ayrshare/Automations" // Your webhook URL
}
```
## Demo Action
Notification for [Demo User Profile](/docs/apis/profiles/overview#demo-user-profiles) lifecycle events. Demo User Profiles are available on the Enterprise plan; please [contact us](mailto:support@ayrshare.com) if you'd like to learn more.
Two event types are sent on the `demo` action, distinguished by the `type` field:
* `upgradeWarning` — sent two days before a Demo User Profile automatically converts to a standard User Profile, so you can prompt your user to continue or remove the profile.
* `upgrade` — sent when the conversion happens.
### Demo Upgrade Warning Event
```json theme={"system"}
{
"action": "demo",
"type": "upgradeWarning",
"demoExpires": "2026-08-27T09:57:00.000Z", // When the profile converts (ISO 8601)
"daysUntilUpgrade": 2,
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083", // User Reference ID
"timeStamp": 1787734624, // Unix timestamp (2026-08-26), present with Webhook Security
"url": "https://api.myapp.com/Webhook/Ayrshare/Demo" // Your webhook URL
}
```
### Demo Upgrade Event
```json theme={"system"}
{
"action": "demo",
"type": "upgrade",
"upgradedAt": "2026-08-28T08:57:04.000Z", // When the profile converted (ISO 8601)
"hookId": "dI3PNhrG83j2FzAFJqkb",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083", // User Reference ID
"timeStamp": 1787907424, // Unix timestamp (2026-08-28), present with Webhook Security
"url": "https://api.myapp.com/Webhook/Ayrshare/Demo" // Your webhook URL
}
```
# Webhook History
Source: https://www.ayrshare.com/docs/apis/webhooks/history
GET /hook/history
Get webhook delivery history grouped by action
## Webhook History
Retrieve recent webhook delivery history grouped by action type.
The response object contains keys for each action (e.g., `social`, `scheduled`, `messages`, `feed`, `batch`, `mentions`, `comments`, `automations`, `demo`), and each key maps to an array of events.
## Header Parameters
## Query Parameters
The webhook action to return history for the last 6 months. If not provided, all actions will be returned.
Available actions: `social`, `scheduled`, `messages`, `feed`, `batch`, `mentions`, `comments`, `automations`, `demo`
```json 200: Response theme={"system"}
{
"social": [
{
"action": "social",
"created": "2025-09-05T23:13:08Z",
"displayName": "ayrshare",
"hookId": "6e4zPT9ozQpxD72WX78r",
"platform": "snapchat",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"source": "user",
"timeStamp": 1757166928,
"title": "Primary Profile",
"type": "link",
"url": "https://us-central1-ayrshare.cloudfunctions.net/testFeed"
},
{
"action": "social",
"created": "2025-09-05T23:13:00Z",
"displayName": "madworlds25",
"hookId": "UWURsgBxTdRAMCZJV4Yp",
"platform": "snapchat",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"source": "user",
"timeStamp": 1757166928,
"title": "Primary Profile",
"type": "unlink",
"url": "https://us-central1-ayrshare.cloudfunctions.net/testFeed"
}
],
"scheduled": [
{
"action": "scheduled",
"created": "2025-09-06T17:02:08Z",
"errors": [],
"hookId": "AxGbVck3Y7hsOdbAqVp7",
"id": "NAOWq7cQf1CsyT7vqTng",
"idShare": "v_pub_url~v2.7547022225119938615",
"isVideo": true,
"mediaUrls": [
"https://img.ayrshare.com/random/portrait8.mp4"
],
"platform": "tiktok",
"platforms": [
"tiktok"
],
"post": "Wise men talk because they have something to say; fools, because they have to say something. - Plato",
"postIds": [
{
"status": "success",
"idShare": "v_pub_url~v2.7547022225119938615",
"id": "7547022158694731022",
"isVideo": true,
"platform": "tiktok",
"postUrl": "https://www.tiktok.com/@helmar1066/video/7547022158694731022",
"mediaUrls": [
"https://img.ayrshare.com/random/portrait8.mp4"
]
}
],
"postUrl": "https://www.tiktok.com/@helmar1066/video/7547022158694731022",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"source": "user",
"status": "success",
"subAction": "tikTokPublished",
"timeStamp": 1757180499,
"title": "Primary Profile",
"url": "https://us-central1-ayrshare.cloudfunctions.net/testFeed"
},
{
"action": "scheduled",
"created": "2025-09-05T11:26:07Z",
"errors": [],
"hookId": "D92f6fMh2FCxNps4S27O",
"id": "2Is9BJkDdoBv01K4nZ2k",
"idShare": "v_pub_url~v2.7546563700132497463",
"isVideo": true,
"mediaUrls": [
"https://img.ayrshare.com/random/portrait6.mp4"
],
"platform": "tiktok",
"platforms": [
"tiktok"
],
"post": "Either write something worth reading or do something worth writing. - Benjamin Franklin",
"postIds": [
{
"status": "success",
"idShare": "v_pub_url~v2.7546563700132497463",
"id": "7546564355161099533",
"isVideo": true,
"platform": "tiktok",
"postUrl": "https://www.tiktok.com/@helmar1066/video/7546564355161099533",
"mediaUrls": [
"https://img.ayrshare.com/random/portrait6.mp4"
]
}
],
"postUrl": "https://www.tiktok.com/@helmar1066/video/7546564355161099533",
"refId": "9abf1426d6ce9122ef11c72bd62e59807c5cc083",
"source": "user",
"status": "success",
"subAction": "tikTokPublished",
"timeStamp": 1757180499,
"title": "Primary Profile",
"url": "https://us-central1-ayrshare.cloudfunctions.net/testFeed"
}
]
}
```
# List Registered Webhooks
Source: https://www.ayrshare.com/docs/apis/webhooks/list
GET /hook/webhook
List the registered webhooks
## Header Parameters
## Query Parameters
Return all registered webhooks for every User Profile associated with your account, including the Primary Profile.
You only need to provide the Primary Profile's API Key in the request header.
```json 200: Response theme={"system"}
{
"batch": "https://mywebsite.com/hook",
"batchUpdated": "2024-01-11T20:05:18Z",
"feedUpdated": "2024-01-11T18:20:50Z",
"refId": "1c72bd62e59807fdfdc5cc083",
"scheduled": "https://mywebsite.com/hook",
"scheduledUpdated": "2023-12-06T01:54:08Z",
"social": "https://mywebsite.com/hook",
"socialUpdated": "2023-10-26T03:20:46Z",
"status": "success",
"updated": "2024-01-11T18:20:51Z"
}
```
```json 200: Using allWebhooks theme={"system"}
{
"webhooks": [
{
"messages": "https://mywebsite.com/hook",
"messagesUpdated": "2024-12-11T09:58:22Z",
"refId": "d0b8bf39805ae442094137f09f2417bf2s82",
"scheduled": "https://mywebsite.com/hook",
"scheduledUpdated": "2024-02-19T12:17:12Z",
"status": "success",
"updated": "2023-08-22T11:55:06Z"
}
]
}
```
# Webhooks Overview
Source: https://www.ayrshare.com/docs/apis/webhooks/overview
Webhook API Endpoints to register webhooks to receive updates on events
## What is a Webhook?
A Webhook allows you to be notified when certain system *actions* occur via a call to a URL you provide. Webhooks are also known as "URL Callbacks" or "HTTP push calls". Your URL must use SSL and begin with HTTPS.
See the available actions for webhooks.
### Understanding Ayrshare Webhooks
Webhooks are categorized by the specific action and are *registered at the Primary Profile or User Profile level*. Any updates for the Primary or User Profiles are sent first to the registered Webhook for the User Profile. If User Profile does not have a registered Webhook, the update will be sent to the Primary Profile registered Webhook.
For example:
If a User Profile has a registered Social Action Webhook and unlinks TikTok,
the registered Social Action Webhook URL for the User Profile will be
called. The Primary Profile webhook *will not* be called.
If a User Profile unlinks TikTok and *does not* have a registered Social
Action Webhook, but the Primary Profile does have a registered Webhook, the
registered Social Action Webhook URL for the Primary Profile will be called.
### Register a Webhook
Register a Webhook by providing an endpoint URL and the type of action type to the POST [`/hook/webhook`](/docs/apis/webhooks/register) endpoint. When the action occurs an `HTTP POST` message will be sent to the provided URL.
E.g. register a URL to get notified of the status of scheduled post.
The Webhook endpoint URL should not use redirects and must be the final destination URL.
If you only register the Primary Profile webhook, the User Profiles will automatically inherit the Primary Profile webhook.
To have a unique webhook for each User Profile, you must register a webhook for each User Profile.
After your Webhook receives the `HTTP POST`, your server **must** respond with
an HTTP status of `200` to mark the call as successful. If your server does
not respond within 15 seconds, the attempt is recorded as failed and
retried. Respond as soon as you receive the request and do your processing
asynchronously — a timeout is not a rejection, so if your handler completes
the work but answers late, the retry will make you process it twice.
You can also register webhooks in the Developer Dashboard.
### Webhook Retries
If the HTTP response from your server is not in the `200-299` success range, or your server does not respond within 15 seconds, the system will automatically retry the Webhook call two more times. The first retry will occur after 5 seconds and the second retry will occur 30 seconds later. The retries will have the same `hookId` and the same payload.
### Delivery Semantics and Idempotency
Ayrshare delivers webhooks **at least once**. **Occasional duplicates are normal operation, not a defect — every consumer needs idempotency as a permanent property.**
Duplicates arrive in two different shapes, and each needs a different key:
| Duplicate | Why it happens | What is identical | Key that catches it |
| --------------------------------- | ---------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- | -------------------------------- |
| **A retry of one delivery** | Your endpoint answered outside `200-299`, timed out, or the connection dropped | `hookId` **and** the whole payload, byte for byte | `hookId` |
| **The same event notified again** | The social network sends us the event a second time, or it is re-observed upstream | The payload's own identifiers, such as `id` on `messages` — but `hookId` is **different** | a key you build from the payload |
`hookId` identifies **one delivery** of an event. It is identical on every retry of that delivery, so claiming on it makes retries safe — but a fresh notification of the same underlying event arrives with a **new** `hookId`, so `hookId` on its own will not recognise that case.
Recommended receiver pattern:
1. **Respond first.** Return `2xx` immediately, then process asynchronously. A timeout is not a rejection — if you finish the work but answer late, the event is sent again.
2. **Claim `hookId` atomically** the moment the request arrives — a unique constraint, an `INSERT ... ON CONFLICT DO NOTHING`, or a `SET NX` — **not** a read-then-write check. Two attempts can arrive concurrently, and a check-then-act guard lets both through.
3. **Claim a key of your own too**, built from the payload, so a second notification carrying a new `hookId` is still recognised. On `messages`, `id` combined with `subAction` works well.
4. **Then** do the work, holding both claims long enough to cover the retry window and any later re-notification.
The payload's `id` is not unique on its own for every event type — the same
message id recurs across edits and reactions, and `messageRead` payloads carry
no `id` — so combine it with `subAction` rather than using it bare.
### Delivery Metadata Headers
Every delivery carries two headers identifying that specific transmission, so you can tell an original from a retry:
```bash theme={"system"}
X-Ayrshare-Delivery-Id :
X-Ayrshare-Delivery-Attempt : <0 on the first send, then 1, 2, ...>
```
`X-Ayrshare-Delivery-Attempt` is `0` on the first send and increments by one on each retry, so any value above `0` means we have already sent this delivery at least once. Treat it as an unbounded counter rather than a fixed set of values — the number of retries is an operational detail that can change. `X-Ayrshare-Delivery-Id` is unique to each attempt — quote it to support and it identifies the exact delivery record.
These identify the **transmission**; `hookId` identifies the **event**. Deduplicate on `hookId`, not on the delivery id — the delivery id is different on every attempt by design, so nothing would ever be recognised as a duplicate.
## Webhook Security
You may choose to add additional security by setting HMAC authentication as an HTTP request. This is often done to prevent replay attacks. Ayrshare uses [HMAC-SHA256](https://en.wikipedia.org/wiki/HMAC) to hash the body of the message and includes it and the UNIX timestamp in the header of the POST.
```bash theme={"system"}
X-Authorization-Timestamp :
X-Authorization-Content-SHA256 :
```
Based on a secret key set when [registering your webhook](/docs/apis/webhooks/register), you may validate the post by comparing the header `X-Authorization-Content-SHA256` with the HMAC-SHA256 of the POST body. The signing secret is profile-wide — one secret per User Profile, used across all of that profile's webhook actions, so setting it for one action changes it for all actions on that profile. Multi-profile accounts manage a separate secret per profile (target a profile with the `Profile-Key` header).
## Webhook Logs
In the Ayrshare Dashboard, you may view the [active webhooks](https://app.ayrshare.com/webhooks), see the details of the Webhook sent, your server response status, and resend the Webhook to the registered URL.
Switch to a particular User Profile to view that profile's Webhook logs.
### HTTP Response Codes
The first column indicates a successful HTTP response ✔️ (200, 300) from the Webhook or a failed response ✖️ (400, 500).
Switch to a particular user profile to view that profile's Webhook logs.
### Error Rate
The "Error Rate" of the most recent 1,000 posts can be viewed on both the Actions and Webhook Logs pages within the dashboard. Any webhook response from your server of 400-500 is considered an error.
# Register Webhook
Source: https://www.ayrshare.com/docs/apis/webhooks/register
POST /hook/webhook
Register a new Webhook
## Register Webhook
Register a new Webhook for one of the [available actions](/docs/apis/webhooks/actions).
A Webhook may be registered with the Primary Profile or a User Profile.
You may also register a webhook in the Ayrshare dashbboard on the Webhooks page.
## Header Parameters
## Body Parameters
Available actions: `feed`, `social`, `scheduled`, `batch`, `messages`, `mentions`, `comments`, `automations`
The URL to be called on action. URL must be in a valid format and begin with *https\://*
Secret text used for HMAC. Please see [overview](/docs/apis/webhooks/overview#webhook-security) for more details.
```json 200: Response theme={"system"}
{
"status": "success",
"action": "scheduled",
"url": "https://mysite.com/hook",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
```
# Rotate Signing Secret
Source: https://www.ayrshare.com/docs/apis/webhooks/rotate-signing-secret
POST /hook/webhook/secret
Safely rotate your webhook signing secret with a 24-hour dual-signing grace window
## Overview
Ayrshare signs every webhook delivery with an [HMAC-SHA256](https://en.wikipedia.org/wiki/HMAC) of the payload, keyed by your **signing secret**, so your receiver can confirm a delivery genuinely came from Ayrshare. See [Webhook Security](/docs/apis/webhooks/overview#webhook-security) for how verification works.
Rotating your signing secret lets you replace it on a regular schedule, or immediately if you suspect it has been exposed. To make rotation safe, Ayrshare opens a **24-hour grace window** after every rotation during which deliveries are signed with **both** your previous and your new secret. This lets you update your receiver on your own schedule without dropping or rejecting a single delivery — the same pattern used by Stripe and GitHub.
The signing secret is **profile-wide**: there is one secret per User Profile (UID),
and it signs **every** webhook action that profile has registered. There is no
per-action signing secret — setting or rotating the secret changes it for all
actions on that profile at once.
## Rotate from the Dashboard
You can set or rotate your signing secret from the [Webhooks page](https://app.ayrshare.com/webhooks) in the Developer Dashboard. The **Signing Secret** panel appears above your webhook list once the profile has at least one registered webhook.
Go to the [Webhooks page](https://app.ayrshare.com/webhooks). If no secret is configured yet, the panel shows **No signing secret configured** with a **Set Signing Secret** button. If one is already configured, it shows **Signing secret configured** with a **Rotate** button.
Click **Set Signing Secret** (first-time) or **Rotate** (existing secret). A modal opens with a strong, randomly generated secret pre-filled and revealed. You can **Copy** it, **Regenerate** a new one, or toggle **paste my own** to supply your own value.
Copy the secret somewhere safe — it is shown only once and can never be retrieved from the UI again — then confirm to submit. A success toast appears and the panel updates.
On a rotation (not a first-time set), the panel shows an active grace-window indicator and the **Rotate** button is disabled until the window closes. You have 24 hours to deploy the new secret to your receiver.
## Rotate via the API
Rotate (or set) the signing secret with a single call. This creates a new secret, repoints the profile's secret reference to it, and — when an existing secret was in place — records the superseded secret as the previous secret with an expiry 24 hours out.
### Header Parameters
### Body Parameters
The new signing secret value. Any non-empty string is accepted. We recommend a long, high-entropy random value (for example, 32 random bytes encoded as base64url).
```bash cURL theme={"system"}
curl --request POST \
--url https://api.ayrshare.com/api/hook/webhook/secret \
--header 'Authorization: Bearer YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--header 'Profile-Key: YOUR_PROFILE_KEY' \
--data '{
"secret": "your-new-signing-secret"
}'
```
```json 200: Response theme={"system"}
{
"status": "success",
"action": "webhook",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
```
The plaintext `secret` is **never** returned in the response and is never logged. The response carries the client-facing `refId` (a hash of the UID), never the UID itself. The `Profile-Key` header is optional and scopes the rotation to a single User Profile for multi-profile accounts.
A missing or empty `secret` returns a mapped error (`code: 101`, "Missing/incorrect parameter") with an HTTP `400` status, and no change is made to your current secret. First-time set via the API (no existing secret) creates the secret with no previous secret recorded and no grace window.
## Safe Rotation Procedure
Because of the 24-hour grace window, there is no required order of operations — your receiver keeps working throughout. The recommended sequence is:
Rotate from the dashboard or via the API. Ayrshare immediately begins signing deliveries with both your previous and your new secret.
Within 24 hours, deploy the new secret to your webhook receiver so it verifies against the new value.
After 24 hours, Ayrshare automatically clears the previous secret and signs only with the new secret. No further action is needed on your side.
If you rotate again while a grace window is still open, the just-superseded
secret becomes the new previous secret and a fresh 24-hour window starts. Only
one previous secret is kept at a time.
## Verifying Signatures During the Grace Window
Outside of a grace window, signed deliveries carry the standard headers (see [Webhook Security](/docs/apis/webhooks/overview#webhook-security)):
```bash theme={"system"}
X-Authorization-Timestamp :
X-Authorization-Content-SHA256 :
X-Authorization-Content-SHA256-V2 : v1=
```
During the 24-hour window after a rotation, the new `X-Authorization-Content-SHA256-V2` header lists **both** signatures, current first, comma-separated:
```bash theme={"system"}
X-Authorization-Timestamp :
X-Authorization-Content-SHA256 :
X-Authorization-Content-SHA256-V2 : v1=,v1=
```
`X-Authorization-Content-SHA256` is unchanged: it always carries the single
current-secret HMAC, for backward compatibility. Dual signatures appear only in
the new `X-Authorization-Content-SHA256-V2` header.
Each value in `X-Authorization-Content-SHA256-V2` is prefixed with a scheme tag. `v1=` denotes an HMAC-SHA256 signature, computed exactly like `X-Authorization-Content-SHA256`. The `-V2` header is always present whenever a delivery is signed — it carries at least `v1=` — so you can rely on it as a stable receiver contract.
To verify a delivery during (or outside) a rotation:
Compute the HMAC-SHA256 of the **raw request body** using your locally configured signing secret.
Read `X-Authorization-Content-SHA256-V2`, split it on commas, strip the `v1=` prefix from each value, and accept the delivery as authentic if your computed HMAC matches **any** listed `v1=` signature.
Accepting if **any** listed signature matches is what makes rotation zero-downtime: a receiver still configured with the old secret matches `v1=`, while a receiver updated to the new secret matches `v1=` — both succeed throughout the window.
### Receiver Verification Example
```javascript Node.js theme={"system"}
import crypto from "crypto";
// secret is the signing secret currently configured on your receiver.
function isAuthenticWebhook(rawBody, headers, secret) {
const expected = crypto
.createHmac("sha256", secret)
.update(rawBody) // the raw, unparsed request body
.digest("hex");
const headerValue = headers["x-authorization-content-sha256-v2"] || "";
// Accept if ANY v1= signature in the header matches our computed HMAC.
return headerValue
.split(",")
.map((part) => part.trim())
.filter((part) => part.startsWith("v1="))
.map((part) => part.slice("v1=".length))
.some((sig) => {
const sigBuf = Buffer.from(sig);
const expectedBuf = Buffer.from(expected);
// timingSafeEqual throws on length mismatch — treat as not authentic.
return (
sigBuf.length === expectedBuf.length &&
crypto.timingSafeEqual(sigBuf, expectedBuf)
);
});
}
```
Always compute the HMAC over the **raw** request body bytes, exactly as
received — not over a re-serialized JSON object. Re-serialization can change
whitespace or key order and break verification. Use a constant-time comparison
(such as `crypto.timingSafeEqual`) to avoid timing attacks.
If a delivery's current secret record is missing, the delivery proceeds **unsigned** (no signature headers) rather than failing. If only the previous secret record is gone, the previous signature is skipped and the current signature is still emitted in both headers.
# Unregister Webhook
Source: https://www.ayrshare.com/docs/apis/webhooks/unregister
DELETE /hook/webhook
Unregister a Webhook associated with an action
Unregister the webhook associated with the action.
## Header Parameters
## Body Parameters
Available actions: `feed`, `social`, `scheduled`, `batch`, `messages`, `mentions`, `comments`, `automations`
```json 200: Response theme={"system"}
{
"status": "success",
"action": "scheduled",
"refId": "3dc079614bdc3f281d9" // User Profile Ref Id
}
```
# RSS, Substack, and YouTube Feeds
Source: https://www.ayrshare.com/docs/dashboard/automated-rss-feeds
Automate posting with any RSS feed such as Wordpress, Substack, NY Times, or your own; add a YouTube Channel Feed to automate your new video posts.
You can subscribe to any RSS feed, including Wordpress, Substack, or YouTube, and Ayrshare will automatically post all new articles and entries. New entries are checked every 10 minutes.
Posts are sent to your connected social accounts: `Bluesky`, `Facebook`, `Instagram`, `LinkedIn`, `Pinterest`, `Snapchat`, `Telegram`, and `Threads`.
Instagram and Pinterest are sent if a [valid image](/docs/media-guidelines/overview) that meets the dimension requirements is found in the article.
Snapchat additionally requires **Use First Image** to be enabled on the feed, because Snapchat cannot publish a post without media. With that option off, Snapchat entries will not publish.
Why only these networks?
A feed publishes on its own, on a schedule, from whatever the article happens to contain. Networks that need something extra at post time can't be filled in automatically:
**Reddit** needs a target subreddit and often a flair.
**TikTok** and **YouTube** need a video file, which an article doesn't provide.
**Google Business Profile** needs a location and a post type.
**X/Twitter is no longer supported for feeds.** As of March 31, 2026, X requires your own API credentials on every request. Those credentials are supplied per request, and a feed publishes from a schedule with no request to carry them — so feeds cannot post to X, whether or not you have [BYO credentials](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) set up. To post your articles to X, use [scheduled posts](/docs/apis/post/overview#schedule-posts) or a direct API call with your own credentials.
To reach any of these networks from a feed, publish the entry yourself with [scheduled posts](/docs/apis/post/overview#schedule-posts) or the [post API](/docs/apis/post/overview).
The RSS feed is checked approximately every 10 minutes for a new post. After adding your RSS
feed, it might take up to 15 minutes to see your first post.
Please also be sure the RSS feed is responsive. The data must return within 5 seconds to be
processed. If it takes longer than 5 seconds to download your RSS feed, the feed will not be
processed.
### Add an RSS Feed
Start by adding your RSS feed in the "RSS Feed" section of the [dashboard](https://app.ayrshare.com). Find the RSS URL of your site by either Googling or adding /rss or /feed to the end of the URL.
Be sure the URL begins with `http://` or `https://`.
#### Substack RSS Example
For example, get your Substack RSS feed by taking your Substack base URL and adding "feed" at the end. Base URL + /feed: `https://www.imfineimfine.com/feed`
You will see the text display of the Substack RSS feed if successful.
#### Wordpress RSS Example
You can find your Wordpress RSS feed by trying the following URLs with your root domain being example.com:
### Auto Hashtags
Enable this option to automatically add up to three relevant hashtags to your posts.
The system analyzes your content to identify the most important keywords and converts them into trending hashtags based on real-time popularity data.
This helps increase your post's discoverability and engagement on social platforms.
### Use First Image
Select this option to extract the first or top image from the article and automatically add it to the post. For example, if a first image is found and you have connected Instagram, the image will be shared on Instagram with the article's text summary.
### Active RSS Feeds
Once you add the RSS feed you will see it listed in the Active section.
### Delete an RSS Feed
You can delete the feed by clicking on the red trashcan or see the main site by clicking on the URL.
### Using the API
You can add and delete RSS feeds with the API. Please see the endpoint.
### Add a YouTube Feed
Ayrshare also allows you to integrate with a YouTube channel to automate posting. In the dashboard click on "YouTube Channels".
Next, go to YouTube and select a channel. Copy the channel URL. For example: [https://www.youtube.com/c/TomScottGo](https://www.youtube.com/c/TomScottGo)
In the dashboard, paste this URL into the "Add a YouTube Channel".
Click *Add YouTube* and the YouTube Channel feed will be added. New YouTube videos posted to this channel will automatically post to your active social networks.
#### Issues Finding Your YouTube Channel
The YouTube URL to your channel is oftentimes a vanity URL and not your real channel ID. For example, [https://www.youtube.com/@ayrshare](https://www.youtube.com/@ayrshare) is a vanity URL, while the real channel URL is [https://www.youtube.com/channel/UCvVNc5oXfyD7yOIFgoY1HqQ](https://www.youtube.com/channel/UCvVNc5oXfyD7yOIFgoY1HqQ)
If you have issues adding your YouTube feed, try the following steps:
Find by clicking your profile icon in the upper right corner at youtube.com and clicking **Your Channel**.
The URL should change to `https://www.youtube.com/channel/` followed by a number.
Copy this full URL and try adding it as your YouTube RSS feed.
If you still have trouble:
Manually find your [YouTube Channel ID](https://support.google.com/youtube/answer/3250431).
Submit the following URL as your YouTube RSS feed:
`https://www.youtube.com/channel/**YOUR_CHANNEL_ID**` replacing `YOUR_CHANNEL_ID` with your
actual channel id gathered in the previous step.
### Find Your RSS Feed
Use our search tool to find your RSS feed:
### RSS Feed API
See our RSS feed endpoint for using the API to set and delete RSS feeds:
# Bluesky Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/bluesky
Authorizing Bluesky with Ayrshare
## How to Link Bluesky with Ayrshare
Authorizing Bluesky with Ayrshare is simple. You will need to enter your Bluesky handle and a one-time app password.
The Bluesky app password is used to sign in to other Bluesky clients without giving full access to your account or password.
You will create this one-time app password in settings section of Bluesky and in the format of XXXX-XXXX-XXXX-XXXX.
**The app password is not your Bluesky password you use to sign in to Bluesky.**
Please see below for more information.
## Authenticating Bluesky
On the Social Accounts page, click the Bluesky icon.
The Bluesky authentication page will open in a modal.
1. Enter your Bluesky handle, which can be found in your [Bluesky profile](https://bsky.app/). For example, `@ayrshare` or `ayrshare.bsky.social`.
2. Create a one-time [Bluesky app password](https://bsky.app/settings/app-passwords). Copy the password to your clipboard. The password should be in the format of XXXX-XXXX-XXXX-XXXX.
3. Enter the app password in the Ayrshare Bluesky App Password field and click **Submit**.
Your Social Accounts page will now be updated with your Bluesky account.
You can publish Bluesky posts, get Bluesky analytics, and manage Bluesky
comments.
## Additional Bluesky Information
* Please see here for details on
[posting to Bluesky](/docs/apis/post/social-networks/bluesky),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Facebook Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/facebook
Authorizing Facebook with Ayrshare
## How to Link Facebook with Ayrshare
Only **Facebook Pages** are supported. Facebook does not support Personal Facebook accounts.
Please be sure you are the admin of Facebook Page and **grant all permissions** to Pages and
selections. Failure to do so might prevent successful posting.
### Linking Facebook
Click the Facebook icon on the Social Accounts page.
A Facebook sign-in will pop-up - *please be sure you allow pop-ups*.
If you have already linked Facebook with Ayrshare, skip ahead to step 4.
Follow the instructions and select a Facebook Page to link.
Click **Continue as NAME** on the login page.
Once back at the Ayrshare dashboard, choose a Facebook page to link and click **Submit**.
Your Social Accounts page will now be updated with your Facebook account.
## Troubleshooting Facebook
If you're having issues with Facebook please see the [troubleshooting guide](/docs/help-center/technical-support/facebook_or_instagram_linking_issues).
## Additional Facebook Information
* Please see here for details on
[posting to Facebook](/docs/apis/post/social-networks/facebook),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Google Business Profile Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/google-business
Authorizing Google Business Profile with Ayrshare
## Claim Your Google Business Profile Page
Google Business Profile (GBP) requires you to [claim](https://support.google.com/business/answer/2911778) your business listing page.
After claiming your listing, you can then link it with Ayrshare, which includes verifying your business with Google.
Check if your business [has been verified](https://business.google.com/locations).
Be sure to choose the Google account that is an admin of your GBP page during link authorization process.
See our [Google Business Profile article](https://www.ayrshare.com/blog/google-my-business-what-is-gmb-why-you-need-it-and-how-to-use-it/) to learn more.
## Additional Google Business Profile Information
Please see here for details on [posting to Google Business
Profile](/docs/apis/post/social-networks/google), [getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or [retrieving history.](/docs/apis/history/overview)
For more information on recommended image sizes, please see:
# Instagram Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/instagram
Authorizing Instagram with Ayrshare
## How to Link Instagram
The following is a guide for linking Instagram. There are two ways to link Instagram:
1. [Directly link Instagram account to Ayrshare.](#linking-instagram-directly)
2. [Link Instagram account to Ayrshare through a Facebook page.](#linking-instagram-through-facebook-facebook-page-required)
Option 1 is the default option. If option 2 is preferred, in the dashboard settings, disable [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) to use the authentication flow that requires a Facebook Page to be associated with the Instagram account.
Instagram does not support Personal Facebook accounts, Creator Studio accounts, and publishing to IGTV.
[See below](/docs/dashboard/connect-social-accounts/instagram#enabling-an-instagram-business-or-creator-account) for details.
### Linking Instagram Directly
Click the Instagram icon on the Social Accounts page.
Input your credentials and click **Log in**.
Toggle on all permissions for Instagram and click **Allow**.
Your Social Accounts page will now be updated with your Instagram account.
### Linking Instagram through Facebook (Facebook Page required)
Please be sure you are the admin of Facebook Page and **grant all
permissions** to Pages, Instagram accounts, and selections. Failure to do so
might prevent successful posting.
This Instagram linking process authenticates through Facebook, so when you
click the Instagram icon on the Social Accounts page, a Facebook sign-in will
pop-up - *please be sure you allow pop-ups*.
Click the Instagram icon on the Social Accounts page.
The first time you link Instagram, you will be asked to authenticate through Facebook.
If you have previously connected Ayrshare with Facebook and don't see this image, skip to step 3.
Click **Edit Settings** during the initial set up.
Check all the **Instagram Business Accounts** or **Instagram Creator Accounts**. Click **Next**.
Check all **Facebook Pages**. Click **Next**.
Turn all permissions to **Yes**. Click **Done**. You will then be asked to
select a specific Instagram account to link with Ayrshare. Once selected your
link will be complete and you can start posting to Instagram.
Your Social Accounts page will now be updated with your Instagram account.
## Enabling an Instagram Business or Creator Account
Instagram requires that your account be an **Instagram Business** or **Instagram Creator** account.
Learn more about [Instagram Business and Creator accounts](https://www.ayrshare.com/blog/understanding-the-difference-between-the-instagram-business-creator-and-personal-profiles/).
### Switching from a Personal to Business or Creator Account
If you have a personal Instagram account, open up the Instagram mobile app:
Go to your profile and tap the menu icon ≡ in the upper right corner to go
to the **Settings and activity** page.
Scroll down to the **For professionals** section.
Click **Account type and tools**.
Tap **Switch to professional account**.
Go through the steps to set up your account and select with **Creator** or
**Business**.
### Switching from a Business to Creator or Vice Versa
If you want to switch from a Business account to a Creator account or vice versa:
Go to your profile and tap the menu icon ≡ in the upper right corner to go
to the **Settings and activity** page.
Scroll down to the **For professionals** section.
Click **Creator (or Business) tools and controls**.
Scroll down and tap **Switch account type**.
Choose to switch to **Creator** or **Business**.
If you do have a Business or Creator account, but when linking Ayrshare you
receive an error saying your account isn't a Creator or Business, try
switching your Instagram back to **Personal** and then back to **Creator** or
**Business**. This often resets the account type and allows you to link
Ayrshare.
## Connect a Facebook Page to Instagram
If you already have an Instagram Business or Creator Account and want to connect a Facebook Page, see [detailed instructions](https://www.facebook.com/business/help/898752960195806).
Or if you want to [create a new Facebook Page](https://www.facebook.com/pages/create/?ref_type=site_footer).
You can check if you have an Instagram Account linked with your Facebook Page:
* Log into Facebook on your desktop [www.facebook.com](http://www.facebook.com).
* Navigate to one of your Facebook pages you are an admin. This will be the one you want to link with an Instagram account.
* On the left-hand panel under "Manage Page" click "Settings". It usually is at the bottom.
* Under Page Settings click "Instagram".
The top title will say "Connected Instagram Account" if one is connected. Otherwise you will be able to connect one.
## Troubleshooting Instagram
If you're having issues with Instagram please see the [troubleshooting guide](/docs/help-center/technical-support/facebook_or_instagram_linking_issues).
## Additional Instagram Information
Instagram has very strict requirements on image sizes. Images must have a width of at least 1080 pixels with an aspect ratio between 1.91:1 and 4:5.
Ayrshare will detect if your image size is not correct and respond with an error.
* Please see here for details on [posting to Instagram](/docs/apis/post/social-networks/instagram), [getting analytics](/docs/apis/analytics/overview), [managing comments](/docs/apis/comments/overview), or [retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# LinkedIn Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/linkedin
Authorizing LinkedIn with Ayrshare
## How to Link LinkedIn with Ayrshare
You can link either your LinkedIn company page or personal LinkedIn account.
When authorizing LinkedIn with Ayrshare, you will be redirected to LinkedIn to login and authorize Ayrshare to access your LinkedIn account.
Click the LinkedIn icon on the Social Accounts page.
The page will be redirected to LinkedIn and request you to login to your
LinkedIn account. If you have previously authorized Ayrshare with LinkedIn,
this step may be skipped.
Accept the authorization permissions Ayrshare is requesting.
You will be redirected back to Ayrshare where you can select the LinkedIn
account type you wish to link with Ayrshare. You may either choose a LinkedIn company page or your personal LinkedIn account.
If selecting to link a company page, the LinkedIn user must be a Super Admin
or Content Admin of the company page to link it with Ayrshare.
If you chose "Company Page", you will see a list of company pages you can select from.
Remember, the LinkedIn user must be a Super Admin or Content Admin of the company page to link it with Ayrshare.
Your Social Accounts page will now be updated with your LinkedIn account.
## LinkedIn Troubleshooting
The most common error you may encounter is a company page not showing in the list of available companies.
This can be caused by the LinkedIn user not being a Super Admin or Content Admin of the company page and can be fixed by a Super Admin of the company page [updating the user's page role](https://www.linkedin.com/help/linkedin/answer/a1481267).
## LinkedIn Link Expiration
LinkedIn must be re-linked every 365 days.
Please see the [user endpoint](/docs/apis/user/profile-details) for getting the refresh required date and days remaining.
## Additional LinkedIn Information
* Please see here for details on
[posting to LinkedIn](/docs/apis/post/social-networks/linkedin),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Connect Your Social Media Accounts | Ayrshare Dashboard
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/overview
Learn how to link Facebook, Instagram, X, LinkedIn, TikTok, and more to the Ayrshare Dashboard so you can start scheduling and publishing posts in minutes.
## Linking and Posting via the Web Dashboard
How to link and post to your social media accounts via the Ayrshare Dashboard.
### How to Link a Social Media Network
Connecting your social media accounts is easy with a few clicks.
On the Social Account linkage page, or the user profile's [social account linking page](/docs/multiple-users/user-integration#user-experience) used for managing multiple users, just click or tap the social network you want to connect. You will then be prompted to authorize access to Ayrshare via a pop-up or page redirect.
Please grant all permissions Ayrshare requests during authorization. Removing permissions may
cause unintended issues at the social networks or Ayrshare's APIs. Also allow pop-ups in your
browser.
Once the social networks has been authorized, you'll see your account logo and the green "Linked" pill will appear, indicating your link is active.
### How to Un-Link a Social Network
Just tap on the green "Linked" pill and you will be prompted to unlink the account.
Posts that have already been sent to the network will be unaffected. However, future scheduled post and new posts will not be sent until the link to the network has been re-established.
### Additional Help
#### Choose a Page or Brand
A few of the social networks will ask you to choose an account or brand. For example, if you
have multiple Facebook Pages, you will be given a choice of which Page to link.
### Additional Linking Guides
# Pinterest Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/pinterest
Authorizing Pinterest with Ayrshare
## How to Link Pinterest with Ayrshare
### Pinterest Board Setup
Before linking your Pinterest account, you must have at least one Pinterest
board set up. To do so, navigate to your Pinterest profile page and click on the
**+**(plus) symbol. Follow the instructions to create a new board.
### Linking Pinterest
Click the Pinterest icon on the Social Accounts page.
If you are not logged in yet, you'll navigate to the Pinterest login page.
Enter your credentials accordingly.
If you are already logged in, please proceed to the next step.
If already logged in, click **Give access** on the Authorize app page.
Once back at the Ayrshare dashboard, choose the Pinterest board to link.
Your Social Accounts page will now be updated with your Pinterest account.
## Additional Pinterest Information
* Please see here for details on
[posting to Pinterest](/docs/apis/post/social-networks/pinterest),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Reddit Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/reddit
Authorizing Reddit with Ayrshare
## How to Link Reddit with Ayrshare
You can link Reddit account with Ayrshare.
When authorizing Reddit with Ayrshare, you will be redirected to Reddit to login and authorize Ayrshare to access your Redditaccount.
Click the Reddit icon on the Social Accounts page.
If you are not logged in yet, enter your credentials to login to Reddit and
click **Log In**.
If you are already logged in, please proceed to the next step.
Allow permissions for Ayrshare to connect to your Reddit account by clicking **Allow**.
Your Social Accounts page will now be updated with your Reddit account.
## Additional Reddit Information
* Please see here for details on
[posting to Reddit](/docs/apis/post/social-networks/reddit),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Snapchat Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/snapchat
Authorizing Snapchat with Ayrshare
## How to Link Snapchat with Ayrshare
### Snapchat Public Profile Setup
Before linking your Snapchat account, you must have a Snapchat Public Profile set up.
Non-public profiles can not be linked to Ayrshare.
Additionally, the public profile must be switched to a Professional Profile.
Without a professional profile, certain features such as posting stories is not
permitted.
If you don't have public profile yet, please follow the steps below.
If you have a public profile already, please proceed to step 3.
If your public profile is already a professional profile, please proceed to [Linking Snapchat](/docs/dashboard/connect-social-accounts/snapchat#linking-snapchat).
Open Snapchat and tap on your icon in the top left corner.
Click on the **Public Profile** button and follow the instructions to set up your public profile.
Navigate to **Switch to a Professional Profile** option in the Profile Settings.
Follow the instructions, select a category, and click **Confirm** to switch
to a professional profile.
### Linking Snapchat
Click the Snapchat icon on the Social Accounts page.
If you are not logged in yet, you'll navigate to the Snapchat login page. Enter your credentials
accordingly. If you are already logged in, please proceed to the next step.
Review the permissions and click **Continue** on the authorization page.
Your Social Accounts page will now be updated with your Snapchat account.
## Additional Snapchat Information
* Please see here for details on
[posting to Snapchat](/docs/apis/post/social-networks/snapchat),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history](/docs/apis/history/overview).
* For more information on recommended image and video sizes, please see:
# Link a Telegram group or channel to Ayrshare
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/telegram
Connect Telegram to Ayrshare by adding @AyrshareBot as an administrator so you can publish and delete posts in your group or channel.
Telegram uses bots to allow posting to your group or channel.
You will need to give admin access to the Ayrshare Telegram Bot via the Telegram mobile app to enable publishing and deleting.
**Add the correct bot: `@AyrshareBot`** (its display name shows as "Ayrshare", with a red logo like the one below).
Searching Telegram for "Ayrshare" returns several bots with similar names or logos that are
**not** ours — for example the usernames `@AyrShareSocialMediaBot`, `@ayrshare_bot`,
`@kylo_post_bot`, and `@AyrshareTestbot`. Only **`@AyrshareBot`** works with Ayrshare. If you
add any other bot, your linking code will never be received and nothing will happen. Before
adding it, open the bot and confirm its username is exactly **`@AyrshareBot`**.
You must have administrative access to the channel or group to add a bot. Telegram channel posts
show the channel name and logo as the author. Telegram group posts show the Ayrshare name and logo
as the author.
**The bot must be an Administrator — not just a member.** `@AyrshareBot` has Telegram Privacy
Mode enabled, so if it is added only as a member it never receives your `Code:` message and
linking silently fails with no error. Promote it to Administrator in the same channel or group
where you paste the code.
## How to Link Telegram with Ayrshare
1. In the Telegram mobile app, go to the channel or group where you want to publish. Tap the three horizontal dots in the upper right corner and go to **Info**.
2. Add Ayrshare as an Admin:
If a *Channel*, select **Administrators** and **Add Admin**.
If a *Group*, add Ayrshare as a member by clicking "+ Add", and search for **Ayrshare** to
add as a member. Next, select **Edit** in the upper right corner, click **Administrators,**
and **Add Admin**.
3. Search for **Ayrshare** and select the official bot **`@AyrshareBot`** (display name "Ayrshare"). Do not select any of the similarly named look-alike bots — see the warning above.
4. You will be asked to select permissions for the bot. Select all the permissions except the last two so the bot can post and delete on your behalf.
5. Tap **Done** when complete.
6. In your Ayrshare Dashboard under Social Accounts you will be given a Telegram access code when you click on the Telegram icon.
7. Copy the code including the "Code:" part.
8. In your Telegram group or channel at the chat prompt, paste this code and press enter/tap the send button. If successful, you will get a success message back in the channel or group.
It could take up to **5 minutes** for Telegram to send you the success message after you enter the
code message, so please be patient.
The Telegram integration is complete. You can now publish via the API or Web App.
If you need help or have questions, please chat with us or [contact us](mailto:support@ayrshare.com).
## Additional Telegram Information
Please see here for details on [posting to Telegram](/docs/apis/post/social-networks/telegram), [getting analytics](/docs/apis/analytics/overview), [managing comments](/docs/apis/comments/overview), or [retrieving history.](/docs/apis/history/overview)
# Threads Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/threads
Authorizing Threads with Ayrshare
## How to Link Threads with Ayrshare
Authorizing Threads with Ayrshare is simple. During the authentication process,
you will be required to sign in with an Instagram account in order to leverage
Threads's full capabilities. Please see the below steps for more information.
## Authenticating Threads
On the Social Accounts page, click the Threads icon.
The first time you link Threads, you will be asked to authenticate with your
Instagram account. An Instagram account is required in order to post to
Threads.
If you have previously connected Ayrshare with Threads and don't see this
image, skip to step 4.
After login, you'll be required to grant Ayrshare access to your Threads
account. Please provide all requested permissions in order to continue. (If
required permissions are not granted, you can re-enable them on the
[Website Permissions Page](https://www.threads.com/settings/website_permissions)
in your Threads settings)
If you have previously connected Ayrshare with Threads, please click the
Continue button to relink your Threads account.
Your Social Accounts page will now be updated with your Threads account.
You can publish Threads posts, get Threads analytics, and manage Threads
comments.
## Additional Threads Information
* Please see here for details on
[posting to Threads](/docs/apis/post/social-networks/threads),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# TikTok Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/tiktok
Authorizing TikTok with Ayrshare
## How to Link TikTok with Ayrshare
You can link either your TikTok personal or business account with Ayrshare.
When authorizing TikTok with Ayrshare, you will be redirected to TikTok to login and authorize Ayrshare to access your TikTok account.
Click the TikTok icon on the Social Accounts page.
If you're not already logged into TikTok, you'll see the TikTok login page.
Enter your credentials to log in to your TikTok account.
If you are already logged in, please proceed to the next step.
Click **Continue** to allow Ayrshare to connect to your TikTok account.
Your Social Accounts page will now be updated with your TikTok account.
## TikTok Link Expiration
TikTok must be re-linked every 365 days.
Please see the [user endpoint](/docs/apis/user/profile-details) for getting the refresh required date and days remaining.
## Troubleshooting TikTok
If you're having issues with Tiktok, please see the [troubleshooting guide](/docs/help-center/technical-support/tiktok_account_restricted).
## Additional TikTok Information
* Please see here for details on
[posting to TikTok](/docs/apis/post/social-networks/tiktok),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# X Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/x-twitter
Authorizing X with Ayrshare
**Starting March 31, 2026**, X requires your own API credentials for all operations through Ayrshare. If you are an API user, you can start using your own credentials immediately. See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for step-by-step instructions.
## How to Link X (Twitter) with Ayrshare
You can link X, formerly known as Twitter, account with Ayrshare.
When authorizing X with Ayrshare, you will be redirected to X to login and authorize Ayrshare to access your X account.
Click **X/Twitter - Click to Link** button on the Social Accounts page.
Before linking, you'll be prompted to enter your **X Consumer Key** (API Key) and **X Consumer Secret** (API Secret). X now requires every Ayrshare account to register one X Developer App and provide its API Key and API Secret in order to link an X account.
**One-time setup per Ayrshare account.** You create your X Developer App **once**, and the same API Key + API Secret are used for every X account you link going forward, including any sub-profiles or end-users. You do **not** create a separate developer app per customer.
If you don't yet have these credentials, follow the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) to create an X Developer App and retrieve your API Key and API Secret. Paste both values into the modal, then continue to link your account.
When you click the X icon on the Social Accounts page, an X
sign-in will pop-up - *please be sure you allow pop-ups*. If you are already
logged in, please proceed to the following step.
Click *Sign In*, follow the instructions, and input relevant login credentials.
If you have already signed in, click **Authorize app** on the pop-up.
This will authorize Ayrshare to access your X account.
Your Social Accounts page will now be updated with your X account.
## Additional X Information
* Please see here for details on
[posting to X](/docs/apis/post/social-networks/x-twitter),
[getting analytics](/docs/apis/analytics/overview),
[managing comments](/docs/apis/comments/overview), or
[retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Set Up Your Own X API Key
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/x-twitter-byo-keys
Step-by-step guide to connect your own X (Twitter) API credentials with Ayrshare
On March 31, 2026, X changed how third-party platforms access its API. As a result, every Ayrshare account posting to X through Ayrshare must register its own X Developer App and use its API Key and API Secret on every request.
This is a platform-wide change mandated by X that affects all third-party tools.
**BYO keys are set once per platform (account-wide), not per customer or sub-profile.** You create **one X Developer App** under your own X account, and the same **API Key + API Secret** apply account-wide for X — they are used for **every** sub-profile / end-user that links X under your Ayrshare account. If you have a Business or Enterprise plan with hundreds of sub-profiles, you do **not** need to repeat this setup for each one. You set it up once for the X platform, then pass the same two headers on every request.
We've streamlined the setup process to make this as simple as possible, and it should take less than 10 minutes to complete. Follow our step-by-step guide below, and if you need any help along the way, our team is here to assist.
## Step 1: Create Your X Developer Account
Go to [console.x.com](https://console.x.com) and sign in with your X account. See [X's getting started guide](https://docs.x.com/x-api/getting-started/getting-access) if you need help.
Complete the developer onboarding and accept the Developer Agreement and policies.
You're now in the X Developer Console.
## Step 2: Create an App
You only create **one X Developer App per Ayrshare account**. The same app and its API Key + API Secret are reused for every sub-profile / end-user you later link under your Ayrshare account. You do not create a new app per customer.
In the Developer Console, navigate to **Apps**.
In the App dashboard, click **Create App** (see [X's App setup docs](https://docs.x.com/fundamentals/developer-apps) for details). Enter an app name (typically your brand name). This name will appear in the OAuth authorization screen when users connect their X account.
Select the **Production** environment in the dropdown.
X will generate several credentials. **Ignore these credentials and close this window.**
## Step 3: Configure App Permissions
Under "Apps," locate the new app (refresh the page if it doesn't appear), then click it to view its details.
Under **User authentication settings**, click **Set up**.
Under **App permissions**, select **Read and write and Direct message**. This is required for full feature support, including posting and DMs.
Under **Type of App**, select **Web App, Automated App or Bot**. This is the right choice for server-side integrations like Ayrshare.
Under **App info**:
* **Callback URL:** Add both of the following callback URLs:
* `https://profile.ayrshare.com/social-accounts`
* `https://app.ayrshare.com/social-accounts`
* **Website URL:** `https://app.ayrshare.com`
**Do not skip this step.** These callback URLs are required for the OAuth linking flow. When your end-users authorize the X connection, X redirects them back to one of these URLs to complete the linking process. If these are missing, the OAuth flow will fail with a `403 Callback URL not approved` error.
Click **Save**. You can ignore the OAuth 2.0 popup, since you will only be using 2 of the OAuth 1.0 keys (API Key and API Secret).
**Important: Set permissions before linking.** The permissions you choose here determine what your app can do. If you change permissions after linking your X account via OAuth, you'll need to re-link so the new Access Token inherits the updated permissions.
Please make sure you store these 2 keys:
1. **API Key** (aka Consumer Key, the X app identifier)
2. **API Secret** (aka Consumer Secret)
You do **NOT** need to manually generate Access Tokens. Ayrshare handles this automatically when you link your X account via OAuth.
## Step 4: Purchase X API Credits
X now uses credit-based API billing, purchased through the developer console.
In the Developer Console, click **Billing → Credits** in the left sidebar.
Purchase credits (the minimum is \$5, which is enough for hundreds of API calls). Each API call is a fraction of a penny, so the cost should be minimal for most users.
You can enable **auto-recharge** to avoid service interruptions, and manage your spend cap by setting a maximum amount you can spend in your billing cycle.
**Your API calls will fail without credits.** X's API is pay-per-use. If your credit balance is zero, every API request will return a `402 CreditsDepleted` error with the message "Your enrolled account does not have any credits to fulfill this request." This includes posting, reading tweets, and user lookups. Load credits before testing your integration. See [How X API Pricing Works](#how-x-api-pricing-works) for a full update on X's pricing.
## Step 5: Update Your Ayrshare API Calls
In Step 3, you saved these 2 items securely in your own env, config, or secrets manager:
1. **API Key** (aka Consumer Key, the X app identifier)
2. **API Secret** (aka Consumer Secret)
Now, add your X credentials to the headers of your Ayrshare API calls.
**Your keys stay private.** Your API Key and API Secret are not stored by Ayrshare.
### Header Reference
| Header | Value |
| ----------------------------- | -------------------------------- |
| `X-Twitter-OAuth1-Api-Key` | API Key (Consumer Key) |
| `X-Twitter-OAuth1-Api-Secret` | API Key Secret (Consumer Secret) |
**How to tell if your permissions are wrong:**
* If your app permissions are misconfigured, your API request may return a `403 Forbidden` error with the message: "Your client app is not configured with the appropriate OAuth1 app permissions."
If you see this error, update your app permissions to **Read and write and Direct message** in the X Developer Console, then re-link your X account via OAuth so the new Access Token inherits the updated permissions.
### Code Examples
```bash cURL theme={"system"}
curl -X POST https://api.ayrshare.com/api/post \
-H "Authorization: Bearer YOUR_AYRSHARE_API_KEY" \
-H "X-Twitter-OAuth1-Api-Key: your_api_key" \
-H "X-Twitter-OAuth1-Api-Secret: your_api_secret" \
-H "Content-Type: application/json" \
-d '{"post": "Hello from my own X App!", "platforms": ["twitter"]}'
```
```javascript Node.js theme={"system"}
const response = await fetch("https://api.ayrshare.com/api/post", {
method: "POST",
headers: {
"Authorization": "Bearer YOUR_AYRSHARE_API_KEY",
"Content-Type": "application/json",
"X-Twitter-OAuth1-Api-Key": process.env.X_API_KEY,
"X-Twitter-OAuth1-Api-Secret": process.env.X_API_SECRET,
},
body: JSON.stringify({
post: "Hello from my own X App!",
platforms: ["twitter"],
}),
});
```
```python Python theme={"system"}
import os
import requests
headers = {
"Authorization": "Bearer YOUR_AYRSHARE_API_KEY",
"Content-Type": "application/json",
"X-Twitter-OAuth1-Api-Key": os.environ["X_API_KEY"],
"X-Twitter-OAuth1-Api-Secret": os.environ["X_API_SECRET"],
}
response = requests.post(
"https://api.ayrshare.com/api/post",
headers=headers,
json={"post": "Hello from my own X App!", "platforms": ["twitter"]},
)
```
Your existing automations and workflows will continue working as long as you include your API Key and API Secret headers in every request that targets X.
### Migrating Existing Profiles (Business & Enterprise)
If you have sub-profiles that are already linked to X through Ayrshare, those profiles need to re-link their X accounts after you switch to BYO keys. This is because the existing access tokens were issued under Ayrshare's X app and cannot be used with your consumer keys (OAuth 1.0a signatures are bound to the app that issued the token).
Add `twitterApiKey` and `twitterApiSecret` to your [generateJWT](/docs/apis/profiles/generate-jwt#body-parameters-13) call body. These are encrypted before being embedded in the JWT and are not exposed to your end users.
```json theme={"system"}
{
"domain": "your-domain",
"profileKey": "...",
"privateKey": "...",
"twitterApiKey": "YOUR_X_CONSUMER_KEY",
"twitterApiSecret": "YOUR_X_CONSUMER_SECRET"
}
```
This is the only request where your consumer keys go in the body. All other X requests use the headers described above.
After generating the JWT with the keys included, your users need to reconnect their X account through the profile linking page. The OAuth consent screen will now show your app name instead of Ayrshare's.
To streamline this, you can:
* Unlink accounts programmatically via the [Unlink API](/docs/apis/profiles/unlink-social-network#unlink-a-social-network), then have users re-authorize
* Use the [`logout` parameter](/docs/apis/profiles/generate-jwt#param-logout) in generateJWT to force a fresh login
* Use [`allowedSocial`](/docs/apis/profiles/generate-jwt#param-allowed-social) to show only X on the linking page during the migration flow
After re-linking, continue including `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret` headers on every API call (posting, analytics, comments, etc.).
Once a profile has re-linked under your X app, all subsequent posts for that profile will use your credentials. You can verify this by checking the Usage page in your [X Developer Console](https://console.x.com).
### Verify Your Setup
Make a test call through the Ayrshare API with your new headers to confirm everything is working. The [/analytics/social](/docs/apis/analytics/social) endpoint is a good lightweight test, since it won't create any posts.
## How X API Pricing Works
Previously, Ayrshare covered the cost of X's API usage on your behalf. Under X's current model, each Ayrshare customer maintains their own X Developer account and pays X directly for the API requests their application makes. (One X Developer account per Ayrshare account, not per end-user. All your sub-profiles share the same X Developer account and credit balance.)
X's pricing model is pay-per-use: you purchase credits in the X Developer Console, and they are deducted as API requests are made. No contracts or subscriptions are needed.
Typical operations are inexpensive. For example:
| Operation | Approximate cost |
| -------------------------------------- | ------------------------------------------------------------------------ |
| Creating a post (text only) | \~\$0.01 per post |
| Creating a post with media | \~\$0.02 per post (media upload and post creation are separate requests) |
| Reading a post | \~\$0.005 per read |
| User lookup | \~\$0.01 per lookup |
| Sending a DM | \~\$0.01 per message |
| Reading DM events | \~\$0.01 per event |
| User interactions (follow, like, etc.) | \~\$0.015 per request |
For context, if you're posting about 100 times per month, your direct X cost would likely be around \$1, and posts with media would be roughly \$2 per month.
X's pay-per-use pricing is currently in a pilot phase. Rates are subject to change, and additional costs may be introduced. Always check the Developer Console for the most current pricing. See [X's pricing information breakdown](https://docs.x.com/x-api/fundamentals/pricing).
We know this introduces a cost that didn't exist before, and we want to be transparent about that. At the same time, this model also unlocks several benefits that weren't possible under the previous shared-key setup.
## Benefits of Using Your Own X API Key
Using your own X API credentials provides more control and reliability than the previous shared-key model. This includes:
* **Branded OAuth experience:** Users see your app name and branding when authorizing X access.
* **Dedicated rate limits:** Your API usage is governed by your own X Developer account limits, separate from other Ayrshare users. You can monitor your usage in the [X Developer Console](https://console.x.com) and review the [X API rate limits documentation](https://developer.x.com/en/docs/x-api/rate-limits).
* **Credential control:** Your API Key and Secret stay in your own X Developer account. Ayrshare does not store your secret keys.
* **Portability:** Because users authenticate with your X App, your integration remains fully under your control.
* **Usage visibility:** Your X Developer dashboard shows API requests, rate limits, and credit usage.
X is the first platform requiring this model, but more platforms are moving toward "bring your own API key." We're expanding this capability across Ayrshare, so developers have the same control and independence across all social platforms.
## Security
* Your API Key and API Secret are not stored by Ayrshare.
* For general security best practices, see [X's authentication security guide](https://docs.x.com/resources/fundamentals/authentication).
## FAQ
**No.** You set up **one** X Developer App under your own X account, and the same **API Key + API Secret** are reused for every sub-profile / end-user you link under your Ayrshare account.
* You create the X Developer App **once**.
* You pass the same two headers (`X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret`) on every Ayrshare API call, regardless of which sub-profile the call is for.
* Your end-users still each go through the OAuth linking flow to authorize their own X account, but they do **not** need their own X Developer App or API keys. They connect through your app.
* All sub-profiles share the same X Developer account, the same rate limits, and the same credit balance.
The only time you handle the keys per-profile is in the [generateJWT](/docs/apis/profiles/generate-jwt) body during migration, which is still your same two keys, just delivered to the linking page so end-users can re-authorize under your app.
Yes. As of March 31, 2026, all X operations through Ayrshare require your own X API credentials. If you haven't set up your X Developer account yet, follow the steps above.
Posting to X through Ayrshare requires your own X API credentials. Requests without valid BYO credentials are rejected. Posting to other platforms (Instagram, LinkedIn, Facebook, TikTok, etc.) is unaffected.
X charges per API call. Creating a post costs about \$0.01, and reading a post costs about \$0.005. For example, publishing 100 posts per month would cost roughly \$1. See [X's pricing page](https://docs.x.com/x-api/fundamentals/pricing) for the full details.
No. Your Ayrshare subscription price stays the same. The only additional cost is the X API usage fee billed directly by X through your developer account.
No. Your API Key and API Secret are not stored by Ayrshare. For general security best practices, see [X's authentication security guide](https://docs.x.com/resources/fundamentals/authentication).
Yes. You can use your existing X App as long as it has "Read and write" permissions enabled (and Direct Messages if you use DM features).
You'll need your API Key (Consumer Key) and API Secret (Consumer Secret) from the Keys and tokens section of the X Developer Console. Link your X account via OAuth, then include these 2 headers in your Ayrshare API requests.
If you've changed your app permissions since the initial setup, re-link your X account so the Access Token inherits the updated permissions.
You need your API Key (Consumer Key) and API Secret (Consumer Secret). See the [header reference table](#header-reference) above for exactly which Ayrshare header each one maps to. You can ignore the Client ID, Client Secret, Bearer Token, Access Token, and Access Token Secret.
They're completely different credentials for different authentication methods:
* **API Key** (also called "Consumer Key") is for OAuth 1.0a. API Key (Consumer Key) + API Secret is what Ayrshare uses. It works with all X features, tokens never expire, and no refresh logic is needed.
* **Client ID** is for OAuth 2.0. You do NOT need this for Ayrshare. OAuth 2.0 tokens expire after a short period and require refresh token management.
For Ayrshare, you only need your API Key and API Secret. You can ignore the Client ID, Client Secret, and Bearer Token.
OAuth 2.0 access tokens expire every 2 hours and X's refresh tokens are single-use (each refresh invalidates the old token). This makes it impossible to support a stateless BYO model, especially for scheduled posts. OAuth 1.0a tokens never expire, work with all X features, and require zero token management.
Yes. If your users linked X through Ayrshare before you set up BYO keys, they will need to reconnect. The existing access tokens were issued under Ayrshare's X app and won't work with your consumer keys. See [Migrating Existing Profiles](#migrating-existing-profiles-business--enterprise) above for the step-by-step process.
No. This change only affects posting to X. All other platform integrations in Ayrshare continue working as usual.
RSS auto-posting to X is no longer supported. RSS feeds run automatically on a schedule, but the bring-your-own API key model requires credentials to be provided with each API request. Because of this, RSS feeds cannot authenticate when the post is sent.
If you previously used RSS to post to X, we recommend switching to [scheduled posts](/docs/apis/post/overview#schedule-posts) or direct API calls that include your credentials. RSS auto-posting to all other platforms is unchanged.
This means your X Developer account has no API credits available. Go to [console.x.com](https://console.x.com) → **Billing → Credits** and purchase credits. Even \$5 is enough for hundreds of API calls. Once credits are loaded, retry your request.
Your Access Token doesn't have the right permissions. This usually means one of two things:
1. **Your app permissions are set to "Read" instead of "Read and write."** Go to your app's Settings in the Developer Console and change it to **Read and write and Direct message**.
2. **You changed permissions after linking your X account.** Access Tokens keep the permissions they were created with. Re-link your X account via OAuth so the new token inherits the updated permissions.
Our support team is happy to help. If you have any questions or run into issues during setup, please reach out via [support@ayrshare.com](mailto:support@ayrshare.com), and we'll walk you through the process.
## Troubleshooting
Make sure you're sending both required headers:
* `X-Twitter-OAuth1-Api-Key`
* `X-Twitter-OAuth1-Api-Secret`
If you see a pair-mismatch error (e.g., "You provided Api-Key but not Api-Secret"), it means one of the two is missing. Both are always required.
The error message will tell you which specific header is missing.
If you see this error when trying to link your X account, make sure you've added the required callback URLs to your X Developer App settings (under Authentication settings > Callback URI / Redirect URL):
* `https://profile.ayrshare.com/social-accounts`
* `https://app.ayrshare.com/social-accounts`
See the [Callback URL setup step](#step-3-configure-app-permissions) above.
Your X Developer account has no API credits loaded. Go to [console.x.com](https://console.x.com) → **Billing → Credits** and purchase credits. Even \$5 is enough for hundreds of API calls.
Your Access Token doesn't have the right permissions. This usually means:
1. **Your app permissions are set to "Read" instead of "Read and write."** Go to your app's Settings in the Developer Console and change it to **Read and write and Direct message**.
2. **You changed permissions after linking your X account.** Access Tokens keep the permissions they were created with. Re-link your X account via OAuth so the new token inherits the updated permissions.
## Need Help?
If you have any questions or run into issues while setting up your X API key, our engineering team is happy to help. You can reach us anytime at [support@ayrshare.com](mailto:support@ayrshare.com).
# YouTube Linking
Source: https://www.ayrshare.com/docs/dashboard/connect-social-accounts/youtube
Authorizing YouTube with Ayrshare
## How to Link a YouTube Channel with Ayrshare
You can link a YouTube channel with Ayrshare.
When authorizing YouTube with Ayrshare, you will be redirected to Google to login, authorize Ayrshare, and select a YouTube channel.
Please be sure your Google account permissioned to manage the YouTube channel you want to connect and the channel is public.
If you're having issues linking your YouTube channel, please see the [YouTube channel permissions guide](/docs/help-center/technical-support/youtube_channels_not_showing) for more information.
YouTube does not support Service Accounts.
Service accounts do not work for YouTube Data API calls because service accounts require an associated YouTube channel, and you cannot associate new or existing channels with service accounts.
Click the YouTube icon on the Ayrshare Social Account linking page.
The page will be redirected to either a Google login page or a list of currently logged in Google accounts.
Select a Google account that is associated with the YouTube channel you want to connect.
Select the YouTube channel you want to connect.
You may then see one or two screens requesting permissions. Click *Continue* on each screen.
Once complete you will be returned to the Ayrshare social linking page.
Your Social Accounts page will now be updated with your YouTube account.
## Troubleshooting YouTube Linking
YouTube posting requires your YouTube account to have at least one Channel and be an owner on the Channel.
To create a YouTube Channel, click on your profile in the YouTube Dashboard and choose "Create a Channel".
You may also use this direct link to create a YouTube Channel if one does not exist: [http://m.youtube.com/create\_channel](http://m.youtube.com/create_channel)
If you're having issues viewing YouTube channels please see the [troubleshooting guide](/docs/help-center/technical-support/youtube_channels_not_showing).
## Additional YouTube Information
* Please see here for details on [posting to YouTube](/docs/apis/post/social-networks/youtube), [getting analytics](/docs/apis/analytics/overview), [managing comments](/docs/apis/comments/overview), or [retrieving history.](/docs/apis/history/overview)
* For more information on recommended image sizes, please see:
# Find an RSS Feed URL
Source: https://www.ayrshare.com/docs/dashboard/find-rss
How to find the RSS Feed URL for a website
You can find an RSS feed URL using the **Find an RSS Feed URL** tool. Get a Substack RSS feed, YouTube Channel RSS feed, or feeds for most publication websites.
## Process
Copy a blog or content website's URL and enter it into our [RSS Finder](https://app.ayrshare.com/rss-feed-finder). In the below example we get the feed for the website daringfireball.net.
For more information, please see this article on Automating Social Media Post with an RSS Feed.
# Ayrshare Dashboard Overview: Manage Social Media Posting
Source: https://www.ayrshare.com/docs/dashboard/overview
Explore the Ayrshare Dashboard to schedule posts, manage connected social accounts, track analytics, and control your social media API from a single place.
The Ayrshare API dashboard provides a straightforward interface for managing your social media integrations, user profiles, and API access.
The dashboard supports connection to major social platforms including:
Bluesky
Facebook
Google Business Profile
Instagram
LinkedIn
Pinterest
Reddit
Snapchat
Telegram
Threads
TikTok
X/Twitter
YouTube
As a management hub, the dashboard enables essential administrative functions:
User profile management, including adding and removing users, switching between profiles, and
viewing user details
Business account settings configuration, such as setting your own logo, customizing text, and
admin settings
Connect your social media accounts
Account data access (billing and add-ons)
API and Profile key management
Webhook set up and log monitoring
RSS feed configuration
For direct social media management, users can manually publish posts to any connected platform and track their social media activities.
The dashboard maintains a comprehensive history of all posts, including the JSON request and response for each interaction, making it invaluable to developers for testing and troubleshooting purposes.
Additional features include:
Post analytics data
Comment viewing and creation
Direct message composition and management
It's important to note that the dashboard represents only a subset of Ayrshare's full [API capabilities](/docs/apis/overview).
While it provides essential management and monitoring tools, the real power of Ayrshare lies in its comprehensive API.
The Ayrshare Dashboard is for your internal use only. You should [never give your users access to the dashboard](/docs/help-center/product/can_i_give_my_users_the_dashboard) as it will give them the ability to make changes to your account.
# How to Publish a Social Media Posts | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/dashboard/publish-post
Step-by-step guide to publishing a social media post from the Ayrshare Dashboard: compose content, add media, choose platforms, then post or schedule.
Here is a step-by-step guide to publishing a post:
In the Ayrshare [Dashboard](https://app.ayrshare.com/), go to "Posts" in the left-hand navigation.
Select the social networks you want to publish the post on. You can also click the to remove all the social networks from the list.
Enter in the post text. Depending on the social network you selected, you may need to enter additional fields.
For example, if you selected YouTube, you will need to enter the video title.
Optionally add image(s) or a video to the post by either uploading from your computer or by pasting in a URL.
Optionally select different options, such as publishing a video as a Facebook Reel or Instagram Story.
Click **Post Now** to publish the post immediately. Click **Schedule Post** to schedule the post for a future time.
Optionally, you can view the JSON payload that will be used to publish the
post. Please see additional details at [View JSON](/docs/dashboard/view-json).
Your post will be published to the selected social networks.
You can view the post status and details by scrolling to the timeline at the bottom of the page.
# Revoke Access to Social Media
Source: https://www.ayrshare.com/docs/dashboard/revoke-access
How to revoke access to the linked social media accounts
## How to Unlink a Social Network
If you want to remove/revoke access to the linked social media accounts:
1. In the Dashboard go to "Social Accounts".
2. Click the linked social account you want to revoke access. Linked accounts are brightly colored with your profile image.
3. Accept the prompt to unlink the account.
Once the account has been unlinked, all access tokens and authorizations are deleted from Ayrshare and are not recoverable.
To re-link, click the social network icon once more and follow the prompts.
# View JSON
Source: https://www.ayrshare.com/docs/dashboard/view-json
How to view the JSON Payload
In the Ayrshare [Dashboard](https://app.ayrshare.com/), navigate to "Posts" in the left-hand navigation.
Create a new post by selecting your desired social networks, post text, and media.
Click the "\> View JSON" button, located at the bottom of the post creation form.
The JSON payload will appear in a modal, showing all the parameters and data that will be used for your post.
You can copy the JSON payload for use with the Ayrshare API directly, or simply review it to understand how your post data is structured.
The JSON payload contains all the information about your post, including the
selected social networks, post text, media URLs, and any additional options
you've configured. This can be used by developers to understand the API
structure and/or replicate posts programmatically.
# Ayrshare Error Codes
Source: https://www.ayrshare.com/docs/errors/errors-ayrshare
Reference for Ayrshare API error codes, including retryable and non-retryable errors, expired Story handling, and multiplatform partial-success responses.
The REST API will include a response with a list of errors if applicable.
Errors have a returned status code of 400, 401, 402, 403, 404, 429, 500, 502, 503, or 504. Success has a returned
status code 200. See [here](/docs/errors/errors-http) for details.
Each API call can return different errors depending on the specific request and any issues encountered at the social network.
The error response will contain details about what went wrong during the API call.
For example, a post that is considered a duplicate by Twitter and Facebook would return the following response.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 110,
"message": "Status is a duplicate.",
"post": "Today is a great day",
"platform": "twitter"
},
{
"action": "post",
"status": "error",
"code": 107,
"message": "Facebook Error: This status update is identical to the last one you posted.
Try posting something different, or delete your previous update.",
"platform": "facebook"
}
],
"postIds": [],
"id": "6APU4qqI7XO7JM3BOy6B"
}
```
Please note:
The `errors` field contains the array of errors, one per social network that had an error.
The `action` refers to the type of error returned.
The top-level `status` field will be "error" if the API call failed. For example, for a /post
call if all social network posting were successful the `status` field will be "success", else
the status field will be "error".
The `code` field contains the Ayrshare reference error code.
The `message` field is the specific details of the error.
### Handling Errors
You should handle any error responses and take the appropriate action. An error occurred if:
The response return code is not `200`
The JSON response status is `error`
For example, if Facebook link was removed by your user - they changed their password or removed Ayrshare's access - the following response would occur when posting with a `400 Bad Request` response code.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 161,
"message": "Facebook authorization error. This can occur if your Facebook security changes. Try unlinking and re-linking Facebook or contact us for assistance.",
"platform": "facebook"
}
],
"postIds": [],
"id": "gh7SyTpeD2CQAMxWk3oh",
"post": "A great Facebook Posts"
}
```
An action might be to notify your user via your dashboard, text or email.
Another example is if the posted Instagram image is the wrong dimensions or ratio with a `400 Bad Request` response code:
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 138,
"message": "Instagram Error: There was an issue posting to Instagram. The submitted image with aspect ratio ('1440/2158',) cannot be published. Please submit an image with a valid aspect ratio.",
"platform": "instagram"
}
],
"postIds": [],
"id": "Jxe2nMM3FmEvMXFSY3g4",
"post": "Is this a good image?"
}
```
An action might be resending the images with the correct ratio.
### Instagram-Specific Error Codes
The following error codes provide specific details about Instagram posting failures, replacing the generic error 138 where possible.
**Code 435 — Instagram Rate Limit (HTTP 429)**
Instagram professional (Business / Creator) accounts are subject to a 50-post rolling 24-hour limit on Meta's [Content Publishing API](https://developers.facebook.com/docs/instagram-platform/instagram-graph-api/reference/ig-user/content_publishing_limit/) (personal accounts cannot publish via API at all and therefore never hit this limit). When the cap is exceeded, Meta returns a rate-limit error. Ayrshare also surfaces `code: 435` when Meta's publish endpoint returns HTTP 429 directly or when the underlying error subcode (`1390008`) indicates a post / comment throttle.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "rate limit",
"status": "error",
"code": 435,
"message": "Instagram rate limit reached. Please wait before retrying your post.",
"details": "Retry-After: 3600",
"platform": "instagram"
}
]
}
```
**Action:** Wait for the rate limit window to reset before retrying. When Meta supplies a `Retry-After` header, the value (in seconds) is passed through on the `details` field — wait at least that long before resubmitting.
**Code 436 — Instagram Media Processing Timeout (HTTP 400)**
Instagram took too long to process the uploaded media. This can happen with large video files or during periods of high load on Meta's servers.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 436,
"message": "Instagram media processing timed out. Please try posting again.",
"retryAvailable": true,
"platform": "instagram"
}
]
}
```
**Action:** Retry the post using the [retry post](/docs/apis/post/retry-post) endpoint. If the issue persists, try reducing the media file size.
**Code 447 — Instagram Trial Reels: Missing graduationStrategy (HTTP 400)**
Returned when `instagramOptions.trialParams` is provided on a [`/post`](/docs/apis/post/post) request but `graduationStrategy` is missing, `null`, or an empty string. Trial reels require an explicit graduation strategy — see [Trial Reels](/docs/apis/post/social-networks/instagram#trial-reels).
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 447,
"message": "Instagram trial reels require instagramOptions.trialParams.graduationStrategy (\"MANUAL\" or \"SS_PERFORMANCE\").",
"platform": "instagram"
}
]
}
```
**Action:** Set `instagramOptions.trialParams.graduationStrategy` to either `"MANUAL"` or `"SS_PERFORMANCE"` and retry, or remove `trialParams` if you did not intend to publish a trial reel.
**Code 448 — Instagram Trial Reels: Invalid graduationStrategy (HTTP 400)**
Returned when `graduationStrategy` is present but is not exactly `"MANUAL"` or `"SS_PERFORMANCE"`. The check is case-sensitive — values like `"manual"` or `"ss_performance"` are rejected. The `details` field echoes the rejected input (truncated to 64 characters) to aid debugging.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 448,
"message": "Invalid Instagram graduationStrategy. Must be \"MANUAL\" or \"SS_PERFORMANCE\".",
"details": "Received: manual",
"platform": "instagram"
}
]
}
```
**Action:** Send `graduationStrategy` as exactly `"MANUAL"` or `"SS_PERFORMANCE"` (uppercase, string type).
**Code 449 — Instagram Trial Reels: Incompatible Media (HTTP 400)**
Returned when the media or post shape is not eligible for a trial reel. Trial reels must be a single `.mp4` or `.mov` video — carousels (more than one URL), stories (`instagramOptions.stories: true`), and non-video extensions are all rejected. The `details` field disambiguates which sub-case fired.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 449,
"message": "Instagram trial reels must be a single video (.mp4 or .mov) — carousels and stories are not supported.",
"details": "Carousels are not supported.",
"platform": "instagram"
}
]
}
```
**Action:** Submit a single `.mp4` or `.mov` video URL with no `stories: true` flag. Drop additional `mediaUrls` entries, or remove `trialParams` if you intended a regular carousel/story post.
**Code 258 — Instagram Account-State Error (HTTP 400)**
A general Instagram account-state failure with the base message "Error with Instagram." This surfaces when Meta rejects the request due to the state of the connected Instagram account rather than the content of the post.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 258,
"message": "Error with Instagram.",
"platform": "instagram"
}
]
}
```
When the underlying Meta `error_subcode` is `2207085`, the response additionally sets `relink: true` and `retryAvailable: true`, and the message instructs the user to unlink and relink the Instagram account, granting all permissions:
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 258,
"message": "Error with Instagram. Please unlink and relink your Instagram account, granting all permissions, then retry.",
"relink": true,
"retryAvailable": true,
"platform": "instagram"
}
]
}
```
**Action:** For the `2207085` sub-case, prompt the user to unlink and relink their Instagram account in [Social Accounts](https://app.ayrshare.com/social-accounts), granting all requested permissions, then retry the post. For other account-state errors, verify the Instagram account is in good standing on Meta and retry.
#### Retry Available
Sometimes the social networks have a unrecoverable error, such as their are having server issues, and the call ultimately fails even after numerous retries.
In those cases, our system will determine if the error is retryable and if so, the `retryAvailable` field will be `true`.
```json theme={"system"}
{
"retryAvailable": true
}
```
You can then retry the call with the same payload.
If it is a post you can use the [retry post](/docs/apis/post/retry-post) endpoint.
### Automation Private-Reply (Comment DM) Errors
These codes surface on comment-triggered [automations](/docs/apis/automations/overview) (`comment_keyword`) when the private reply that carries the DM cannot be sent. They appear as the activity row `status: "failed"` with the reason on `actionResults[].errorDetails`.
None of them are retried **automatically** — the Instagram Send API has no idempotency key, so an automatic retry risks delivering the DM twice. Handling differs per code (see **Action** below): most are permanent for that specific comment, `492` needs the account reconnected, and `493` clears on its own when the hourly limit resets.
| Code | HTTP | Meaning |
| ---- | ---- | -------------------------------------------------------------------------------------------------------------------------------------- |
| 490 | 400 | The comment no longer exists — Instagram reported the comment ID itself as invalid. |
| 491 | 400 | Instagram declined to accept a private reply to this comment. One code, several causes — see the note below. |
| 492 | 403 | The account is missing the `instagram_business_manage_comments` permission. Reconnect the account to grant it. |
| 493 | 429 | Instagram's hourly private-reply limit (750/hour per account) was reached. Clears when the hour rolls over. |
| 494 | 500 | The automation could not run because the source comment ID was unavailable (internal misconfiguration; no fallback is attempted). |
| 495 | 400 | Instagram rejected the private reply for a reason not yet mapped to a specific code. Instagram's own explanation is on `errorDetails`. |
**Code 491 covers several causes that Instagram does not distinguish, and 490 is the narrow exception.** Instagram returns one shared error for a comment that is more than **7 days** old, a comment that **already received a reply** (only one private reply per comment is ever allowed), a **deleted** comment, and a commenter who **blocks message requests**. All of those report `491`.
`490` is reported only in the narrower case where Instagram identifies the comment ID as invalid outright rather than returning the shared bucket — so a deleted comment can surface as **either** `490` or `491` depending on which Instagram returns.
Because the API does not separate these, always read `errorDetails`: it carries Instagram's own wording, which is usually specific about the cause.
**Code `489` is reserved and not currently returned.** It is held for the "this comment already has a reply" case, which Instagram does not presently expose as a distinct signal — that case reports `491` today. It is listed here only so the number is not reused.
**A genuinely expired or invalid connection is not in this range.** If the stored Instagram credential has expired, the activity row is `status: "auth_error"` rather than `failed`, and reconnecting the account is the correct fix. With the exception of `492` — a missing permission, granted by reconnecting the account — the codes above are comment-level conditions and never mean "relink".
These codes appear in **two different shapes** depending on where you read them, and the field carrying Instagram's reason is named differently in each.
**1. On the automation activity row** — what [`GET /automations/:id/activity`](/docs/apis/automations/get-activity) returns. Instagram's reason is on `actionResults[].errorDetails`:
```json theme={"system"}
{
"status": "failed",
"commentId": "18012345678905555",
"actionResults": [
{
"type": "send_dm",
"status": "failed",
"errorDetails": "Cannot send private reply: This comment is no longer eligible for a private reply."
}
]
}
```
**2. As a direct API error envelope** — the standard error shape, where the same reason is on `details`:
```json theme={"system"}
{
"action": "messages",
"status": "error",
"code": 491,
"message": "Instagram would not accept a private reply to this comment. The comment may be more than 7 days old, may already have a reply, may have been deleted, or the commenter may not allow message requests.",
"details": "Cannot send private reply: This comment is no longer eligible for a private reply.",
"platform": "instagram"
}
```
For a comment-triggered automation you will almost always be reading shape 1. `errorDetails` there carries the same string the envelope puts in `details`.
**Action:**
* **490, 491, 495** — per-comment conditions. They cannot be recovered for that specific comment, and no retry will help; the automation works normally on the next fresh comment. Read `errorDetails` for Instagram's stated reason.
* **492** — reconnect the Instagram account, granting all requested permissions. This is an account-level fix and will otherwise affect every comment.
* **493** — no action needed beyond waiting; the hourly limit resets on its own. Not retried automatically, so the DM for that comment is not sent.
* **494** — internal misconfiguration, not a customer-side condition. Contact support if it recurs.
**A `sent` status does not guarantee delivery.** Separately from the failures above, a private reply that Instagram *accepts* (`status: "sent"`) can still be silently dropped when the recipient's Instagram **Message requests** setting blocks strangers — this produces no error code at all. See [Automation DM Sent but Not Delivered](/docs/help-center/technical-support/automation_dm_sent_but_not_delivered).
### X/Twitter BYO Key Errors
The following error codes are specific to X/Twitter BYO (Bring Your Own) key operations:
**Code 272 - Failed to Verify BYO Twitter Identity (HTTP 400)**
Ayrshare could not confirm your X/Twitter identity using your BYO consumer keys and the OAuth tokens stored at link time. The response shape varies by which call triggered it; both forms map to the same three sub-cases below. Verify which one applies by logging into [x.com](https://x.com) with the account that owns the BYO Developer App.
The post path emits a minimal response:
```json theme={"system"}
{
"status": "error",
"code": 272,
"message": "Failed to verify BYO Twitter identity",
"platform": "twitter"
}
```
The analytics path emits a longer, self-documenting message and may include a `details` field carrying X's raw error string:
```json theme={"system"}
{
"action": "post",
"status": "error",
"code": 272,
"message": "There is an issue authorizing your X/Twitter account. Login to x.com to verify your account status and then try unlinking Twitter and relinking on the social accounts page.",
"resolution": {
"relink": true,
"platform": "twitter"
},
"details": "The user used for authentication is suspended"
}
```
When present, `details` mirrors the X-side hint and is the most reliable single signal for which sub-case below applies.
**Account suspended.** Logging into x.com shows a suspension notice. **Action:** Contact X support. Re-linking will not restore access until X reinstates the account.
**Account locked.** Logging into x.com presents an unlock challenge (CAPTCHA, phone verification, etc.). **Action:** Complete the unlock challenge on x.com, then retry the request. No re-link is required.
**Identity or key mismatch.** Your X account is in good standing on x.com, but your BYO consumer keys belong to a different X Developer App than the OAuth tokens stored at link time. **Action:** Re-link X under Social Accounts and authorize with the same X account that owns the BYO Developer App.
**Code 416 — X Credits Depleted (HTTP 402)**
Your X Developer account has no API credits loaded. All X API calls require credits.
```json theme={"system"}
{
"status": "error",
"code": 416,
"message": "Your enrolled account does not have any credits to fulfill this request. Purchase credits at console.x.com.",
"platform": "twitter"
}
```
**Action:** Go to [console.x.com](https://console.x.com) → Billing → Credits and purchase credits. Even \$5 is enough for hundreds of API calls.
**Code 417 — OAuth 1.0a App Permissions (HTTP 403)**
Your X Access Token does not have the correct permissions for the requested operation.
```json theme={"system"}
{
"status": "error",
"code": 417,
"message": "Your client app is not configured with the appropriate oauth1 app permissions. Set app to 'Read and write and Direct message', then regenerate your Access Token.",
"platform": "twitter"
}
```
You may also see the response header `x-access-level: read`, which confirms your Access Token was generated with read-only permissions.
**Action:** In the X Developer Console, update your app permissions to **Read and write and Direct message**, then regenerate your Access Token under Keys and tokens. The new token will inherit the updated permissions. See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys#troubleshooting) for details.
**Code 419 - Missing BYO Credentials (HTTP 400)**
X/Twitter operations require BYO API credentials in the request headers. Ayrshare returns code 419 when both headers are missing, and also when only one of the pair is present. The `message` string varies depending on which header(s) are missing.
When both `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret` are missing:
```json theme={"system"}
{
"action": "x_credentials_required",
"status": "error",
"code": 419,
"message": "X/Twitter operations require your own API credentials. Missing: X-Twitter-OAuth1-Api-Key, X-Twitter-OAuth1-Api-Secret. Please provide your X Developer App credentials in the request headers. See https://docs.ayrshare.com/x-api-setup for setup instructions.",
"resolution": {
"docs": "https://docs.ayrshare.com/x-api-setup"
},
"platform": "twitter"
}
```
When only one of the pair is present (for example, the key without the secret):
```json theme={"system"}
{
"action": "x_credentials_required",
"status": "error",
"code": 419,
"message": "You provided X-Twitter-OAuth1-Api-Key but not X-Twitter-OAuth1-Api-Secret. OAuth 1.0a requires both. Missing: X-Twitter-OAuth1-Api-Secret. See https://docs.ayrshare.com/x-api-setup for setup instructions.",
"resolution": {
"docs": "https://docs.ayrshare.com/x-api-setup"
},
"platform": "twitter"
}
```
**Action:** Send both `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret` on every X-bound request. If you provide one without the other, the request is rejected with the same code. See the [X BYO Keys Header Reference](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys#header-reference) for the full header list.
**Code 423 — Legacy X/Twitter OAuth No Longer Supported (HTTP 403)**
Returned when an X/Twitter request relies on the legacy (non-BYO) OAuth path, which is no longer supported. X API access now requires your own X Developer App credentials supplied via request headers.
```json theme={"system"}
{
"status": "error",
"code": 423,
"message": "X (Twitter) API access now requires your own API credentials. Include X-Twitter-OAuth1-Api-Key and X-Twitter-OAuth1-Api-Secret headers in your request. Setup guide: https://docs.ayrshare.com/dashboard/connect-social-accounts/x-twitter-byo-keys",
"platform": "twitter"
}
```
**Action:** Configure an X Developer App and send the `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret` headers on every X-bound request. See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for the full setup steps.
### Caption Enhancement Errors
**Code 441 — Caption Enhancement Failed (HTTP 502)**
Returned when a caption enhancement (for example [`shortenLinks`](/docs/apis/post/post)) fails for one or more platforms while preparing a post. Each affected platform appears in the `errors` array with `source: "handlePostAdditions"` and `code: 441`.
When only some platforms fail, the other platforms still post successfully and their results appear in `postIds`. In that case the top-level `status` is `"error"` but `postIds` is non-empty — clients should treat `status` and `errors[]` as complementary rather than mutually exclusive.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"platform": "twitter",
"status": "error",
"source": "handlePostAdditions",
"code": 441,
"message": "Caption enhancement failed for twitter. . Post was not sent to this platform."
}
],
"postIds": [
{
"status": "success",
"id": "...",
"postUrl": "...",
"platform": "bluesky"
}
],
"id": "..."
}
```
If **all** platforms fail enhancement, the response is a top-level `code: 441` with HTTP `502` and no post is created:
```json theme={"system"}
{
"status": "error",
"action": "post",
"code": 441,
"message": "Caption enhancement failed. See error details for affected platforms.",
"errors": [
{
"platform": "twitter",
"status": "error",
"source": "handlePostAdditions",
"code": 441,
"message": "Caption enhancement failed for twitter. "
}
]
}
```
**Action:** Caption enhancement failures are typically transient (the underlying shortener or enhancement service returned an error).
* **If `postIds` is non-empty** (some platforms posted successfully), do **not** resubmit the full platform set — that would duplicate the post on the successful platforms. Instead, inspect `errors[]` to identify the failed platforms and retry the request with only those platforms, or rely on your own idempotent retry flow.
* **If `postIds` is empty or missing** (total failure at schedule/post time), safely retry the full request.
* If the failure persists, submit the post without the enhancement flag (for example, drop `shortenLinks`) or contact support.
### Media Fetch / Crawler Access Errors
**Code 479 — Social Network Could Not Fetch Media / Crawler Blocked (HTTP 400)**
Dedicated, **non-retryable** code returned when Meta could not fetch the media from the provided URL **even after Ayrshare re-hosted it on its own CDN** as a fallback. This indicates the host is blocking Meta's crawlers (`facebookexternalhit` / `Facebot`) via `robots.txt` or CDN / WAF rules, or the source is unreachable server-side. References Meta/Instagram subcode **2207052**.
Because Ayrshare's CDN re-host fallback has already been attempted and also failed, retrying will not help — the fix is on the hosting side (allow Meta's crawlers or serve the media from a reachable, unblocked host). This error carries `retryAvailable: false`.
```json theme={"system"}
{
"status": "error",
"errors": [{
"action": "post",
"code": 479,
"retryAvailable": false,
"message": "The social network could not fetch the media from this URL, even after Ayrshare re-hosted it on its own CDN (Meta subcode 2207052). The host is blocking Meta's crawlers (facebookexternalhit / Facebot) via robots.txt or CDN/WAF rules, or the source is unreachable server-side. This is not retryable — allow Meta's crawlers or serve the media from a reachable host.",
"details": "Media download has failed.: The media could not be fetched from the provided URI...",
"platform": "instagram",
"status": "error"
}],
"postIds": [],
"id": "..."
}
```
**Action:** See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) for full troubleshooting, including `robots.txt` snippets and a verification command.
**Code 440 — Instagram Could Not Ingest Media (Transient, HTTP 400)**
Returned for genuinely transient Meta ingestion issues — Meta/Instagram subcodes **2207032** ("download too slow") / **2207003** ("create media fail"), or unclassified ingestion exhaustion — after Meta has failed to ingest the media across multiple internal retries. Unlike code 479, this is **retryable** via [`/post/retry`](/docs/apis/post/retry-post).
If the failure is instead a host-side crawler block or an unreachable source (subcode 2207052, and Ayrshare's CDN re-host fallback also failed), you'll get **code 479** instead — see above.
`retryAvailable` is `true` for transient ingestion failures; a small number of 440 cases (for example, source media exceeding size limits) return `false`.
```json theme={"system"}
{
"status": "error",
"errors": [{
"action": "post",
"code": 440,
"retryAvailable": true,
"message": "Instagram could not ingest this media after multiple retries. This may be a transient Instagram processing issue or a URL accessibility problem. Retry the post via /post/retry",
"platform": "instagram",
"status": "error"
}],
"postIds": [],
"id": "..."
}
```
**Code 138 — Instagram Media Fetch Blocked (HTTP 400)**
Fallback code for Instagram media-fetch failures when the upstream response is less specific than the one that triggers code 479. The `details` string typically contains `"Restricted by robots.txt"` or `"HTTP error code 403"`. Code 138 is also used for aspect-ratio / format issues and other generic Instagram errors, so the media-fetch variant is identifiable by the `details` string. When the block is a confirmed host-side crawler block (subcode 2207052), you'll typically see the dedicated **code 479** instead; for transient ingestion failures see **code 440**.
```json theme={"system"}
{
"status": "error",
"errors": [{
"retryAvailable": true,
"status": "error",
"code": 138,
"details": "Media download has failed.: The media could not be fetched from the provided URI. Video download failed with: HTTP error code 403. Restricted by robots.txt",
"action": "post",
"platform": "instagram",
"message": "Instagram Error: Instagram cannot process your post at this time. Please try your post again."
}],
"postIds": [],
"id": "..."
}
```
**Code 379 — Threads Posting Error**
Returned when Threads publishing fails. Most commonly caused by the same media-fetch issue as codes 479 / 138 when publishing to both platforms with the same `mediaUrl`. The Threads API does not return detail strings, so diagnosis usually requires checking for a co-occurring Instagram error in the same publish — a **479** (host-side crawler block / unreachable source) or **440** (transient ingestion) on Instagram is the usual signal.
```json theme={"system"}
{
"status": "error",
"errors": [{
"status": "error",
"code": 379,
"message": "Error posting to Threads.",
"action": "post",
"platform": "threads"
}],
"postIds": [],
"id": "..."
}
```
**Action:** See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked) for full troubleshooting, including `robots.txt` snippets and a verification command.
### Facebook Analytics Rate Limit
**Code 444 — Facebook Page Analytics Rate Limit (HTTP 429)**
Returned when a Facebook Page has exceeded Meta's per-Page rate limit on the analytics endpoint. The underlying Meta error is `80001` ("There have been too many calls to this Page account."). The Page remains linked and publishing continues to work — only the analytics fan-out for that Page is throttled.
When the throttle is detected for a single post in a [`/history/facebook`](/docs/apis/history/history-platform) or [analytics](/docs/apis/analytics/social) response, each affected post carries `code: 444` at `facebook.code` with `errCode: 80001`:
```json theme={"system"}
{
"status": "error",
"facebook": {
"action": "rate limit",
"status": "error",
"code": 444,
"errCode": 80001,
"message": "Facebook Page has hit its per-Page rate limit on the analytics endpoint. Please wait a few minutes and retry.",
"pageId": "...",
"id": "..."
},
"httpErrorCode": 444,
"lastUpdated": "...",
"nextUpdate": "..."
}
```
**Action:** Wait a few minutes and retry. Meta's per-Page rate-limit window typically resolves within the hour without any action on the Page. Do **not** prompt the user to relink the account — this is a transient throttle on Meta's side, not an authorization failure.
If you previously handled this condition as `code: 161` ("Facebook authorization error … unlink and re-link"), update your integration to recognize `code: 444` and retry with backoff instead of initiating a relink flow. The `161` classification was corrected in April 2026.
### Meta Identity Verification
**Code 326 — Meta Identity Verification Required (HTTP 403)**
Returned when Meta requires additional identity verification for the connected account before it will accept the request. This applies across Meta platforms — Facebook, Instagram, Facebook Groups, Threads, and Messenger. Reconnecting the account does **not** resolve this; the verification must be completed on Meta's side.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 326,
"message": "Meta is requesting additional identity verification for this account. Complete it at https://www.facebook.com/business-support-home and then retry. Reconnecting the account will not resolve this.",
"platform": "facebook"
}
]
}
```
**Action:** Have the account owner complete Meta's identity verification at [Meta Business Support](https://www.facebook.com/business-support-home), then retry the request. Do **not** prompt the user to relink the account — relinking will not clear this requirement.
### Facebook Account Restriction
**Code 476 — Facebook Account Restriction (HTTP 400)**
Returned when a post to Facebook fails because Meta has placed a restriction on the account (Meta error subcodes `2424009` and `1404078`, or Meta's restriction wording when the error carries no subcode). This is an account-level restriction, not a transient publishing hiccup — it is **non-retryable** and carries **no** `retryAvailable` flag. Resubmitting the same post will not succeed until the restriction is resolved with Meta. The account remains linked to Ayrshare; no relink is required.
Meta does not return the specific restriction reason through the API, so the customer must check Meta's Account Status page directly to see the reason and appeal. When Meta supplies its own verbatim text, Ayrshare surfaces it in the `details` field. Ayrshare also sends the account owner a notification email when the restriction is detected.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 476,
"message": "There is a Facebook restriction on your account. Log in to Facebook, click your profile picture (top-right), open the Help section and select Account Status. Meta's support assistant there surfaces the specific restriction reason (which the API doesn't return) and lets you appeal.",
"details": "...",
"platform": "facebook"
}
]
}
```
**Action:** Log in to Facebook, click your profile picture (top-right), open the Help section and select **Account Status**. Meta's support assistant there surfaces the specific restriction reason and lets you appeal. Because the restriction is enforced by Meta at the account level, this code is non-retryable — do not build automatic retry logic around it; resolve the restriction with Meta first.
### Image Format Conversion Errors
Ayrshare automatically converts WebP, HEIC, HEIF, and AVIF images to JPEG before posting to platforms that don't accept them (Instagram, LinkedIn, TikTok, Google My Business, Threads, and Snapchat for WebP; all platforms for HEIC, HEIF, and AVIF). Conversion runs transparently at send time. The three errors below fire only when the conversion pipeline itself can't complete; if the source image is already in a supported format, no conversion is attempted and these codes will not surface.
**Code 450 — Image Format Conversion Failed (HTTP 400)**
The image was downloaded but could not be re-encoded as JPEG. Most common causes are a corrupt source file, an unexpected internal format inside the container, or an image that exceeds the conversion size cap.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "image conversion",
"status": "error",
"code": 450,
"message": "The image format could not be converted. The source image may be corrupt or inaccessible. Please verify the media URL and try again.",
"platform": "instagram"
}
]
}
```
**Action:** Open the source `mediaUrl` directly in a browser to confirm it renders. If it does, re-export the image to a clean JPEG or PNG and retry the post.
**Code 451 — Image Download Failed for Conversion (HTTP 400)**
The conversion pipeline could not fetch the source image. Typical causes include a 4xx/5xx response from the origin, a network timeout, a redirect chain that exceeds the hop limit, or a URL that resolves to a non-public address (blocked by the SSRF guard). The `details` field, when present, carries the underlying cause string.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "image conversion",
"status": "error",
"code": 451,
"message": "The image could not be downloaded for format conversion.",
"details": "HTTP 403 from origin",
"platform": "linkedin"
}
]
}
```
**Action:** Confirm the `mediaUrl` is publicly reachable (no auth, no `robots.txt` blocks, resolves over HTTPS). If the URL redirects, ensure the final destination is also public and not on a private network.
**Code 452 — Converted Image Upload Failed (HTTP 500)**
Conversion succeeded but Ayrshare could not stage the converted JPEG to its temporary storage bucket. This is an internal failure on the Ayrshare side and is retryable.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "image conversion",
"status": "error",
"code": 452,
"message": "An error occurred uploading the converted image. Please try again.",
"platform": "tiktok"
}
]
}
```
**Action:** Retry the post. If the error persists across multiple retries, contact support with the `mediaUrl` and approximate timestamp.
### YouTube Transient Upload Errors
The following error codes provide specific signals for YouTube upload failures that are typically transient and safe to retry. Both responses include `retryAvailable: true`, so integrations can branch on that boolean rather than on the HTTP status code.
Most prior `code: 176` responses for YouTube uploads now route to **453** (transient timeout) or **454** (transient service unavailable), both with `retryAvailable: true`. If your integration filters on HTTP 500 to retry YouTube uploads, switch to filtering on the `retryAvailable` field on the response body.
**Code 453 — YouTube Upload Timed Out (HTTP 504)**
Returned when Google's YouTube ingest pipeline timed out while accepting the upload. This is typically transient and resolves on its own within a minute or two.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 453,
"message": "YouTube upload timed out (Google ingest). This is typically transient; please retry in 1–2 minutes.",
"retryAvailable": true,
"platform": "youtube"
}
]
}
```
**Action:** Retry the post after 1–2 minutes with exponential backoff. Branch on the `retryAvailable` field on the response body rather than HTTP status to detect retryable failures. You can use the [retry post](/docs/apis/post/retry-post) endpoint to resubmit the same payload.
**Code 454 — YouTube Upload Service Temporarily Unavailable (HTTP 503)**
Returned when YouTube's upload endpoint returns a 5xx status, or when the connection to YouTube was reset or timed out at the socket layer (`ECONNRESET`, `ETIMEDOUT`, `ESOCKETTIMEDOUT`). These conditions are transient.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 454,
"message": "YouTube upload service temporarily unavailable. Please retry.",
"retryAvailable": true,
"platform": "youtube"
}
]
}
```
**Action:** Retry the post with exponential backoff. Branch on the `retryAvailable` field on the response body rather than HTTP status to detect retryable failures. You can use the [retry post](/docs/apis/post/retry-post) endpoint to resubmit the same payload.
### YouTube Thumbnail Errors Code 307
Code `307` is returned when a custom YouTube `thumbNail` cannot be applied. When the video itself posts successfully, this does **not** fail the post — the YouTube result keeps `status: "success"` and surfaces the failure additively in a `warnings` array (`feature: "thumbnail"`, `code: 307`). The legacy `thumbnail` sub-object is retained for backward compatibility.
The most common cause is an **unverified YouTube channel**. When a channel has not completed phone verification, YouTube returns an upstream `403` with the generic message `"The authenticated user doesn't have permissions to upload and set custom video thumbnails"`. That wording sounds like an OAuth problem, but in practice it is almost always a verification problem, so verify the channel first. Re-linking the YouTube account is a secondary cause.
```json theme={"system"}
{
"status": "success",
"id": "",
"thumbnail": {
"action": "post",
"status": "error",
"code": 307,
"message": "Your YouTube channel must be verified to set a custom thumbnail. Verify your channel at https://www.youtube.com/verify (phone verification). If your channel is already verified, try unlinking and re-linking your YouTube account to restore permissions.",
"details": ""
},
"warnings": [
{
"feature": "thumbnail",
"code": 307,
"message": "Your YouTube channel must be verified to set a custom thumbnail. Verify your channel at https://www.youtube.com/verify (phone verification). If your channel is already verified, try unlinking and re-linking your YouTube account to restore permissions.",
"details": ""
}
]
}
```
Ayrshare also validates the thumbnail before publishing where possible: the file must be a **PNG or JPG/JPEG**, **2MB or less**, and served from a **reachable URL**.
A thumbnail problem **never fails the post** — the video always publishes and the failure is always surfaced as a non-fatal `warnings` entry (top-level `status` stays `"success"`). This holds regardless of when the problem is detected:
* **Caught before upload.** When pre-publish validation can definitively tell the thumbnail is invalid (wrong file type, confirmed over 2MB, or an unreachable URL), Ayrshare skips the thumbnail, still publishes the video, and reports the precise reason in `warnings` — so you avoid a doomed upload attempt and get a clearer message than the provider would return.
* **Caught after upload.** When the failure is only detectable once YouTube processes the request (for example the unverified-channel `403`, or a `413` for an oversized image), the video is already live and the failure is surfaced in the same `warnings` array.
Either way the response looks like the `status: "success"` + `warnings` example shown earlier in this section.
**Action:** Verify your YouTube channel at [https://www.youtube.com/verify](https://www.youtube.com/verify) (phone verification). If your channel is already verified and thumbnails still fail, unlink and re-link your YouTube account in [Social Accounts](https://app.ayrshare.com/social-accounts) and grant all permissions. See [YouTube Thumbnail Not Applied (Unverified Channel)](/docs/help-center/technical-support/youtube_thumbnail_unverified_channel) for the full troubleshooting guide.
### Reddit Posting Errors
**Code 442 — Reddit Banned Subreddit (HTTP 400)**
Returned when the account has been banned from posting to the target subreddit. This is **not** retryable — the post will not succeed if resubmitted as-is. The message includes the affected subreddit name (for example, `r/news`).
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 442,
"message": "You've been banned from posting to r/news. This post will not succeed on retry — remove it from your target subreddits.",
"platform": "reddit"
}
]
}
```
**Action:** Remove the banned subreddit from your target subreddits. Retrying the post unchanged will not succeed.
**Code 443 — Reddit Disallowed Word in Title (HTTP 400)**
Returned when a subreddit rejects the post because its title contains a disallowed word. Edit the title before retrying — resubmitting as-is will not succeed. The message includes the affected subreddit name (for example, `r/news`).
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "post",
"status": "error",
"code": 443,
"message": "r/news rejected this post because the title contains a disallowed word. Edit the title before retrying — retrying as-is will not succeed.",
"platform": "reddit"
}
]
}
```
**Action:** Edit the post title to remove the disallowed word, then retry.
### Moderation Errors
**Code 438 — Moderation Input Rejected (HTTP 400)**
Returned by [`POST /validate/moderation`](/docs/apis/post/post) when the AI provider rejects the supplied input — for example, an unsupported file type. This is an input problem with the request, not a transient processing failure.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "moderation",
"status": "error",
"code": 438,
"message": "There was an issue with the AI processing."
}
]
}
```
**Action:** Verify the moderation input is valid and uses a supported file type, then resubmit.
Contrast code 438 with **code 331**. Code 331 covers the same moderation scenario but represents a genuine processing failure on the provider side (HTTP 500, message "There was an issue with the AI processing. Please try again."). Code 331 is a transient server-side failure you can retry, whereas code 438 indicates the input itself was rejected and must be corrected before retrying.
### LinkedIn Analytics Errors
**Code 475 — Re-link LinkedIn Profile for Analytics (HTTP 403)**
Returned by [`POST /analytics/post`](/docs/apis/analytics/post) and [`POST /analytics/social`](/docs/apis/analytics/social) for a personal (member) LinkedIn profile that was linked before member analytics shipped. These profiles lack the LinkedIn member analytics scopes (`r_member_postAnalytics`, `r_member_profileAnalytics`), so LinkedIn rejects the analytics request. Posting is unaffected.
```json theme={"system"}
{
"action": "authorization",
"status": "error",
"code": 475,
"message": "Your LinkedIn profile is missing the analytics permissions. Please re-link your LinkedIn profile to enable analytics.",
"resolution": {
"relink": true,
"platform": "linkedin"
}
}
```
**Action:** Have the account owner re-link their LinkedIn profile in [Social Accounts](https://app.ayrshare.com/social-accounts) to grant the new analytics scopes, then retry the analytics request. After re-linking, allow a few minutes before the error clears: Ayrshare caches this error briefly and LinkedIn also caches the token's permissions, so a re-linked profile can keep returning code `475` for up to \~5-10 minutes before analytics succeed.
### TikTok Comment Errors
**Code 288 — TikTok Comment Deferred / Post Still Processing (HTTP 400)**
TikTok processes videos asynchronously, so a freshly published post's `id` is `"pending"` until TikTok's `post.publish.publicly_available` webhook resolves the real video id. A [get-comments](/docs/apis/comments/get-comments), comment, or reply request against a post that is still processing (or one whose `id` is `"failed"`) is refused before any call to TikTok and returns code 288 instead of a generic failure.
```json theme={"system"}
{
"status": "error",
"errors": [
{
"action": "get",
"status": "error",
"code": 288,
"message": "TikTok video is still processing; the action is deferred until the post is live.",
"platform": "tiktok"
}
]
}
```
**Action:** Wait until TikTok finishes processing, then retry. Listen for the [`tikTokPublished` Scheduled Action webhook](/docs/apis/webhooks/actions#scheduled-action) or poll [/history](/docs/apis/history/overview) until the post `id` is the resolved numeric video id. A [first comment](/docs/apis/post/overview#first-comment) is posted automatically once the post resolves, so it does not need to be retried. For a `"failed"` post the message instead notes the video failed to publish and the action will not run.
### Expired or Unavailable Story Errors
**Code 485 — Instagram / Facebook Story Comments and Instagram Story Analytics (HTTP 404 when representative)**
Stories can become expired or unavailable after their availability window. After that window, comments or insights cannot be retrieved. Code `485` identifies:
* expired or unavailable Instagram and Facebook Story legs from [get-comments](/docs/apis/comments/get-comments); and
* an expired or unavailable Instagram Story leg from [`POST /analytics/post`](/docs/apis/analytics/post).
Facebook Story analytics are unavailable and are not covered by code `485`. Clients should match the numeric `code`, not the exact message text, which can vary or be translated.
On a multiplatform read where at least one other platform succeeds, the failed leg appears in the top-level `errors[]` array while the healthy platforms return normally. The overall response is **HTTP `200`** with top-level `status: "partial"` (see [Multiplatform Reads & Partial Success](/docs/apis/comments/get-comments#multiplatform-reads--partial-success) for comments and [analytics](/docs/apis/analytics/post#multiplatform-reads--partial-success)).
#### Get Comments Partial-Success Example
```json theme={"system"}
{
"facebook": [
{
"comment": "What a great comment",
"commentId": "806720068141593_1849585385469876",
"created": "2026-07-14T19:55:28Z",
"likeCount": 12,
"platform": "facebook"
}
],
"status": "partial",
"id": "Ut2fWU6XkqkMayHGnJZ7",
"lastUpdated": "2026-07-14T22:30:13.035Z",
"nextUpdate": "2026-07-14T22:41:13.035Z",
"errors": [
{
"platform": "instagram",
"status": "error",
"code": 485,
"message": "Instagram Story expired or unavailable — comments/insights cannot be retrieved.",
"id": "17895695668004550"
}
]
}
```
#### Post Analytics Partial-Success Example
```json theme={"system"}
{
"facebook": {
"id": "1397547544885713_2159201585286968",
"postUrl": "https://www.facebook.com/1397547544885713_2159201585286968",
"analytics": {
"commentsCount": 1,
"likeCount": 23,
"sharesCount": 12,
"mediaView": 450
},
"lastUpdated": "2026-07-14T18:44:29.778Z",
"nextUpdate": "2026-07-14T19:19:29.778Z"
},
"status": "partial",
"id": "IHvCLacgPc6hMU9IQ6oK",
"errors": [
{
"platform": "instagram",
"status": "error",
"code": 485,
"message": "Instagram Story expired or unavailable — comments/insights cannot be retrieved.",
"id": "17895695668004550"
}
]
}
```
When every platform fails, the response has top-level `status: "error"` and includes the full `errors[]` array. Representative code `485` maps to HTTP `404`; other representative codes use their own HTTP mappings.
**Action:** Treat code `485` as a signal that the requested Story comments or insights cannot be retrieved. Match on the code rather than drawing permanent-failure, retryability, or account-link conclusions from the message text.
### Error Message Translation
The API error message response can be automatically translated to the language of your choice.
This is useful if you want to display the error directly to your user in their preferred language.
See here if you want to [choose the language of the social linking page](/docs/multiple-users/manage-user-profiles#set-language-for-the-social-linking-page).
In the header include:
```json theme={"system"}
"Translate-Error-Message": "Language_Code"
```
Where the `Language_Code` is one of the available[ language codes](/docs/iso-codes/language).
For example, the following will translate the error to French.
```json theme={"system"}
"Translate-Error-Message": "fr" // Translate to French
```
Our system will automatically detect the error message language.
# HTTP Status Codes
Source: https://www.ayrshare.com/docs/errors/errors-http
HTTP codes returned with a response.
Errors will return with [standard HTTP status codes](https://tools.ietf.org/html/rfc2616#section-10).
Status codes are as follows:
1xx: Informational - Communicates transfer protocol-level information.
2xx: Success - The request was successful.
3xx: Redirection - The client must take some additional action to complete the request.
4xx: Client Error - Failed request due to client error.
5xx: Server Error - Failed request due to server error.
### 200 Success
A successful request was made.
### 400 Bad Request
A `400 Bad Request` error means that the server was unable to proceed with the request. The most common cause of the error is bad syntax in the request URL or body.
### 401 Unauthorized
`401 Unauthorized` errors are usually caused by a problem in the request header of your API call, i.e. you didn't use a valid API key to make the API call.
### 403 Access Denied
When your application makes an API call with your API key and the request is not allowed.
A 403 might also be returned if the [User Profile is suspended](/docs/multiple-users/manage-user-profiles#reactivate-a-suspended-user-profile).
### 404 Resource Not Found
This error occurs when your application tries to call an API or fetch an entity that does not exist.
### 405 Method Not Allowed
This error indicates that the HTTP protocol methods in your request are not supported. Check the documentation for the API to see supported methods.
### 429 Rate Limit
#### User Profile Rate Limits
Each User Profile has a rate limit of 300 API requests per 5-minute interval. You can monitor your rate limit usage through the response headers:
`x-ratelimit-max`: Shows your maximum allowed requests per 5-minute period
`x-ratelimit-count`: Displays how many requests you've made in the current 5-minute period
We recommend checking for 429 error code responses. If you see a 429 error, you've reached your rate
limit. Repeated attempts to exceed the rate limit may result in the User Profile being suspended.
Learn more about [handling rate limits](https://www.ayrshare.com/blog/complete-guide-to-handling-rate-limits-prevent-429-errors/) for multiple user profiles.
#### Platform Analytics Rate Limits
HTTP `429` may also be returned when a social network throttles analytics calls for a specific account — independent of your Ayrshare User Profile limits. In that case the response carries a platform-specific Ayrshare error code (for example [`code: 444`](/docs/errors/errors-ayrshare#facebook-analytics-rate-limit) for Facebook per-Page analytics throttles). Inspect the `code` field to distinguish a profile rate limit from a platform-side throttle, and retry with backoff rather than prompting the user to relink.
#### User Profile Deletion Rate Limits
You may delete 8 user profiles per second. Please stagger API calls if you need to bulk delete.
#### Rate Limit Protection and Suspension Policy
To protect our system integrity, we implement automatic suspension if a User Profile exceeds rate limits too frequently.
Here's how it works:
When you make API requests, you must carefully manage the 5-minute window.
For example, if you make 300 requests in one minute, you'll need to wait four more minutes before making additional requests.
Any requests during this waiting period will trigger a `429` error response.
If a User Profile accumulates 1,000 rate limit violations (429 errors) within a 24-hour period, the profile will be automatically suspended.
After a 5-minute waiting period expires, you can resume making requests up to the standard limit of 300 per 5-minute window.
### 500 Internal Server Error
A `500 Internal Server Error` indicates that Ayrshare is experiencing an internal error or processing failed.
# Errors Overview
Source: https://www.ayrshare.com/docs/errors/overview
Reference for the error codes you will see on Ayrshare.
## API and HTTP Errors
Errors are important to understand when something goes wrong. Our errors are dynamically built upon the numerous scenarios from the social networks, so we try to tailor the message based on the situation.
Two types of errors exist. Top-level HTTP status codes, with 200 as successful, and Ayrshare error codes associated with individual posts.
# Bluesky
Source: https://www.ayrshare.com/docs/media-guidelines/bluesky
Image and video media requirements for [Bluesky](/apis/post/social-networks/bluesky)
## Images
Max image size: 1 MB.
Supported formats: JPG, Animated GIF, and PNG.
Recommended size for images: 1200 x 627 px.
Annimated GIF will be sent as a video. Only one animated GIF can be sent per post.
## Video
Max video size: 100 MB.
Supported formats: MP4.
Duration max: 3 minutes.
Duration min: 1 second.
Aspect ratio must be between 1:3 and 3:1.
# Facebook Pages
Source: https://www.ayrshare.com/docs/media-guidelines/facebook_pages
Image and video media requirements for [Facebook](/apis/post/social-networks/facebook)
## Images
Max image size: 10 MB
Supported formats: JPEG, BMP, PNG, [Animated
GIF](/docs/apis/post/social-networks/facebook#animated-gifs), and TIFF.
Maximum height: 2048 px.
Maximum width: 2048 px.
Recommended upload size of 1,200 x 630 px.
Appears in feed at a max width of 470 px and will scale to a max of 1:1.
Appears on page at a max width of 504 px and will scale to a max of 1:1.
HEIC, HEIF, and AVIF images are converted to JPEG before posting. The conversion preserves the
image's color rendering and writes a small XMP packet carrying only the
`Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one — which Facebook renders
as an "AI content" label. No other metadata is carried over: not EXIF, and nothing else from the
original XMP, so a location, a creator name or a copyright line can't be published by accident. The
C2PA signature does not survive a re-encode. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Video
Max video size: 10 GB. Please contact us about Enterprise plans for larger files.
Supported formats: MP4, MOV, and AVI.
Duration max: 4 hours.
Recommended video dimensions is 1280 x 720 px for landscape and portrait.
Landscape aspect ratio is 16:9.
Portrait aspect ratio is 9:16.
Video max frames 30fps.
### Video Thumbnail
Supported formats: BMP, GIF, JPEG, PNG, TIFF
Max image size: 10 MB
Dimensions: There are no image dimension requirements, but it should share the same aspect ratio
as your video.
## Reels
Max video size: 2 GB.
Supported formats: MP4, MOV, and AVI.
Minimum video width: 540 pixels.
Minimum video height: 960 pixels.
Duration: 3 seconds minimum and 90 seconds maximum.
Aspect ratio: 9:16.
Frame rate: 24 to 60 frames per second.
Video settings:
Chroma subsampling 4:2:0
Closed GOP (2-5 seconds)
Compression: H.264, H.265 (VP9, AV1 are also supported)
Fixed frame rate
Progressive scan
Audio settings:
Audio bitrate: 128kbs+
Channels: Stereo
Codec: AAC Low Complexity
Sample rate: 48kHz
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
Self-hosting your media? Meta's crawler must be allowed to fetch your URLs. A hard
media-fetch failure surfaces as the dedicated, non-retryable Ayrshare error code 479.
See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked)
to configure `robots.txt`.
### Reels Thumbnail
Supported formats: JPEG or PNG
Max image size: 10MB
Dimensions: There are no image dimension requirements, but it should share the same aspect ratio
as your video.
## Stories
### Photos
Format: JPEG, BMP, PNG, GIF, TIFF
Max image size: 4MB
For .png files, we recommend not exceeding 1MB or the image may appear pixelated.
### Videos
Max video size: 4 GB.
Format: MP4, MOV, and AVI.
Aspect ratio: 9:16
Resolution: 1080 x 1920 pixels (recommended). Minimum is 540 x 960 pixels.
Frame rate: 24 to 60 frames per second.
Duration: 3 seconds minimum and 90 seconds maximum. A reel published as a story on a Facebook
Page cannot exceed 60 seconds.
Video settings:
Chroma subsampling 4:2:0
Closed GOP (2-5 seconds)
Compression: H.264, H.265 (VP9, AV1 are also supported)
Fixed frame rate
Progressive scan
Audio settings:
Audio bitrate: 128kbs+
Channels: Stereo
Codec: AAC Low Complexity
Sample rate: 48kHz
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
# Google Business Profile
Source: https://www.ayrshare.com/docs/media-guidelines/google_business_profile
Image and video media requirements for [Google Business Profile](/apis/post/social-networks/google)
## Images
Image size: Between 10 KB and 5 MB.
Supported formats: JPG and PNG.
Recommended dimensions: 720 px x 720 px.
Minimum dimensions: 250 px x 250 px.
Google Business Profile generally supports landscape images. Portrait images and multi-frame
images could give an error of "*Multiframe images not supported*". Please rotate the image to
landscape and try again.
WebP, HEIC, HEIF, and AVIF images are converted to JPEG before posting, and the conversion preserves the image's color rendering and writes a small XMP packet carrying only the `Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The
C2PA signature does not survive a re-encode.
See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Video
Max video size: 26 MB.
Duration Max: 30 seconds.
Duration Min: 1 second.
Resolution: 720p or higher.
# Instagram
Source: https://www.ayrshare.com/docs/media-guidelines/instagram
Image and video media requirements for [Instagram](/apis/post/social-networks/instagram)
## Images
Max image size: 8 MB
Supported formats: JPG, GIF, and PNG. Animated GIFs will show as regular images.
Only 50 Instagram posts are allowed over a 24 hour period.
Multi-image posts are supported via a carousel.
Aspect ratio:
Within a 4:5 to 1.91:1 range.
9:16 portrait sized images are also supported.
Instagram gives leeway on the height and width as long as the aspect ratio is within the
acceptable range.
Minimum width: 320 px.
Maximum width: 1440 px.
Example sizes:
Square: 1080 x 1080 pixels (1:1 ratio).
Portrait: 1080 x 1350 pixels (4:5 ratio).
Landscape: 1080 x 566 pixels (1.91:1 ratio).
WebP, HEIC, HEIF, and AVIF images are converted to JPEG before posting. The conversion preserves
the image's color rendering and writes a small XMP packet carrying only the
`Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one — which Instagram renders
as an "AI info" label. No other metadata is carried over: not EXIF, and nothing else from the
original XMP, so a location, a creator name or a copyright line can't be published by accident. The
C2PA signature does not survive a re-encode. Note that Instagram's `autoResize` option resizes
through a separate step that carries no metadata, so leave it off if the disclosure needs to reach
Instagram. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Reels
### Reels Video
Max video size: 1 GB.
Container: MOV or MP4 (MPEG-4 Part 14), no edit lists, moov atom at the front of the file.
Audio codec: AAC, 48khz sample rate maximum, 1 or 2 channels (mono or stereo).
Video codec: HEVC or H264, progressive scan, closed GOP, 4:2:0 chroma subsampling.
Duration max: 15 minutes.
Duration min: 3 seconds.
Frame rate: 23-60 FPS.
Video size:
Maximum width (horizontal pixels): 1920 px. However, Instagram gives leeway on the height and
width as long as the aspect ratio is within the acceptable range. For example: 1080 x 1920 px
or 1920 x 1080 px.
Recommended aspect ratio: 9:16.
Recommended Resolution: 1080 x 1920 px. Minimum is 540 x 960 px.
Maximum height: 3600 px.
Required aspect ratio is between 0.01:1 and 10:1 but we recommend 9:16 to avoid cropping or
blank spaces.
Video bitrate: VBR, 25Mbps maximum.
Audio bitrate: 128kbps.
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
Self-hosting your media? Meta's crawler must be allowed to fetch your URLs. A hard
media-fetch failure now surfaces as the dedicated, non-retryable Ayrshare error code 479.
See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked)
to configure `robots.txt`.
### Reels Thumbnails
Supported formats: JPEG
Max image size: 8MB
Color Space: sRGB. Images that use other color spaces will be converted to sRGB.
Aspect ratio: Recommend 9:16 to avoid cropping or blank space. If the aspect ratio of the
original image is not 9:16, Instagram crops the image and use the middle most 9:16 rectangle as
the cover photo for the reel. If you share a reel to your feed, Instgram crop the image and use
the middle most 1:1 square as the cover photo for your feed post.
## Stories
### Story Images
Supported formats: JPEG.
Max image size: 8MB.
Aspect ratio: Recommended 9:16 to avoid cropping or blank space. Instagram gives leeway on the
height and width as long as the aspect ratio is within the acceptable range. For example: 1080 x
1920 px.
Color Space: sRGB. Images using other color spaces will have their color spaces converted to
sRGB.
### Story Video
Container: MOV or MP4 (MPEG-4 Part 14), no edit lists, moov atom at the front of the file.
Audio codec: AAC, 48khz sample rate maximum, 1 or 2 channels (mono or stereo).
Video codec: HEVC or H264, progressive scan, closed GOP, 4:2:0 chroma subsampling.
Frame rate: 23-60 FPS.
Video size:
Maximum width (horizontal pixels): 1920 px. However, Instagram gives leeway on the height and
width as long as the aspect ratio is within the acceptable range. For example: 1080 x 1920 px.
Maximum height: 3600 px.
Required aspect ratio is between 0.1:1 and 10:1 but recommend 9:16 to avoid cropping or blank
space.
Video bitrate: VBR, 25Mbps maximum.
Audio bitrate: 128kbps.
Duration: 60 seconds maximum, 3 seconds minimum.
Max video size: 100MB.
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
# LinkedIn
Source: https://www.ayrshare.com/docs/media-guidelines/linkedin
Image and video media requirements for [LinkedIn](/apis/post/social-networks/linkedin)
## Document
Max document size: 100 MB
Max pages: 300pages.
Supported formats: PPT, PPTX, DOC, DOCX, and PDF.
For additional details, please view the
[LinkedIn social network page](/docs/apis/post/social-networks/linkedin#linkedin-documents)
## Image
Max image size: 5 MB
Supported formats: JPG, GIF, Animated GIF, and PNG.
Recommended size for images or links: 1200 x 627 px.
Images must have less than 36,152,320 pixels.
WebP, HEIC, HEIF, and AVIF images are converted to JPEG before posting. The conversion preserves the
image's color rendering and writes a small XMP packet carrying only the
`Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one. No other metadata is
carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a
copyright line can't be published by accident. Note that LinkedIn strips embedded metadata when it
ingests an image, so provenance metadata — including that AI disclosure — does not survive
LinkedIn's image processing and no AI label is applied. See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Video
Max video size: 500 MB
Supported formats: MP4.
Duration max: 30 minutes.
Duration min: 3 seconds.
Aspect ratio must be between 1:2.4 and 2.4:1.
# Social Media Image & Video Requirements | Ayrshare Docs
Source: https://www.ayrshare.com/docs/media-guidelines/overview
Reference image and video requirements for Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Telegram, TikTok, X & YouTube.
## Image and Video Posting Requirements
When publishing a post to the social networks, it is important to follow each network's requirements.
By following these guidelines, you can ensure your post is accepted by the social networks and reaches the intended audience.
Please see the [post](/docs/apis/post/post) endpoint for additional details.
### Accepted File Types
Files have an accepted file ending type (extension), such as jpg, jpeg, png,
webp, gif, mp4, mov, or avi, with content-types such as image/jpeg or video/mp4.
Additionally, LinkedIn accepts file types with the following extensions: ppt,
pptx, doc, docx, and pdf.
If the media URL has special characters, e.g. ñ, please encode the special characters before sending.
Please see below for details on each network.
**Automatic image format conversion.** WebP, HEIC, HEIF, and AVIF source images are automatically converted to JPEG before posting to platforms that don't accept them natively. WebP is converted for Instagram, LinkedIn, TikTok, Google My Business, Threads, and Snapchat; HEIC, HEIF, and AVIF are converted across all supported platforms. Conversion runs transparently at send time, so you can submit any of these formats via `mediaUrls` and Ayrshare will handle the format on the destination platform's behalf. The per-platform "supported formats" lists below describe what each network ultimately accepts on the wire; you do not need to convert beforehand. See [Image Format Conversion Errors](/docs/errors/errors-ayrshare#image-format-conversion-errors) for the failure modes (codes 450, 451, 452), and [Image Metadata and Content Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials) for what happens to embedded metadata when an image is converted.
### **Maximum Images**
Max images accepted per platform in a single post:
Bluesky: 4 images.
Facebook Pages: 10 images, including a [carousel
post](/docs/apis/post/social-networks/facebook#carousel-images).
Instagram: 10 images.
Google Business Profile: 1 image.
LinkedIn: 9 images.
Pinterest: 1 image.
Reddit: 1 image.
Telegram: 1 image.
Threads: 20 images.
TikTok: 35 images.
X/Twitter: 4 images.
### **Maximum Videos**
Only ***one*** video is allowed per post for Bluesky, Facebook, Instagram, LinkedIn, Pinterest, Telegram, Threads, TikTok, X/Twitter, and YouTube. Reddit does not yet support videos.
Please be sure your video URL ends in an accepted video extension such as .mp4 or .mov, depending upon the network.
For example:
Accepted: `https://mysite.com/video.mp4`
Not Accepted: `https://mysite.com/video.mp4?code=30s93`
If your video is a signed URL or cannot end in an accepted video extension, you can use the [`isVideo`](/docs/apis/post/overview#video-extension) parameter when publishing the post.
We recommend for larger video files over 50 MB create a scheduled post with the `scheduleDate` parameter for async processing.
Be sure to also check the upload speed of your media URLs to prevent timeouts at the social networks.
If the media file cannot be downloaded within approximately 5 minutes a time out will likely occur.
### Standard Social Video Requirements
Each social network has different video requirements. If you want a video that can be published to social networks such as X/Twitter, Instagram, Facebook, and TikTok use the following standards:
**Dimensions:** 1080 x 1920 px
**Length:** 60 seconds
**Size:** 50 MB
**Format:** MP4
**Example Portrait Video:** `https://img.ayrshare.com/random/portrait5.mp4`
You may also create specific sized video for networks such as YouTube that accept longer and larger files. Please see below for details of each network.
See how to [create random videos](/docs/quickstart#random-image) for your testing.
### Content Type
**When posting,** be sure the `content-type` is set appropriately, e.g. image/png, image/jpg, or image/jpeg.
### Secure URLs
When posting your own media URL, the link must be secure by using SSL and starting with `https://`
### Social Network Media Requirements
## Image Metadata and Content Credentials
Images frequently carry embedded metadata: an ICC color profile, an XMP packet, EXIF camera data, or a [C2PA](https://c2pa.org/) Content Credentials manifest.
When an image is generated or edited with an AI tool, the AI disclosure normally lives in the XMP packet as the `Iptc4xmpExt:DigitalSourceType` property, and often inside a C2PA manifest as well.
Ayrshare re-encodes an image to JPEG when the destination network won't accept the source format, as described under [Accepted File Types](/docs/media-guidelines/overview#accepted-file-types) above.
A re-encode rewrites the file, so this section states exactly what Ayrshare carries across, what it drops, and what each network does with the result.
Videos are never re-encoded and their metadata is untouched.
### Metadata Retained on Conversion
**Color rendering.** A wide-gamut image looks the same after conversion as it did before. How
that is achieved depends on the source format, and the difference is worth knowing if you
inspect the converted file. A **HEIC or HEIF** image keeps its original ICC color profile, which
is carried into the JPEG. A **WebP or AVIF** image is converted to standard sRGB instead, so the
colors are correct even on a network that discards embedded profiles — the converted JPEG
carries no ICC profile because it no longer needs one.
**The AI disclosure, and only the AI disclosure.** Ayrshare writes a small, new XMP packet
containing `Iptc4xmpExt:DigitalSourceType` — the IPTC property that records whether an image was
captured by a camera, edited, or produced by an algorithm — so a disclosure written by your
generation tool reaches the network. The packet is **built fresh rather than copied**: nothing
else from your image's original XMP travels with it. Creator and copyright fields, keywords,
editing history and location fields such as `photoshop:City` and `Iptc4xmpExt:LocationCreated`
are all left behind, so nothing about you or where a photo was taken can be published by
accident. See [Metadata Not
Retained](/docs/media-guidelines/overview#metadata-not-retained) below.
**A synthesized AI disclosure.** If a C2PA manifest asserts an AI origin but the XMP packet
doesn't record it, Ayrshare writes the equivalent `Iptc4xmpExt:DigitalSourceType` value into the
output XMP, so the disclosure isn't lost along with the manifest. Ayrshare never infers an AI
origin on its own: the value is carried across when the image already carries one, and
synthesized only when a C2PA manifest asserts it. An AI-generated image that arrives with no
disclosure in either place is published without one.
### Metadata Not Retained
**Everything except the AI disclosure.** A converted image carries no EXIF block at all — no GPS
coordinates, no camera make, model or capture time — and nothing from the original XMP packet
beyond the disclosure itself. That includes `dc:creator` and `dc:rights`, keywords, editing
history, and every location field, `exif:GPS*` and authored text such as `photoshop:City` and
`Iptc4xmpExt:LocationCreated` alike. The output packet is built from scratch rather than filtered,
so the only thing that can appear in it is the disclosure. If you need authorship or copyright
metadata to reach a network, publish in a format that network accepts natively so no conversion
takes place.
**A very long disclosure value.** The packet Ayrshare writes has to fit a fixed amount of space in
the JPEG, and a disclosure value long enough to push it past 60,000 bytes is left out rather than
truncated. Real IPTC values are a few dozen bytes, so this does not happen in practice; it is
documented because the post still succeeds and no warning is returned. Note this is a limit on the
*disclosure*, not on your image's original packet — a large original XMP no longer costs you the
disclosure, because the original is not what gets written.
**The C2PA cryptographic signature can't survive a re-encode.** A C2PA manifest is signed over
the exact bytes of the file it was attached to. Converting the image to JPEG produces different
bytes, so the signature can no longer be valid and is not carried over. The *disclosure* survives
the conversion; the *signature* does not. A converted image will not verify as signed content in
a Content Credentials validator.
Don't rely on a converted image to prove authorship or tamper-evidence. If a verifiable C2PA
signature is a requirement, publish the image in a format the destination network accepts natively
so that no conversion takes place.
### When Conversion Happens
**JPEG and PNG pass through untouched.** No re-encode and no metadata change — the bytes you
supply are the bytes the network receives.
**WebP** is converted to JPEG for Instagram, Threads, LinkedIn, TikTok, Google Business Profile,
and Snapchat.
**HEIC, HEIF, and AVIF** are converted to JPEG for every network.
**Videos** are never converted.
If you need certainty that no re-encode will happen, supply JPEG or PNG.
### What Each Network Does With the Metadata
Retaining the metadata is only half the journey. Each network decides independently whether to keep it on ingest and whether to render an AI label.
The results below come from live posts published in August 2026 with no platform AI flag set, so the embedded metadata was the only possible signal:
| Network | AI disclosure kept | ICC color profile kept | AI label rendered |
| --------- | ----------------------------------------- | ---------------------- | --------------------------- |
| Facebook | Yes | Yes | Yes — shown as "AI content" |
| Instagram | Yes | No — stripped | Yes — shown as "AI info" |
| Threads | Yes | Not measured | No label is rendered today |
| LinkedIn | No — image metadata is stripped on ingest | No — stripped | No |
Meta keeps the disclosure consistently across Facebook, Instagram, and Threads, but renders the label per surface: Facebook and Instagram show it, Threads currently does not.
The two columns are independent, and Instagram is the reason it's worth saying so: it keeps the AI disclosure while discarding the color profile. That's also why WebP and AVIF images are converted to standard sRGB instead of being given a profile to carry — a profile only helps on a network that keeps it, whereas correct sRGB color is correct everywhere.
**Provenance metadata does not survive LinkedIn's image processing.** LinkedIn removes embedded
metadata when it ingests an image, so the `Iptc4xmpExt:DigitalSourceType` disclosure is not present
on the published image and no AI label is applied. Don't treat embedded metadata as an
AI-disclosure mechanism for LinkedIn.
Networks not listed above were not measured. Network behavior can change without notice, so treat the table as observed behavior rather than a guarantee.
**Instagram `autoResize` discards the disclosure.** When a post uses
[`instagramOptions.autoResize`](/docs/apis/post/social-networks/instagram#auto-image-resize), the image is resized to
1080×1080 by a separate step that writes a new file and carries no metadata forward — so the AI
disclosure, the ICC profile and any C2PA manifest are all absent from the image Instagram receives,
regardless of what the source carried. If the disclosure needs to reach Instagram, supply an image
that already meets Instagram's aspect-ratio requirements and leave `autoResize` off.
### Uploading Media Directly
[`POST /media/upload`](/docs/apis/media/upload-media) stores your bytes verbatim.
Nothing is re-encoded and all metadata — including EXIF and any C2PA manifest — is stored exactly as supplied.
The retention behavior above applies only when an image is published to a network that requires a different format.
# Pinterest
Source: https://www.ayrshare.com/docs/media-guidelines/pinterest
Image and video media requirements for [Pinterest](/apis/post/social-networks/pinterest)
## Images
Content-Type: A valid media Content-Type such as image/jpeg, image/png, or image/webp returned
by the hosting provider.
## Image Carousel
Up to five carousel images.
Images must be the same dimension.
## Video
Max video size: 2 GB
Supported formats: MP4, MOV, and M4V.
Duration max: 15 minutes.
Duration min: 4 seconds.
Aspect ratio: Taller than 1.91:1 and shorter than 1:2. Recommended for standard video: 1:1
(square) or 2:3, 4:5 or 9:16 (vertical).
# Reddit
Source: https://www.ayrshare.com/docs/media-guidelines/reddit
Image and video media requirements for [Reddit](/apis/post/social-networks/reddit)
## Images
Max image size: 10 MB.
Supported formats: JPG, PNG, GIF, and WEBP.
## Video
Video API posting is not supported by Reddit.
# Snapchat
Source: https://www.ayrshare.com/docs/media-guidelines/snapchat
Image and video media requirements for [Snapchat](/apis/post/social-networks/snapchat)
## Story
### Image
Snapchat supports story image media in the following formats:
Supported formats: JPEG and PNG.
Max image size: 20 MB.
Recommended dimensions: 1080 x 1920 px.
WebP, HEIC, HEIF, and AVIF images are converted to JPEG before posting, and the conversion preserves the image's color rendering and writes a small XMP packet carrying only the `Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The
C2PA signature does not survive a re-encode.
See [Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
### Video
Snapchat supports story video media in the following formats:
Supported formats: MP4
Max video size: 1 GB.
Duration max: 5-60 seconds.
Recommended video dimensions: 540x960 px.
Portrait aspect ratio: 9:16.
## Spotlight
### Image
Snapchat supports spotlight image media in the following formats:
Supported formats: JPEG and PNG.
Max image size: 20 MB.
Recommended dimensions: 1080 x 1920 px.
### Video
Snapchat supports spotlight video media in the following formats:
Supported formats: MP4
Max video size: 1 GB.
Duration max: 5-60 seconds.
Recommended video dimensions: 540x960 px.
Portrait aspect ratio: 9:16.
# Telegram
Source: https://www.ayrshare.com/docs/media-guidelines/telegram
Image and video media requirements for [Telegram](/apis/post/social-networks/telegram)
## Images
Max image size: 5 MB.
Supported formats: JPG, PNG, GIF, [Animated
GIF](/docs/apis/post/social-networks/telegram#animated-gifs), and WEBP.
Width and height must not exceed 10,000 in total.
Width and height ratio must be at most 20.
Post text length max 1,024 characters. Will be truncated if exceeding 1,024.
## Video
Max video size: 20 MB.
Post text length max 1,024 characters. Will be truncated if exceeding 1,024.
# Threads
Source: https://www.ayrshare.com/docs/media-guidelines/threads
Image and video media upload types, size limits, and other requirements for [Threads](/apis/post/social-networks/threads)
## Image
Format: JPEG and PNG image types are the officially supported formats for image posts.
File Size: 8 MB maximum.
Aspect Ratio Limit: 10:1
Minimum Width: 320 (will be scaled up to the minimum if necessary)
Maximum Width: 1440 (will be scaled down to the maximum if necessary)
Height: Varies (depending on width and aspect ratio)
Color Space: sRGB. Images using other color spaces will have their color spaces converted to
sRGB.
WebP, HEIC, HEIF, and AVIF images are converted to JPEG before posting, and the conversion preserves the image's color rendering and writes a small XMP packet carrying only the `Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one. Threads stores the
disclosure but does not render an AI label today. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA
signature does not survive a re-encode. See [Image Metadata and
Content Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Video
Container: MOV or MP4 (MPEG-4 Part 14), no edit lists, moov atom at the front of the file.
Audio Codec: AAC, 48khz sample rate maximum, 1 or 2 channels (mono or stereo).
Video Codec: HEVC or H264, progressive scan, closed GOP, 4:2:0 chroma subsampling.
Frame Rate: 23-60 FPS
Picture Size:
Maximum Columns (horizontal pixels): 1920
Required aspect ratio is between 0.01:1 and 10:1 but we recommend 9:16 to avoid cropping or
blank space.
***
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
Self-hosting your media? Meta's crawler must be allowed to fetch your URLs.
See [Meta Media Crawler Blocked](/docs/help-center/technical-support/meta_media_crawler_blocked)
to configure `robots.txt`.
# TikTok
Source: https://www.ayrshare.com/docs/media-guidelines/tiktok
Image and video media requirements for [TikTok](/apis/post/social-networks/tiktok)
## Images
Max image size: 20 MB.
Supported formats on TikTok: JPG and JPEG. WebP source images are accepted by Ayrshare and
[automatically converted to JPEG](/docs/errors/errors-ayrshare#image-format-conversion-errors) before
posting. PNG files are not supported by TikTok for the photo-post endpoint and are not auto-
converted on this path; see the [Max Pack](/docs/additional/maxpack) add-on for [converting from a
PNG to a JPG](/docs/apis/media/resize#convert-to-a-jpg-or-webp).
Image Resolution: 1080 x 1920 px or 1920 x 1080 px.
Square images (aspect ratio 1:1) are permitted of dimensions 1080 x 1080 px or smaller
When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG it preserves the image's color rendering and writes a small XMP packet carrying only the `Iptc4xmpExt:DigitalSourceType` AI disclosure, when the image declares one. No other metadata is carried over: not EXIF, and nothing else from the original XMP, so a location, a creator name or a copyright line can't be published by accident. The C2PA signature does not survive
a re-encode. TikTok's own
[`isAIGenerated`](/docs/apis/post/social-networks/tiktok) toggle is a separate, video-only mechanism. See
[Image Metadata and Content
Credentials](/docs/media-guidelines/overview#image-metadata-and-content-credentials).
## Video
Max video size: 10 GB.
Supported formats: MP4, MOV, and WebM.
Duration Max: 600 seconds.
Duration Min: 3 seconds.
Video Resolution: the minimum height and minimum width of the video must be 360 px.
Frame Rate: the minimum frame rate of the video must be 23 FPS, and maximum frame rate is 60
FPS.
Video width: 360 px - 4096 px.
Video height: 360 px - 4096 px.
Video aspect ratio: 9:16 or 16:9.
## Video Thumbnail
Maximum image size: 20 MB.
Supported formats on TikTok: JPG, JPEG, and PNG. WebP source images are accepted by Ayrshare and [automatically converted to JPEG](/docs/errors/errors-ayrshare#image-format-conversion-errors) before posting.
Maximum resolution: 1080 x 1920 px or 1920 x 1080 px.
Minimum resolution: 360 x 360 px.
# X
Source: https://www.ayrshare.com/docs/media-guidelines/x_twitter
Image and video media requirements for [X](/apis/post/social-networks/x-twitter), formerly Twitter
## Images
Up to 4 images can be uploaded in a single Tweet.
Max image size: 5 MB
Supported formats: JPG, PNG, GIF, Animated GIF, and WEBP.
Image dimensions must be >= 4x4 and \<= 8192x8192 px.
Recommended Tweet sharing a single image: 1200 x 675 px.
Recommended Tweet sharing two images: 700 x 800 px each image.
Recommended Tweet sharing three images:
Left image: 700 x 800 px.
Right images: 1200 x 686 px.
Tweet sharing four images: 1200 x 600 px each image.
Duration must be between 0.5 seconds and 140 seconds. Please [see
here](/docs/apis/post/social-networks/x-twitter#upload-long-videos) for posting longer X
videos up to 10+ minutes.
Aspect ratio must be between 1:3 and 3:1.
Must have 1:1 [pixel aspect ratio](https://en.wikipedia.org/wiki/Pixel_aspect_ratio).
Audio must be mono or stereo, not 5.1 or greater.
Some video software creates MP4 files that are not compatible with X/Twitter. For example,
Camtasia versions older than 2019.0.9 create MP4 files that X/Twitter rejects. Please check
your video software for compatibility. See
[here](/docs/apis/post/social-networks/x-twitter#x-twitter-video-compatibility) for more
information.
X might have an issue processing video media hosted on Dropbox or signed URLs (for example an
S3 signed URL). If you encounter an issue, we recommend using an alternative hosting provider
or [uploading directly](/docs/apis/media/overview) to Ayrshare.
If you're using a video creation tool and you're having issues publishing your video, try
[re-encoding the video](/docs/help-center/technical-support/video_publishing_fails).
## Video Thumbnail
Set a custom thumbnail (cover image) for X videos. The thumbnail is displayed before the video plays.
Only one thumbnail image per video.
Supported formats: JPEG, PNG, BMP, and WebP.
Max image size: 5 MB
Recommended dimensions: Match the video resolution (e.g., 1280x720 px for landscape, 720x1280 px for portrait).
Recommended aspect ratio: Match the video aspect ratio (16:9 for landscape, 9:16 for portrait, 1:1 for square).
See [Video Thumbnail](/docs/apis/post/social-networks/x-twitter#video-thumbnail) for usage details.
# YouTube
Source: https://www.ayrshare.com/docs/media-guidelines/youtube
Video media requirements for [YouTube](/apis/post/social-networks/youtube)
## Video
Max video size: 4 GB. Please contact us about Enterprise plans for larger files.
Supported formats: MP4 and MOV.
The standard aspect ratio for YouTube on a computer is 16:9. When uploading other aspect ratios such as vertical or square, the player automatically adapts itself to the size of the video. This setting gives the best viewing experience based on the aspect ratio and device.
Recommended format MP4 with H.264 video codec and AAC audio codec. Results in a high-quality video with a smaller file size.
The standard video’s frame rate frequency is: 24, 25, 30, 48, 50, 60 frames a second. YouTube also accepts other frequencies.
For larger videos, please be sure your server has a very fast upload speed. Slower speeds will result in timeouts.
## Thumbnails
Supported formats: JPEG or PNG.
Max thumbnail size: 2MB.
Custom thumbnails require a **verified YouTube channel** (phone verification at [https://www.youtube.com/verify](https://www.youtube.com/verify)). If a video posts but the thumbnail is missing, see [YouTube Thumbnail Not Applied (Unverified Channel)](/docs/help-center/technical-support/youtube_thumbnail_unverified_channel).
## Shorts
YouTube Shorts should have a 9:16 aspect ratio.
Dimensions: 1080x1920 px.
Duration: 3 minutes or less.
YouTube will not show the video as a Short if the aspect ratio is not 9:16, if it's a portrait video, and if the video is over 3 minutes in length.
## Watermark
Max watermark size: 1MB.
Supported formats: JPEG or PNG.
Watermark image must be a square (1:1 aspect ratio).
Minimum dimensions: 150x150 pixels.
Maximum dimensions: 1920x1920 pixels.
# API Integration for Business
Source: https://www.ayrshare.com/docs/multiple-users/api-integration-business
Allow Your Users to Connect Their Social Media Accounts
An important part of the Business Plan or [Launch Plan](/docs/multiple-users/business-launch-overview) integration consists of creating new profile accounts in Ayrshare for your users or clients and allowing your users to link their social networks with the [social linking page](/docs/multiple-users/user-integration).
Each of your users is set up as an Ayrshare user profile. A user profile gets one connection to each social network.
**This is the standard way to onboard customers.** Your users connect their own
social accounts through the white-labeled JWT URL connect page described below —
they never log in to Ayrshare and never touch your dashboard. The
[dashboard](/docs/multiple-users/manage-user-profiles#using-the-dashboard) is reserved for your
internal team (creating and managing profiles, testing, and posting on a
client's behalf).
## Integration Workflow
To integrate Ayrshare into your application, you'll need to make two API calls:
1. Call the [Create Profiles endpoint](/docs/apis/profiles/create-profile) to create a new Ayrshare profile for your user.
2. Call the [Generate JWT endpoint](/docs/apis/profiles/generate-jwt) to get a JWT URL.
The JWT URL allows your user to securely access the social linking page through single sign-on authentication.
You'll display this page in a new tab, window, or view controller to let users connect their social media accounts.
After your user links their social media accounts, you will be able to publish posts, get analytics, and manage their accounts via the API.
For security reasons, social media platforms require users to authenticate through their browser,
which cannot be done through backend server calls. This ensures your users can safely connect
their social media accounts by logging in directly with each platform's official login page.
Social networks restrict authentication to happen only through their authorized partner domains,
such as Ayrshare. They also block iFrames, which means you cannot embed or display the Ayrshare
linking page within an iFrame on your site.
## Create an Ayrshare User Profile
### Create a Profile with the API
When a new user registers with your system or when your client clicks the social network link in your app, create a new Ayrshare profile account by calling the [/profiles/create-profile](/docs/apis/profiles/create-profile) RESTful endpoint, or using the [NPM](/docs/packages-guides/nodejs) or [PyPi](/docs/packages-guides/python) packages.
Returned from this call will be your user's *PROFILE KEY*. This key will be used to post on your user's behalf and to manage their account. You should store it in a secure location.
### Create a Profile with the Dashboard (Internal Team)
Your internal team can also create User Profiles directly from the **Developer Dashboard** — useful for testing, onboarding a profile manually, or one-off administration. This is a team tool, not a customer-facing flow: your customers are never given dashboard access and are always onboarded through the [JWT URL connect page](#single-sign-on-with-jwt-authentication). For production onboarding, create profiles programmatically with the [API](/docs/apis/profiles/create-profile) so each new user is provisioned automatically.
### Integration Package
During your onboarding as a Business Plan or Launch Plan client, you received a personalized integration package with important set up and domain information, example endpoint calls, and more. Please check with your primary account holder for this information.
You may also retrieve or reset the integration package in the dashboard in the API page. Be sure to first switch to your Primary Profile.
## Single Sign-On with JWT Authentication
Ayrshare uses a JWT (JSON Web Token) to authenticate your user and perform Single Sign-On to the social linking page. A JWT is a secure mechanism for passing digitally signed information and allows Ayrshare to authenticate you and your user.
### Generate a JWT
Your app will construct a JWT comprised of your API Key, user Profile Key, and a few other parameters. This will be signed with your 1024-bit private key.
The JWT token is valid for 5 minutes. Please see the [Max Pack](/docs/additional/maxpack) for longer
expire time.
Please use the [Generate JWT endpoint](/docs/apis/profiles/generate-jwt) to have Ayrshare create the token and social linking URL. Open the social linking URL in a new tab or window, allowing your users to easily [link their social networks](/docs/multiple-users/user-integration).
The JWT URL is the recommended onboarding path for every customer. Your users authenticate
directly with each social network on their own — you never collect or store their social
credentials. If your team needs to link an account manually during testing, you can do so from
the dashboard, but this is an internal convenience and not how customers should be onboarded.
### White-Label the Connect Accounts Page
Because the connect page opened by the JWT URL is the only Ayrshare interface your users ever see, you should brand it as your own. Add your logo and custom headers, choose which social networks appear, set the page language, and use your own help links — and with the [Max Pack](/docs/additional/maxpack), apply a full custom CSS file, favicon, page title, and footer. These options are configured once by your team from the Primary Profile and apply to every JWT URL you generate.
See every branding and customization option for the connect page.
### Automatic Logout of a Profile Session
**How to Automatically Logout of the Active Profile Session**
If a profile is already logged in, sending a different profile's JWT will not switch profiles. This is done to make the experience faster for already logged-in users. When testing, log out of the current profile before making an SSO call with a different profile. Signed-in profiles remain signed in until explicitly logged out.
However, if you have a business need, such as your users having multiple profiles they often access, or you want to test, include the URL parameter in the SSO URL:
`logout=true`
For example:
`https://profile.ayrshare.com?domain=[domain id]&jwt=[jwt token]&logout=true`
This forces a logout and then logs in the new profile.
Please also see the [Generate JWT endpoint](/docs/apis/profiles/generate-jwt) to automatically add the logout.
**Warning**: Using automatic logout causes a performance delay for your user, so unless you need it, we suggest not forcing a logout and not using it in production.
## Opening & Closing the Social Linking URL
The Social Accounts page has a "Close" button that closes the window and returns your user to your site.
### Opening the Social Linking URL
When you open the social linking URL, we recommend using JavaScript's `window.open()` function instead of an anchor href.
The "Close" button uses JavaScript to close the window, and most browsers only allow windows opened via a script to be closed.
You can use the following sample code on your website to launch the social linkage window.
```html Window Open theme={"system"}
Link Social Networks
```
or
```html Window Open Function theme={"system"}
```
You may control the "Close' button to either redirect the social linking tab to a page of your choosing or redirect the origin opener tab/window and close the social linking tab.
This can be done using the redirect parameter and adding `origin=true` to the query parameters of the redirect URL.
Please see [Generate JWT endpoint](/docs/apis/profiles/generate-jwt) for more details.
### Redirecting When Closing
Additionally, if you want to have the `Close` button redirect back to your page (often useful on mobile), pass in the `redirect` GET parameter as a *URL encoded* string starting with https.
Please see the [Generate JWT endpoint parameters](/docs/apis/profiles/generate-jwt#body-parameters) for more details.
```javascript JWT URL theme={"system"}
https://profile.ayrshare.com?domain=[domain id]&jwt=[jwt token]&redirect=https%3A%2F%2Fmywebsite.com
```
The redirect will be saved for that profile and used in subsequent SSO calls even if the `redirect` parameter is not passed.
To reset the `Close` button back to close, pass the parameter `redirect=null`.
## More Information
### User Linking or Unlinking Notifications
When a user links or unlinks a social network, you can receive a notification via webhook. Please see the [Social Action Webhooks](/docs/apis/webhooks/actions#social-action) page for more information.
You may also use the [user endpoint](/docs/apis/user/profile-details) to get the connected social networks for a user profile.
### Multiple Sets of Social Accounts
#### Overview
Each User Profile has a set of social media accounts and can make one connection to each social network.
If your users or clients have multiple sets of social media accounts, such as two Facebook Pages, two Instagram accounts, and two YouTube channels, you can manage these multiple sets of social media accounts by following these steps:
1. **Create multiple User Profiles** - [Create separate User Profiles](/docs/apis/profiles/create-profile) within the Ayrshare system for each set of social accounts your user or client needs to manage.
2. **Store unique Profile Keys** - Each User Profile will have its own unique Profile Key, returned from the create User Profile endpoint.
3. **Label your profiles** - [Title](/docs/apis/profiles/create-profile#param-title) or [tag](/docs/apis/profiles/create-profile#param-tags) each User Profile to clearly identify which social media accounts they're associated with (e.g., "Facebook Page A" and "Facebook Page B").
4. **Map in your database** - In your own system, associate all relevant Profile Keys with the respective user or client.
5. **Use appropriate Profile Key** - When posting content or retrieving analytics for a specific social account, use the Profile Key associated with that account. For example, to post to Facebook Page A, use the Profile Key of the User Profile connected to Facebook Page A.
#### Example
Let's consider a practical scenario for multiple client accounts:
**Client:** Joe's Restaurant Chain with two locations
Joe needs separate social media accounts for each restaurant location:
**Restaurant Location 1:**
Facebook Page: "Joe's Downtown Bistro"
Instagram: @joesdowntownbistro
LinkedIn: Joe's Downtown Bistro business page
**Restaurant Location 2:**
Facebook Page: "Joe's Seaside Grill"
Instagram: @joesseasidegrill
LinkedIn: Joe's Seaside Grill business page
**Implementation solution:**
1. Create two separate User Profiles in Ayrshare:
User Profile 1: Titled "Joe's Downtown Bistro Accounts"
User Profile 2: Titled "Joe's Seaside Grill Accounts"
2. Connect the appropriate social accounts to each profile:
Profile 1: Links the Downtown Bistro Facebook, Instagram, and LinkedIn
Profile 2: Links the Seaside Grill Facebook, Instagram, and LinkedIn
3. Store both Profile Keys in your database, associating them with Joe's account:
```
Client: Joe's Restaurant Chain
- Profile Key 1: abc123... (Downtown location)
- Profile Key 2: xyz789... (Seaside location)
```
4. When posting a special menu update for the Downtown location, use Profile Key 1 in the API calls. When posting about a seafood promotion at the Seaside location, use Profile Key 2.
By creating multiple User Profiles, [titling](/docs/apis/profiles/create-profile#param-title) or [tagging](/docs/apis/profiles/create-profile#param-tags) them appropriately, and associating them to a single user or client in your system, you can manage their multiple social media accounts across the same platforms using Ayrshare.
This approach allows for targeted posting and analytics retrieval for each specific account.
### Next Steps
Please see here for more details of the user experience:
Once your user sets up their social media links, you will be able to begin posting on their behalf using
the /post and /profile endpoints.
# Launch Plan: entry-level multi-user Business plan
Source: https://www.ayrshare.com/docs/multiple-users/business-launch-overview
The Ayrshare Launch Plan is the entry-level Business tier for agencies and platforms managing multi-user social media posting, analytics, and DMs.
The **Launch Plan** is the entry-level tier of the [Ayrshare Business Plan](/docs/multiple-users/business-plan-overview). It's designed for companies, agencies, and platforms that are just starting to manage social media on behalf of their users, clients, or brands and don't yet need the scale of the full Business plan.
The Launch Plan includes the same multi-user APIs as the full Business plan (posting, analytics, comments, DMs, and ads on behalf of your users) at a lower starting price, with a smaller profile cap to match the needs of early-stage teams. Post quotas, API rate limits, and support match the full Business plan.
To get started, see current pricing and start your subscription on the [Ayrshare pricing page](https://www.ayrshare.com/pricing/).
## Who Launch Is For
Early-stage SaaS platforms adding social posting for their first users.
Agencies onboarding a small set of clients before scaling further.
Teams running a pilot or proof-of-concept that needs production-grade APIs without committing to the full Business plan.
Anyone who needs Business-tier features (multi-user JWT linking, per-user analytics, comments, DMs, ads) for **up to 10 user profiles**.
The Launch Plan is capped at 10 [User Profiles](/docs/multiple-users/manage-user-profiles)
(sub-profiles, separate from your primary account). Once you reach the cap,
the API returns an error with upgrade guidance, and the dashboard shows the
same message as a toast. To add more, upgrade to the full
[Business Plan](/docs/multiple-users/business-plan-overview).
## What's Included
The Launch Plan gives you the full Business API surface for managing multiple users, capped at 10 [User Profiles](/docs/multiple-users/manage-user-profiles):
A single API call to post to your users' [social media networks](/docs/apis/post/overview): Bluesky,
Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat,
Telegram, Threads, TikTok, X, and YouTube.
[Schedule posts](/docs/apis/post/overview#schedule-posts) and [auto-schedule](/docs/apis/auto-schedule/overview) at pre-determined times.
[Per-user analytics](/docs/apis/analytics/overview) on posts, social profiles, and links.
[Comment management](/docs/apis/comments/overview) and [direct messages](/docs/apis/messages/overview) on supported platforms.
[Facebook Ads](/docs/apis/ads/overview) created from existing posts.
[Hashtag automation](/docs/apis/hashtags/overview), [RSS feeds](/docs/apis/feeds/overview), [post validation](/docs/apis/validate/overview), and [post history](/docs/apis/history/overview).
Secure social authentication via [JWT](/docs/multiple-users/api-integration-business): your users connect their own accounts and you never handle their credentials.
## How the Launch Plan Compares to the Full Business Plan
The Launch Plan and full Business Plan share the same API tier and feature set for posting, analytics, comments, DMs, and ads. The differences are about scale and add-ons:
| Capability | Launch | Business |
| ------------------------------------------- | ----------------------------------- | ---------------------- |
| User Profile cap | Up to 10 | 30+ (scales as needed) |
| Core posting, analytics, comments, DMs APIs | Included | Included |
| Facebook Ads add-on | Available | Available |
| [Max Pack](/docs/additional/maxpack) add-on | Available at a reduced Launch price | Available |
| Free trial | 28 days | — |
Post quotas, API rate limits, and support are the same on the Launch Plan and the full Business Plan.
For exact pricing and the most up-to-date details, see the [Business Plan page](https://www.ayrshare.com/business-plan-for-multiple-users/).
## 28-Day Free Trial
The Launch Plan includes a **28-day free trial** so you can integrate the multi-user APIs and validate the flow with real users before committing. The trial gives you the same APIs and profile capacity as a paid Launch Plan subscription.
## Upgrading to the Full Business Plan
Because the Launch Plan is capped at 10 User Profiles, you'll need to upgrade to the full [Business Plan](/docs/multiple-users/business-plan-overview) once you're ready to onboard your 11th User Profile. You can upgrade at any time from your [account dashboard](https://app.ayrshare.com). Your existing User Profiles, JWT integration, and API keys carry over. No re-integration required.
## Moving to Launch from the Premium Plan
If you're on the Premium Plan and want to move to the Launch Plan, this is a change between plan families (single-user to multi-user). A self-serve option for this isn't available in the dashboard yet — for now, email [support@ayrshare.com](mailto:support@ayrshare.com) and we'll migrate your account to the Launch Plan for you — your connected social accounts, API keys, and settings carry over.
Self-serve dashboard upgrades currently apply only to the monthly Launch Plan
moving to the full Business Plan. Moving from the Premium Plan to the Launch
Plan or Business Plan is handled by support for now, and moving from an annual
Launch Plan to the Business Plan is also support-only. (New customers on the
free Basic Plan can self-serve any plan from the [pricing page](https://www.ayrshare.com/pricing/).)
## Get Started
Generate JWTs and connect your users' social accounts via the API.
Create, update, and manage the User Profiles included in your plan.
Compare the Launch Plan against the full Business Plan and Max Pack add-ons.
# Business Plan Overview
Source: https://www.ayrshare.com/docs/multiple-users/business-plan-overview
Ayrshare Business Plan for managing multiple users, clients, or brands
The [Business Plan](https://www.ayrshare.com/business-plan-for-multiple-users/) enables organizations such as companies, agencies, and platforms to manage social media activities including posting, scheduling, analytics, and comment management across multiple users, clients, or brands from a single API integration.
Ayrshare is API-first. You build your own front end and call the API to post, fetch analytics, and manage comments on behalf of your users. Your customers connect their own social accounts through a **white-labeled connect page** that you open with a [JWT URL](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication) — they never log in to Ayrshare and never see your dashboard.
**The dashboard is for your internal team only.** On the Launch, Business, and
Enterprise plans, the [Ayrshare dashboard](/docs/multiple-users/manage-user-profiles#using-the-dashboard)
is where *your team* creates and manages [User Profiles](/docs/multiple-users/manage-user-profiles),
tests integrations, and posts on a client's behalf. Your customers should
**always** be onboarded through the [JWT URL connect page](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication) —
never give clients dashboard access, as it exposes your account, billing, and
every other profile. (On the single-user Premium plan, you use the dashboard
directly yourself.)
Just getting started with multi-user social? The
[Launch Plan](/docs/multiple-users/business-launch-overview) is the
entry-level Business tier with the same API surface, capped at 10 User Profiles,
and a 28-day free trial.
Get more details about the Business Plan by [contacting us](https://www.ayrshare.com/business-plan-for-multiple-users/#contactbusiness).
## Post, Get Analytics, Manage Comments and DMs, and Create Facebook Ads on Behalf of Your Users
A single API call to post to your users' [social media networks](/docs/apis/post/overview): Bluesky,
Facebook, Google Business Profile (Google My Business), Instagram, LinkedIn, Pinterest,
Reddit, Snapchat, Telegram, Threads, TikTok, X, and YouTube.
[Send scheduled posts](/docs/apis/post/overview#schedule-posts) of text, images, and videos or
[create an auto schedule](/docs/apis/auto-schedule/overview) to post at pre-determined times.
Get [detailed analytics](/docs/apis/analytics/overview) on your user's posts, social profile, and
links. E.g. number of impressions, follower demographics, average view time of videos, and more.
[Add comments](/docs/apis/comments/overview) to a user's post or get all comments made by other
users.
[Manage direct messages](/docs/apis/messages/overview) across supported platforms.
[Create Facebook ads](/docs/apis/ads/overview) from existing posts.
Automatically [add hashtags](/docs/apis/hashtags/overview) to posts based on the content, and
automatically post your users' [RSS feeds](/docs/apis/feeds/overview).
[Validate posts](/docs/apis/validate/overview) before sending to the social networks so your users'
social accounts are always protected and don't get in trouble with the social networks.
Retrieve a user's [post history](/docs/apis/history/overview), [analytics](/docs/apis/analytics/overview),
and [comments](/docs/apis/comments/overview), even on posts that originated outside of Ayrshare.
## Seamlessly Integrate with Your Product or Platform
Simple and transparent integration for your users, clients, and brand.
Make RESTful API calls, or use the Node.js, Python, Bubble.io, or Airtable [packages and
integrations](/docs/packages-guides/overview).
Enterprise grade security and secure social authentication where you never ask for your users'
credentials.
Staging environment add-on available for your build workflow.
## White-Label the Connect Accounts Page
The connect accounts page is the only Ayrshare interface your customers ever see, so make it your own. Add your logo, set custom headers, choose which social networks appear, localize the language, and swap in your own help links — and with the [Max Pack](/docs/additional/maxpack), apply a full custom CSS file, favicon, page title, and footer. Done well, the connect page feels like a native part of your product, not a third-party tool.
See every branding and customization option available for the connect page.
## Additional Capabilities Available with Max Pack
The [Max Pack](/docs/additional/maxpack) provides additional endpoints and other useful utilities for building your app or platform.
# Manage Multiple User Profiles
Source: https://www.ayrshare.com/docs/multiple-users/manage-user-profiles
There are two ways to create and manage multiple account profiles for your organization, users, clients, or brands - via the Dashboard or API.
**The dashboard is for your internal team only.** On the Launch, Business, and
Enterprise plans, the dashboard is where *your team* creates and manages User
Profiles, tests, and posts on a client's behalf. Your customers are **never**
given dashboard access — they connect their social accounts through the
white-labeled [JWT URL connect page](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication).
In production, create and manage profiles programmatically with the
[API](#using-the-api). (The single-user Premium plan is the exception: there is
no multi-user layer, so you use the dashboard directly yourself.)
## Using the Dashboard
If your Ayrshare account is entitled to manage multiple profiles, then you will see the option for **User Profiles** in the left-hand navigation.
If your account does not have the option to manage profiles, then contact your Ayrshare
representative or [contact us](mailto:contact@ayrshare.com) to upgrade.
### Create a New Profile
Click the **Add Profile** button and enter your User Profile Title.
### Switch to the New Profile
You will see the new Profile show up in the Active Profiles section.
You can now click on the **switch to this profile** icon to switch to that User Profile.
When you switch to a different User Profile, you will see that profile name shown in the top left of the screen under the profile icon.
You can always switch back to your primary account profile by clicking the **switch profile** link next to the Primary Profile or by clicking the **Switch to Primary** button at the top of the User Profiles page.
From here you are acting as your client/user and can post on their behalf by going the the *Post* page.
### Get the Profile Key
The Profile Key is used to post on behalf of the profile with the API. Switch to a [User Profile](/docs/multiple-users/manage-user-profiles) and go to the *Profile Key page* in the left-hand navigation of the Dashboard to get that profile's Key.
When making an API call, be sure to include your [API\_KEY](/docs/apis/overview#authorization) and [PROFILE\_KEY](/docs/apis/overview#profile-key-format) in the header.
You also receive the Profile Key when you create a new User Profile using the [/profiles/profile endpoint](/docs/apis/profiles/create-profile). This is the preferred method to get the Profile Key.
### Invite a Team Member
You can create Users Profiles for members of your team. By default, Team Members have an Ayrshare account with full access/admin rights to the dashboard and count as a new User Profile. Please note, you may restrict access by [locking the Primary Profile](/docs/multiple-users/manage-user-profiles#primary-profile-lock).
You can only invite team members who have not yet been registered with Ayrshare. If you want to
use an already registered email, please have the user login to the dashboard, go to the Account
page, and click the **Delete** button.
In the User Profiles page, switch to your Primary Profile and click the *+ Add Profile* button at the top of the page.
In the pop-up modal, click the checkbox "Create a team member profiles with admin rights" box and enter your team member's email address.
Click *Add Team Profile* and an email is sent to the team member's email address with a link to activate their account.
#### Team Member Status
Once the team member has accepted the invite you will see a green check mark next to the Team Member tag.
If the team member has not yet accepted the invite you may resend it by clicking the mail icon.
#### Team Members Contacting Support
For security, only registered team members may contact support on behalf of a business. We will
not be able to assist if they are not registered and verified as a team member of your business.
### Reactivate a Suspended User Profile
#### Suspension Reason
When a User Profile gets suspended due to a social network violation (such as a [Facebook community standards violation](/docs/help-center/technical-support/facebook_or_instagram_account_restricted)), you will receive a detailed notification email.
This email contains important information about the suspension, including the specific reason and the affected User Profile.
To locate this notification email:
1. Search your inbox using the RefId of the suspended User Profile
2. The email subject will clearly indicate a suspension has occurred
Alternatively, you can view suspension details directly in the dashboard by clicking on the "Suspended" tag that appears next to the affected User Profile.
All API calls for that User Profile will return a [403 HTTP status code](/docs/errors/errors-http#403-access-denied).
#### Reactivate a Suspended User Profile
You may reactivate, i.e. unsuspend, the User Profile by:
1. Logging into the Dashboard and going to the User Profiles page.
2. Find the suspended User Profiles by clicking the "Suspended" tab or searching by the RefId of the User Profile, which is included in the email.
3. Unsuspend the User Profile by clicking the "Unsuspended" button.
4. Review and accept the compliance certification.
For a User Profile's first suspension, the User Profile can be immediately unsuspended once you accept the compliance certification.
However, for subsequent suspensions the User Profile will be reinstated 48 hours after accepting the compliance certification.
We recommend you *do not* use your Primary Profile as a regular User Profile. If the Primary
Profile is suspended, all user profiles will also be suspended.
### Managing Active User Profiles
Effective management of User Profiles is essential for maintaining an efficient system in Ayrshare.
We recommend implementing a policy to remove inactive User Profiles based on your business requirements.
For example, if a user hasn't engaged with your platform by posting content, requesting analytics for some time period, or has not connected any social networks, consider deleting their Ayrshare User Profile, thus keeping your user base current and reducing future costs.
You can check if a User Profile has been active in the current month by reviewing their [posting history](/docs/apis/history/overview) and [API usage and connections](/docs/apis/user/overview).
If you determined it to be inactive, [delete the User Profile](/docs/apis/profiles/delete-profile).
## White-Label the Connect Accounts Page
The connect accounts (social linking) page is the **only** Ayrshare interface your customers ever see, so you can white-label it to match your brand. Settings below are configured once by your team from the Primary Profile and apply to the page your users open via the [JWT URL](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication).
**Available on the Launch, Business, and Enterprise plans:**
[Add or remove your company logo](#update-logo-on-social-linking-page) and set its height.
[Choose which social networks](#set-social-networks-access) your users can connect.
[Set the page language](#set-language-for-social-linking).
[Show your own help links or hide Ayrshare's](#help-links-visible).
[Set the top and sub headers](/docs/apis/profiles/create-profile) per User Profile (e.g. the client's name or business).
[Control the Close button redirect](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url) back to your app.
[Customize the Instagram and Telegram modals](#custom-modals) with your own HTML.
**Available with the [Max Pack](/docs/additional/maxpack) (and included with Enterprise):**
[Apply a custom CSS file](#customize-css) to control colors, fonts, and which features show, using [documented class hooks](#css-class-hooks) to restyle the connect buttons themselves.
[Set your own page title, Close button text, and favicon](#change-page-title-close-button-and-favicon).
[Add custom footer text or HTML](#footer-text).
See the [User Integration](/docs/multiple-users/user-integration#social-linking-page-customization) page for how this looks from your user's perspective.
## Settings
In the *User Profiles* page select "⚙️ Settings" button to access global settings for your profiles.
Be sure to first switch to your *Primary Profile* to access the settings.
### Video Demo of Linking Page Customization Options
### Restrict User Profile Access
#### Restrict Primary Profile Access
Restrict access to the Primary Profile from user and team member profiles by locking the Primary Profile.
Activate the Primary Profile lock if you want to prevent team members or user profiles from accessing Profile Settings or the Account/Billing page.
When activated team member and user profiles will not be able to switch to the Primary Profile, but may
switch to other team member or user profiles.
#### Restrict Team Member Access
Restrict access to team member profiles by locking their account.
This prevents the team member from switching to any other User Profile.
Enable the lock by clicking the or icon in the top right of a team member profile.
You may also lock the team member when you [create the profile](/docs/multiple-users/manage-user-profiles#create-a-new-profile).
### Update Logo on Social Linking Page
Add your own logo and set the logo height for the [social linking page](/docs/multiple-users/user-integration).
Individual User Profiles can suppress this logo on their own linking page via the `hideLogo` parameter on [Create Profile](/docs/apis/profiles/create-profile) and [Update Profile](/docs/apis/profiles/update-profile). The account-wide logo on every other profile is unaffected. This is useful when an agency white-labels one partner while keeping branding on the rest of their profiles.
### Set Social Networks Access
Remove or grant your users/profiles access to the available social networks.
By default all social networks are active and available.
Permissions are global across all your user profiles. Disabling only removes the network from your
user's Social Accounts view and does not remove established links.
See the [create a profile](/docs/apis/profiles/overview#enable-or-disable-social-networks) endpoint for more
information on disabling social networks at the User Profile level.
### Set Language for Social Linking
Set the language for the social linking page. The default is English.
Available languages are:
English
Chinese (Simplified)
French
German
Spanish
If you require a language that is not listed, please contact us.
See here for additonal translation options:
[Translate API Error Message Responses](/docs/errors/errors-ayrshare#error-message-translation)
[Translate a Post](/docs/apis/generate/translate-post#translate-post)
### Display Page Location
On the social linking page, if a Meta (Facebook or Instagram) or Google Business Profile Page has a location associated with it, display that location information along with the Page name. This additional location context is helpful in scenarios where there are multiple Pages with identical names, as it allows users to differentiate between them more easily.
The Page location, if available, will be displayed below the Page name in the social linking page:
### Help Links Visible
Enable or disable visibility of the links to the Ayrshare help docs on your users' social linking page. You can also use your own by entering a URL to your publicly available docs.
### Alternative Emails for Alerts
Choose different email addresses to deliver alerts, such as unlinked accounts.
Further customization, such as the title can be done via the [/profiles endpoint](/docs/apis/profiles/create-profile).
### Instagram Login
Enable or disable Instagram login on the social linking page.
Choose whether to enable direct Instagram Login linking that does not require a connected Facebook Page for authentication. If disabled, Instagram linking will require a [connected Facebook Page](/docs/dashboard/connect-social-accounts/facebook) for authentication.
Instagram Login is **enabled by default**. If you require the advanced features listed below
(hashtag search, collaborations, location tagging, or brand data), you must manually disable this
option to use Facebook Page authentication instead.
#### Direct Instagram Login vs Facebook Page Authentication
**Direct Instagram Login** Instagram API with Instagram Login allows Instagram professionals (businesses and creators) to link their accounts directly without needing an associated Facebook Page. This provides a simplified authentication flow.
**Facebook Page Authentication** (traditional method) requires users to first connect a Facebook Page that is linked to their Instagram professional account.
#### Feature Limitations with Direct Instagram Login
While direct Instagram Login offers convenience, certain features are **not available** when using this method:
* **[Brand/User Data](/docs/apis/listen/brand-user#param-instagram-user)** - Cannot retrieve Instagram account information through the brand endpoints.
* **[Hashtag Search](/docs/apis/hashtags/search-hashtags)** - Cannot search for hashtags on Instagram.
* **[Collaborations](/docs/apis/post/social-networks/instagram#collaboration)** - Cannot invite collaborators to Instagram posts.
* **[Location Tagging](/docs/apis/post/social-networks/instagram#location)** - Cannot add location tags to Instagram posts.
* **[`idId`- Legacy Instagram User ID](/docs/apis/analytics/social)** - field not returned for Instagram social analytics.
#### Which Method Should You Choose?
* **Enable Direct Instagram Login** if you only need basic posting functionality and don't require the advanced features listed above.
* **Disable Direct Instagram Login** (use Facebook Page authentication) if you need access to all Instagram features, including hashtag search, collaborations, location tagging, or brand data retrieval.
For most clients, the preferred method is to use the direct Instagram Login authentication. If
you're unsure which method to use, we recommend disabling Direct Instagram Login to ensure access
to all features. You can always enable it later if you determine the advanced features are not
needed.
### Custom Modals
You can customize the content shown in the Instagram and Telegram modals on the social linking page with your own custom HTML content, such as displaying the content in different languages.
For Telegram, your content replaces the modal's default instructions. For Instagram, the modal only appears when you provide custom content — otherwise, clicking Instagram goes straight to the configured login flow: Instagram's own login or, if you have disabled [Instagram Login](#instagram-login), a Facebook login.
Your custom content can include formatted text, images, or a combination of both to better suit your needs.
For example, add you custom text with and anchor link:
```html Custom HTML Modal theme={"system"}
` tags. Add custom CSS to add color and/or underlining to anchor links.
## Using the API
### Create and Manage Profiles
You can create, delete, and manage your profiles via the API using the /profiles endpoints. Please see below for details.
### Get the Profile Key
The Profile Key is returned when you create a new profile via the API using the [/profile](/docs/apis/profiles/create-profile) endpoint. If you need to get the profile key again, go to the Dashboard to retrieve. See above.
## Enable Messaging
You can enable messaging for your Ayrshare account in the Account page. Please see here for more details:
## Max Pack Customization
In the Ayrshare Dashboard page *User Profile -> Setting*, you can customize aspects of the social linking page. Please see the [Max Pack](/docs/additional/maxpack) for details on the capabilities and features.
### Customize CSS
Use your own CSS file to customize the look and feel of the social accounts page: color, fonts, hide features, change buttons, and more.
A CSS file also fixes the page to the light color scheme. Your users are not shown the light/dark switch on a social linking page that has a CSS file, so your stylesheet alone decides how the page looks. Pages without a CSS file keep the switch.
#### CSS Class Hooks
The page carries stable class names so your stylesheet has something to select: on the page itself, on the grid the cards are laid out in, and on each social network card. These names are a **contract**: a stylesheet written against them keeps working across dashboard releases, so you can safely build on them.
Hosting your own stylesheet is **available with the [Max Pack](/docs/additional/maxpack)
(and included with Enterprise)**. The *Custom CSS* field is read-only without it.
These class names apply to the white-labeled social linking page your users open,
not to your own dashboard.
Anything not listed on this page is not a contract. In particular, do not select the page's own generated class names (they change without notice). See [Updating an older stylesheet](#updating-an-older-stylesheet).
**Page elements**
| Selector | Applies to |
| ----------------------------- | --------------------------------------------------------------------------------- |
| `.main-content` | The page content wrapper, edge to edge — put your page background here |
| `.social-linking-page-column` | The centred, width-capped column inside it that the content sits in |
| `.social-linking-header` | The header band holding your logo, the heading and the instruction block |
| `.company-logo` | Your [logo](#update-logo-on-social-linking-page), when you have set one |
| `.heading-social-accounts` | The page heading, an `
` element |
| `.additional-info` | The instruction block below the heading |
| `.additional-info__body` | The same element as `.additional-info`; see the note below |
| `.additional-info-text` | The instruction text inside that block |
| `.troubleshooting-guide` | The "Having trouble?" link, when [help links](#help-links-visible) are on |
| `.close-button` | The [Close button](#change-page-title-close-button-and-favicon) that ends linking |
`.main-content` and `.social-linking-page-column` are different elements, and the difference is what lets you widen the content without narrowing your background. The column carries the maximum width; the wrapper spans the full page. To run the cards wider than the default, set the width on the column:
```css theme={"system"}
.social-linking-page-column {
max-width: none !important;
}
```
**Card layout**
These two are new, so no older stylesheet selects them. Both are containers: they change where the cards sit and how wide they are, not how a card looks. See [Change the Card Layout](#change-the-card-layout).
| Selector | Applies to |
| ------------------------------ | ----------------------------------------------------------------------- |
| `.social-accounts-grid` | The grid that lays the cards out, and the `gap` between them |
| `.social-account-card-wrapper` | The grid cell holding one card, the element that owns that card's width |
**Social network cards**
| Selector | Applies to |
| ----------------------------- | ------------------------------------------------------------------ |
| `.social-account-card` | Every social network card, connected or not |
| `.connected-card` | A card whose network is connected |
| `.unlinked-card` | A card whose network is not connected yet |
| `.social-account-icon` | The square holding the network's logo on a card |
| `.social-account-name` | The network's name on a card |
| `.social-account-avatar` | The connected account's profile picture, on a connected card |
| `.click-to-link` | The "Click to link" call-to-action text on an unconnected card |
| `[data-platform=""]` | One specific network's card; see [below](#target-a-single-network) |
Every card carries `.social-account-card` plus exactly one of `.connected-card` or `.unlinked-card`, so the connected and unconnected states can be styled independently.
`.social-account-icon` is the square, not the logo drawn inside it. To resize a logo, size both — sizing only the square leaves the logo at its original size and it overflows:
```css theme={"system"}
.social-account-icon {
width: 24px !important;
height: 24px !important;
}
.social-account-icon :is(svg, img) {
width: 21px !important;
height: 21px !important;
}
```
**Status badge colors**
The "Connected" and "Messaging" badges on a connected card read two custom properties. Set them anywhere above the badge — `.social-account-card` is the natural place — and every badge on that card follows:
| Property | Sets |
| --------------- | ----------------------- |
| `--ayr-pill-bg` | The badge background |
| `--ayr-pill-fg` | The badge text and icon |
```css theme={"system"}
.social-account-card {
--ayr-pill-bg: #1b3a2b;
--ayr-pill-fg: #79bd96;
}
```
No `!important` is needed here, because a custom property is not competing with a generated rule. Leaving them unset renders the default colors.
Warning badges — "Relink required", "Reconnect", "Identity check" — deliberately
ignore these properties and keep their own colors. They tell your user that an
account has stopped working and needs their attention, and a warning painted in
the same color as "Connected" reads as reassuring. Those badges have no selector
of their own for the same reason.
**How the elements nest**
A card is five levels below `.main-content`, and one of those levels has no class name of its own:
```html theme={"system"}
…
…
…
TikTok
…
…
```
The card above is an unconnected one. A **connected** card carries `.connected-card` instead of `.unlinked-card` and swaps the last two pieces: `.click-to-link` is replaced by the status badges, and a `.social-account-avatar` holding the connected account's picture is added after the text column. So `.click-to-link` and `.social-account-avatar` never appear on the same card.
Select the named elements rather than the unnamed ones between them. The unnamed levels are not part of the contract and are the reason a rule that counts levels down from `.main-content` (`.main-content > div`, `.main-content > div > div > div`, `.main-content > div:not(.additional-info)`) lands a level or two off its target rather than on the grid or a card. See [Updating an older stylesheet](#updating-an-older-stylesheet) if your stylesheet has rules of that shape.
Style the card itself with `.social-account-card`, and reach for `.social-accounts-grid` or `.social-account-card-wrapper` when you want to change the layout rather than the card. See [Change the Card Layout](#change-the-card-layout).
**Change the order of the page**
To move the whole blocks of the page around — for example to put the instruction block at the bottom — flatten the containers between the page column and the pieces you want to order, then order them:
```css theme={"system"}
.social-linking-page-column {
display: flex !important;
flex-direction: column !important;
}
.social-linking-header {
display: contents !important;
}
/* Your logo, the instruction block and the Close button each sit inside a
further wrapper that has no name of its own. Flatten those too, or `order`
below has nothing to compare. */
.social-linking-header > div,
.social-linking-page-column > div:has(> .close-button) {
display: contents !important;
}
.company-logo {
order: 0 !important;
}
.social-accounts-grid {
order: 1 !important;
}
.close-button {
order: 2 !important;
}
.additional-info {
order: 3 !important;
}
```
`display: contents` removes a container from the layout while keeping its children, which is what puts your logo, the grid and the Close button on the same level so `order` can compare them. `order` only applies to items that are direct children of a flex container, so every wrapper in between has to be flattened — that is what the middle rule does.
The heading and the instruction block share one box, so they move together; hide the heading with `.heading-social-accounts { display: none !important }` if you only want the instruction block.
The two selectors in the middle rule are the one place on this page where you
still have to reach an element that has no name. They are anchored to named
elements one level up, so they are far more durable than counting down from
`.main-content` — but they are the rules to check first if a future release
changes how the page reorders.
Elements that depend on a setting (your logo, the "Having trouble?" link, the Close button) only exist in the page when that setting is on, so a rule targeting one is simply inert until then.
Your rules need `!important` to take effect. The page's own styles are
generated with a higher specificity than a plain class selector, so a
declaration without `!important` is silently ignored.
**Restyle `.click-to-link`, do not hide it.** It is the only thing on an
unconnected card that tells your user the network is not connected yet and that
the card can be clicked. A rule like
`.click-to-link { display: none !important }` leaves a card showing nothing but
the network name, which reads as inactive. If you want your own wording or
badge instead, add it to the card with `.unlinked-card::after` rather than
hiding the text and relying on a replacement elsewhere.
`.additional-info` and `.additional-info__body` match the **same** element. They
were previously two nested elements, so if your stylesheet sets different values
for the same property on each, they now compete on one element and the more
specific rule wins instead of both applying. Combine them into a single rule.
#### Updating an Older Stylesheet
If you wrote your stylesheet before the dashboard was rebuilt, some rules may no longer match. Rules built on the selectors documented above keep working. Rules built on anything else do not, and cannot be restored:
* **The page's own generated class names.** Class names you may have copied out of browser developer tools (for example anything beginning with `chakra-`) belong to the framework the page is built with, not to a public contract. Those class names no longer exist and there is no equivalent to swap in. Rewrite the rule against the selectors in the tables above.
* **Bare element or attribute selectors** such as `div > div` or `button[type="button"]`. The page's structure is not a contract and has changed, so a rule counting levels down from `.main-content` now lands on a different element than it did before. This is the most common reason a layout rule appears to do nothing, or does something unexpected.
* **Positional rules that counted elements to reach the card grid.** Before the grid and the cells had names, the only way to reach them was to count levels down from `.main-content`, using rules shaped like `.main-content > div`, `.main-content > div > div`, `.main-content > div > div > div` or `.main-content > div:not(.additional-info)`. Those rules still match something, which is why they are easy to miss: `.main-content` is still there, but a card now sits [five levels below it](#css-class-hooks), so each rule lands a level or two off target. A rule aimed at the grid can end up on the wrapper holding the page header, and a rule aimed at one card can end up resizing every card at once. Replace them with the two names that now exist for this: `.social-accounts-grid` for the grid, and `.social-account-card-wrapper` for the cell holding one card. See [Change the Card Layout](#change-the-card-layout).
* **Rules that only work on a flex item: `z-index`, `order`, `align-self`, `flex`.** These are the hardest to spot, because the selector still matches and the declaration is still valid — it simply has no effect. On the older page your logo, heading, instruction block and Close button were direct children of `.main-content`, which your stylesheet made a flex container, so each of them was a flex item. A flex item honours `z-index` even without `position`, and honours `order` and `align-self`. On the rebuilt page those four sit inside wrappers, so they are no longer flex items and all four properties stop applying to them.
The symptom is usually something vanishing rather than moving. A `z-index` on your logo, for example, is what used to lift it above a fixed header bar drawn with `.main-content::before` — without it the bar paints straight over the logo and the logo appears to be missing entirely, even though it loaded correctly and is the right size.
Two fixes, either is fine:
```css theme={"system"}
/* 1. Give the element a position, so z-index applies on its own. */
.company-logo {
position: relative;
z-index: 2;
}
```
```css theme={"system"}
/* 2. Or flatten the wrappers, which makes these elements flex items again
and restores z-index, order and align-self together. This is the same
recipe as Change the order of the page, above. */
.social-linking-page-column {
display: flex !important;
flex-direction: column !important;
}
.social-linking-header {
display: contents !important;
}
.social-linking-header > div,
.social-linking-page-column > div:has(> .close-button) {
display: contents !important;
}
```
* **`.linked-tag`.** The older page put this on the status badges of a connected card. It is **not** part of the contract above, deliberately: a connected card can now also show "Relink required" or "Identity check", so a rule hiding `.linked-tag` would hide a warning your user needs to act on. If your stylesheet hides `.linked-tag` and draws a replacement badge of its own, the replacement will not appear. Style [`.connected-card`](#css-class-hooks) itself instead, and leave the status badges visible.
If you are unsure whether your stylesheet still works, open your linking page and check that each rule takes effect. The stylesheet loads either way, so rules that no longer match fail silently rather than reporting an error. [Contact support](/docs/help-center/overview) if you would like help rewriting one.
#### Target a Single Network
Use the `data-platform` attribute rather than a position-based selector such as `:nth-child`. The networks available to your users [can be filtered](#set-social-networks-access) per account or per User Profile, which changes how many cards render and in what order. Position-based selectors break when that filter changes, and `data-platform` does not.
```css theme={"system"}
.social-account-card[data-platform="tiktok"] {
/* ... */
}
```
The value is the network's key on this page:
`bluesky`, `facebook`, `gmb`, `instagramApi`, `linkedin`, `pinterest`, `reddit`, `snapchat`, `telegram`, `threads`, `tiktok`, `twitterByok`, `whatsapp`, `youtube`
Two of these differ from the platform names you send to the API: on this page
Instagram is `instagramApi` and X/Twitter is `twitterByok`.
#### Change the Card Layout
By default the cards flow into a responsive grid: one column on a phone, two on a tablet, and three on a desktop. Two selectors control that layout, and which one you want depends on what you are changing:
* **`.social-accounts-grid`** is the grid itself. It is a flex row that wraps, and the space between cards is its `gap`. Use it to change that spacing, or to replace the layout entirely.
* **`.social-account-card-wrapper`** is the cell holding one card. Its `width` is what decides how many cards fit per row, and the page sets that width per screen size.
The cell is the **only** element on which a card's width, or the number of cards per row, can be changed. Everything between the cell and the card already fills the cell's full width, so a `width` set on `.social-account-card` (or on the unnamed wrapper between them) repaints the card inside a cell that has not moved, and the columns stay exactly where they were.
Neither of these is the card. To restyle a card's border, background, or text, use [`.social-account-card`](#css-class-hooks) as before.
To change only the space between cards:
```css theme={"system"}
.social-accounts-grid {
gap: 24px !important;
}
```
To put every card on its own full-width row, one rule covers every screen size, because `!important` also wins against the widths the page sets in its own screen-size rules:
```css theme={"system"}
.social-account-card-wrapper {
width: 100% !important;
}
```
To set your own column count, take the grid over completely. The cell width has to be released as well, otherwise it fights the columns you just defined:
```css theme={"system"}
.social-accounts-grid {
display: grid !important;
grid-template-columns: repeat(2, 1fr) !important;
gap: 16px !important;
}
.social-accounts-grid .social-account-card-wrapper {
width: auto !important;
}
```
**If you have [restricted the page](#set-social-networks-access) to one or two
networks**, the row does not fill its columns, and the page centers it for you. On
`.social-accounts-grid` it sets a `width` and a `max-width` that narrow the grid to
the cards it actually has, and `align-self: center` to center that narrower box,
with automatic side margins as a fallback. On each `.social-account-card-wrapper`
it sets a correspondingly wider `width`, so the cards keep the size they have in a
full row. All of this applies only at the screen sizes where the row is actually
short. With three or more networks the row is always full and none of it is set at
all. Your own rules override either element as normal, with `!important`, but note
that `align-self` is the declaration doing the centering: to align a short row
differently, override that as well as the widths.
Avoid selectors that count elements, such as
`.main-content > div > div > div`. The page's structure is not a contract and
changes between releases, so a rule like this can start matching a different
element, or every card at once, without your stylesheet changing. The two
selectors above are stable and are the supported way to reach the layout.
#### Example: Hide the Page Heading
The heading is an `
` element, so a tag-qualified selector works if you prefer one:
```css theme={"system"}
h1.heading-social-accounts {
display: none !important;
}
```
#### Example: Restyle Unconnected Cards as Buttons
By default an unconnected card is a recessed grey surface with muted text, which some users read as unavailable rather than as something to click. The rules below turn every unconnected card into an outlined button in your brand color and leave connected cards untouched.
```css theme={"system"}
/* Unconnected cards become outlined buttons. */
.social-account-card.unlinked-card {
background-color: #ffffff !important;
border-color: #4f46e5 !important;
border-width: 2px !important;
border-radius: 8px !important;
}
/* An !important rule also wins over the page's own hover styles,
so restate the hover state you want. */
.social-account-card.unlinked-card:hover {
background-color: #eef2ff !important;
border-color: #4338ca !important;
}
/* The muted call to action becomes the button label. */
.social-account-card.unlinked-card .click-to-link {
color: #4f46e5 !important;
font-weight: 600 !important;
}
```
For a solid fill instead, set the card background and recolor its text. Only the selectors in the table above are a contract, so recolor the network name with a plain descendant selector:
```css theme={"system"}
.social-account-card.unlinked-card {
background-color: #4f46e5 !important;
border-color: #4f46e5 !important;
}
.social-account-card.unlinked-card p {
color: #ffffff !important;
}
```
The network logo on an unconnected card is intentionally desaturated and has no
selector of its own, so it stays greyscale on a colored background. Preview
your stylesheet on the [linking page](/docs/multiple-users/user-integration) before
rolling it out to your users.
### Change Page Title, Close Button, and Favicon
Set your own page title, close button, and favicon (.ico file).
### Footer Text
Customize the footer text and add copyright information on the social linking page. This allows you to display the footer text in different languages.
## Enterprise Features
### Max Pack
All the feature of [Max Pack](/docs/additional/maxpack) included with Enterprise.
### Automatically Resync Facebook and Instagram Pages
When security events occur on Facebook, such as password changes, all Facebook pages associated with that user account (including linked Instagram accounts) need to be reconnected to Ayrshare. For accounts managing numerous pages, this process can be time-consuming.
The "Resync" option is available when connecting Facebook or Instagram pages.
By enabling this feature, all previously connected pages will be automatically relinked to the
user profile.
Note: Only previously linked pages will be reconnected; new pages will not be added
automatically.
This feature supports Facebook accounts with up to 400 pages.
For accounts exceeding 400 pages, it's recommended to distribute pages across multiple Facebook
accounts.
**Best Practice:** Only use the "Resync" option when necessary to reconnect all pages. For
routine operations, it's generally not required.
### White List IP
Enhance your account security by whitelisting specific IP addresses. This feature restricts API access to only approved IP addresses, adding an extra layer of protection to your Ayrshare integration.
### Technical and Security Reviews
Collaborate directly with Ayrshare's project team for comprehensive technical and security reviews. This service ensures that your integration aligns with best practices and meets your organization's specific security requirements.
### Dedicated Account Management with Priority Support
Receive personalized support from a dedicated account manager who understands your unique needs and can provide tailored solutions. Enjoy priority access to technical support, with faster response times and escalation procedures for critical issues.
### Custom API Endpoints
For enterprises with specific requirements, Ayrshare can develop custom API endpoints to seamlessly integrate with your existing systems and workflows.
# User Integration
Source: https://www.ayrshare.com/docs/multiple-users/user-integration
How to integrate with Ayrshare allowing your users, clients, or brands to link their social media accounts.
Ayrshare operates as an API-centric platform, designed to work discreetly in the background.
The *only interaction* your users will have with an Ayrshare interface is through the white-labeled social linking page, which you open for them with a [JWT URL](/docs/multiple-users/api-integration-business#single-sign-on-with-jwt-authentication).
This process is designed to be smooth and effortless for your users, without requiring them to create an account or log in.
Your customers never access the Ayrshare dashboard — that is reserved for your
internal team. You can [white-label the connect accounts page](/docs/multiple-users/manage-user-profiles#white-label-the-connect-accounts-page)
with your logo, colors, headers, and more so it feels like a native part of
your product.
Ayrshare organizes each of your users into an Ayrshare **User Profile**. A User Profile can have one connection to each social network.
## User Experience
Your users will authorize their social media accounts, such as Instagram or Facebook, to allow you to post, get analytics, etc. on their behalf via Ayrshare's API. **Each User Profile can have one connection to each of the social networks.**
1. Within your app, create a link or button, e.g. "Link Your Social Accounts", that your user will click to open the social linking page.
2. When the link is clicked, open a new browser tab, window, or webview with the URL returned from the [/generateJWT endpoint](/docs/apis/profiles/generate-jwt).
3. The social linking page will show all the available networks, which you can [control](/docs/multiple-users/manage-user-profiles#set-social-networks-access). At the top will be your branded logo. You can [customize](/docs/multiple-users/manage-user-profiles#user-profile-settings) many aspects of this page such as the title, help link, and profile image.
4. Your user will choose the social networks they want to link and close the tab once complete by clicking the All Done button.
At the top of the page will be your branded logo.
**From the user's perspective they are done and have successfully linked their social media accounts**. With just a few clicks they will have their social media accounts linked and you'll be able to post on their behalf.
Behind the scenes, you'll create new profiles via the API or Dashboard, receive a Profile Key used to post on behalf of the users, and open the above social linking page by passing a JWT token to perform single sign on.
Please see the next page on API Integration for Business on how to do this.
## Social Linking Page Customization
You can customize many portions of the social linking page for either all users
or specific users. Please see each section for details. There are also specific
details for the Business and Launch Plans, with and without Max Pack.
### Business Plan and Launch Plan Customizations
Add your own [company
logo](/docs/multiple-users/manage-user-profiles#update-logo-on-social-linking-page) or remove
entirely. Please see your onboarding integration guide for details.
Select which social networks your users can access either
[globally](/docs/multiple-users/manage-user-profiles#set-social-networks-access) or at the [user
profile level](/docs/apis/profiles/overview#enable-or-disable-social-networks).
Remove links to help pages and [add your own help
pages](/docs/multiple-users/manage-user-profiles#help-links-visible).
Set the [page
redirect](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url)
for closing the social linking page.
Set the [top and sub headers](/docs/apis/profiles/create-profile) on the social linking page.
You can show your user's name, their business, another message, or remove entirely.
### Business Plan and Launch Plan Max Pack Customizations
Personalize your social linking page appearance with your own [custom CSS
file](/docs/multiple-users/manage-user-profiles#customize-css) - modify colors, fonts, and control
which features are displayed. The page heading, instruction text, logo, Close button and every
social network card carry [stable class
hooks](/docs/multiple-users/manage-user-profiles#css-class-hooks) so you can restyle the connect
buttons, style connected and unconnected cards differently, target a single network, or change
how the cards are laid out.
Customize the browser tab by adding your own [favicon and
title](/docs/multiple-users/manage-user-profiles#change-page-title-close-button-and-favicon) to
the social linking page.
Edit the ['Close' button text](/docs/multiple-users/manage-user-profiles#change-page-title-close-button-and-favicon) on
the social linking page.
Add [custom footer content](/docs/multiple-users/manage-user-profiles#footer-text) to the social
linking page using text or HTML - perfect for your copyright notice or website links.
Set up a staging server environment to test with live social accounts, up to your plan's User
Profile cap.
**Business Plan** and **Launch Plan** customers can purchase the [Max Pack](/docs/additional/maxpack) for
more customization options.
**Enterprise Plan** customers get
[advanced features](/docs/multiple-users/manage-user-profiles#enterprise-features).
# Airtable
Source: https://www.ayrshare.com/docs/packages-guides/airtable
Manage your users' social media accounts from Airtable
## Overview
[Airtable](https://www.airtable.com) is a versatile cloud-based platform that seamlessly blends the structure of a spreadsheet with the robust capabilities of a database.
By integrating Airtable's automation scripts - written in JavaScript - with Ayrshare's API, you can streamline your social media management directly within Airtable. This integration empowers you to post content, analyze performance metrics, and manage comments on behalf of your users, all from one centralized location.
In this guide, we'll walk you through the steps to set up the integration.
## Set Up
Running Airtable Automation Scripts requires a [paid](https://airtable.com/pricing) Airtable plan.
Please be sure your Airtable plan includes automations with scripts.
This guide shows you how to automatically post to linked social media accounts in Airtable via [Ayrshare](https://www.ayrshare.com).
You can post to a single company's social accounts or to your managed client's social media accounts. All the below code can be found at [GitHub](https://github.com/ayrshare/airtable-post-social-media/blob/main/script.js).
## Gather Your API Key
Start by getting your free or paid plan API Key in [Ayrshare Dashboard](https://www.ayrshare.com). The key will be used in the script below.
If you are on the Ayrshare [Launch Plan](/docs/multiple-users/business-launch-overview) or [Business Plan](https://www.ayrshare.com/business-plan-for-multiple-users/) and want to post on behalf of your clients, gather all your client's Profile Keys either via the /user or /create-profile endpoints or in the Ayrshare Dashboard.
Be sure you have linked a few social accounts in Ayrshare. Please verify in [Ayrshare Social
Linking page](https://app.ayrshare.com/social-accounts).
## Create an Airtable Workspace
In [Airtable](https://www.airtable.com), create a new workspace with the fields. Please be sure to name cell columns as below:
`Post` as Long Text
`Platforms` as Multi Select with types: facebook, instagram, twitter, linkedin, reddit, and
telegram
`Images` as Attachment
`Profile Keys` as Single Line Text
`Status` as Single Line Text.
`Schedule Date` as Date with Local Format, Include Time Field, and Time Format 24 Hours
These fields will be used in the Airtable automation script we are about to build.
See a [live Airtable example](https://airtable.com/shrCWY0oA1ghB42tI/tblpnTEiPwyuViqBo).
See a live Airtable example
## Enter in Test Post Data
We need some sample data to test the post. Here is a suggestion:
`Post`: Enter *Happy New Year 2025*
`Platforms`: select one or more networks you have linked. Please be sure the name is lowercase.
`Images`: Attach an image. We like this one you can download and attach:
[https://img.ayrshare.com/012/gb.jpg](https://img.ayrshare.com/012/gb.jpg)
`Profile Keys`: If you are on the Business Plan or Launch Plan and want to post to a client's profile, enter
their Profile Key. *Otherwise, leave blank.*
`Status`: Enter *pending*. The script only grabs records that are set to pending. Please be
sure "`pending` is lowercase.
`Schedule Date`: Leave blank since we'll just test immediate posting right now. Later you can
select a future date to schedule the post.
## Build an Automation Script with the Script Editor
We'll now build the Airtable automation script that reads your data from the table, creates a post, and send it to the social networks via Ayrshare. You will be using the Airtable script editor.
### Add Trigger
* In the workspace, click on *Automation* and then *+New automation.*
Name the automation.
Click *Choose a Trigger*.
Select When a Record is Created.
Select the table with the above fields.
Click Done.
## Add Action
Start by clicking *Add Action*.
Select *Run Script*. You will be brought into the script editor.
**Delete** the line:
```javascript theme={"system"}
console.log(`Hello, ${base.name}!`);
```
And **copy and paste** into the script editor the following code:
```javascript theme={"system"}
const API_KEY = "Your API Key"; // Get a free key at app.ayrshare.com
console.log(`Starting Post ${base.name}!`);
const sendPost = async (data) => {
const { post, platforms, imageUrls, profileKeys, scheduleDate, shortenLinks } = data;
const body = Object.assign(
{},
post && { post },
platforms && { platforms },
profileKeys && { profileKeys: profileKeys.split(",") },
Array.isArray(imageUrls) &&
imageUrls.length > 0 && {
mediaUrls: imageUrls.map((image) => image.url)
},
scheduleDate && { scheduleDate },
shortenLinks !== undefined && shortenLinks !== null && { shortenLinks }
);
console.log("Posting JSON:", JSON.stringify(body, null, 2));
if (profileKeys) {
body.profileKeys = profileKeys.split(",");
}
const response = await fetch("https://api.ayrshare.com/api/post", {
method: "POST",
body: JSON.stringify(body),
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${API_KEY}`
}
}).then((res) => res.json());
return response;
};
const table = base.getTable("Posts");
const query = await table.selectRecordsAsync();
const filteredRecords = query.records.filter((record) => {
const status = record.getCellValue("Status");
return status === "pending";
});
for (let record of filteredRecords) {
const post = record.getCellValue("Post");
const images = record.getCellValue("Images");
const platforms = record.getCellValue("Platforms");
const profileKeys = record.getCellValue("Profile Keys");
const scheduleDate = record.getCellValue("Schedule Date");
const shortenLinks = false;
const response = await sendPost({
post,
platforms: platforms.map((x) => x.name),
imageUrls: images,
profileKeys,
scheduleDate,
shortenLinks
});
console.log(response);
if (response) {
let status;
if (Array.isArray(response)) {
status = response.map((x) => x.status).every((x) => x === "success") ? "success" : "error";
} else {
status = response.status;
}
await table.updateRecordAsync(record, {
Status: status
});
}
}
```
This code will read from your table and post to Ayrshare. However, you first need to add in your API Key (gathered from above).
Replace `Your API Key` with your real API key.
## Test the Script
In the script editor, press *>Test*
The script will run and output the response from the API call. If everything worked, you'll see a success message returned, the pending field in your records changed to success, and your post on the selected social network.
Once you create a new record in the table, the script will run and process pending records.
## Airtable Docs
If you want more information, see the [Airtable docs](https://www.airtable.com/developers).
They have details on how to use the Airtable script editor.
## Video Tutorial
Here is a great video tutorial from the team at Automate All The Things. This video walks through how to integrate Ayrshare into a live Airtable project.
Please see more [examples of integrating Airtable with social media](https://www.ayrshare.com/blog/automatically-post-to-social-media-from-airtable/).
## Questions
If you have any questions or comments, please reach out to us via [email](mailto:contact@ayrshare.com) or chat with us.
# Bubble.io
Source: https://www.ayrshare.com/docs/packages-guides/bubble
Use the Bubble Ayrshare plugin or API Connector to manage your users' social media accounts
## Overview
[Bubble.io](https://www.bubble.io), a popular no-code platform, enables you to build web and mobile apps without writing a single line of code.
By integrating Ayrshare's social media API, you can manage your users' social media accounts directly within your Bubble app.
There are two ways to achieve this:
**Bubble Ayrshare Plugin**: This user-friendly option requires minimal set up. However, it has
limited functionality compared to the Bubble API Connector.
**Bubble API Connector**: For greater flexibility and control, utilize the Bubble API Connector.
This approach allows you to directly interact with Ayrshare's API, enabling a wider range of
functionalities within your Bubble.io app.
This guide will walk you through both integration options.
## Quick Start: The Bubble.io Ayrshare Plugin
[Bubble is one of the most powerful no-code software development platforms](https://www.ayrshare.com/blog/the-definitive-bubble-review-a-flexible-no-code-app-builder-growing-over-50/). The simplest way to get started is with Ayrshare's [Bubble.io Plugin](https://bubble.io/plugin/ayrshare-social-media-api-1607956467620x490188301088063500). See below for a more [advanced Bubble integration](/docs/packages-guides/bubble#the-bubble-api-connector-plugin).
First create an account at [ayrshare.com](https://www.ayrshare.com). Then connect your social media accounts.
Once your accounts are connected you can navigate to the API Dashboard and copy your API key.
Remember that when you paste in your API key in your Bubble app, to include the word "Bearer" in front of your API key.
For example:
`Bearer bf55cc6f-76ac-46ce-b497-439d766f6c12`
Add the Ayrshare plugin via the Bubble plugin marketplace to your Bubble app. In the plugin field "API Key" enter your API Key.
Now you can send posts via your Bubble app to your social media accounts.
The image below is an example workflow call in Bubble to the plugin for an post with an image.
The video above explains this in more detail. Ensure that you are using the following parameter types:
post: a text formatted as JSON-safe
platforms: a list of texts where each text has parenthesis around it, such as
`"facebook","instagram"`
media: a text URL formatted as JSON-safe
date: a date/time formatted as JSON-safe
The Ayrshare Plugin allows you to post and delete posts. To unlock the full power of Ayrshare, we recommend you use the Bubble API Connector Plugin and configure it with the endpoints that you need for your app.
## The Bubble API Connector Plugin
Alternatively, you can use the Bubble API Connector Plugin to access the full power of the Ayrshare API. Here is a video which will get you started using the Bubble API connector with Ayrshare and walks you through how to post multiple images per post.
Bubble's API Connector can sometimes be tricky where missing a single closing quote or space can
cause the connection to fail. We recommend watching the below videos carefully and re-reviewing if
something isn't working.
Below is another tutorial video showing how to get social profile analytics in Bubble.
## Post to Multiple Social Media Accounts
Here is a article with an overview:
## Validate Bubble Post Data
When posting to Bubble via the API Connector, it can be difficult to determine if you are sending valid JSON. Often if the JSON posted to Ayrshare is invalid the response will be HTML.
Ayrshare has a /validateJSON URL that allow you to post to instead of the typical /post endpoint. It will return "Valid" or "Not Valid". Be sure to set the Content-Type as `text/plain` instead of the typical `application/json`.
Click the Troubleshooting link for "Response Returns as Bad Request" to see the details.
## Upload Media Files in Bubble
Use Bubble's File Uploader to upload your media files. These files are stored on Amazon's S3. You will receive back a URL that can be used in the `mediaUrls` body parameter of the `/post` endpoint.
## Generate JWT Token in Bubble
To generate a JWT Token in Bubble, first you need to Stringify the private.key you send to the [/profiles/generateJWT](/docs/apis/profiles/generate-jwt) endpoint.
**Step 1:** Go to [https://onlinetexttools.com/json-stringify-text](https://onlinetexttools.com/json-stringify-text) and paste in your private.key in the left-hand input text section. Then copy the stringified text on the right side to your clipboard.
**Step 2:** In your Bubble app, create a new call with the API Connector as shown below. The text in the `privateKey` field in the Body area is the stringified text that you created in step 1 above.
Also include your provided `domain` and `profileKey` as shown below.
**Step 3:** Click the **Initialize call** button and save the response. The `url` field in the response is what your user will click to access the social media accounts linking page.
## Allow Users to Link Their Social Accounts
If you are using the Launch Plan, Business Plan, or Enterprise Plan, this video shows you how to set up Bubble to enable all your users to link their social accounts.
## Rewrite Text and Post to Social with AI in Bubble
How you can use Ayrshare and Bubble.io to build a rewriting and social posting app. The app takes some text, rewrites it 5 different ways, and posts it to your social accounts.
## Bubble API Connector
We recommend using the [Bubble API Connector](https://manual.bubble.io/account-and-marketplace/building-plugins/adding-api-connections) to make your Ayrshare API calls.
Please note that Bubble will time out all API calls after 150 seconds and then retry the call once more. Large video might take longer than 150 seconds, which will cause Bubble to automatically try the post once more and result in a duplicate post error. We recommend using a [schedule post](/docs/help-center/technical-support/response_bad_gateway_502_or_504_error) for larger videos.
## Useful Bubble Blog Articles
* [Build a Social Media Posting Mobile App with No Code](https://www.ayrshare.com/blog/build-a-social-media-posting-mobile-app-with-no-code/).
* [How to Create a Social Media Scheduling App with No Code.](https://www.ayrshare.com/blog/how-to-create-a-social-media-scheduling-app-with-no-code/)
# Flutter
Source: https://www.ayrshare.com/docs/packages-guides/flutter
Manage your users' social media accounts from Flutter using the Ayrshare Flutter SDK package
## Overview
[Flutter](https://flutter.dev) is Google's UI toolkit for building beautiful, natively compiled applications for mobile, web, and desktop from a single codebase.
The Ayrshare Flutter SDK package allows you to integrate Ayrshare's social media API with your Flutter apps.
## Installing
Install the package as a library in your app.
```shell theme={"system"}
$ flutter pub add ayrshare_flutter
```
Ayrshare Flutter SDK package
## Usage Example of Posting
This sample app creates a button which calls the post function. It posts a random quote and a random image to the linked Twitter and Facebook accounts. It prints the response which includes the URLs for the live posts on the social networks.
```dart theme={"system"}
import 'package:flutter/material.dart';
import 'ayrshare_flutter.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: PostingPage(),
);
}
}
class PostingPage extends StatelessWidget {
///TODO get your API key by signing up at ayrshare.com
final apiKey = '###-###-###-###';
@override
Widget build(BuildContext context) {
return Scaffold(
// appBar: null,
body: Center(
child: ElevatedButton(
onPressed: () async {
await post(
apiKey: apiKey,
body: {
'randomPost': true,
'platforms': ['twitter', 'facebook'],
'randomMediaUrl': true
},
).then((value) => print(value));
},
child: const Text('Post To Social'),
),
));
}
}
```
## More Information and Documentation
Launch the linking page (generateJWT) on [iOS with
Flutter](/docs/apis/profiles/generate-jwt#mobile-jwt-examples).
# FlutterFlow
Source: https://www.ayrshare.com/docs/packages-guides/flutterflow
Integrate the Ayrshare API into your FlutterFlow app
## Overview
[FlutterFlow](https://flutterflow.io) is a no-code development platform that allows you to build mobile and web apps.
The Ayrshare API can be integrated into your FlutterFlow app to manage your users' social media accounts.
## Tutorial
We've created a [great tutorial](https://www.ayrshare.com/blog/build-a-social-media-posting-app-in-no-code-platform-flutterflow/) on integrating the Ayrshare API using [FlutterFlow](https://flutterflow.io).
In this FlutterFlow tutorial, we will create a mobile application using FlutterFlow, a no-code development platform. The primary goal of the app is to enable users to post text and images simultaneously to multiple social media platforms, including Facebook, X/Twitter, and LinkedIn.
To achieve this, we will utilize the Ayrshare API, which simplifies the process of posting content to various social networks. By integrating Ayrshare into our FlutterFlow app, users will be able to connect their social media accounts and post updates across multiple platforms with ease.
Furthermore, we will expand the functionality of the app to allow all users of the FlutterFlow platform to post to their own social media accounts.
This will be accomplished by leveraging the Ayrshare Profile Key, a unique identifier that securely links a user's social media profiles to their Ayrshare account.
By the end of this tutorial, you will have a fully functional mobile app built with FlutterFlow that empowers users to seamlessly post content to Facebook, X/Twitter, LinkedIn, and other supported social networks, all from a single interface. The integration of Ayrshare and the utilization of Profile Keys will provide a streamlined and efficient way for users to manage their social media presence.
# Ayrshare SDKs & Integration Guides Overview | Documentation
Source: https://www.ayrshare.com/docs/packages-guides/overview
Explore Ayrshare's official SDKs and integration guides, including Node.js and Python, to connect the social media API to your app quickly and reliably.
## Ayrshare SDKs and Integration Guides
SDKs, packages, modules, and guides can help facilitate integration with Ayrshare.
Use an Airtable automation scripts to post to social media directly from Ayrshare
Integrate Ayrshare with Bubble.io using the Ayrshare Bubble plugin or the Bubble API Connector
Manage your users' social media accounts from Flutter using the Ayrshare Flutter SDK package
Integrate the Ayrshare API into your FlutterFlow app
Integrate the Ayrshare API into your Make app to manage your users' social media accounts
Connect n8n's AI Agent to the Ayrshare MCP Server to publish, schedule, and analyze across your social networks
Node.js NPM client package for Ayrshare
Integrate the Ayrshare API into your Notion app to manage your users' social media accounts
Python PyPI client package for Ayrshare
Integrate the Ayrshare API into your Retool app to manage your users' social media accounts
If there is a package or guide you are looking for, please [contact us](mailto:support@ayrshare.com).
# Update Archive
Source: https://www.ayrshare.com/docs/whatsnew/archive
What's New Archive
## Ayrshare Changelog
Follow us on Twitter, our Social Media API Podcast, or our Newsletter for the latest updates.
### December 2023
**Instagram Followers By Time**. Get detailed hourly breakdowns for when
your Instagram followers are online. This allows you to optimize posting for
maximum engagement, by determining the most popular times.
**Public Analytics Data**. The Brand endpoint is now available with the
Business Plan. Retrieve analytics data on all public social accounts. For
example, get social stats on @theRock or @taylorswift. This also allows the
lookup of Facebook Page IDs for tagging locations in Facebook and Instagram
posts.
**Reply to Comments**. Reply to comments (i.e. comment on comments) for
Facebook, Instagram, LinkedIn, TikTok, Twitter, and YouTube.
**Facebook History**. Facebook Groups history is now available for posts
made outside of Ayrshare.
**Media Metadata**. Get the metadata of a media file URL. For example, for a
video you can get the codec, duration, file size, resolution, and more.
**X/Twitter Analytics**. X/Twitter post analytics and get all history now
returns links to the video or animated GIF files.
### November 2023
**Facebook Stories**. Publish photos or videos as Facebook Stories. Stories
are a more immersive posting format that disappear after 24 hours.
**YouTube Comments**. Get YouTube comments by the YouTube social ID.
**Instagram Analytics**. Instagram Reels Analytics have been enhanced to
include the average amount of time spent playing the reel and the total
amount of time the reel was played.
**Linkedin History**. The history endpoint for LinkedIn now returns all the
media images of a post.
**Reddit Flair**. Retrieve the flair of a Subreddit to add the flair to a
Reddit post. Some subreddits require specific flair categories to post.
**Social Linking**. Customize the modals on the social linking page for
Facebook Groups, Instagram, and Telegram. Add your own HTML including
images.
**Pinterest Image Carousel**. Now you can post up to five photos in a
carousel with links, titles, and descriptions. Users on Pinterest can swipe
through the carousel directly from the feed.
**Facebook Analytics**. New Facebook analytics data points on social
accounts available. New data includes video data and more detailed
impressions.
**Integration Package**. You can now download or reset your integration
package via the dashboard. The integration package includes important set up
and domain information, example endpoint calls, and more.
**Comment Deletion**. Delete Instagram and YouTube comments. Other social
networks where you can delete comments are Facebook, LinkedIn, Reddit, and
X/Twitter.
**YouTube Categories**. Look up and assign YouTube video categories. The
categories are an important input for discovery of your videos in the
YouTube algorithm.
**Reddit Comments**. Now you can add, get, and delete comments on Reddit.
**Staging Server**. Create a staging server environment in the dashboard. Go
to the User Profiles page and click on Settings to add this to your account.
This is a Max Pack feature.
### October 2023
**New Dashboard**. We released the new Ayrshare dashboard, which you can
access at app.ayrshare.com. It's now easier than ever to navigate with the
new design, based on Chakra UI, with many enhancements over the previous
developer dashboard.
Improved self service account management, such a subscribing to Max Pack.
Enhanced User Profile settings, such as upload your logo and set custom
CSS (Max Pack required).
All new webhook logs with advanced search.
More detailed API call tracking.
**Publish Documents to LinkedIn**. Use the API to post a document on
LinkedIn. Supported file formats include: PPT, PPTX, DOC, DOCX, and PDF.
**Webhooks Per User Profile**. Webhooks can now be registered per User
Profile. Set up a different webhook for each User Profile.
### September 2023
**Facebook Post Draft**. Now you can create a draft post or scheduled post
that appears in the Meta Business Suite Draft or the Meta Business Suite
Scheduled Posts tab.
**Notes on a Post**. Add reference notes to a post that can be retrieved via
the history endpoint. You can also update those notes later. A useful
complement to the post approval workflow.
**TikTok Comments**. TikTok comments now returns replies on comments in a
list with the associated metadata for each reply.
**Facebook and Instagram Comments**. Now you can get Facebook and Instagram
single comments and replies.
**Check if Uploaded URL Exists**. A new endpoint to check if a uploaded
media URL exists. Should be used in conjunction with the large media upload
URL.
**Linkedin History**. Get All History now returns the link to the image or
video attached to the LinkedIn post.
### August 2023
**TikTok Post Text**. TikTok post text now supports up to 2,200 characters.
This is an increase from the prior limit of 150 characters. Get increased
engagement on your videos since the TikTok algorithm uses this text to make
recommendations.
**X/Twitter Captions**. Add subtitles, also known as captions, to X/Twitter
video files. Uploading your own captions ensures that your videos are
transcribed correctly.
**Post to All Social**. There is a new "platforms": \["all"] parameter for
the /post endpoint. This allows you to automatically post to all linked
social accounts.
**Alt Text Generation**. Use the /generate endpoint to automatically
generate alt text for an image. This alt text description is usually not
visible to average users but is accessible to search engines and assistive
technologies like screen readers, used by visually impaired individuals.
### July 2023
**Announcing the Max Pack**. The Max Pack is a new add-on that provides
additional endpoints and other useful utilities for building your app or
platform. Includes all these great features for a single monthly fee.
AI-Generated post creation, rewrite, and transcription.
JWT longer expiration time with an account connection email link.
New link shortener with analytics.
Resize images for each social network with added effects options.
Create images based on a template.
Staging server.
Advanced customizations for Business Plan linking page.
**Linkedin User Profile**. The /user endpoint now returns the LinkedIn
logged in username and the profileUrl with the company vanity URL. For
example the username "ayrshare" and the profileUrl
"[https://www.linkedin.com/company/ayrshare](https://www.linkedin.com/company/ayrshare)".
**Linkedin Comments**. You can now delete comments on LinkedIn.
**YouTube Comments**. The /comments endpoint now returns all the replies to
YouTube comments.
### June 2023
**Facebook Analytics**. New data points were added for video content posted
to Facebook and Facebook Reels. The /analytics endpoint has a richer set of
data available.
**New Instagram Capabilities.**
Instagram now allows 50 published posts in a 24-hour period, up from 25.
Now you can add a cover image to a Reels video by sending a URL.
Tag a Reel with Instagram users.
You can set the name of the audio when you post Instagram Reels.
### May 2023
**Instagram Stories**. Instagram just made available the publishing of
Instagram Stories - something we have all been waiting a long time for. You
can now post Instagram Stories via the Ayrshare API with an image and video.
Stories disappear after 24 hours.
**YouTube Analytics**. YouTube Live Broadcasts data was added the analytics.
When you have a live broadcast either current on-going or completed, you can
retrieve data such as the start and end times, number of current viewers,
and current status.
**Video Transcription**. The new /generate/transcription endpoint can
provide a transcription of a video file. This transcription can then be used
in the /generate/post to quickly create a social media summary of the video.
**Twitter Polls**. You can now create a Twitter poll by specifying the
answer choices and the duration. Also, analytics have been updated to return
poll data such as the results.
**Quote Tweet**. You can now quote another Tweet when you post a new Tweet
by including the Tweet id.
### April 2023
**TikTok Direct Publishing**. Ayrshare now offers direct publishing of
TikTok videos. There is no longer a requirement to approve the video in the
mobile app.
**TikTok Comments**. TikTok has been added as one of the social networks
where you can get, add, and delete comments.
**TiKTok Demographics**. Get demographic data for a user's TikTok account
including audience country and gender analytics.
**Facebook Reels**. Reels posting now supports videos up to 90 seconds.
**Hashtag Suggestions**. New endpoint to get recommended hashtags based on a
keyword. The suggestions are ranked by view count and sourced from TikTok.
**Validation**. Two new endpoints to help you validate your content. One
which will pre-validate a post before publishing, and the other will verify
your JSON formatting.
### March 2023
**AI Content Generation**. There are two new Generate endpoints. One allows
you to create text based on the text you send, and the other will rewrite
your post and give you several options to use. Powered by OpenAI ChatGPT
with GPT-4.
**Instagram Creator Accounts**. Ayrshare has added support for Instagram
Creator Accounts. You can get analytics for these accounts, but you cannot
post via the API.
**Comment Management**.
Get, Post, and Delete comments on posts not sent via Ayrshare.
We have also added a new Delete Comments endpoint for Facebook and
Twitter posts sent via Ayrshare.
The limit of how many comments you can get for a post has been increased
to 500.
**Instagram Stories**. The All Post History endpoint now returns Instagram
Stories.
**Retries**. There is a new Retry endpoint which allows you to retry
publishing a failed post once.
**Telegram**. The Telegram username is now available in the User endpoint.
### February 2023
**Ayrshare Flutter Package**. The initial release of the official Ayrshare
Flutter package was released on pub.dev. It's now easier to integrate
Ayrshare into your iOS and Android apps.
**Easier Testing**. Send random post text, comment text, and images for
testing on the social networks. Remember that even your test posts have to
adhere to the guidelines of the social networks.
**LinkedIn Major Update**:
Now you can get the history of posts for LinkedIn, even if those posts
were not sent via Ayrshare.
Linkedin post analytics were enhanced to include reactions such as
"insightful" or "love" on a post, the count of video views, and now
supports Personal Page posts.
Get LinkedIn post analytics for posts that were not sent through
Ayrshare.
Set your own thumbnail for an uploaded video.
Add alternative text (alt text) for images and videos.
Add title or media captions to LinkedIn images or videos.
Mention another LinkedIn organization handle by adding @handle in the
post text.
Post up to 9 images on a LinkedIn post.
**Idempotent Posts**. Idempotency allows you to safely retry posts without
accidentally performing the same operation twice.
### January 2023
**YouTube Playlists Analytics**. Get analytics on your playlists including
average view duration, minutes watched, views, playlist starts, and more.
**Ayrlink**. The Ayrlink link in bio now automatically adds a default image
and your connected social accounts when you create a new page for a user.
**TikTok Webhook**. When the user publishes the video in the TikTok mobile
app, a "scheduled" webhook will be sent with the subAction:
"tikTokPublished".
**Notion Integration**. The new Notion integration allows you to post to
your social accounts directly from a Notion table.
**Retweet Analytics**. Now you can get analytics on retweets that you sent.
**Ayrshare System Status**. In addition to following @ayrshare on Twitter,
you can get status updates via email.
### December 2022 🦇
**Post Analytics**. Post Analytics now automatically returns analytics on
all the social networks where the post was sent. Previously you needed to
specify the list of social networks in the `platforms` parameter.
**LinkedIn Analytics**. New analytics data points added to LinkedIn Social
Analytics endpoint: `uniqueImpressionsCount`, `clickCount`, `engagement`,
`likeCount`, `commentCount`, `shareCount`, `commentMentionsCount`,
`impressionCount`, `shareMentionsCount`.
**Facebook Video**. Facebook video uploads are much faster 🏃. You should
see a decrease in the API call time.
**Single Sign On Take Base64**. The generateJWT endpoint now accepts the
private.key as a Base64 string. This makes it easier to manage the keys
including the complexity of newline characters.
**LinkedIn Get All Posts History**. The /history get all posts endpoint now
retrieves LinkedIn posts and analytics, even for posts that didn't originate
from Ayrshare.
### November 2022 🦉
**Ayrlink**. Create a customized Ayrlink personal bio page using the leading
social media API. Share products, websites, content, and more on Instagram,
Twitter, and TikTok.
**Google Business Profile Analytics**. Get analytics data like views and
action counts for Google Business Profile. Formerly known as Google My
Business.
**Reddit Analytics**. Get analytics data including Karma, profile image, and
page URL.
**Facebook Analytics**. The count for the number of times your Facebook post
was shared is now available on the analytics endpoint. The Facebook
reactions count has been extended to include the past two years of data.
**Bitly**. Business and Enterprise plans now support Bitly for link
shortening.
**Account Linking**. Change the subHeader on the Social Account linkage page
for a user profile.
**NPM Package**. The Ayrshare social-post-api NPM package was updated with
new functions and examples.
**User Data**. The /user endpoint now returns the profile urls and
usernames.
### October 2022 🦅
**Pinterest**. Add alternative text, also known as alt text, to a Pinterest
image or video. Pinterest alt text is an accessibility feature used for
additional user info and screen readers.
**Google Business Profile**. Formerly known as Google My Business. You can
specify a product category for an image or video so the media is categorized
in the "Photos" section of the GMB console. For example, if an image has the
category "product", it will appear under the "Product" tab in Photos.
**YouTube Posting**. The YouTube endpoint now supports notifying your
subscribers and setting a publish at time.
**Dashboard Improvements**. The Ayrshare web dashboard was updated with an
updated design with some new icons and colors. You can also reset your API
or Profile Key in the Dashboard.
**Image Generation API Beta**. The Ayrshare social image generation API lets
you specify visual elements to create infinite variations of graphics that
you can use with the social media platforms. Powerful and easy to use.
### September 2022 🦆
**Facebook Reels**. You can now post videos as Facebook Reels. Reels are
short video that are 3-60 seconds long with a 9x16 aspect ratio.
**Short Link Preview Metadata.** Set the title, description, and image of
the link preview.
**Twitter History**. The platform history endpoint has been enhanced for
Twitter. The response now includes links to the published videos and photos.
**Twitter Comments**. Comments on a Tweet now returns the comments for all
the posts in the thread.
**TikTok Analytics**. Post analytics for TikTok now includes the video
thumbnail and music link.
**Pinterest History**. Get all the historical Pinterest posts, even those
not posted via Ayrshare.
**Brand Monitoring**. The brand endpoint has been enhanced to include
YouTube users and channels.
**Deleted Posts**. Now you can retrieve deleted posts via the history
endpoint.
**Instagram Reels**. Get analytics data on Instagram Reels including comment
count, like count, play count, and more.
**Alternative Emails for Ayrshare Alerts**. Choose different email addresses
to deliver alerts, such as unlinked accounts.
### August 2022 🐥
**Facebook Page Analytics**. The post analytics endpoint was enhanced with
Facebook Page like and comment counts and the original post URL.
**Facebook Animated GIFs**. Posting to Facebook now supports animated GIFs.
**YouTube Video Visibility**. Update a YouTube video visibility as unlisted,
public, or private.
**YouTube Analytics**. The YouTube channel analytics has been enhanced with
additional metrics including estimated minutes watched and thumbnail URL.
**YouTube History**. The platform history endpoint was enhanced to return
YouTube posts.
**YouTube Post History**. Get the history data of any YouTube post, even
those not sent via Ayrshare, by the platform social ID:
**YouTube Comments**: Now you can post top-level YouTube comments.
**LinkedIn Comments**. Get the comments for Linkedin posts sent via
Ayrshare.
### July 2022 🐧
**Webhook Tools in the Dashboard:** In the Ayrshare dashboard, you can see
all your registered webhooks, all the actions sent, and even replay the
webhook. Learn more about webhooks.
**Twitter Analytics Enhanced:** The Twitter analytics data set now includes
verified account, number of likes, number of lists added, and banner url.
**Pinterest Videos:** You can now post videos to Pinterest via video pins.
**Enhanced Facebook Social Analytics:** Get additional analytics and
demographics data on Facebook Pages.
**Video captions for LinkedIn:** You can add captions to videos uploaded to
Linkedin.
### June 2022 🐔
**Instagram Reels**: Post an Instagram Reel via the API. Reels are like
TikTok videos where you can share a 60-second video and do some cool
creative additions, such as stitch together and edit video clips, add music,
apply filters, write captions, insert interactive backgrounds, and add
stickers.
**More Data On Posts**: The Analytics, Comments, and History endpoints have
been enhanced to return data on posts that were not sent via Ayrshare. These
new enhancements are for Facebook, Instagram, and Twitter.
**Approval Workflows**: You may need an approval workflow to separate the
content creator and the content approver. This is common practice to avoid
mistakes, maintain consistency, and adhere to regulatory or compliance
requirements in some industries. The Ayrshare API now natively supports an
approval state for each post.
**Twitter Threads Images**: Twitter Threads now accepts multiple images per
Tweet in the Thread. You can also specify that specific Tweets in the Thread
will not have an image.
**Instagram Location Tag**: Add an Instagram locations tag with the Facebook
Page Name. You can also still use a Facebook Page ID in place of the Page
Name.
**Reactivate User Profiles**: Business and Enterprise Plan admins can
reactivate suspended user profiles in the dashboard.
### May 2022 🐵
**Facebook @mentions**: Now you can @mention another page with the page name
directly. Previously the endpoint needed the page ID, and now you can use
the page name, such as @Ayrshare.
**Improved Brand Data**: The brand endpoint now supports Facebook. Send a
Facebook page name to look up a user's or company's social media public
information, such as followers, profiles image, and websites. These users
and companies do not need to be a linked Ayrshare user.
**Help Docs**: Use your own help docs as the link on the Social Accounts
page on the Business Plan. Your users can now link to your own support
pages.
**Twitter Comments and Replies**: Now get and add Twitter comments and
replies on a post.
**YouTube Comments**: Get comments on a YouTube video.
**RSS Feeds**: The feed endpoint was updated with new abilities to update
the feed and get all feeds.
**Delete User Profile Enhanced**: Now you can delete a user profile even if
you only have the title.
**New /post Endpoints**: The /post endpoints were enhanced to allow GET to
retrieve an individual post and the ability to update the schedule date of a
post.
**Alt Text**: Add alt text to Twitter images and Facebook images and videos.
Alt text is an accessibility feature used for additional user info and
screen readers.
**Twitter Thread Analytics**: Analytics now supports Twitter Threads. If
your Twitter post ID was sent as a thread, you will see an array of
analytics data for all of the posts in the thread.
### April 2022 🐸
**Web Dashboard Improved**: The Ayrshare web dashboard has been upgraded and
now is faster, more responsive, and with several UI improvements. And you
can now post Twitter Threads, a.k.a TweetStorms, via the dashboard.
**New Analytics Data**: New analytics data points available. Access
demographics data for Instagram and Facebook accounts. Access country, city,
age distribution, and language reach. In addition, Instagram analytics now
provides the total like and comment count.
**Instagram Comments**: Instagram comments now return the commenter's
username and number of likes.
**GZIP Support**: API responses now support optional gzip compression.
**Tweet History**: Get all Tweets in the history endpoint, even those not
sent via Ayrshare.
**Test Unique Content**: As part of your testing, always use unique content
when sending to a social network. Now the randomPost parameter of the /post
endpoint will generate a random quote.
### March 2022 🐷
Get **LinkedIn Company Page Analytics** such as followers, views, and
clicks.
Get **TikTok Post Analytics** such as views, likes, and comments on your
TikTok videos.
**Post Instagram carousels** with images. You can now post up to 10 images
in an Instagram carousel.
**Use your own link shortener**, such as Bit.ly. This allows you to use a
custom domain in place of the Ayrshare short URL when shortening the link.
**Send videos titles** when posting videos to Facebook Pages and Groups.
The **history** endpoint for Instagram and TikTok was enhanced. Now the
/history endpoint returns the video thumbnail image for Instagram and the
username for TikTok.
A new **endpoint to unlink** a user profile's social accounts.
There is an **upcoming API change** to the /history endpoint. By default, it
will return the most recent 20 records. You can specify the "count"
parameter to retrieve up to 500 records.
### February 2022 🐮
Enhancements to the **Google My Business** capabilities now allow for
"What's New" posts that can include Call to Actions, such as Learn More
buttons, images, and text.
**Automatically create a Twitter Thread** aka Tweetstorm. Send your text of
any length and Ayrshare will break it up into appropriately sized Tweets
with numbering.
**Get your whole development team using Ayrshare** with their own logins.
You can now add team members in the Ayrshare dashboard. Just go to User
Profile and when creating a new profile check the *create as team member*
box.
If Twitter has approved your account for **longer videos**, you can now post
videos up to 10 minutes in length.
### January 2022 🦁
**TikTok profile analytics** summaries are available.See average video
duration plus like, views, and share totals across all TikTok shares.
Get all **TikTok post history and analytics**. Even posts and shares created
outside of Ayrshare.
**Pinterest post analytics** now available. See impressions, saves, pin
clicks, and other useful data points.
**Post YouTube Shorts** via the API. Shorts are videos up to 60 seconds long
and have new discovery placement within the YouTube apps.
Post an image and add flair to **Reddit**.
There is a new release of the **Ayrshare mobile app** for both iOS and
Android. With the new apps, you can see the full json responses for errors
and tap successful posts to open the live posts.
### November / December 2021 🐯
Add a bit of spice to your posts with **rich text**. For example: "I want
this one **bold**, x₂ and *italic*." Check out which HTML elements are
supported in the docs.
**Post to any Pinterest board** connected with a user. Whether the user has
1 or 200 boards you can now specify the specific board to post to. Learn
more.
**Direct TikTok Posting** for Premium and Business Plan users. Now post
videos directly to the TikTok mobile app. See how the full flow works.
We have updated the Node.js NPM and Python **packages**.
The /user endpoint was updated to now retrieve the **count of Instagram
posts** done over the past 24-hour rolling period.
The /profile endpoint was updated to allow filtering to **find the exact
user's profile** you need. Filter by user profile title or refId.
### October 2021 🐨
**Pinterest** is now available as a destination platform. Pinterest has over
400 million monthly active users, and 60% are women. 80% of Pinners have
discovered a new brand on Pinterest so it's a great platform even if you are
just starting out. Read more.
Now Business plan members can get **all past Instagram and Facebook posts**
plus the Analytic on each. Regardless if you created these posts via
Ayrshare or not. Learn more in the docs.
Sometimes you have an image that does not meet the strict image requirements
for Instagram. Now Ayrshare will **automatically resize your images for**
Instagram if you want via the /post endpoint. Learn more in the docs.
We have upgraded to **generateJWT** endpoint with a logout option and the
title of the user profile returned. Learn more in the docs.
**Our docs were updated**. Check out the new font and style. If you are
wondering, it is powered by GitBook.
The **post verification system** will now check URLs in post to make sure
they comply with the social networks' guidelines. This is a great addition
to the existing industry leading verification checks that protect your
user's social accounts. Learn more in the docs.
Posting to **YouTube** now has support for tags and the "made for kids" self
declaration. Learn more in the docs.
### September 2021 🐻❄️
**Facebook Groups** now available as a destination platform. Over 1.4
Billion people use Facebook Groups each month. Your users can now link a
Facebook Group where they are the owner or admin. Learn more in the docs.
**Automatically resize images for Instagram** photo dimensions. Just upload
a photo to Ayrshare and you'll get a resized image that works on Instagram.
Learn more in the docs.
**Google My Business** tooltip in the Developer Dashboard now displays the
linked account name.
See a **visual graph of your API usage** in the Developer Dashboard.
One-click copy button for the request and response code in the Developer
Dashboard for the post history.
### August 2021 🐼
Get more detailed **Analytics** data. New data sets are now available at the
social network level, such as a Facebook Page or Instagram Account. Get the
number of followers, username, and more. Learn more in the docs.
The **Developer Dashboard** now lets you select the **timezone** of the
scheduled time for a scheduled post.
**Automated RSS Feed posting**, including Substack, now supports posting to
Instagram. Learn more in the docs.
The **RSS Feed endpoint** now allows you to automatically add hashtags and
post the image from your article. Learn more in the docs.
**Media uploading** now supports multipart form data. Learn more in the
docs.
**Facebook video posts** now support the ability to set a thumbnail image.
Learn more in the docs.
**Node.js NPM package** updated to support analytics and user profile
creation.
### July 2021 🐻
**Google My Business** is now a supported Ayrshare destination. Post images,
videos, events, offers, and call-to-actions. Read more in our blog post.
The **Developer Dashboard** on ayrshare.com has been updated to show the
full JSON for every request and response. The Dashboard now has the link to
every post on the social networks, allows you to view all your posts across
all profiles at the same time, and has a new filter by the post status.
The **History** endpoint now lets you filter by the status of the post. Get
only success, error, or pending posts. Learn more in the docs.
We have improved the speed and responsiveness of the **profile linkage
page**.
We have improved the **verification checks** for scheduled posts so you can
see errors when you create the posts. Learn more in the docs.
We have improved the **similarity checks** and some of the other
verification checks to better protect your accounts. Learn more in the docs.
The **NPM package** was updated with support for Analytics, Comments, Auto
Schedule and Google My Business. Learn more in the docs.
### June 2021 🐶
**Webhooks** are now available for Enterprise plan clients. Get
notifications when scheduled posts are published, users link or unlink
social network accounts, and new RSS articles are published. Learn more in
the docs.
**Analytics** enhanced with Instagram and Facebook insights. For Facebook,
get counts of unique impressions, engaged users, and unique clicks. For
Instagram, get counts of engagements, impressions, reach, and saved posts.
Learn more in the docs.
A new **History** endpoint call to get the history for a specific post ID.
Learn more in the docs.
We have improved the account **monitoring** for your Twitter accounts. Get
notifications and API call responses that explain that your account was
locked or suspended by Twitter.
New **Comments** API endpoint. Retrieve comments and create new comments for
Facebook and Instagram posts. Learn more in the docs.
Ayrshare Business clients can now manage the following for their users'
**profiles**:
Customize the social account linkage page title
The Done button wording and link on the social linkage page
Set which social networks are available on the social linkage page
When creating a new profile, you receive back the **display name** or handle
the user has set at the social network.
When posting, you receive back the **public URL** to the post on the social
network.
Updated the Ayrshare Social Media API **Bubble** plugin to support
scheduling future posts and sending videos to YouTube. Learn more in the
tutorial article.
### May 2021 🐱
**Promote your Tweet** as an ad to increase its reach and help it find a
bigger audience. Ayrshare now allows you to easily promote a Tweet with a
single API call. You can promote a Tweet when you create it or any time
after. To add Promoted Tweets to your account, log in to the Ayrshare
dashboard and enable it on the Social Accounts page. Learn more in the docs.
**Upload videos** to Instagram and Telegram.
See the **Status Page** for a real-time check on the status of the Ayrshare
services. Access it at status.ayrshare.com.
Business plan users can generate the **single-sign-on URL** via the API.
Learn more in the docs.
In the developer dashboard, you can set your **Tax ID** under account info.
New **Airtable** integration guide. Learn more in the docs.
Updated code examples in Node.js, PHP, C#, and Python.
### April 2021 🐭
**TikTok** integration is now available to Premium Plan users as early
access, meaning it is still under active development. Posting to TikTok
requires the Ayrshare iOS mobile app. Learn more in the docs.
**CSV** bulk upload of posts is now available. Learn more in the docs.
Post images to **Telegram**.
Add user and locations tags to **Instagram** posts. Learn more in the docs.
New API endpoint to **auto-schedule** your posts. Set up an auto-post
schedule by providing times to send. Post will automatically be sent at the
next available time. If no more times are available today, the first
available time tomorrow will be used, and so on. Learn more in the docs.
Ayrshare paid users can now access **billing** information directly from the
web dashboard.
### March 2021 🐹
You can now post to **Instagram** via the Ayrshare API. After a detailed
review process, Ayrshare has been approved by Instagram for direct posting.
Learn more in our article.
**Auto repost** is now available via the Post endpoint. Automatically repost
n times every x days. Learn more in the docs.
Support for **Facebook carousel**. Learn more in our tutorial article.
Get **Analytics** for your posts and videos on Twitter, Linkedin, and
YouTube. Learn more in the docs.
### February 2021 🐰
You can now post videos to **YouTube** via the Ayrshare API. Learn more in
the article.
New **verification system** to make sure your social network accounts stay
in good standing. Learn more in the docs.
Updated the "social-post-api" Node.js **NPM** and Python **PyPI** packages
to support YouTube video posting. You can find it on NPM and PyPi.
### January 2021 🦊
Released the Ayrshare Social Media API **Bubble** plugin. Post to your
social media accounts with the Bubble no-code platform.
Connect and post to **Reddit** and **Telegram.**
# Latest Updates
Source: https://www.ayrshare.com/docs/whatsnew/latest
Ayrshare changelog with the latest social media API updates, bug fixes, platform features, and improvements across Facebook, Instagram, TikTok, and X.
[Follow us on X](https://twitter.com/intent/user?screen_name=ayrshare), listen to our [Social Media API Podcast](https://ayrshare.podbean.com/), or sign up for our [Newsletter](https://dashboard.mailerlite.com/forms/42719/54642298519029076/share) for the latest updates.
## August 2026
August 14 - Custom CSS Reaches Inside the Connect Accounts Cards. Five more class names are now available to your Max Pack custom CSS on the white-labeled connect accounts page: social-account-avatar on a connected account's profile picture, social-account-icon on the square holding a network's logo, social-account-name on the network's name, plus social-linking-page-column and social-linking-header on the two containers holding the page. The column is separate from main-content on purpose, so you can run the cards wider without narrowing your page background, and flattening the header with display: contents lets you reorder the logo, cards, Close button and instruction block with order. The "Connected" and "Messaging" badges also read two custom properties, --ayr-pill-bg and --ayr-pill-fg, which you can set once on social-account-card; warning badges such as "Relink required" keep their own colors so an account that has stopped working still looks like one. If your stylesheet reached any of these by counting elements or by selecting a Mui class name, rewrite those rules against the names above — they are the ones that will keep working. See Customize CSS for the full list and worked examples.
August 14 - More Breathing Room Above Your Linking Page. The white-labeled connect accounts page starts its content further down the page, so your logo and heading no longer sit tight against the top of the browser window. Nothing else moves, and a stylesheet that already sets padding-top on main-content keeps its own value.
August 12 - AI Disclosures Survive Image Format Conversion. When Ayrshare converts a WebP, HEIC, HEIF, or AVIF image to JPEG for a network that doesn't accept the source format, the image's AI disclosure is now carried across instead of being discarded. Ayrshare writes a small new XMP packet containing Iptc4xmpExt:DigitalSourceType, the IPTC AI-disclosure property, and synthesizes the equivalent value when a C2PA manifest asserts an AI origin the XMP doesn't record. Facebook and Instagram render their own AI label from that property alone, with no platform AI flag set. Nothing else travels: the packet is built from scratch rather than copied, so no EXIF, no GPS, and no creator, copyright, keyword or location fields from your original image reach the network. Color rendering is preserved either way — a HEIC or HEIF image keeps its ICC color profile, and a WebP or AVIF image is converted to standard sRGB so its colors are correct even on a network that discards embedded profiles. The C2PA cryptographic signature cannot survive a re-encode and is not preserved — the disclosure survives, the signature does not. JPEG and PNG images still pass through untouched, videos are unaffected, and media uploads continue to store your bytes verbatim. Note that Instagram's autoResize option resizes through a separate step that carries no metadata, so leave it off if the disclosure needs to reach Instagram. See Image Metadata and Content Credentials for the full policy and the per-network results.
August 12 - LinkedIn Company Page Selection No Longer Times Out. If you administer a very large number of LinkedIn company pages, connecting LinkedIn could time out before the page selection list appeared, leaving nothing to choose from — including after the August 10 discovery improvement below. Building your page list is now many times faster and finishes well inside the request limit. Separately, some pages could be left out of the list depending on how LinkedIn returned them; those pages now appear.
August 11 - Custom CSS Control Over the Connect Accounts Card Layout. The white-labeled connect accounts page now carries two more class names your Max Pack custom CSS can select: social-accounts-grid on the grid holding the network cards, and social-account-card-wrapper on the cell holding each card. Between them they control the spacing between cards and how many cards fit per row, neither of which had a selector before. If your stylesheet reached the card area by counting elements down from main-content, such as .main-content > div > div > div, those rules match a different element since the dashboard was rebuilt and can resize every card at once; rewrite them against the two names above. Your rules still need !important to override the page's generated styles. See Change the Card Layout for worked examples.
August 11 - Custom CSS Linking Pages Stay Light. A social linking page with your own CSS file now stays on the light color scheme, and your users are no longer shown the light/dark switch on it. Stylesheets are written against the light page, so a user who switched to dark kept your colors while the text colors around them changed, which could leave network names hard to read on your cards. Your stylesheet is now the only thing deciding how the page looks. Linking pages without a CSS file are unchanged and keep the switch.
August 11 - Streamlined Instagram Linking. Clicking Instagram on the linking page previously opened a dialog warning that only Instagram Business or Creator accounts are supported before the login began. Instagram's own login now offers to switch a personal account to a professional account during authorization, so that extra step is gone — clicking Instagram goes straight to the login flow: Instagram's own login or, if you have disabled Instagram Login, the Facebook login. If you have configured a custom Instagram modal for your linking page, your custom instructions still appear exactly as before.
August 10 - Custom CSS Class Hooks Restored on the Connect Accounts Page. The white-labeled connect accounts page again carries the stable class names your Max Pack custom CSS selects. When the page was rebuilt these class names were dropped, so an existing stylesheet still loaded but silently matched nothing: a rule that hid the page heading, restyled the Close button, or recolored the instruction text simply stopped taking effect, with no error anywhere. Restored on the page: main-content, company-logo, heading-social-accounts, additional-info, additional-info\_\_body, additional-info-text, troubleshooting-guide and close-button. Restored on each network card: connected-card and click-to-link. Also new: social-account-card on every card, unlinked-card for the not-yet-connected state, and a data-platform attribute carrying the network key, so an unconnected card can be restyled as a button, which was previously impossible because a connected and an unconnected card were indistinguishable in CSS. Your rules need !important to override the page's generated styles. See CSS Class Hooks for the full list and a worked example.
Check your stylesheet. Rules built on these class names work again with no change from you. Rules built on the page's own generated class names (anything you copied from browser developer tools, such as names beginning with chakra-) cannot be restored and need rewriting against the documented selectors. See Updating an Older Stylesheet.
One older class name is not coming back.linked-tag is deliberately not part of the contract: a connected card can now show "Relink required" or "Identity check" too, so a rule hiding it would hide a warning your user needs to act on. Style connected-card instead. See Updating an Older Stylesheet.
August 10 - Improved LinkedIn Company Page Discovery. If you administer a large number of LinkedIn company pages, some of them could be missing when you connected or refreshed LinkedIn — those pages didn't appear for selection and couldn't be posted to. Company page discovery now reads past the point where it previously stopped short, so pages missed for this reason are available to select and publish to.
August 7 - Dashboard 3.0. The Ayrshare Dashboard has been rebuilt from the ground up with a modern design system, refreshed navigation, and a faster, cleaner workflow on every page.
Dark mode & new design — dark mode by default with a one-click light/dark theme toggle in the sidebar, plus new typography, cards, and layouts across every page for better readability and information density.
Billing, now in the dashboard — a new Billing section (replacing the old Account page) lets you manage your subscription without leaving the dashboard: view your current plan, next billing date, and payment method; change plans, view invoices, and update billing info; and enable or manage add-ons (Max Pack, Messaging, and Facebook Boost Ads) directly.
Publish a Post — network toggles with a live selection count, Select all / Deselect all, and an "Only" shortcut to post to a single network; View API Code (formerly View JSON) shows the exact API request for your composed post; and a cleaner Additional Options panel that surfaces platform-specific settings (like Instagram Post Type) contextually.
Post History — search your recent posts alongside the existing status filters (Success, Scheduled, Paused, Awaiting Approval, Error), media thumbnails on each post, and platform icons, status chips, copyable Post IDs, and a collapsible API Request & Response viewer on every card.
User Profiles — redesigned profile cards with avatars and structured fields (Created, RefId, Accounts, Messaging), new role badges (Owner, Team Member, and Active profile), and an inline Messaging toggle on each card.
Webhooks — a new Events tab to inspect webhook event logs alongside your registered webhooks.
August 6 - TikTok Video Visibility Fix. The tikTokOptions.visibility option is now honored for video posts. Previously it only took effect on image posts — a video sent with visibility: "private", "followers", or "friends" published as Public with no error or warning. Videos now publish with the requested visibility, and the visibility parameter docs have been updated to reflect video support.
August 6 - Instagram AI Content Label. Instagram posts can now carry Instagram's AI info label by setting isAIGenerated to true in instagramOptions. The self-disclosure applies to single images, single videos, Reels, Stories, and carousels — for a carousel the label applies to the whole carousel rather than individual items. Accepted values are true, "true", false, and "false"; any other value ("yes" or 1, for example) still publishes the post normally but without the label and returns a non-fatal warnings entry (code: 497, feature: "isAIGenerated") listing the accepted values. Omitting the parameter is unchanged and publishes with no label, and the label cannot be changed after a post publishes. The parameter matches the existing tikTokOptions.isAIGenerated, so the same flag name works on both networks. See Instagram AI Content Label.
August 4 - X "Made with AI" Label. X posts can now disclose AI-generated media with twitterOptions.isAIGenerated, which applies X's native "Made with AI" label. See X posting options.
August 4 - LinkedIn Comment Replies on Organic Company-Page Posts. Replying to a LinkedIn comment by [Social Comment ID](/docs/apis/comments/overview#comments-with-social-comment-id) now works on organic company-page posts, which previously failed with code: 215. In this mode (searchPlatformId: true), pass the full commentUrn returned by [get-comments](/docs/apis/comments/get-comments) rather than the bare commentId — for example urn:li:comment:(urn:li:activity:\,\). See the new commentUrn parameter on [Reply to a Comment](/docs/apis/comments/reply-to-comment).
## July 2026
July 31 - WhatsApp Messages in Private Beta. The Messaging API now supports WhatsApp in private beta. Approved accounts can link a WhatsApp Business Account through Meta's embedded signup flow, send free-form messages during Meta's 24-hour customer service window, receive incoming messages and media, and retrieve stored WhatsApp conversations. Email [lotty@ayrshare.com](mailto:lotty@ayrshare.com) to request access.
July 31 - Instagram Comment & Mention Webhooks No Longer Require Messaging. Instagram comments and mentions webhooks are now fully independent of the Messaging add-on. Registering a webhook with action: "comments" or action: "mentions" subscribes the required Meta fields automatically using your existing linked accounts — no Messaging add-on and no relinking required (comment permissions are already part of the default grant). This works for every Instagram account type, including accounts linked through a Facebook Page, and disabling Messaging no longer disrupts an active comments or mentions webhook. This change applies to the Instagram scope; Facebook comment and mention events are not yet included. See the Webhooks overview to register a webhook.
July 31 - Batch Analytics Attribution Fix. In a multi-post post analytics request, a failing entry could cause subsequent results in the same batch to be recorded under the wrong post ID. Results are now always attributed to the correct post, even when some entries in the batch fail.
July 31 - Instagram Analytics Post-ID Validation. Invalid Instagram post IDs sent to post analytics are now rejected locally before any call is made to Meta, so malformed IDs no longer cost a Meta Graph API call — matching the protection already in place for Facebook, Threads, and X/Twitter. Numeric post IDs are also handled gracefully: an all-digit numeric id validates normally, and values that can't form a valid ID return a clean code: 186 error instead of an unhandled failure. Valid string IDs behave exactly as before.
July 31 - n8n Starter Workflow Refresh. The downloadable n8n MCP starter workflow has been updated: the suggested first prompt now targets LinkedIn and Facebook only (the previous prompt included Instagram, which requires media and caused first-run validation to fail), and the workflow's chat model is now claude-sonnet-5 with version-agnostic setup instructions.
July 29 - Instagram Comment Automations Now Use Private Replies. Comment-triggered automations (comment\_keyword) now deliver their DM through Instagram private replies, anchored to the comment's own 7-day window. This removes the requirement for a prior conversation, so an automation can now reach a commenter you have never messaged before — the rejection that previously blocked cold commenters. The comment's own 7-day window still applies: a reply to a comment older than that fails with 491. Note that delivery is still ultimately dictated by the recipient's Instagram Message requests setting: a DM can be accepted by Instagram (activity status: "sent") and then silently dropped, with no signal on any API surface. Accordingly, sent means Instagram accepted the message, never that the recipient received it. New failure reasons surface on actionResults\[].errorDetails with dedicated error codes 490–495. See the new Automation DM Sent but Not Delivered troubleshooting guide.
July 23 - Post-Quantum Ready Encryption (PQC). The Ayrshare API now supports post-quantum cryptography at the TLS layer. We've enabled the X25519MLKEM768 hybrid key exchange on our global SSL policy, adding a quantum-safe (ML-KEM) algorithm alongside classical ECDHE in the TLS 1.3 handshake. This protects your API traffic against "harvest now, decrypt later" attacks — where an adversary records encrypted traffic today to decrypt once quantum computers mature. The change is fully backward compatible: because it's a hybrid negotiation, a connection only upgrades to PQC when the client requests it, and every other client continues to connect normally over standard ECDHE. And since 74% of our API traffic is already on TLS 1.3, most integrations get post-quantum protection right now with no code changes — as long as your HTTP/TLS library supports the X25519MLKEM768 group (OpenSSL 3.5+ and other modern TLS stacks already do), it's negotiated automatically.
July 15 - Instagram Reels Aspect-Ratio Validation Fix. Tall and narrow Instagram Reels are no longer falsely rejected before reaching Meta. Ayrshare's pre-flight video check was applying the Instagram image aspect rules (4:5 to 1.91:1, plus a 9:16 portrait exception) to Reels, so a valid portrait Reel (for example 886 x 1920, a 0.46:1 width-to-height ratio) was blocked locally with code: 182 even though Instagram would accept it. Reel videos are now validated against the documented Reel range of 0.01:1 to 10:1 (9:16 still recommended to avoid cropping), matching Meta's own specification and the Instagram media guidelines. The code: 182 message for aspect-ratio failures has also been corrected — it previously read "Video does not meet duration requirement." No API changes are required.
July 14 - Partial Success on Multiplatform Comments & Analytics Reads. A multiplatform get-comments or post analytics read (one Ayrshare Post ID spanning several platforms) no longer collapses the whole response to an error when a single platform's leg fails. When at least one leg succeeds and at least one fails, the response returns HTTP 200 with status: "partial", preserving healthy platform data and listing each failed leg in top-level errors\[]. All-success responses are unchanged. All-fail responses retain status: "error" and map the representative top-level error code to its configured HTTP status; code 485 maps to HTTP 404. Code 485 identifies expired or unavailable Instagram/Facebook Story comments and Instagram Story analytics when comments or insights cannot be retrieved; Facebook Story analytics remain unavailable and are not included. Clients should inspect errors\[] and match the numeric code, not exact message text.
July 8 - Faster API Response Times. We've shipped a round of backend performance work that meaningfully cuts latency across some of our most popular endpoints. Average and 95th-percentile (p95) response times are both down substantially, with the largest gains showing up when under heavy load. The biggest wins are on profiles and analytics. No API changes are required; every request is now faster automatically.
| Endpoint | Faster Avg | Faster p95 |
| ---------------- | ---------- | ---------- |
| `GET /profiles` | **-71.6%** | **-88.7%** |
| `GET /analytics` | **-59.5%** | **-75.0%** |
| `GET /user` | **-51.0%** | **-48.6%** |
| `GET /post` | **-47.6%** | **-63.1%** |
| `GET /messages` | **-40.5%** | **-59.4%** |
July 7 - Per-Session Instagram Link Method on generateJWT. The generateJWT endpoint now accepts an optional instagramLinkMethod body parameter that overrides your account-wide Instagram Login setting for a single linking session. Send "instagram" to start direct Instagram Login (no Facebook Page required) or "facebook" to link via a connected Facebook Page when the user clicks the Instagram button on the social linking page. The override applies only to the linking page opened from the returned JWT URL — it persists across the authorization redirect but never changes your account-wide setting, and omitting the parameter keeps the existing behavior. Invalid values return a 400 listing the valid options. See the new Instagram Link Method section for details, including the feature differences between the two flows.
July 3 - Clearer Error When Meta Can't Fetch Your Media. Media-fetch / crawler-block failures (Meta subcode 2207052) that previously returned the generic, retryable code: 440 now return a dedicated, non-retryable code: 479 (HTTP 400) — returned when Meta cannot fetch the media even after Ayrshare re-hosts it on its own CDN. The message names the likely cause (the host blocking Meta's crawlers facebookexternalhit / Facebot via robots.txt or CDN/WAF rules) and the fix (allow the crawlers, or serve the media from a Meta-reachable host). Genuinely transient ingestion failures (subcodes 2207032 / 2207003) keep code: 440 with its retry guidance. See Meta Media Crawler Blocked and the error codes reference.
## June 2026
June 24 - n8n Integration. Connect n8n to the Ayrshare MCP Server using n8n's built-in MCP Client Tool node, with no custom code and no community node to install. See the new n8n integration page for an overview, and the full n8n guide for setup, three worked examples, multi-tenant profiles, X BYO, and a downloadable starter workflow (Chat Trigger to AI Agent to the Ayrshare MCP node). See also Connect & Setup and the Tool Catalog.
June 17 - Facebook Analytics: Meta Retired Reach & 3-Second Video Metrics. Meta removed the unique-impression and 3-second video-view Insights metrics across all Graph API versions (effective June 15, 2026). Facebook post analytics no longer return impressionsUnique, impressionsFanUnique, impressionsOrganicUnique, impressionsPaidUnique, or videoViewsUnique, and social analytics no longer return the pagePostsImpressions\* family (including pagePostsServedImpressionsOrganicUnique). The still-supported fields (reactionsByType, videoViews, mediaView, pagePostEngagements, pageVideoViews) are unaffected. Use mediaView / pageMediaView for reach; a Total Unique Media Views successor is planned. Reference: Meta Graph API v25 changelog.
June 15 - Facebook Account Restriction Error Code 476. Facebook posts that fail because Meta has placed a restriction on the account (Meta subcodes 2424009 and 1404078, or Meta's restriction wording when no subcode is present) now return a dedicated, non-retryable code: 476 (HTTP 400) instead of the generic retryable code: 108. The account stays linked — resolve the restriction via Meta's Account Status page (Facebook → profile picture → Help → Account Status), which surfaces the specific reason and an appeal flow that the API can't return. See Facebook Account Restriction for details.
June 10 - LinkedIn Personal Profile Analytics. Personal (member) LinkedIn profiles now return an expanded analytics matrix. Post analytics include impressionCount, uniqueImpressionsCount (members reached), likeCount, commentCount, shareCount, engagement, reactions, and — for video posts — videoViews, videoViewers, and videoWatchTimeMs. Social analytics add lifetime followersCount, daily followersDaily growth, and aggregate post metrics. Aggregate reshare/reaction/comment counts are best-effort and may differ slightly from the LinkedIn UI. Existing linked accounts must re-link their LinkedIn profile on the Social Accounts page to grant the new analytics scopes — until then, analytics return code: 475 ("re-link your LinkedIn profile to enable analytics"). Posting is unaffected.
June 10 - TikTok First Comments Now Event-Driven. A first comment on a TikTok post is no longer attempted on a fixed timed wait. Because TikTok processes videos asynchronously, the /post response now returns the TikTok first comment with status: "pending", and the comment is posted automatically once TikTok finishes processing and the tikTokPublished webhook resolves the real video id. The video visibility must be public, otherwise a clear comment error is returned. Separately, get-comments on a still-processing TikTok post now returns code: 288 instead of a generic failure.
June 8 - Webhook Signing-Secret Rotation. You can now safely rotate your webhook signing secret from the [Webhooks dashboard](https://app.ayrshare.com/webhooks) in 2 clicks, or via the new [POST /hook/webhook/secret](/docs/apis/webhooks/rotate-signing-secret) endpoint with a secret body parameter. After a rotation, deliveries are signed with both your previous and new secret for a 24-hour grace window via the new X-Authorization-Content-SHA256-V2 header (v1=\,v1=\, current first), so you can update your receiver with zero dropped or rejected deliveries. The existing X-Authorization-Content-SHA256 header is unchanged. The signing secret is profile-wide (one per User Profile, signing every action on that profile). See [Rotate Signing Secret](/docs/apis/webhooks/rotate-signing-secret) for the safe rotation procedure and a receiver verification example.
June 8 - YouTube Thumbnail Failures Now Surfaced. When a YouTube video posts but its custom thumbnail fails to apply, the YouTube result now keeps status: "success" (the video stays live) and adds a warnings array (feature: "thumbnail", code: 307) describing the failure — previously the failure was buried in the thumbNail sub-object, which is still retained for backward compatibility. The misleading 403 guidance has been corrected to lead with channel **phone verification** at [https://www.youtube.com/verify](https://www.youtube.com/verify) (an unverified channel is the dominant cause), with OAuth re-link as a secondary step. New **pre-publish validation** also catches thumbnails that are not PNG/JPG, are over 2MB, or are unreachable before upload and skips them, so the video still posts with the reason reported in `warnings` (a thumbnail problem never fails the post). See the [YouTube Post API](/docs/apis/post/social-networks/youtube#youtube-thumbnails) and the new [YouTube Thumbnail Not Applied (Unverified Channel)](/docs/help-center/technical-support/youtube_thumbnail_unverified_channel) troubleshooting guide.
June 8 - X BYOK Analytics Now Returns Code 416 on Depleted Credits. When an X/Twitter BYOK account's enrolled X Developer account is out of API credits, the analytics and user-lookup paths now return code: 416 (HTTP 402, X CreditsDepleted) with the enrolled account id in the detail — previously these were masked as code: 294 (HTTP 400, "Unable to get X User"). The fix is to top up credits in the X Developer Portal. This aligns the analytics/lookup surface with the publish path (which already returns 416). If your integration branches on 294 from analytics to detect a bad handle, add handling for 416.
June 4 - MCP Server & Claude Code plugin. AI agents can now drive the Ayrshare API through the new MCP Server ([https://api.ayrshare.com/mcp](https://api.ayrshare.com/mcp)), including the Claude Code plugin. See Connect & Setup and the Tool Catalog. The existing docs-search MCP is now Documentation MCP.
## May 2026
May 22 - Bulk Post Profile-Key Routing Fix.POST /post/bulk now honors the Profile-Key header, so CSV rows publish to the resolved User Profile instead of the Primary Profile. Previously bulk uploads sent with a Profile-Key were silently routed to the Primary Profile's social accounts. See Bulk Post.
May 21 - TikTok DELETE /comments scope clarified. Updated the [Delete Comments](/docs/apis/comments/delete-comments) and [Comments Overview](/docs/apis/comments/overview) pages to document that DELETE /comments on TikTok only succeeds for comments authored by the authenticated TikTok account itself (your own replies). Attempting to delete a third-party comment returns Ayrshare code: 328. Customers who need to moderate third-party comments on their own TikTok videos should contact support. No API behavior change; documentation only.
May 21 - Hide TikTok Comments.DELETE /comments now supports hiding a TikTok comment from public viewers via hide=true together with videoId. The success response returns action: "hide" and echoes the comment text; sending hide=true without videoId is rejected with a 400. Hidden comments remain visible to the video owner in TikTok Studio.
May 20 - Node SDK v1.3.0 — X/Twitter BYO support. The official Node SDK now exposes setTwitterByo(apiKey, apiSecret) and clearTwitterByo() for X/Twitter Bring-Your-Own-Keys. Once set, every SDK request includes the required X-Twitter-OAuth1-Api-Key and X-Twitter-OAuth1-Api-Secret headers — required for X/Twitter operations now that Ayrshare's BYO requirement is enforced (as of March 31, 2026). Install via npm install social-media-api\@1.3.0; release notes on npm and GitHub.
May 20 - Messaging Metered Pricing. Business Messaging is now billed via Stripe metered pricing at $0.09 per active conversation on Launch and Business plans (Premium remains a flat $49/month add-on), with up to 1,000 active conversations per billing cycle. See Messaging pricing.
May 20 - Instagram Analytics No Longer Unlinks on Permission Errors. When Instagram analytics hits a missing-permission error (Meta errCode 10), the account is no longer automatically unlinked. Previously a scope/permission issue was treated like a revoked token and silently disconnected the account even though posting still worked. Ayrshare now keeps the account linked and surfaces a permission-scope error instead.
May 19 - Per-profile hideLogo. New hideLogo boolean on [Create Profile](/docs/apis/profiles/create-profile) and [Update Profile](/docs/apis/profiles/update-profile) suppresses the account-wide logo on an individual User Profile's social linking page. Useful for white-labeling individual partner profiles.
May 19 - Facebook Boost Ad Set Budget Sharing. The [Boost endpoint](/docs/apis/ads/facebook/boost-post) now accepts a new optional adSetBudgetSharingEnabled boolean (default false). Meta now requires this wire field on every campaign created without a campaign-level budget, and Ayrshare sends it on every request — defaulting to false preserves prior behavior with no caller changes needed. Set it to true to enable Meta's cross-ad-set optimization, which can shift up to \~20% of an ad set's budget to other ad sets in the same campaign for better overall performance.
May 19 - Reddit Banned-Subreddit Error. Posting to a subreddit you are banned from now returns a distinct, non-retry-safe error instead of the generic retry-safe code 121. This stops schedulers from retrying a permanently rejected post in a loop. See Ayrshare error codes.
May 19 - Bluesky Video Size Limit. The maximum Bluesky video upload size is now 100 MB (previously advertised as 1 GB) to match Bluesky's platform cap. Files above 100 MB are now rejected up front rather than failing late at upload. See the Bluesky media guidelines.
May 19 - Dashboard X/Twitter Messaging for BYO Keys. The Ayrshare dashboard Messaging page now supports X/Twitter direct messages for Bring-Your-Own-Keys (BYO) accounts. Your X consumer key and secret are collected in the browser for the session and threaded through send, refresh, and image-fetch actions — no keys are stored. Required now that X/Twitter is BYO-only on Ayrshare.
May 19 - Facebook Ads Cities Targeting Fix. The Facebook Ads Cities endpoint (GET /ads/facebook/cities) now correctly resolves cities and their associated region data. Each result includes region, regionId, and supportsRegion so you can target a city's region when available. Use the search query parameter with a partial or full city name.
May 18 - YouTube Status Field Controls. Three new optional parameters on the YouTube Post APIyouTubeOptions: license ("youtube" or "creativeCommon"), embeddable (boolean), and publicStatsViewable (boolean — controls the extended statistics panel on the watch page; basic view and like counts remain public regardless). The /history/youtube response now also returns these fields. Two new validation error codes — 455 (invalid license) and 456 (invalid embeddable or publicStatsViewable) — reject malformed requests at the Ayrshare edge. Monetization toggles (enabling/disabling ads) are not included; those require YouTube CMS credentials and are not available via the standard YouTube API.
May 18 - GMB First Comment No Longer Masks Post Success. Fixed an issue where including firstComment on a Google Business Profile post returned code: 163 with no postIds even though the post succeeded. Google Business Profile does not support post comments, so firstComment is now skipped for GMB and the successful post result is returned normally.
May 14 - Preventing Account Unlinking. Social networks have been quietly rolling out stricter anti-bot controls, which were causing an unusually high number of user accounts to get unlinked. We've rolled out several backend improvements to reduce unlinks and clarify error messages, and updated the account linking page to make the UI much clearer for users — including a new "Action required" state for Meta networks (Facebook, Instagram, FB Groups, Threads, Messenger) when an account hits identity-verification limbo, with a "Resolve with Meta" link and a "Check again" probe so users can fix the issue without unlinking and relinking.
May 12 - Instagram Engagement Automations (Beta). New Automations API lets your users automatically react to Instagram engagement — fire a DM, webhook, or email when an end user comments on a post, replies to a story, sends a DM, or reacts to a DM. Four trigger types (comment\_keyword, story\_reply, dm\_reaction, dm\_keyword) and three action types (send\_dm, fire\_webhook, send\_email) — up to 50 of each per rule. Includes per-action 7-day dedup (configurable per action via dedupWindowMinutes), daily DM caps (1,000 Business / 5,000 Enterprise), and a cursor-paginated activity log. Available on Business and Enterprise plans. New error codes 462–472 cover validation, tier gating, the active-automation cap, missing linked accounts, and feature-flag opt-in. Beta — we are actively collecting feedback; please send bug reports and feature requests to support.
May 12 - Scheduled Post Throughput Improvements. We've added more hardware for processing scheduled posts which is dramatically improving throughput and performance. We'll be adding more platform specific hardware for YouTube and TikTok soon as well.
May 12 - Instagram Relink Hint for Account-State Errors. Certain Instagram account-state failures (Meta error\_subcode 2207085, previously surfaced as a generic code: 258 with no guidance) now return relink: true and retryAvailable: true with a remediation message instructing the user to unlink and relink the Instagram account granting all permissions. See error codes.
May 11 - YouTube transient error codes.
YouTube uploads that fail due to transient upstream issues now return new
error codes 453 (HTTP 504, Google ingest timeout) and
454 (HTTP 503, service unavailable) with a
retryAvailable: true flag your integration can use to retry
automatically. See [error codes](/docs/errors/errors-ayrshare) for details.
May 11 - X/Twitter Analytics & Lookups Open to All BYO Users. The legacy X add-on gate has been removed from /analytics/social and /lookups/x. Any X/Twitter Bring-Your-Own-Keys customer can now look up analytics for arbitrary handles and use the X lookups endpoint without hitting code: 3. Calls are signed with your own X Developer App credentials and count against your own X rate limits.
May 8 - Python SDK v1.3.0 — X/Twitter BYO support. The official Python SDK now exposes set\_twitter\_byo(api\_key, api\_secret) and clear\_twitter\_byo() for X/Twitter Bring-Your-Own-Keys. Once set, every SDK request includes the required X-Twitter-OAuth1-Api-Key and X-Twitter-OAuth1-Api-Secret headers — required for X/Twitter operations now that Ayrshare's BYO requirement is enforced (as of March 31, 2026). Install via pip install --upgrade social-post-api; release notes on GitHub and PyPI.
May 4 - Automatic Image Format Conversion. WebP, HEIC, and AVIF images are now automatically converted to JPEG before posting to platforms that don't accept them. WebP conversion applies to Instagram, LinkedIn, TikTok, Google My Business, Threads, and Snapchat. HEIC and AVIF are converted across all supported platforms. No API changes needed; conversion runs transparently at send time. New error codes 450 (conversion failure), 451 (source download failure), and 452 (converted-image upload failure) surface when conversion can't complete.
May 4 - Instagram errors now include Meta's raw message. Instagram media-status failures now surface Meta's underlying error text in the details field alongside the Ayrshare error code, so callers can distinguish causes (for example, robots.txt/crawler issues vs. token problems) without guessing from the generic code. See the [Instagram Post API](/docs/apis/post/social-networks/instagram) and [error codes](/docs/errors/errors-ayrshare).
## April 2026
April 30 - X/Twitter BYOK in the API Explorer. The Ayrshare API Explorer now includes a collapsible X/Twitter BYOK (Bring Your Own Keys) section so you can paste your X API Key and API Secret once and have them attached as X-Twitter-OAuth1-Api-Key and X-Twitter-OAuth1-Api-Secret headers on every outgoing request — no more dropping to curl or Postman to test BYOK from the Explorer. Values are scoped to the current browser tab via sessionStorage, masked by default with a reveal toggle, and cleared with one click. See the X BYO Key Setup Guide for how to obtain your credentials.
April 28 - Social Analytics Enhancements (rolling out). The Social Analytics endpoint is gaining Instagram shareCount (total shares aggregated over the 90-day rolling window) and YouTube lifetimeLikes (opt-in via youtube: \{ lifetime: true }); the new fields will appear in responses as the deployment reaches your account. Documentation corrections included in this update: Instagram viewsCount is a 90-day rolling window (not 180 days), mediaCount is always lifetime, YouTube likes is scoped by quarters, and TikTok profile-level metrics are capped at 60 days with per-post lifetime semantics when quarters is used.
April 28 - Instagram Trial Reels. The /post endpoint now supports publishing Instagram Trial Reels — Reels visible only to non-followers when first published. Set instagramOptions.trialParams.graduationStrategy to "MANUAL" (graduate from inside the Instagram app) or "SS\_PERFORMANCE" (Meta auto-graduates based on early performance). Three new validation error codes — 447, 448, 449 — reject invalid trial-reel requests at the Ayrshare edge.
April 24 - Instagram Posting Reliability. Expanded automated retry handling for Instagram during busy times and improved error messages across the board. Instead of generic errors, you'll now receive specific error codes for rate limits (code: 435) and media processing timeouts (code: 436) — making it easier to diagnose issues and build smarter retry logic in your integrations.
April 23 - Facebook Analytics Rate Limit Error Code 444. Facebook Page per-Page analytics throttles (Meta error 80001) now return code: 444 (HTTP 429) on post and social analytics responses. Previously these throttles were misclassified as code: 161 ("relink your account"). If your integration branches on 161 to trigger a relink flow, update it to recognize 444 and retry with backoff instead. See Facebook Analytics Rate Limit for details.
April 23 - Meta Media Crawler Troubleshooting. New help-center guide on fixing error code: 440 ("social network could not download media from this URL") and the related Instagram code: 138 / Threads code: 379, all caused by robots.txt or bot rules blocking Meta's publishing crawler. See Meta Media Crawler Blocked.
April 21 - Moderation input errors now return 400.POST /validate/moderation now returns new error code 438 (HTTP 400) for caller-input problems (e.g. an unsupported file as imageUrl, or an unreachable/malformed URL) instead of a misleading 500 with retry guidance. Genuine processing failures still return code 331 (HTTP 500). See [error codes](/docs/errors/errors-ayrshare).
April 20 - Caption Enhancement Error Code 441. The Post endpoint now returns error code: 441 (HTTP 502) when a caption enhancement such as shortenLinks fails. When the failure affects only some platforms, the successful platforms still post and appear in postIds alongside a top-level status: "error" and per-platform entries in errors\[]. See Caption Enhancement Errors for details.
April 15 - Instagram dead-token detection. Instagram posts that fail because of an invalid/expired OAuth token — or a page-role/permission error (Meta subcode 492) — now return Ayrshare code 161 (authorization error) and automatically unlink the affected account so the user is notified to relink, instead of the misleading generic code 138 "please try again" response that previously masked these cases. See [error codes](/docs/errors/errors-ayrshare) and the [Instagram Post API](/docs/apis/post/social-networks/instagram).
April 9 - Instagram & TikTok Analytics All-Time Data & Date Filtering. The social analytics endpoint now returns all-time Instagram and TikTok data when neither daily nor quarters is specified. Use quarters (1–4, where 1 = 90 days) or daily=true to filter by date range — now supported on TikTok as well. When active, TikTok comment, share, and view period labels and totals reflect the filtered date range.
April 9 - Analytics Reliability and Recovery. The Social Analytics and Post Analytics endpoints now automatically backfill cumulative metrics (followers, likes, views) from stored data when the social network temporarily returns zeros. Two new optional response fields, backfilledFrom and recoveredFrom, indicate when stored data was used. Additionally, requesting analytics when no platforms return data now returns a 400 error (code: 187) instead of an empty success response.
April 1 - generateJWT Header-Based X Credentials. The Generate JWT endpoint now accepts X-Twitter-OAuth1-Api-Key and X-Twitter-OAuth1-Api-Secret headers for passing your X consumer keys — consistent with all other X/Twitter endpoints. Body parameters remain supported for backward compatibility.
## March 2026
March 30 - X Credit-Depletion Errors Surfaced. When a BYOK X/Twitter Developer account runs out of API credits, posts that previously got stuck in processing with no error now correctly fail with code: 416 (X Credits Depleted, HTTP 402). Detection for code: 416 has been broadened to also catch X's HTTP 429 responses that mention credits. See error codes for details.
March 28 - Instagram Post Null Response Fixed. Resolved an edge case where an Instagram post would succeed on the platform but the /post response returned null instead of the normal success body with postIds and id. Successful Instagram posts now always return a valid response your integration can parse.
March 26 - Instagram Daily Reach Fix. Fixed an issue where Instagram Social Analytics omitted daily reach data when daily=true was set. The response now returns a nested reach object (with period and a values time-series) in daily mode; the scalar reachCount is still returned in non-daily mode and is preserved as a fallback when daily data is temporarily unavailable.
March 26 - X/Twitter BYOK Enforcement Error Codes. With the [Bring Your Own Keys](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) requirement now enforced, X/Twitter requests return specific error codes you can branch on: 419 (HTTP 400, missing X-Twitter-OAuth1-Api-Key/Secret headers), 416 (HTTP 402, X Developer account out of credits), and 417 (HTTP 403, OAuth 1.0a app permissions not set to Read/Write/DM). See error codes for messages and resolutions.
March 23 - Keyword Search on X. New keyword search endpoint for BYOK customers. Search X/Twitter for tweets matching keywords, hashtags, and advanced search operators. Supports pagination, filtering by language and location, and returns normalized tweet data.
March 23 - Listening Section. A new Listening section has been added, expanding on the Brand endpoints with new features like keyword search.
March 19 - @Mentions in Comments. Added documentation for @mention support in the comment text string on the [Post a Comment](/docs/apis/comments/post-comment) and [Reply to a Comment](/docs/apis/comments/reply-to-comment) endpoints. Includes LinkedIn server-side resolution details and links to platform-specific mention syntax.
X/Twitter Paginated Messages. The [Get Messages](/docs/apis/messages/get-messages) endpoint now supports a limit query parameter for X/Twitter, allowing you to fetch only the latest N messages (1–100) without a full history sync. Combined with cursor-based pagination via the next parameter, this enables efficient polling — fetch a small batch, check if you already have them, and only page further if needed.
Increased Video Size Limits. With so much of social publishing now focused on video content, we increased our video upload limits across multiple platforms: LinkedIn (200 MB → 500 MB), TikTok (1 GB → 10 GB), X Premium long video (1 GB → 16 GB), and added larger content-type-specific limits for Facebook (Reels 2 GB, Stories 4 GB, Feed 10 GB) and Pinterest (2 GB). See the [Media Guidelines](/docs/media-guidelines/overview) for full details.
X/Twitter Messages BYO Key Support. [Get Messages](/docs/apis/messages/get-messages) and [Send Message](/docs/apis/messages/send-message) endpoints now support BYO (Bring Your Own) X/Twitter API credentials. Real-time DM notifications via webhooks are not available for BYO users; use polling via the GET Messages endpoint instead.
Bring Your Own Keys on X. A major change to how X/Twitter accounts are connected. The new [Bring Your Own Keys](/docs/apis/post/social-networks/x-twitter) approach gives you more control of your account, better data portability, and a branded OAuth flow. All users need to make the transition by March 31, 2026.
Editable Short Links. You can now [update short links](/docs/apis/links/update-short-link) after they've been published.
Scheduled Post Processing Reliability. Resolved an issue where the scheduled post processing job could run out of memory and return 503 errors. Increased resource allocation, added paginated query processing, and introduced a distributed application lock to prevent duplicate execution — ensuring single, reliable runs for all scheduled post processing.
Facebook & Instagram History Improvements. Improved the [/history/facebook](/docs/apis/history/history-platform) and [/history/instagram](/docs/apis/history/history-platform) endpoints: for Facebook, expired/archived Stories are now filtered out by default so only active Stories appear alongside regular posts, and new since and until query parameters allow time-based filtering with ISO UTC date strings. For both Facebook and Instagram, a new dataType parameter lets you request only posts, only stories, or both (default).
X Rate Limits Removed. As part of the [X/Twitter BYO Keys migration](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys), Ayrshare no longer enforces monthly or daily rate limits on X analytics. Your usage is now governed by your own X Developer account limits.
## February 2026
February 25 - X/Twitter Video Titles & Descriptions. Videos posted to X/Twitter now support setting a videoTitle and videoDescription (sent on the twitterOptions object of the X Post API) for media uploaded to X Media Studio. These accompany the existing thumbNail support for richer video metadata.
Batch Analytics. Added support for batch analytics of social post IDs, allowing up to 100 posts per analytics call using the new postIds parameter. Read about it on our [Analytics on a Post by Social ID](/docs/apis/analytics/social-by-id) endpoint.
History Pagination. Added pagination support to the [posts history for a platform](/docs/apis/history/history-platform) API for Threads and X/Twitter. No more 500 post limit — you can now pull longer history using pagination, and split calls into smaller chunks for faster, more efficient responses.
Free Trial Enhancements. Free trial users can now test the [Messaging API](/docs/apis/messages/overview) and [Max Pack](/docs/additional/maxpack) — you won't be charged until the end of the free trial period.
Improved Error Messages. Added additional detail to [X/Twitter](/docs/apis/post/social-networks/x-twitter) and [LinkedIn](/docs/apis/post/social-networks/linkedin) error messages, making it easier to diagnose issues with your API calls.
Instagram Comments Fix. Fixed an issue where top-level Instagram comments with nested replies were not being returned correctly from the [Get Comments](/docs/apis/comments/get-comments) endpoint.
Python SDK. Updated our [Python SDK](https://pypi.org/project/social-post-api/) with the latest features and improvements.
X/Twitter Webhook URL. A new ayrshareUrl field is now included in [Direct Message Event webhook](/docs/apis/webhooks/actions#new-message-events) payload, providing an unauthenticated URL for convenience.
Status Page Slack Integration. You can link updates from our [Status Page](https://status.ayrshare.com) into Slack automatically. Just click "Get Updates" in the upper right and select the Slack option.
## January 2026
January 21 - Link Analytics Custom Domain Fix. The [Link Analytics](/docs/apis/links/link-analytics) endpoint (GET /links/:id) now returns short links using your configured custom domain instead of the default Ayrshare domain. If you use a custom short-link domain (Business/Enterprise), analytics URLs now match your live links.
January 15 - Instagram Outbound Message Deletion Sync. When an Instagram outbound (sent) message is deleted in the native Instagram app, it is now correctly marked as deleted in Ayrshare's [Messages](/docs/apis/messages/get-messages) data — matching the existing behavior for inbound messages. Conversation history now stays accurate for both directions.
MCP Server. Back by popular demand — we've relaunched our [MCP Server](/docs/additional/mcp-server)! Connect your AI tools directly to the Ayrshare API.
Self-Serve Signup. Added a new [self-serve signup](https://www.ayrshare.com/pricing/) for the Business Plan and Launch Plan. New customers can now access a 14-day free trial of the Launch Plan to test the Ayrshare platform.
X/Twitter Video Thumbnails. [X/Twitter video posts](/docs/apis/post/social-networks/x-twitter#video-thumbnail) now support including a thumbnail preview image (as a URL). This is sent as part of the metadata when uploading a video.
Instagram Hashtag Limit. Changed the hashtag limit on [Instagram posts](/docs/apis/post/social-networks/instagram) to 5 to align with new guidelines published by Instagram.
Bluesky Video Duration. Bluesky video media duration limit has been adjusted to [three minutes](/docs/media-guidelines/bluesky#video) to be in line with Bluesky API requirements.
## December 2025
We're ending this year focused on transparency and reliability, with a ton of new feature releases planned in Q1 2026.
December 23 - X/Twitter URL Entities in Response. X/Twitter post and [history](/docs/apis/history/history-platform) responses now include URL entity data for links in a tweet's body: a top-level urls array carrying X's raw fields (display\_url, expanded\_url) plus a camelCased entities object where the same links appear as entities.urls\[].displayUrl / expandedUrl — making it easier to render link previews and detect outbound links in your integration.
X/Twitter Entities. The [post analytics](/docs/apis/analytics/post) and [platform history](/docs/apis/history/history-platform) endpoints for X/Twitter now return parsed entities from the tweet text, including URLs, mentions, hashtags, and cashtags with their positions and display URLs.
Facebook Post Analytics. New metrics added to [Facebook post analytics](/docs/apis/analytics/post) including mediaView, mediaViewIsFromAds, and mediaViewIsFromFollowers to replace [deprecated impression metrics](/docs/whatsnew/upcoming-api-changes#november-14%2C-2025).
Bluesky Comments. Improved support for [Bluesky comment retrieval](/docs/apis/comments/get-comments) with proper handling of AT Protocol-style post and comment IDs.
Threads Linking. Enhanced [Threads account linking](/docs/dashboard/connect-social-accounts/threads) to handle cases where the name or username fields are not present on the account.
24/7 Monitoring. Onboarded a dedicated DevOps team to monitor the platform around the clock for improved reliability.
Monthly Receipts. Automatic monthly receipts are now emailed to the primary account holder, providing better transparency around pricing and payments.
## November 2025
Instagram Token Refresh. Added automated refresh for long-life Instagram tokens for users who link to Instagram using direct IG login (without Facebook Page).
Facebook Analytics Updates. [Facebook post analytics](/docs/apis/analytics/post) now returns enhanced impression metrics including post\_impressions\_paid\_unique, post\_impressions\_fan\_unique, post\_impressions\_organic\_unique, and post\_impressions\_unique.
Facebook Page Insights. New [Facebook social analytics](/docs/apis/analytics/social) fields added: pageFollows, pageMediaView, pageMediaViewIsFromAds, and pageMediaViewIsFromFollowers with both aggregate and daily breakdown support.
Instagram Analytics. [Instagram social analytics](/docs/apis/analytics/social) viewsCount and reachCount metrics are now supported with both direct Instagram Login and Facebook-linked accounts.
LinkedIn Mentions. Fixed handling of [LinkedIn mentions](/docs/apis/post/social-networks/linkedin#linkedin-mentions) to properly distinguish between mentioning organizations versus individuals.
Dashboard Improvements. The [Ayrshare web dashboard](https://app.ayrshare.com) API page has been refactored with improved performance and a better organized messaging usage card.
Team Expansion. Expanding the development team to speed up support and feature development.
## October 2025
Ayrshare Acquired by Saas.group. Ayrshare has been acquired by Saas.group. The team is expanding to deliver faster feature development and better customer support.
Webhook History. New endpoint to [get webhook history](/docs/apis/webhooks/history) per action for the past 6 months.
Facebook Ads Location Targeting. In addition to country targeting, you can now [specify a region or city](/docs/apis/ads/facebook/boost-post#param-locations) when boosting Facebook posts.
LinkedIn Video Thumbnails. The [LinkedIn history endpoint](/docs/apis/history/history-platform) now returns the thumbnailUrl for video posts, making it easier to display video previews in your application.
Reddit Post Analytics. [Reddit post analytics](/docs/apis/analytics/post) reliability has been improved with enhanced authentication handling to avoid rate limiting issues.
Instagram History. Improved handling of large result sets in [Instagram post history](/docs/apis/history/history-platform) for accounts with many posts.
Facebook Ads. The [Facebook ads history endpoint](/docs/apis/ads/facebook/get-ad-history) now includes clarification on which ads are returned based on the campaign structure.
Instagram Collaboration. Added documentation clarifying that [accepted collaboration posts](/docs/apis/history/history-platform) may not return from the platform history endpoint due to Instagram API limitations.
## September 2025
TikTok Drafts. [Sending a post to TikTok drafts](/docs/apis/post/social-networks/tiktok#param-draft) now supports images as well as videos.
Facebook Ads. As part of the requirements set forth by the
European Union Digital Services Act (DSA), Facebook requires ads targeting any
part of the EU to provide values defining the beneficiary and payor of the ad
being created. You can now [look up the DSA
recommendations](/docs/apis/ads/facebook/get-dsa-recommendations) and add it to the
ad.
Media Management. The [GET media
endpoint](/docs/apis/media/get-media-in-gallery) has been enhanced to include large
media files uploaded, and now shows the expireAt field.
Threads Posting. Easily create a [thread on
Threads](/docs/apis/post/social-networks/threads#thread) (aka threadstorms), which
is a series of connected posts on Meta Threads.
Direct Messaging. Facebook and Instagram Messaging now
support [sending audio files](/docs/apis/messages/send-message#param-media-urls)
(AAC or WAV).
## August 2025
Reddit Analytics. New [Reddit social analytics data](/docs/apis/analytics/social) on a user. This includes friend count, follower acceptance, suspension expiration date if the account was suspended, and more.
Threads Analytics. New [Threads social analytics
data](/docs/apis/analytics/social) on a user. This includes bio, geo restriction
eligibility, username, and more.
Threads Geo Restrictions. On Threads, you can [set geographic
restrictions](/docs/apis/post/social-networks/threads#geo-restrictions) to only
allow posts to show in certain countries.
LinkedIn Distribution. [Disable the ability for other users
to re-share your LinkedIn
posts](/docs/apis/post/social-networks/linkedin#disable-share).
Ayrshare Status. In addition to email alerts, you can get the
[social network and Ayrshare system status via an
endpoint](/docs/additional/status).
YouTube Watermark. Set a [watermark image on your YouTube channel](/docs/apis/utils/set-youtube-watermark) that will appear on all your videos. The watermark can be configured to appear at specific times during video playback.
## July 2025
Instagram Login. The [Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) feature is generally available on July 6, 2025.
All new Instagram connections will use the new Instagram Login feature. Current connections will not be affected.
If you don't want to use the new Instagram Login feature, you can disable it in your account settings.
LinkedIn Mentions. You can now [mention another LinkedIn
profile](/docs/apis/post/social-networks/linkedin#member-profiles) either by their
vanity name or actual name.
LinkedIn Search. [Search for LinkedIn companies or people
based on a search query.](/docs/apis/listen/search/linkedin-search) This endpoint is
commonly used for typeahead mention completion in social media posts.
LinkedIn Videos. [LinkedIn now accepts video files up to 500
MB](/docs/media-guidelines/linkedin#video) in size, up from 200 MB previously.
X Account Activity. Get the full account activity from X via
a webhook including posts, likes, mentions, DMs, and more. The X Account
Activity feature must be enabled for your linked X account to receive these
webhooks. Please contact your account representative to enable this feature.
X Geographic Restrictions. [Set allowed and blocked
countries](/docs/apis/post/social-networks/x-twitter#geo-restrictions) for your X
media.
X Posts Limited to Subscribers. You can set a [X post to only
be visible to
subscribers](/docs/apis/post/social-networks/x-twitter#subscribers-only).
X Reply Settings. On X, you can allow only [certain types of
users to reply to your
post](/docs/apis/post/social-networks/x-twitter#reply-settings). You can choose
either followers, mentioned, subscribers, or verified users.
TikTok Thumbnail. Set a [custom thumbnail for
TikTok](/docs/apis/post/social-networks/tiktok#thumbnail-url) videos.
Instagram Analytics. Instagram analytics on a post now
[includes the direct link to the media](/docs/apis/analytics/post).
Developer Dashboard. You can now [register Webhooks directly
in the Ayrshare dashboard](/docs/apis/webhooks/overview#register-a-webhook).
Skip Pre-Validation. There is now an option to [skip
pre-validation on scheduled](/docs/apis/post/post#param-validate-scheduled) posts.
Premium Plan History. Premium plans now have access to the
[history by platform](/docs/apis/history/history-platform) to get all posts, even
those not sent via Ayrshare.
Auto Repost. You can now [get post history by auto repost ID](/docs/apis/history/get-history). When creating an [auto repost](/docs/apis/post/overview#auto-repost), an ID is assigned to track that series of posts. You can now retrieve the auto repost either by the ID or by getting all.
## June 2025
Instagram Login (coming soon). [Enable or disable Instagram
Login](/docs/multiple-users/manage-user-profiles#instagram-login) on the social
linking page. Instagram Login will be enabled by default in the coming weeks.
If you require the advanced features listed including hashtag search,
collaborations, location tagging, or brand data, you must manually disable
this option to use Facebook Page authentication instead. We recommend most
clients use the new direct Instagram Login since it is a simpler work flow and
does not require a Facebook Page.
Introducing Snapchat. Ayrshare now supports
[Snapchat](/docs/dashboard/connect-social-accounts/snapchat). The Snapchat API
enables direct publishing of content to both Stories and Spotlight, and
getting analytics and history. Stories are temporary posts that disappear
after 24 hours, while Spotlight posts are permanent and can help creators and
businesses reach a wider audience.
MCP Server. Connect the [Ayrshare API Docs MCP
server](/docs/additional/mcp-server) with your AI agent. By connecting the Ayrshare
API documentation MCP server to your AI development tools like Cursor or
Claude Desktop, you can give your AI agent direct access to Ayrshare’s
documentation.
Copy a Post. [Copy an existing post](/docs/apis/post/copy-post) to
another platform. This new endpoint allows you to reuse successful posts
across different platforms or with different configurations.
Developer Dashboard. Two new improvements in the posting flow
in the [developer dashboard](https://app.ayrshare.com). In addition to
uploading media files, you can now also use URLs to post your media. And you
can now view the JSON used to publish your post which helps verify the
correctness of your JSON.
User Management. The [User
endpoint](/docs/multiple-users/manage-user-profiles#get-user-profile) now returns
the real-time state of connected social networks, automatically updating
whenever users connect or disconnect their social media accounts.
YouTube. Publishing a video on YouTube now allows disclosure
of realistic Altered or Synthetic (A/S) content by setting the
`containsSyntheticMedia` parameter. [View
docs](/docs/apis/post/social-networks/youtube).
Facebook. [Getting comments on
Facebook](/docs/apis/comments/get-comments) now returns the direct URL to the
specific comment.
## May 2025
Introducing Threads. Ayrshare now supports [posting and
scheduling to
Threads](https://www.ayrshare.com/docs/dashboard/connect-social-accounts/threads),
getting analytics, managing comments, and retrieving history.
Messaging. [Messaging is now a standard
feature](https://www.ayrshare.com/docs/apis/messages/overview) included in the
Business Plan. Key features include managing your users’ conversations with
correspondents, sending text, image, video, and emoji messages, setting up
automated message responses, and webhooks.
X Analytics. X [comment
analytics](https://www.ayrshare.com/docs/apis/comments/get-comments) and [post
analytics](https://www.ayrshare.com/docs/apis/analytics/post) now include
impression, quote, and bookmark count.
Linking Page Languages. You can now [set the language for the
social linking
page](https://www.ayrshare.com/docs/multiple-users/manage-user-profiles#set-language-for-social-linking).
Currently supported languages include English, Chinese (Simplified), French,
German, and Spanish.
LinkedIn Posting. Set the [LinkedIn post
visibility](https://www.ayrshare.com/docs/apis/post/social-networks/linkedin#post-visibility)
to public, 1st degree connections, or logged-in user.
LinkedIn Posting. You can now [include media in the LinkedIn
first
comment](https://www.ayrshare.com/docs/apis/post/overview#first-comment).
Instagram Hashtag Search. [Search the most popular or recent
Instagram posts](/docs/apis/hashtags/search-hashtags)
for a given hashtag to inform your content strategy and identify trending
topics.
## April 2025
Facebook Ads. [Boost Facebook Posts as
Ads.](/docs/apis/ads/overview) The Ayrshare Ads API includes boosting posts,
managing ads, tracking performance, and analyzing ad spend.
User Profile Management. Get a [historical log of created and
deleted user profiles](/docs/apis/profiles/get-profiles#param-action-log).
User Profile Management. In the User Profile section of the
web dashboard, if a User Profile is suspended you can now click the
“Suspended” badge to get the reason.
Post History. The [history
endpoint](/docs/apis/history/get-history) now allows you to filter by start and end
dates.
Social Linking. We introduced an upgraded X authentication
linking. This is a better experience for you and your users.
Social Linking. [Specify the allowed social
networks](/docs/apis/profiles/generate-jwt#param-allowed-social) directly when
creating the Business Plan linking page using the allowedSocial
parameter.
Instagram Posting. [Instagram
images](/docs/apis/post/social-networks/instagram#alternative-text) now support alt
text.
Bluesky Posting. [Bluesky image and video
posting](/docs/apis/post/social-networks/bluesky#alternative-text) now support alt
text.
Pinterest. Add a private note to a [Pinterest
Pin](/docs/apis/post/social-networks/pinterest#posting-an-image-pin-to-pinterest).
YouTube Shorts. [YouTube
Shorts](/docs/apis/post/social-networks/youtube#youtube-shorts) now can be up to 3
minutes long, an increase from the prior limit of 60 seconds.
## March 2025
X Analytics. New [X social analytics
data](/docs/apis/analytics/social) including like count, add to list count, profile
banner image, and more.
X Rate Limits. The [monthly call limits for
X](/docs/errors/errors-http#x%2Ftwitter-analytics-rate-limits) have been increased
to 100,000 for the Business Plan and 5,000 for the Premium Plan.
LinkedIn Analytics. [LinkedIn personal
pages](/docs/apis/analytics/social) now return a basic set of data including the
website url and profile image.
Facebook Reels. You can now add a thumbnail which is a [cover
image for a reel video](/docs/apis/post/social-networks/facebook#facebook-reels).
Linking Page. You can [set the image height of your custom
logo](/docs/multiple-users/manage-user-profiles#update-logo-on-social-linking-page)
on the social linking page. Specify the height in pixels in your account
settings in the web dashboard.
Linking Page. When linking Facebook and Instagram pages, long
lists of pages now have a search field that allows you to filter by the page
name or location.
Team Member Management. Individual team members can now be
[restricted from accessing other user
profiles](/docs/multiple-users/manage-user-profiles#restrict-team-member-access).
Media. The [upload media endpoint](/docs/apis/media/upload-media)
now supports uploads of images and videos up to 30 MB.
Media. [Google Drive and Dropbox share URLs can now be
used](/docs/apis/post/overview#valid-url) directly in the `mediaUrls` post
parameter, eliminating the need to create a separate download URL.
## February 2025
**TikTok Posting**. [Create a draft video
post](/docs/apis/post/social-networks/tiktok#tiktok-video-draft-post) in the TikTok
app. The draft video will be in the notification Inbox in the app, and the
user can edit the video before publishing.
**TikTok Analytics**. Additional [TikTok analytics data fields were
added](/docs/apis/analytics/social), including demographics such as audience cities
and gender. Other new profile fields include profile views and email, address,
and bio link clicks.
**Instagram Collaboration**. In addition to images and Reels, users can now
[add collaborators to
carousels](/docs/apis/post/social-networks/instagram#collaboration).
**Instagram Analytics**. [Instagram post analytics](/docs/apis/analytics/post) now
includes the view count, which is the total number of times your post has been
seen.
**Instagram Details**. Get [additional Instagram
details](/docs/apis/user/profile-details) for a user profile, such as used quota
and whether the account type is Creator or Business.
**Compression**. [Compression now supports Brotli](/docs/apis/overview#compression)
for all endpoints, which is faster and offers better compression.
**LinkedIn Comments**. [LinkedIn comments and replies to
comments](/docs/apis/comments/post-comment) now support images.
**Reddit Mentions**. Reddit posts now [support mentions of other users or
subreddits](/docs/apis/post/social-networks/reddit#reddit-mentions).
**Bluesky Posting**. [Link previews are now supported in
Bluesky](/docs/apis/post/social-networks/bluesky#bluesky-supported-features) posts.
Include a link in a post, and a preview will automatically be generated.
**Max Pack**. Image resizing and conversion now supports [converting to
WebP](/docs/apis/media/resize#convert-to-a-jpg-or-webp).
**Max Pack**. Image resizing and
[watermarking](/docs/apis/media/resize#watermark-position) now support positioning
the watermark, such as the northeast corner.
**Dashboard**. The [Ayrshare web dashboard](https://app.ayrshare.com) has been
refreshed with a new color scheme, enhanced alerts, and improved workflows for
a smoother user experience.
## January 2025
**Bluesky API**. [Bluesky social media management](/docs/apis/post/social-networks/bluesky) is now available as the 11th social network that Ayrshare supports.
**LinkedIn Targeting**. LinkedIn allows you to [target your organic posts to
specific groups of
users](/docs/apis/post/social-networks/linkedin#linkedin-audience-targeting). You
can target by countries, industry, job title, and more.
**YouTube Targeting**. [Block or allow countries and
regions](/docs/apis/post/social-networks/youtube#location-targeting) for a YouTube
video.
**Auto Schedule**. Reset an auto-schedule to start scheduling from the current
time. This is accomplished by [deleting the last scheduled
date](/docs/apis/auto-schedule/delete-schedule).
**TikTok Analytics**. TikTok social network analytics on a user profile is now
available as a historical [daily time
series](/docs/apis/analytics/social#param-daily).
**TikTok Posting**. If the post is completely or mostly created with AI, you
can label the post as [“Creator labeled as
AI-generated”](/docs/apis/post/social-networks/tiktok#available-tiktok-options).
**X Posting**. X now supports [up to 4 videos in a single Tweet](/docs/media-guidelines/x_twitter).
## December 2024
**Dashboard**. The User Profiles page performance in the web dashboard has
been optimized. You will now get a smooth scrolling and loading experience
regardless of how many user profiles you have in your account.
**Dashboard**. The Posts page in the web dashboard now allows you to include
deleted posts in your history timeline. This lets you access, filter, and
search deleted posts in the same way as successful posts.
**Deleted Posts**. If you or your users have manually deleted a post on a
social network, you can [mark it as manually
deleted](/docs/apis/post/delete-post#body-parameters) in Ayrshare. This will
prevent Ayrshare from trying to delete the post in the future and allow you to
access a more accurate post history.
**Webhooks**. You can now [get all the registered webhooks for all your user
profiles](/docs/apis/webhooks/list) in a single call.
**Analytics**. [Instagram post analytics](/docs/apis/analytics/post) now includes
share, followers gained, profile visits, and profile activity counts.
**Comments**. [TikTok comments](/docs/apis/comments/get-comments) now return the
name of the person who made the comment.
**Comments**. [X comments](/docs/apis/comments/get-comments) now return the ID of
the Tweet the comment was replied to.
## November 2024
**All New Docs**. Check out the [new Ayrshare docs](/docs/introduction). We migrated to a more advanced
Documentation platform with many user experience improvements versus the
prior version.
**Instagram Analytics**. [Instagram post analytics](/docs/apis/analytics/post) now includes the metrics for how many times your reel replayed after the first time and how total times your reel played after the first impression.
**Hashtags**. The [hashtags endpoint](/docs/apis/hashtags/auto-hashtags) now allows you to specify a language hint to keep the hashtags in the same language as the post.
**X Analytics**. [X/Twitter Social analytics](/docs/apis/analytics/social) now returns the most recent Tweet and the Pinned Tweet, if a pinned Tweet has been set.
**Dashboard**. In the developer dashboard, Auto-Scheduled Posts are now tagged as “Auto-Schedule”.
**Auto-Schedule**. Get all the [pending Auto-Scheduled Posts](/docs/apis/auto-schedule/pending-auto-schedule) via the API. This returns the list of posts that have been scheduled but not yet published.
**TikTok**. You can [check if a linked TikTok account is a business account](/docs/apis/analytics/social) with the Social Analytics endpoint.
**Instagram Comments**. The [comments endpoint](/docs/apis/comments/get-comments) now returns the Instagram top-level post ID to identify the original post.
**History**. The [history endpoint](/docs/apis/history/get-history) now returns “paused” scheduled posts. In addition the number of past posts returned was increased to 1000.
**Linking Page**. [Add a footer and copyright info](/docs/multiple-users/manage-user-profiles#footer-text) on the user profile social linking page. Max Pack required.
**Image Conversion**. The image resizing endpoint can now [convert a PNG or other image type to a JPG](/docs/apis/media/resize#convert-to-jpg) as part of the conversion process. Max Pack required.
## October 2024
**First Comment**. [Automatically add a first comment](/docs/apis/post/overview#first-comment) to
your published social media posts. The first social media posts. The first comment is a great
feature that allows you to add more details and context, boost engagement, and set the tone of
the conversation.
**Comment Errors**. [Comment errors also are returned in an errors array
field](/docs/apis/comments/post-comment) to align with how post errors are
returned. how post errors are returned.
**X/Twitter Comments**. You can now [add media to X/Twitter
comments](/docs/apis/comments/post-comment) and comment replies, which includes
both images and videos.
**Pinterest Analytics**. [Pinterest metrics were
enhanced](/docs/apis/analytics/post) and now include one full year of analytics
data, lifetime now include one full year of analytics data, lifetime comments,
and reactions for both images and videos.
**RSS Feeds**. When [adding an RSS feed](/docs/apis/feeds/add-feed) you can now
select which social networks the article is published. This is available both
on the dashboard and via the API.
**Dashboard**. In the Ayrshare Dashboard API page there is a new Monthly API Calls overview,
which now includes comment API calls as well as post API calls.
**PyPi Package**. The [Python PyPi
package](https://pypi.org/project/social-post-api/1.2.1/) has been updated
with new endpoints.
## September 2024
**Facebook Analytics**. The [History Get All Posts](/docs/apis/history/history-platform) and
[Analytics](/docs/apis/analytics/post) endpoints now return the users who liked a Facebook post. For
each user, you can get the user name and the user ID.
**Content Moderation**. There is a new [Moderation](/docs/apis/validate/moderation)
endpoint which checks if the content is harmful or inappropriate. This
endpoint supports both text and images.
**LinkedIn Linking**. Connecting LinkedIn company pages previously required
the user to be a Super Admin on the page. Now Content Admins who manage the
LinkedIn company page can connect, allowing them to post, get analytics, and
manage comments.
**User Management**. The [User endpoint](/docs/apis/user/profile-details) now
returns both the Page ID and User ID for Facebook and Instagram.
**Dashboard**. The web dashboard Post page now shows an icon indicator if the
post was published from an rss feed.
**Facebook Reviews**. [Facebook Reviews](/docs/apis/reviews/get-reviews) now return
the profile picture of the reviewer.
**Google Reviews**. [Google Business Profile Reviews ](/docs/apis/reviews/get-reviews)now return all
your reviews, even if there are thousands.
## August 2024
**LinkedIn History**. Now you can get the [post history for LinkedIn personal
pages](/docs/apis/history/history-platform). Previously only LinkedIn company pages returned history.
Requires relinking of LinkedIn with Ayrshare.
**LinkedIn Analytics**. There are new [data points available for
LinkedIn](/docs/apis/analytics/social) personal and company pages including
`likedBy` and `comment` details.
**LinkedIn Lookup**. The [brand endpoint](/docs/apis/listen/brand-user) now allows
you to look up a person or company. This is useful to see details of who liked
one of your posts.
**Facebook History**. You can limit the results for a [Facebook Page
history](/docs/apis/history/history-platform) to only show posts that were
published by the page itself. This will filter out all the content that was
not published by the page.
**User Profile**. The [user endpoint](/docs/apis/user/overview) now returns a new
field with the timestamp of the last time that an API call was made for this
user profile.
**X Long Posts**. You can publish [long posts to Premium X
Accounts](/docs/apis/post/social-networks/x-twitter). Long posts can be up to
25,000 characters long. You can also now [get full long Post
data](/docs/apis/history/history-platform) including the full body and URL in the
long Post body when calling analytics or history.
**Web Dashboard**. The post page design was improved and several new content types were added.
You can now post Facebook and Instagram Reels or Stories or YouTube Shorts directly from the
dashboard.
**Team Management**. When you [invite a team
member](/docs/multiple-users/manage-user-profiles#team-member-status) you can now see if they
accepted the invite or resend the invite from the Dashboard User Profiles page.
**AI Video Titles**. The [video transcripts](/docs/apis/generate/transcribe-video)
now include a suggested title. This is useful for posting to YouTube which
requires a title for every video upload. (Max Pack Required)
**Pausing Posts**. You can [pause and unpause scheduled
posts](/docs/apis/post/overview#pause-scheduled-posts) with the post endpoint.
**Sentiment Analysis**. The [generate endpoint](/docs/apis/generate/sentiment) now
can generate sentiment analysis for a post or comment to understand if it is
negative, positive, or neutral. The result also includes recommendations on
how to improve.
**Instagram Analytics**. [Instagram analytics](/docs/apis/analytics/social) has
been enhanced to return additional demographic data on the engaged audience.
**TikTok Photos**. You can now[ post to TikTok with a
photo](/docs/apis/post/social-networks/tiktok#tiktok-image-post). Previously a video was required.
## July 2024
**Post History.** [Filter the history endpoint](/docs/apis/history/get-history) based on the social
network platform, whether the post was immediate or scheduled, and the status.
**Web Dashboard.** The list of user profiles can now be sorted by title or
create date and the scheduling modal for posts has been improved.
**Webhooks.** [Webhooks now automatically
retry](/docs/apis/webhooks/overview#webhook-retries) two times with the same hookId
if the initial webhook does not get a success response.
**Reddit.** [Check if a subreddit exists](/docs/apis/validate/check-subreddit)
based on the subreddit name.
**Facebook Stories.** A [Facebook Story returned via the history
endpoint](/docs/apis/history/history-platform) now includes the cover image and
direct url to the video.
**Cropping Images.** There are new "[crop" mode options for resizing an
image](/docs/apis/media/overview). Now you can specify the dimensions and starting
coordinates to crop an image.
**Demo Social Media Posting App.** We released the code for a [demo React +
Node.js web application](https://github.com/ayrshare/social-api-demo) that
allows users to compose, schedule, and post content to multiple social media
platforms simultaneously.
**Multi-Platform Posts.** The post endpoint was enhanced to allow you to
[customize your post content and media for different social
networks](/docs/apis/post/overview#multi-platform-posts-and-media) in a single API
call.
**Instagram Analytics.** Instagram profile analytics are now available in a
[daily historical time-series](/docs/apis/analytics/social).
**Linkedin Comments.** Getting [comments from Linkedin](/docs/apis/comments/get-comments)
now return the comment media link for images or videos.
## June 2024
**Ayrshare Messaging API**. The [Ayrshare Messaging
Add-On](https://www.ayrshare.com/social-media-messenger-apis/) is an optional paid add-on that
allows your platform to manage the direct messaging for your users including Facebook Messenger,
Instagram Messaging, and X/Twitter Messaging.
**YouTube Comments**. You can now [delete comments on
YouTube](/docs/apis/comments/delete-comments) by using the YouTube comment ID.
**Auto Hashtags**. Introducing the new fully rebuilt [auto-hashtag
system](/docs/apis/hashtags/auto-hashtags) with more relevant hashtags and no limit
on post length. The amount of hashtags has also been increased to allow up to
10 hashtags per post.
**Web Dashboard**. The dashboard UI has been updated with the ability to
remove all the target social networks in the post page with a single click,
and a new code example section in the API Key page.
**User Profile Management**. The [Profiles endpoint has been
enhanced](/docs/apis/profiles/get-profiles) to allow you to filter the results to profiles that have
active social accounts or contain certain platforms.
## May 2024
**Google Business**. You can now [update your Google Business Profile
location](/docs/apis/user/update-user) data including phone numbers, website URL, map location, and
more.
**History Search**. With the History endpoint you can now [search post
IDs](/docs/apis/history/get-history-id) across all your user profiles. This is
useful if you have a post ID and do not know which user profile posted it.
**User Profile Tags**. [Add your own tags to a user
profile](/docs/apis/profiles/create-profile) so you can better organize and manage
profiles. The web dashboard also allows you to see the tags assigned and
search for tags in the User Profiles page.
**YouTube Captions**. [Add your own custom
captions](/docs/apis/post/social-networks/youtube#subtitles-captions-for-videos) to
a YouTube video with a SRT or SVB file.
**NPM Package**. An updated Node.js [NPM
package](https://www.npmjs.com/package/social-media-api) was released with new
endpoints and more detailed documentation. The package was also renamed to
social-media-api.
**Facebook Comments**. You can now [add an image as part of your
comment](/docs/apis/comments/post-comment) on Facebook.
**Linkedin Comments**. Linkedin Comments now return the [like count for that
specific comment](/docs/apis/comments/get-comments).
**Linkedin Brands**. The Brands endpoint for [Linkedin
data](/docs/apis/listen/brand-user) was enhanced with the localized name of the
account, company specialities, and company description.
**Disable Comments**. You can [disable comments on a
post](/docs/apis/comments/overview#disable-comments) on Instagram, LinkedIn, and
TikTok. This works on new posts or already published posts.
**Historical Posts**. [Get historical post data from
TikTok](/docs/apis/history/get-history-id) on posts that were not posted via
Ayrshare.
**Instagram Analytics**. New data points available for [Instagram
Stories](/docs/apis/analytics/post) including replies, shares, and exit counts.
**AI Generate**. [Generate social media post](/docs/apis/generate/post-text) text
with AI based on one or more images. This can also be used to write an image
caption.
**Web Dashboard**. For each user profile listed in the dashboard, you can see
the connected social networks. Each social network icon can be hovered to see
the name on the social network.
**Social Linking**. In the web dashboard and in your social linking page, there are now profile
images shown next to the page or company name.
## April 2024
**Auto-Schedule**. Enhanced to allow selection of the days of the week for [auto-schedule
publishing](/docs/apis/auto-schedule/set-schedule) or select specific dates to exclude.
**Facebook Analytics**. [Facebook Post analytics](/docs/apis/analytics/social) now
includes impressions.
**Instagram Comments**. [Instagram Get comments](/docs/apis/comments/get-comments)
response now include additional reply information, such as the username, like
count, and hidden status.
**Facebook Page Location**. You can now tag a post with a [Facebook Page
Location](/docs/apis/post/social-networks/facebook#location-tagging).
**Facebook Audience Targeting**. When creating a Page post on Facebook, you
have the option to [limit its visibility to a specific
audience](/docs/apis/post/social-networks/facebook#audience-targeting) using
different demographic factors such as age, county, education, and others.
**Linkedin Comments**. [LinkedIn comments](/docs/apis/comments/get-comments) from a
company now have additional fields including organization type, company
website, and the company description.
**Instagram History**. The history for Instagram now returns all the [images
and videos in a carousel](/docs/apis/history/history-platform).
**YouTube Analytics**. Get a [daily breakdown of YouTube analytics](/docs/apis/analytics/social) at
the channel level.
## March 2024
**Instagram Collaborators**. Instagram collaboration allows you to co-author content with other
accounts. The public original author can tag another private or public account as a
collaborator. [Add Instagram collaborators to media
posts](/docs/apis/utils/instagram-get-collaborator).
**Google Business Profile**. Additional data on [Google Business
Profile](/docs/apis/user/profile-details) is now available including links to the
reviews and map, place Id, and other data. Getting this additional data
requires relinking of the Google Business Profile.
**Facebook Page, Instagram, Google Profile Location**. On the page linking
screen, [you can now display the page
location](/docs/multiple-users/manage-user-profiles#display-page-location) for a
Facebook Page, Instagram account, and Google Business profile.
**Facebook Profile Analytics**. [Facebook Social Profile
Analytics](/docs/apis/analytics/social-by-id) now returns up to 4 quarters of data.
You can set the data to be returned either aggregated or daily.
**Facebook History**. Facebook Stories now returned in the [Get All History
endpoint](/docs/apis/history/history-platform).
**Social Linking Page**. The Ayrshare Social Linking page now [supports
redirecting](/docs/multiple-users/api-integration-business#opening-and-closing-the-social-linking-url)
to the origin opening tab or window.
**Facebook Reviews**. You can now [reply to a review on
Facebook](/docs/apis/reviews/reply-review).
**Instagram Followers**. [Instagram Get Followers
Online](/docs/apis/analytics/instagram-follower-count) has an enhanced UTC Format.
This data returns the total historical count of your Instagram followers
online per hour, which allows you to optimize posting for maximum engagement.
**Instagram Carousel**. Now publish both videos and images in an [Instagram
carousel](/docs/apis/post/social-networks/instagram#carousel-of-images-and-videos).
Up to a combined 10 media items can be included.
**TikTok**. TikTok captions now support line breaks with the "\n" character.
## February 2024
**Reviews**. Get, reply, and delete reviews on Google Business Profile and Facebook Pages using
the new [/reviews](/docs/apis/reviews/get-reviews) endpoint.
**Linkedin Comments**. Get [LinkedIn comments](/docs/apis/comments/get-comments) by
comment ID for comments done outside of Ayrshare.
**Linkedin Mentions**. [Linkedin
mentions](/docs/apis/post/social-networks/linkedin#linkedin-mentions) in comments
and reply to comments now resolve to the referenced organization handle.
**Public Profile Data**. Now you can search for Facebook Pages and Linkedin
names in the [brand endpoint](/docs/apis/listen/search/fb-page-search). Look up
users' or companies' social media public information, such as followers,
profile image, and websites. These users and companies do not need to be a
linked Ayrshare user.
**Facebook Comments**. The comments endpoint API for [Facebook
Comments](/docs/apis/comments/get-comments) now returns replies directly in the
response body.
**Instagram Banned Hashtags**. Check for banned hashtags by using the new [API
endpoint](/docs/apis/hashtags/check-hashtags) or the new [web
tool](https://app.ayrshare.com/instagram-banned-hashtag-checker). This is
helpful to keep your accounts safe from suspensions or shadow banning.
**Facebook Groups**. Facebook has announced that they will be removing API access to Facebook
Groups. [Learn
more](https://www.ayrshare.com/blog/facebook-removes-groups-api-access-impact-and-implications/).
## January 2024
**Longer Instagram Videos**. [Instagram Video posts](/docs/media-guidelines/instagram) now
support up to 15 minute lengths and 1 GB. This is an increase from the prior 60 seconds and 100
MB.
**Translate Post Text**. Choose over 100 different languages to [translate
your post text](/docs/apis/generate/translate-post). For example, translate English
to French or Spanish to German. The source language is automatically detected.
**Error Translation**. Error messages can be [automatically
translated](/docs/errors/errors-ayrshare#error-message-translation) to the language
of your choice. This is useful if you want to display the error directly to
your user in their preferred language.
**Pinterest Analytics**. Additional [Pinterest data
points](/docs/apis/history/history-platform) are available for get all history
including post title, notes, and board id.
**Check Post Length**. The [Check Post Length
endpoint](/docs/apis/validate/check-post-length) now includes validations for
Facebook, Google Business Profile, LinkedIn, Pinterest, and YouTube.
**New User Batch Endpoints**. When you need a large data set, the batch
endpoints are a great option. You can use the batch endpoints to [get json
files](/docs/apis/user/batch-all-users) for all your user profiles and then use the
[webhook to let you know when the file is
ready](/docs/apis/webhooks/actions#batch-action).
**Linkedin Historical Posts**. Get [historical data for a Linkedin
post](/docs/apis/history/history-social-id) published outside of Ayrshare.
**Linkedin Posts Reactions**. The [Get All Post
endpoint](/docs/apis/history/history-platform) for LinkedIn now returns reactions
for the post, such as Likes, Praise, Maybe, and Appreciation.
**Last API Call Time**. Access the time that you last used the API key in the
web dashboard in the API Key section.
**Ayrshare Dashboard History**. The web dashboard now allows you to load all
your historical posts or webhook logs with a new "Load more" button.
**Webhook Errors**. View the [error rate of your webhooks](/docs/apis/webhooks/overview#webhook-logs)
to see the percentage of success vs error responses.
## Older Updates
Check the [Update Archive](/docs/whatsnew/archive) to see older updates.
# Upcoming API Changes
Source: https://www.ayrshare.com/docs/whatsnew/upcoming-api-changes
Changes to the API that may impact your integration
The following changes to the API will be effective on the date specified.
Please review carefully for any potentially breaking changes.
See [What's New](/docs/whatsnew/latest) for all new features.
**Facebook: Meta retired unique-impression (reach) and 3-second video-view Insights metrics.** Meta removed these metrics across all Graph API versions, so the affected fields are no longer returned. See the [Meta Graph API v25 changelog](https://developers.facebook.com/blog/post/2026/02/18/introducing-graph-api-v25-and-marketing-api-v25/) for details.
[GET analytics/post](/docs/apis/analytics/post) no longer returns the following Facebook fields:
impressionsUnique → migrate to `mediaView`
impressionsFanUnique → migrate to `mediaView`
impressionsOrganicUnique → migrate to `mediaView`
impressionsPaidUnique → migrate to `mediaViewIsFromAds`
videoViewsUnique → use `videoViews` for non-unique 3-second views
The `totalVideoViews*Unique` and `totalVideoImpressions*` families (e.g. `totalVideoViewsOrganicUnique`, `totalVideoViewsPaidUnique`, `totalVideoViewsUnique`)
[GET analytics/social](/docs/apis/analytics/social) no longer returns the following Facebook fields:
The `pagePostsImpressions*` family (`pagePostsImpressions`, `pagePostsImpressionsPaid`, `pagePostsImpressionsUnique`, `pagePostsImpressionsOrganicUnique`, `pagePostsImpressionsViral*`, `pagePostsImpressionsNonviral*`) → migrate to `pageMediaView`
pagePostsServedImpressionsOrganicUnique → migrate to `pageMediaView`
pageVideoViewsUnique → use `pageVideoViews` for non-unique 3-second views
Use `mediaView` / `pageMediaView` for reach. A Total Unique Media Views successor metric is planned. Still-supported fields such as `reactionsByType`, `videoViews`, `mediaView`, `pagePostEngagements`, `pageVideoViews`, and `pageVideoViewsPaid` are unaffected.
**YouTube transient failures now return HTTP 503/504 instead of 500:** Some YouTube upload failures previously surfacing as HTTP 500 (`code: 176`) now return HTTP 503 (`code: 454`) or HTTP 504 (`code: 453`). Both responses include `retryAvailable: true`. Customer integrations that filter on HTTP 500 to retry YouTube uploads should switch to filtering on the `retryAvailable` field on the response body. See [error codes](/docs/errors/errors-ayrshare) for details.
**Empty Analytics Returns Error 187:** Requesting [Social Analytics](/docs/apis/analytics/social) or [Post Analytics](/docs/apis/analytics/post) when no platforms return data now returns `{ "status": "error", "code": 187 }` instead of `{ "status": "success" }`. Update any client code that relies on the previous empty-success behavior.
**X/Twitter BYO Key Requirement:** All X/Twitter operations through Ayrshare will require your own API credentials. After linking your X account via OAuth, include 2 headers in every X/Twitter request: `X-Twitter-OAuth1-Api-Key` and `X-Twitter-OAuth1-Api-Secret`. Requests without valid credentials will be rejected. See the [X BYO Key Setup Guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for instructions.
**RSS-to-X Deprecated:** RSS auto-posting to X/Twitter will no longer be supported after March 31, 2026. RSS feeds run on a schedule without per-request credentials, which is incompatible with the BYO key model. RSS auto-posting to all other platforms is unaffected.
**X Account Activity Webhook Deprecated:** The X Account Activity webhook action (`accountActivity`) will no longer be available after March 31, 2026. This includes all real-time event notifications for linked X accounts (posts, mentions, DMs, likes, follows, blocks, etc.).
Starting November 14, 2025, Facebook will be deprecating the following fields for [GET analytics/social](/docs/apis/analytics/social):
pageFans
pageFansCity
pageFansLocale
pageFansCountry
pageFansAdds
pageFanAddsUnique
pageFanRemoves
pageFanRemovesUnique
pageImpressions → migrate to `pageMediaView`
pageImpressionsPaidUnique → migrate to `pageMediaViewIsFromAds`
pageImpressionsUnique
pageImpressionsViral
pageImpressionsViralUnique
pageImpressionsPaid → migrate to `pageMediaViewIsFromAds`
Starting November 14, 2025, Facebook will be deprecating the following fields for [GET analytics/post](/docs/apis/analytics/post):
impressions and impressionsFanPaidUnique → migrate to `mediaView`. Granular breakdowns available via `mediaViewIsFromAds` (ad-attributed views) and `mediaViewIsFromFollowers` (follower-attributed views).
postImpressionsUnique (Reels) → use `blueReelsPlayCount` for reel play count or `postVideoViewTime` for total watch time.
Starting September 1, 2025, the [get comments](/docs/apis/comments/get-comments) endpoint for
Instagram will no longer include the `text` field in reply objects. Use the `comment` field
instead to access reply content.
X (Twitter) [get comments](/docs/apis/comments/get-comments) endpoint will move the user public
metrics to the new `publicMetrics` object. The following fields will be moved from the top
level to the `publicMetrics` object:
followersCount
followingCount
tweetCount
listedCount
mediaCount
Facebook will be deprecating the following fields for [GET
analytics/social](/docs/apis/analytics/social):
pageVideoViews10S
pageVideoViews10SAutoplayed
pageVideoViews10SClickToPlay
pageVideoViews10SOrganic
pageVideoViews10SPaid
pageVideoViews10SRepeat
pageVideoViews10SUnique
YouTube has deprecated the setting allowed and blocked regions. You can still add in the
allowed and blocked regions to the post endpoint, but they will be ignored.
The following metrics for [Instagram post analytics](/docs/apis/analytics/post) will be deprecated:
REELS:
playsCount
clipsReplaysCount
igReelsAggregatedAllPlaysCount
FEED/STORY:
impressionsCount
The [history endpoint](/docs/apis/history/get-history) will enforce the cache for 1 minute if the `limit` is greater than the default value of 25.
The [get comments](/docs/apis/comments/get-comments) endpoint for TikTok will standardize field names
to match other social networks.
The field `replyList` will be renamed to `replies` and `profileImage` will be renamed to
`profileImageUrl`.
Both new field names are already available and can be used in your integration.
TikTok as the following updates:
[social analytics](/docs/apis/analytics/social) endpoint: The following changes are coming: •
The `durationAverage` field will be deprecated and removed. • Due to TikTok API
limitations, the fields `shareCountTotal`, `viewCountTotal` and `commentCountTotal` will
now only return totals for the past 60 days instead of all-time totals. • To start using
the 60-day totals now, add `period60Days: true` to your API request body Note: Using this
parameter will significantly improve response times.
[history platform](/docs/apis/history/history-platform) and [post
analytics](/docs/apis/analytics/post) endpoints: The undocumented fields `caption`, `comments`,
`shares`, `likes`, `shareUrl`, and `itemsId` will be removed - the fields `post`,
`commentsCount`, `sharesCount`, `likesCount`, `postUrl`, and `id` should be used instead.
The [/user](/docs/apis/user/profile-details) endpoint is changing how it reports API usage:
The `monthlyApiCalls` field will be expanded to count all API calls (posts, comments,
analytics, etc.).
For post-specific counts, use the new `monthlyPostCount` field.
The `monthlyApiCallsQuota` field will be deprecated and replaced by the new `monthlyPostQuota`
field.
Meta is deprecating the `videoViews` field on the Instagram [post analytics
endpoint](/docs/apis/analytics/post).
Additionally, the `emailContactsCount`, `getDirectionClicks`, `profileViewsCount`,
`textMessageClicks`, `websiteClicksCount`, and `phoneCallClicksCount` fields will be removed
from the Instagram [social analytics](/docs/apis/analytics/social) endpoint.
These fields will be removed on January 5, 2025.
For enhanced security, we will prevent Profile Keys from being used as API Keys. If you
attempt to use a Profile Key in place of the API Key, the system will return an error. [See
here](/docs/apis/overview#authorization) on how to properly use a Profile Key.
We've updated how errors for TikTok scheduled webhooks are reported. These errors will now
appear in the errors array, consistent with our error handling for other scheduled webhook
types. Note, the current top-level errors will still be returned, but we encourage use of the
errors array.
The history endpoint will now return responses as objects by default. The objResponse
parameter will be set to true automatically.
Get All History LinkedIn will return an array for the mediaUrls object. Previously an object
was returned if only one media item and an array if multiple media items. Now an array will
always be returned even if only a single media item. If you need the previous behavior, you
can use the `objResponse: false` query parameter.
The media endpoint will no longer return url\_1080. If you do need to resize an image, please
see the [resize endpoint](/docs/apis/media/resize).
**Update September 25, 2024**: Meta (Facebook) has released the fields deprecation, so the
removal of the fields are in effect. Please see the updated returned in [social
analytics](/docs/apis/analytics/social).
Facebook will be [deprecating several
fields](https://developers.facebook.com/docs/pages-api/changelog/). The [social analytics
endpoint](/docs/apis/analytics/social-by-id) will no longer return these fields after September 16,
2024\.
The [new linked shortener](/docs/apis/links/overview) system will replace the shortener endpoint,
which has been deprecated by Google. The new link shortener requires the add-on [Max
Pack](/docs/additional/maxpack).
Link shortening will be off (`false`) by default. To automatically shorten links use
`shortenLinks: true` in the post endpoint call, which uses the new[ link
endpoint](/docs/apis/links/overview).
Meta will be deprecating their Facebook Groups API. Please see the
[announcement](https://www.ayrshare.com/blog/facebook-removes-groups-api-access-impact-and-implications/).
Instagram has clarified the time period of the online followers data set. Please see here for
[details](/docs/apis/analytics/instagram-follower-count).
[Reply to comment with comment ID](/docs/apis/comments/reply-to-comment) default response will be
an object as listed in the docs instead of an Array. You may use the objResponse parameter set
to boolean `false` if wish to keep an Array response.
The [retry post endpoint](/docs/apis/post/retry-post) will return a status of "pending" instead of
"success" to better reflect the status of the retry.
The [API changes on scheduleDate and
createDate](/docs/whatsnew/upcoming-api-changes#changes-in-effect-june-17-2022) will be released.
The `/history/instagram` endpoint fields `caption`, `message`, `createdTime` and `timestamp`
fields were deprecated on April 1, 2023 and will be removed. Please use the `post` and
`created` fields.
The `/history/linkedin` endpoint field `mediaUrls` will be returned as an array instead of an
object to support multiple images. You can force the array being returned now by including the
LinkedIn query parameter `?multiMedia=true`. Please note, before December 1, 2023 the
`multiMedia` query parameter must be used to return media with multiple images. After December
1, 2023 multiple images will be returned by default.
The Scheduled Action TikTok webhook will have the String `platform` deprecated. Please use the
`platforms` array field as is done for other Scheduled Action webhooks.
The delete comment docs have been corrected to align with the correct return.
The TikTok commentId field will be replaced with the id field to align with the standard
comment delete format.
The Twitter delete comment return will no longer contain a `posts` array so the return aligns
with the standard comment delete format. The new return will be as follows:
The following [social analytics endpoint](/docs/apis/analytics/social) YouTube fields will be
returned as numeric instead of String values.
We have upgrade to Twitter's new API version 2. Twitter has deprecated a few fields in Version
2, which affects the /analytics/social and getAllHistory endpoints. These following fields
will still be returned until September 1, 2023, but will have a zero or empty string value.
We're excited to launch [TikTok direct publishing](/docs/apis/post/social-networks/tiktok), comment
management, and advanced analytics. Your users will no longer need to open their TikTok mobile
app to post and enter caption text. Now after sending via Ayrshare, the TikTok video and
caption is directly published.
We're also introducing adding, getting, and deleting TikTok comments + demographic analytics
data.
Your user will need to unlink and relink their TikTok account to enable direct publishing.
Existing connections will continue with the indirect method and require the TikTok mobile app
to publish.
Google Business Profile has changed the available social analytics data available. The new
fields available are the following. Previous fields will still be present, but with a zero
value and fully removed on March 17, 2023.
Get All Posts descriptions, text, message fields standardized to `post` field.
TikTok fields deprecated: `shareUrl`. Use `postUrl` instead.
For all history endpoints the fields `createdAt`, `createdTime`, and `timestamp` will be
replaced by the `created` field which returns the creation time in UTC format.
The `scheduleDate` field will no longer return an Object by a String containing the schedule
time in UTC format.
The undocumented `created_date` field on /history will be removed. Use `created` instead.
Analytics on a [Facebook post](/docs/apis/analytics/post) returns `reactions` as an object in the
following format.
History by default will return the last 20 posts. Up to 500 can be returned with the
`lastRecords` parameter.
# System Status
Source: https://www.ayrshare.com/docs/additional/status
Social network and Ayrshare API system status
See the current system status of the social networks and Ayrshare APIs.
Click the button below to view the status page and sign up for email alerts.
You can also stay informed by following us on X [@ayrshare](https://x.com/intent/user?screen_name=ayrshare) or [Bluesky](https://bsky.app/profile/ayrshare.com).
### API and Social Network Status
Call the status endpoint directly:
```
https://status.ayrshare.com/summary.json
```
# Do I need a credit card to start Ayrshare?
Source: https://www.ayrshare.com/docs/help-center/account/do_i_need_to_enter_a_credit_card_to_get_started
Starting the Launch Plan 28-day free trial requires a credit card or Stripe Link at checkout. Learn what the trial includes and how to cancel.
Yes. Starting the 28-day free trial of the [Launch Plan](/docs/multiple-users/business-launch-overview) requires a payment method. When you begin the trial from the [pricing page](https://www.ayrshare.com/pricing/), checkout collects a payment method (a credit card or Stripe Link) before the trial starts.
The trial is free for the full 28 days, and you can cancel anytime before it renews so you are not charged.
For ongoing use, the [Launch Plan](/docs/multiple-users/business-launch-overview) is the entry-tier multi-user plan (capped at 10 user profiles), and the full [Business Plan](/docs/multiple-users/business-plan-overview) is for scaling beyond that.
# How to change or cancel your Ayrshare subscription
Source: https://www.ayrshare.com/docs/help-center/account/how_do_i_change_or_cancel_my_subscription
Upgrade, downgrade, or cancel your Ayrshare subscription from the dashboard, and see which plan changes are self-serve versus support-only.
If you have a paid subscription, follow these steps to view your billing information or make changes to your subscription, such as adding a tax id, update billing information, or canceling your subscription:
1. Sign in to your [Ayrshare dashboard](https://app.ayrshare.com).
2. If you have a Business Plan or Launch Plan, make sure you are switched to your Primary Profile.
3. Navigate to the "Account" page.
4. On the "Account" page, you will find your billing details and options to modify or cancel your subscription.
**Note on Plan Upgrades**
Self-serve: On the free Basic Plan, you can upgrade to any
plan yourself from the [pricing page](https://www.ayrshare.com/pricing/).
Within the multi-user plans, a monthly Launch Plan can upgrade to the full
Business Plan directly from the [dashboard](https://app.ayrshare.com).
Support-only (for now): Moving from the paid Premium Plan
to a multi-user plan (the Launch Plan or Business Plan), or from an annual
Launch Plan to the Business Plan, isn't self-serve yet — for now, email
[support@ayrshare.com](mailto:support@ayrshare.com) and we'll handle the
migration. Your connected social accounts, API keys, and settings carry over.
Please note the following important information regarding cancellations:
**All Account Types**
Upon cancellation, all posts will be removed from the Ayrshare systems.
However, they will still remain visible on the respective social media
platforms where they were originally posted.
When you cancel your subscription, all information associated with your User
Profiles will be permanently deleted from our system.
**Business and Premium Plus Plans**
When you cancel your subscription, it will remain active until the end of
your current billing cycle.
You will be charged one final time on the cancellation date, as charges are
processed at the end of each billing period.
For more details, please refer to our [terms of
use](https://www.ayrshare.com/terms/).
**Delete Account**
Ayrshare accounts in good standing can be deleted by using the "Delete Account" button in the "Account" page.
# How to Reset Your Ayrshare Password | Help Center
Source: https://www.ayrshare.com/docs/help-center/account/how_do_i_reset_my_password
Reset your Ayrshare account password in a few quick steps. Follow this guide to request a reset link and regain access if you have forgotten your password.
If you registered with an email and forgot your password, you can change it by:
1. Go to the [Ayrshare Dashboard](https://app.ayrshare.com) and the login screen. You may need to first logout.
2. Click "Forgot Password".
3. Enter your email address.
4. An email from Ayrshare Support will be sent to your inbox with a link to reset your password. Please be sure to check your spam or other sorting folders if you don't see it.
If you registered with Google or Github, please change your password at their site.
# How Ayrshare Secures & Protects Your Account | API Docs
Source: https://www.ayrshare.com/docs/help-center/account/how_does_ayrshare_secure_and_protect_my_account
Learn how Ayrshare keeps your account and connected social media data secure, including the authentication and data-protection measures the platform uses.
## Security
We take security very seriously. You have full control over the connection between Ayrshare and your social media accounts.
All the data you upload to Ayrshare is securely stored on the secure-by-design global cloud infrastructure.
All stored data is encrypted in transit and [at
rest](https://cloud.google.com/docs/security/encryption/default-encryption). Every object's data
and metadata is encrypted under the [Advanced Encryption
Standard](https://en.wikipedia.org/wiki/Advanced_Encryption_Standard), and each encryption key
is itself encrypted with a regularly rotated set of master keys.
API traffic is protected in transit with **TLS 1.3**, including **post-quantum ready** encryption
via the `X25519MLKEM768` hybrid key exchange. This adds a quantum-safe
([ML-KEM](https://en.wikipedia.org/wiki/Kyber)) algorithm alongside classical ECDHE to defend
against "harvest now, decrypt later" attacks, and is fully backward compatible — connections
upgrade to post-quantum protection only when the client supports it.
All social networks keys are stored in a secure [secret
manager](https://cloud.google.com/secret-manager) vault.
Authentication is handled by Google with top-level security. Even we can't access your
passwords.
When you delete a social network linkage we delete all information about that network. If you
need to restore the link you need to re-authorize the network.
All payment information is handled by Stripe, who are fully PCI compliant.
We also maintain controls to restrict our employees' access to your data.
If you have any questions please [contact us](mailto:support@ayrshare.com).
## Data Encryption
The Google Cloud handles all data storage:
Google uses several layers of encryption to protect customer data at rest in Google Cloud
products.
Google Cloud encrypts all customer content stored at rest, without any action required from the
customer, using one or more encryption mechanisms.
Data for storage is split into chunks, and each chunk is encrypted with a unique data encryption
key. These data encryption keys are stored with the data, encrypted with ("wrapped" by) key
encryption keys that are exclusively stored and used inside Google's central Key Management
Service. Google's Key Management Service is redundant and globally distributed.
All data stored in Google Cloud is encrypted at the storage level using AES256, with the
exception of a small number of Persistent Disks created before 2015 that use AES128.
Google uses a common cryptographic library, Tink, which incorporates a FIPS 140-2 Level 1
validated module, BoringCrypto, to implement encryption consistently across almost all Google
Cloud products. Consistent use of a common library means that only a small team of
cryptographers needs to implement and maintain this tightly controlled and reviewed code.
## GDPR Data Protection Agreement
Please see our [DPA](https://www.ayrshare.com/data-processing-agreement/) for details on GDPR compliance.
## Privacy Policy & Terms of Service
For comprehensive information on data handling practices, please review our [Privacy Policy](https://www.ayrshare.com/privacy/) which details how we collect, use, and protect your information.
Additionally, our [Terms of Service](https://www.ayrshare.com/terms/) outlines the rules and guidelines governing the use of our platform and services.
## Post Verification
Ayrshare has a verification system that analyzes your posts for compliance with the social networks' guidelines. If there is an issue we'll let you know before sending the post. This helps prevent your social account from being locked or shadow banned.
See here more for information:
# How to view your invoices - Ayrshare API Documentation
Source: https://www.ayrshare.com/docs/help-center/account/how_to_view_your_invoices
Find and download your Ayrshare billing invoices from the dashboard. This guide shows where to view payment history and access invoices for your records.
You can access your invoices in the Dashboard Account page.
If you have a paid account, please go to the [dashboard](https://app.ayrshare.com), switch to your **Primary Profile** if you have a Business Plan or Launch Plan in the "User Profiles" page, and go to the "Account" page.
On the Account page click "View ->" to access your past invoices, see your upcoming invoice, update your tax ID for future invoices, or update your billing details.
Due to audit compliance requirements, our payment provider does not allow modifications to invoices that have already been completed and processed.
Any changes to your billing details will be reflected on your next invoice.
For information on how your invoice is calculated, please see the bottom of your invoice for details.
# Ayrshare Help Center: Guides, FAQs & Support | API Docs
Source: https://www.ayrshare.com/docs/help-center/overview
Browse the Ayrshare Help Center for setup guides, account and billing FAQs, troubleshooting tips, and answers to the most common social media API questions.
Welcome to the Ayrshare Help Center!
We've organized everything into three easy-to-navigate sections to help you find the information you need.
## Account
This section helps you understand everything about managing your Ayrshare account.
You'll find detailed information on subscription management, invoicing, and account set up.
## Product
This section helps you understand everything about getting the most value from the platform.
You'll find detailed information about how Ayrshare works, how to use the API, and how to get the most out of your social media.
## Technical Support
When you need hands-on help with implementation or troubleshooting, the technical support section provides practical solutions for common challenges.
This section is particularly valuable for developers and social media managers who are actively using the platform.
# Are Social Networks' Apps & APIs at Parity? | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/product/are_social_networks_native_apps_and_the_apis_at_parity
Understand how social network APIs compare with their native apps, which features reach parity, and what the differences mean when posting through Ayrshare.
The social networks do not generally allow the same feature set via their API as they do within their own native app. Often a feature will exist in the native app that is not available via the API.
The social networks are continually enhancing their offerings as is Ayrshare, so keep an eye out on our [latest releases](/docs/whatsnew/latest).
# Give Users Dashboard Access | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/help-center/product/can_i_give_my_users_the_dashboard
Learn whether you can give your own users access to the Ayrshare Dashboard, how user profiles and shared access work, and how to manage accounts for clients.
The Ayrshare Dashboard is designed to give you, the account owner, full access to your Launch Plan, Business Plan, or Enterprise Plan account and it is meant for your internal use only.
You should **never give your users or clients access to the dashboard** as it will give them the ability to make changes to your account.
Ayrshare is an API-first service and does not offer a white-label client facing GUI, except for [linking social accounts](/docs/multiple-users/api-integration-business).
You design and build the best front-end GUI solutions for your users and we'll handle all the social media complexity on the back-end.
If you need to give another user access to your account, you can invite them to be a [Team
Member](/docs/multiple-users/manage-user-profiles#invite-a-team-member) in your account. Team Members
have the ability to post on your behalf using the Ayrshare API. You can also restrict the team
member's access by [locking the Primary
Profile](/docs/multiple-users/manage-user-profiles#primary-profile-lock).
# Ayrshare SDK Packages | Help Documentation
Source: https://www.ayrshare.com/docs/help-center/product/do_you_have_sdk_packages_to_make_my_life_easier
See which official Ayrshare SDKs and packages are available, such as Node.js and Python, to integrate the social media API faster in your own tech stack.
We certainly do. We have [Node.js](/docs/packages-guides/nodejs) and [Python](/docs/packages-guides/python) packages available.
We also have a [Bubble.io](/docs/packages-guides/bubble) plugin, [Airtable](/docs/packages-guides/airtable), [Make](/docs/packages-guides/make), [Notion](/docs/packages-guides/notion), [Flutter](/docs/packages-guides/flutter), and [Retool](/docs/packages-guides/retool) guides.
# Does an API Affect Post Views or Engagement? | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/product/does_using_an_api_affect_post_views_or_engagement
Find out whether publishing through a social media API like Ayrshare affects your reach, views, or engagement compared with posting natively in each app.
You may wonder if using an API to publish content to social networks affects their post performance or engagement. Based on real-world social media usage of our clients and other companies, and third party research, we know that using an API versus a native social network app does not impact the performance of posts.
**Summary:** The social media networks do not penalize or favor one posting method over another,
so using the social network's native app, or via API in a third-party social media publishing
platform, or through direct API calls will not impact post performance.
### API Posting is the Standard for Professional and Business Content
Our analysis of client conversations and industry usage trends confirms that the vast majority of professional social media content is published via APIs.
We find that over 80% of small businesses and professional creators and just about 100% of medium and large businesses post their content to social networks via an API.
If a company or brand employs an agency or uses one of the [hundreds of social media management platforms](https://www.g2.com/categories/social-media-mgmt), then they are posting via API.
All third-party software designed for social media publishing integrates directly with the APIs provided by social networks, making API-based posting the industry standard.
Think of any major brand or company that you know. Chances are, they are using an API to publish their content to social networks.
### Third Party Research
There are multiple published data-driven studies \[1, 2, 3], which conclude that the method of posting - whether directly on the social network's native app, a third-party social media publishing platform, or through an API - does not impact performance including post views, reach, and engagement rates.
## Understanding Performance Variations
While the API itself doesn't affect post performance, you may notice differences between API and manual posts.
These engagement variations typically stem from several key factors rather than the posting method:
### Algorithms Change
What drives engagement on social networks today may not yield the same results tomorrow. Social media algorithms are dynamic, constantly adapting to various factors, and their exact workings cannot be fully reverse-engineered. Platforms frequently update their ranking criteria, impacting content visibility in unpredictable ways.
For instance, Facebook has alternately prioritized and deprioritized news content over time, meaning publishers posting news regularly may experience significant fluctuations in reach. Similarly, X modified its algorithm to downrank posts containing links to third-party sites, directly affecting the performance of link-based content.
### Algorithm Learning Patterns
Social media algorithms, particularly Meta's Facebook, also learn from your own historical post performance. If your past content has consistently performed well, the algorithm is more likely to prioritize similar posts in the future. However, any change in wording, tone, content type, AI involvement, or other factors can rapidly shift how favorably the algorithm ranks your posts. And always [avoid duplicate posts](/docs/testing/post-verification#duplicate-and-similar-posts) - the social networks will penalize you for posting the same content multiple times.
### Timing Sensitivity
Social media algorithms are highly sensitive to timing.
Even a *30-minute difference* during peak hours can significantly impact reach and engagement.
What might appear as an API-related issue is often a timing difference.
[Research shows](https://www.ayrshare.com/blog/best-times-frequency-to-post-on-social-media-networks/) that each social network has unique peak engagement windows, and your specific audience may have different active hours than the general population.
## What Actually Drives Social Media Engagement?
The performance success of your social media posts depends on three key factors:
### 1. Content Quality and Relevance
High-performing posts share common characteristics regardless of how they're published:
Unique content that resonates with your specific audience's interests.
Clear, compelling messaging that encourages interaction.
High-quality media assets (images, videos) that capture attention.
Strong calls-to-action that drive engagement.
### 2. Strategic Timing
Understanding and leveraging publishing timing is crucial for maximizing engagement:
Maintain consistency in your posting schedule to build regular engagement.
Consider time zones - post when your target audience is online. For example, using the [count of
Instagram followers
online](/docs/apis/analytics/instagram-follower-count#count-of-instagram-followers-online) to
determine the best time to post.
Test different posting times to identify your [optimal publishing
windows](https://www.ayrshare.com/blog/best-times-frequency-to-post-on-social-media-networks/).
Use analytics to track when your content performs best.
### 3. Optimal Posting Frequency
Finding the right cadence is crucial for maintaining engagement.
[Review our recommended posting limits](/docs/testing/post-verification#recommended-posting-limits) to optimize your strategy.
Over-posting can lead to audience fatigue and reduced engagement, while under-posting may result in decreased visibility.
The key is finding and maintaining a consistent schedule your audience can rely on.
## Optimizing Your API Posting Strategy
If you notice engagement differences between API and manual posts, try these optimization steps:
1. **Analyze Your Timing**
Track when your highest-performing posts occur and adjust your API posting schedule accordingly.
Compare posts made at the same time through different methods to isolate timing effects from posting method effects.
2. **Monitor Performance Metrics**
Keep detailed metrics of your posts, including:
Engagement rates across different posting times.
Reach and impression data.
Audience activity patterns.
Content type performance.
3. **Refine Your Approach**
Use the data you gather to continuously optimize your strategy.
If certain content types or posting times consistently perform better, adjust your API posting schedule to align with these insights.
## References
1.
Impact on Facebook Reach
2.
Third-Party Social Media Tools Study
3.
Analysis of Third-Party Posting Tools
# How to Submit a Feature Request | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/help-center/product/how_do_i_submit_a_feature_request
Learn how to submit a feature request to the Ayrshare team, where to share product feedback, and how new social media API features get reviewed and prioritized.
Do you have an idea for a feature or capability that's not currently available on our platform? We'd love to hear from you! Many of our features were developed based on feedback from users like you.
Use our [feature request form](https://www.ayrshare.com/feature-request) to share your suggestions.
Our team will review all recommendations. To see if your suggestion is implemented, keep an eye on our [What's New at Ayrshare](https://www.ayrshare.com) page.
# How do you pronounce Ayrshare? - Ayrshare API Documentation
Source: https://www.ayrshare.com/docs/help-center/product/how_do_you_pronounce_ayrshare
Ayrshare is pronounced "air-share." Learn the origin of the name and the correct way to say it when talking about the Ayrshare social media API.
Ayrshare is pronounced as "Air Share". Sharing over the social air!
# How Does Ayrshare Integrate With Social Networks?
Source: https://www.ayrshare.com/docs/help-center/product/how_does_ayrshare_integrate_with_the_social_networks
Learn how Ayrshare connects to social networks through their official APIs, how authentication works, and what that means for posting and analytics at scale.
Ayrshare integrates directly with each social network's official APIs and partnership programs.
This ensures our platform delivers the most reliable, secure, and current social media management features available, all while maintaining compliance with each network's policies and best practices.
For more information on security and compliance, please see our [security](/docs/help-center/account/how_does_ayrshare_secure_and_protect_my_account) page.
# How Many Posts & API Calls Can I Make? | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/product/how_many_posts_and_api_calls_can_i_make
Understand how Ayrshare's posting and API call limits work across plans, how usage is counted, and how to pick the right plan for your social media volume.
Ayrshare generally does not impose limits on posting beyond the social networks' requirements. For example, LinkedIn limits 150 posts per day and Instagram 50 posts every 24 hours.
We recommend limiting daily posts to maximize views and engagement.
Please see our [recommended posting limits](https://ayrshare.mintlify.app/testing/post-verification#recommended-posting-limits).
All posts and API calls are subject to Ayrshare's fair use policy to prevent abuse of the social networks' services. Please review the [terms of service](https://www.ayrshare.com/terms/) and [rate limits](/docs/errors/errors-http#429-rate-limit) for details.
# How Many Social Accounts Can I Connect? | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/product/how_many_social_accounts_can_i_connect
Learn how many social media accounts you can connect to Ayrshare, how user profiles let you scale to many accounts, and which plans support the most accounts.
Each user (also known as a user profile) in Ayrshare has one set of social accounts, e.g. one connection to each of our 13 available social networks.
For example, a user can have one Bluesky, Facebook Page, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Telegram, Threads, TikTok, Twitter, and YouTube connection for a total of 13 connections.
A Premium account is considered one user with one set of social accounts.
If you have multiple users, see the [Launch Plan](/docs/multiple-users/business-launch-overview) (entry tier, up to 10 user profiles) or [Business Plan](https://www.ayrshare.com/business-plan-for-multiple-users/) for larger scale.
# Premium Plan vs. Business Plan: Which to Choose? | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/product/premium_plan_vs_business_plan_which_fits_your_social_media_needs
Compare Ayrshare's Premium and Business plans across features, user profiles, and API access to pick the one that fits your posting and integration needs.
Ayrshare offers different plans to cater to various social media management needs. The **Premium**, **Launch**, and **Business** plans each serve distinct user groups. Here's a breakdown of who these plans are best suited for:
## Ayrshare Premium Plan
Ideal for: Individuals or companies managing their own social media
presence.
Use case: Publishing posts and obtaining analytics for their own social
accounts.
Best for: Those who directly manage a single set of social media accounts.
## Ayrshare Launch Plan
Ideal for: Early-stage SaaS platforms, small agencies, or pilots that need
multi-user APIs but only manage a small number of client or end-user
accounts.
Use case: Same as the Business plan: letting your users securely connect
their social accounts so you can post, fetch analytics, and manage comments
and DMs on their behalf, capped at 10 User Profiles.
Best for: Teams launching multi-user social functionality who want the full
Business API at a lower starting price, with a 28-day free trial.
## Ayrshare Business Plan
Ideal for: Companies, agencies, or platforms that need to manage social
media on behalf of their users or clients at scale.
Use case: Allowing users to securely connect their social accounts, then
managing those accounts by: 1. Pushing posts 2. Obtaining analytics 3.
Managing comments 4. Handling direct messages (DMs)
Best for: Platforms, agencies, or businesses operating many external social
media accounts at scale, beyond the 10-profile cap of the Launch Plan.
## Quick Comparison
| | Premium | Launch | Business |
| --------------------------------------------- | ------- | -------- | ------------ |
| Manage your own social accounts | Yes | Yes | Yes |
| Manage your users' / clients' social accounts | No | Yes | Yes |
| User Profile cap | N/A | Up to 10 | 30+ (scales) |
| Max Pack add-on | Yes | Yes | Yes |
For current pricing, see the [Ayrshare pricing page](https://www.ayrshare.com/pricing/).
Learn more:
# What Features Does Ayrshare Offer? | Social Media API
Source: https://www.ayrshare.com/docs/help-center/product/what_features_does_ayrshare_offer
Discover Ayrshare's core features: multi-platform posting, scheduling, analytics, auto-hashtags, media management, and a social media API built for developers.
The key Ayrshare API features are:
Manage all your users' social accounts right from your product. Post, Auto
Schedule, and Analytics with the Business Plan or Launch Plan via
the API or the Ayrshare Dashboard.
Create a post with text, images, or videos and send it immediately or
schedule it for a future date or time.
Simply send the post ID to the delete endpoint to delete your post from all
of the social media networks.
Get history and status of the posts you sent via Ayrshare, with detailed
metadata for each post.
Get advanced analytics for your users and post links including likes,
retweets, and clicks.
Manage your user's direct messages, via the Messages API, to those who
contact them across their preferred channels, allowing them to provide a
seamless customer experience.
Upload your image or videos directly to Ayrshare and get a URL to post with.
No need for a separate image/video hosting service.
Submit a URL and get a short URL to save characters in your posts.
Retrieve, post, and manage comments on a post. Never miss an opportunity to
increase engagement.
Automatically add hashtags to your posts based on the most relevant key
words. Takes into account real-time hashtag popularity.
Retrieve, reply, or delete replies of reviews on Google Business Profile and
Facebook pages.
Save your team's time by connecting with one of the Ayrshare integrations,
such as Notion, Airtable, Make, Retool, and Bubble.
Create or rewrite social posts, transcribe videos, and more using AI.
Register webhooks to receive asynchronous updates on events including scheduled posts, messages, and social account linking.
# What Is Ayrshare? The Social Media API Explained
Source: https://www.ayrshare.com/docs/help-center/product/what_is_ayrshare_and_the_social_media_api
Ayrshare is a social media API that lets developers and businesses post, schedule, and analyze content across all major networks from one integration.
Take a look at this quick video on how Ayrshare integrates with your platform and can power your social media via an API.
# What Is the Basic Plan Post Limit? | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/product/what_is_the_basic_plan_post_limit
Learn how the post limit works on Ayrshare's Basic plan, how posts are counted across platforms, and when to upgrade for higher social media posting volume.
The Basic Plan, which included 20 posts per month, is no longer available to new sign-ups. If you are already on the Basic Plan, your existing plan continues. Check your [dashboard](https://app.ayrshare.com) for your current post quota.
For new accounts, the entry tiers are the **Premium Plan** for single-user use and **Launch Plan** for multi-user use (capped at 10 user profiles). To try Ayrshare for free, start a 28-day free trial of the Launch Plan on the [pricing page](https://www.ayrshare.com/pricing/).
# What Kind of Support Does Ayrshare Offer? | Help Docs
Source: https://www.ayrshare.com/docs/help-center/product/what_kind_of_support_does_ayrshare_offer
See the support options Ayrshare offers, including documentation, help center, email, and developer resources to help you build and troubleshoot the API.
Ayrshare offers comprehensive support via the web chat interface and [email](mailto:support@ayrshare.com).
Most support tickets are quickly addressed within hours, general expectations for ticket responses from the support team are as follows:
| Plan | Support Response Times |
| :--------- | :--------------------- |
| Enterprise | 2 business days |
| Business | 5 business days |
| Premium | 10 business days |
For security, only [registered team members](/docs/multiple-users/manage-user-profiles#team-members-contacting-support) may contact support on behalf of a business.
If your business requires a higher level of support, please contact your account representative to learn more about the Enterprise plans.
# What Social Networks Does Ayrshare Support? | Docs
Source: https://www.ayrshare.com/docs/help-center/product/what_social_networks_are_supported
Ayrshare supports Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Telegram, TikTok, X (Twitter), and YouTube.
Ayrshare supports twelve social networks: Bluesky, Facebook, Google Business Profile, Instagram, LinkedIn, Pinterest, Reddit, Snapchat, Telegram, Threads, TikTok, X/Twitter, and YouTube.
# Why Use Ayrshare Over Other Social Scheduling Tools?
Source: https://www.ayrshare.com/docs/help-center/product/why_should_i_use_ayrshare_rather_than_the_other_social_scheduling_tools
Learn what sets Ayrshare apart from other social media scheduling tools: an API-first approach, multi-account scaling, and developer-friendly integration.
There are dozens of great products out there like Buffer, Hootsuite, etc. that help you manually manage and post to your social media accounts via a GUI.
However, only Ayrshare is focused on giving developers an API-first solution. The Ayrshare API gives you the power to programmatically post or schedule content, get analytics, or create comments directly from your platform or website.
# Automation DM Sent but Not Delivered | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/automation_dm_sent_but_not_delivered
Why an Instagram automation can report a DM as sent while the recipient never receives it — the recipient's Message requests setting, private-reply mechanics, and what you can and cannot do about it.
If a [comment-triggered automation](/docs/apis/automations/overview) reports an activity `status: "sent"` but the person who commented says they never got the DM, this is almost always the recipient's Instagram privacy settings — **not** a bug in your automation or in Ayrshare.
**`sent` means Instagram accepted the message, not that it was delivered.** Instagram does not expose message delivery on any API surface. Ayrshare marks a `send_dm` action `sent` the instant Instagram accepts it; whether it actually reaches the recipient is decided by settings Ayrshare cannot read or change.
## The recipient's "Message requests" setting decides delivery
Every Instagram user controls who may send them a message request under **Settings and activity → Messages and story replies → Message requests**. The options are roughly "Everyone", "Your followers", and "No one".
When your automation sends a DM to someone who has restricted message requests, Meta accepts the request, returns a **success response with a message ID**, and then **silently drops the message**. There is no error, no failure webhook, and no delivery/read signal — the drop is invisible at every API layer. Meta knows the message is undeliverable (its own app UI shows *"This account can't receive your message because they don't allow new message requests from everyone"*), but it does not expose that on the API.
| Recipient's Message requests setting | What happens |
| ------------------------------------------------------------- | ---------------------------------------------------------------------- |
| Everyone | Delivered — arrives as a **message request** the recipient must accept |
| Your followers (and the recipient does not follow the sender) | Accepted by Meta, then silently dropped |
| No one | Accepted by Meta, then silently dropped |
## An existing conversation overrides the setting
If the sender and recipient **already have a message thread** (for example, the recipient has DMed the account before), that existing conversation overrides the Message requests setting and the automation DM is delivered into the existing thread rather than as a new request. This is why the same automation can reach some commenters and not others, and why a recipient who messages the account first will then reliably receive automation DMs.
## How to recognize this
The activity row shows status: "sent" with no errorDetails.
The recipient reports no DM (and it is not sitting in their message-requests folder).
It is intermittent across recipients — some receive the DM, others do not — with no pattern in your configuration.
This is a delivery outcome, not a failure state, so it will never appear as `failed`. A `failed` row means Instagram *rejected* the send and the reason is on `actionResults[].errorDetails` — that is a different situation (see [error codes](/docs/errors/errors-ayrshare)).
## What you can do
There is **no programmatic workaround** — no API, scope, or send shape can bypass a recipient's Message requests setting. What you can do:
Set expectations up front: a comment-triggered DM only reaches people whose Instagram settings allow message requests, or who already have a conversation with your account.
Encourage commenters to DM your account (or turn on message requests) if they want the follow-up — an inbound message opens the thread permanently.
Consider a public reply to the comment as a fallback path for reaching everyone.
## How comment-triggered DMs are sent (private replies)
Comment-triggered automations deliver the DM through Instagram **private replies**, anchored to the comment itself. This is what lets the automation message a commenter you have never messaged before. The mechanics — and their limits — are worth knowing:
Comment-anchored 7-day window. The reply must be sent within 7 days of the comment. After that the window closes and the send fails with code: 491.
One reply per comment, ever. Instagram allows only a single private reply per comment. A second attempt fails with code: 491 — Instagram reports "already replied" through the same shared error it uses for a closed window, so check errorDetails for which it was.
Arrives as a message request. Even a successfully delivered private reply lands in the recipient's message-requests folder and must be accepted — unless a conversation already exists.
Delivery still depends on the recipient's settings. Private replies remove the "must have messaged first" requirement, but they do not override the recipient's Message requests setting, which is the limitation described above.
# Social Media Character Limits by Platform | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/character_limits
Reference post character limits for each social network: Facebook, Instagram, X, LinkedIn, TikTok, and more, when publishing through the Ayrshare API.
# Social Media Character Limits Reference
This comprehensive guide provides character limits for all supported social media platforms when posting through Ayrshare. Understanding these limits helps ensure your content is properly formatted and doesn't get truncated or rejected.
## Platform-Specific Character Limits
### Bluesky Character Limits
| Property | Description |
| -------- | ---------------------- |
| post | 300 characters maximum |
See [Bluesky Publishing Options](/docs/apis/post/social-networks/bluesky) for more information.
### Facebook Character Limits
| Property | Description |
| -------- | -------------------------------------------------------- |
| post | 63,206 characters maximum |
| title | reels title - 255 characters maximum (truncated if over) |
See [Facebook Publishing Options](/docs/apis/post/social-networks/facebook) for more information.
### Google Business Profile Character Limits
| Property | Description |
| ----------- | ------------------------ |
| post | 1,500 characters maximum |
| Event Title | 58 characters maximum |
| Coupon Code | 58 characters maximum |
See [Google Business Profile Publishing Options](/docs/apis/post/social-networks/google) for more information.
### Instagram Character Limits
| Property | Description |
| -------- | ---------------------------------- |
| post | 2,200 characters maximum |
| altText | 1,000 characters maximum per image |
| comment | 2,196 characters maximum |
See [Instagram Publishing Options](/docs/apis/post/social-networks/instagram) for more information.
### LinkedIn Character Limits
| Property | Description |
| -------- | ------------------------ |
| post | 3,000 characters maximum |
| title | 400 characters maximum |
| comment | 1,250 characters maximum |
See [LinkedIn Publishing Options](/docs/apis/post/social-networks/linkedin) for more information.
### Pinterest Character Limits
| Property | Description |
| -------- | ------------------------ |
| post | 500 characters maximum |
| title | 100 characters maximum |
| link | 2,048 characters maximum |
| altText | 500 characters maximum |
See [Pinterest Publishing Options](/docs/apis/post/social-networks/pinterest) for more information.
### Reddit Character Limits
| Property | Description |
| -------- | ------------------------- |
| post | 5,000 characters maximum |
| title | 300 characters maximum |
| comment | 10,000 characters maximum |
See [Reddit Publishing Options](/docs/apis/post/social-networks/reddit) for more information.
### Snapchat Character Limits
| Property | Description |
| -------- | ------------------------------------------------------ |
| post | 500 characters maximum |
| post | spotlight - 160 characters maximum (truncated if over) |
See [Snapchat Publishing Options](/docs/apis/post/social-networks/snapchat) for more information.
### Telegram Character Limits
| Property | Description |
| -------- | -------------------------------------------- |
| post | 1,024 characters maximum (truncated if over) |
See [Telegram Publishing Options](/docs/apis/post/social-networks/telegram) for more information.
### Threads Character Limits
| Property | Description |
| -------- | ---------------------- |
| post | 500 characters maximum |
See [Threads Publishing Options](/docs/apis/post/social-networks/threads) for more information.
### TikTok Character Limits
| Property | Description |
| -------- | ------------------------ |
| post | 2,200 characters maximum |
See [TikTok Publishing Options](/docs/apis/post/social-networks/tiktok) for more information.
### X/Twitter Character Limits
| Property | Description |
| ------------ | ------------------------------------------------------------------------------ |
| post | 280 characters maximum |
| post | 25,000 characters maximum (Premium X accounts such as Premium or Premium Plus) |
| altText | 1,000 characters maximum per image |
| subTitleName | 150 characters maximum |
See [X/Twitter Publishing Options](/docs/apis/post/social-networks/x-twitter) for more information.
### YouTube Character Limits
| Property | Description |
| ----------------------------- | ---------------------------------------- |
| post | 5,000 characters maximum |
| youTubeOptions > title | 100 characters maximum |
| youTubeOptions > tags | 500 characters total, 2+ characters each |
| youTubeOptions > subTitleName | 150 characters maximum |
See [YouTube Publishing Options](/docs/apis/post/social-networks/youtube) for more information.
## API Considerations
When using the Ayrshare API:
* Posts exceeding character limits will be rejected with an error
* Some platforms may truncate content rather than reject it (Telegram, Snapchat Spotlight)
* Consider using `shortenLinks: true` for platforms with tight limits
## Updates and Changes
Social media platforms do update their character limits. This guide is current as of the last update, but we recommend:
* Using our API error responses to identify limit issues
* Checking the Ayrshare [Latest Updates page](/docs/whatsnew/latest) for platform updates
# Choosing Between Different Meta Accounts | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/choosing_different_meta_accounts
Learn how to select the correct Facebook or Instagram (Meta) account when linking to Ayrshare, and how to fix issues when multiple Meta accounts appear.
## How to Link a Different Meta Account to Ayrshare
If you have previously linked a Meta account, such as Facebook or Instagram, to Ayrshare, you may notice that Facebook will not ask you to login again.
If you want to link a different Instagram or Facebook account to Ayrshare, you can do so by logging out of Facebook/Instagram in the browser - just open facebook.com/instagram.com in a different tab and logout - and then relinking with Ayrshare again.
Meta will ask you to login again and you can then choose the account you want to link to Ayrshare.
This also works for choosing a different X (Twitter) or TikTok account to link to Ayrshare - just
log out of the social network in a different browser tab and then relink with Ayrshare.
# Commenting on Other Users' Social Posts | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/commenting_on_another_user_post
Learn how to post comments on other users' social media posts with the Ayrshare API, including the supported platforms and the parameters you'll need.
Social networks have restrictions on commenting functionality to prevent spam and abuse. Here's what you need to know:
1. You can only comment on posts that belong to your own social media accounts/pages. These can be posts you or others published on your account/page.
2. You cannot comment on posts from on users' accounts or pages. Again, the social networks have this restriction to prevent spam and abuse.
3. This is a limitation enforced by the social networks themselves (especially Meta platforms like Facebook and Instagram) through their official APIs.
4. Even if you try to cross-post a comment, e.g. on Instagram, it will only appear under your own posts, not other users' posts.
These restrictions are security measures implemented by social networks to prevent automated spam commenting through APIs.
Please see the [Comments API documentation](/docs/apis/comments/overview) for more information on how to comment on a post.
# How to Deal With Duplicate Posts | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/help-center/technical-support/dealing_with_duplicate_posts
Find out why duplicate social media posts happen when using an API and how to prevent and resolve them with Ayrshare's duplicate-post safeguards.
If you see duplicate posts and there are two post IDs, the likely cause is you've accidentally made two of the same API post requests.
Our system checks for duplicate posts, so the second post should be blocked.
However, if the posts are made at the exact same time, both may be published.
If you need to find the duplicate post, you can use the [details in the publish post response](/docs/help-center/technical-support/dealing_with_duplicate_posts#find-the-duplicate-post).
There are a few things you can do to verify that two post calls were made.
## Check Your System Logs
The best place to start is your own system logs and code.
Look for the API post request and response in the logs to see if there are two requests.
Verify that the post request doesn't have unintended automatics retries. For example, if the
request took over 30 seconds to respond, the system automatically retried the request -
sometimes larger images or videos take longer for the social platforms to process.
## Use the Ayrshare Dashboard
Go to the Ayrshare Dashboard and switch to the relevant User Profile. Next, search for the post IDs in the search box. Only the last 100 posts are loaded, so you may need to load more to find the posts IDs.
Open the *API Request & Response* accordion and in the Request section is the request create time.
Compare the times of the two posts to see if they were sent at different moments.
The different Post IDs is also an indication two different API requests were made.
These steps should help you in determining the cause of the duplicate posts. Please let us know if you need any help on this.
## Find the Duplicate Post
The publish post response contains the details of the found duplicate post.
For example:
```json Duplicate Post Details theme={"system"}
{
"errors": [
{
"action": "post",
"status": "error",
"code": 137,
"message": "Duplicate or similar content posted within the same two day period. The social networks prohibit duplicate content and ban accounts that do not comply. https://www.ayrshare.com/docs/help-center/technical-support/dealing_with_duplicate_posts#dealing-with-duplicate-posts",
"details": "Duplicate found in user profile: John Profile, post id: pRo7vkM1vYVMJu8sJa, and refId: ace4bcd07336582e2fd9",
"platform": "facebook"
}
]
}
```
You can use the `post id` and `refId` to find the duplicate post in the Ayrshare Dashboard - be sure to switch to the User Profile first - or using the [history API endpoint](/docs/apis/history/get-history-id).
## More Information on Duplicate Posts
See [Duplicate and Similar Posts](/docs/testing/post-verification#duplicate-and-similar-posts) for more information.
# Fix Errors Linking Google Business Profile | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/errors_linking_google_business_profile
Troubleshoot common errors when connecting your Google Business Profile to Ayrshare, including permission, location, and authorization issues, with clear fixes.
You must [claim your Google Business Profile](https://support.google.com/business/answer/2911778) page before linking it with Ayrshare.
Be sure to choose the Google account that is an admin of your Google Business Profile page during link authorization.
See our article to learn more about [setting up a Google Business Profile](https://www.ayrshare.com/blog/google-my-business-what-is-gmb-why-you-need-it-and-how-to-use-it/).
# Troubleshooting API Request Errors | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/help-center/technical-support/errors_making_requests_with_the_api
Diagnose and fix common errors when making requests to the Ayrshare API, including authentication, parameters, and response codes, with practical steps.
A few things to check to verify you have all the required information to successfully post, or call any API endpoint.
1. Verify you are sending the API\*KEY, found in the Ayrshare GUI dashboard under API Dashboard, in the header as an [Authorization Bearer](/docs/apis/overview#authorization) token. Also the proper [Content Type](/docs/apis/overview#content-type) must be set.
2. For POST calls, validate properly formatted JSON is being sent in the body. Online tools can assist such as [https://jsonlint.com/](https://jsonlint.com/)
3. If sending media via an external URL, make sure the proper [MIME type](https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Common_types) is set for the image or video.
4. Review the required endpoint's required parameters to be sure they are included and have the proper format.
# How to Fix the "Facebook Login Disabled" Error | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_login_disabled
Learn what causes the "Facebook Login Disabled" error in Ayrshare and how to re-enable login and reconnect your Facebook account so posting works again.
If you try to link your Facebook or Instagram account on an Android device and receive:
"For your account security, logging in to Facebook from an embedded browser is disabled. To continue, download and log in to the Facebook app on your device and try again."
You will need to allow external links in your Facebook app.
Fix the issue by opening your Android Facebook app, going to settings, tap on “Media”, and then enable “Links open externally”. You can then try linking your Facebook or Instagram account once more.
Unfortunately, there is currently no work-around for iOS devices.
# Facebook or Instagram Account Restricted? | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_or_instagram_account_restricted
Find out why your Facebook or Instagram account may be restricted, how it affects posting through Ayrshare, and the steps to resolve the restriction.
## Why Does Facebook Suspend Accounts or report the Content Violated Community Standards
Facebook suspends accounts or marks posts as violating their community standards when their security AI is triggered. The reasons are often unknown, but can occur when the user changes their password at Facebook, posts a message manually to their feed or Facebook Messenger, or the security AI sees suspicious activity on the Facebook account. Sometimes posts are flagged by Facebook even when the post is seemingly innocuous, but the security AI sees the post as spam or other users have flagged similar post.
These issues typically occur with posts that did not go through Ayrshare.
Please see [Facebook's Post Blocking Guide](https://www.facebook.com/help/116393198446749).
Steps that we recommend:
1. Review your recent posts to ensure they aren't spammy, political, repetitive, or posted too frequently.
2. Double-check any URLs you've included, as Facebook often flags posts with suspicious links. For example, if you are using your own link shortener that might cause issues.
3. Don't include HTML in the post.
4. Check your server logs for any error messages returned from /post.
5. Have the user log into Facebook and check if Facebook asks them to take any actions or provide more information. If everything looks ok, the user can try relinking Facebook with Ayrshare and posting again.
6. If the user was suspended by Ayrshare, [re-activate the user profile](/docs/multiple-users/manage-user-profiles#reactivate-a-suspended-user-profile) in the Ayrshare Dashboard.
## Facebook Message: "We limit how often you can post, comment or do other things in a given amount of time in order to help protect the community from spam. You can try again later."
If you encounter at facebook.com the message "*We limit how often you can post, comment or do other things in a given amount of time in order to help protect the community from spam. You can try again later*" this might mean you posted or liked too frequently, invited too many people to a Page, messaged too frequently on Facebook Messenger, or Facebook made a mistake.
[Facebook flagged your account](https://www.facebook.com/help/116393198446749?helpref=faq_content) a potential spammer or a bot. While there is no guaranteed remedy, we recommend decreasing your post, commenting, liking, and messaging frequency for *several days*.
See our [recommended social posting limits.](/docs/testing/post-verification#recommended-posting-limits)
## Instagram Account Restricted
Your Instagram account may be marked as inactive, checkpointed, or restricted by Meta. This can occur for various reasons such as a security issue occurred or Instagram needs you to take an action in the app. Please sign in to the Instagram app and complete any actions the app requires to re-enable the account.
If there is no action to take in the Instagram app, the issue may be resolved if you set the "minimum age restriction" to off or by country in the Instagram app settings. Please see here for detailed instructions on how to [change the Instagram minimum age restrictions](https://help.instagram.com/853772598370828).
***
Security violations from the social networks should be taken seriously and resolved as soon as possible.
Repeated violations may result in a permanent suspension of the social media account or Ayrshare account.
Social networks and their partners enforce these measures to maintain a safe experience for all users and a healthy social media ecosystem.
# Fix Facebook/Instagram "Unsupported Request" Error | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_or_instagram_error_unsupported_request
Resolve the Facebook or Instagram "Unsupported Request" error in Ayrshare with steps to fix the permissions, tokens, and account settings behind the message.
If you receive an Instagram or Facebook error: "Unsupported request - method type: post" this could be due to a bug at Facebook. A possible fix is enabling the Facebook **Off-Facebook Activity** feature and then reconnect Ayrshare with Facebook.
The Off-Facebook permission allows other websites to publish on your or your users' behalf.
Please see the following steps to correct.
1. On a desktop login to [facebook.com.](http://facebook.com/) Mobile not supported.
2. Review your "Future Off-Facebook Activity" by going [here](https://www.facebook.com/off_facebook_activity) and selecting "**Manage your off-facebook activity**". If you're already connected you'll only see "**Disconnect future activity**".
3. Verify off-facebook is toggled **on.** If off, please turn on. Otherwise, if on please toggle off and then back on.
4. After toggling off-facebook to **on**, reset your Facebook connection and relink with Ayrshare: [Trouble Posting to Facebook](/docs/help-center/technical-support/facebook_posting_issues).
5. When relinking, be sure **all** permissions are granted.
# Fix Facebook or Instagram Linking Issues | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_or_instagram_linking_issues
Troubleshoot problems linking your Facebook or Instagram account to Ayrshare, from permission errors to missing pages, with step-by-step solutions.
If you're having issues linking your Facebook or Instagram accounts, a few potential issues might be the cause.
## Top Linking Issues
### 400: Session Invalid
You may receive this error when attempting to link your Instagram account using
direct login. This occurs because your Instagram account has already been
authorized with the Ayrshare app. Please follow these instructions:
Navigate to your Instagram settings in your mobile app or from [Settings](https://www.instagram.com/accounts/edit/) in your browser.
Click **Website permissions** under **Your app and media**.
Click on **Apps and websites**.
Click the **Remove** button next to the Ayrshare app.
Relink your Instagram account in the Ayrshare dashboard or from the social linking page via [JWT URL](/docs/apis/profiles/generate-jwt).
If all else fails and you are on a business account, you can [turn off Instagram Login](/docs/multiple-users/manage-user-profiles#instagram-login) and use Facebook Page authentication instead.
### Recently Created Accounts
You might get this error on recently created Facebook or Instagram accounts:
*Ayrshare could not be linked to Facebook. Maybe you're out of network connection or we couldn't establish a connection to our server. Check your connection and try again later.*
Facebook and Instagram try to prevent spam and new accounts are considered higher risk. We suggest only linking Facebook and Instagram accounts that are at least **7 days old**.
See [New Account Error](/docs/help-center/technical-support/facebook_or_instagram_linking_issues#facebook-or-instagram-account-is-new) for more information.
### No Facebook Pages / Zero Pages
As mentioned above, Facebook Pages must be at least 7 days old.
Only Facebook Business Pages will show. Facebook does not allow Personal Pages to be linked.
Verify you are the admin of the Pages you want to connect.
Please see here for additional information on [missing Facebook
Pages](/docs/help-center/technical-support/facebook_or_instagram_linking_issues#missing-facebook-pages).
### Grant All Permissions
Grant all permissions Ayrshare requests during authorization. Removing permissions may cause unintended issues at the social networks or Ayrshare's APIs. Also allow pop-ups in your browser.
### Facebook Page Admin Rights
Your personal Facebook profile must have an admin role for that Page you wish to connect,
including when [connecting an Instagram account](/docs/dashboard/connect-social-accounts/instagram).
Admin rights through inheritance from a parent Page cannot be connected. You may verify by going
to facebook.com => settings -> Page Roles and seeing the section labeled "Admin (inherited from
parent Page)".
If you have the correct permission, but do not see the Page listed when connecting either
Facebook or Instagram, it means the permissions have not been fully granted.
Switching from Business or Creator Profiles to Personal unlinks the Facebook Page connection.
The Facebook-Instagram connection must be
[re-established](/docs/dashboard/connect-social-accounts/instagram).
Verify that your Instagram account is a [Business or Creator
profile](/docs/help-center/technical-support/facebook_or_instagram_linking_issues#check-if-your-account-is-instagram-business-or-creator).
If your Instagram account is a Creator or Business account, but when linking Ayrshare you
receive an error saying your account isn't a Creator or Business, try switching your Instagram
back to **Personal** and then back to **Creator** or **Business**. This often resets the account
type and allows you to link Ayrshare.
### Linking Instagram Must Be a Business or Creator Profile
Linking Instagram requires selecting a Facebook Page that is [linked](/docs/dashboard/connect-social-accounts/instagram) to an Instagram Account. The Instagram account must be a Business or Creator Profile.
[Verify](/docs/apis/post/social-networks/instagram#instagram-business-or-creator-account) that the
Instagram Account is a [Business or Creator
Profile](/docs/help-center/technical-support/facebook_or_instagram_linking_issues#check-if-your-account-is-instagram-business-or-creator).
Not being a Business or Creator Profile is usually the issue. Instagram does not allow Personal
Profiles to be linked.
[Verify](/docs/help-center/technical-support/instagram_posting_issues#1-verify-your-instagram-business-account-is-connected-to-a-facebook-page)
the Facebook Page is linked to the correct Instagram Account. This is the second most common
issue.
If all else fails, start over by [removing the Facebook
permissions](/docs/help-center/technical-support/facebook_posting_issues#still-having-issue-with-facebook-permissions).
If you're still having issues you can [reset all Facebook
permissions](/docs/help-center/technical-support/facebook_posting_issues#still-having-issue-with-facebook-permissions).
## Request to Reverify Facebook Login
Facebook is asking you to verify your account login again.
Open a new tab/window in your browser and go to facebook.com. Log out of Facebook and login once more. If you're asked to verify your account or a CAPTCHA question, please complete it.
Head back to the Ayrshare dashboard Social Accounts page, refresh your page, and try linking Facebook once more.
Please be sure you have created a Facebook Page associated with your Facebook account. This is required to link to Facebook and you will be asked to select the Page during authorization.
## Facebook or Instagram Account is New
If you receive the error: "Could not link Ayrshare to Facebook. You may not be connected to the network or we could not establish a connection with our server. Check your connection and try again later."
The cause might be you're using a newly created Facebook or Instagram account. Facebook states that "*There is a 60-minute delay before new accounts can log in to any applications*".
Please wait 60 minutes and try again. However, we've seen new Facebook accounts take **5-7 days to be allowed** to connect and publish posts.
## Your Instagram Account Must Be a Business/Creator Account and Linked to a Facebook Page
Please see here for details:
Switching from Business or Creator Profiles to Personal unlinks the Facebook Page connection. The Facebook-Instagram connection must be [re-established](/docs/dashboard/connect-social-accounts/instagram).
## Check If Your Account is Instagram Business or Creator
You can verify if your Instagram account is a Business or Creator Account by going to your Instagram mobile app and clicking the three bars in the upper right corner. Select "Settings" and then "Account".
At the bottom of the screen there may be a link "Switch account type". If not, please see the link Instagram Linking above for instructions. Click "Switch account type" and you should see the following if it is a Business Account:
If you see the above image, your account is Business or Creator and no changes are needed.
If you have the option to switch to a Business or Creator Account, please choose it.
## Missing Facebook Pages
If you don't see all your Facebook pages when linking:
Verify you are the owner, admin, or manager of the missing Pages. See [Facebook Page Admin
Rights](/docs/help-center/technical-support/facebook_or_instagram_linking_issues#facebook-page-admin-rights)
for details. Also ensure the Page is at least 7 days old.
Only Facebook Business Pages can be linked. Facebook does not allow Personal Pages to be linked.
When authorizing check to make sure the Facebook page permission is granted during linking.
If you do not see the "Edit Settings" or a pop-up during linking does not appear, please see how
to [reauthorize Facebook](/docs/help-center/technical-support/facebook_posting_issues).
Still having issues? Try [reauthorizing the
link](/docs/help-center/technical-support/facebook_posting_issues#still-having-issue-with-facebook-permissions).
Click **Edit Settings**
Check all checkboxes next to the pages and click **Next** and then **Done.**
## Facebook or Instagram Could Not Load
If you encounter an error that there was an issue loading the Facebook packages while trying to link Facebook or Instagram, it means that your browser blocked the loading of an essential Facebook SDK.
**Please disable your VPN, tracking prevention, or ad blocker, reload the Ayrshare Dashboard, and try linking once more.**
Also check your browser security settings for tracking prevention/protection:
### Microsoft Edge
In Microsoft Edge, open *Settings -> Privacy, Search, and Services*. Change the *Tracking Prevention* to *Balanced*. Refresh the Ayrshare dashboard and try linking again.
### Firefox
In Firefox, open *Settings -> Privacy & Security*. Change the *Enhanced* *Tracking Protection* to *Standard*. Refresh the Ayrshare dashboard and try linking again.
## Reset All Facebook Permissions
If you are having issues with Facebook permissions, you can reset all Facebook Ayrshare permissions.
# Facebook or Instagram Account Unlinked? Fix It | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_or_instagram_unlinked
Learn why your Facebook or Instagram account became unlinked from Ayrshare and how to securely reconnect it so your scheduled posts keep publishing.
## Why Was My Facebook or Instagram Account Unlinked
We know it can be frustrating when your users are unlinked since they now need to take action, i.e. relink their social account. It causes trouble for both you and your users. At Ayrshare we try to minimize it as much as possible and provide both data and insights on what we've learned by working with the social networks for many years.
Unfortunately, the social networks have their own internal policies and rules on when to de-authorize an account and require a relink.
Meta (Facebook and Instagram) has the most aggressive security rules. If they flag a security event or suspicious activity on a user's account, Meta may require re-authorization. Other social networks have similar, but less arduous, rules.
These security events usually occur outside of Ayrshare. For example, if the user changes on facebook.com their password or username in a region they are not generally located, Facebook may flag this account and require 3rd party links to be re-established.
Possible causes:
Logging into Facebook in a new region or browser.
Logging into the same Facebook account from multiple browsers.
Changing your Facebook password or username.
Connecting numerous Facebook Pages under a single Facebook account, i.e. one Facebook login, and
posting duplicate, similar, or frequent content across all the pages.
The next step is to have your user re-authorize Facebook or Instagram with Ayrshare.
Facebook security events occur at the account level rather than at individual page levels. When
security event happen on a Facebook account (like password changes in a different reagion), all
Facebook pages associated with that account — including pages linked to Instagram accounts — must be
relinked with Ayrshare. For more information on how to handle this, please see the [Manage User
Profiles](/docs/multiple-users/manage-user-profiles) section in our documentation.
Check the [status of your violations](https://www.facebook.com/help/1985220725104252) at Facebook.
# Facebook Page Authorization Guide | Ayrshare Documentation
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_page_authorization
Learn how to authorize the right Facebook Page permissions for Ayrshare, why authorization matters, and how to fix missing-permission errors when posting.
If you're posting to Facebook or Instagram and receive the following error
message:
"Please visit facebook.com from a desktop browser and complete the required
security check or confirmation steps. Once confirmed, try your call again. If
problems persist, try unlinking and then relinking your account with Ayrshare."
This can occur due to Meta's efforts to increase accountability for high
potential reach Facebook Pages by requiring that these Pages undergo a security
check. If not authorized, the Facebook Page will not be able to publish posts.
Both Facebook Pages and Instagram accounts connected to Facebook Pages will be
affected.
### How to Get Authorized
Log into your Facebook account from a desktop browser. Complete the required
security check or confirmation steps. These steps may include:
Turn on [two-factor authentication](https://www.facebook.com/help/148233965247823) for your Facebook account.
Confirm your location by turning on [Location Services](https://www.facebook.com/help/275925085769221)
on your mobile device. Update your current city listed on your Facebook Page
and then open Facebook from your current location may aid Facebook in
determining which country you're based in. It may take some time for
Facebook to confirm your location.
If your Facebook Page has a System User, please verify all Business Manager
accounts in order to let your System User publish on your page. See
[How to Verify Your Business on Meta](https://www.facebook.com/business/help/2058515294227817)
for more information.
When authorized, your Facebook Page name will display a blue badge with white
checkmark next to the page name.
# Facebook Page Country Restrictions Explained | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_page_country_restrictions
Understand how Facebook Page country restrictions can affect posting through Ayrshare and which settings to check so your content reaches the right audience.
If you want to permanently restrict your content from being visible in certain
countries or only allow it to appear in specific countries, you can set country
restrictions directly on your Facebook Page. This eliminates the need to
configure targeting settings each time you publish a post.
## How to Set Country Restrictions
From Facebook, click your profile icon in the top right corner and select
your Facebook Page to switch to it
Go to your page's [Country Restrictions](https://www.facebook.com/settings/?tab=followers_and_public_content\&setting_id=country_restrictions) settings.
Specify which countries should either see or be restricted from seeing your content
**Important**: These page-level country restrictions will override any country
targeting you set using `faceBookOptions.targeting.countries` in your API calls.
If you've restricted a country at the Page level, Facebook users won't see your
content even if you include their country in your post targeting.
# How to Post on Facebook in Multiple Languages | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_post_in_multiple_languages
Learn how to publish Facebook posts in multiple languages using Ayrshare, including how multi-language content is handled and best practices for reach.
Multiple language posting is not supported due to Facebook API limitations.
However, Facebook attempts to translate posts into the local language of the viewer.
A user can turn on multi-language translations and even select the languages they don't want translated.
### Turn On or Off Automatic Facebook Translations
You can turn off automatic Facebook translations of posts by going to facebook.com:
1. Click ▼ in the top right of Facebook.
2. Select **Settings & Privacy**, then click **Settings**.
3. Click **Language and Region**.
4. Click *Edit* of **Languages you'd like to have posts translated into** or **Languages you don't want automatically translated**.
5. Search for the languages you don't want to be automatically translated, then click to select the language.
6. Click **Save Changes**
Please see here [Facebook Multiple Languages](https://www.facebook.com/help/894653377249514) for more info.
### API Translations
If you do want to create posting in multiple languages, you can use the [Translate Post](/docs/apis/generate/translate-post) API endpoint.
You may either then sent to posts to the same Facebook page, which might be confusing for your audience, or create a new Facebook page for each language.
# Troubleshooting Facebook Posting Issues | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_posting_issues
Fix the most common Facebook posting problems in Ayrshare, including failed posts, permissions, and media errors, with clear step-by-step troubleshooting.
If you receive an error when posting that indicates Facebook permission issues or you don't see a Facebook Page listed, it could be that some access permissions were not granted
## Facebook Business Admin Settings
Access the Business Integration page by logging into Facebook and go to "Setting" -> "Settings & Privacy" -> "Security & Login" -> "Business Integration".
Click here for a direct link to the Facebook Setting & Privacy page.
## Edit Facebook Permissions
On the [Business Integration page](https://www.facebook.com/help/405094243235242/), click the Ayrshare App and choose "View and Edit".
A pop-up will show. Scroll down to "Create and Manage Content on Your Page" and ensure that it is enabled. If you see a checkbox with "Pages" then check it to select all pages.
Click "**Save**".
Head back to the [Ayrshare Dashboard](https://app.ayrshare.com/social-accounts) and **unlink** and **relink** Facebook. You should now have the correct permissions.
## Still Having Issue with Facebook Permissions?
*If the issue still persists*, please go back into the [Facebook admin settings](/docs/help-center/technical-support/facebook_posting_issues#facebook-business-admin-settings) under Business Integration and "Remove" the Ayrshare app.
Go back into the [Ayrshare Dashboard](https://app.ayrshare.com/social-accounts) **unlink** and **relink** Facebook.
# Why Facebook Shows "Published by Ayrshare" | Help Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/facebook_shows_published_by_ayrshare
Learn why Facebook displays a "Published by Ayrshare" label on your posts, what it means for your page, and whether the attribution can be changed.
The "Published by..." is not displayed to your Facebook Page visitors, only to administrators ("admin") of the Page.
In the Facebook admin view of a Page the source of the post is shown, for example "Published by Ayrshare". Facebook automatically adds this meta data in the admin view.
Please see here on how to [view a Page as a visitor](https://www.facebook.com/help/1641659076113582) or view the page in a Private/Incognito tab in your browser.
# How to Get All Your Posts via the API | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/get_all_posts
Learn how to retrieve all your published and scheduled social media posts with the Ayrshare API, including history, status, and analytics for each post.
This guide explains how to retrieve all posts associated with your account
through different approaches, whether they originated from Ayrshare or other
sources.
## Getting All Posts for All User Profiles (Ayrshare origin)
1. Get all user profiles associated with the primary profile:
* Use your [Authorization Bearer](/docs/apis/overview#authorization) token in the header
* Call the [Get User Profiles](/docs/apis/profiles/get-profiles) endpoint
2. Get profile keys:
* Extract the `refId` from each user profile
* Use your internal store to create a list of associated user profile keys
3. Retrieve posts:
* Use the [Posts History](/docs/apis/history/get-history) endpoint
* Get all posts associated with each user profile key
## Getting Posts for a Particular Social Network for All Users (Ayrshare and non-Ayrshare origin)
1. Get all user profiles associated with the primary profile:
* Use your [Authorization Bearer](/docs/apis/overview#authorization) token in the header
* Call the [Get User Profiles](/docs/apis/profiles/get-profiles) endpoint
2. Get profile keys:
* Extract the `refId` from each user profile
* Use your internal store to create a list of associated user profile keys
3. Retrieve posts specific to a social network
* Use the [Posts History for a Platform](/docs/apis/history/history-platform)
endpoint
* Place a platform in the `platform` path parameter. Values: `facebook`,
`instagram`, `linkedin`, `pinterest`, `snapchat`, `threads`, `tiktok`, `twitter`, `youtube`
* Get all platform posts associated with each user profile key
# How to Get an Unsplash Image URL | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/get_an_unsplash_image_url
Learn how to find and use an Unsplash image URL in your Ayrshare posts to add free, high-quality images to your social media content via the API.
If copying an Unsplash URL to post in `media_urls`, please be sure to copy the image address.
Click on the Unsplash image you want to copy, right click the image, and select "Copy Image Address".
# How Do I Contact the Social Networks? | Ayrshare
Source: https://www.ayrshare.com/docs/help-center/technical-support/how_do_i_contact_the_social_networks
Find out when and how to contact social networks directly for account or platform issues that fall outside Ayrshare, and what the networks can help with.
We will try to help with any social network questions or issues you have, but sometimes the only solution is to directly contact the social networks. For example, if you have trouble logging into Facebook, only Meta (Facebook) would be able to assist.
Here is the social networks' contact information:
# How to Retrieve refId for User Profile | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/how_to_retrieve_refId
Learn how to find and retrieve the refId for a user profile in Ayrshare, what it is used for, and how to manage multiple connected accounts with it.
This page details how to retrieve the `refId` for a user profile.
## Background
During [user profile creation](/docs/apis/profiles/create-profile), you will receive
four fields in the response:
```json theme={"system"}
{
"status": "success",
"title": "Digg It",
"refId": "140b8709bd6ade099b242d895e268fb886130c53",
"profileKey": "7TVRLEZ-24A43C0-NJW0Z82-F11984N"
}
```
It is important to securely store both the `refId` and `profileKey` in your
system. The `profileKey` is used to make API requests for a specific user
profile while the `refId` is how Ayrshare refers to that user profile during API
calls.
## RefId Retrieval
There are a couple ways to retrieve the `refId` for your user profiles.
1. Use the [Get User Profiles](/docs/apis/profiles/get-profiles) endpoint to get all
user profiles associated with the primary profile. Filter through each returned
profile to find the `refId` associated with the title provided during user
profile creation. (Note: The `profileKey` for each user profile is not returned
from this endpoint, so you can't associate the `refId` against an existing
`profileKey`).
2. Navigate to the User Profiles page in the Ayrshare dashboard. Scroll through
or search for the relevant user profile. You'll be able to view the `refId` for
the user profile here.
# Instagram Analytics Demographics Warning | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/instagram_analytics_demographics_warning
Understand the Instagram analytics demographics warning in Ayrshare, why it appears when follower data is limited, and what it means for your reports.
When pulling [Analytics on a Social Network](/docs/apis/analytics/social) on
Instagram, you may receive warning message:
"Demographic data not available. You will be able to get more information about
your audience when this metric has more than 100 people in each breakdown."
(Note: the warning message may be in a different language)
This warning occurs because there are fewer than 100 people in each
demographic category. For example, let's look at the following age groups:
* **13-17**: 25
* **18-24**: 212
* **25-34**: 347
* **35-44**: 40
* **45-54**: 712
* **55-64**: 2
* **65+**: 73
Age groups 13-17, 35-44, and 55-64 have fewer than 100 people each. Therefore,
this age group demographic breakdown is not available from Instagram.
Additionally, there are some other reasons why demographic data may not be
available:
* Different locations may have more comprehensive data collection processes than
others. Also, data privacy regulations in different locations can influence
how Instagram collects and then shares demographic data.
* Instagram's algorithms and feature rollouts may not be uniform across
different locations. This includes insights data.
# Troubleshooting Instagram Posting Issues | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/instagram_posting_issues
Fix common Instagram posting problems in Ayrshare, including failed publishes, media format errors, and account permissions, with step-by-step solutions.
If you receive an error when posting about Instagram permission issues or that your account isn't linked, even though you linked your Facebook account, it could be some access permissions were not granted.
For example, if you receive the errors:
*Unsupported post request. Object with ID \[id number] does not exist,
cannot be loaded due to missing permissions, or does not support this
operation. Please read the Graph API documentation*
or
*There is an issue with your Instagram account type or permissions.*
Take the following steps:
### 1. Verify Your Instagram Business Account is Still Connected to a Facebook Page
If you used the Facebook Page connections, make sure your Instagram is a Business account and it is connected to a Facebook Page.
1. Login to Facebook and navigate to your Facebook Page. Click 'Settings' from the left-hand menu on your screen.
2. Select "Instagram" and verify your Instagram account is linked or click "Connect Account".
3. Unlink and re-link your Instagram account in the Ayrshare Dashboard under "Social Accounts".
See here for more details:
### 2. Check your Instagram Permissions
If the issue still persists, check your permissions granted to Ayrshare.
Login to Facebook and go to the "Setting" -> "Settings & Privacy" -> "Security & Login" -> "Business Integration".
Click here for a direct link
On the [Business Integration page](https://www.facebook.com/help/405094243235242/), click the Ayrshare App.
A pop-up will show. Scroll down to "Upload media and create post for Instagram" and "Access profile and posts for Instagram". Check both the boxes "Instagram Accounts":
Click "Save".
Head back to the Ayrshare Dashboard and unlink and relink Instagram. You should now have the correct permissions.
# Link Users' Social Accounts From Backend Code | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/link_social_from_backend_code
Learn how to link your users' social media accounts directly from your backend code with Ayrshare, enabling seamless onboarding without the dashboard.
The social networks do not allow authentication (linking) of social media accounts via backend code.
This is to ensure your users can securely connect their social media accounts by logging in directly with each platform's official login page.
For security reasons, social networks prevent their login pages from being embedded in iFrames. This means you cannot display the Ayrshare social linking page within an iFrame on your website - it must be opened in a new tab or window.
Please see here on the workflow for linking social media accounts: [API Integration for Business](/docs/multiple-users/api-integration-business).
# Linked Social Accounts Not Showing? Fix It | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/linked_social_accounts_not_showing
Troubleshoot why your linked social media accounts aren't showing in Ayrshare and how to refresh, reconnect, or resync them so they appear correctly.
If you or your user has linked social accounts using the Profile Linking page from [generateJWT](/docs/multiple-users/api-integration-business#generate-a-jwt),
but the linked accounts are not showing up in the Ayrshare Dashboard, you can try the following steps to resolve the issue:
## Logout JWT Session
If you're testing and using different User Profiles, you might need to use the `logout=true` parameter.
Please see [automatic logout of a profile session](/docs/multiple-users/api-integration-business#automatic-logout-of-a-profile-session) to clear the session.
## Verify the User Profile
Check that the User Profile used to generate the JWT is the same as the User Profiles being viewed in the Ayrshare Dashboard.
You can verify by checking the Title of the User Profile in the Ayrshare Dashboard against the Title shown on the Profile Linking page (the URL from generateJWT).
If they don't match then two different User Profiles are being used.
This could be because a different User Profile was selected in the Ayrshare Dashboard or the incorrect Profile Key was used when calling generateJWT.
# Fix "LinkedIn Post Cannot Be Displayed" Error | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/linkedin_post_cannot_be_displayed
Learn what causes the "LinkedIn post cannot be displayed" error and how to fix permissions, tokens, or content so your LinkedIn posts publish via Ayrshare.
If you've used the [Publish a Post](/docs/apis/post/post) endpoint on LinkedIn and
included mediaUrls in your post, your post, despite receiving a successful
response, may no longer display if the media or post content doesn't meet
LinkedIn's requirements.
For example, the LinkedIn post may return the following successful response:
```json LinkedIn Post Response theme={"system"}
{
"status": "success",
"errors": [],
"postIds": [
{
"status": "success",
"id": "urn:li:share:7287840497870462977", // LinkedIn Social Post ID
"postUrl": "https://www.linkedin.com/feed/update/urn:li:share:7287840497870462977/"
"owner": "urn:li:organization:12345670",
"platform": "linkedin"
}
],
"id": "PmrbzuYh1hdKMc52zC8"
}
```
However, the post may not display in LinkedIn, using the `postUrl`, if the media or post content doesn't meet
LinkedIn's requirements.
While LinkedIn may provide a `postUrl` initially, they will reject the post if,
during post-processing, any of the media or post content doesn't meet their requirements.
Please consult the [LinkedIn Media Guidelines](/docs/media-guidelines/linkedin) to
ensure that your media remains compliant and verify the content of your post is acceptable.
# Meta Media Crawler Blocked (Instagram / Threads)
Source: https://www.ayrshare.com/docs/help-center/technical-support/meta_media_crawler_blocked
How to fix error code 479 (media could not be fetched — the dedicated non-retryable crawler-block code), the transient code 440, and related Instagram 138 / Threads 379, caused by robots.txt or bot rules blocking Meta's media crawler.
Error code **479** is the dedicated, **non-retryable** Ayrshare code returned when Meta cannot fetch your media URL — most commonly because `robots.txt` or a bot-blocking rule on your server is denying the crawler (`facebookexternalhit`). It is returned only after Ayrshare's automatic re-host fallback has also failed, which strongly indicates a host-side block or an unreachable source.
When Ayrshare publishes to Instagram or Threads, it does not blindly hand your URL to Meta and give up. Ayrshare automatically retries the fetch and, if Meta still cannot reach the media, **re-hosts a copy on its own CDN** and asks Meta to fetch that instead. Code **479** means even that fallback could not get Meta to fetch the media — so retrying the same request will not help until the underlying hosting issue is fixed (`retryAvailable: false`, HTTP 400).
This page covers failures whose error message or details mention that the social network could not download the media, typically referencing `facebookexternalhit`, `robots.txt`, `"Restricted by robots.txt"`, `"HTTP error code 403"`, or Meta subcode `2207052`. For aspect-ratio or format errors on Instagram code 138, see [Instagram Media Guidelines](/docs/media-guidelines/instagram) or [Threads Media Guidelines](/docs/media-guidelines/threads) instead.
## Symptom
When the crawler is blocked, you'll see errors like these:
```json Error 479 (primary — dedicated, non-retryable) theme={"system"}
{
"status": "error",
"errors": [{
"action": "post",
"code": 479,
"retryAvailable": false,
"message": "The social network could not fetch the media from this URL, even after Ayrshare re-hosted it on its own CDN (Instagram/Meta subcode 2207052). Ensure the file is publicly reachable by Meta's crawlers (facebookexternalhit / Facebot) — check your robots.txt and any WAF/bot rules — not only in a browser. Retrying the same URL will not help until hosting is fixed.",
"details": "Media download has failed.: The media could not be fetched from the provided URI. Restricted by robots.txt (HTTP error code 403). Meta subcode 2207052.",
"platform": "instagram",
"status": "error"
}],
"postIds": [],
"id": "..."
}
```
```json Error 440 (transient ingestion — retryable) theme={"system"}
{
"status": "error",
"errors": [{
"action": "post",
"code": 440,
"retryAvailable": true,
"message": "The social network could not ingest the media in time. This is usually transient (for example Meta subcode 2207032 'download too slow' or 2207003 'create media fail'). Retry the post.",
"details": "Media download has failed.: Media download took too long / could not create media...",
"platform": "instagram",
"status": "error"
}],
"postIds": [],
"id": "..."
}
```
```json Instagram Error 138 (fallback — less specific upstream response) theme={"system"}
{
"status": "error",
"errors": [{
"retryAvailable": true,
"status": "error",
"code": 138,
"details": "Media download has failed.: The media could not be fetched from the provided URI. Video download failed with: HTTP error code 403. Restricted by robots.txt",
"action": "post",
"platform": "instagram",
"message": "Instagram Error: Instagram cannot process your post at this time. Please try your post again."
}],
"postIds": [],
"id": "..."
}
```
```json Threads Error 379 theme={"system"}
{
"status": "error",
"errors": [{
"status": "error",
"code": 379,
"message": "Error posting to Threads.",
"action": "post",
"platform": "threads"
}],
"postIds": [],
"id": "..."
}
```
Understanding the split between these codes:
**Code 479 — dedicated media-fetch / crawler-block (non-retryable).** This is the code for the failure covered by this page. It is returned with `retryAvailable: false` when Meta could not fetch the media (subcode `2207052` or a media-fetch text pattern) **even after Ayrshare re-hosted it on its own CDN**. Its message explicitly names `facebookexternalhit` / `Facebot` and `robots.txt` — if you see 479, you're on the right page. Fix hosting before retrying.
**Code 440 — transient ingestion (retryable).** Now used for genuinely transient ingestion exhaustion — Meta subcodes `2207032` ("download too slow") / `2207003` ("create media fail"), or unclassified exhaustion. It carries `retryAvailable: true`; retry via [`/post/retry`](/docs/apis/post/retry-post).
**Code 138 — less-specific Instagram fallback.** Emitted for the same root cause when the upstream response is less specific. 138 is also used for aspect-ratio / format issues, so the media-fetch variant is identifiable by `"Restricted by robots.txt"` or `"HTTP error code 403"` in `details`.
**Code 379 — Threads.** Does not include a `details` field. If Threads fails alongside an Instagram 479 or 138, the root cause is typically the same.
## Why This Happens
When you publish to Instagram or Threads via Ayrshare, Meta's servers fetch your media from the URL you provide. This server-side fetch uses the `facebookexternalhit` User-Agent. If your server's `robots.txt` disallows this crawler — or a WAF/bot-protection rule blocks it — Meta cannot download the file and the publish fails.
Facebook Page publishing uses a different ingestion path, which is why the same `mediaUrl` may work for Facebook but fail for Instagram and Threads.
## Fix: Update Your robots.txt
### Recommended: Allow Meta explicitly, keep others open
Add these rules to your `robots.txt` file:
```txt robots.txt theme={"system"}
User-agent: facebookexternalhit
Allow: /
User-agent: *
Allow: /
```
This explicitly allows Meta's crawler while keeping your site open to other crawlers (Google, Bing, etc.).
### Advanced: Lock down to social publishers only
If you want to block most crawlers but allow social media platforms:
```txt robots.txt theme={"system"}
User-agent: facebookexternalhit
Allow: /
User-agent: Twitterbot
Allow: /
User-agent: LinkedInBot
Allow: /
User-agent: Pinterest
Allow: /
User-agent: *
Disallow: /
```
Use a single `User-agent: *` block, placed at the end of the file. RFC 9309-compliant crawlers merge multiple wildcard groups into one, but not every parser in the wild is RFC-compliant — duplicate wildcard groups are a common source of rules being dropped or applied inconsistently.
## Verify Meta Can Fetch Your URL
Before retrying your post, verify that Meta's crawler can now access your media. Run this command, replacing `$URL` with your full media URL:
```bash theme={"system"}
curl -v --compressed -H "Range: bytes=0-524288" -H "Connection: close" \
-A "facebookexternalhit/1.1 (+http://www.facebook.com/externalhit_uatext.php)" \
"$URL"
```
**Healthy response:** HTTP 200 or 206 with binary data in the body.
**Blocked response:** HTTP 403 or an empty/HTML error page.
Per Meta's documentation, `robots.txt` changes may take up to 24 hours to propagate through Meta's crawler cache. If verification succeeds but your post still fails, wait and retry later.
## If This Doesn't Fix It
If you've updated `robots.txt` and verified with the `curl` command but still see failures:
**24-hour propagation delay** — Meta caches `robots.txt`. Wait up to 24 hours after making changes before retrying.
**WAF or bot-fight rules** — Cloudflare Bot Fight Mode, AWS WAF managed bot rule groups, and similar services may block Meta's crawler IP ranges even if `robots.txt` allows it. Check your WAF logs and add an exception for `facebookexternalhit`.
**Hotlink protection / Referer checks** — Some CDNs block requests from data-center IPs or without a valid `Referer` header. Whitelist Meta's crawler or disable hotlink protection for media paths.
**Signed-URL / presigned-URL expiry** — If your media URL has an expiration timestamp (common with S3 presigned URLs), ensure it doesn't expire before Meta's crawler can fetch it. For scheduled posts, generate URLs that remain valid until well after the scheduled time.
**Managed media hosting** — If you use a service like Cloudinary, Imgix, or similar where you cannot edit `robots.txt`, check their documentation for a Meta/Facebook crawler allow-list setting.
If none of these resolve the issue, [contact Ayrshare support](https://www.ayrshare.com/contact) and include:
* The failing `postId` from the error response
* The output of the `curl` verification command above
* Your `robots.txt` contents
## Retry a Failed Post
Retry behavior depends on which code you received:
**Code 440 (transient, `retryAvailable: true`)** — the ingestion simply ran out of time or hit a temporary Meta error. Retry directly using the [Retry Post endpoint](/docs/apis/post/retry-post); no changes to your hosting are needed.
**Code 479 (`retryAvailable: false`)** — Meta could not fetch the media even after Ayrshare re-hosted it on its own CDN, so retrying the unchanged blocked URL will fail again. **Fix hosting first**: allow Meta's crawlers (`facebookexternalhit` / `Facebot`) in `robots.txt` and your WAF, or re-host the media on a Meta-reachable CDN. Verify with the `curl` command above, then retry via the [Retry Post endpoint](/docs/apis/post/retry-post).
# Technical Support Overview & Troubleshooting | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/overview
Browse Ayrshare's technical support guides for fixing posting errors, account-linking issues, and API problems across all supported social networks.
For additional information on specific technical issues, there are specific troubleshooting steps that we recommend.
Issues and errors related to Meta including Facebook and Instagram.
Issues and errors related to other social networks.
Additional help on specific error messages and responses.
More technical support topics.
# Password Required for LinkedIn Linking | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/password_required_for_linkedin_linking
Learn why LinkedIn may require a password when linking to Ayrshare, how to complete authentication securely, and how to fix linking errors that follow.
When connecting your LinkedIn account to Ayrshare, you may be asked to provide
your username and password.
If you do not have a password due to authenticating into LinkedIn using a Google
or Microsoft account, please use the following steps:
1. Click the "Forgot password?" link.
2. Input your email and
click "Next".
3. Check your email and copy over the 6-digit code.
4. At the "Choose a new password" screen, input a new password, retype it, and then
click "Submit".
Return to the Ayrshare dashboard and try to connect your LinkedIn account again.
Upon arriving at the signin page, input your email and the new password.
# Post With @Mentions Didn't Go Through? | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/post_with_mentions_didn_t_go_through
Find out why social media posts with @mentions may fail to publish through Ayrshare and how to format mentions correctly so they go through every time.
The social networks are very particular about the frequency of @mentions and who is mentioned. The Free Plan does not allow mentions and will not send your posts.
Paid plans allow mentions, but a connected social account may only mention the same handle once per day. To prevent abuse, deleted posts with mentions count towards the total.
# How to Fix a 500 Internal Server Error | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/response_500_internal_error
Learn what causes a 500 Internal Server Error from the Ayrshare API, how to diagnose the request, and the steps to resolve it and retry your post.
If you receive a 500 error with the message "Internal Error" or "Internal Server Error" please verify that the URL called is valid as detailed in the Ayrshare docs.
If the URL looks ok, the Internal Error means that there was a network connectivity issue between your server and our cloud provider Google.
If this error occurs, please retry your request.
Other issues may be related to:
Invalid JSON being sent. Please see here for more information: [Invalid
JSON](/docs/help-center/technical-support/response_returns_as_bad_request).
Endpoint timeout. We recommend using the new base API endpoint: [New Base API
Endpoint](/docs/help-center/technical-support/response_bad_gateway_502_or_504_error).
# How to Fix 502 Bad Gateway & 504 Errors | Ayrshare API Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/response_bad_gateway_502_or_504_error
Understand what 502 Bad Gateway and 504 Gateway Timeout errors mean from the Ayrshare API, why they happen, and how to retry your requests safely.
If you've encountered:
* A 502 or 504 HTTP error with a "Bad Gateway" message
* A timeout while trying to post a large media file
* An HTML CloudFlare response
Please try sending the post again using `api.ayrshare.com` as your base endpoint. See the [/post](/docs/apis/post/post) endpoint for details.
`https://api.ayrshare.com/api/{endpoint name}`
For example, instead of `https://app.ayrshare.com/api/post`, use `https://api.ayrshare.com/api/post`
You may also use `api.ayrshare.com` for the `/post` endpoint or any other endpoint.
# How to Fix a 400 Bad Request Error | Ayrshare API Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/response_returns_as_bad_request
Learn why the Ayrshare API returns a Bad Request (400) error, how to spot missing or invalid parameters, and how to correct your request and resend it.
If you receive HTML as a response of "Bad Request" instead of JSON, it is possible the POST body parameter is not valid JSON.
For example, if you send this invalid JSON:
```javascript theme={"system"}
{
"post": "A "great" post"
"platforms: ["twitter"]
}
```
A response of "Bad Request" will be returned. The code above has three issues: a missing comma on `post`, the post text has a double set of " quotes without escaping, and a missing end quote on `platform`. The valid JSON should be:
```javascript theme={"system"}
{
"post": "A \"great\" post",
"platforms": ["twitter"]
}
```
You can test your JSON by POSTing to the following URL to validate your JSON. Be sure to set the Content-Type to `text/plain`.
We recommend trying the call in [Postman](/docs/testing/postman), which can help correct JSON formatting. Please see the next section for more information.
## Validate JSON
You can validate your JSON by using either an online linter, such as [https://jsonlint.com/](https://jsonlint.com/) or using [Postman](/docs/testing/postman).
You may also use our `/validate/json` endpoint:
# TikTok Account Restricted? How to Fix It | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/tiktok_account_restricted
Find out why your TikTok account may be restricted, how it affects posting through Ayrshare, and the steps to resolve the restriction and resume publishing.
## Why Does TikTok Restrict or Suspend Accounts?
TikTok may restrict or suspend accounts when their security algorithm is triggered. Unlike some platforms, TikTok often provides limited information about specific violations. Restrictions can occur when TikTok's algorithm detects unusual activity, potential violations of community guidelines, or when content is flagged by their automated systems.
Please see [TikTok's Community Guidelines](https://www.tiktok.com/community-guidelines) for more information.
## Steps We Recommend:
1. Review your recent content for potential community guideline violations including copyright infringement, inappropriate content, or misleading information.
2. Check your posting frequency - TikTok may flag accounts that post too frequently as potential spam accounts. Please see our [recommended social posting limits](/docs/testing/post-verification#recommended-posting-limits) for guidance on optimal posting frequency.
3. Verify any links included in your profile or content, as TikTok closely scrutinizes external URLs.
4. Check your server logs for any error messages returned from /post.
5. Have the account owner log into TikTok directly and check for any notifications, warnings, or verification requests that may need to be addressed.
6. If you've received a specific violation message, follow TikTok's appeal process within the app (Settings > Report a Problem).
7. After following the above steps, if the user was suspended by Ayrshare, [re-activate the user profile](/docs/multiple-users/manage-user-profiles#reactivate-a-suspended-user-profile) in the Ayrshare Dashboard.
## TikTok's Algorithm and Content Moderation
TikTok uses a sophisticated algorithm to determine account status and content distribution. This algorithm monitors posting frequency, content patterns, account history, and user reports. Content that appears automated or bot-like may trigger restrictions, even when the content itself doesn't violate guidelines.
TikTok may limit your account's reach ("shadowban") before moving to a full restriction if they detect concerning patterns. This can appear as dramatically reduced views or engagement.
See our [recommended social posting limits](/docs/testing/post-verification#recommended-posting-limits) for guidance on optimal posting frequency.
## TikTok Message: "This account is currently unavailable" or "Action Blocked"
If the user encounters messages such as "This account is currently unavailable" or "Action Blocked," TikTok has likely placed temporary restrictions on your account. While TikTok provides limited specific information about these restrictions, they typically resolve within 24-72 hours if no further triggering actions occur.
During this period:
* Avoid posting new content
* Do not attempt to create new accounts from the same device
* Refrain from mass following/unfollowing actions
* Do not repeatedly attempt actions that have been blocked
## Duplicate Content Concerns
Posting identical content across multiple TikTok accounts is particularly problematic and may trigger restrictions. TikTok's algorithms are designed to identify and limit the reach of duplicate content to prevent spam and maintain platform quality.
If you're managing multiple accounts, ensure each post is unique and tailored to the specific account's audience. Even minor variations in captions, hashtags, or visual elements can help avoid duplicate content flags.
See our guide on [managing duplicate content across social platforms](/docs/testing/post-verification#duplicate-and-similar-posts) for more information on how to safely repurpose content while avoiding restrictions.
***
Security violations from the social platforms should be taken seriously and resolved as soon as possible.
Repeated violations may result in a permanent suspension of the social account.
# Why Video Publishing Fails & How to Fix It | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/video_publishing_fails
Troubleshoot failed video posts in Ayrshare by checking format, size, duration, and platform limits, with step-by-step fixes to get your videos publishing.
## When Social Networks Reject Your Videos
If Meta - Facebook, Instagram, or Threads - or X (Twitter) keeps rejecting your video posts when publishing, even after a [post retry attempt](/docs/apis/post/retry-post), the problem may not be with the platform, but with the video encoding itself.
### Common Issue with Video Encoding
Meta platforms (Facebook, Instagram, and Threads) and X have specific video format requirements: [Facebook Media Guidelines](/docs/media-guidelines/facebook_pages), [Instagram Video Guidelines](/docs/media-guidelines/instagram), [Threads Video Guidelines](/docs/media-guidelines/threads), and [X Video Guidelines](/docs/media-guidelines/x_twitter).
Some video creation tools occasionally produce videos with encoding that Meta's systems don't accept. At times, their output needs to be re-encoded for compatibility.
### One Solution: Re-encode with FFmpeg
If your video uploads are failing, try re-encoding the video using [FFmpeg](https://ffmpeg.org/), an open-source tool for video processing:
```bash theme={"system"}
ffmpeg -i your_original_video.mp4 -c:v libx264 -preset medium -profile:v high -level 4.0 -pix_fmt yuv420p -c:a aac -movflags +faststart meta_compatible_video.mp4
```
This command converts your video to use the widely-compatible H.264 video codec and AAC audio codec, which Meta platforms accept.
Re-encoding "normalizes" your video to use standard encoding parameters that Meta's platforms are designed to process, without sacrificing quality.
If you see these errors regularly, this simple step can save you frustration when sharing your creative content.
### FFmpeg Installation and Usage
Installation instructions:
-preset medium: Balance between encoding speed and quality
-profile:v high -level 4.0: Compatibility settings
-pix\_fmt yuv420p: Standard pixel format for maximum compatibility
-b:v 5000k: Video bitrate (adjust as needed for quality)
-c:a aac: AAC audio codec
-b:a 192k: Audio bitrate
-movflags +faststart: Optimizes file for web streaming
# Fix X/Twitter Link Preview Not Showing | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/x_twitter_link_preview_not_showing
Learn why link previews (Twitter Cards) may not show on your X/Twitter posts published via Ayrshare and how to fix metadata so previews render correctly.
When a link is included in a post, X/Twitter tries to render a preview. [X/Twitter meta tags](https://developer.twitter.com/en/docs/twitter-for-websites/cards/overview/markup) on your site/page in the header are used to render the preview text, image, and link.
You can validate how the X/Twitter card will look by submitting your page link here:
If everything looks ok, but the preview is still not showing, please contact us for assistance.
# YouTube Channels Not Showing? How to Fix It | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/youtube_channels_not_showing
Troubleshoot why your YouTube channels aren't appearing in Ayrshare and how to reconnect permissions so the right channel is available for posting.
When you authorize access to your YouTube channel, Google requires you to select a Google account and then choose a specific channel.
For more information on how to connect your YouTube channel to Ayrshare, see the [YouTube channel linking guide](/docs/dashboard/connect-social-accounts/youtube).
However, you may notice that one or more of your channels are missing from the selection list - probably the channel you want to connect to the YouTube API.
Google controls which channels appear in this list based on several factors: the Google account you're using for authentication, your permission level on each channel, and the privacy settings configured for each channel.
### Missing YouTube Channel Reasons
1. Channel Required
YouTube posting requires your YouTube account to have at least one channel and [be an owner
on the channel](https://support.google.com/youtube/answer/9481328). Please see number 2
below.
To create a YouTube channel, click on your profile in the YouTube Dashboard and choose
"Create a Channel". You may also use this direct link to create a YouTube Channel:
[http://m.youtube.com/create\_channel](http://m.youtube.com/create_channel)
2. Owner or Admin of the Channel
The [Google account](/docs/dashboard/connect-social-accounts/youtube) logged in as must be the
owner or admin of the Channel for it to be presented.
You can check the [brand permissions](https://myaccount.google.com/brandaccounts) to ensure
that the account has the necessary permissions. If you don't see the channel listed, you can
ask the channel owner to add you as a manager or owner.
3. Channel Privacy Settings
If a channel owner has set their channel privacy to "Private" or "Unlisted," their channel
and its content will not be accessible through the API.
You can test this by opening up an incognito brower and trying to go search for the channel.
A private or unlisted channel will not show up in the search results.
Private channels are only visible to the channel owner and authorized users, while unlisted
channels can only be accessed with the direct channel URL.
4. Age or Region Restrictions
If a channel has age-restricted content or is restricted in certain regions.
Age-restricted channels require users to be signed in and meet the age requirements to view
the content.
5. Deleted or Suspended Channels
If a channel has been deleted by the owner or suspended by YouTube for violating terms of
service, it will no longer be accessible through the API.
Deleted channels are permanently removed, while suspended channels may become accessible
again if the suspension is lifted.
# Fix YouTube "disallowed_useragent" on Android | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/youtube_on_android_disallowed_useragent
Learn what the YouTube "disallowed_useragent" error on Android means when linking to Ayrshare and how to complete authorization in a supported browser.
If you are trying to link YouTube on an Android or iOS device but receive an "**Error: disallowed\_useragent**", it may be due to Google rejecting your login request. An old browser is often the cause for this unauthorized browser agent rejection.
You can try to address this issue by updating your app to the latest Android SDK, Android OS, and Chrome version.
# YouTube Thumbnail Not Applied (Unverified Channel)
Source: https://www.ayrshare.com/docs/help-center/technical-support/youtube_thumbnail_unverified_channel
Your YouTube video posts successfully but the custom thumbnail is missing. The most common cause is an unverified YouTube channel.
When you post a YouTube video with a custom `thumbNail`, the video may publish successfully while the thumbnail fails to apply. In this case the post's top-level `status` stays `"success"` (the video is live), but the YouTube result carries a `warnings` array describing the thumbnail failure:
```json theme={"system"}
{
"status": "success",
"id": "",
"thumbnail": {
"action": "post",
"status": "error",
"code": 307,
"message": "Your YouTube channel must be verified to set a custom thumbnail. Verify your channel at https://www.youtube.com/verify (phone verification). If your channel is already verified, try unlinking and re-linking your YouTube account to restore permissions.",
"details": ""
},
"warnings": [
{
"feature": "thumbnail",
"code": 307,
"message": "Your YouTube channel must be verified to set a custom thumbnail. Verify your channel at https://www.youtube.com/verify (phone verification). If your channel is already verified, try unlinking and re-linking your YouTube account to restore permissions.",
"details": ""
}
]
}
```
## Symptom
Your YouTube video appears on the channel, but the custom thumbnail you supplied is missing — YouTube uses an auto-generated frame instead. The API response returns `status: "success"` with a thumbnail `warnings` entry (`feature: "thumbnail"`, `code: 307`).
## Most Common Cause: Unverified Channel
The dominant cause of a YouTube thumbnail `403` failure is an **unverified YouTube channel**. YouTube requires channel (phone) verification before it will accept a custom thumbnail upload.
### Fix: Verify Your Channel
1. Go to [https://www.youtube.com/verify](https://www.youtube.com/verify) and complete **phone verification** for the channel.
2. Alternatively, in [YouTube Studio](https://studio.youtube.com/) go to *Settings → Channel*, select *Feature Eligibility*, and enable *Features that require phone verification*.
3. YouTube may take up to 24 hours to enable custom thumbnails after verification. "Enabled" phone verification does not guarantee YouTube will allow thumbnail uploads — YouTube ultimately determines eligibility.
4. Confirm you can manually upload a thumbnail in YouTube Studio. If you cannot do it manually, the API cannot either.
## Secondary Cause: OAuth Permissions
If your channel is **already verified** and thumbnails still fail with a `403`, the linked YouTube account may be missing the required permissions. Try **unlinking and re-linking** your YouTube account in [Social Accounts](https://app.ayrshare.com/social-accounts) and grant all requested permissions during re-linking.
For Brand / Content Owner accounts (often used for business or organization channels), make sure the linked account has the necessary permissions — we recommend "Owner" rights.
## Pre-Publish Thumbnail Requirements
Ayrshare validates the `thumbNail` before publishing where possible. To avoid a `307` thumbnail failure, ensure the thumbnail meets these requirements:
**Format:** PNG or JPG/JPEG. The file extension must end in png, jpg, or jpeg.
**Size:** 2MB or less.
**Reachable URL:** The thumbNail URL must be publicly reachable so Ayrshare can fetch it.
A thumbnail problem never fails the post. If a thumbnail is definitively invalid (wrong extension, confirmed over 2MB, or unreachable), Ayrshare skips it before the video is uploaded, still publishes the video, and reports the reason in `warnings`. If the failure can only be determined after the video is uploaded, the video stays live and the failure is surfaced via the same `warnings` array described above. Either way the video publishes and `status` stays `"success"`.
## Related
* [YouTube Post API — Thumbnails](/docs/apis/post/social-networks/youtube#youtube-thumbnails)
* [YouTube media guidelines](/docs/media-guidelines/youtube#thumbnails)
* [Error codes — Code 307](/docs/errors/errors-ayrshare#youtube-thumbnail-errors-code-307)
# YouTube Videos Changed to Private? Fix It | Ayrshare Docs
Source: https://www.ayrshare.com/docs/help-center/technical-support/youtube_videos_changed_to_private
Find out why YouTube may switch uploaded videos to private when posted via Ayrshare, how channel verification affects this, and how to keep videos public.
If your public YouTube videos are changed to private, it is likely due to a YouTube policy violation.
This could be due to unrelated or misleading tags from the "Description" and "Tag" sections of your video.
Information about [YouTube's metadata best practices](https://support.google.com/youtube/answer/2801973?sjid=8684425261187021057-NA).
You *should* receive an email from YouTube with the details of the violation with next steps.
Learn more about [YouTube Video Locked as Private](https://support.google.com/youtube/answer]/7300965).
# Country Codes
Source: https://www.ayrshare.com/docs/iso-codes/country
ISO 3166 format country codes
The country codes to use with the API endpoints. Please see the specific endpoint for details.
| Country | Code |
| :------------------------------------------- | ---: |
| Afghanistan | AF |
| Albania | AL |
| Algeria | DZ |
| American Samoa | AS |
| Andorra | AD |
| Angola | AO |
| Anguilla | AI |
| Antarctica | AQ |
| Antigua and Barbuda | AG |
| Argentina | AR |
| Armenia | AM |
| Aruba | AW |
| Australia | AU |
| Austria | AT |
| Azerbaijan | AZ |
| Bahamas | BS |
| Bahrain | BH |
| Bangladesh | BD |
| Barbados | BB |
| Belarus | BY |
| Belgium | BE |
| Belize | BZ |
| Benin | BJ |
| Bermuda | BM |
| Bhutan | BT |
| Bolivia, Plurinational State of | BO |
| Bonaire, Sint Eustatius and Saba | BQ |
| Bosnia and Herzegovina | BA |
| Botswana | BW |
| Bouvet Island | BV |
| Brazil | BR |
| British Indian Ocean Territory | IO |
| Brunei Darussalam | BN |
| Bulgaria | BG |
| Burkina Faso | BF |
| Burundi | BI |
| Cambodia | KH |
| Cameroon | CM |
| Canada | CA |
| Cape Verde | CV |
| Cayman Islands | KY |
| Central African Republic | CF |
| Chad | TD |
| Chile | CL |
| China | CN |
| Christmas Island | CX |
| Cocos (Keeling) Islands | CC |
| Colombia | CO |
| Comoros | KM |
| Congo | CG |
| Congo, the Democratic Republic of the | CD |
| Cook Islands | CK |
| Costa Rica | CR |
| Croatia | HR |
| Cuba | CU |
| Curaçao | CW |
| Cyprus | CY |
| Czech Republic | CZ |
| Côte d'Ivoire | CI |
| Denmark | DK |
| Djibouti | DJ |
| Dominica | DM |
| Dominican Republic | DO |
| Ecuador | EC |
| Egypt | EG |
| El Salvador | SV |
| Equatorial Guinea | GQ |
| Eritrea | ER |
| Estonia | EE |
| Ethiopia | ET |
| Falkland Islands (Malvinas) | FK |
| Faroe Islands | FO |
| Fiji | FJ |
| Finland | FI |
| France | FR |
| French Guiana | GF |
| French Polynesia | PF |
| French Southern Territories | TF |
| Gabon | GA |
| Gambia | GM |
| Georgia | GE |
| Germany | DE |
| Ghana | GH |
| Gibraltar | GI |
| Greece | GR |
| Greenland | GL |
| Grenada | GD |
| Guadeloupe | GP |
| Guam | GU |
| Guatemala | GT |
| Guernsey | GG |
| Guinea | GN |
| Guinea-Bissau | GW |
| Guyana | GY |
| Haiti | HT |
| Heard Island and McDonald Islands | HM |
| Holy See (Vatican City State) | VA |
| Honduras | HN |
| Hong Kong | HK |
| Hungary | HU |
| Iceland | IS |
| India | IN |
| Indonesia | ID |
| Iran, Islamic Republic of | IR |
| Iraq | IQ |
| Ireland | IE |
| Isle of Man | IM |
| Israel | IL |
| Italy | IT |
| Jamaica | JM |
| Japan | JP |
| Jersey | JE |
| Jordan | JO |
| Kazakhstan | KZ |
| Kenya | KE |
| Kiribati | KI |
| Korea, Democratic People's Republic of | KP |
| Korea, Republic of | KR |
| Kuwait | KW |
| Kyrgyzstan | KG |
| Lao People's Democratic Republic | LA |
| Latvia | LV |
| Lebanon | LB |
| Lesotho | LS |
| Liberia | LR |
| Libya | LY |
| Liechtenstein | LI |
| Lithuania | LT |
| Luxembourg | LU |
| Macao | MO |
| Macedonia, the Former Yugoslav Republic of | MK |
| Madagascar | MG |
| Malawi | MW |
| Malaysia | MY |
| Maldives | MV |
| Mali | ML |
| Malta | MT |
| Marshall Islands | MH |
| Martinique | MQ |
| Mauritania | MR |
| Mauritius | MU |
| Mayotte | YT |
| Mexico | MX |
| Micronesia, Federated States of | FM |
| Moldova, Republic of | MD |
| Monaco | MC |
| Mongolia | MN |
| Montenegro | ME |
| Montserrat | MS |
| Morocco | MA |
| Mozambique | MZ |
| Myanmar | MM |
| Namibia | NA |
| Nauru | NR |
| Nepal | NP |
| Netherlands | NL |
| New Caledonia | NC |
| New Zealand | NZ |
| Nicaragua | NI |
| Niger | NE |
| Nigeria | NG |
| Niue | NU |
| Norfolk Island | NF |
| Northern Mariana Islands | MP |
| Norway | NO |
| Oman | OM |
| Pakistan | PK |
| Palau | PW |
| Palestine, State of | PS |
| Panama | PA |
| Papua New Guinea | PG |
| Paraguay | PY |
| Peru | PE |
| Philippines | PH |
| Pitcairn | PN |
| Poland | PL |
| Portugal | PT |
| Puerto Rico | PR |
| Qatar | QA |
| Romania | RO |
| Russian Federation | RU |
| Rwanda | RW |
| Réunion | RE |
| Saint Barthélemy | BL |
| Saint Helena, Ascension and Tristan da Cunha | SH |
| Saint Kitts and Nevis | KN |
| Saint Lucia | LC |
| Saint Martin (French part) | MF |
| Saint Pierre and Miquelon | PM |
| Saint Vincent and the Grenadines | VC |
| Samoa | WS |
| San Marino | SM |
| São Tomé and Principe | ST |
| Saudi Arabia | SA |
| Senegal | SN |
| Serbia | RS |
| Seychelles | SC |
| Sierra Leone | SL |
| Singapore | SG |
| Sint Maarten (Dutch part) | SX |
| Slovakia | SK |
| Slovenia | SI |
| Solomon Islands | SB |
| Somalia | SO |
| South Africa | ZA |
| South Georgia and the South Sandwich Islands | GS |
| South Sudan | SS |
| Spain | ES |
| Sri Lanka | LK |
| Sudan | SD |
| Suriname | SR |
| Svalbard and Jan Mayen | SJ |
| Swaziland | SZ |
| Sweden | SE |
| Switzerland | CH |
| Syrian Arab Republic | SY |
| Taiwan, Province of China | TW |
| Tajikistan | TJ |
| Tanzania, United Republic of | TZ |
| Thailand | TH |
| Timor-Leste | TL |
| Togo | TG |
| Tokelau | TK |
| Tonga | TO |
| Trinidad and Tobago | TT |
| Tunisia | TN |
| Turkey | TR |
| Turkmenistan | TM |
| Turks and Caicos Islands | TC |
| Tuvalu | TV |
| Uganda | UG |
| Ukraine | UA |
| United Arab Emirates | AE |
| United Kingdom | GB |
| United States | US |
| United States Minor Outlying Islands | UM |
| Uruguay | UY |
| Uzbekistan | UZ |
| Vanuatu | VU |
| Venezuela, Bolivarian Republic of | VE |
| Vietnam | VN |
| Virgin Islands, British | VG |
| Virgin Islands, U.S. | VI |
| Wallis and Futuna | WF |
| Western Sahara | EH |
| Yemen | YE |
| Zambia | ZM |
| Zimbabwe | ZW |
| Åland Islands | AX |
# Language Codes
Source: https://www.ayrshare.com/docs/iso-codes/language
Available languages and codes
The language codes to use with the API endpoints. Please see the specific endpoint for details.
| Language | Language Code |
| :------------------ | ------------: |
| Abkhaz | ab |
| Afar | aa |
| Afrikaans | af |
| Akan | ak |
| Albanian | sq |
| Amharic | am |
| Arabic | ar |
| Aragonese | an |
| Armenian | hy |
| Assamese | as |
| Avaric | av |
| Avestan | ae |
| Aymara | ay |
| Azerbaijani | az |
| Bambara | bm |
| Bashkir | ba |
| Basque | eu |
| Belarusian | be |
| Bengali | bn |
| Bihari | bh |
| Bislama | bi |
| Bosnian | bs |
| Breton | br |
| Bulgarian | bg |
| Burmese | my |
| Catalan | ca |
| Chamorro | ch |
| Chechen | ce |
| Chichewa | ny |
| Chinese | zh |
| Chuvash | cv |
| Cornish | kw |
| Corsican | co |
| Cree | cr |
| Croatian | hr |
| Czech | cs |
| Danish | da |
| Dhivehi | dv |
| Dutch | nl |
| English | en |
| Esperanto | eo |
| Estonian | et |
| Ewe | ee |
| Faroese | fo |
| Fijian | fj |
| Finnish | fi |
| French | fr |
| Fula | ff |
| Galician | gl |
| Georgian | ka |
| German | de |
| Greek | el |
| Guaraní | gn |
| Gujarati | gu |
| Haitian Creole | ht |
| Hausa | ha |
| Hebrew | he |
| Herero | hz |
| Hindi | hi |
| Hiri Motu | ho |
| Hungarian | hu |
| Icelandic | is |
| Ido | io |
| Igbo | ig |
| Indonesian | id |
| Interlingua | ia |
| Interlingue | ie |
| Inuktitut | iu |
| Inupiaq | ik |
| Irish | ga |
| Italian | it |
| Japanese | ja |
| Javanese | jv |
| Kalaallisut | kl |
| Kannada | kn |
| Kanuri | kr |
| Kashmiri | ks |
| Kazakh | kk |
| Khmer | km |
| Kikuyu | ki |
| Kinyarwanda | rw |
| Komi | kv |
| Kongo | kg |
| Korean | ko |
| Kurdish | ku |
| Kwanyama | kj |
| Kyrgyz | ky |
| Lao | lo |
| Latin | la |
| Latvian | lv |
| Limburgish | li |
| Lingala | ln |
| Lithuanian | lt |
| Luba-Katanga | lu |
| Luganda | lg |
| Luxembourgish | lb |
| Macedonian | mk |
| Malagasy | mg |
| Malay | ms |
| Malayalam | ml |
| Maltese | mt |
| Manx | gv |
| Māori | mi |
| Marathi | mr |
| Marshallese | mh |
| Mongolian | mn |
| Nauru | na |
| Navajo | nv |
| Ndonga | ng |
| Nepali | ne |
| North Ndebele | nd |
| Northern Sami | se |
| Norwegian | no |
| Norwegian Bokmål | nb |
| Norwegian Nynorsk | nn |
| Nuosu | ii |
| Occitan | oc |
| Ojibwe | oj |
| Old Church Slavonic | cu |
| Oriya | or |
| Oromo | om |
| Ossetian | os |
| Pāli | pi |
| Panjabi | pa |
| Pashto | ps |
| Persian | fa |
| Polish | pl |
| Portuguese | pt |
| Quechua | qu |
| Romanian | ro |
| Romansh | rm |
| Russian | ru |
| Samoan | sm |
| Sango | sg |
| Sanskrit | sa |
| Sardinian | sc |
| Scottish Gaelic | gd |
| Serbian | sr |
| Shona | sn |
| Sindhi | sd |
| Sinhala | si |
| Slovak | sk |
| Slovene | sl |
| Somali | so |
| South Ndebele | nr |
| Southern Sotho | st |
| Spanish | es |
| Sundanese | su |
| Swahili | sw |
| Swati | ss |
| Swedish | sv |
| Tagalog | tl |
| Tahitian | ty |
| Tajik | tg |
| Tamil | ta |
| Tatar | tt |
| Telugu | te |
| Thai | th |
| Tibetan | bo |
| Tigrinya | ti |
| Tonga | to |
| Tsonga | ts |
| Tswana | tn |
| Turkish | tr |
| Turkmen | tk |
| Twi | tw |
| Ukrainian | uk |
| Urdu | ur |
| Uyghur | ug |
| Uzbek | uz |
| Venda | ve |
| Vietnamese | vi |
| Volapük | vo |
| Walloon | wa |
| Welsh | cy |
| Western Frisian | fy |
| Wolof | wo |
| Xhosa | xh |
| Yiddish | yi |
| Yoruba | yo |
| Zhuang | za |
# Make
Source: https://www.ayrshare.com/docs/packages-guides/make
Integrate the Ayrshare API into your Make app to manage your users' social media accounts
## Overview
[Make](https://make.com) is a no-code automation tool that allows you to connect apps and automate workflows.
The Ayrshare API can be integrated into your Make app to manage your users' social media accounts.
## Tutorial
**Post To Social Media From Your Website Form Using Make + Ayrshare + Wordpress + Contact Form 7**
A video tutorial on how you can post to your user's social media accounts using the no-code tool Make, formerly Integromat, and Ayrshare.
Managing your users' social accounts requires the [business plan](/docs/multiple-users/business-plan-overview), but you can similarly manage your own social accounts with the Premium plan using just the [API KEY](/docs/apis/overview#authorization) in the request header.
## Make X Integration
While [Make has ended their X integration](https://www.ayrshare.com/blog/make-coms-x-integration-alternative/), you can still use the Ayrshare API to create Make automations to manage your users' X social media accounts.
## Learn More
Learn more about no-code [Make](https://www.make.com/en).
Learn more about the [Contact Form 7 plugin](https://wordpress.org/plugins/contact-form-7/).
Learn more about the Contact Form 7 and [Redirections, Integrations, and Database
plugin](https://wordpress.org/plugins/cf7-redirections-integrations-and-database/).
# n8n
Source: https://www.ayrshare.com/docs/packages-guides/n8n
Integrate the Ayrshare social media API into your n8n workflows to publish, schedule, and analyze your users' social media accounts.
## Overview
[n8n](https://n8n.io) is a workflow automation platform that lets you connect apps and orchestrate processes, including AI agents, on Cloud or self-hosted.
The Ayrshare social media API can be integrated into your n8n workflows to manage your users' social media accounts. One API call publishes to Facebook, Instagram, LinkedIn, YouTube, TikTok, Pinterest, Reddit, Threads, Bluesky, Telegram, Google Business Profile, Snapchat, and X, so you do not write or maintain per-platform API code.
There are two ways to connect:
**MCP Server (agent-driven).** Attach the [Ayrshare MCP Server](/docs/additional/mcp-action-server) to n8n's built-in MCP Client Tool node, and your AI Agent can run the whole loop on its own: draft a post, validate it against each network's rules, publish or schedule it, then read the analytics back. There is nothing to host and no community node to install.
**REST API (fixed workflow).** For deterministic, non-agent workflows, call the [Ayrshare REST API](/docs/apis/overview) directly from an HTTP Request node.
Managing your users' social accounts requires the [Business plan](/docs/multiple-users/business-plan-overview), but you can similarly manage your own social accounts with the Premium plan using just the [API Key](/docs/apis/overview#authorization) in the request header.
## How it connects
With the MCP path, the **AI Agent** node is the brain. The **MCP Client Tool** sub-node attaches to it, connects to the Ayrshare MCP Server, discovers the available tools, and exposes them to the agent. When the agent acts, the node dispatches the call to Ayrshare, which publishes to the networks.
```
Trigger -> AI Agent (+ Chat Model) -> MCP Client Tool -> Ayrshare MCP Server -> social networks
```
Use the **HTTP Streamable** transport, not SSE. The [n8n guide](/docs/additional/mcp-n8n) covers transport, authentication, and setup in detail.
## Guide
The full n8n guide covers the MCP-first path end to end: prerequisites, setting up the MCP Client Tool node, the validate-first system prompt, worked examples (draft and publish from a chat message, auto-publish new content, a weekly analytics digest), acting on behalf of clients with sub-profiles, keeping a human in the loop, the REST fallback, and troubleshooting.
Connect n8n's AI Agent to the Ayrshare MCP Server to publish, schedule, and analyze across your social networks, with no per-platform API code.
A ready-to-import workflow: Chat Trigger, AI Agent, an Anthropic chat model, and the Ayrshare MCP node pre-wired with the validate-first system prompt.
## Posting to X (formerly Twitter)
In n8n, switch the MCP Client Tool node's **Authentication** to **Multiple Headers** and add the two `X-Twitter-OAuth1-*` headers alongside `Authorization`. See [Connect & Setup → X/Twitter BYO credentials](/docs/additional/mcp-action-connect#xtwitter-byo-credentials).
## Learn more
Learn more about [n8n](https://n8n.io) and its [AI Agent](https://docs.n8n.io/advanced-ai/) and [MCP Client Tool](https://docs.n8n.io/integrations/builtin/cluster-nodes/sub-nodes/n8n-nodes-langchain.toolmcp/) nodes.
See the [MCP Server overview](/docs/additional/mcp-action-server) for what the server is and how it maps to the Ayrshare API.
Browse the [Tool Catalog](/docs/additional/mcp-action-tools) for the tools your agent can call, grouped by domain.
Read [Connect & Setup](/docs/additional/mcp-action-connect) for endpoint, transport, authentication, and profile targeting details.
# Node.js NPM
Source: https://www.ayrshare.com/docs/packages-guides/nodejs
Integrate the Ayrshare API into your Node app with the Social API NPM Package
## Overview
Ayrshare's [Social API NPM Package](https://www.npmjs.com/package/social-media-api) allows you to integrate the Ayrshare API into your Node.js app.
### Installation
Install the Social API NPM Package if you use Node on the server-side.
The package simplifies the calls by wrapping the RESTful calls.
```bash theme={"system"}
npm i social-media-api
```
Obtain your secret API Key in the [Ayrshare Dashboard](https://app.ayrshare.com/).
### General Usage
Examples of Post, History, and Delete:
**Posting to X/Twitter?** As of March 31, 2026, X/Twitter operations through Ayrshare require your own X Developer App credentials — Ayrshare enforces this on every X-bound call. Add the 2 BYO headers to your request. See the [setup guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for details.
As of v1.3.0 the SDK includes a `setTwitterByo(apiKey, apiSecret)` helper that attaches the two required `X-Twitter-OAuth1-*` headers to every subsequent request:
```javascript theme={"system"}
const SocialPost = require("social-media-api");
const social = new SocialPost(API_KEY)
.setTwitterByo(MY_X_API_KEY, MY_X_API_SECRET);
await social.post({
post: "Hello from BYO",
platforms: ["twitter"]
});
```
Use `clearTwitterByo()` to drop the headers — useful when reusing one SDK instance across tenants:
```javascript theme={"system"}
social.clearTwitterByo().setTwitterByo(nextTenant.key, nextTenant.secret);
```
```javascript theme={"system"}
const SocialPost = require("social-media-api");
const API_KEY = "API KEY"; // get an API Key at ayrshare.com
const social = new SocialPost(API_KEY);
const run = async () => {
/** post */
const post = await social
.post({
post: "One more time",
platforms: ["twitter", "facebook", "linkedin"],
profileKey: "DJKJDK-SKDJKDJF" // used with a User Profile
})
.catch(console.error);
console.log(post);
/** history */
const history = await social.history().catch(console.error);
console.log(history);
/** delete */
const deletePost = await social.delete({ id: post.id }).catch(console.error);
console.log(deletePost);
};
run();
```
### Video Overview of the Social Media API NPM Package
Post to Social Media via an API
### Profile Key
You may specify the Profile Key for User Profile in the body of a POST or query of a GET with the `profileKey` field.
### Social API Demo
For a sample Node.js integration (using the RESTful API calls), see the GitHub repository:
The Social API Demo is a web application that allows users to compose, schedule, and post content
to multiple social media platforms simultaneously.
### More Information and Documentation
# Notion
Source: https://www.ayrshare.com/docs/packages-guides/notion
Integrate the Ayrshare API into your Notion app to manage your users' social media accounts
## Overview
[Notion](https://notion.so) is a workspace app that combines note-taking, project management, wikis, and a customizable database into a GUI interface.
From Notion, you can build an interface to manage your users' social media accounts with Ayrshare's social media API, allowing you to post, get analytics, and manage comments.
## Tutorial
A video tutorial on how you can post to your social media networks directly from Notion.
Also see our [Notion API walk-through guide](https://www.ayrshare.com/blog/schedule-social-media-posts-from-notion/).
Github code of Notion social posting integration:
Post to your social media networks directly from Notion
### Create a Notion Database
In Notion, create a database in table view with the following column names and column types:
`Post` as *Title column* type (you don't have a choice here with the column type)
`Platforms` as *Multi Select column* type with values: `facebook`, `instagram`, `twitter`,
`linkedin`, `tiktok`, and/or `telegram`.
`Images` as *Files & Media column* type.
`Profile Keys` as *Text column* type.
`Status` as *Text column* type.
`Schedule Date` as *Date column* type with Date Format Month/Day/Year, Time Format 24 Hours, and
include time
These fields will be used in the script specified later in this page. Please note, some social networks "platforms" require images or videos. For example, Instagram requires an image or video and TikTok requires a video. Please see the [endpoints](/docs/apis/post/social-networks/facebook) for the different networks.
[See a live Notion example](https://ayrshare-example.notion.site/607c15ce7872456a879adbb0a5f17fdf?v=ee9f65a4afb24033813f245a45bc9e83)
### Enter in Test Post Data
We need some sample data to test the post. Here is a suggestion:
`Post`: Enter "Happy New Year!"
`Platforms`: select one or more networks you have linked. Please be sure the name is lowercase.
`Images`: Attach an [image](https://img.ayrshare.com/012/gb.jpg) or a video.
**You must upload an image to Notion.** You cannot use an image URL.
`Profile Keys`: If you are on the Business Plan or Launch Plan and want to post to a client's profile, enter
their Profile Key. Otherwise, leave blank.
`Status`: Enter "pending". The script only grabs records that are set to "pending". Please be
sure "pending" is lowercase.
`Schedule Date`: Leave blank since we'll just test immediate posting right now. Later you can
select a future date to schedule the post.
### Create Internal Integration in Notion
Go to the [My Integrations page](https://www.notion.so/my-integrations) in Notion and click on New Integration.
[Learn more about Notion Integrations](https://developers.notion.com/docs/getting-started#utilizing-notions-public-api-for-integrations).
You can name the integration "Ayrshare" to identify it easily and choose the appropriate workspace that will have the post data.
Finally, the default capabilities that have been selected for you will do. Submit to create the integration.
If successful, an internal integration token will be available to you. Note this for future steps in this page.
And gather your Notion integration token.
### Connect Notion Database to the Internal Integration
Open the Notion database that you created earlier. Click on the ellipsis on the top right corner of the page and go to **Add Connection**.
Here you can search for the internal integration you created in the previous step by the name you chose for it.
Once you click on the internal integration, you have now connected this Notion database to the integration.
### Run script to Send Posts from Notion
You can now run a script in your local environment that will read data from the Notion database and make a post through the Ayrshare API for each row in it with status of "pending".
Make sure to set the following environment variables used in the script:
`API_KEY`: this is `API Key` you get from Ayrshare. This is the primary API Key for your
Ayrshare primary profile.
`NOTION_DATABASE_ID`: Open the database you created earlier in this page and get the database ID
from the URL.
The database ID will be the value before the ?v= in the database page URL.
```html theme={"system"}
https://www.notion.so/company/?v=aaee9f
```
`NOTION_KEY`: internal integration token from earlier.
Run the following JavaScript in a Node.js environment:
cd into the **notion** directory and run `npm install`.
Update the `.env` file with your Ayrshare `API_KEY`, Notion `NOTION_KEY` and
`NOTION_DATABASE_ID`.
Run `node index.js`
You can run it at [Heroku](https://www.heroku.com/), [Digital Ocean](https://www.digitalocean.com/), or [Vercel](https://vercel.com/) in production.
If successful, all `pending` status columns will be changed to `success` and the posts will have been made to the appropriate social networks.
Post to your social media networks directly from Notion
# Python PyPI
Source: https://www.ayrshare.com/docs/packages-guides/python
Python PyPI client package for Ayrshare
## Overview
Ayrshare's [Social-Post-API PyPI Package](https://pypi.org/project/social-post-api/) allows you to integrate the Ayrshare API into your Python app.
### Installation
Install the [Social-Post-API PyPI Package](https://pypi.org/project/social-post-api/) if you use Python on the server-side. The package simplifies the calls by wrapping the RESTful calls.
Start by getting your secret API Key in [Ayrshare Dashboard](https://app.ayrshare.com/api).
Next, install the Python package:
```bash theme={"system"}
pip install social-post-api
```
### General Usage
Examples of Post, History, and Delete. Please see the [PyPI Package](https://pypi.org/project/social-post-api/) for more information.
**Posting to X/Twitter?** As of March 31, 2026, X/Twitter operations through Ayrshare require your own X Developer App credentials — Ayrshare enforces this on every X-bound call. Add the 2 BYO headers to your request. See the [setup guide](/docs/dashboard/connect-social-accounts/x-twitter-byo-keys) for details.
As of v1.3.0 the SDK includes a `set_twitter_byo(api_key, api_secret)` helper that attaches the two required `X-Twitter-OAuth1-*` headers to every subsequent request:
```python theme={"system"}
from ayrshare import SocialPost
social = SocialPost(API_KEY)
social.set_twitter_byo(MY_X_API_KEY, MY_X_API_SECRET)
social.post({"post": "Hello from BYO", "platforms": ["twitter"]})
```
Use `clear_twitter_byo()` to drop the headers — useful when reusing one SDK instance across tenants:
```python theme={"system"}
social.clear_twitter_byo().set_twitter_byo(next_tenant_key, next_tenant_secret)
```
```python theme={"system"}
from ayrshare import SocialPost
social = SocialPost('8jKj782Aw8910dCN') # get an API Key at ayrshare.com
# Required for any post that includes 'twitter' in platforms (BYO is enforced).
social.set_twitter_byo('YOUR_X_CONSUMER_KEY', 'YOUR_X_CONSUMER_SECRET')
# Post to Platforms Twitter, Facebook, and LinkedIn
postResult = social.post({'post': 'Nice Posting 2', 'platforms': ['twitter', 'facebook', 'linkedin'], 'profileKey': 'JKSDJI-JKKJKKJ'})
print(postResult)
# Delete (use the top-level Ayrshare post id from postResult['id'])
deleteResult = social.delete({'id': postResult['id']})
print(deleteResult)
# History
print(social.history())
```
### Profile Key
You may specify the Profile Key for User Profile in the body of a POST or query of a GET with the `profileKey` field.
### More Information and Documentation
# Retool
Source: https://www.ayrshare.com/docs/packages-guides/retool
Integrate the Ayrshare API into your Retool app to manage your users' social media accounts
## Overview
[Retool](https://retool.com/) is a very powerful internal no-code builder used extensively by companies such as Amazon, DoorDash, and Lyft. With Retool, you can build amazing workflows, such as automatically posting to social media, and it is easy to get started in a few minutes. We use Retool extensively ourselves.
In this walk-through video we will show how an agency or a marketing team can build their own social media management system using Retool without the need to touch code.
The final social app will let you enter in the post text, add an image, select which social networks you want to target including Facebook, Twitter, Instagram, and LinkedIn, and then send the post and get a response that the post succeeded.
Follow this video tutorial to build your own social media posting app using the leading social media API and the leading internal tools builder.
Social Media Scheduler Retool
## Build A X/Twitter Analytics App in Retool
This video is a tutorial which shows how you can build a Twitter Analytics app in Retool. Retool is one of the most powerful tools for building apps with little or no code needed.
In this video we explain how to do the following:
1. Create the HTTP Rest API call to get historical Tweets from Twitter.
2. Create a listview with the historical Tweets, including the post body, timestamp of creation, and a link to the Tweet on twitter.com.
3. Pull in analytics metrics including the count of likes, impressions, retweets, replies, profile clicks, and link clicks.
# Hurl
Source: https://www.ayrshare.com/docs/testing/hurl
Test your API requests with Hurl
[Hurl](https://hurl.dev/) is a command line tool that runs HTTP requests defined in a simple plain text format. It is great for quickly testing your API calls. You can learn more about [how to use Hurl](https://www.ayrshare.com/blog/hurl-run-and-test-http-api-requests/) on our blog.
After you are set up, you may use these .hurl files to run your test.
1. Update the var.env with your API Key.
2. Add in `profileKeys` to the requests if you are testing a user profile.
3. Modify the hurl files if you have not linked all the social networks.
Test Ayrshare's social media APIs using HURL scripts. Including testing posting images, videos,
and getting analytics.
# Post Verification
Source: https://www.ayrshare.com/docs/testing/post-verification
How Ayrshare verifies your posts to protect your accounts with the Social Post Verification System.
The Ayrshare Social Post Verification System analyzes your posts for compliance with the social networks' guidelines.
Most of the social networks have rules around what content is allowed to be posted and how frequently posts can be made.
Breaking these rules can result in your social account being locked, suspended, or even shadow banned.
[Shadow banning](https://www.ayrshare.com/blog/avoid-using-these-instagram-banned-hashtags/) is when
your social account is still active and you can still post, but users aren't seeing the posts
because the network banned you...but didn't tell you. Often a steep loss of engagement is an
indication of a shadow ban.
## Social Post Verification System
Every post sent through Ayrshare goes through a verification check to minimize the risk of being rejected by the social networks. This helps keep your social account in good standing with the networks.
The following are some of the checks performed by the Social Post Verification System:
Limit the number of repeat mentions. *We recommend to not mention the same handle more than once
a week.* Your own handle is always allowed. We also will limit the number of mentions per day to
stay in compliance with the [social networks' policies](/docs/testing/post-verification#mentions). A
connected social account may only mention the same handle once per day.
Prevent duplicate and similar posts. Please [see
below.](/docs/testing/post-verification#duplicate-and-similar-posts)
Spam detector to help prevent the social networks from marking your account as spam. This
includes reviewing the frequency of posting over a period of time to prevent abuse of the social
networks' services.
Remove banned Instagram hashtag and hashtag count complies with guidelines.
Verify the post length meets the social networks' requirements. For example, is the tweet length
280 characters or less. Please see [TweetStorm](/docs/apis/post/social-networks/x-twitter) for using
Twitter Threads for longer posts.
Verify images and videos are valid and comply with network
[requirements](/docs/media-guidelines/overview).
Check for URLs that go against the social networks' policies, such as adult content.
Check images for content deemed inappropriate by the social networks, such as adult content or
extreme violence.
Limit the number of post within a given time period. For example Instagram only allows 50 posts
per account during a rolling 24-hour period and LinkedIn only allows 150 posts per account every
24 hours.
## Duplicate and Similar Posts
**Every post should be as unique as possible.**
Cross-posting is sharing the exact same post across different social media networks, or on the same account multiple times. It is not recommended.
Your audience doesn't like the same story over and over again, and neither do the social networks.
The social networks frown on duplicate and similar posts. These posts get poor visibility and engagement, and sometimes the networks suspend or ban accounts with too many duplicate or similar posts.
The social network X, for example, explicitly **does not allow duplicate content** posted across multiple X handles. Violation of this rule will lead to a suspended account.
Ayrshare prevents duplicate and similar posts from being scheduled within **two days** of each other using several algorithms including [Dice's Co-Efficient](https://en.wikipedia.org/wiki/S%C3%B8rensen%E2%80%93Dice_coefficient).
Please see the [Max Pack Generate API endpoint](/docs/apis/generate/overview) on how to create variations of posts.
For more information on duplicate posts see [Dealing with Duplicate Posts](/docs/help-center/technical-support/dealing_with_duplicate_posts).
## Mentions
**Only mention users who have **clearly** indicated a desire to be contacted by you.** For example, if a user has directly mentioned your account or your brand name, thats a good sign that they're interested in receiving a response from you. Bulk or automated unsolicited mentions in response to generic or broad discussions of a topic or industry are prohibited. In the absence of other interactions, following your account does not constitute an intent to be automatically contacted by you.
Continuously mentioning the same handle in a short period, especially if the mentions are unsolicited or irrelevant, could lead to your account being restricted or banned due to spammy behavior.
**What This Means**
Every time you mention a handle, the handle's owner gets a notification of the mention. Mentioning the same handle repeatedly could be considered spam or even harassment by the social networks.
**Mention Restriction**
A connected Ayrshare social account may **only mention the same handle once per day** and are allowed up to **five mentions per post**. To prevent abuse, deleted posts with mentions count towards the total.
Ayrshare has established mention limits based on extensive experience with social network APIs. These restrictions reflect both official guidelines and observed practices of various platforms. The limits are designed to ensure users comply with each social network's policies and maintain good standing on these platforms.
**Recommendation**
*We recommend not mentioning the same handle more than once a week.* Instead of doing an @mention, use a hashtag such as #Name or just directly include the person/company's name in the post text. The social networks have great search engines that will surface the content.
## Recommended Posting Limits
We recommend limiting the number of post within a given time period to maximize views and engagement.
Some social networks have hard limits. For example, Instagram only allows 50 posts per account during a rolling 24-hour period, TikTok 15 per day, and LinkedIn 150 posts per day.
Ayrshare will ensure that the hard limits set by the networks are abided by.
Each social network has recommendations on daily post limits. Going over these limits typically *decreases views and engagement*.
When it comes to posting on the social networks, more is not necessarily better.
For example, Facebook recommends no more than 5 daily posts, and over 25 posts could negatively impact engagement and cause [partial blocking](/docs/help-center/technical-support/facebook_or_instagram_account_restricted#facebook-message-we-limit-how-often-you-can-post-comment-or-do-other-things-in-a-given-amount-of-time-in-order-to-help-protect-the-community-from-spam-you-can-try-again-later).
In other words, if you post above the recommended limit the social network will likely deem you a spammer and start hiding your content.
You also want to be cautious if you're posting on a newly created social account. The social networks will often block new accounts that post too frequently.
The following are the recommended social posting limits:
| Social Network | Recommended Daily Limits |
| :----------------- | -----------------------: |
| Bluesky | 50 |
| Facebook | 25 |
| Google My Business | 15 |
| Instagram | 30 |
| LinkedIn | 25 |
| Pinterest | 20 |
| Reddit | 40 |
| Snapchat | 30 |
| Telegram | 25 |
| Threads | 50 |
| TikTok | 15 |
| X | 50 |
| YouTube | 10 |
While we try not to limit your posting, we will halt posting on a social network if we detect that you are posting too frequently over a period of time.
This is to help protect your account from being suspended or banned and to be good partners with the social networks.
**All posts are subject to Ayrshare's fair use policy to prevent abuse of the social networks' services.**
## Banned Hashtags
[Banned Instagram](https://www.ayrshare.com/blog/avoid-using-these-instagram-banned-hashtags/) hashtags automatically removed from posts.
## X Automated Label
X allows you to label your X account as "Automated". This is required by X for all accounts that send automated, programmatically generated posts.
For example if you automated weather, stock, or news updated that had no human intervention is writing.
One of the benefits of this label is that other X users will have better transparency and insight into tweets that come from bots.
### How to Turn on Twitter Automated Bot Label
Please turn on the Automated label by:
1. Log into your X account.
2. Go to your account settings.
3. Select "Your account".
4. Select "Automation".
5. Select "Managing account".
6. Next, select the X account, which runs your bot account. This is required to identify the owner of the bot account.
7. Enter your password to log in.
8. Finally, you should see confirmation that the label has been applied to your account.
For additional information see [here](https://www.ayrshare.com/blog/twitter-launches-automated-label-for-bots/).
# Postman
Source: https://www.ayrshare.com/docs/testing/postman
Test your REST API calls with Postman
Postman is a great tool to test HTTP API endpoint calls. We recommend first using Postman to more easily diagnose issues.
Click the "Run in Postman" button to ***fork a version in Postman*** for the web:
[](https://god.gw.postman.com/run-collection/7602335-776bf0f9-c710-43cf-b3a2-7987801887f3?action=collection%2Ffork\&collection-url=entityId%3D7602335-776bf0f9-c710-43cf-b3a2-7987801887f3%26entityType%3Dcollection%26workspaceId%3Dcf2bf012-ff59-48a6-ba37-cf4864d2e43c)
After forking we recommend you [download Postman](https://www.postman.com/downloads/) for free and use locally.
The desktop version is more reliable and has more features.
Be sure to set your `Authorization: Bearer API_Key` value or Profile Key in the header.
Also, set the environment variable of \{API\_Key} with your API\_KEY.
**Postman Tips**
You can add a variable value, such as a global variable like API\_KEY to make
it easier to make your API calls in Postman. [More details how to do
this](https://learning.postman.com/docs/sending-requests/variables/variables/)
on the Postman site.
You can send an array as a variable in the Postman body set as x-www-form-urlencoded by setting the key with a \[0] value. For example, to send a post, you can set the key platforms\[0] to the first value and platforms\[1] for the second value.
## Test with Random Text and Images
We also recommend you test with [random text and images](/docs/quickstart#publish-test-posts) so your accounts are not locked by the social networks.
## Auto Generate API Code with Postman
You can even automatically generate code directly from Postman in most programming languages - Node.js, PHP, Python, C#, and more. See the video for details on how to use Postman and generate code.
# Validation Endpoints
Source: https://www.ayrshare.com/docs/testing/validation-endpoints
Validate social posts, JSON, and media
Please see here for more information validation endpoints:
Validate social posts, JSON, and media