Examples
Client approval flow
Send drafts for review, list pending posts, and approve or reject with a comment.
Scopes: posts:read, posts:write (plus posts:publish if creation also schedules).
Agencies typically split this across two credentials: the content tool creates drafts and requests approval; the review tool lists pending posts and records decisions. Both keys belong to the same workspace.
1. Create a draft and request approval
# Create the draft (schedule can also be set now — it's kept through approval)
curl -X POST https://api.nimply.io/v1/posts \
-H "Authorization: Bearer $NIMPLY_API_KEY" \
-H "Content-Type: application/json" \
-H "Idempotency-Key: client-acme-aug-01" \
-d '{
"channelIds": ["123e4567-e89b-12d3-a456-426614174000"],
"content": "Acme summer sale starts Monday ☀️",
"schedule": "2026-08-01T09:00:00.000Z"
}'
# Send it for review
curl -X POST https://api.nimply.io/v1/posts/7a245d46-…/request-approval \
-H "Authorization: Bearer $NIMPLY_API_KEY"The post moves to PENDING_APPROVAL and the post.approval_requested
webhook fires — a good trigger for notifying the reviewer.
2. List posts awaiting review
curl "https://api.nimply.io/v1/posts?status=PENDING_APPROVAL" \
-H "Authorization: Bearer $NIMPLY_API_KEY"{
"data": [
{
"id": "7a245d46-…",
"channelId": "123e4567-e89b-12d3-a456-426614174000",
"content": "Acme summer sale starts Monday ☀️",
"status": "PENDING_APPROVAL",
"scheduledAt": "2026-08-01T09:00:00.000Z"
}
],
"nextCursor": null
}The list is cursor-paginated — keep passing ?cursor={nextCursor} until nextCursor is null.
3. Approve — or reject with feedback
# Approve
curl -X POST https://api.nimply.io/v1/posts/7a245d46-…/approve \
-H "Authorization: Bearer $NIMPLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "comment": "Looks great, ship it" }'# ...or reject
curl -X POST https://api.nimply.io/v1/posts/7a245d46-…/reject \
-H "Authorization: Bearer $NIMPLY_API_KEY" \
-H "Content-Type: application/json" \
-d '{ "comment": "Swap the hero image for the blue variant, please" }'- Approve → the post returns to
SCHEDULEDif it has a future publish time, otherwiseDRAFT. Firespost.approved. - Reject → the post returns to
DRAFT. Firespost.rejected.
The decision and comment are recorded either way (comment is optional).
Gotchas
- The state machine is strict:
request-approvalonly works on aDRAFT(409otherwise), andapprove/rejectonly work onPENDING_APPROVAL(409otherwise). Handle409as "someone else already acted on it". - Set the publish time before requesting approval — an approved post with a future
scheduledAtgoes straight back toSCHEDULEDand needs no second touch. - A rejected post lands back in
DRAFT: fix it withPATCH /v1/posts/{id}, then request approval again. - To drive reviewer notifications, subscribe to
post.approval_requested,post.approved, andpost.rejectedwebhook events.