Syndroo docs
Version 0.2.0-rc.1 unpublished release candidate Website GitHub

Threads setup

Threads uses one credential: a Meta user access token authorized to publish for the account. There is no OAuth flow inside Syndroo, so you create the app, authorize the account and keep the token fresh yourself.

Mock-tested, no live-account record Provider threads-native

Status and evidence

Syndroo 0.2.0-rc.1 is an unpublished release candidate: prepared in the repository, not published to npm, not tagged, and not deployed. Threads is recorded as mock-tested for this candidate.

Evidence: unit tests plus the local Mock SNS end-to-end gate in the core repository. That gate replaces only the network boundary with a loopback mock, so it proves wiring, persistence, idempotency, ambiguity handling and scheduling. It cannot prove provider permissions, current API compatibility or rate limits. No live-account acceptance record exists yet, and live acceptance is an open release gate. See Platform readiness and the capability record.

What you need

  • A Threads account you can post from, reachable from the Meta account you will use in the developer dashboard.
  • A Meta app with the Threads use case. Threads publishing is configured through Meta's developer platform rather than a separate Threads-only portal.
  • A Threads user access token authorized for publishing. Meta issues short-lived tokens that you exchange for a long-lived user token; only the user token can publish for the account.
  • A running Worker and its API key. Either a deployment in your own Cloudflare account or a local instance. The Worker holds the platform credentials; clients hold only SYNDROO_API_KEY. If you have not set one up yet, the first-post walkthrough covers the whole path with Bluesky.

The adapter reads one Worker secret:

SecretRequiredValue
THREADS_ACCESS_TOKENYesA Threads user access token authorized for publishing. Meta's current documentation lists threads_basic as required for all Threads endpoints and threads_content_publish as required for the publishing endpoints.

Authorize the account by hand

Meta's dashboard, product names and permission scopes change over time. Follow the official Threads documentation and the Meta Postman collection linked under Official sources, which carry the current authorization, token exchange, refresh and debugging requests.

  1. Create the app with the Threads use case

    In the Meta developer dashboard, create or reuse an app and attach the Threads use case. The use case is what exposes the Threads publishing API for your app.

  2. Authorize the Threads account

    Run the authorization step for the account you will publish from, requesting the Threads publishing permission in addition to basic profile access. Approve the requested access in the Threads client when Meta asks.

  3. Exchange the short-lived token

    Exchange the short-lived token for a long-lived user token with Meta's documented token endpoint. Store the long-lived token as THREADS_ACCESS_TOKEN; do not use an app access token here, because it cannot post for the account.

  4. Check the token before wiring it up

    Meta's token debugger reports the owning account, the granted scopes and the expiry. Check it while the token is fresh, so a wrong account or a missing scope shows up here instead of as a failed publication.

Token renewal is your job.

Meta's current documentation describes exchanging a short-lived token for a long-lived token that is valid for 60 days, and refreshing it through the GET /refresh_access_token endpoint before it expires. Syndroo stores the token you give it and never runs an OAuth flow or a refresh on your behalf, so schedule that refresh yourself and re-check Meta's page, because these rules are Meta's to change.

Add the secret to the Worker

Put the value where your runtime reads secrets: Worker secrets for a deployment, .dev.vars for a local instance. Cloudflare deployment and Local development cover the exact commands for each path.

THREADS_ACCESS_TOKEN="your-threads-long-lived-user-access-token"
Configuration is checked for shape, not for validity.

Before accepting a post, Syndroo checks that the value exists and is non-empty. It does not call Meta to test the token. An expired, revoked or under-scoped token passes that check and surfaces later as a publication failure with errorCode AUTH.

Only the platforms you configure are selectable. Sending platforms: ["threads"] without this secret returns HTTP 422 with PLATFORM_NOT_CONFIGURED before anything is stored or queued.

Publish and check one post

The commands below publish for real once the secret above is configured. Set the two client variables in the terminal that will call Syndroo.

export SYNDROO_URL="https://your-worker.your-subdomain.workers.dev"
export SYNDROO_API_KEY="the-same-secret-your-worker-has"
curl -X POST "$SYNDROO_URL/v1/posts" \
  -H "Authorization: Bearer $SYNDROO_API_KEY" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: threads-setup-001" \
  --data '{
    "content": "First post from my own Syndroo Worker.",
    "platforms": ["threads"]
  }'

The accepted response is HTTP 202 with status queued:

{
  "id": "post_...",
  "status": "queued"
}

HTTP 202 means the request was accepted for processing. It does not confirm that Threads accepted anything, and it does not prove that the Queue has not already sent the platform request, because delivery can start immediately after acceptance. Read the stored state to learn the outcome:

curl \
  -H "Authorization: Bearer $SYNDROO_API_KEY" \
  "$SYNDROO_URL/v1/posts/post_..."
{
  "id": "post_...",
  "content": "First post from my own Syndroo Worker.",
  "platforms": ["threads"],
  "status": "published",
  "publications": [
    {
      "platform": "threads",
      "provider": "threads-native",
      "status": "published",
      "attempts": 1,
      "externalId": "18000000000000000",
      "errorAmbiguous": false
    }
  ]
}

queued and publishing are not terminal; poll the same URL. published and failed are terminal. An externalUrl appears only when the platform returns a usable link; when it is missing, treat the stored identifier as the reference rather than building a URL by hand.

Repeating the identical request with the same Idempotency-Key returns the stored result with HTTP 200 instead of creating a second post. See Idempotency-Key.

Limits, tokens and external dependencies

ItemRecorded for 0.2.0-rc.1
Text limit500 characters, validated before the network call.
Content typeText only. Media, carousels and replies are outside this version.
Credential maintenanceYours. Refresh or reauthorize the user token with Meta, then replace the Worker secret. Syndroo has no OAuth flow and does not renew tokens.
External dependencyMeta's own product terms, app review requirements and rate limits apply. Syndroo controls none of them, includes no pricing of its own, and promises nothing about a current plan, quota or token lifetime; follow Meta's current documentation.

Check the provider's current documentation before relying on a specific scope, token lifetime or limit. Those facts change on the provider's schedule, not on this page; the links under Official sources are the references to re-check.

When something fails

A failed publication stores errorCode, errorMessage and errorAmbiguous in the post response. Read them before you act.

What you seeWhat it meansWhat to do
HTTP 422 PLATFORM_NOT_CONFIGUREDTHREADS_ACCESS_TOKEN is missing or empty.Add the secret, then send the request again. Nothing was stored or queued.
AUTHMeta rejected the token: expired, revoked, or missing the publishing permission.Reauthorize or refresh the token, update the Worker secret, and check the account before resending, because an earlier attempt may have succeeded before the token broke.
INVALID_CONTENTThe text exceeded the adapter limit and nothing was sent.Shorten the text and publish again with a new key.
RATE_LIMITThreads asked the caller to slow down.Syndroo retries this automatically with backoff, up to three attempts. Let it finish, then poll the same post.
PROVIDER_UNAVAILABLE, NETWORK or UNKNOWN, with errorAmbiguous: trueThe write may have reached Threads; the outcome is unknown.Check the account by hand. Syndroo never resends an ambiguous publication automatically.
Post status partialSome selected platforms succeeded and some failed.Never resubmit the platforms that succeeded. The failed ones need attention only after you have excluded an ambiguous outcome.
Rule out an ambiguous outcome before publishing again.

If a publication is failed with errorAmbiguous: true, check the Threads account by hand first, because the post may already exist. Only when you have confirmed that nothing was published and you still want the post should you send a new request with a new Idempotency-Key. Reusing the old key replays the stored result instead of publishing. Read Ambiguous outcomes for the reasoning.

Official sources

This page follows the candidate's capability record and the product revision above. It was not verified against a live Threads account, so re-check the official documentation when a step, scope or limit differs from what you see.