Dry-run validation — the same response, nothing stored
Check before you commit: pass an inline draft (`content` + `channels`), or a stored post's `id` to re-check exactly what is saved (media readiness included). Returns the standard post response with `ready`, per-channel `errors[]`, and `warnings[]`; for inline drafts `id` is null.
/posts/validateCheck before you commit: pass an inline draft (content + channels), or a stored post's id to re-check exactly what is saved (media readiness included). Returns the standard post response with ready, per-channel errors[], and warnings[]; for inline drafts id is null.
Authorization
bearerAuth In: header
Query Parameters
Organization slug (OAuth actors with several orgs); API keys imply theirs.
Request Body
application/json
TypeScript Definitions
Use the request body type in TypeScript.
Response Body
application/json
application/json
application/json
curl -X POST "https://example.com/posts/validate" \ -H "Content-Type: application/json" \ -d '{ "content": "string", "channels": [ "string" ], "per_channel": {}, "media": [ "string" ], "id": "string" }'{ "id": "string", "status": "draft", "scheduled_at": "string", "ready": true, "content": { "markdown": "string", "text": "string" }, "channels": [ { "channel_id": "string", "provider": "string", "name": "string", "format": "post", "ready": true, "source": "adapted", "content": { "markdown": "string", "text": "string", "length": 0, "limit": 0 }, "errors": [ { "code": "string", "field": "content", "message": "string", "fixes": [ { "kind": "trim_to_fold", "label": "string", "max_length": 0 } ] } ], "warnings": [ { "code": "string", "message": "string", "detail": { "property1": null, "property2": null } } ], "options": { "property1": null, "property2": null }, "ink_estimate": 0, "status": "draft", "external_post_id": "string", "url": "string", "error": "string", "published_at": "string" } ], "media": [ { "id": "string", "ready": true, "failed": true, "alt_text": "string", "source_url": "string" } ], "labels": [ { "id": "string", "name": "string" } ], "campaign": "string", "approval": { "required": true, "state": "not_requested" }, "fixes_applied": [ { "channel_id": "string", "provider": "string", "kind": "string" } ], "ink_estimate": 0, "created_at": "string", "updated_at": "string", "published_at": "string"}{ "error": { "code": "string", "message": "string", "reason": "string", "index": 0, "request_id": "string" }}{ "error": { "code": "string", "message": "string", "reason": "string", "index": 0, "request_id": "string" }}Publish an existing draft now POST
Its own verb because it is irreversible and carries its own idempotency key (`Idempotency-Key` header). Fans out to every channel immediately; the response's channel entries carry the per-destination results as the worker fills them in — poll `GET /posts/{id}` for the outcome. A post that is not `ready` is refused with the post itself under `error.post`. Guard against publishing someone else's concurrent edit with `expected_updated_at` (or the `If-Match` header holding the `ETag` your read returned) — a post that moved since is refused 409.
Reserve presigned upload URLs for 1–10 files (all-or-nothing) POST
Next Page