Skip to main content
Ayrshare
Ayrshare is a trademark of its respective owner, used here for identification and migration comparison only. No endorsement, partnership, or affiliation is implied.
Ayrshare is a social media API: link a set of social accounts, then publish, schedule, and pull analytics across 10+ networks with one /post call. It does multi-network publishing well — a broad platform matrix, per-platform options, comments, DMs, RSS auto-posting, and (on the Business plan) User Profiles so you can act on behalf of many end-users. But when the thing doing the posting is an agent that also holds cards, an inbox, a phone number, and a KYC’d identity, an Ayrshare account is a disconnected vendor account:
  • Publishing lives behind an Ayrshare API key, and per-end-user separation is an Ayrshare Profile Key (Business plan) — an identity that exists only inside Ayrshare, unrelated to where the same agent’s cards, email, and KYC live.
  • Whether the agent may post, and how much it may spend doing so, is not something Ayrshare governs — it is a key you hold. There is no execution-time “can this agent post right now?” check tied to the agent’s broader permission set.
  • “Which agent posted this, for which end-user, and who let it?” is answered in Ayrshare’s post history for social, and in unrelated systems for the agent’s spend, comms, and identity.
Naive’s social primitive gives the agent the same capability — connect accounts over OAuth, then create/schedule/publish across the major networks and read analytics back — but posting is one primitive on one governed account:
  • The Account Kit that decides whether the agent may issue a card, send email, or buy a domain also decides whether it may use social at all — checked at execution time, not in a separate dashboard.
  • Publishing spend is metered in the same credit balance and budget ceiling as every other primitive, so a runaway agent hits one cap, not a separate Ayrshare bill.
  • Every post records the acting agent and lands in the same per-user activity log as its card spend, email sends, and KYC events.
This guide maps Ayrshare’s publishing API to Naive’s, shows the smallest working swap, and is explicit about what does not map yet — most importantly, that Naive social is workspace-scoped today, not per-end-user isolated the way Ayrshare Profile Keys are.
Tested against: the Ayrshare Node SDK social-media-api v1.3.0 (against the Ayrshare REST API, base https://api.ayrshare.com/api, /post, /profiles, /analytics, /history endpoints, docs snapshot July 2026), and the Naive Node SDK @usenaive-sdk/server against the Naive API (base https://api.usenaive.ai/v1, /social/* endpoints, docs snapshot July 2026).Version notes:
  • Scope model differs. Ayrshare authenticates with an account-wide API key and (Business plan) scopes an end-user with a Profile Key header. Naive authenticates per workspace and scopes an end-user with naive.forUser(id) — the same handle that reaches every other primitive. See what doesn’t map yet for the isolation caveat.
  • Publish shape is close. Ayrshare social.post({ post, platforms, mediaUrls }) → Naive client.social.createPost({ content, platforms, media_urls, publish_now: true }). The core publish/schedule/list/analytics path is a near one-to-one swap.
  • Platform names differ in case and coverage. Ayrshare uses lowercase (twitter, linkedin); Naive uses uppercase (TWITTER, LINKEDIN). Naive supports 11 networks and adds MASTODON; Ayrshare additionally covers gmb (Google Business Profile), snapchat, and telegram, which Naive does not — see gaps.
  • X/Twitter BYO. As of March 31, 2026, Ayrshare requires your own X Developer App credentials (setTwitterByo(...)). Naive posts X through its provider without you supplying X app keys.
  • No equivalent yet for Ayrshare comments/DMs, RSS auto-posting, auto-schedule, auto-repost, the link shortener, or reviews — see what doesn’t map yet.

Concept map

AyrshareNaiveNotes
new SocialMediaAPI(apiKey)new Naive({ apiKey }) then naive.forUser(id)Server-side credential in both cases
Account API Key + (Business) Profile Key per end-usertenant user via naive.forUser(id) — scopes every primitiveSee the isolation caveat — Naive social data is workspace-scoped today
Link accounts via POST /api/profiles/generateJWT → hosted linking URLPOST /v1/social/connect { platform, redirect_url } → OAuth URL, or POST /v1/social/portal for multi-platformBoth return a URL the user opens to authorize; Naive’s portal can hide “powered by” branding
social.post({ post, platforms, mediaUrls })POST /api/postclient.social.createPost({ content, platforms, media_urls, publish_now: true })POST /v1/social/postsPublish now to the listed networks
scheduleDate: "2026-07-08T12:30:00Z"createPost({ ..., scheduled_at: "2026-07-08T12:30:00Z" })ISO-8601 UTC on both sides
— (post is immediate or scheduled)Omit publish_now/scheduled_atdraft, then POST /v1/social/posts/:id/publishDraft/edit-then-publish is a Naive addition
social.delete({ id })DELETE /api/postDELETE /v1/social/posts/:idDelete a post (subject to per-network limits)
social.history()GET /api/historyclient.social.listPosts()GET /v1/social/postsList the agent’s posts
social.analyticsPost({ id, platforms })POST /api/analytics/postGET /v1/social/posts/:id/analyticsPer-post metrics
Social-network analytics POST /api/analytics/socialGET /v1/social/accounts/:id/analyticsAccount-level metrics
mediaUrls: ["https://..."]media_urls: ["https://..."] (auto-uploaded) or pre-uploaded upload_idsNaive downloads + attaches to media-capable platforms
Profile Key gate (a key you hold)Account Kit social primitive enabled: true/false per userPermission is execution-time policy on the identity — see gain #2
Account-wide Ayrshare billingSame credit balance + budget ceiling as every primitivePublishing costs 1 credit; drafts are free
gmb, snapchat, telegram platformsNot supported on Naive today
Comments / DMs, RSS auto-posting, auto-schedule, auto-repost, link shortener, reviews— (posts have read-only comments)See gaps

Before / after: the core path

The path that matters for almost every agent is publish a post to a few networks, then read it back / pull analytics. Here it is on both platforms.
import SocialMediaAPI from "social-media-api";

// One account-wide API key. On the Business plan you scope an end-user by
// passing their Profile Key — an identity that exists only inside Ayrshare.
const social = new SocialMediaAPI(process.env.AYRSHARE_API_KEY!);

// 1. Publish now (POST /api/post)
const post = await social.post({
  post: "We just shipped agent-native social posting!",
  platforms: ["twitter", "linkedin"],
  mediaUrls: ["https://cdn.example.com/launch.png"],
  profileKeys: [process.env.ACME_PROFILE_KEY!], // Business plan, per end-user
});

// 2. Pull analytics for the post (POST /api/analytics/post)
const stats = await social.analyticsPost({
  id: post.id,
  platforms: ["twitter", "linkedin"],
});

// The card, inbox, phone, and KYC for this customer's agent live in entirely
// separate systems — and whether the agent "may post" is a key you hold, not a
// governed, execution-time decision.
import { Naive } from "@usenaive-sdk/server";

const naive = new Naive({ apiKey: process.env.NAIVE_API_KEY! });
const client = naive.forUser("acme"); // same id space as your own users

// 1. Publish now (POST /v1/social/posts) — platforms are UPPERCASE
const post = await client.social.createPost({
  content: "We just shipped agent-native social posting!",
  platforms: ["TWITTER", "LINKEDIN"],
  media_urls: ["https://cdn.example.com/launch.png"],
  publish_now: true,
});

// 2. Pull analytics for the post (GET /v1/social/posts/:id/analytics)
const res = await fetch(
  `https://api.usenaive.ai/v1/social/posts/${post.id}/analytics`,
  { headers: { Authorization: `Bearer ${process.env.NAIVE_API_KEY}` } },
);
const { analytics } = await res.json();

// Whether this agent may post at all is its Account Kit's `social` primitive,
// checked at execution time; the 1-credit publish counts against the SAME
// budget ceiling as its cards, email, and phone — and the post is logged
// against the acting agent.
The publish/analytics shape lines up closely. The real differences to plan for:
  • Platform names are uppercase. twitterTWITTER, linkedinLINKEDIN, etc. Naive supports TWITTER, LINKEDIN, INSTAGRAM, FACEBOOK, TIKTOK, YOUTUBE, THREADS, PINTEREST, REDDIT, BLUESKY, and MASTODON.
  • postcontent, mediaUrlsmedia_urls. Naive downloads each media URL and attaches it to media-capable platforms; text-only platforms are unaffected.
  • Publish is explicit. Set publish_now: true to post immediately, scheduled_at to schedule, or omit both to save a draft you can edit and publish later.
  • Accounts are connected first. Before the first post, connect accounts with POST /v1/social/connect (or the multi-platform POST /v1/social/portal) and POST /v1/social/sync — the equivalent of linking accounts through Ayrshare’s generateJWT URL.

Minimal viable migration

The smallest swap that keeps a working agent running is connect + publish + list/delete.
1

Install the SDK and set your key

npm install @usenaive-sdk/server
Set NAIVE_API_KEY (a server-side key from the dashboard).
2

Activate + connect the accounts

Replace Ayrshare’s generateJWT linking flow with Naive’s connect flow: POST /v1/social/activate once, then POST /v1/social/connect { platform, redirect_url } (or POST /v1/social/portal to link several at once). Open the returned url for the user to authorize, then call POST /v1/social/sync to pick up the connected accounts.
3

Swap the publish call

Map social.post({ post, platforms, mediaUrls })client.social.createPost({ content, platforms, media_urls, publish_now: true }). Uppercase the platform names and rename postcontent, mediaUrlsmedia_urls. For scheduling, pass scheduled_at instead of scheduleDate.
4

Swap list + delete

Map social.history()client.social.listPosts() (GET /v1/social/posts, filter with ?status=), and social.delete({ id })DELETE /v1/social/posts/:id. Note some networks (Instagram, TikTok) don’t allow API deletes on either platform.
5

Swap analytics (optional)

Map social.analyticsPost({ id, platforms })GET /v1/social/posts/:id/analytics, and account-level social.analyticsSocial(...)GET /v1/social/accounts/:id/analytics.
6

Ship it

At this point the agent’s publish path is off Ayrshare. Everything below is upside, not a requirement.

Consolidate further once you’re on Naive

This is where the migration pays for itself. In Ayrshare, posting is a self-contained account: an API key, optional Profile Keys, and its own billing — disconnected from the agent’s money, comms, and identity. On Naive, social is one primitive on the same account and Account Kit that governs the agent’s cards, email, phone, and vault.
// The API key posts; the Profile Key scopes an Ayrshare-only identity.
const social = new SocialMediaAPI(process.env.AYRSHARE_API_KEY!);
await social.post({
  post: "Launch day!",
  platforms: ["twitter", "linkedin"],
  profileKeys: [process.env.ACME_PROFILE_KEY!],
});

// The card, inbox, phone, and KYC for this customer's agent live elsewhere —
// separate accounts, separate billing, separate audit — and "may this agent
// post?" is a key you hold, not a governed decision.
// One tenant user per customer; the same handle reaches every primitive.
const acme = await naive.users.create({
  external_id: dbCustomer.id,
  email: dbCustomer.email,
});

const client = naive.forUser(acme.id);

// Publishing is one primitive, gated + metered like the rest.
await client.social.createPost({
  content: "Launch day!",
  platforms: ["TWITTER", "LINKEDIN"],
  publish_now: true,
});

// The SAME client owns this customer's card, inbox, phone, and KYC — one
// account, one budget, one audit trail, every capability governed by its
// Account Kit.
await client.cards.create({ spending_limit_cents: 25_000 });
await client.email.createInbox({ local_part: "ops" });

Gain #1 — one account across primitives

  • With Ayrshare, social posting is an island behind its own key and billing. With Naive, naive.forUser(acme.id) is a single handle to social and cards and email and phone and KYC — no second vendor account, no Profile Keys to provision and rotate, no separate invoice.
  • Third-party connections (OAuth grants like Slack or Notion) and the agent’s native primitives sit under one identity and one Account Kit — the SaaS the agent connected and the networks it posts to, governed the same way.

Gain #2 — execution-time permission enforcement

  • Whether an agent may post at all is the social primitive on the user’s Account Kit, decided at execution time — not a key you gate separately from everything else the agent can do.
// This tier's agents get email + cards, but cannot post to social at all.
const kit = await naive.accountKits.create({
  name: "No-social tier",
  primitives_config: {
    email: { enabled: true },
    cards: { enabled: true },
    social: { enabled: false }, // social calls are refused with `forbidden`
  },
});
await naive.accountKits.assignUser(kit.id, acme.id);
  • The agent’s code path stays the same for every tier — client.social.createPost(...). Whether it runs is decided by policy: a user whose Account Kit does not enable social is refused with forbidden, with no code change on your side.
  • Publishing spends 1 credit against the same budget ceiling as the agent’s cards, phone, and LLM calls — so a misbehaving agent trips one combined cap, not a separate Ayrshare limit you monitor on its own.
Social publishing is gated by the primitive toggle and the budget, but it is not frozen for human approval by default — unlike money-moving primitives (cards, trading, domains). If you need a human in the loop before a post goes out, use the draft flow (create without publish_now/scheduled_at, review, then POST /v1/social/posts/:id/publish) or disable the social primitive for that tier.

Gain #3 — unified accountability

  • Every post records the acting agent and lands in one per-user activity log — alongside that customer’s card spend, email sends, and KYC events, not in a separate Ayrshare post history:
const { events } = await naive.forUser(acme.id).logs.query({ limit: 50 });
// "what did this agent do, for whom?" — social posts, card spend, email sends, one timeline
  • That is the question that is hard to answer when posts live in Ayrshare, cards live in Stripe, and the inbox lives somewhere else. Under Naive it is a single query.

What does not map yet

A migration guide that hides gaps is worse than none. The core path (connect → publish → schedule → list → analytics → delete) maps cleanly, but the following Ayrshare capabilities have no direct equivalent on Naive’s social primitive today. Check this list against your app before you commit.
Ayrshare featureStatus on NaiveWorkaround
Per-end-user isolation (Profile Keys separate each user’s linked accounts + posts)Partial — the social primitive is gated per user via Account Kits, but connected accounts and post data are workspace-scoped today (posts carry no per-user tenant id)Use one Naive workspace per end-user if you need hard data isolation now; per-user isolation of social is on the roadmap
gmb (Google Business Profile), snapchat, telegram platformsNot supported (Naive covers 11 networks incl. MASTODON)Keep Ayrshare for those specific networks, or post to the supported set
Comments + DMs (post/reply/get comments, direct messages)Read-only — GET /v1/social/posts/:id/comments; no comment/DM postingUse the platform’s own API for writing comments/DMs
RSS auto-posting, auto-schedule, auto-repost, auto-hashtagNot providedDrive scheduling from your own scheduler + scheduled_at
Link shortener (shortenLinks, custom domains) + link analyticsNot providedShorten links in your own code before createPost
Reviews (get/reply/delete on connected accounts)Not providedUse the platform’s own API
First comment, disable comments, per-network advanced optionsPartial — platform_data overrides per platform; not every Ayrshare option is surfacedPass supported fields via platform_data; otherwise not available
X/Twitter BYO credentials (setTwitterByo)Different model — Naive posts X via its provider; you don’t supply an X Developer AppNo action needed on Naive; you can’t reuse your Ayrshare X app config
JWT white-label linking URL on your domainPartial — POST /v1/social/portal returns a hosted OAuth URL (can hide “powered by”), not a JWT SSO URL on your domainUse the connect/portal URL for account linking
The biggest thing to weigh is isolation model, not method. Ayrshare’s Profile Keys (Business plan) give each of your end-users a genuinely separate set of linked accounts and post history inside Ayrshare. Naive’s social primitive is workspace-scoped today: the social toggle and budget are enforced per user through the Account Kit, but the connected accounts and the posts themselves are not yet isolated per end-user (a post has no per-user tenant id). If your product hard-requires that end users A and B never see or touch each other’s connected accounts, run a workspace per end-user for now, or keep Ayrshare for the social surface until per-user social isolation ships. Also note the platform coverage difference (gmb/snapchat/telegram are Ayrshare-only) and that comments/DMs are read-only on Naive — if those are load-bearing, they are the gaps most likely to matter.

Where to go next

  • social primitive — full connect / post / schedule / analytics lifecycle, platform matrix, and platform defaults
  • social SDK sub-client — typed listPosts / createPost
  • social CLInaive social connect / post per user
  • Account Kits — enabling/disabling the social primitive per user at execution time
  • Tenant users — the identity that owns social, cards, email, and phone
  • Billing — the shared credit balance and budget ceiling publishing spends against
  • Logs — the unified per-user activity trail every post lands in