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

X setup

X is published through the official @xdevplatform/xdk SDK with OAuth 1.0a user authentication. That means four secrets rather than one token, and an app that is allowed to post for the account.

Experimental Provider x-sdk

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. X is recorded as experimental for this candidate.

Evidence: unit tests in the core repository, including workerd coverage of the SDK path. There is no Mock SNS end-to-end coverage for X, and no live-account acceptance record exists. Experimental means the adapter is implemented and tested locally, and that live publishing through it has not been validated. See Platform readiness and the capability record.

What you need

  • An X account you can post from, on the same account as the developer app you will create.
  • Access to the X developer portal and an app with permission to publish for that account. The recorded requirement for this candidate is an app with Read and Write permissions; access levels and their names are X's to change, so confirm the current requirement in the portal and the official documentation.
  • Four OAuth 1.0a values for that app: the consumer key and secret, plus the user access token and its secret.
  • 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 all four Worker secrets:

SecretRequiredValue
X_API_KEYYesOAuth 1.0a consumer API key for the app.
X_API_SECRETYesOAuth 1.0a consumer API secret.
X_ACCESS_TOKENYesUser access token issued for the account, after the app can post.
X_ACCESS_TOKEN_SECRETYesSecret paired with that user access token.

All four are required. A partial set leaves X unconfigured, and selecting it returns HTTP 422 with PLATFORM_NOT_CONFIGURED.

Create the app and its keys by hand

The developer portal's layout, permission names and plan names change over time. Follow the official X documentation linked under Official sources while you work through this sequence.

  1. Create or open the app

    Sign in to the developer portal with the account you will publish from, then create a project and app, or open an existing one.

  2. Set the app's permission level

    In the app's user-authentication settings, choose the permission level that allows posting for the account. The recorded requirement for this candidate is Read and Write; if the portal offers different wording, pick the level the documentation describes as posting access.

  3. Generate the user access token and secret

    Generate the user access token and its secret after the permission level is set. The portal can produce the pair directly, and X also documents a three-legged OAuth 1.0a flow that ends with the same two values; that flow needs a registered callback URL, and X documents a PIN-based variant for cases where no callback UI exists. If you change the permission level later, regenerate the user credentials, because a token issued under one permission level does not gain the new one by itself.

  4. Record all four values

    Copy the consumer API key and secret and the user access token and secret into your secret store. Treat each value as a secret; do not paste them into a page, a chat message or an issue.

Posting permission depends on your X access level.

Whether an app can publish, and how many requests it may make, is decided by X and by the access level attached to your developer account. Syndroo cannot grant, buy or work around that access, and this page makes no promise about which level you need or what it costs.

Add the secrets to the Worker

Put the values 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.

X_API_KEY="your-x-consumer-api-key"
X_API_SECRET="your-x-consumer-api-secret"
X_ACCESS_TOKEN="your-x-user-access-token"
X_ACCESS_TOKEN_SECRET="your-x-user-access-token-secret"
Configuration is checked for shape, not for validity.

Before accepting a post, Syndroo checks that all four values exist and are non-empty. It does not call X to test them. Revoked, expired or under-permissioned credentials pass that check and surface later as a publication failure with errorCode AUTH.

Publish and check one post

The commands below publish for real once the secrets above are 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: x-setup-001" \
  --data '{
    "content": "First post from my own Syndroo Worker.",
    "platforms": ["x"]
  }'

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 X 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": ["x"],
  "status": "published",
  "publications": [
    {
      "platform": "x",
      "provider": "x-sdk",
      "status": "published",
      "attempts": 1,
      "externalId": "1800000000000000000",
      "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; build no links by hand from the identifier.

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 limit280 weighted characters, validated with twitter-text before the network call. Longer formats such as premium long posts are outside this version.
Content typeText only, with SDK retries disabled so Syndroo's own retry policy is the only one.
Credential maintenanceYours. X documents OAuth 1.0a user tokens as not expiring on their own but remaining revocable, so a revoked token keeps failing as AUTH until you regenerate the user credentials and replace the Worker secrets. Syndroo has no OAuth flow and does not renew credentials.
External dependencyX's access levels, request limits and posting rules apply. Syndroo includes no pricing of its own and promises nothing about which access level you have or need; check X's current plans and documentation.

Check the provider's current documentation before relying on a specific permission, character-counting rule or request 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_CONFIGUREDAt least one of the four X secrets is missing or empty.Add all four secrets, then send the request again. Nothing was stored or queued.
AUTHX rejected the credentials: revoked, expired, or issued without posting permission.Regenerate the user credentials with the right permission level, update the Worker secrets, and check the account before resending.
INVALID_CONTENTThe text exceeded the weighted-character limit, or failed validation, and nothing was sent.Shorten the text and publish again with a new key.
RATE_LIMITX refused the request because of its own request limits.Syndroo retries this automatically with backoff, up to three attempts. If it still fails, your access level's limit is the constraint; wait before trying again.
PROVIDER_UNAVAILABLE, NETWORK or UNKNOWN, with errorAmbiguous: trueThe write may have reached X; 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 X 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 X account, so re-check the official documentation when a permission, limit or portal step differs from what you see.