Upload media

Attach an image, video or PDF for a post. Three shapes: JSON {url} (the server fetches a public https URL — also how an MCP host's attachment arrives, through its temporary download url), JSON {ticket} (redeems an upload slot from POST /media/ticket), or multipart form-data with a file field. ≤100 MB. Optional: thumbnail_timestamp_ms picks a video's cover frame; alt_text (≤1000 chars) sets an image's accessibility text (applied natively on X and Bluesky); people_tags tags people in a picture (see the field — Instagram only, and every handle is checked before the file is stored). Returns {id, kind} — pass id in create_post media_ids. A PDF (kind: "document") is a LinkedIn document post: one per post, attached on its own, and only to a LinkedIn account whose connection supports documents — create_post refuses anything else and says why.

post/media

Request

  • Base URL: https://xpost.to/api/v1
  • URL: https://xpost.to/api/v1/media
  • Auth: HTTP bearer

Request body

urlstring uri
ticketstring

An upload ticket from POST /media/ticket, once the file has been posted to the slot. Give either this or url.

thumbnail_timestamp_msinteger
alt_textstring

Example request

{
  "people_tags": [
    {
      "id": "somestudio",
      "x": 0.42,
      "y": 0.61
    }
  ]
}

Response

Stored

idstring uuid
kind'image' | 'video' | 'document'

document is a PDF — it publishes on LinkedIn only, alone

people_tagsobject[]

Echoed back only when tags were sent and stored — the cleaned copy (@ stripped, coordinates clamped) that will actually go out.

media_idsstring[]

Only when redeeming a ticket whose browser door (attach_url) was used: every file it received, in the order they were added. With more than one file this is the whole answer — id and kind are absent and count says how many.

already_uploadedboolean

True when the file arrived through the ticket's browser door rather than the upload slot. Nothing to retry — use the ids.

Changes

No recorded changes to this operation across all 1 revision of this API.