Micropub is an open API standard (W3C Recommendation) that is used to create, update, and delete posts on one's own domain using third-party clients, and supersedes both MetaWeblog and AtomPub. Web apps and native apps (e.g. iPhone, Android) can use Micropub to post and edit articles, short notes, comments, likes, photos, events, or other kinds of posts to your own site.
Submit an implementation report for Micropub to help the specification advance at W3C!
- Start here: https://micropub.rocks/
The Micropub vocabulary is derived directly from the Microformats vocabulary. Micropub is meant to be a serialization of Microformats that can be submitted as an HTTP POST. The method for developing new Micropub vocabularies is to look at the Microformats representation and work backwards.
Similar to how microformats has a relatively small ruleset for parsing HTML documents into a data structure, Micropub defines a small set of rules to interpret HTTP POST and GET requests as Micropub commands. Where Microformats does not require changing the parsing rules to introduce new properties of an object such as an h-entry, Micropub similarly does not require changing parsing rules to interpret requests that may correspond to different post types, such as posting videos vs "likes".
The Micropub syntax describes how to interpret HTTP POST and GET requests into a useful action the server can take.
The full specification can be read at http://micropub.net/draft/
All Micropub requests to create posts are sent as form-encoded, multipart form-data , or JSON encoded HTTP requests. Responses typically do not include a response body, indicating the needed information (such as the URL of the created post) in HTTP headers. When a response body is required, it is returned as either form-encoded or JSON, depending on the HTTP Accept header.
How to implement
How to implement the Micropub API, both in a client that can discover an endpoint and publish to it, and on a server to support an endpoint to create/update/delete posts in response.
It should be possible to configure an API client by authenticating as your domain name using IndieAuth. After signing in, your domain needs a way to specify the API endpoint the client will use to create new posts.
Add a <link> tag in the HTML head of your home page, or send an HTTP Link header.
Link: <https://example.com/micropub>; rel="micropub"
<link rel="micropub" href="https://example.com/micropub">
Micropub requests are authenticated by including a Bearer Token in either the HTTP header or a form-encoded body parameter as described in the OAuth Bearer Token RFC.
Authorization should be handled via the IndieAuth protocol, built on top of OAuth 2.0. See obtaining-an-access-token for more details. An app that wants to post to a user's Micropub endpoint will need to obtain authorization from the user in order to get an access token.
Authorization: Bearer XXXXXXXX
Form-Encoded Body Parameter
The client may request one or more scopes during the authorization request. It does this according to standard OAuth 2.0 techniques, by passing a space-separated list of scope names in the authorization request.
The authorization server must indicate to the user any scopes that are part of the request, whether or not the authorization server recognizes the scopes. The authorization server may also allow the user to add or remove scopes that the client requests.
For example, most Micropub servers require clients to obtain the "post" scope in order to create posts. However, some servers may require more granular scope requests, such as "delete" or "post:video". See scope for more details and a list of all currently used values for scope.
A micropub client can verify that an access token is still valid (and other details) by querying the user's token endpoint.
- this does not cover the case where the server has decided not to accept it anymore, e.g. because the user's access to the site has been removed
- if a micropub endpoint plans on rejecting a token in the future, it should ensure the token endpoint also rejects the token. For systems where the token endpoint and micropub endpoint are part of the same software, this is an implementation detail. If the token endpoint and micropub endpoint are on different systems, there needs to be a mechanism for the micropub endpoint to expire the token at the token endpoint. This is what's known as token revocation, and has been written up for OAuth 2: https://tools.ietf.org/html/rfc7009
Form-encoded Microformats Representation
For the simplicity of writing clients and servers, all Micropub endpoints must handle the standard form-encoded format. At a most basic level, you should be able to write an HTML form and set the form action to your own endpoint and use it to post to your site.
Examples of Creating Objects
How to create some of the common post types
Indicating the object being created
To indicate the object being created, use a property called "h", (which would never be the name of a property of a microformats object), followed by the name of the microformats object. Examples:
The following properties may be included in a request to create a new h-entry:
- category = tag1, tag2, tag3 (sent as array syntax:
- as a Geo URI, for example
- GeoURIs allow additional parameters that may be used to include the title of a location:
- GeoURIs allow additional parameters that may be used to include the title of a location:
- as a URL that contains an h-card
- My micropub client currently has a map to mark the specific location in LatLng values, and a text input for an actual place name. So my client is sending a request of the form "&location=1.23,%40-4.56:An%40Address" Jonnybarnes.net 07:57, 10 June 2014 (PDT)
- as a Geo URI, for example
- Pass one or more URLs pointing to places where this entry already exists. Can be used for PESOS implementations.
- mp-syndicate-to = https://myfavoritesocialnetwork.example/aaronpk, https://archive.org/, etc.
- This property is slightly different from the others since it is giving a command to the server rather than describing an object, which is why it is prefixed with "mp-".
Posting a new note with tags, syndicating to myfavoritesocialnetwork:
- published (optional, defaults to "now" if not present. Useful for writing offline and syncing later)
POST /micropub HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=entry &content=The+%40Jawbone+UP%2C+my+favorite+of+the+%23quantifiedself+trackers%2C+finally+released+their+official+API%21+http%3A%2F%2Fjawbone.com%2Fup%2Fdeveloper%2F &category=jawbone&category=quantifiedself&category=api &mp-syndicate-to=https://myfavoritesocialnetwork.example/aaronpk
POST /micropub HTTP/1.1 Host: example.com Content-type: application/x-www-form-urlencoded Authorization: Bearer XXXXXXX h=entry &content=Hello+World
curl https://example.com/micropub -d h=entry -d "content=Hello World" -H "Authorization: Bearer XXXXXXX"
Posting a new reply, syndicating to myfavoritesocialnetwork
POST /post/new HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=entry &content=%40BarnabyWalters+My+favorite+for+that+use+case+is+Redis.+It%27s+easy+to+set+up+and+use%2C+I+often+use+it+to+move+data+between+apps+written+in+different+languages+too. &in-reply-to=http://waterpigs.co.uk/notes/4S0LMw/ &mp-syndicate-to=https://myfavoritesocialnetwork.example/aaronpk
Posting a new repost, and adding additional tags.
POST /micropub HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=entry &repost-of=http://waterpigs.co.uk/notes/4S0LMw/ &category=realtime
Posting a new article
Posting a new bookmark with name, quote, and tags.
POST /micropub HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=entry &bookmark-of=https%3A%2F%2Fplus.google.com%2F%2BKartikPrabhu%2Fposts%2FUzKErSbfmHq &name=To+everyone+who+is+complaining+about+Popular+Science+shutting+down+comments... &content=%22Why+is+there+this+expectation+that+every+website+should+be+a+forum%3F+No+website+has+any+obligation+to+provide+a+space+for+your+rants.+Use+your+own+space+on+the+web+to+do+that.%22 &category=indieweb&category=comments
When a Micropub request includes a file, the entire request is sent in the
multipart/form-data encoding, and the file is named by content type, either "audio", "video" or "photo". A request may include one or more of these files.
When OwnYourGram makes a Micropub request to post a video, it also sends a photo which is a thumbnail preview of the video.
In PHP, these files are accessible using the
$_FILES['video'] $_FILES['photo'] $_FILES['audio']
Note that there is no practical way to upload a file when the request body is JSON encoded. The media endpoint needs to be used in that case.
$ curl -H 'Authorization: Bearer abc'\ -F 'h=entry'\ -F 'content=an image!'\ -F 'photo=@/home/cweiske/Bilder/openid-id.bogo.png'\ 'http://known.bogo/micropub/endpoint'
The following properties may be included in a request to create a new h-event:
Posting a new event
POST /micropub HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=event &name=IndieWeb Dinner at 21st Amendment &description=In SF Monday evening? Join @caseorganic and I for an #indieweb dinner at 6pm! (Sorry for the short notice!) &start=2013-09-30T18:00:00-07:00 &category=indieweb &location=http://21st-amendment.com/
The following properties may be included in a request to create a new h-cite:
(The following list is from microformats.org/wiki/h-cite)
- published - date of publication of the work (not the date the h-cite was created)
- author - URL of an h-card
- url - a URL to access the cited work
- content - the content or partial content of the work itself, such as when including a blockquote snippet of a work
Nested Microformat Objects
Whenever possible, nested Microformats objects should be avoided. A better alternative is to reference objects by their URLs. The most common example is including an h-card for a venue, such as checking in to a location or tagging a photo with a person or location. In these cases, it is better to reference the object by URL, creating it first if necessary.
For simple values such as an h-geo property with latitude and longitude, just use a Geo URI such as
This technique has the advantage of ensuring that each object that is created has its own URL (each piece of data has its own link). This also gives the server an opportunity to handle each entity separately. E.g., rather than creating a duplicate of an existing venue, it may give back a link to one that was already created, possibly even merging in newly received data first.
For more complicated objects, it is better to first create an object on the target site so that it has its own URL, then reference that object's URL in the main request.
For example, creating a checkin post would involve two POST requests:
First create the venue by posting an h-card:
POST /micropub h=card &name=Ford+Food+and+Drink &url=http://www.fordfoodanddrink.com/ &street-address=2505 SE 11th Ave &locality=Portland ®ion=OR &postal-code=97214 &geo=geo:45.5048473,-122.6549551 &tel=(503) 236-3023
HTTP/1.1 201 Created Location: http://example.com/venue/10
Then create the checkin post:
POST /micropub h=entry &location=http://example.com/venue/10 &name=Working on Micropub &category=indieweb
HTTP/1.1 201 Created Location: http://example.com/entry/1001
- This technique has the advantage of ensuring that each object that is created has its own URL (each piece of data has its own link)
- Also gives the server an opportunity to handle each entity separately. E.g., rather than creating a duplicate of an existing venue, it may give back a link to one that was already created, possibly even merging in newly received data first.
In some cases, it does not make sense for the nested object to have a URL. For example, when posting an h-measure value, there is no reason for the h-measure itself to have a URL, so this is an acceptable case to use the nested microformats object syntax.
For example, creating a new "weight" measurement post as an h-entry with h-measure objects:
h=entry &weight[type]=h-measure &weight[properties][num]=155.73 &weight[properties][unit]=lb &bodyfat[type]=h-measure &bodyfat[properties][num]=19.83 &bodyfat[properties][unit]=%
Examples of Micropub endpoints are listed at Micropub/Servers.
Click through to the main article for a list of sites and client applications that publish via Micropub as well as a table indicating implementation statuses.
Open source libraries & implementations used to support micropub on the client app side and on the API endpoint side on the server:
- p3k-micropub PHP library used in p3k
- taproot/authentication PHP library used in Taproot, implements both client app and resource provider authentication
- wordpress-micropub: WordPress plugin for server endpoint
- flask-micropub: Flask (Python) plugin that makes it easy to add IndieAuth authentication and Micropub authorization to a client application.
- micropub-express Node.js server library created and used by Pelle Wessman for voxpelli.com's micropub endpoint
- micropub-helper Node.js client library created and used by grant.codes
Please use the Github repo for issues and discussion related to the spec.
For issues that have been discussed and are ready to consider for inclusion in the spec, use the Micropub-brainstorming page to collect examples and iterate on the ideas.