Posts API
Use these endpoints to manage your own drafts and published posts.
Endpoints
POST /api/v1/postscreate draftGET /api/v1/postslist posts (?status=draft|publishedoptional)GET /api/v1/posts/:idget post by UUIDPATCH /api/v1/posts/:idupdate post fieldsDELETE /api/v1/posts/:iddelete draft
Create draft
POST /api/v1/posts
Required body fields:
paidContentMarkdownorfreeContentMarkdown
Common optional fields:
title,descriptionfreeContentMarkdownenablePaywall,priceRawprimaryCategoryId,secondaryCategoryIdslug,canonicalUrl,language,commentsEnabledogTitle,ogDescription,ogImage
Behavior:
- If
paidContentMarkdownis omitted or empty,enablePaywallis treated asfalse. - Non-paywalled posts keep
paidContentMarkdownandfreeContentMarkdownaligned.
List posts
GET /api/v1/posts?status=draft&page=1&per_page=20
Returns:
{
"data": [{ "id": "uuid", "status": "draft" }],
"total": 1,
"page": 1,
"perPage": 20
}
Get post
GET /api/v1/posts/:id
Returns a full resource including:
paidContentMarkdownfreeContentMarkdownogImageEffective
ogImageEffective follows this order:
- Explicit
metadata.og.image - First image found in
freeContentMarkdown
Update post
PATCH /api/v1/posts/:id
Partial updates are supported. Slug updates are rejected when the post is already published.
Delete post
DELETE /api/v1/posts/:id
Rules:
- Only drafts can be deleted.
- Published posts must be unpublished first.
- Posts with paid purchases cannot be deleted.
Integration Recipe: Post with 2 Images
Use this when you want one clear, copy-safe flow from draft to published.
- Create draft
- Upload image 1 (
intent=content) - Upload image 2 (
intent=content) - Patch markdown with both image URLs
- Publish with
Idempotency-Key
Step 1: create draft
curl -X POST "https://subnano.me/api/v1/posts" \
-H "Authorization: Bearer $SUBNANO_PUBLISH_KEY" \
-H "Content-Type: application/json" \
-d '{
"title": "My post with two images",
"description": "Example flow",
"paidContentMarkdown": "Draft body placeholder",
"enablePaywall": true,
"priceRaw": "100000000000000000000000000000",
"primaryCategoryId": 4,
"language": "en"
}'
Save the returned id as POST_ID.
Step 2: upload image 1
curl -X POST "https://subnano.me/api/v1/posts/$POST_ID/images?intent=content" \
-H "Authorization: Bearer $SUBNANO_PUBLISH_KEY" \
-F "file=@/path/to/image-1.jpg"
Save returned url as IMG_1.
Step 3: upload image 2
curl -X POST "https://subnano.me/api/v1/posts/$POST_ID/images?intent=content" \
-H "Authorization: Bearer $SUBNANO_PUBLISH_KEY" \
-F "file=@/path/to/image-2.jpg"
Save returned url as IMG_2.
Step 4: patch markdown with both image URLs
curl -X PATCH "https://subnano.me/api/v1/posts/$POST_ID" \
-H "Authorization: Bearer $SUBNANO_PUBLISH_KEY" \
-H "Content-Type: application/json" \
-d "{
\"paidContentMarkdown\": \"# Final title\n\nIntro text.\n\n\n\nMore text.\n\n\"
}"
Tip: if building payloads in shell, use \n (not \\n) for markdown line breaks.
Step 5: publish
curl -X POST "https://subnano.me/api/v1/posts/$POST_ID/publish" \
-H "Authorization: Bearer $SUBNANO_PUBLISH_KEY" \
-H "Idempotency-Key: 6d65f0f8-6897-4d8e-a3cb-f6f12f947f99"
Optional: if you want a dedicated social preview image, upload with intent=og (or set ogImage via PATCH).