Drafts and approvals API
Drafts hold a post that is not live. Approvals add a review step: a draft moves to pending_approval, and someone with approval rights either publishes it or sends it back. This is the safe path for AI agents, because a key with require-approval turned on can create and submit posts but cannot publish them.
All paths are under /api/content. Authentication and workspace selection work as described in the REST API overview.
What is the draft and approval lifecycle?
saveDraft: true --> draft --submit-for-approval--> pending_approval
^ |
|------------- reject --------------|
|
approve --> publishes (or schedules)| Status | Meaning |
|---|---|
draft | Saved, not live. Editable. |
pending_approval | Waiting for a reviewer. |
pending | Scheduled for a future time, or just approved and dispatching. |
How do I save a draft with the API?
Add "saveDraft": true to any create request. Media is still uploaded, and no job is queued.
curl -X POST https://api.socifyr.com/api/content/text \
-H "Authorization: Bearer sk_..." \
-H "Content-Type: application/json" \
-d '{
"connections": ["linkedin-mybrand"],
"text": "Draft: Q4 roadmap announcement",
"saveDraft": true
}'{ "success": true, "data": { "success": true, "draftId": "6a05032a84584482ace13d52" } }Saving a draft does not count against the monthly upload limit and does not use a key's daily post limit. Body parameters are listed in Content API. Edit a draft with PATCH /content/:id, and publish it with POST /content/:id/publish. See the drafts guide.
How do I submit a draft for approval?
POST /content/:id/submit-for-approval, no body. Needs post.create. A guarded key may call it, but only for drafts that key created.
curl -X POST https://api.socifyr.com/api/content/6a05032a84584482ace13d52/submit-for-approval \
-H "Authorization: Bearer sk_..."{
"success": true,
"data": { "success": true, "id": "6a05032a84584482ace13d52", "status": "pending_approval" }
}| Status | Cause | Fix |
|---|---|---|
| 404 | Content not found | Check the ID and workspace. |
| 409 | Only a draft can be submitted for approval | The post is not in draft. |
| 403 | A guardrail limit was reached when the key submitted | See guardrails. |
When a key with a daily post limit or X spend cap submits a draft, that key's quota is reserved at submit time.
How do I approve a post?
POST /content/:id/approve, no body. Needs post.approve, which Editors, Admins and Owners have. It flips the post to draft and publishes it through the normal path, so the response is the same as publishing a draft (requestId, usage, message, scheduledAt, totalChannels). A post with a future scheduledAt is scheduled instead.
curl -X POST https://api.socifyr.com/api/content/6a05032a84584482ace13d52/approve \
-H "Authorization: Bearer sk_..."{
"success": true,
"data": {
"success": true,
"requestId": "97005ec5-6361-4953-8a69-ce7292ad9f11",
"usage": { "count": 8, "limit": 30, "remaining": 22 },
"message": "Upload processing started",
"scheduledAt": null,
"totalChannels": 1
}
}| Status | Cause |
|---|---|
| 404 | Content not found |
| 409 | Content is not pending approval |
| 403 | This API key requires approval and cannot approve posts — ... when a require-approval key calls it |
| 403 | Your role does not have the 'post.approve' permission |
How do I reject a post?
POST /content/:id/reject, no body. Needs post.approve. The post goes back to draft so the author can revise and resubmit.
{ "success": true, "data": { "success": true, "id": "6a05032a84584482ace13d52", "status": "draft" } }Errors match approve: 404 Content not found, 409 Content is not pending approval.
Which routes can a require-approval key call?
A key with require-approval can create posts, but every post it creates (without saveDraft) lands in pending_approval and the create response says so. It is blocked from skipping review:
| Route | Require-approval key |
|---|---|
POST /content/* (create) | Allowed. Result is pending_approval. |
POST /content/:id/submit-for-approval | Allowed. |
PATCH /content/:id | Allowed, drafts only. |
POST /content/:id/publish | 403 ...cannot publish drafts directly... |
POST /content/:id/publish-now | 403 ...cannot publish immediately... |
POST /content/:id/approve | 403, and the route is not available to guarded keys. |
POST /content/:id/reject | 403, and the route is not available to guarded keys. |
How do I find posts waiting for approval?
GET /content/:id returns status: "pending_approval". The list endpoint's status filter does not accept pending_approval (it returns 400), so list posts without that filter and look for the status in each item.
Frequently asked questions
Can an agent approve its own post? No. A key with guardrails cannot call approve, and approve needs the post.approve permission from a member. Use a dashboard session or an unrestricted key.
Does rejecting delete the post? No. It returns to draft with its content intact.