REST API

Posts

Publish, read, retry and delete.

GET/v1/posts

Recent publishes, newest first. Replies are not listed as posts.

Paging

NameTypeDescription
limitquery1-100, defaults to 20.
beforequeryA publish id from a previous page's nextBefore. Returns the ones older than it.
includeDeletedquerytrue brings back posts you deleted from the channel. They are hidden by default. Our record and its metrics stay either way.
statusqueryNarrow to one status: publishing, published, partial, failed or cancelled. Omit for everything.
hasMoreresponseThe list was cut short.
nextBeforeresponsePass it back as before. Absent when there is nothing more.

POST/v1/posts

Publish to one or more connected accounts.

NameTypeDescription
contentRequiredstringPost text. Emoji count as UTF-8 bytes.
accountIdsRequiredstring[]Ids from GET /v1/accounts.
mediaIdsstring[]Media already confirmed with complete.
replyTostringPublish this as a reply to that post id.
threadItemsobject[]Split a long post into a chain: [{ content, mediaIds? }]. The first item is the root, the rest become replies under it in order. Each item obeys the character limit on its own. Exclusive with content. If a later item fails the ones already up stay up, and the response carries thread.resumeFrom.
topicTagstringOne topic to tag the post with. Threads takes exactly one and rejects periods and ampersands. On a thread it applies to the first piece only.
Idempotency-KeyheaderSend the same key when you retry and we return the first answer instead of publishing twice. Reusing a key with a different body is a 422. Kept for 24 hours.
waitbooleanHold the response until the post is really out. Text waits up to 10 seconds, media up to 90. Past that you get the usual 202 with a next hint, and the post keeps going. Defaults to false.
curl -X POST https://api.uplika.com/v1/posts \
  -H "authorization: Bearer $UPLIKA_KEY" \
  -H "content-type: application/json" \
  -d '{
    "content": "Now with images",
    "accountIds": ["acc_01H..."],
    "mediaIds": ["med_01H..."]
  }'

GET/v1/posts/{id}

One publish with the status of each target.

Target status

NameTypeDescription
publishingstatusIn flight at the channel.
publishedstatusCarries externalId and url.
partialstatusSome channels went out and some did not. Retry sends only the ones that failed. There is no 207 β€” publishing is 202 plus polling, so nothing is held open.
cancelledstatusDeleted from the channel. Our record and its metrics stay. Hidden from GET /v1/posts unless you pass includeDeleted=true.
failedstatusCarries error.

A publish has one row per channel. publishing is in flight, published carries the channel's own id and URL, failed carries a reason.

POST/v1/posts/{id}/retry

Retry the targets that failed. Targets that already went out are skipped.

DELETE/v1/posts/{id}

Delete the post from the channel and mark our record deleted.

Reading what is already on the channel

Our history only has what went out through us. These four read the channel itself and pick which channels to publish to. They are the routes behind list_channel_posts, get_quota, open_post and select_channels, so an agent gets the same answers over REST.

GET/v1/posts/{id}/thread

One post with its replies and metrics in a single call.

GET/v1/channels/posts

What is on the channel right now, including posts written in the app.

Query

NameTypeDescription
accountIdqueryLimit to one connected account. Omit to cover every channel.
limitquery1-100, defaults to 25.

GET/v1/channels/quota

How much of the 24 hour allowance the channel says is used.

POST/v1/accounts/select

Pick which connected channels to publish to.

NameTypeDescription
scopestring | string[]Omit to list candidates. "all" for every active channel, or an array mixing platform names, handles and account ids.
publishing ──► published     the channel accepted it, permalink is set
           └─► partial       some channels made it, some did not
           └─► failed        none of them made it, error says why

failed     ──► publishing   retry, and only the targets that failed go again
published  ──► cancelled    you deleted it; our record and its metrics stay

Common questions

How do I publish to several channels at once?

Name them all in accountIds on a single call. One request creates one publish with one row per channel, so you read the outcome in one place instead of correlating separate calls.

What does a 202 actually mean?

That we accepted the post and the channels have not answered yet. Read the per-target status to know what landed; the top-level response only says the work started.

Can I delete a post after it went out?

Yes. Deleting removes it from the channel and marks our record deleted, so the history still shows that it existed and when it went.