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 header
Authorization: Bearer sk_live_…

Confirm the key works by calling the public health check (it requires no auth) and then a key-gated endpoint:

curl
# 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_…"
200 OK
{ "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
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"]
  }'
201 Created
{
  "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
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"
  }'
200 OK
{ "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_uri with ?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_uri with ?status=pending&session=…. Fetch the choices and finalize:
curl
# 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…"] }'
200 OK — finalize
{
  "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
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-…"]
  }'
201 Created
{
  "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
curl https://api.postfuze.com/api/v1/posts/p0s7-… \
  -H "Authorization: Bearer sk_live_…"
200 OK
{
  "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.