Posty API reference
Programmatic access to Posty workspaces: posts, approvals, comments, channels, media, campaigns, client shares, questionnaires, analytics, link in bio, inbox, Today and members. Authenticate with an API key or a Better Auth OAuth access token with mcp:tools scope. OAuth requests require X-Workspace-Id, except GET /v1/workspaces.
- Base URL
- https://api.posty.social
- Format
- JSON over HTTPS
- OpenAPI document
- openapi.json
curl "https://api.posty.social/v1/workspaces" \
-H "Authorization: Bearer $POSTY_API_KEY"Authentication
Send an API key as a bearer token: Authorization: Bearer pk_live_.... Team owners and admins create keys on the API keys page in Posty. A key works while its workspace is on a plan that includes API access.
A key is scoped to one workspace or to its whole team. A team key must name the workspace on every request, with the workspaceId query parameter or the X-Workspace-Id header. GET /v1/workspaces lists the workspaces a key can reach.
Each key keeps the scopes it was created with. A request outside those scopes answers 403 with the code missing_scope. AI clients connect through OAuth instead of a key; see the MCP server guide.
curl "https://api.posty.social/v1/posts?workspaceId=$WORKSPACE_ID" \
-H "Authorization: Bearer $POSTY_API_KEY"Errors
Failed requests answer with a 4xx or 5xx status and an error object. Branch on type for the broad class and on code for the exact cause. Quote requestId when you contact support.
| Type | Status | Meaning |
|---|---|---|
| authentication_error | 401 | The key is missing, invalid, expired or revoked. |
| permission_error | 402, 403 | The key lacks a scope, the plan does not include the feature, or a limit is reached. |
| invalid_request_error | 400 | A parameter or body field failed validation. |
| not_found_error | 404 | The resource does not exist in the selected workspace. |
| conflict_error | 409 | The resource is in a state that does not allow the change, or an idempotent request is still running. |
| rate_limit_error | 429 | Too many requests. Wait for the Retry-After seconds. |
| api_error | 500 | Something failed on our side. Retry POST requests with the same Idempotency-Key. |
Error object
errorobjectrequiredChild attributes
typestringrequiredOne of
authentication_errorpermission_errorinvalid_request_errornot_found_errorconflict_errorrate_limit_errorapi_errorcodestringrequiredOne of
authentication_requiredinvalid_api_keyapi_key_expiredapi_key_revokedapi_key_orphanedmissing_scopevalidation_failedinvalid_scheduleinvalid_channelinvalid_mediaduplicate_channel_contentstorage_limit_exceededpost_limit_exceededworkspace_inactiveworkspace_requiredworkspace_not_foundworkspace_mismatchplan_not_eligiblemedia_not_uploadedpost_not_editablepost_not_foundchannel_not_foundmedia_not_foundcomment_not_foundinvalid_transitionapproval_requiredchannel_inactivemedia_not_readyresource_not_foundlimit_exceededfeature_not_availablecampaign_not_foundpersona_not_foundobjective_not_foundquestionnaire_not_foundresponse_not_foundlink_not_foundtemplate_not_foundblock_not_foundconversation_not_foundpost_thread_not_foundinvitation_not_foundmember_not_foundlast_workspace_admintoday_item_not_founduser_session_requiredfolder_not_foundreview_request_not_foundcampaigns_disabledcampaign_archivedcampaign_status_conflictinvalid_campaign_windowpersona_not_in_campaignpost_not_in_campaignshare_not_foundcampaign_limit_exceededquestionnaire_archivedquestionnaire_not_activequestionnaire_limit_exceededresponse_not_submittedmember_limit_exceededchannel_limit_exceededhandle_unavailableoperating_model_not_agencydelegated_connect_not_availableorganization_not_foundidempotency_key_in_useidempotency_in_progressrate_limit_exceededinternal_errormessagestringrequiredparamstringdocUrlstringrequestIdstringrequired
{
"error": {
"type": "invalid_request_error",
"code": "validation_failed",
"message": "content must contain at least 1 item",
"param": "content",
"requestId": "req_8f2c1e0b"
}
}Pagination
List endpoints return a list object. Ask for up to 100 items with limit (20 by default). When has_more is true, pass next_cursor as starting_after to fetch the next page.
{
"object": "list",
"data": [
{
"id": "post_123"
}
],
"has_more": true,
"next_cursor": "eyJpZCI6InBvc3RfMTIzIn0"
}Idempotency
Add an Idempotency-Key header (up to 255 characters) to any POST to make retries safe. A successful response is stored for 24 hours, and a retry with the same key and body gets it back with Idempotent-Replayed: true instead of running again.
The same key with a different body answers 409 idempotency_key_in_use. A retry that arrives while the first request is still running answers 409 idempotency_in_progress; try again shortly. Failed requests are not stored, so they can be retried with the same key.
curl -X POST "https://api.posty.social/v1/posts" \
-H "Authorization: Bearer $POSTY_API_KEY" \
-H "Idempotency-Key: 6f1c9a52-launch-post" \
-H "Content-Type: application/json" \
-d '{"content":[{"channelId":"$CHANNEL_ID","body":"Hello"}]}'Rate limits
Each key can make 600 GET requests and 120 other requests per minute. Unauthenticated traffic is limited to 60 requests per minute per IP address.
Responses carry X-RateLimit-Limit, X-RateLimit-Remaining and X-RateLimit-Reset (Unix seconds). Over the limit, requests answer 429 with a Retry-After header in seconds.
Resources
- Workspaces1 endpoint
- Channels2 endpoints
- Posts22 endpoints
- Comments3 endpoints
- Media16 endpoints
- Campaigns18 endpoints
- Client shares3 endpoints
- Questionnaires17 endpoints
- Analytics7 endpoints
- Link in bio9 endpoints
- Inbox6 endpoints
- Today5 endpoints
- Members5 endpoints
- Workspace settings2 endpoints
- Notification preferences4 endpoints