Migrating from Zernio to bundle.social: A Developer's Guide
Endpoint-by-endpoint mapping, the object-model translation, and an honest list of what bundle.social does not do. Tokens cannot transfer between vendors, so re-consent sets the timeline, not engineering. How to run it in shadow mode first and flip tenant by tenant without duplicates.
This is the engineering runbook for moving a production social publishing integration off Zernio. It covers the object-model mapping, the endpoint-by-endpoint translation, the OAuth problem that determines your entire timeline, and a parallel-run plan with a rollback that actually works.

It is deliberately not a sales argument. If you are still deciding whether to move, the commercial comparison - pricing bands, feature matrix, buyer fit - lives on the Zernio alternative page, and it is a better use of your time than this one. Come back here once the decision is made.
One thing worth saying up front, because it shapes how you should read everything below: Zernio is a well-built product with unusually good documentation. Their published rate-limit tables, idempotency semantics, and multi-tenant guides are more detailed than most of the category. Migrating away from it is a question of fit - meter shape, platform coverage, tenancy model - not a rescue operation.
Before you migrate: three things that decide whether you should
Migrations are cheap to start and expensive to abandon halfway. Three checks, in order.
1. The two products meter different things
Zernio bills per connected social account, in graduated bands. bundle.social bills per published post, with connected accounts unlimited on every paid plan. Both figures verified 31 July 2026.
| Zernio: accounts | Rate | bundle.social | Price | Posts/month | |
|---|---|---|---|---|---|
| 1–2 | Free | Free | $0 | 20 (3 accounts) | |
| 3–10 | $6 each | Pro | $100 | 10,000 | |
| 11–100 | $3 each | Business | $400 | 100,000 | |
| 101+ | $1 each | Custom | Negotiated | Custom |
Because the meters measure different quantities, neither is universally cheaper. The crossover depends entirely on your posts-per-account ratio:
| Connected accounts | Zernio/month | bundle.social plan | bundle.social/month |
|---|---|---|---|
| 10 | $48 | Pro | $100 |
| 27 | $99 | Pro | $100 |
| 50 | $168 | Pro | $100 |
| 100 | $318 | Pro | $100 |
| 182 | $400 | Business | $400 |
| 500 | $718 | Pro or Business | $100–$400 |
| 1,000 | $1,218 | Pro or Business | $100–$400 |
Two break-even points, assuming you stay inside the post allowance: around 27 accounts against Pro, and around 182 accounts against Business.
Run the arithmetic in the other direction too, because it is the case people skip. Five connected accounts publishing 15,000 posts a month costs $18 on Zernio and $400 on bundle.social - the post meter puts you on Business while the account meter barely registers. A high-volume publisher with few accounts should not migrate for price. An agency or SaaS platform with hundreds of lightly-used client accounts is the profile where the account meter compounds against you.
2. Platform coverage is not identical, and the gaps run both ways
Fifteen platforms each, with a genuine asymmetry:
| Zernio | bundle.social | |
|---|---|---|
| Instagram, Facebook, TikTok, YouTube, LinkedIn, X, Threads, Pinterest, Reddit, Bluesky, Discord, Slack, Snapchat, Google Business | ✅ | ✅ |
| Mastodon | ❌ | ✅ |
| WhatsApp, Telegram | ✅ | ❌ |
| Ad networks (Meta, Google, TikTok, LinkedIn, Pinterest, X Ads) | ✅ | ❌ |
| DMs / inbox / conversations | ✅ | ❌ |
If your product depends on WhatsApp, Telegram, paid ads, or direct messages, stop reading. There is no migration path for those surfaces today and pretending otherwise would waste a sprint of your time. bundle.social does not ship direct messaging or ads, and there is no date to plan a cutover around.
3. Nobody is charging you per seat
The earlier version of this page argued against Zernio's "high per-seat pricing." That was wrong, and it is worth correcting explicitly rather than quietly deleting.
Neither vendor publishes a seat cap or a per-seat charge. Zernio's meter is connected accounts; team members are invited into a workspace without a published per-user fee. bundle.social's meter is published posts, also with no published seat cap. If you are migrating to escape per-seat billing, you are solving a problem that does not exist in either product. Migrate for the meter shape, the tenancy model, or the platform list - not for seats.

The part that decides your timeline: OAuth tokens do not migrate
This is the single most important fact in this document, and it is missing from most migration guides in this category, including ones written by vendors who know better.
You cannot transfer OAuth tokens from Zernio to bundle.social. Every end user must re-authorize. This is not a limitation either vendor chose. It is how the platforms work.
An OAuth access token is issued to a specific registered application - a specific client_id. Zernio's Meta app and bundle.social's Meta app are different applications with different review status and different granted scopes. A token minted for one is meaningless to the other, and there is no export, handoff, or vendor-to-vendor transfer mechanism at any of the platforms.
It goes deeper than the tokens. The user identifiers themselves are scoped to the application, so even your stored IDs do not survive the move:
- Meta: the user ID returned to your app is an App-Scoped User ID - "This ID is unique to the app and cannot be used by other apps."
- LinkedIn: "The
idis unique to your specific developer application. Any attempts to use theidwith other developer applications will not succeed." Sharing a person ID across applications returns a 404. - TikTok:
open_idis documented as an "Application specific unique identifier for the TikTok account."
Three consequences you have to design around:
Your migration is a user-consent campaign, not a data transfer. The engineering work is the easy half. Getting a few hundred customers to click through an OAuth screen again is the half that takes calendar time, and it is the half that determines your cutover date.
Your join keys change. Any table keyed on a Zernio accountId, a Meta ASID, or a LinkedIn person ID needs a new column, not a rewritten one. Keep both identifiers side by side through the entire migration - you will need the old one to reconcile and the new one to publish.
Historical analytics do not follow the token. Metrics you pulled through Zernio's app stay associated with Zernio's app. Plan to either keep a read-only Zernio subscription for the reporting window or snapshot the history into your own store before you cancel. Snapshotting is almost always cheaper.
For the wider picture of how token lifecycles behave once you are past the migration, see the social media API integration guide.
Mapping the object model
Zernio and bundle.social both model tenancy in three levels. The names differ and one boundary sits in a different place.
| Zernio | bundle.social | Notes |
|---|---|---|
| Team (your whole workspace, billing owner + invited members) | Organization | Top-level billing and API-key scope in both |
| Profile (the tenant boundary; one per customer) | Team | Where connected accounts are grouped |
Account (_id, 24-char ObjectId) | Social account (id) | The connected social profile |
Scoped API key (scope: "profiles", permission: "read") | (no public equivalent) | See the honesty section below |
The rename is the confusing part and it bites in code review: a Zernio "team" is a bundle.social "organization", and a Zernio "profile" is a bundle.social "team". Grep your codebase for profileId before you start and decide on the new name once, centrally.
The practical difference is where the isolation lives. In Zernio, a profile is a folder and the customer ↔ profileId mapping is documented as living in your database. In bundle.social, organizationId is derived server-side from the API key and stamped onto every team, post, and upload - it is never a field you send, which means it is not a field you can get wrong. A bug in your tenant-routing code produces a 404 rather than a cross-tenant write.
That is the substance of the multi-tenant argument, and it is worth stating precisely rather than grandly. Both products support multi-tenant platforms and both document it. bundle.social's difference is that the outer boundary is enforced by the credential rather than by your application code. Whether that matters to you depends on how much you trust your own tenant-routing layer under time pressure. The architectural trade-offs are covered properly in multi-tenant social media API architecture.
The same call, in both APIs
Here is a scheduled post to X. Zernio first, verbatim from their quickstart:
curl -X POST https://zernio.com/api/v1/posts \ -H "Authorization: Bearer $ZERNIO_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "content": "We just shipped webhook retries.", "scheduledFor": "2026-08-14T09:00:00", "timezone": "America/New_York", "platforms": [ {"platform": "twitter", "accountId": "66b2e19d8c3f5a7e9d0b1c2d"} ] }'
The same post on bundle.social:
curl -X POST https://api.bundle.social/api/v1/post \ -H "x-api-key: $BUNDLE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "teamId": "team_123", "title": "Webhook retries announcement", "postDate": "2026-08-14T13:00:00Z", "status": "SCHEDULED", "socialAccountTypes": ["TWITTER"], "data": { "TWITTER": { "text": "We just shipped webhook retries." } } }'
Five differences matter enough to call out, and four of them will bite you in the first hour.
Authentication is a different header. x-api-key, not Authorization: Bearer. The key resolves to an organization server-side, which is why no organizationId appears in the body.
Time is absolute, not local. Zernio takes a naive timestamp plus a timezone field. bundle.social has no timezone field anywhere on the post schema - postDate is a single ISO-8601 string and you resolve the offset yourself. Every scheduledFor + timezone pair in your codebase has to collapse into one UTC instant. Get this wrong and your posts are silently hours off, which is the worst kind of migration bug because nothing errors. Note that 2026-08-14T09:00:00 in America/New_York is 13:00:00Z, as above.
title is required and has no Zernio equivalent. It is an internal label, not published content. Generate something deterministic from your own record - do not leave it blank, the schema rejects an empty string.
Content is per-platform by default. Zernio's content is one string fanned out to every target. bundle.social's data is keyed by platform, so data.TWITTER.text and data.LINKEDIN.text can differ in the same call. During migration the cheapest move is to write the same string into every key; the per-platform copy is an improvement you make afterwards, not during.
Accounts are addressed by type, not by ID. Zernio targets {platform, accountId}. bundle.social targets teamId + socialAccountTypes: ["TWITTER"] and resolves the account from the team. One connected account per platform per team is the model - if a customer has three X profiles, that is three teams, not one team with three accounts.
Endpoint translation table
| Operation | Zernio | bundle.social |
|---|---|---|
| Auth | Authorization: Bearer <key> | x-api-key: <key> |
| Base URL | https://zernio.com/api/v1 | https://api.bundle.social/api/v1 |
| Create tenant | POST /profiles | POST /team (name, 3–80 chars) |
| List tenants | GET /profiles | GET /team → { items, total } |
| List accounts | GET /accounts | GET /team/:id → socialAccounts[] (no flat list endpoint) |
| One account | - | GET /social-account/by-type?type=&teamId= |
| Start OAuth | GET /connect/{platform}?profileId= → authUrl | POST /social-account/connect → { url } |
| Hosted connect UI | - | POST /social-account/create-portal-link → { url } |
| Create post | POST /posts | POST /post (singular) |
| Read post | GET /posts/{postId} | GET /post/:id |
| Publish now | publishNow: true | status: "SCHEDULED" with a near-now postDate |
| Draft | omit timing fields | status: "DRAFT" |
| Upload media | mediaItems: [{type, url}] | POST /upload/from-url → uploadIds[] |
| Large file | - | POST /upload/init → signed PUT → POST /upload/finalize (>90 MB) |
| Retry safety | Idempotency-Key header | referenceKey + GET /post/reference-key/:key |
| Webhooks | POST /webhooks | Dashboard only - no public API endpoint |
Two rows deserve more than a table cell.
Idempotency works differently, and this is the most likely source of duplicate posts during a parallel run. Zernio gives you an Idempotency-Key header: same key, same body, replays the original response. bundle.social has no such header. Instead you set referenceKey (1–128 characters) on the post and look it up with GET /post/reference-key/:referenceKey. That is a check-then-write, not an atomic replay - so the pattern is look up your reference key first, create only if absent, and make your reference key derive from your own domain object rather than from a retry counter. Zernio additionally rejects a duplicate (platform, accountId, content+media) fingerprint within 24 hours with a 409; do not assume that safety net exists on the other side.
Webhooks are dashboard-configured, not API-configured. The bundle.social public contract exposes no webhook routes - registration happens in the dashboard. Eight events fire today: post.published, comment.published, team.created, team.updated, team.deleted, social-account.created, social-account.updated, social-account.deleted. If your Zernio integration programmatically provisions a webhook per tenant, that code has no counterpart and the logic has to move to a one-time setup step.
Status mapping
| Zernio | bundle.social |
|---|---|
scheduled | SCHEDULED |
publishing | PROCESSING |
published | POSTED |
failed | ERROR |
partial | (no equivalent - inspect per-platform errorsVerbose) |
| - | DRAFT, RETRYING, REVIEW, DELETED |
partial is the one to watch. Zernio surfaces a single status for a multi-platform post that partly succeeded. bundle.social has no aggregate partial state; a post that failed on one platform and succeeded on another carries per-platform detail in errorsVerbose. If your UI renders a status badge from a single enum, it needs a per-platform reducer before cutover.

Migration, step by step
Seven steps. Steps 1–4 are safe and reversible; step 5 is where you start double-paying; step 6 is the only irreversible one.
Step 1 - Inventory and export, before you change anything
Pull everything out of Zernio while you still have a working key:
- Connected accounts, via
GET /accounts- platform,_id, and which profile each belongs to. - Profiles, via
GET /profiles, with your own customer mapping alongside. - Scheduled posts that have not fired yet. This is the queue you have to recreate; anything you miss simply does not publish.
- Historical analytics for whatever reporting window your customers expect. Remember that this data does not follow you.
Write it all to your own store, not to a spreadsheet. You will read from it repeatedly for the next several weeks and you will need it for reconciliation in step 6.
Step 2 - Provision the tenancy skeleton
Create one bundle.social team per Zernio profile:
curl -X POST https://api.bundle.social/api/v1/team \ -H "x-api-key: $BUNDLE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "Acme Corp" }'
Store the returned id next to the Zernio profileId in your own mapping table. Do not overwrite the old value. That two-column table is your rollback, your reconciliation key, and your progress dashboard for the rest of the migration.
Team names must be 3–80 characters, so any customer whose name is shorter than three characters needs a fallback before you loop over your list.
Step 3 - Build the translation layer, not the rewrite
Resist the urge to rip out your Zernio client. Put an interface in front of both, with the Zernio implementation as the default and the bundle.social implementation behind a per-tenant flag.
The interface only needs four methods to carry a publishing product: create a post, read a post, list accounts for a tenant, start a connect flow. Everything in the translation table above collapses into those four. Doing it this way means step 5 is a config change per customer rather than a deploy, and step 7 is a config change back.
Step 4 - Run the re-consent campaign
This is the long pole. Every connected account needs a fresh OAuth grant against bundle.social's platform apps.
The lowest-friction path is a hosted portal link - bundle.social generates a short-lived URL your customer opens to connect their accounts, with your logo on it:
curl -X POST https://api.bundle.social/api/v1/social-account/create-portal-link \ -H "x-api-key: $BUNDLE_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "teamId": "team_123", "socialAccountTypes": ["TWITTER", "LINKEDIN", "INSTAGRAM"], "redirectUrl": "https://app.example.com/settings/connections", "logoUrl": "https://app.example.com/logo.svg", "expiresIn": 1440, "hidePoweredBy": true }'
expiresIn is in minutes, minimum 5 and maximum 2,880 - so a link you email out can stay valid for up to two days. The default when you omit it is 10 minutes, which is fine for an in-app flow and far too short for an email campaign. Set it explicitly.
If you would rather keep users entirely inside your own UI, POST /social-account/connect returns a raw OAuth URL you redirect to yourself.
What this looked like in practice
We have moved roughly 35 platforms off Zernio onto bundle.social, and the honest summary is that the "campaign" framing oversells it.
Nobody ran a multi-week email funnel with reminder sequences. Migrations happened a few tenants at a time, and the mechanism was the portal link above: our customer sent it to their own end-clients, those end-clients clicked it and reconnected their accounts. Most were done inside 24 hours.
Two things explain why that worked, and both are worth copying.
The link went from our customer to their client, not from us to a stranger. The person receiving it already had a relationship with the sender and was expecting it. That is a completely different open rate from a vendor-branded "action required" email, and it is the single biggest reason the tail was short.
Batching kept it recoverable. Moving a handful of tenants at a time means that when something does go wrong - a Facebook Page selection that confuses someone, an account nobody can find the owner of - you are debugging one tenant's problem, not triaging two hundred. The instinct to migrate everyone at once is what creates the long tail people warn you about.
So: set expiresIn generously, have your customer send the link rather than sending it yourself, and move in batches small enough that you can chase stragglers by name. If you are migrating a handful of tenants, the whole re-consent step is likely a day or two, not the multi-week campaign the internet will tell you to plan for.
The caveat that scales: this was tens of tenants. At thousands of end-clients, the tail stops being something you can chase individually, and you will need the reminder sequence and the per-platform funnel instrumentation after all. Expect Instagram to lag X and LinkedIn when you get there, because its flow routes through a Facebook Page selection that people get wrong.
Step 5 - Parallel run, in shadow mode first
Once a tenant has reconnected, do not flip them. Run both integrations at once, in two phases.
Shadow phase. Keep publishing through Zernio. For every post, also create the equivalent on bundle.social as status: "DRAFT". Drafts do not publish, so there is no duplicate-post risk, and you get a real diff between what your translation layer produced and what you intended. Compare the created draft against your source record: text, media, scheduled instant in UTC, target platforms. This is where you find the timezone bugs, and you find them without anyone's followers seeing them.
Live phase. Flip the tenant's flag so bundle.social becomes the publisher and Zernio drops to read-only. Do not delete anything in Zernio yet - pause or cancel its scheduled posts so they cannot fire, but leave the account connected.
Two rules that prevent the failure mode everyone hits:
- Exactly one system publishes per tenant at any moment. Not per platform, not per campaign. Per tenant. Split ownership at a finer granularity than the tenant and you will eventually double-post.
- Cancel the Zernio queue before you populate the bundle.social one. The window between "recreated on the new system" and "cancelled on the old one" is precisely the window where both fire.
Start with your smallest, most tolerant tenant. Then an internal account. Then the long tail. Your largest customer goes last, not first.
Step 6 - Verify before you cancel
Cancelling the Zernio subscription is the irreversible step. Gate it on four checks:
- Queue parity. Every future-dated post in your step 1 export exists exactly once on bundle.social, with the same UTC instant. Assert on the count, not by eyeballing a list.
- Publish success rate. Watch
POSTEDversusERRORfor a full cycle - at least one week, and long enough to cover your weekly and monthly scheduled content. Compare against your Zernio baseline rather than against zero. - Per-platform error inspection. Pull
errorsVerboseon everything that failed. Migration-era failures cluster in specific, recognisable shapes: missing required per-platform fields (boardNameon Pinterest,sron Reddit,channelIdon Discord and Slack,texton LinkedIn), and media that was a URL on Zernio but needs an upload ID here. - Analytics snapshot taken. Confirmed in your own store, not still sitting behind a Zernio API key you are about to turn off.
Only then cancel. Note that Zernio bills per account-day, so disconnecting accounts as tenants migrate reduces the overlap cost progressively rather than all at once at the end - you do not have to pay two full subscriptions for the whole overlap window.
Step 7 - Rollback
Your rollback exists only for as long as the Zernio accounts stay connected. That is the whole reason step 6 is a gate rather than a formality.
While Zernio accounts remain connected, rollback is: flip the tenant's flag back, re-enable the paused Zernio queue, done. No re-consent needed, because those tokens were never revoked.
Once you disconnect a Zernio account or cancel the subscription, rollback stops being a flag flip and becomes a second full re-consent campaign - the tokens are gone in that direction too. So the honest advice is to keep Zernio connected and paid for one full billing cycle past your last cutover. It is the cheapest insurance in the entire project, and the account-day billing means a mostly-migrated workspace costs very little to keep alive.
It's not all sunshine and rainbows
A comparison page written by one of the two vendors is worth roughly what it costs unless it lists the things the other side does better. Here is that list, current as of 31 July 2026.
No DM or inbox API. Zernio ships /inbox/conversations, message sending, broadcasts, comment-triggered auto-DM, and WhatsApp conversation flows. bundle.social has none of it. Comments - full CRUD, plus first-comment scheduling - are shipped and solid, but comments are not DMs and conflating the two would be dishonest.
No ads API. Zernio covers Meta, Google, TikTok, LinkedIn, Pinterest and X Ads, including tailored-audience upload. bundle.social does not do paid at all.
No WhatsApp, no Telegram. Structural gaps, not roadmap items you can plan a quarter around.
No API-managed webhooks. Zernio lets you provision webhooks through the API. bundle.social requires the dashboard. For a platform onboarding tenants programmatically, that is a real ergonomic loss.
No per-tenant scoped API keys. Zernio offers keys scoped to specific profiles, optionally read-only - a genuinely useful access-control primitive for handing a restricted credential to an internal dashboard or an untrusted service. bundle.social's public API key is organization-wide. Your tenant isolation on the outbound side is enforced by the credential; your isolation within the organization is still your application's job.
Rate limits published at different granularity. Both vendors publish numbers, but not the same kind. bundle.social enforces three concurrent windows on every request - 100 per second, 500 per 10 seconds, 2,000 per minute - and a request must pass all three. Zernio instead scales its ceiling with account count (60 req/min free, 600 from 3–2,000 accounts, 1,200 above that) and breaks out a separate per-second window for analytics endpoints, with X-RateLimit-* headers on every response. If your worker is bursty, bundle.social's flat 100/second is the more generous shape. If you need to reason about one endpoint family in isolation, Zernio's per-bucket breakdown tells you more, and its response headers save you from tracking budget yourself.
No partial status. Covered above, but it is a real porting cost, not a footnote.
If three or more of those are load-bearing in your product, the honest recommendation is to stay where you are.
The Getlate signal, and what it says about lock-in
One verifiable fact worth sitting with.
getlate.dev now returns HTTP 301 Moved Permanently with Location: https://zernio.com/. Confirmed 31 July 2026 by direct request. Getlate was an independent social media API in the same category, with its own developer audience, its own SDKs, and its own integrations.
What I can state: the domain permanently redirects to a competitor, and Zernio's own site, documentation and changelog carry no announcement explaining it - zero mentions of Getlate across all 95,000 lines of their published docs. What I cannot state, because it is not published anywhere I could verify: whether this was an acquisition, an asset purchase, a shutdown with a redirect, or something else. I am not going to guess at a transaction I have no evidence for.
The lesson is about your architecture, not about anyone's cap table. If you built on Getlate, your infrastructure vendor changed identity without a migration notice - and, per everything in the OAuth section above, every one of your users' tokens was tied to Getlate's platform apps. That is the concrete shape of vendor lock-in in this category: not a contract you cannot exit, but a consent graph you cannot move.
Two defences, and neither depends on which vendor you pick:
Keep the vendor behind an interface. The four-method abstraction from step 3 is not migration scaffolding to be deleted afterwards. Keep it. It is what makes the next migration a fortnight instead of a quarter.
Own your consent metadata. Store, in your own database, which user authorized which platform, when, with which scopes, and through which vendor. You cannot move the tokens, but knowing exactly who needs to re-authorize converts an unbounded problem into a mail-merge.
Side by side, after the migration
| Dimension | Zernio | bundle.social |
|---|---|---|
| Meter | Connected accounts, graduated $6/$3/$1 bands | Published posts; accounts unlimited on paid plans |
| Tenancy | Team → profile → account; customer↔profile mapping in your DB | Organization → team → social account; org derived from the API key |
| Platforms | 15, including WhatsApp and Telegram | 15, including Mastodon |
| Ads | 6 ad networks | Not offered |
| DMs / inbox | Shipped | Waitlist |
| Comments | Shipped | Shipped, plus first-comment scheduling |
| Retry safety | Idempotency-Key header, 24h content-hash dedup | referenceKey + lookup endpoint |
| Webhooks | API-managed | Dashboard-managed, 8 events |
| Rate limits | Published table, scales with accounts | Per-endpoint, not published |
| Large media | Public URL passthrough | URL ingest, plus init/finalize above 90 MB |
| Per-platform content | One content string fanned out | data keyed per platform |
| AI tooling | OpenAPI spec, CLI, generated SDKs | OpenAPI spec, CLI, TypeScript SDK, MCP server |
The row that most often decides it is the first one. Everything else is a porting cost you pay once; the meter is a cost you pay every month, and it either compounds with your growth or it does not.
Frequently asked questions
Can I transfer my OAuth tokens from Zernio to bundle.social?
No. Access tokens are issued to a specific registered application, and the two vendors have different platform apps. The user identifiers are also application-scoped - Meta App-Scoped User IDs, LinkedIn person IDs and TikTok open_id values are explicitly documented as unusable by other applications. Every connected account must be re-authorized. Plan the migration as a consent campaign with an engineering task attached, not the other way round.
How long does migrating from Zernio take? The code is the short part: a translation layer covering create-post, read-post, list-accounts and start-connect is typically a few days of work, because the object models map cleanly once you know that a Zernio profile is a bundle.social team. Re-consent sets the real timeline, and it scales with your customer count and their responsiveness rather than with your engineering capacity. Across the ~35 platforms we have moved, tenants migrated in small batches and most end-clients reconnected within 24 hours of receiving a portal link from their own provider. At that scale the whole thing is days. At thousands of end-clients, plan for reminder sequences and a longer tail.
Can I run Zernio and bundle.social at the same time?
Yes, and you should. Publish through Zernio while creating the same posts as DRAFT on bundle.social to diff the output safely, then flip tenant by tenant. The one rule that matters: exactly one system publishes per tenant at any moment, and you cancel the Zernio queue before you populate the new one. Zernio bills per account-day, so the overlap cost falls progressively as you migrate rather than doubling for the full window.
What happens to my scheduled posts and my analytics history? Neither transfers. Export your future-dated queue before you start and recreate it - anything you miss silently never publishes. Analytics stay bound to the vendor's platform apps, so snapshot whatever reporting window your customers expect into your own store before cancelling. That snapshot is almost always cheaper than keeping a subscription alive for reporting.
Should I migrate if I use WhatsApp, ads, or DMs? No. bundle.social does not offer WhatsApp, Telegram, any ad network, or a direct-message API today. Those are structural gaps, not near-term roadmap items, and no amount of translation-layer work routes around them. If ads or DMs are load-bearing in your product, this migration is not for you.
Where to start
If you have read this far, the useful next step is not a signup. It is running step 1 against your own account: export your profiles, your connected accounts, and your future-dated queue, then count them. That number - accounts, and posts per month - tells you which side of the crossover you are on faster than any comparison table can.
Then, in order: the Zernio alternative page for the commercial case, pricing for the current post allowances, and the social media API overview for the endpoint surface you will be porting to.