Let AI agents draft Instagram and Threads posts via /api/v1/social and aveiro_social_* MCP tools. Requires social:write — approval stays in the dashboard.
Grant social:write on an API token or MCP OAuth connection. Agents list accounts, create and revise drafts, generate media, and read rejection feedback. Approve, reject, and publish remain dashboard-only — there is no scope that grants them.
What agents can and cannot do
Action
Agent (API / MCP)
Human (dashboard)
List connected accounts
Yes
Yes
Create and revise drafts
Yes — draft, pending_approval, rejected only
Yes
Generate or register media
Yes
Yes
Read feedback timeline
Yes
Yes
Read post engagement
Yes
Yes
Approve, reject, post now
No — not exposed
Yes
Publish autonomously
No — structural guardrail
No without approval
This split is intentional. Social posts go to public profiles — Aveiro keeps approval in session-authenticated UI actions only.
Token setup
Enable Social publishing under Organization → Features
Open Organization → API tokens → Create token
Add the social:write scope (requires Audience manage capability)
Copy the av_live_… secret — shown once
For MCP in Cursor or Claude, connect via the hosted MCP server at https://www.aveiro.app/api/mcp/mcp. OAuth grants include social:write when you authorize social drafting tools.Default content tokens (sites:read, content:read, content:write) do not include social access — add social:write explicitly.See API tokens for the full scope list.
REST API
All routes live under /api/v1/social on your platform host. Full reference: Social API overview.
Method
Route
Purpose
GET
/api/v1/social/accounts
Connected Instagram/Threads accounts and IDs for targets
GET
/api/v1/social/posts
List posts — filter by status (e.g. rejected, pending_approval)
POST
/api/v1/social/posts
Create a draft (source=mcp); optional submitForReview
GET
/api/v1/social/posts/{postId}
One post with event timeline and engagement snapshots
GET
/api/v1/social/performance
Published posts with first (~1h) and latest engagement snapshots
PATCH
/api/v1/social/posts/{postId}
Revise draft, pending, or rejected post
GET
/api/v1/social/media
Social media library (registered and generated assets)
GET
/api/v1/social/org-media
Browse org media storage (dashboard uploads — not yet in the social library)
POST
/api/v1/social/media
Register a public URL into the social library
POST
/api/v1/social/media/upload
Get a direct-upload target for a local image or video file
POST
/api/v1/social/media/generate
AI image generation — up to 4 aspectRatios per call (plan + credits per ratio)
GET
/api/v1/social/video
List website-render presets and recent renders
POST
/api/v1/social/video
Film a public URL into a 3D mockup video (async)
GET
/api/v1/social/video/{renderId}
Poll one render until done or error
Send Authorization: Bearer av_live_… on every request.
Typical agent loop
GET /api/v1/social/performance (optional) — see which topics, platforms, and timing perform
GET /api/v1/social/accounts — pick target account IDs
GET /api/v1/social/org-media (optional) — find an existing dashboard upload, then POST /api/v1/social/media to register its URL
POST /api/v1/social/media/generate or POST /api/v1/social/media — attach media
POST /api/v1/social/posts with targets, content, platformOverrides, proposedScheduleAt, and a note explaining the draft
Human approves in Dashboard → Social
If rejected, GET /api/v1/social/posts/{id} — read events, then PATCH with fixes and submitForReview: true
Caption limits enforced at validation: Instagram 2,200, Threads 500, X 280 characters.
When registering videos with POST /api/v1/social/media, pass durationMs when you know the clip length — dispatch sends the same midpoint cover frame the library tile shows on platforms that accept thumbOffsetMs. Assets from POST /api/v1/social/media/generate carry origin: generated and trigger Instagram's AI self-disclosure; Frametic mockups from POST /api/v1/social/video register as origin: rendered and do not.
Instagram stories
Instagram targets accept optional postType: "story" to publish to Stories instead of the feed. Stories publish without caption or first comment and need one media item — 9:16 assets work best. Caption validation skips story-only targets.
Example target:
One draft can mix surfaces — e.g. LinkedIn feed post, Instagram story, and X post in the same approval queue.
Multi-aspect generation and per-platform crops
POST /api/v1/social/media/generate accepts aspectRatios — an array of up to four supported ratios (1:1, 4:5, 5:4, 3:4, 4:3, 2:3, 3:2, 9:16, 16:9). Default is ["16:9"]. Each ratio is generated independently with the same prompt and billed as one AI image generation.
The response is { assets, failures } — partial success is normal when one ratio fails quota or provider limits.
aveiro_social_generate_media accepts the same aspect_ratios parameter (max four).
Assign each returned asset to a platform. An assignment's platform field marks an asset as that platform's crop: assets attached to a platform are that platform's own set and replace the generic one for it.
Assets left generic (platform: null) are the post's carousel, and every one of them publishes, in sortOrder. Attaching three ratios of the same picture without a platform produces a three-slide carousel on every target — not one auto-picked crop.
This replaced auto-pick-by-aspect-ratio, which could not tell one visual in three crops apart from three different pictures and silently truncated the second case.
Org media storage — files uploaded through any dashboard dialog (brand assets, screenshots, AI images saved to the org library). Browse with GET /api/v1/social/org-media.
Social media library — assets registered or generated for social posts (GET /api/v1/social/media). Only these IDs attach to drafts.
To reuse an org upload on a social post, register its public URL with POST /api/v1/social/media (or aveiro_social_register_media). Registration is idempotent per URL. Use mediaType: "video" for Reels — the AI generator produces images only.
Direct uploads from agents
When the file only exists on the agent's side — an image generated on the caller's own AI plan, a video rendered locally — POST /api/v1/social/media/upload (or aveiro_social_prepare_upload) returns a short-lived upload target. The agent PUTs the raw bytes to it over plain HTTPS, then registers the returned publicUrl as usual. Images (JPEG/PNG/WebP/GIF, max 10MB) land in org image storage; videos (MP4/WebM/MOV, max 200MB) land directly on the video CDN, so no host: true is needed on the register call.
This flow needs a client that can make HTTP requests (shell or code execution, e.g. Claude Code or Cursor). Chat-only MCP clients can't push local bytes — they keep using register-by-URL. See the Social media API for the exact request/response shapes.
Website mockup videos
Film a publicly reachable web page in a 3D device mockup and register the finished video in the social library. Unlike every other media route, renders are asynchronous — POST returns pending jobs and you poll until done.
GET /api/v1/social/video — list presets and recent renders
POST /api/v1/social/video — start a render (pass estimateOnly: true first to quote credits)
GET /api/v1/social/video/{renderId} — poll until the library asset is ready
Credits are charged at enqueue and refunded on failure. MCP: aveiro_video_list_presets, aveiro_video_create_mockup, aveiro_video_get.
The Aveiro MCP server exposes thin wrappers around the same routes:
Tool
REST equivalent
aveiro_social_list_accounts
GET /api/v1/social/accounts
aveiro_social_list_posts
GET /api/v1/social/posts
aveiro_social_get_post
GET /api/v1/social/posts/{id}
aveiro_social_get_performance
GET /api/v1/social/performance
aveiro_social_create_draft
POST /api/v1/social/posts
aveiro_social_update_draft
PATCH /api/v1/social/posts/{id}
aveiro_social_list_media
GET /api/v1/social/media
aveiro_social_list_org_media
GET /api/v1/social/org-media
aveiro_social_register_media
POST /api/v1/social/media
aveiro_social_prepare_upload
POST /api/v1/social/media/upload
aveiro_social_generate_media
POST /api/v1/social/media/generate
aveiro_video_list_presets
GET /api/v1/social/video
aveiro_video_create_mockup
POST /api/v1/social/video
aveiro_video_get
GET /api/v1/social/video/{renderId}
Tools are available on the hosted MCP server and the stdio server in mcp/aveiro. Both expose the same aveiro_social_create_draft target schema — all six platforms (Instagram, Threads, X, LinkedIn, Reddit, and Orbit), plus optional spaceSlug on Orbit targets and postType: "story" on Instagram. See the Aveiro MCP README in the repo for local setup.
Proposed vs confirmed schedule
Agents set proposedScheduleAt on create or update. The dashboard row shows this as a proposed time. It never triggers publish.
When a human clicks Approve, the datetime picker sets the confirmedscheduled_at. Only approved, scheduled posts reach Chirio via the dispatcher.
A proposal is not validated when the agent writes it, but it is when a human approves: approval requires a confirmed time in the future. A proposal that has since gone stale is refused at that point, and the reviewer picks a new time — it never becomes an instant publish.