yeetpost

Posting

Posting

Two endpoints post: a plain-text one-liner for shell scripts and cron jobs, and a JSON endpoint that fans one post out over several connections.

#The one-liner

The request body is the post. It goes to a single connection and is the simplest thing to call from a shell script. Content-Type must be text/plain or application/x-www-form-urlencoded, or be left off; anything else is 415.

curl -X POST "https://api.yeetpost.com/api/v2/post/linkedin" \
  -H "x-api-key: $YEETPOST_API_KEY" \
  -H "content-type: text/plain" \
  -d 'shipped the new api docs today'

This is the original v2 endpoint and it is not going away, but new integrations should prefer the JSON one below: it takes several connections, supports Idempotency-Key, and returns post ids.

#JSON fan-out

POST /posts posts the same text to every slug in connectionSlugs. Duplicate slugs are ignored.

curl -X POST "https://api.yeetpost.com/api/v2/posts" \
  -H "x-api-key: $YEETPOST_API_KEY" \
  -H "content-type: application/json" \
  -H "Idempotency-Key: $(uuidgen)" \
  -d '{
  "text": "shipped the new api docs today",
  "connectionSlugs": [
    "linkedin",
    "x"
  ]
}'
response
{
  "results": [
    {
      "connectionSlug": "linkedin",
      "status": "sent",
      "postId": "6f1b0c8a-1f3d-4d3e-9a2b-2f5a1c9e7d10",
      "url": "https://www.linkedin.com/feed/update/urn:li:share:1234567890",
      "scheduledFor": null,
      "error": null
    },
    {
      "connectionSlug": "x",
      "status": "failed",
      "postId": "0b7e4a52-9f0c-4a1c-8b3a-6d2f5b1c0e44",
      "url": null,
      "scheduledFor": null,
      "error": {
        "code": "platform_rejected",
        "message": "X: duplicate post was detected"
      }
    }
  ]
}
Partial failures are normal. As long as at least one slug matches a live connection you get a 200, and every connection has its own entry in results with a status of sent, scheduled or failed. Check the per-item status and error. The request only fails as a whole (400 invalid_connection) when none of the slugs match.

#Scheduling

Both endpoints schedule instead of sending when you give them a time. It has to be in the future and within 30 days. The one-liner takes a query parameter, scheduled_for; the JSON endpoint takes a field, scheduledFor. Both are ISO 8601.

curl -X POST "https://api.yeetpost.com/api/v2/posts" \
  -H "x-api-key: $YEETPOST_API_KEY" \
  -H "content-type: application/json" \
  -d '{
  "text": "shipped the new api docs today",
  "connectionSlugs": ["linkedin"],
  "scheduledFor": "2026-09-15T15:00:00Z"
}'

A scheduled post sits in status scheduled until the worker picks it up. Nobody is waiting on an HTTP response by then, which is what webhooks are for.

#Cancelling a scheduled post

Cancel one while it is still waiting. The row is kept: it moves to status cancelled and still shows up in GET /posts. Nothing is deleted.

curl -X DELETE "https://api.yeetpost.com/api/v2/posts/6f1b0c8a-1f3d-4d3e-9a2b-2f5a1c9e7d10" \
  -H "x-api-key: $YEETPOST_API_KEY"

Only a post that has not gone out can be cancelled. One that is already sent, failed, cancelled, or being sent right now gives 400 invalid_request. If the worker claims the post while your request is in flight you get 409 post_not_cancellable: it was not cancelled and is on its way out, so read it back with GET /posts/{postId} to see how it ended.

#Listing posts

Your posts, newest first, one row per connection they went to. Filter with status (sent, scheduled, processing, failed, cancelled) and page with limit (1 to 100, default 25) and offset.

curl "https://api.yeetpost.com/api/v2/posts" \
  -H "x-api-key: $YEETPOST_API_KEY"

Timestamps go both ways in ISO 8601 UTC: createdAt and scheduledFor come back as 2026-08-26T09:24:11.412Z.

#Full schemas

Every parameter, field and error for these endpoints is on the API reference, generated from the spec.