yeetpostyeetpost

Changelog

What shipped

Every change that reached you, newest first. Things that are still open pull requests are not on this list.

#175 #176 #177 #178 #179 #180 #181 #182 #183 #184 #185

  • Tags have a real charset now: 1 to 40 lowercase letters, digits, dashes, underscores, colons, dots and slashes. A tag you send is lowercased and trimmed before it is checked, so cms:Launch and cms:launch are the same tag; anything else is 400 invalid_request.
  • Queues can be paused. PATCH /connections/{connectionId}/queue with { "paused": true } holds every queued post where it is until you resume it; resuming moves anything that fell overdue onto the connection's next free slot, one at a time, so a backlog never bursts out at once. The endpoint is strict now too: an unknown field in the body is 400 invalid_request instead of being silently ignored.
  • Copy a connection's queue slots to other accounts in one action, instead of re-entering the same weekly schedule by hand for each one.
  • Refusals clear themselves. A refusal that was really about a dead login (reconnect_required), a platform outage (platform_unavailable), or a send that never confirmed (send_interrupted) now disappears from the account's warnings on its own once the account reconnects or the platform recovers, and it names the account it is about.
  • New accounts get a welcome message in their own language.

#146 #147 #148 #149 #150 #151 #152 #153 #154 #155 #156 #157 #158 #159 #160 #161 #162 #163 #164 #165 #166 #167 #168 #169 #170 #171 #172 #173 #174

  • Reconnecting a broken login is obvious now. LinkedIn, X, Facebook, Instagram, Discord and the rest tell you before a login expires and show a Reconnect button on the card. Reconnecting just says Reconnected, and for a customer's account you can send them a reconnect link instead.
  • Failures are recorded and explained, not swallowed. A failed post keeps its reason in plain words with a retry button, a platform that is only busy or down is safe to resend, and a dead webhook or bot now asks you to reconnect instead of failing forever.
  • Writing a post got a real composer: one consistent design, a fix-before-resend step so a bad post never goes out twice, and an optional AI polish that uses your own Claude or OpenAI key to adjust the tone before you send.
  • Connections are easier to manage. Customer-facing connect links come first, Facebook and Instagram page pickers refresh properly on reconnect, Reddit asks for your subreddit up front, and picking your LinkedIn profile and pages happens once, after a single login.
  • Billing is clearer: you can see exactly which accounts are billed, only active connections are charged, VAT shows at checkout.
  • Dozens of smaller fixes across the app: a working slot editor, a full-width queue calendar, a posts list that fits the page and scrolls, forgiving CSV import, working invites, and phone screens that finally fit.

#90 #91 #92 #93 #94 #95 #96 #97 #98

  • Analytics. Once a post is out, yeetpost reads its numbers back off the platform and keeps every read: an hour after it goes out, then hourly for 48 hours, then daily until it is 30 days old. GET /posts/{postId}/metrics gives you the latest read and the whole history, GET /analytics?from&to gives totals, a per-day series and a per-platform split, and a post.metrics webhook fires once a post per day while the numbers are still moving. MCP get_post carries metrics.latest too.
  • What each platform reports is not the same, and the API says so rather than guessing. A number a platform does not report is null, never 0. Bluesky and Mastodon report likes, reposts and replies. LinkedIn reports reactions and comments from any account, and impressions and clicks only for a company page, because that is the only surface LinkedIn answers statistics for. Discord, Telegram, Slack, SMS and email report nothing back at all.
  • X reads are metered, at 1 cent a read on the same monthly X spend cap as the post fees, because X charges for reads. That price is a placeholder, so X analytics is off by default: X posts are not read unless the deployment turns it on. Everything else in analytics works today and is free.
  • The key management API. Minting a key for a customer stops being a dashboard errand: POST /profiles/{profileId}/keys mints one scoped to that profile and answers the secret once, GET /profiles/{profileId}/keys and GET /keys list keys by prefix, and DELETE /profiles/{profileId}/keys/{keyId} and DELETE /keys/{keyId} revoke. Only an unscoped key may use them, a test key mints and manages test keys only, a key minted here is always scoped to the profile in the path, and 50 live plus 50 test keys per profile is the cap. Revoking takes effect on the next request across REST, MCP and connect URLs.
  • Connect an MCP client with a login. Add https://api.yeetpost.com/api/v2/mcp as a custom connector in claude.ai with no key: it discovers the authorization server, registers itself, opens a consent screen where you sign in, pick your whole account or one profile, pick live or test, and approve. yeetpost runs the OAuth 2.1 server behind that (RFC 9728 and RFC 8414 discovery, RFC 7591 registration, PKCE required, rotating refresh tokens, reuse detection). A grant is scoped and paced exactly like a key, the apps you approved are listed on the MCP screen in the console, and revoking one there kills its tokens at their next request. Clients that can hold a key keep using a key, and REST stays key-only.
  • Team members. An account is now a thing several people can share. Invite by email, and each member is an owner, an admin or a member: owners do everything including billing and deleting the account, admins do everything except those, members post and read and manage connections and profiles but cannot touch keys, members or billing. A user can belong to several accounts and switch between them in the sidebar. Billing does not change: every account has one owner and one bill.
  • The console got a dashboard worth looking at. Posts have grid, list and calendar views, with the list as the default and 30 rows at a time; a Queues screen draws a week of every connection's slots with the queued posts on them; CSV import parses the file in your browser and shows every row before anything is sent; and an Analytics screen draws the numbers above with a 7, 30 or 90 day window.
  • The console also has a dark mode now, on a sun and moon toggle in the sidebar, following your system until you pick.
  • These docs are regenerated from the OpenAPI spec: 38 endpoints, including the five key management endpoints, the two analytics endpoints and the post.metrics webhook event.
  • Still unpublished: the CLI in [email protected] is not on npm, and the Node, Python and Go SDKs are not on npm, PyPI or reachable by go get. The API, the MCP server and the console are the ways in today.

#53 #54 #55 #56 #57 #58 #60 #61 #62 #63 #64 #66 #67 #68 #69 #71 #72 #74 #75

  • Discord channels are live. Create a webhook in the channel, paste the url, and posts land there under the name and avatar you gave it. 2000 characters, up to five images with alt text, no threads.
  • Telegram channels are live. Make your own BotFather bot an admin of the channel and paste the token. 4096 characters, 1024 when an image is attached, png and jpeg only, threads and photo albums.
  • Mastodon is live, on any instance. Type the host, approve on your own server. The character limit is your instance's own, read when you connect, and a thread rolls back if one segment is refused.
  • All three are free to post to and count as one connected account each, like LinkedIn and Bluesky. Six platforms are live now, and every one has its own docs page: how to connect, what works, and the refusal you get when it does not.
  • A yeetpost CLI, and a Claude Code plugin that installs the MCP server for you. Written and merged; npm publishing next, so neither is installable from a package registry yet.
  • A Go SDK, hand written against the v2 API like the Node and Python ones. Written and merged; publishing next, so go get does not reach it yet.
  • Webhooks got serious. Every delivery carries x-yeetpost-event-id so you can dedupe, retries run 7 attempts on a backoff (1m, 5m, 30m, 2h, 6h, 12h, 24h) and then land in a dead letter state instead of disappearing, and you can replay any delivery from the console or the API.
  • Posting queues. Give a connection a set of daily slots and a timezone, and a post without a time goes into the next free slot instead of straight out.
  • Profiles. If you are building on yeetpost and posting for your own customers, create a profile per customer, connect their accounts into it, and post with profileId. A post that names a profile cannot reach anything outside it, connections and posts each carry their own profileId, and two new webhook events, connection.created and connection.removed, tell you when a customer's account arrives or goes. Billing does not change: every connection counts on the same per-account ladder and you get one invoice. The guide is at /docs/build-a-platform.
  • Hosted connect URLs. POST /profiles/{profileId}/connect gives you a link to a page we host. Send your customer there, they connect their own account into that profile, and they land back on your redirectUrl with the connection id in the query. The token in the url is the whole authorization: one profile, one redirect, one use, fifteen minutes, and only its hash is stored. headless: true drops our header and footer so the page sits inside your own popup, GET /connect-sessions/{id} says how it went if you would rather poll than read the query, and connection.created now carries connectSessionId so a receiver can file the connection without a browser. A test key offers the sandbox and nothing else, so the whole flow runs in CI.
  • Scoped API keys. Pick a customer under Scope when you create a key and that key can only ever reach that one profile: its connections, posts, media and webhooks, and nothing else. Anything outside is 404, managing profiles is the new 403 forbidden, and an Idempotency-Key is reserved inside the scope, so two of your customers can both send order-123 on the same day. A key can also carry a list of origins its connect URLs may redirect to. Deleting a profile revokes the keys scoped to it in the same transaction that disconnects the accounts. Keys are minted in the dashboard: public key-management endpoints are next.
  • Delete a published post, not just cancel a scheduled one. DELETE /posts/{postId} now takes it down on X, Bluesky, Mastodon, Telegram, Discord and LinkedIn, and fires a post.deleted webhook. Platforms with no delete answer delete_unsupported and say so.
  • Drafts and tags. POST /posts can store a post instead of sending it, PATCH /posts/{postId} edits it, and POST /posts/{postId}/publish sends it under the id you already have. Tag a post on the way in and filter your history by tag on the way out.
  • Health and uptime. GET /health and GET /health/history are public, no key needed, and report the API and every worker. The new status page reads them and shows 90 days of daily uptime, with days before sampling began marked unmeasured rather than down.
  • The Node, Python and Go SDKs and the CLI are all at parity with the v2 API now: images, shapes, drafts, tags, queues, profiles, connect sessions, health and the webhook signature check. Every one of them can create a profile, ask for a connect URL and read the session back. Said plainly: none of them is published. They are not on npm, not on PyPI and not reachable by go get, so the API itself is still the way in.
  • The OpenAPI spec got a hygiene pass, and these docs are regenerated from it: every error code is in the enum and in the description, every code has a real example, and the three outcomes of DELETE /posts/{postId} are titled rather than numbered.

#31 #46 #48 #49 #50 #51

  • Images. Upload one with POST /media, get an id back, attach it to a post by id. Delivered on X, LinkedIn and Bluesky, with alt text.
  • Post shapes. Send a thread on X and Bluesky, or a first comment on LinkedIn, from the same request that sends the post.
  • Node and Python SDKs, written by hand against the v2 API rather than generated, both versioned 2.0.0. Written and merged; npm and PyPI publishing next. Until that lands they are not installable from a package registry, so the API itself is still the way in.
  • Free accounts have one fair-use cap: 100 posts a day, counted in UTC across all your connections. Paid accounts have no daily cap, and sandbox posts never count toward it.

#11 #12 #19 #20 #27 #28 #30 #37 #38 #43 #45

  • Bluesky is live. Connect with your handle and an app password, no OAuth dance. A self-hosted PDS works too. Bluesky posts are free to send and count as one connected account, like LinkedIn.
  • X posts now bill a flat fee per post: 2 cents, or 25 cents when the post contains a link. LinkedIn, Bluesky and sandbox posts stay free. The fee is charged from your first X post, so a card has to be on file before X will send, and you can cap what you spend on X per month.
  • Sandbox connections and test API keys. A test key starts with yp_test_, reaches sandbox connections and nothing else, and a sandbox post is validated, stored and webhooked like a real one but published nowhere. Start a post with [fail] to test your error path.
  • Every authenticated response carries an x-request-id, plus rate limit headers that tell you where you are in the window. Quote a request id and we can find that exact call. A Logs section in the console lists your requests per key, with secrets redacted.
  • The API answers browsers directly now, and takes Authorization: Bearer everywhere it took x-api-key. Every timestamp is ISO-8601 UTC, and the playground sends real requests instead of a preview.
  • Support threads in the app: message us, get a reply, see it without digging through email.
  • The whole product was redesigned, dark first and monochrome.
  • The API page fills its example commands in with your own key and your own connection slugs.
  • The docs and the OpenAPI spec now name only the platforms that are actually live, so nothing on the page is a promise.
  • Em dashes are gone from the docs, the spec descriptions and the product copy.

The developer API

#10

  • The v2 API. POST /posts takes text and a list of connection slugs and fans out to all of them in one call, with a result per connection. POST /post/{slug} takes the post as a plain body, for the one-liner case.
  • List your connections, list and read your posts, cancel a scheduled one.
  • An OpenAPI 3.1 spec at /api/v2/openapi.json, no key needed to read it.
  • Send an Idempotency-Key with a post and a retry cannot post twice.
  • Signed webhooks for post.sent and post.failed, delivered with retries.
  • An MCP server with five tools, so an agent can post without any glue code.
  • New pricing: posts are unlimited, and you pay per connected account. The first two accounts are free, then $5 each, $2.50 from the eleventh, $1 from the hundred and first.
  • A developer console: API keys, an MCP page, and a playground.

Keeping up

There is an RSS feed of this page. The docs always describe what is live right now, and status tells you whether the API is answering. Building on the API? Watch this page: new endpoints and new platforms land here first.