Reference · problem details
Errors
Postdom returns RFC-style problem details with one stable machine-readable code. Preserve the code and detail before deciding whether to correct, retry, or hand off.
application/problem+json
Problem envelope
Every problem response contains at least type, title, status, detail, and code. Some carry more — a refused publish adds reason, next_step, resolution, retryable and documentation_url, described under Publishing refusals below. Read the five as guaranteed and ignore fields you do not recognise rather than rejecting the response. The example detail is synthetic; runtime detail names the current failure.
Two 422s are raised because a selected destination cannot take what you sent, and both carry destinations, an array of { platform, fact }: media_invalid for the video and caption_invalid for the text. The field is the same shape in both, so branch on it rather than parsing detail, and handle the two codes the same way — the question is which destination to drop. The codes stay distinct because the fix differs: re-encoding the video cannot shorten a caption. A media_invalid without destinations means the asset failed reachability, immutability, type, host, or size checks.
{
"type": "https://postdom.com/problems/media_invalid",
"title": "Video source unavailable",
"status": 422,
"detail": "Video source could not be reached",
"code": "media_invalid"
}Agent decisions
Handling rules
correctFix 400 or 422 input evidence before making a deliberate new call.
stopReturn 401, 403, 404, and 423 failures to a human when the caller cannot restore authority or context.
readOn publish_in_progress, read the existing post instead of duplicating the write.
retryUse bounded backoff for 503 failures. Never convert a retry budget into an unbounded loop.
Common agent-facing failures
Error codes
These codes are emitted by current setup, connection, brief, plan, publish, and read routes. Dashboard-only review errors remain outside the agent reference.
invalid_request400
The request failed schema or runtime input validation.
Correct the reported field or value before retrying.
idempotency_key_required400
A raw API write omitted its Idempotency-Key header.
Send one stable key for the logical write. Configured adapters may generate this key.
unauthorized401
The agent credential is missing or invalid.
Stop and ask a human to restore configured access. Never request the raw credential in chat.
insufficient_scope403
The workspace key lacks the read or write scope required by this operation.
Stop and ask an owner or admin to create an appropriately scoped key. Never request the raw key in chat.
connect_disabled403
Destination connections are currently unavailable for this workspace.
Return the connection gate to a human. Do not try to unlock or route around the workspace boundary.
policy_blocked409
Postdom refused to publish. The body carries a stable reason, what to do next, and a link to that reason's entry.
Read reason, not the sentence. Retry only when retryable is true; otherwise resolve what next_step names.
target_not_connected403
The destination is not connected to the current workspace.
Return the destination ID and hand connection work to a human.
plan_target_not_l2403
A proposed plan target lacks the required trust level.
Return the target and let a human change trust or revise the plan.
plan_not_found404
No plan with that ID exists in the workspace.
Stop plan-backed work and return the exact plan ID to a human.
post_not_found404
No post with that ID exists in the workspace.
Stop polling and return the exact post ID to a human.
media_not_found404
No upload with that media handle exists in the workspace.
Stop polling and return the exact media handle. Never guess or substitute another workspace's handle.
brief_not_found404
The workspace does not have a saved Workspace Brief.
Ask a human to add the brief. Do not invent brand, voice, timing, or never-do guidance.
idempotency_conflict409
The key was already used with a different payload.
Do not overwrite the original operation. Use a new key only for a deliberate new request.
publish_in_progress409
The original idempotent publish is still being processed.
Read the existing post instead of creating another publish request.
provider_not_provisioned409
The workspace has not created its isolated social-provider profile yet.
Read the workspace connection gate, then use connect_account only when that gate is unlocked.
supplier_spend_guard409
Postdom stopped a connection before it could exceed the supplier-spend review threshold.
Return the exact detail to a human. Do not retry around the cost guard.
account_cap_reached409
The workspace connection attempt reached the account cap for its current plan.
Return the exact detail to a human. Do not replace or disconnect another account.
invalid_media_handle400
The supplied media handle is malformed.
Use the opaque handle returned by upload_media without modifying it.
media_upload_rate_limited429
The workspace reached its rolling media-upload contract cap.
Wait for the reported window, then retry once. Do not rotate credentials or workspaces to bypass the cap.
rate_limited429
The API credential or workspace reached its shared agent-request limit.
Honor Retry-After and retry with bounded backoff. Do not rotate keys or workspaces to bypass the cap.
media_invalid422
The video source failed reachability, immutability, type, host, or size checks, or a selected destination cannot receive it.
If the response carries destinations, each entry names a destination and the fact it failed, read from the video rather than guessed: publish without those destinations, or re-encode to a format and size all of them accept. Otherwise obtain an accepted media URL before making a new request.
caption_invalid422
A selected destination will not accept a caption this long, measured against the limit that destination publishes.
Read `destinations`: each entry names a destination and the caption fact it exceeds. Shorten the caption to that destination's limit, or publish to the destinations that accept it in a separate request. Postdom refuses only where the caption limit is marked `enforced_by_postdom` - some destinations publish a limit that is deliberately not gated here, each with a stated reason, and those are reported on the approval card rather than refused.
brief_version_not_found422
The submitted Workspace Brief version does not exist in this workspace.
Call get_brief again and deliberately resubmit the plan with the returned current version.
agent_paused423
The workspace-wide agent pause blocks write activity.
Stop writes and hand control to a human. Only a human can resume activity.
provider_down503
The provider or durable publish worker is unavailable.
Retry with bounded backoff. Return the code, detail, and any already-known resource ID when the budget ends.
media_upload_unavailable503
Postdom could not issue a private, scoped upload contract.
Do not upload elsewhere silently. Retry with bounded backoff, then return the error to a human.
media_unavailable503
Private media status or delivery is not configured or available.
Preserve the media handle, stop publishing it, and return the exact error to a human.
persistence_unavailable503
The required durable store is unavailable or not configured.
Do not assume the write was recorded. Retry with bounded backoff, then hand off.
Why a publish was refused
Publishing refusals
A refused publish returns 409 with code policy_blocked. The body carries a stable reason from the list below, a next_step, and a documentation_url pointing at that reason's entry here. Read reason rather than matching on the sentence — the wording may improve, the code will not.
Every reason Postdom can refuse with is listed. The list is generated from the same definition the API refuses with, so a reason cannot exist without an entry on this page.
This list grows. New reasons are added as Postdom learns to tell states apart that it previously reported under a nearer-but-wrong reason. Treat an unfamiliar reason as “refused, explanation unavailable” and read next_step, rather than writing an exhaustive switch that treats a future member as an error. Adding a member is an additive change:policy_blocked stays the code you branch on, existing reasons keep their meaning, and a new state gets a new member rather than being folded into an old one.
publishing_disabled
Publishing is switched off, so Postdom accepted nothing for delivery.
What to do: Nothing in the request needs changing. Contact Postdom to find out when publishing is available for this workspace.
policy_unavailable
Postdom could not read the publishing policy for this workspace, so it refused rather than guessed.
What to do: Try again shortly. If it persists, contact Postdom — this is not something the request can fix.
policy_invalid
The stored publishing policy did not pass validation, so Postdom refused rather than acting on it.
What to do: Contact Postdom. Retrying will not help until the policy is corrected.
target_mismatch
The destinations on the request were missing, repeated, or not usable as written.
What to do: Send one entry per destination account, each with a non-empty account ID and no duplicates, then submit again.
agents_paused
Publishing is paused — either for the whole workspace or for this account.
What to do: Resume the workspace or the account from the Accounts page, then submit again.
authorization_changed
What was about to be published no longer matches what a human approved — the caption, the media or the request identity changed after approval.
What to do: Submit the post again and have it approved in its current form. Postdom will not publish an unapproved version.
prior_submission_uncertain
An earlier attempt may already have reached the destination, and Postdom cannot confirm that it did not.
What to do: Check the destination before resubmitting. Postdom stops here deliberately rather than risk publishing the same video twice.
execution_interrupted
The run stopped before Postdom could confirm an outcome, so it was recorded as stopped rather than published.
What to do: Check the destination, then submit again if the post did not appear.
media_invalid
The video could not be validated when publishing began.
What to do: Check that the media is still reachable and matches what was approved, then submit again.
account_disconnected
This account is no longer connected to Postdom, so nothing can be published to it.
What to do: Reconnect the account from the Accounts page. Its policy and any scheduled posts are kept.
trust_level_too_low
This account's autonomy level does not allow an agent to publish to it.
What to do: Raise the account's autonomy level on the Policy page, or have a human approve each post for it.
Safe recovery
Retry boundary
Preserve the operation
Reuse an idempotency key only for the same logical write. When a bounded retry window ends, return the code, detail, and any already-known resource ID.