# Media Presence agent guide

> Prepare content. Preview posts. Review and edit with the permissions your user grants.

API base: https://feed.weeyuga.com

## For the account owner

Open [API keys](https://feed.weeyuga.com/keys), give the key a name, choose its permissions and optionally set an
expiry. Copy the new key once and save it privately. Later you can change its name, permissions
or expiry, or revoke it. Existing secrets cannot be retrieved again. This guide never includes
your actual key or client data.

A client key can act only on its owner's destinations, even if the owner follows other clients.
Only the workspace operator can create a master key for all clients. Master keys still need
explicit permissions. Give an agent the key, this guide's URL and a clear task; do not give it
your browser password.

## Discover your access

Send `Authorization: Bearer YOUR_KEY` with each protected API request. Keep the key in a private
environment variable or secret store. Never put it in a URL, source repository, screenshots or
logs. Browser cookies do not replace an API key.

Start with `GET /api/agent/v1/me` and `GET /api/agent/v1/accounts`. Use destination IDs returned
by the directory, never guess an owner or rely on freeform client metadata. A new key defaults
to upload permission only. A key's permissions are capabilities, not instructions to approve
everything: perform only the task the user requested.

## Permissions

- `upload`: Upload images/videos and new pending drafts; inspect import receipts.
- `read`: Read existing posts and protected images/videos.
- `review`: Approve, reject or unschedule posts.
- `edit`: Edit captions, titles, tags, links and uploaded attachments.
- `reply`: Prepare X replies. Also requires review permission.

Reading is independent of reviewing and editing. Uploading new attachments requires upload
permission. Preparing replies and editing scheduled posts require review permission as well.
Keys cannot create users, manage other keys, change ownership, or enable social publishing
workers.

## Upload drafts and media

Generate the caption and files externally. Upload raw bytes to the media endpoint with
`Content-Type: image/png`, `image/jpeg`, `image/webp`, `video/mp4` or `video/webm`. This is not
a multipart form. Use URL-encoded query parameters for account_id, filename and optional
alt_text. The returned media ID is bound to that exact destination; upload again for another
destination.

Create a draft using this shape (replace the uppercase placeholders):

```json
{
  "account_id": "ACCOUNT_ID",
  "external_id": "campaign-2026-001",
  "body": "A clear opening.\n\nA little room for the details.",
  "media_ids": ["UPLOADED_MEDIA_UUID"],
  "source": "Content assistant",
  "metadata": {"campaign": "example"}
}
```

For text-only drafts, omit media_ids. Optional fields are title, tags and an HTTPS link_url.
Each draft starts pending. Use `{"posts": [DRAFT_1, DRAFT_2]}` for a batch of up to 40.
Inspect every results[].status_code and the failed count; a batch may partially succeed despite
HTTP 200.

Keep external_id stable within the destination. The same payload retries safely and returns
replayed=true; changing its payload returns 409. Retrying an import never overwrites a later
edit or review. Media uploads deduplicate by destination, bytes and alt text. To edit an
imported draft, use the edit endpoint rather than changing its import payload.

## Read and review existing posts

List `/api/agent/v1/posts?account_id=ACCOUNT_ID&status=pending&limit=20`. Available statuses are
pending, scheduled, archived, published, attention and all. Page size is 1–50. While has_more is
true, pass next_cursor as cursor on the next request with the same account and status. Each
destination identifies its platform; enumerate accounts to inspect all networks.

Posts include full text, media, status, schedule, revision and allowed-action flags. For
pictures/videos, fetch the returned attachments[].url or media[].agent_url with your Bearer key.
Those routes also handle private sample images and video byte ranges. Browser-only media URLs
still require a login. External attachments are not proxied; the original_url is provided.

For approve, reject and unschedule send this JSON:

```json
{"expected_revision": "THE_64_CHARACTER_REVISION_FROM_THE_CURRENT_POST"}
```

A revision covers content, destination, identity and lifecycle state. Approval schedules the
next free configured slot. Rejection archives pending/scheduled posts and cancels their
schedules and pending/scheduled replies. Unschedule is explicit. Repeated or stale actions
return 409; refresh the post and reconcile its current state before deciding whether to act
again.

## Edit content

PATCH an existing post using its current revision and only the fields to change:

```json
{
  "expected_revision": "THE_64_CHARACTER_REVISION_FROM_THE_CURRENT_POST",
  "body": "An improved caption.\n\nReady for another look."
}
```

Editable fields: body, title, tags, link_url and media_ids. Set link_url to null to remove it,
or media_ids to [] to remove attachments. Media IDs must be uploaded to the same destination.
Arbitrary media_urls, account ownership, status and scheduling-time fields are rejected.

AI edits to pending posts stay pending until explicitly approved. Archived edits stay archived.
Editing a scheduled post requires edit plus review permissions and keeps its exact publishing
time; invalid platform content or active/live delivery prevents edits. Manual edits through the
browser retain their existing automatic approval behavior. Replies cannot be edited through this
endpoint.

## Prepare replies

Replies currently support X only and must use a replying account owned by the same client as the
parent. Send account_id, body, a stable request_id UUID, and the parent's expected_revision to
the replies endpoint. Both reply and review permissions are required because the prepared reply
is approved when submitted. Repeating the same request_id and text returns the same reply;
different text with that ID returns 409. Replies wait for confirmed parent publication before
delivery.

## Limits and errors

Captions are limited to 20,000 characters at import/edit, titles to 160, attachments to 10 and
tags to 30. JSON requests are capped at 2 MiB; metadata is a flat object up to 8 KiB. Images are
at most 10 MiB and 20 million pixels; videos at most 100 MiB, 10 minutes, 4096 pixels per
dimension and 8,847,360 pixels per frame. Supported video codecs: H.264/AV1 in MP4, VP8/VP9/AV1
in WebM. H.264 MP4 is the broadest demo choice. Social networks have their own publication
requirements.

401 means missing, expired or revoked key. 403 means missing permission. 404 means missing or
inaccessible account/post/media. 409 means stale revision or lifecycle/import conflict. 413
means too large; 415 unsupported media; 422 invalid input. A 503 interrupted import can be
retried with the original external_id and exact payload. Never retry changed content under an
old import reference.

## Current publishing behavior

This hosted demo is dry-run. Reviewing changes the app's schedule/archive state; it does not
currently send posts to social networks. No publishing workers or platform credentials are
enabled.

## Optional Patreon drafts

Patreon is disabled by default. The client must enable it in Account preferences before its
destination appears in directories or feeds. Keys, including master keys, cannot enable it for
the client. Destinations expose delivery_mode: Patreon uses manual_export.

Patreon drafts accept a reader-facing title (up to 160 characters), body (up to 20,000), and
the documented image/video attachments. Review and edit permissions work on enabled drafts,
but approval reserves only a local planned time. The owner uses Export draft and finishes
publishing in Patreon. Its documented public API does not create ordinary posts. Never claim
automatic publication, native scheduling, membership tiers or paywall configuration.

Disabling Patreon hides its destination and blocks post/media access with 409 while retaining
drafts. Ask the owner to enable it in preferences if they want to work on those drafts again.

## Endpoint reference

- `GET /api/agent/v1/me` — Inspect your key's granted permissions. Permission: Any key.
- `GET /api/agent/v1/accounts` — Discover accessible destination IDs. Permission: Any key.
- `GET /api/agent/v1/posts?account_id=ACCOUNT_ID` — List posts, 20 at a time. Permission: read.
- `GET /api/agent/v1/posts/POST_ID` — Read one post and its current revision. Permission: read.
- `POST /api/ingest/v1/media?account_id=ACCOUNT_ID&filename=FILE` — Upload raw image/video bytes. Permission: upload.
- `POST /api/ingest/v1/posts` — Import one pending draft. Permission: upload.
- `POST /api/ingest/v1/posts/batch` — Import up to 40 drafts. Permission: upload.
- `GET /api/ingest/v1/posts/receipt?account_id=ACCOUNT_ID&external_id=EXTERNAL_ID` — Inspect a known import's status and original metadata. Permission: upload.
- `PATCH /api/agent/v1/posts/POST_ID` — Edit content; scheduled posts also need review permission. Permission: edit.
- `POST /api/agent/v1/posts/POST_ID/approve` — Approve and choose the next free publishing slot. Permission: review.
- `POST /api/agent/v1/posts/POST_ID/reject` — Archive and cancel any active schedule and pending replies. Permission: review.
- `POST /api/agent/v1/posts/POST_ID/unschedule` — Return a scheduled post to pending. Permission: review.
- `POST /api/agent/v1/posts/POST_ID/replies` — Prepare a dependent X reply. Permission: reply + review.
- `GET /api/agent/v1/media/MEDIA_ID` — Read an owned upload; video supports Range. Permission: read.
- `GET /api/agent/v1/posts/POST_ID/media/INDEX` — Read an authorized attachment, including existing samples. Permission: read.

## Machine-readable references

- [Agent discovery index](https://feed.weeyuga.com/llms.txt)
- [Full guide in Markdown](https://feed.weeyuga.com/agent-guide.md)
- [Full text guide](https://feed.weeyuga.com/llms-full.txt)
- [Scoped API OpenAPI schema](https://feed.weeyuga.com/api/agent/v1/openapi.json)
- [Instructions page for signed-in users](https://feed.weeyuga.com/agent-guide)

The [llms.txt proposal](https://llmstxt.org/) helps tools discover instructions; support varies.
It does not authenticate an agent or grant permission. Tell an agent to read this guide
explicitly if its tool does not discover it automatically.
