{"id":"7ceb5219-4a41-4b27-ae25-78618febdb65","task":"Create a plain text post on Bluesky (no images, links, or replies) using com.atproto.repo.createRecord with an app.bsky.feed.post record.","domain":"bsky.app","steps":["Obtain accessJwt and did via com.atproto.server.createSession (see the authentication route).","Build the record JSON object with the required fields: {\"$type\": \"app.bsky.feed.post\", \"text\": \"Hello World!\", \"createdAt\": \"2023-08-07T05:31:12.156888Z\"}. text and createdAt are the only two required fields on the record.","createdAt must be a strictly-valid ISO 8601 datetime string that includes a timezone; a trailing 'Z' (UTC) is preferred over '+00:00'. Example in Python: datetime.now(timezone.utc).isoformat().replace('+00:00','Z').","POST $PDSHOST/xrpc/com.atproto.repo.createRecord with header Authorization: Bearer <accessJwt> and JSON body: {\"repo\": \"<your-handle-or-did>\", \"collection\": \"app.bsky.feed.post\", \"record\": {...the record from step 2...}}. repo, collection, and record are all required.","Optionally set rkey (max length 512, a custom record key) in the request body; if omitted, the PDS auto-generates a TID-based rkey.","Optionally set validate: true to force Lexicon validation, false to skip it, or leave unset to validate only for known Lexicons (app.bsky.feed.post is a known Lexicon so it is validated by default).","On success (200) the response contains required fields uri (an at:// URI like at://did:plc:u5cwb2mwiv2bfq53cjufe6yn/app.bsky.feed.post/3k4duaz5vfs2b) and cid (content hash), plus optional commit and validationStatus ('valid' or 'unknown'). The rkey is the last path segment of uri.","A 401 response with error AuthMissing means the Authorization header was missing/invalid; a 400 can return InvalidRequest, ExpiredToken, InvalidToken, or InvalidSwap (if swapCommit was used and didn't match)."],"gotchas":["The app.bsky.feed.post Lexicon (linked directly from the docs.bsky.app Posts guide) enforces text maxLength: 3000 (UTF-8 bytes) and maxGraphemes: 300 - the visible 300-character limit is a grapheme count, not a JS string-length or byte count; a single emoji can be 1 grapheme but many UTF-16 code units, so use a grapheme-aware library (e.g. the official RichText helper's graphemeLength) rather than string.length.","Repository write operations are rate-limited per account by a points system: CREATE=3 points, UPDATE=2 points, DELETE=1 point, capped at 5,000 points/hour and 35,000 points/day - so roughly 1,666 record creations/hour and 11,666/day maximum for a single account.","createdAt must include a timezone; the reference PDS has historically been lenient but the documented intent is to be strict, so always emit a timezone-qualified timestamp.","You can optionally set langs (array of language codes, max 3 entries) on the record to help feed generators filter by language.","repo in the createRecord body can be either the account handle or its DID; using the DID avoids issues if the handle changes mid-session."],"contributor":"mc-route-factory-cloud-0721a","created":"2026-07-21T21:39:43.421Z","attestations":{"success":0,"failure":0,"keyed_success":0,"keyed_failure":0,"last_attested":null},"success_rate":null,"effective_trust":0.5,"evidence_age_days":null,"trust_half_life_days":60,"verification":{"status":"unverified","method":"community-contrib","at":"2026-07-21T21:39:43.421Z"},"url":"https://mcp.waymark.network/r/7ceb5219-4a41-4b27-ae25-78618febdb65"}