Guides

Migrate from Buffer

Move your queue and connections

You’ve been using Buffer. You want to move to OpenPost. Here’s the full cutover plan so nothing gets lost: channel connections, queue slots, and the drafts you haven’t published yet.

Before you start

  • Open both tabs: Buffer on one, OpenPost on the other.
  • Pick a cutover date. Everything scheduled before it stays in Buffer; after, in OpenPost.
  • Don’t cancel your Buffer subscription yet — finish migrating first.

1. Export from Buffer

1

Export your drafts

In Buffer: Account → Export data. You’ll get a ZIP of JSON files. The updates.json contains every scheduled and drafted post.

2

Export your queue slots

Buffer doesn’t export these directly. Screenshot the Posting schedulepage per channel. We’ll re-create in OpenPost.

2. Connect the same channels in OpenPost

Go to Channels → Connectfor each social account you had in Buffer. OpenPost uses its own OAuth app, so you’ll re-authorize — this is expected. Connecting here doesn’t touch your Buffer connection; both tools can publish to the same account.

Don’t worry about duplicates yet. Each post is only published once — the first tool to fire wins. We’ll drain Buffer’s queue before enabling OpenPost’s queue.

3. Re-create queue slots

For each channel, go to Publishing → Queuesand re-enter the time slots from your Buffer screenshots. You’re done in 2 minutes per channel.

4. Import drafts

We accept a Buffer-compatible CSV through the bulk importer. Convert your exported JSON with the script below, then drop it into Publishing → Bulk import.

ts
// convert.ts
import fs from "node:fs";
 
type BufferUpdate = {
  text: string;
  due_at: number; // Unix seconds
  profile_service: string; // twitter, linkedin...
};
 
const updates: BufferUpdate[] = JSON.parse(fs.readFileSync("updates.json", "utf8"));
 
const rows = updates.map((u) => ({
  content: u.text.replace(/\n/g, "\\n"),
  channel: ({
    twitter: "x",
    linkedin: "linkedin",
    instagram: "instagram",
    facebook: "facebook",
  } as Record<string, string>)[u.profile_service] ?? u.profile_service,
  schedule_at: new Date(u.due_at * 1000).toISOString(),
}));
 
fs.writeFileSync(
  "openpost-import.csv",
  "content,channel,schedule_at\n" + rows.map((r) =>
    `"${r.content}",${r.channel},${r.schedule_at}`,
  ).join("\n"),
);
console.log("Wrote", rows.length, "rows");

Run:

bash
bun run convert.ts
# → openpost-import.csv

5. Dry-run the import

Publishing → Bulk import → Upload CSV. Check the “Dry run” box. You’ll get a preview — rejected rows highlighted, character overages flagged, suggested fixes inline. Fix the CSV until dry run is clean.

6. Cut over

FieldTypeDescription
Day 0prepChannels connected. Queues set. CSV dry-run is clean.
Day 1 morningfreeze BufferPause every queue in Buffer. Drafts stay as drafts.
Day 1 afternoonimportRun the bulk import for real. OpenPost schedules everything past the cutover time.
Day 1 eveningverifyOpen the OpenPost calendar — should match what was in Buffer.
Day 7cancel BufferAfter a week of parallel calendars matching expectations, cancel Buffer.
Don’t cancel Buffer on the same day you import. If anything looks off post-migration, you want the old system still available to reference.

What doesn’t migrate

  • Buffer Analyze dashboards— OpenPost has its own analytics, but historical Buffer metrics don’t import.
  • Buffer Reply inbox— OpenPost doesn’t (yet) have a unified inbox.
  • Pablo / Create— bring your own image editor; we’ll crop for you.

Help during migration

Email contact@infina.soand we’ll do a 30-minute screen share to walk through your specific case. Free on every plan during your trial.

Last updated April 2026 Edit this page