Quickstart
This guide takes you from zero to a published post in about five minutes. You will create an API key, connect a social account through the hosted OAuth flow, create your first post, and check its status. Every request hits the base URL https://api.postfuze.com/api/v1 and is authenticated with a bearer token.
Before you begin
- A PostFuze account. Sign up at
https://postfuze.com/sign-up— it is free, no credit card required. - A BYOK OAuth app for the platform you want to connect (PostFuze uses your own developer app credentials). You will register these in step 3.
- Publishing requires an active subscription only on deployments with billing enabled. Local/self-hosted MVP installs default to ungated publishing.
Step 1 — Sign up
Create your account at /sign-up using email and password, then sign in at /sign-in. The first time you sign in, PostFuze provisions an org for you — every API key, account and post belongs to that org and is isolated from everyone else by row-level security.
Step 2 — Create an API key
Open the dashboard at /dashboard/api-keys and generate an API key. Keys come in two flavors:
sk_live_…— for production traffic.sk_test_…— for development and testing; draft creation only, never real scheduling or publishing.
Copy the key as soon as it is shown — PostFuze stores only a hash, so you cannot retrieve it again. Send it on every request as a bearer token:
Authorization: Bearer sk_live_…Confirm the key works by calling the public health check (it requires no auth) and then a key-gated endpoint:
# Unauthenticated health check
curl https://api.postfuze.com/api/v1/health
# Authenticated request — lists your connected accounts (empty for now)
curl https://api.postfuze.com/api/v1/social-accounts \
-H "Authorization: Bearer sk_live_…"{ "ok": true, "service": "PostFuze", "time": "2026-06-09T10:00:00.000Z" }See Authentication for key rotation, revocation and security details.
Step 3 — Register your OAuth app (BYOK)
PostFuze is bring-your-own-keys: you supply the OAuth app credentials for each platform and PostFuze drives the user-authorization flow on top of them. Register them once per platform with POST /social-networks. The client_secret is encrypted at rest and never returned.
curl https://api.postfuze.com/api/v1/social-networks \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"platform": "x",
"display_name": "My X App",
"client_id": "YOUR_X_CLIENT_ID",
"client_secret": "YOUR_X_CLIENT_SECRET",
"redirect_uri": "https://api.postfuze.com/api/v1/connect/callback",
"scopes": ["tweet.read", "tweet.write", "users.read", "offline.access"]
}'{
"id": "f1e2d3c4-…",
"platform": "x",
"display_name": "My X App",
"client_id": "YOUR_X_CLIENT_ID",
"redirect_uri": "https://api.postfuze.com/api/v1/connect/callback",
"scopes": ["tweet.read", "tweet.write", "users.read", "offline.access"],
"extra_config": {},
"is_enabled": true,
"created_at": "2026-06-09T10:01:00.000Z",
"updated_at": "2026-06-09T10:01:00.000Z"
}The endpoint upserts on (org, platform), so calling it again for the same platform updates the credentials in place.
Step 4 — Connect an account
With a BYOK app registered, ask for an authorize URL. POST /social-networks/{platform}/auth-urlreturns the platform's authorize URL with a signed state baked in.
curl https://api.postfuze.com/api/v1/social-networks/x/auth-url \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{
"redirect_uri": "https://yourapp.com/connected",
"tenant_id": "user_42"
}'{ "auth_url": "https://twitter.com/i/oauth2/authorize?response_type=code&client_id=…&state=…" }Send the user to auth_url. After they approve, the platform redirects to PostFuze's callback (/connect/callback), which exchanges the code and either:
- Connects one account immediately when the authorization yields a single account. The user is redirected to your
redirect_uriwith?status=connected&account_id=…. - Hands off to page selection when several accounts are available (e.g. Facebook Pages or Google Business locations). The user lands on your
redirect_uriwith?status=pending&session=…. Fetch the choices and finalize:
# 1. List the pages/accounts available in this pending session
curl https://api.postfuze.com/api/v1/social-accounts/pending/SESSION_TOKEN \
-H "Authorization: Bearer sk_live_…"
# 2. Finalize by selecting one or more page ids
curl https://api.postfuze.com/api/v1/social-accounts/pending/SESSION_TOKEN/finalize \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-d '{ "selectedPageIds": ["1784523…"] }'{
"connectedAccounts": [
{
"id": "a1b2c3d4-…",
"nickname": "acme_co",
"username": "acme_co",
"network": "x",
"accountType": "account"
}
]
}The id in connectedAccounts (or the account_id from the immediate-connect redirect) is the social account ID you target when publishing. You can always look it up later with GET /social-accounts.
Step 5 — Create your first post
A post fans out to one target per account in accounts[]. Omit scheduled_at to publish immediately. The accounts array takes the social account IDs you just connected.
curl https://api.postfuze.com/api/v1/posts \
-H "Authorization: Bearer sk_live_…" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: quickstart-001" \
-d '{
"content": "Hello from the unified PostFuze API 👋",
"accounts": ["a1b2c3d4-…"]
}'{
"id": "p0s7-…",
"status": "queued",
"is_draft": false,
"scheduled_at": null,
"published_at": null,
"default_config": {},
"external_ref": "quickstart-001",
"created_at": "2026-06-09T10:05:00.000Z",
"updated_at": "2026-06-09T10:05:00.000Z",
"containers": [
{ "id": "c…", "position": 0, "role": "main", "content": "Hello from the unified PostFuze API 👋" }
],
"targets": [
{ "id": "t…", "social_account_id": "a1b2c3d4-…", "platform": "x", "status": "queued",
"platform_post_id": null, "platform_post_url": null, "error_code": null, "error_message": null, "published_at": null }
]
}The Idempotency-Key header (or an external_ref field) makes the call safe to retry: replaying the same key returns the original post with a 200 instead of creating a duplicate.
Step 6 — Check the status
Fetch the post to watch each target move from queued to published. When a target lands, it carries the platform's native post ID and URL.
curl https://api.postfuze.com/api/v1/posts/p0s7-… \
-H "Authorization: Bearer sk_live_…"{
"id": "p0s7-…",
"status": "published",
"published_at": "2026-06-09T10:05:09.000Z",
"targets": [
{
"id": "t…",
"social_account_id": "a1b2c3d4-…",
"platform": "x",
"status": "published",
"platform_post_id": "1799…",
"platform_post_url": "https://x.com/acme_co/status/1799…",
"error_code": null,
"error_message": null,
"published_at": "2026-06-09T10:05:09.000Z"
}
]
}Each target tracks its own status, so a post can be published on one platform while another retries. Polling works, but for production you should subscribe to webhooks and receive post.published / post.error events instead.
Next steps
- Authentication — key rotation, revocation and security.
- Backend integration — the recommended server-side architecture and a database schema.
- Posts — scheduling, first comments, threads, media and per-platform config.
- Webhooks — receive publish results instead of polling.