Posting and Micropub
View .mdEndpoints for publishing, replying, uploading media, and querying Micropub resources.
https://micro.blog
/micropub
Answers Micropub queries for configuration, cross-posting services, categories, contacts, and existing posts or pages. The q parameter picks the query; an unknown value returns {}. Requires a token. q=source needs the read or update scope; the other queries accept any of read, create, update, delete, or media.
Example Request
curl -X GET "https://micro.blog/micropub?q=config" \
--header "Authorization: Bearer ABCDEF1234567890ABCD"
Examples
List recent posts
q=source returns items, each an h-entry with uid, name, content, summary, published, post-status, url, category, and syndication. Replies, likes, a thumbnail, and a location are added when the post has them. With url, the single h-entry comes back without the items wrapper. Pages carry microblog-template, microblog-smart, and microblog-generating instead.
{
"items": [
{
"type": "h-entry",
"properties": {
"uid": [12345],
"name": [""],
"content": ["Hello world."],
"summary": [""],
"published": ["2026-04-26T12:00:00+00:00"],
"post-status": ["published"],
"url": ["https://example.micro.blog/2026/04/26/hello-world.html"],
"category": ["Travel"],
"syndication": []
}
}
]
}
List categories
q=category returns category names, plus Micro.blog details for each.
{
"categories": ["Travel"],
"microblog-categories": [
{
"uid": 42,
"url": "https://example.micro.blog/categories/42",
"name": "Travel",
"path": "travel",
"posts_count": 12
}
]
}
Look up contacts
q=contact returns up to 10 Micro.blog users whose username starts with filter.
{
"contacts": [
{
"name": "Manton Reece",
"url": "https://www.manton.org/",
"photo": "https://micro.blog/manton/avatar.jpg",
"nickname": "manton"
}
]
}
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
q
|
string | Required |
Query type: config, syndicate-to, category, contact, or source.
Example:
config
|
mp-destination
|
string | Optional |
Blog to query, as the uid URL from a config destination. Falls back to the user’s default blog when it doesn’t match one of their blogs. Used by config, syndicate-to, category, and source.
Example:
https://example.micro.blog/
|
mp-channel
|
string | Optional |
For source, list pages or collections instead of blog posts.
Example:
pages
|
post-status
|
string | Optional |
For source, set to draft to list only drafts.
Example:
draft
|
url
|
string | Optional |
For source, return one post by its URL instead of a list. Returns 400 when no post on the blog has this URL.
Example:
https://example.micro.blog/2026/04/26/hello-world.html
|
category
|
integer | Optional |
For source, only list posts in this category ID.
Example:
42
|
filter
|
string | Optional |
For source, only list posts or pages whose title or text contains this text. For category, only list categories whose name starts with it. For contact, match usernames that start with it; at least 3 characters are needed to get results.
Example:
travel
|
limit
|
integer | Optional |
For source, the maximum number of items to return.
Example:
20
|
offset
|
integer | Optional |
For source and contact, the number of items to skip.
Example:
20
|
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Response
200 OK application/json
Returns a JSON object whose shape depends on q. The example shows q=config. Errors use the Micropub format, {"error": "invalid_request", "error_description": "..."}, with status 400.
Example Response
{
"media-endpoint": "https://micro.blog/micropub/media",
"destination": [
{
"uid": "https://example.micro.blog/",
"name": "example.micro.blog",
"microblog-audio": true,
"microblog-default": true,
"microblog-title": "Example Blog"
}
],
"post-types": [
{
"type": "note",
"name": "Post",
"properties": ["content", "published", "post-status", "category", "read-of", "mp-destination", "checkin", "location"]
},
{
"type": "article",
"name": "Article",
"properties": ["name", "content", "published", "post-status", "category", "mp-channel", "mp-destination"]
},
{
"type": "photo",
"name": "Photo",
"properties": ["name", "content", "published", "post-status", "category", "mp-destination", "photo", "mp-photo-alt"]
},
{
"type": "reply",
"name": "Reply",
"properties": ["content", "in-reply-to"]
},
{
"type": "bookmark",
"name": "Bookmark",
"properties": ["bookmark-of", "summary"]
}
],
"channels": [
{
"uid": "default",
"name": "Posts"
},
{
"uid": "pages",
"name": "Pages"
}
],
"syndicate-to": [
{
"uid": "mastodon",
"name": "Mastodon (@example@mastodon.social)"
}
]
}
/micropub
Creates, updates, or deletes posts, pages, collections, bookmarks, and categories through Micropub. Send form-encoded parameters, multipart form data when uploading a photo file, or a Micropub JSON body. Creating needs the create scope, action=update needs update, and action=delete needs delete.
name form parameter. Updates (action=update with replace, add, or delete), check-ins, locations, and read-of are only read from JSON. Array parameters in a form use [], for example category[]=Travel&category[]=Food.
POST /posts/reply.
Example Request
curl -X POST "https://micro.blog/micropub" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--data-urlencode "h=entry" \
--data-urlencode "content=Hello world." \
--data-urlencode "category[]=Travel"
Examples
Create a post with JSON
Photos in JSON can be URLs or {"value": "...", "alt": "..."} objects.
curl -X POST "https://micro.blog/micropub" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--header "Content-Type: application/json" \
--data '{
"type": ["h-entry"],
"properties": {
"content": ["Hello world."],
"photo": [{"value": "https://example.micro.blog/uploads/2026/photo.jpg", "alt": "A sunset over the bay"}],
"category": ["Travel"]
}
}'
Update a post
replace can set name, content, summary, post-status, published, category, photo, audio, and video.
curl -X POST "https://micro.blog/micropub" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--header "Content-Type: application/json" \
--data '{
"action": "update",
"url": "https://example.micro.blog/2026/04/26/hello-world.html",
"replace": {
"content": ["Hello again."]
}
}'
Delete a post
curl -X POST "https://micro.blog/micropub" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--data-urlencode "action=delete" \
--data-urlencode "url=https://example.micro.blog/2026/04/26/hello-world.html"
Create a category
With mp-channel=categories, name is the category name, and path and text set its URL path and description. Creating returns 202 with the category in the same shape as q=category. action=update with the category url returns 200 with the updated category, and action=delete returns 200 with {}.
curl -X POST "https://micro.blog/micropub" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--data-urlencode "mp-channel=categories" \
--data-urlencode "name=Travel"
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}. As Micropub allows, the token can be sent as an access_token parameter instead.
|
Content-Type
|
string | Required |
application/x-www-form-urlencoded, multipart/form-data, or application/json.
|
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
h
|
string | Optional |
Micropub object type. Send entry; Micro.blog doesn’t require it.
Example:
entry
|
content
|
string | Optional |
Post text, in Markdown or HTML. A new post needs content, photo, or bookmark-of.
Example:
Hello world.
|
name
|
string | Optional |
Post title. Required for a new page (mp-channel=pages) or collection (mp-channel=collections), and used as the category name when mp-channel=categories.
Example:
A title for a longer post
|
summary
|
string | Optional |
Post summary. For a bookmark, the note saved with it.
Example:
A short summary.
|
published
|
string | Optional |
Publish date, as an ISO 8601 date. A future date schedules the post.
Example:
2026-04-26T12:00:00+00:00
|
post-status
|
string | Optional |
Set to draft to save a draft instead of publishing.
Example:
draft
|
category
|
array | Optional |
Category names for the post. Repeat as category[] for several.
Example:
Travel
|
photo
|
array | Optional |
Photo URL, usually from POST /micropub/media, or a photo file in a multipart request. Repeat as photo[] for several.
Example:
https://example.micro.blog/uploads/2026/photo.jpg
|
mp-photo-alt
|
array | Optional |
Alt text for each photo, in the same order as photo. Repeat as mp-photo-alt[].
Example:
A sunset over the bay
|
audio
|
array | Optional |
Audio file URL from POST /micropub/media. Repeat as audio[] for several.
Example:
https://example.micro.blog/uploads/2026/episode.mp3
|
video
|
array | Optional |
Video file URL from POST /micropub/media. Repeat as video[] for several.
Example:
https://example.micro.blog/uploads/2026/video.mp4
|
in-reply-to
|
string | Optional |
URL being replied to. The URL of a post on Micro.blog creates a Micro.blog reply; any other URL creates a blog post that starts “In reply to”.
Example:
https://www.manton.org/2026/04/26/hello.html
|
bookmark-of
|
string | Optional |
URL to save as a Micro.blog bookmark. A bookmark isn’t published to the blog.
Example:
https://example.com/article
|
bookmark-content
|
string | Optional |
HTML of the bookmarked page, used instead of downloading it. Only read with bookmark-of.
Example:
<html>...</html>
|
repost-of
|
string | Optional |
URL being reposted. A link to it is added to the end of the content.
Example:
https://example.com/post
|
mp-destination
|
string | Optional |
Blog to post to, as the uid URL from a config destination. Defaults to the user’s default blog.
Example:
https://example.micro.blog/
|
mp-channel
|
string | Optional |
pages creates a standalone page, collections creates an upload collection, and categories creates, updates, or deletes a category. Leave it out for blog posts.
Example:
pages
|
mp-navigation
|
string | Optional |
For a new page, set to 1 or true to add it to the blog’s navigation.
Example:
1
|
mp-syndicate-to
|
array | Optional |
Cross-posting service uids from q=syndicate-to, sent as mp-syndicate-to[]. Without it, the post goes to every cross-posting service the blog has enabled. Send one empty value to skip cross-posting.
Example:
mastodon
|
action
|
string | Optional |
update or delete. Both need url. Updates take a JSON body.
Example:
delete
|
url
|
string | Optional |
URL of the post, page, reply, collection, or category to update or delete.
Example:
https://example.micro.blog/2026/04/26/hello-world.html
|
Response
202 OK application/json
A new blog post returns 202 with its URL in the Location header and a JSON body holding url, preview, and edit. New pages, new collections, and posts replying to sites outside Micro.blog return 202 with url. Bookmarks and replies to Micro.blog posts return 202 with an empty body. Updates and deletes return 200 with an empty body, or 404 when url isn’t found. Category changes return the category instead. Errors return 400 with {"error": "invalid_request", "error_description": "..."}.
Example Response
{
"url": "https://example.micro.blog/2026/04/26/hello-world.html",
"preview": "https://micro.blog/account/posts/123/preview/12345",
"edit": "https://micro.blog/account/posts/123/edit/12345"
}
/micropub/media
Lists files uploaded to a blog, newest first. Only q=source is supported; any other query returns {}. The upload endpoint itself is advertised by GET /micropub?q=config. Requires a token with the read scope.
Example Request
curl -X GET "https://micro.blog/micropub/media?q=source&limit=20" \
--header "Authorization: Bearer ABCDEF1234567890ABCD"
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
q
|
string | Required |
Set to source.
Example:
source
|
mp-destination
|
string | Optional |
Blog to list uploads for, as the uid URL from a config destination. Defaults to the user’s default blog.
Example:
https://example.micro.blog/
|
filter
|
string | Optional |
Only list uploads whose alt text, generated description, keywords, or URL contains this text.
Example:
sunset
|
microblog-collection
|
string | Optional |
Collection URL. Lists that collection’s uploads in their collection order, ignoring limit and offset.
Example:
https://example.micro.blog/collections/7
|
limit
|
integer | Optional |
Maximum number of uploads to return.
Example:
20
|
offset
|
integer | Optional |
Number of uploads to skip.
Example:
20
|
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Response
200 OK application/json
Returns an items array. Images include alt, microblog-ai (whether the alt text was generated), and sizes and cdn URLs; medium and small appear when those sizes exist. Videos with a poster image return url, poster, published, microblog-id, and duration instead.
Example Response
{
"items": [
{
"url": "https://example.micro.blog/uploads/2026/photo.jpg",
"published": "2026-04-26T12:00:00+00:00",
"alt": "A sunset over the bay",
"microblog-ai": false,
"microblog-id": 12345,
"sizes": {
"large": "https://example.micro.blog/uploads/2026/photo.jpg",
"medium": "https://example.micro.blog/uploads/2026/m-photo.jpg"
},
"cdn": {
"large": "https://cdn.uploads.micro.blog/123/2026/photo.jpg",
"medium": "https://cdn.uploads.micro.blog/123/2026/m-photo.jpg"
}
}
]
}
/micropub/media
Uploads a photo, video, or audio file, or updates or deletes an existing upload. Uploading needs the media scope and action=delete needs delete; action=update needs write. External blogs only accept images.
Example Request
curl -X POST "https://micro.blog/micropub/media" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--form "file=@/path/to/photo.jpg"
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Content-Type
|
string | Required |
multipart/form-data for an upload.
|
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
file
|
file | Optional |
The file to upload. Required unless action is delete or update.
Example:
@/path/to/photo.jpg
|
mp-destination
|
string | Optional |
Blog to upload to, as the uid URL from a config destination. Defaults to the user’s default blog.
Example:
https://example.micro.blog/
|
action
|
string | Optional |
delete removes the upload at url. update sets the alt text of the upload at url to alt.
Example:
delete
|
url
|
string | Optional |
URL of the upload to delete or update.
Example:
https://example.micro.blog/uploads/2026/photo.jpg
|
alt
|
string | Optional |
New alt text, with action=update.
Example:
A sunset over the bay
|
Response
202 OK application/json
An upload returns 202 with the file URL in the Location header and in the body. poster is a poster image URL for videos and an empty string otherwise. action=delete and action=update return 200 with an empty body; delete returns 404 when the upload isn’t found. Errors return 400 with {"error": "invalid_request", "error_description": "..."}.
Example Response
{
"url": "https://example.micro.blog/uploads/2026/photo.jpg",
"poster": ""
}
/micropub/media/append
Uploads one chunk of a large video or audio file. Send every chunk with the same file_id, in order, then call POST /micropub/media/finished. Requires a token with the media scope. External blogs don’t support chunked uploads.
Example Request
curl -X POST "https://micro.blog/micropub/media/append" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--form "file_id=12345" \
--form "file_data=data:;base64,AAAA"
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
file_id
|
integer | Required |
Identifier your app generates for the file, shared by all of its chunks.
Example:
12345
|
file_data
|
string | Required |
Base64-encoded chunk data. A data URL prefix such as data:;base64, is stripped.
Example:
data:;base64,AAAA
|
mp-destination
|
string | Optional |
Blog the file is for, as the uid URL from a config destination. Defaults to the user’s default blog.
Example:
https://example.micro.blog/
|
Response
200 OK application/json
Returns an empty JSON object. Errors return 400 with {"error": "invalid_request", "error_description": "..."}.
Example Response
{}
/micropub/media/finished
Marks a chunked upload as complete and starts processing it. Poll GET /micropub/media/waiting for the final URL. Requires a token with the media scope.
Example Request
curl -X POST "https://micro.blog/micropub/media/finished" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--form "file_id=12345" \
--form "file_name=video.mov"
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
file_id
|
integer | Required |
The file_id used for the appended chunks.
Example:
12345
|
file_name
|
string | Required |
Original file name. Its extension tells Micro.blog the file type.
Example:
video.mov
|
mp-destination
|
string | Optional |
Blog the file is for, as the uid URL from a config destination. Defaults to the user’s default blog.
Example:
https://example.micro.blog/
|
Response
200 OK application/json
Returns an empty JSON object once processing is queued. Errors return 400 with {"error": "invalid_request", "error_description": "..."}.
Example Response
{}
/micropub/media/waiting
Returns whether a chunked upload is still processing and, once it’s done, its URL. Requires a token with the media or read scope.
Example Request
curl -X GET "https://micro.blog/micropub/media/waiting?file_id=12345" \
--header "Authorization: Bearer ABCDEF1234567890ABCD"
Query Parameters
| Name | Type | Required | Description |
|---|---|---|---|
file_id
|
integer | Required |
The file_id used for the upload.
Example:
12345
|
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Response
200 OK application/json
url is null until processing finishes.
Example Response
{
"is_processing": false,
"url": "https://example.micro.blog/uploads/2026/video.mp4"
}
/posts/reply
Replies to a Micro.blog post or reply. Requires a token with the create scope.
Example Request
curl -X POST "https://micro.blog/posts/reply" \
--header "Authorization: Bearer ABCDEF1234567890ABCD" \
--data-urlencode "id=77479242" \
--data-urlencode "content=@manton Thanks for the update."
Header Parameters
| Name | Type | Required | Description |
|---|---|---|---|
Authorization
|
string | Required |
Bearer token for authentication. Format: Bearer {token}.
|
Request Body
| Name | Type | Required | Description |
|---|---|---|---|
id
|
integer | Required |
ID of the post being replied to.
Example:
77479242
|
content
|
string | Required |
Reply text, in Markdown. Include the @-mentions for everyone you’re replying to. text is accepted as an alias.
Example:
@manton Thanks for the update.
|
Response
200 OK application/json
Returns an empty JSON object on success. When the reply can’t be sent, for example because replying is disabled, a trial account has no payment method, or it mentions a fediverse or Bluesky user without that service connected, the status is still 200 and the body is {"error": "..."}.
Example Response
{}