Create an API key
Open Dashboard → AI & API and create a key. Copy it once. It starts with pw_live_. Send it on every request:
Header
Authorization: Bearer pw_live_…
Every URL below starts at https://postwing.io/api/v1.
the whole flow
You call PostWing. PostWing publishes to Facebook at the time you set. The post also shows up on your calendar.
Open Dashboard → AI & API and create a key. Copy it once. It starts with pw_live_. Send it on every request:
Header
Authorization: Bearer pw_live_…
Every URL below starts at https://postwing.io/api/v1.
Connect the Facebook account you want to post from. You only do this once.
The simple way is in the dashboard. Open Accounts, choose Facebook, and finish the Facebook login.
From the API, start that same login. The response includes a url. Open it and approve Facebook.
Start connect
curl -s -X POST "https://postwing.io/api/v1/accounts" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{ "platform": "facebook" }'After you finish in the browser, sync. This imports the account into your workspace and returns the account id.
Sync
curl -s -X POST "https://postwing.io/api/v1/accounts/sync" \ -H "Authorization: Bearer pw_live_…"
In the response, find the object where platform is facebook and copy account_id. That is the id you send when you create the post.
Sync response
{
"synced_count": 1,
"accounts": [
{
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "facebook",
"handle": "brand-page",
"display_name": "Brand",
"status": "connected"
}
]
}Connected Facebook in the dashboard instead? The sync response is not in front of you, so list accounts and copy the same field:
List accounts
curl -s -X GET "https://postwing.io/api/v1/accounts" \ -H "Authorization: Bearer pw_live_…"
Send the caption, a future time, and the Facebook account_id you copied after sync. This call creates the post. Facebook does not publish until you confirm in the next step. scheduled_at is UTC. An image URL has to be public HTTPS.
Create a feed post
curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{
"caption": "New hours this week. We are open until 7.",
"scheduled_at": "2026-10-12T15:00:00Z",
"targets": [
{ "account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" }
],
"media_items": [
{ "url": "https://cdn.example.com/storefront.jpg", "type": "image" }
]
}'You get back three things that matter:
Response
{
"preview": {
"caption": "New hours this week. We are open until 7.",
"scheduled_at": "2026-10-12T15:00:00.000Z",
"post_type": "image",
"targets": [
{
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform": "facebook",
"handle": "brand-page"
}
]
},
"confirmation_token": "eyJ…signature",
"expires_in_seconds": 300
}The same post can go to Instagram and TikTok. Connect each channel the way you connected Facebook, then copy its account_id from the sync response.
Connect Instagram
curl -s -X POST "https://postwing.io/api/v1/accounts" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{ "platform": "instagram" }'Connect TikTok
curl -s -X POST "https://postwing.io/api/v1/accounts" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{ "platform": "tiktok" }'Open each url, finish the login, then sync once. Copy account_id where platform is instagram, and where platform is tiktok or tiktok_business.
Add those ids to targets on the create call. One request, one confirm. Every account publishes at the same scheduled_at. Leave caption off a target to use the shared caption. Set caption when that channel needs different text.
Create one post for three channels
curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{
"caption": "New hours this week. We are open until 7.",
"scheduled_at": "2026-10-12T15:00:00Z",
"targets": [
{ "account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890" },
{
"account_id": "b2c3d4e5-f6a7-8901-bcde-f12345678901",
"caption": "Open until 7 this week."
},
{ "account_id": "c3d4e5f6-a7b8-9012-cdef-123456789012" }
],
"media_items": [
{ "url": "https://cdn.example.com/storefront.jpg", "type": "image" }
]
}'Instagram and TikTok need an image or a video. A text-only post stays on Facebook. Then confirm once, the same way as the next step.
When the post you just created looks right, confirm with the token from that response. Use the token as-is. Do not invent one.
Confirm
curl -s -X POST "https://postwing.io/api/v1/posts/confirm" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{ "confirmation_token": "eyJ…signature" }'The response includes view_url. Open it to see the post on your calendar. Every account in targets publishes at the time you set, including Instagram and TikTok when you added them. You can edit or cancel later from the dashboard or with the same API.
If confirm says the token expired, create the post again and confirm the new token within 5 minutes.
video
A video defaults to a Reel. Use the same Facebook account_id from sync, and set placement to reels.
Create a Reel
curl -s -X POST "https://postwing.io/api/v1/posts/preview" \
-H "Authorization: Bearer pw_live_…" \
-H "Content-Type: application/json" \
-d '{
"caption": "A 15-second look at the new menu",
"scheduled_at": "2026-10-12T18:00:00Z",
"targets": [
{
"account_id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"platform_options": { "placement": "reels" }
}
],
"media_items": [
{ "url": "https://cdn.example.com/reel.mp4", "type": "video" }
]
}'To put that video on the feed instead, set placement to timeline. Images and text already go to the feed, so you can leave placement off for those.
Videos imported from a URL need to be 100MB or smaller. A file on your computer uses the direct upload URL, covered in the API docs.
questions
Yes. Create the post with caption, scheduled_at, and the Facebook account_id. Leave out media_items. Then confirm with the token.