API reference
Schedule and manage posts from your own code, a script or an AI agent.
https://postqueuehd.com/api/v1
Authentication
Every request needs a bearer token, created under Settings → API.
Authorization: Bearer pq_live_xxxxxxxx
The token is shown once, at creation, and stored only as a hash. If it is lost, revoke it and make another.
The API is included in paid plans. A valid token on the free plan answers 403, not 401 — the token is fine, the plan is not.
Errors
One shape for everything, so a client parses one thing:
{
"message": "Pick at least one channel.",
"errors": { "channels": ["Pick at least one channel."] }
}
| Status | Meaning |
|---|---|
| 401 | No token, or the token is unknown, revoked or expired |
| 403 | The token is valid but the plan does not include the API |
| 404 | No such post, or it belongs to another team |
| 422 | The payload or a plan limit rejected the request |
| 429 | Rate limited — wait for the seconds in Retry-After |
Rate limits
Per token: 60 reads a minute and 20 writes a minute. Over the limit answers 429 with a Retry-After header.
What this token can do
The team the token belongs to, its plan, and how much of each allowance is left. Call this first: it answers what you are allowed to do without having to fail a write to find out.
curl https://postqueuehd.com/api/v1/me \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
The channels you can publish to
Every connected channel with its provider and status. The `id` values here are what `POST /posts` expects in `channels`. A channel whose `needs_attention` is true will refuse to publish until it is reconnected.
curl https://postqueuehd.com/api/v1/channels \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
The queue
Posts newest-cued first, cursor-paginated. Follow `links.next` to page.
| Field | Type | Required | Notes |
|---|---|---|---|
| status | string | no | draft, scheduled, publishing, published, partially_failed, failed or cancelled |
| per_page | integer | no | Up to 100. Defaults to 25. |
curl "https://postqueuehd.com/api/v1/posts?status=scheduled" \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
One post
A single post with one target per channel, each carrying its own status. An id belonging to another team answers 404, exactly like an id that does not exist.
curl https://postqueuehd.com/api/v1/posts/42 \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
Schedule a post
Creates a post and one target per channel. Leave `scheduled_for` out to publish as soon as possible. Send the same `idempotency_key` twice and you get the same post back, which is what makes retrying after a timeout safe.
| Field | Type | Required | Notes |
|---|---|---|---|
| caption | string | no | Up to 5000 characters. Each platform truncates to its own limit. |
| channels | integer[] | yes | Channel ids from GET /channels. |
| scheduled_for | ISO 8601 | no | Must be in the future. Omit to publish now. |
| media_ids | integer[] | no | Media already uploaded to this team. |
| idempotency_key | string | no | Up to 64 characters. Reuse it to make a retry safe. |
| channel_captions | object | no | Per-channel caption override, keyed by channel id. |
| channel_options | object | no | Per-channel platform options, keyed by channel id. |
curl -X POST https://postqueuehd.com/api/v1/posts \
-H "Authorization: Bearer $POSTQUEUE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"caption": "Summer drop is live",
"channels": [1, 2],
"scheduled_for": "2026-08-01T18:30:00Z",
"idempotency_key": "summer-drop-1"
}'
Cancel a cued post
Cancels every channel that has not gone out yet. Anything already published is history and stays as it is; if every channel is already publishing, this answers 422.
curl -X DELETE https://postqueuehd.com/api/v1/posts/42 \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
The media you have uploaded
Everything this team has uploaded, newest first, cursor-paginated. Transcoded variants are left out: they are built per platform and are not something you refer to. Use this to reuse a file you already sent rather than uploading it twice.
| Field | Type | Required | Notes |
|---|---|---|---|
| per_page | integer | no | Up to 100. Defaults to 25. |
curl https://postqueuehd.com/api/v1/media \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
Start an upload
Reserves a media row and answers with somewhere to PUT the file. The bytes go to the URL that comes back, not to this endpoint, so a large video is never held in a JSON request. Your plan limits are checked here, before you send anything — a file over the limit is refused now rather than after the upload finishes. Send a sha256 `checksum` and a file already uploaded answers 200 with `already_uploaded: true` and no upload target, because there is nothing left to send.
| Field | Type | Required | Notes |
|---|---|---|---|
| filename | string | yes | The original name. Its extension decides the stored one. |
| mime_type | string | yes | Anything starting image/ is an image; everything else is treated as video. |
| size_bytes | integer | yes | Checked against the plan's video size and storage allowance before you upload. |
| checksum | string | no | sha256 of the file, 64 hex characters. A match reuses the existing media instead of uploading again. |
# 1. reserve the row and read the upload target
curl -X POST https://postqueuehd.com/api/v1/media \
-H "Authorization: Bearer $POSTQUEUE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"filename": "summer.mp4",
"mime_type": "video/mp4",
"size_bytes": 8412345
}'
# 2. send the bytes where it told you to
curl -X PUT "$UPLOAD_URL" \
-H "Content-Type: video/mp4" \
--data-binary @summer.mp4
Finish an upload
Confirms the bytes arrived and starts the probe that reads the dimensions, duration and codecs. Answers 422 if nothing was uploaded. The probe runs in the background, so this does not mean the file is usable yet — poll `GET /media/{id}` until the status is `ready`.
curl -X POST https://postqueuehd.com/api/v1/media/91/complete \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
One piece of media
The status, and what the probe found. Status walks `uploaded` → `probing` → `ready`, or `failed` with the reason in `error`. Only `ready` media is worth scheduling: a failed file will not publish, and the `error` says why in words you can pass on to whoever supplied it.
curl https://postqueuehd.com/api/v1/media/91 \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
Delete media
Deletes the file and everything transcoded from it, freeing the storage against your plan. Media still attached to a post that has not gone out answers 422 — cancel the post first. Media whose posts have all published can go; it would be deleted by the retention window anyway.
curl -X DELETE https://postqueuehd.com/api/v1/media/91 \ -H "Authorization: Bearer $POSTQUEUE_TOKEN"
For AI agents
Point your agent at one of these instead of at this page — both are plain text and read in a single fetch.
This works with Claude, Gemini, ChatGPT or anything else that can fetch a URL — there is nothing to install.
Read https://postqueuehd.com/docs/api.md and schedule a post for tomorrow at 18:30 on every connected channel.