permissions. Send permissions when you connect an account to ask for less: the person connecting sees a shorter consent screen where the platform allows it, and the account can do only what you selected.
Permissions are not API key scopes. A permission limits what a connected account can do on its platform and is written resource.action. A key scope limits what an API key can do in SocialAPI and is written resource:action. Connecting an account and changing its permissions cost no credits.
Endpoints
Connect with permissions
This request connects an Instagram account that can read and answer comments and nothing else:GET /v1/accounts returns the account in data with both lists (other fields omitted):
permissions is a list of the names in The permissions. Duplicates collapse, and the lists are always in the order of that table.
- Omitted. SocialAPI keeps the permissions of the brand’s existing account on that platform. A brand with none gets every permission. Reconnecting without
permissionsnever changes them. - An empty list. The request returns
400 validation.permissions_empty. - An unknown name. The request returns
400 validation.permission_unknown, anderror.meta.permissionholds the name. - A name the platform has no use for. The request is accepted. The name stays in
permissionsand never appears ineffective_permissions. For examplereviews.readon Instagram.
The permissions
Permissions per platform
An account can use a permission only on a platform that supports it. The other names are accepted and ignored.- Follows the selection. The consent screen asks for the platform scopes of the permissions you selected. A platform scope that serves more than one permission can make the screen show more than you selected: Instagram asks for comments and for messages as 1 scope each, covering reading and writing. Facebook asks for messages as 1 scope, and asks for
pages_read_user_contentfor bothcomments.readandcomments.write. Pinterest asks forboards:readandpins:readfor bothposts.readandposts.write. Threads asks for publishing and deleting as 1 pair of scopes shared byposts.writeandcomments.write. X asks fortweet.writeonce forposts.writeandcomments.write. The account stays limited to your selection: an Instagram account connected withcomments.readalone cannot reply to comments. - The same for every selection. The platform shows its fixed list of scopes. Google Business Profile asks for 3 identity scopes and 1 scope,
business.manage, that covers all of its permissions. YouTube asks for 1 scope that covers everything. TikTok (except a creator connection), WhatsApp, and Zalo ask for no scope that depends on your selection. The account is still limited to your selection, and an account connected withreviews.readalone cannot reply to reviews. - No selection step. Telegram and Bluesky connect without a consent screen, so SocialAPI alone enforces your selection.
What an account can do right now
Every account has two lists:effective_permissions is permissions limited to what the platform supports and what the person connecting granted. The person can decline part of the consent screen, and a platform can withdraw access later.
A call that needs a permission outside effective_permissions fails with 403 account.permission_missing, and error.meta.permission names it. The refusal comes before the call reaches the platform. A platform’s unsupported operation keeps its usual answer, 501 resource.not_supported, whatever the permissions. These calls answer differently:
- Publishing (
POST /v1/posts,POST /v1/posts/{pid}/publish,POST /v1/posts/{pid}/retry, and a scheduled post when it is delivered) reportsaccount.permission_missingon the target and returns no403. - Removing a published post from a platform.
DELETE /v1/posts/{pid}reports the target inresultswithoutcome: "failed"and leaves itpublished.POST /v1/posts/{pid}/unpublishreturns500 system.internal, and the target stayspublished. - Live post metrics (
GET /v1/posts/{pid}/metrics) reportresource.not_foundon the target. - Stored lists.
GET /v1/inbox/comments,GET /v1/inbox/conversations, andGET /v1/inbox/conversations/{id}/messagesreturn what SocialAPI stored and never returnaccount.permission_missing. - Review accounts.
GET /v1/inbox/reviewsdoes not checkreviews.read.
- A comment reply, a DM, a review reply, and a mention reply cost no credit, because the check comes before the charge.
- A post follows the post credit rules in Plans and usage.
- Every other call is free.
- Webhooks and Automations. Comments, mentions, messages, and reviews for a permission the account lacks are dropped: they do not reach your webhook endpoints, your Automations, or the inbox. With
messages.writealone, the account still receivesdm.status.readon Instagram,dm.status.deliveredanddm.status.readon Facebook, and everydm.status.*event on WhatsApp. It receives nodm.sentand nodm.status.senton Instagram or Facebook. - Posts. A post to an account without
posts.writefails on its target withaccount.permission_missing, whether you publish it now or schedule it. For a scheduled post, the failure appears when the delivery runs. - Analytics. The account adds no new points to its stored analytics history.
account.updated webhook with change set to permissions_reduced. Reconnect the account to ask for the permission again.
On X, when X refuses a call because the account’s access lacks a scope, the call returns 403 platform.twitter.insufficient_scope. error.meta.scope names the scope when it is known (media.write for a media upload). The account does not become token_expired. When the scope is named, the permissions that need it leave effective_permissions until you reconnect the account: posts.write for media.write. Other platforms return their own platform.<name>.* code for the same refusal and do not change effective_permissions.
Invite links
POST /v1/invites takes the same permissions field. The account the person connects gets exactly that list, and on a platform whose consent screen follows the selection the person is asked only for what those permissions need.
GET /v1/invites return permissions as you set it. null means you omitted it: when the link is used, SocialAPI applies the rule for an omitted permissions described in Connect with permissions.
Change an account’s permissions
PATCH /v1/accounts/{id} replaces an account’s permissions. permissions is required: send a list, or null to give the account every permission, including ones added later.
permissions and effective_permissions.
permissions field returns 400 validation.field_required. A value that is neither a list of strings nor null returns 400 validation.body_invalid. An empty list returns 400 validation.permissions_empty, and an unknown name returns 400 validation.permission_unknown. An ID that is not one of your accounts, or that a brand-restricted key cannot reach, returns 404 account.not_found.
Removing a permission deletes data
If the deletion fails, the call fails and the permissions stay unchanged. Connecting the account again with a narrower
permissions list deletes the same data.
A permission the person declines on the consent screen when reconnecting leaves effective_permissions, and SocialAPI sends account.updated. It also deletes the same data, except on the first reconnect of an account connected before account permissions existed.
Adding a permission
Adding a permission takes effect at once when the platform already granted it to the account. Otherwise the permission appears inpermissions but not in effective_permissions: reconnect the account so the person can grant it. Once a permission is in effective_permissions, the events it covers arrive again.
Automations
An Automation needs permissions on its account. Creating or updating it returns400 validation.permission_missing when its trigger or actions need a permission outside the account’s effective_permissions, and error.meta.permission names it.
An update is checked only when it changes
steps or sets status to active. An Automation is not paused when its account later loses a permission: its actions fail on the Firing with account.permission_missing.
Errors
403 account.permission_missing: the account does not have the permission the call needs.error.meta.permissionnames it. Add it withPATCH /v1/accounts/{id}, or reconnect the account when the platform has not granted it.400 validation.permission_unknown: a value inpermissionsis not a permission.error.meta.permissionnames it.400 validation.permissions_empty:permissionsis an empty list.400 validation.permission_missing: an Automation needs a permission the account does not have.error.meta.permissionnames it.403 platform.twitter.insufficient_scope: X refused the call because the account’s access lacks a scope.
Scopes
Invite endpoints need a full-access key. See Scoped API keys.
Events
account.updated with change: "permissions_reduced" fires when an account loses a permission you did not remove yourself. It does not fire when you remove a permission with PATCH /v1/accounts/{id}. The payload is in Webhook events.
Use from an AI agent
See MCP tools for every tool.
Related
- Connect accounts for the connect flow and the account fields
- Webhook events for the
account.updatedpayload - Automations for the permissions each trigger and action needs
- Scoped API keys for limiting what an API key can do
- Errors for every error code