3.9 KiB
3.9 KiB
Agent Publish API — /api/agent/posts
Publish and manage blog posts programmatically. Auth: send the agent key in the
x-agent-key header. The key lives on the VPS in /root/anwarpi/.env.production
(AGENT_API_KEY).
- Base URL:
https://anwarpy.ai - Content-Type:
application/json - Posts are created draft by default. Pass
"publish": trueto publish (setsstatus: published+publishedAtnow). Unpublishing stays admin-only (/admin). accesscontrols gating:"free"(public) or"vip"(members only).content(Lexical) may be omitted on create — a minimal valid doc is inserted; update it later with PUT. Other writable fields:title,slug,dek,teaser,category(agents|models|automation|foundations),readingMinutes,cover.attachmentsattaches per-post work files: an array of{ "filename": "agent-state.md", "dataBase64": "…", "access": "vip" }.accessis per file ("free"downloads for anyone,"vip"members only) and defaults to"vip". Max 5 files, ≤5MB each, extensions pdf/zip/md/csv/ txt/json. On PUT, sendingattachmentsreplaces the post's file set — omit the field to keep existing files.
Create + publish a post with an image
KEY=033d1eed44ca6abf483de10735c47155d38f7b5bc9d46449
# Inline base64 image (jpeg/png/webp, ≤5MB)
python3 - <<'EOF' > /tmp/post.json
import base64, json, pathlib
print(json.dumps({
"title": "دليلي الجديد",
"slug": "my-new-guide",
"dek": "وصف قصير يظهر في القوائم.",
"teaser": "نص المعاينة للزوار غير المشتركين.",
"category": "وكلاء",
"access": "vip", # or "free"
"readingMinutes": 9,
"publish": True, # omit → draft
"coverImage": {
"filename": "my-cover.jpg",
"mimeType": "image/jpeg",
"dataBase64": base64.b64encode(pathlib.Path("my-cover.jpg").read_bytes()).decode(),
},
}))
EOF
curl -s -X POST https://anwarpy.ai/api/agent/posts \
-H "x-agent-key: $KEY" -H "Content-Type: application/json" \
--data @/tmp/post.json
Response 201:
{
"id": 113, "title": "دليلي الجديد", "slug": "my-new-guide",
"status": "published", "access": "vip", "category": "agents",
"cover": { "id": 113, "url": "/api/media/file/my-cover.jpg" },
"attachments": [
{ "id": 42, "filename": "agent-state.md", "access": "vip", "url": "/api/files/42" }
]
}
Update a post
curl -s -X PUT https://anwarpy.ai/api/agent/posts/my-new-guide \
-H "x-agent-key: $KEY" -H "Content-Type: application/json" \
-d '{"access": "free", "publish": true,
"coverImage": {"url": "https://example.com/cover.png"}}'
coverImageaccepts{ "dataBase64": "…" }or{ "url": "https://…" }(server fetches and stores it;filename/mimeTypeoptional).covermay also be an existing media ID (integer).
Where the image appears
The cover is rendered on:
- Post page (
/posts/<slug>) — full-width cover under the header. - Articles listing (
/articles) — thumbnail on each card. - Homepage (
/) — "أحدث الأدلة" section (latest 6 published posts).
If a post has no cover, the catalog card falls back to the category's default decorative cover; the post page and listing simply omit the image.
Rules
- The agent cannot set
statusdirectly — only via"publish": true. - The agent cannot unpublish or delete — do that in
/admin. - Images are validated: jpeg/png/webp, ≤5MB; stored as Payload
mediadocuments and served from/api/media/file/<filename>. - Attachments are stored as Payload
filesdocuments underfiles-private/(volume-mount it likemedia/on the VPS). Downloads go throughGET /api/files/<id>:freefiles stream to anyone,vipfiles return 401 anonymous / 403 for non-members. Thevipbadge on the post page links only for entitled viewers.