{identity} accepts an idn_… id or the identity’s name.
Activate
POST /v1/identities/{identity}/social/activate — scope billing:write
Creates the identity’s social workspace. The operation is idempotent: a later call returns the
existing workspace.
Read status
GET /v1/identities/{identity}/social — scope agents:read
Returns activated and the provider’s current connected accounts. Before activation it returns
activated: false and an empty account list.
Open the account portal
POST /v1/identities/{identity}/social/portal — scope billing:write
redirect_url defaults to the persona’s own studio screen on deployments
that configure one. The response contains a hosted url the account owner visits to authorize
one or more networks. The URL is short-lived provider state; do not store it as an account.
List accounts
GET /v1/identities/{identity}/social/accounts — scope agents:read
Returns a paginated list. This is a live reconciliation read, not a mirror of an
OAuth token or cached account table.
Upload media
POST /v1/identities/{identity}/social/uploads — scope sessions:write
Pass { "url": "https://…" }. The provider fetches the public image, video, or document and
returns a social_upload. Vetta stores neither the source bytes nor a second upload record.
Create or schedule a post
POST /v1/identities/{identity}/social/posts — scope sessions:write
scheduled_at to queue the post immediately. title is optional and defaults to the first 100
characters. media_urls accepts up to ten public URLs, and file_ids up to ten stored fil_
ids — each resolves to a short-lived signed URL fetched once, so a stored file posts
without ever needing a public address.
Which targets are legal depends on whether the post carries media. bluesky, facebook,
linkedin, mastodon, threads, and x take a post either way. instagram, tiktok, and
youtube publish media, not text, so naming one requires at least one media_urls or file_ids
entry — a text-only post to them is refused validation_failed on platforms, and the message
says which platform and what is missing. pinterest and reddit are connectable but not yet
postable: each needs a per-post destination (a board, a subreddit) this body has no field for, and
a post naming one is refused with that reason rather than accepted and ignored.
visibility is optional and says who may see the published post: public, unlisted, or
private. Only mastodon and youtube accept it — they are the two networks whose contract
carries all three — and naming any other platform alongside a visibility is refused
validation_failed on visibility, with the network named. Omit the field and nothing is sent
upstream: the post publishes at the connected account’s own default, which on a video channel is
normally public. Vetta chooses no default of its own, so no existing integration changes behaviour.
social component.
Read a post
GET /v1/identities/{identity}/social/posts/{post} — scope agents:read
The response reports scheduled, processing, posted, failed, or deleted state. A post id
owned by another identity returns not_found.
Analytics, comments, and deletion
GET /v1/identities/{identity}/social/accounts/{account}/analyticsGET /v1/identities/{identity}/social/posts/{post}/analyticsGET /v1/identities/{identity}/social/posts/{post}/commentsDELETE /v1/identities/{identity}/social/posts/{post}
data; comments use Vetta’s ordinary
pagination envelope.