Syndroodocs
WebsiteGitHubOverview

Threads

Overview

Provider id threads. Metadata documents a two-step publish: create a text container, then publish it. The provider takes the documented one-call path instead, sending media_type=TEXT together with auto_publish_text=true, so a text post is created and published by one request.

Requirements

  • A Meta app with the Threads use case, and its client id and client secret.
  • A registered redirect URI that the authorization step can return to.
  • A Threads account that has authorized the app.

Credentials

FieldMeaningSecret
client_idThe app's client id.No
client_secretThe app's client secret.Yes

The authorization code is exchanged at the API host, and a long-lived token is requested at the documented 60-day exchange. The token is what the connection stores.

Connect

redirectUri is required, and the two hosts default to the values published by Meta, so a caller that supplies one host cannot silently mix the pair:

{
  "type": "start",
  "provider": "threads",
  "options": { "redirectUri": "https://example.com/oauth/callback/threads" }
}
syndroo connect --input connect.json --json

With no options the two hosts are https://www.threads.net for authorization and https://graph.threads.net for the API, and the default scope list is threads_basic plus threads_content_publish. The client id and secret can be supplied as connect options by a machine caller, or read as the two credential fields.

The start step answers an authorization action that a browser completes at the Threads authorization host, and the local CLI completes that OAuth callback itself, with --redirect-uri and a controlling terminal or with --callback-url -, as the credential reference describes. That local callback path is fixture-tested against local servers only; no live Threads account was connected.

Deploy a server

This page's syndroo connect flow stays local. To run Threads OAuth through your own Cloudflare Worker and publish from GitHub Actions, follow Deploy a server. That flow registers https://YOUR-WORKER.YOUR-SUBDOMAIN.workers.dev/oauth/callback/threads with the confirmed host and runs syndroo server connect threads --app-id APP_ID.

Self-hosted Server. The Server flow uses @syndroo/[email protected] and @syndroo/[email protected]. See the CLI reference for acceptance limits.

First publish

The text that is sent is the target's text publish option:

{
  "type": "prepare",
  "content": {},
  "targets": [
    { "provider": "threads", "options": { "text": "Hello from Syndroo." } }
  ]
}
syndroo publish --input post.json --json

The provider pins media_type and auto_publish_text itself; they are not caller options. The only evidence-backed URL for an account is its profile URL, so a delivery reports the post id and, when the stored account has a username, the profile URL. No post permalink format is invented.

Capabilities

The manifest declares text. UNRESOLVED. A text limit is not present in the reachable Meta artifacts, so this guide does not print one.

Options

WhereAccepted keys
Connect optionsredirectUri (required), apiHost, authorizationHost, clientId, clientSecret, scopes.
Publish optionstext, required.
ContentNone required; Threads sends the target option.

Troubleshooting

The provider never retries and never reclassifies. A container that was created while the publish call failed would be a real ambiguous window; with the one-call path there is no stored container to reconcile, and a timeout after the call still stays unknown and non-retryable.

UNRESOLVED. The reachable Meta artifacts disagree on .net versus .com for both hosts, no general error-code table is available, and PKCE support is not documented in them. The provider uses the collection's .net pair by default for that reason.

Revoke and security

UNRESOLVED. No token or app revocation procedure was retrieved from a primary Meta source, so this guide does not print one. Removing the app's access in your Meta account settings and then disconnecting the local connection is the safe local step:

syndroo connect --disconnect <connectionId>