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

Recipe: publish a product update

One release note, two destinations, and wording that fits each platform. This is the smallest realistic cross-posting job: a shared body, one override, one idempotency key, and a result you read back instead of assuming.

Inputs

  • A release identifier you can reproduce, such as a tag or a version string. It becomes the idempotency key.
  • Shared text for every platform, and optionally shorter text for one of them.
  • A Worker URL and key in the environment: SYNDROO_URL and SYNDROO_API_KEY.
  • Configured platforms. This recipe uses bluesky and threads; both need their credentials before the request is accepted (Bluesky, Threads).

Steps

  1. Write both versions inside their limits

    The candidate enforces 300 Unicode code points and 3,000 UTF-8 bytes for Bluesky, and 500 characters for Threads. The API caps the shared body at 10,000 code points, and a per-platform limit that is exceeded later fails that publication with INVALID_CONTENT instead of being truncated.

  2. Send the request

    The key is derived from the release identifier, so repeating this exact request after a network failure returns the original post instead of publishing twice.

    curl -X POST "$SYNDROO_URL/v1/posts" \
      -H "Authorization: Bearer $SYNDROO_API_KEY" \
      -H "Content-Type: application/json" \
      -H "Idempotency-Key: release-0.2.0-rc.1" \
      --data '{
        "content": "Syndroo 0.2.0-rc.1 candidate: one HTTP call accepts a post and queues one publication per platform.",
        "platforms": ["threads", "bluesky"],
        "overrides": {
          "bluesky": { "content": "0.2.0-rc.1 candidate: Mock SNS gate green for Bluesky and Threads. Live accounts still pending." }
        }
      }'
  3. Expected acceptance

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

    Keep the id. HTTP 202 does not confirm platform success, and it may already be out of date when it reaches you: the Queue consumer can have published before you read the response. Poll the post for the real outcome.

  4. Read the per-platform result

    Query the post with the id from the receipt:

    curl \
      -H "Authorization: Bearer $SYNDROO_API_KEY" \
      "$SYNDROO_URL/v1/posts/post_..."

    The response carries one publication entry per platform:

    {
      "id": "post_...",
      "status": "published",
      "publications": [
        { "platform": "threads", "status": "published", "attempts": 1, "externalId": "1789..." },
        { "platform": "bluesky", "status": "published", "attempts": 1, "externalId": "at://...", "externalUrl": "https://bsky.app/..." }
      ]
    }

    Show the platform's own link when it returned one. A platform that returned only an identifier gets only that identifier shown; do not construct a URL from it.

Failure handling

What you seeWhat happenedWhat to do
Post status partial One platform published and the other did not. Report per platform. There is no retry endpoint: first confirm errorAmbiguous is false on the failing entry, fix the cause, and then decide whether to send a new request with a new key that lists only the platforms you confirmed failed. Never include the platforms that already published.
errorCode: "RATE_LIMIT", attempts: 3 Retries were attempted and the retry budget is exhausted. Wait for the platform's window to pass, then publish a new request. Do not resend the whole original request against every platform.
errorCode: "INVALID_CONTENT" The text exceeded the platform's own limit after the API accepted it. Shorten that platform's override and send a new request with a new key.
errorAmbiguous: true The platform may have accepted the post. Check the account by hand before doing anything else. Syndroo never resends an ambiguous publication.
HTTP 409 IDEMPOTENCY_CONFLICT The release key was already used with different text. Decide whether this is the same post or a new one. Same post: resend the original body. New post: use a new key.

Applies to

Syndroo 0.2.0-rc.1 (unpublished candidate). Statuses, fields and limits are those documented in the HTTP API reference; per-platform wording needs the platform's own guide.