Media
Upload an image, list and delete them, render HTML into one.
Images you upload once and attach to posts. Free within your storage allowance.
List your images
GET/media
Your uploaded and rendered images, newest first, each with the posts that attach it. Read an image itself with GET /media/{mediaId}. A scoped key lists only its own profile's images.
Pages are walked with cursor: pass the cursor of one page as ?cursor= for the next, until it comes back null.
Rate limit: 60 requests per minute per API key.
curl "https://api.yeetpost.com/api/v2/media" \ -H "x-api-key: $YEETPOST_API_KEY"query parameters
Only images attached to a post on this connection.
Only images attached to this post.
Only images uploaded after this ISO 8601 timestamp.
The cursor of the previous page.
Images per page, 1 to 100. Defaults to 25.
response 200
One page of images.
headers: x-request-id, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
response body
image/png | image/jpeg | image/gif | image/webp
The posts that attach the image, newest first.
Pass as ?cursor= for the next page. Null on the last page.
errors
A malformed query parameter.
Missing or invalid API key.
More than 60 requests in a minute for this API key. Back off and retry.
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
What each code means and the fix: errors.
Upload an image
POST/media
Uploads one image and answers with the id you attach to a post. The body is the raw file, not a multipart form: set Content-Type to the image type and send the bytes. The bytes have to be that type: a file whose signature disagrees with the header is rejected with 400 invalid_media_type.
Images are free. The only limits are size: 8 MB per image, 50 MB stored per account, and 5 images per post. Delete images you no longer need to make room.
Uploading the same bytes twice is one image. The second upload answers with the id of the first and costs nothing against your allowance, so a client that retries an upload cannot fill your storage with copies. If the second upload carries alt_text and the stored image has none, the description is kept; if the stored image already has one, it wins and the new one is ignored. Give a post its own altText to override either.
Rate limit: 60 requests per minute per API key.
curl -X POST "https://api.yeetpost.com/api/v2/media" \ -H "x-api-key: $YEETPOST_API_KEY" \ -H "content-type: image/png" \ --data-binary @image.png{ "mediaId": "9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d", "contentType": "image/png", "sizeBytes": 48213}query parameters
Description of the image for screen readers, kept with the upload and used by every post that attaches it unless the post gives its own.
The image itself. At most 8 MB.
response 200
The image is stored and ready to attach.
headers: x-request-id, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
response body
Id to attach to a post. Uploading the same bytes again returns this same id.
image/png | image/jpeg | image/gif | image/webp
Size of the stored image in bytes.
errors
Empty body, a bad alt_text, or bytes that are not the image type they were sent as (invalid_media_type).
Missing or invalid API key.
The image is over 8 MB (media_too_large), or storing it would put you over your 50 MB allowance (media_storage_full).
The Content-Type is not one of the image types we take.
More than 60 requests in a minute for this API key. Back off and retry.
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
What each code means and the fix: errors.
Download an image
GET/media/{mediaId}
Serves the bytes back, with the Content-Type they were uploaded as. The response also carries X-Content-Type-Options: nosniff and Content-Disposition: inline, so a browser renders it as the type it is and never guesses another. Only your own images: somebody else's id answers 404.
Rate limit: 60 requests per minute per API key.
curl "https://api.yeetpost.com/api/v2/media/9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d" \ -H "x-api-key: $YEETPOST_API_KEY"path parameters
Id of the image, as returned by POST /media.
response 200
The image itself.
headers: x-content-type-options, content-disposition, x-request-id, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
errors
Malformed media id.
Missing or invalid API key.
No image of yours with that id.
More than 60 requests in a minute for this API key. Back off and retry.
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
What each code means and the fix: errors.
Delete an image
DELETE/media/{mediaId}
Deletes the image and frees the storage. Posts that used it keep their text and lose the image, so delete an image only once the posts that need it have gone out. A scheduled post whose images were deleted sends as text.
Rate limit: 60 requests per minute per API key.
curl -X DELETE "https://api.yeetpost.com/api/v2/media/9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d" \ -H "x-api-key: $YEETPOST_API_KEY"{ "id": "9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d", "deleted": true}path parameters
Id of the image, as returned by POST /media.
response 200
The image is deleted.
headers: x-request-id, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
response body
true
errors
Malformed media id.
Missing or invalid API key.
No image of yours with that id.
More than 60 requests in a minute for this API key. Back off and retry.
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
What each code means and the fix: errors.
Serve an image to a platform that fetches it by URL
GET/media/{mediaId}/raw
Instagram and Threads do not take an upload: a post names a URL and Meta's own servers fetch the bytes from it, with no API key to send. So this one endpoint serves an image without a key, and only through a link yeetpost signed for that image: the id and an expiry, HMAC'd, good for one hour, and minted only when a post to one of those two platforms actually needs it.
You never build these URLs and you never receive one. There is no way to ask for a link, nothing lists them, and an id with no matching signature is a 404, so an id cannot be probed for existence. It is documented because it is a public route on this API and you may see it in your logs.
Rate limit: 60 requests per minute per IP address.
curl "https://api.yeetpost.com/api/v2/media/9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d/raw?exp=&sig="path parameters
Id of the image.
query parameters
When the link stops working, as a Unix timestamp in seconds.
The signature over the id and the expiry.
response 200
The image itself.
errors
The link is expired, unsigned, signed wrong, or names an image that is not there. All four answer the same way.
More than 60 requests in a minute for this API key. Back off and retry.
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
What each code means and the fix: errors.
Render HTML into an image
POST/images/render
Renders one HTML document into a jpeg or png and stores it as an image you can attach to a post, exactly as if you had uploaded it. Use it for cards: a quote, a launch graphic, a chart drawn in HTML and SVG.
Size the card with preset (square 1200x1200, landscape 1200x627, portrait 1080x1350) or with width and height (200 to 2000). The size is in CSS pixels and the image is drawn at twice that density, so a 1200x1200 card is a 2400x2400 file. A render is stored under the same 8 MB per image and 50 MB per account limits as an upload.
What a card can load. JavaScript does not run. The only network a card has is Google Fonts (fonts.googleapis.com and fonts.gstatic.com); every other request is blocked. To show one of your own uploaded images, write yeetpost-media:<mediaId> where a URL goes, for example <img src="yeetpost-media:9b1c2d3e-4f50-4a6b-8c7d-1e2f3a4b5c6d">. We inline it before rendering. A key can only reference images it could attach to a post, the images in one card may total at most 10 MB with every use of an image counted, and anything else is 400 invalid_media.
Allowance. 300 renders per calendar month (UTC) per account. A render that fails on the renderer's side does not count; one that times out or comes out over 8 MB does, because it used the renderer's time. Past 300 the answer is 429 render_allowance_reached, naming the date it comes back. An account can also start at most 30 renders a minute across all its keys (429 render_rate_limited).
Attaching. Send postId to append the image to a scheduled post, after the images it already has (five at most). The post is checked before rendering, so one that cannot take the image costs nothing. A post that is being sent answers 409 post_not_editable; if it is picked up mid-render, the image is kept, the render counts, and the error carries mediaId and rendersUsed so you can still use the image. Otherwise use the returned mediaId in mediaIds when you create the post.
A render that takes more than 10 seconds is 504 render_timeout, a renderer failure is 502 render_failed, and 503 renderer_busy means try again in a few seconds; all are safe to retry.
Rate limit: 20 requests per minute per API key.
curl -X POST "https://api.yeetpost.com/api/v2/images/render" \ -H "x-api-key: $YEETPOST_API_KEY" \ -H "content-type: application/json"request body (application/json)
The card as an HTML document with inline CSS. No JavaScript runs. Reference your own uploads as yeetpost-media:<mediaId>.
square 1200x1200, landscape 1200x627, portrait 1080x1350.
square | landscape | portrait
Width in CSS pixels. Needs height.
Height in CSS pixels. Needs width.
jpeg | png
Description of the image for screen readers.
The connection the card is for. Recorded with the render; it does not restrict where the image can be posted.
A scheduled post to append the image to, after its existing images.
response 200
The image is rendered, stored and ready to attach.
headers: x-request-id, x-ratelimit-limit, x-ratelimit-remaining, x-ratelimit-reset
response body
Id to attach to a post. Rendering identical bytes again returns this same id.
image/jpeg | image/png
Size of the stored image in bytes.
The card's width in CSS pixels. The image itself is twice this.
The card's height in CSS pixels. The image itself is twice this.
The post the image was appended to, or null when no postId was sent.
Renders used this calendar month (UTC), this one included.
Renders allowed per calendar month.
errors
The request is malformed, a yeetpost-media: reference is not yours (invalid_media), or the post already has five images (too_many_media).
Missing or invalid API key.
connectionId is not one of your connections, or postId is not one of your scheduled posts.
The post was picked up for sending and can no longer be edited (post_not_editable).
The rendered image is over 8 MB (media_too_large), or storing it would put you over your 50 MB allowance (media_storage_full).
The rate limit (20 requests per minute per key, or 30 renders per minute per account as render_rate_limited), or the month's render allowance (render_allowance_reached).
Something went wrong on our side. Quote the x-request-id when you report it. A failure can happen before the rate limit is checked, so this response carries the request id and nothing else.
The renderer failed (render_failed).
The renderer is busy (renderer_busy). The render was not counted.
The card took more than 10 seconds to render (render_timeout).
What each code means and the fix: errors.