Move from bundle.social to PostWire in an afternoon
bundle.social's publish request, mapped field by field to PostWire's, with the same post side by side as cURL, an n8n node and an MCP call — and a converter that rewrites your bundle.social requests for you, in the browser.
Authorization: Bearer pw_live_…. teamId (a team per customer) becomes brand_id, one brand per client. Scheduling: POST /api/schedule with run_at. And one thing PostWire adds: POST /api/generate writes each network's post from one idea before you publish.bundle.social's fields read on its own docs on Oct 9, 2026, linked on each row; PostWire's checked against openapi.json when this page was built.
Field by field
bundle.social: POST https://api.bundle.social/api/v1/post/. PostWire: POST https://postwire.io/api/post (now) or POST https://postwire.io/api/schedule (later).
| bundle.social | PostWire | Notes |
|---|---|---|
teamIdinfo.bundle.social, Oct 9, 2026 | brand_id | One brand per client. |
socialAccountTypes[]info.bundle.social, Oct 9, 2026 | platforms[] | TWITTER → x, the rest in lower case. |
data.<PLATFORM>.textinfo.bundle.social, Oct 9, 2026 | text / per_platform.<network>.text | bundle.social keeps the text per platform; PostWire takes one text plus overrides. |
data.YOUTUBE.text / .descriptioninfo.bundle.social, Oct 9, 2026 | title / per_platform.youtube.text | On bundle.social YOUTUBE.text is the video title. |
data.<PLATFORM>.uploadIdsinfo.bundle.social, Oct 9, 2026 | media[].url | bundle.social uploads first; PostWire takes any public URL. |
postDate + status: SCHEDULEDinfo.bundle.social, Oct 9, 2026 | run_at (POST /api/schedule) | |
firstComment.<PLATFORM>info.bundle.social, Oct 9, 2026 | per_platform.<network>.first_comment | PostWire: LinkedIn, X, Bluesky, Mastodon. |
title (internal)info.bundle.social, Oct 9, 2026 | label (POST /api/schedule) | An internal name in both. |
Network names: TIKTOK → tiktok · YOUTUBE → youtube · INSTAGRAM → instagram · FACEBOOK → facebook · TWITTER → x · LINKEDIN → linkedin · MASTODON → mastodon · DISCORD → discord · SLACK → slack · BLUESKY → bluesky · THREADS → not offered by PostWire · PINTEREST → not offered by PostWire · REDDIT → not offered by PostWire · GOOGLE_BUSINESS → not offered by PostWire · SNAPCHAT → not offered by PostWire.
The same post, side by side
bundle.social — their docs' example
curl -X POST https://api.bundle.social/api/v1/post \
-H "Content-Type: application/json" \
-H "x-api-key: $BUNDLE_API_KEY" \
-d '{
"teamId": "team_123",
"title": "Launch post",
"status": "SCHEDULED",
"postDate": "2026-06-01T15:00:00.000Z",
"socialAccountTypes": ["FACEBOOK", "INSTAGRAM"],
"data": {
"FACEBOOK": { "type": "POST", "text": "We are live.", "uploadIds": ["upload_image_123"] },
"INSTAGRAM": { "type": "POST", "text": "We are live.", "uploadIds": ["upload_image_123"], "altText": "Product dashboard screenshot" }
}
}'From info.bundle.social, read Oct 9, 2026. Their docs show this body inside a TypeScript fetch() call; here as cURL with the same body.
PostWire — REST (the converter's output)
curl -X POST https://postwire.io/api/schedule \
-H "Authorization: Bearer $POSTWIRE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"platforms": [
"facebook",
"instagram"
],
"text": "We are live.",
"run_at": "2026-06-01T15:00:00.000Z",
"label": "Launch post"
}'your key from the pasted command is not carried over: the output uses $POSTWIRE_API_KEY FACEBOOK: uploadIds are bundle.social uploads — pass the files' public URLs in "media" (or upload them to PostWire: POST /api/media/upload-url) INSTAGRAM: uploadIds are bundle.social uploads — pass the files' public URLs in "media" (or upload them to PostWire: POST /api/media/upload-url) teamId (a bundle.social team) → brand_id: create one PostWire brand per client (POST /api/brands) and send its id; with a single brand you can leave brand_id out run_at is in the past: PostWire refuses a schedule in the past — set a future time
PostWire — n8n node
PostWire node Resource: Post Operation: Schedule Networks: facebook, instagram Content: Same Text on Every Network Text: We are live. When: At a Specific Time Publish At: 2026-06-01T15:00:00.000Z Options → Brand: the client's brand
PostWire — MCP (Claude, ChatGPT, any agent)
schedule_post({
"platforms": [
"facebook",
"instagram"
],
"text": "We are live.",
"run_at": "2026-06-01T15:00:00.000Z",
"label": "Launch post"
})
# or ask your agent: "Schedule this on Facebook and Instagram for 2026-06-01T15:00:00.000Z"What changes
| bundle.social | PostWire | |
|---|---|---|
| Authentication | x-api-key: YOUR_API_KEYinfo.bundle.social, Oct 9, 2026 | Authorization: Bearer pw_live_… — an API key from the dashboard; the MCP server also signs in with OAuth 2.1 |
| One client | teamId (a team per customer)info.bundle.social, Oct 9, 2026 | brand_id — one brand per client, its networks connected once (GET /api/brands lists them) |
| Scheduling | postDate (ISO 8601 with timezone) with status SCHEDULED or DRAFTinfo.bundle.social, Oct 9, 2026 | POST /api/schedule with run_at (ISO 8601 with offset) or "next_slot", checked at queue time |
| Webhooks | post.published (read data.status for failures), comment.published, social-account.*, team.*info.bundle.social, Oct 9, 2026 | post.published, post.failed, connection.reauth_required — one per network, signed (PostWire-Signature, HMAC-SHA256), retried for two days |
| Retries without duplicates | Not listed | idempotency_key (24 hours); an identical post is refused for 2 minutes even without one |
| Checking a post | GET https://api.bundle.social/api/v1/post/{id}info.bundle.social, Oct 9, 2026 | GET /api/post/status, or the webhook |
Convert your bundle.social requests
Paste a cURL command or a JSON body from your code. The PostWire request comes out, ready to run.
Move in an afternoon
- Open a PostWire account (free, no card) and create an API key under API & MCP.
- Create one brand per client —
POST /api/brandsor the dashboard. It takes the place of bundle.social's teamId. - Connect each client's networks:
POST /api/connect-linkreturns a one-hour link the client opens to sign in to each network. TikTok, Meta and Google approvals are PostWire's, so there is no app review on your side. - Swap the base URL and the auth header in your code:
https://postwire.io/api/andAuthorization: Bearer pw_live_…. - Convert your requests with the converter above (or by the field table), and send
brand_idwith each one. - Move the queue: list what is still scheduled on bundle.social and re-create it with
POST /api/schedule, or as one CSV under Automate → Bulk upload (checked row by row before anything is scheduled). - Point your webhook receiver at PostWire:
POST /api/webhookswith your URL, and verifyPostWire-Signature. - Send one real post to one network and watch
GET /api/post/statusor the webhook. - When the bundle.social queue is empty, cancel that plan. PostWire's paid plans have a 14-day refund if it is not for you.
Where PostWire is ahead of bundle.social
- Each network's post written for you from one idea, in one request — a hook-first TikTok caption, a YouTube title and tags, a longer LinkedIn post. bundle.social takes one post with platform-specific payload blocks that you fill (its MCP page, Oct 9, 2026).
- A hosted MCP server you add to Claude by signing in (OAuth 2.1). bundle.social's MCP server runs locally with npx and an API key; a hosted one is on its roadmap.
- $29 for 10 businesses, every network included. bundle.social's first paid plan is $100 a month (Pro).
- Media by URL in the same request. bundle.social's post body takes upload IDs, so each file is uploaded first (its docs).
- A 14-day refund on every paid plan. bundle.social's terms say fees are non-refundable.
Questions people ask
How long does it take to move from bundle.social to PostWire?
An afternoon for most integrations: the request maps field by field (the table on this page), the auth header and the client key change, and the converter on this page turns bundle.social requests into PostWire's. Connecting each client's networks is one sign-in per network, from a link you can send the client.
What replaces bundle.social's teamId (a team per customer)?
A brand: one per client business, each with its own connected networks. Send brand_id with the post (GET /api/brands lists them); a key that only has one brand can leave it out.
Does PostWire have webhooks and idempotency like bundle.social?
PostWire signs every webhook (PostWire-Signature: HMAC-SHA256) and sends post.published, post.failed and connection.reauth_required, one per network, retried for two days. An identical post is refused for 2 minutes, or for 24 hours when you send your own idempotency_key.
Can I try PostWire before cancelling bundle.social?
Yes. The free plan has the REST API and the MCP server (1 business, 20 posts a month, no card), and Pro has a 7-day free trial; run both side by side until your queue on bundle.social is empty.
Type one idea and see the post each network gets.
The demo on the home page writes live, with no account, and never publishes. The free plan covers one business — every network connects free, 2 networks per post — with no card and no time limit. Paid plans have a 14-day refund.