Copyright © 2016 W3C® (MIT, ERCIM, Keio, Beihang). W3C liability, trademark and permissive document license rules apply.
Micropub is an open API standard used to create posts on one's own domain using third-party clients. Web apps and native apps (e.g., iPhone, Android) can use Micropub to post short notes, photos, events or other posts to your own site.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This document was published by the Social Web Working Group as a Working Draft. This document is intended to become a W3C Recommendation. If you wish to make comments regarding this document, please send them to public-socialweb@w3.org (subscribe, archives). All comments are welcome.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This document is governed by the 1 September 2015 W3C Process Document.
Micropub is a spec to create content on a server using web or native app clients.
This section is non-normative.
The Micropub vocabulary is derived directly from the [Microformats2] 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.
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in [RFC2119].
This section describes the conformance criteria for Micropub clients and servers.
A conforming Micropub client that creates posts:
A conforming Micropub client that edits posts:
A conforming Micropub server:
As [Microformats2] has a relatively small ruleset for parsing HTML documents into a data structure, Micropub similarly 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 useful server actions.
All Micropub requests to create posts are sent as x-www-form-urlencoded, multipart form-data [HTML5], 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 necessary, it SHOULD be returned as a [JSON] encoded object.
A few POST body property names are reserved when requests are sent as x-www-form-urlencoded or multipart form data.
access_token
- the OAuth Bearer token authenticating the request (the access token may be sent in an HTTP Authorization header or this form parameter)h
- used to specify the object type being createdq
- used to query a Micropub endpointurl
- indicates the URL of the object being changedmp-action
- indicates whether this is an update
, delete
, or undelete
replace
- for updates, the top-level property containing properties to replaceadd
- for updates, the top-level property containing properties to adddelete
- for updates, the top-level property containing properties to removemp-*
- reserved for future useWhen creating posts, all other properties in the request are considered properties of the object being created.
To create a post, send an HTTP POST request to the Micropub endpoint indicating the type of post you are creating, as well as specifying the properties of the post. If no type is specified, the default type [h-entry] SHOULD be used. Clients and servers MUST support creating posts using the x-www-form-urlencoded encoding, and MAY also support creating posts using the JSON syntax.
h={Microformats object type}
e.g., h=entry
All parameters not beginning with "mp-" are properties of the object being created.
e.g., content=hello+world
To specify multiple values for a property, such as multiple categories of an h-entry, use array bracket notation for the property name.
e.g., category[]=foo&category[]=bar
Properties that accept multiple values MUST also accept a single value as a string. A complete example of a form-encoded request follows.
h=entry&content=hello+world&category[]=foo&category[]=bar
To upload files, format the whole request as multipart/form-data and send the file(s) as a standard property.
For example, to upload a photo with a caption, send a request that contains three parts, named h
, content
and photo
.
multipart/form-data; boundary=553d9cee2030456a81931fb708ece92c --553d9cee2030456a81931fb708ece92c Content-Disposition: form-data; name="h" entry --553d9cee2030456a81931fb708ece92c Content-Disposition: form-data; name="content" Hello World! --553d9cee2030456a81931fb708ece92c Content-Disposition: form-data; name="photo"; filename="aaronpk.png" Content-Type: image/png Content-Transfer-Encoding: binary ... (binary data) ... --553d9cee2030456a81931fb708ece92c--
Alternately, you can create a post with JSON syntax by sending the entry in the parsed Microformats 2 JSON format. However, in this case, you cannot also send a file.
{ "type": ["h-entry"], "properties": { "content": ["hello world"], "category": ["foo","bar"] } }
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.
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 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.
The example below creates a new "weight" measurement post as an h-entry with a h-measure objects to describe the weight and bodyfat values.
h=entry &summary=Weighed+155.73+pounds &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]=%
{ "type": ["h-entry"], "properties": { "summary": [ "Weight 155.73 pounds" ], "weight": [ { "type": "h-measure", "properties": { "num": ["155.73"], "unit": ["lb"] } } ], "bodyfat": [ { "type": "h-measure", "properties": { "num": ["19.83"], "unit": ["%"] } } ] } }
If the request includes properties that the server does not recognize, it SHOULD create the post anyway with any values that are recognized, and SHOULD store the unrecognized values internally, and return them when queried.
This allows clients to post rich types of content to servers that recognize it, while also posting fallback content to servers that don't.
When the post is created, the Micropub endpoint MUST return either
an HTTP 201 Created
status code or HTTP 202 Accepted
code, and MUST return a Location
header indicating the
URL of the created post. [RFC2616]
If the target also provides a shortlink, or if it syndicated the post to another location, the Micropub endpoint MAY return additional URLs using the HTTP Link header, along with an appropriate "rel" value. For example, it can return the short URL of a post by responding with:
Link: <http://aaron.pk/xxxxx>; rel="shortlink"or can include the location of the syndicated post with:
Link: <https://https://myfavoritesocialnetwork.example/aaronpk/xxxxxx>; rel="syndication"
If the endpoint chooses to process the request asynchronously rather
than creating and storing the post immediately, it MUST return an
HTTP 202 Accepted
status code, and MUST also return
the Location
header in this case. If the server is
going to return 202, it MUST ensure the object will be created
successfully prior to returning 202, as clients will expect the
object at the indicated URL to exist at some point in the (near)
future. In other words, the server must do any error checking
and validation before returning 202.
See the "Error Responses" section below for details on how to indicate an error occurred.
This section does not currently have interoperable implementations on both the server and client side, and therefore may change significantly once more implementation experience is gathered.
Micropub servers SHOULD support updating posts, including adding and removing individual properties as described in this section.
Updating entries can be done with either a JSON post or form-encoded post. The syntax of the update request is the same in both cases, using the array bracket notation when encoding in form-encoded format.
To update an entry, send mp-action=update
and specify the
URL of the entry that is being updated using the "url" property.
The request MUST also include either a replace
,
add
or delete
property containing the updates to make.
Replace all values of the property. If the property does not exist already, it is created.
mp-action=update &url=http://example.com/post/1 &replace[content]=hello+moon
{ "mp-action": "update", "url": "http://example.com/post/1", "replace": { "content": ["hello moon"] } }
This will replace the entire entry content with the new text.
If there are any existing values for this property, they are not changed, the new values are added. If the property does not exist already, it is created.
Use case: adding a syndication link to a post after it has been published. For example, when a client supports posting first then syndicating to MyFavoriteSocialNetwork or Wikimedia after the fact, the site needs a way to update the original post with the new syndication URL.
To add syndication URLs, include one or more URLs in the update request.
mp-action=update &url=http://aaronpk.example/notes/2014/06/01/2/indieweb &add[syndication][]=https://archive.org/example
{ "mp-action": "update", "url": "http://aaronparecki.com/notes/2014/06/01/2/indieweb", "add": { "syndication": ["https://archive.org/"] } }
Use case: adding tags to a post after it's been created.
To add multiple values to a property (such as category), use array notation to specify the multiple values.
mp-action=update &url=http://aaronpk.example/notes/2014/06/01/2/indieweb &add[category][]=webmention &add[category][]=indieweb
{ "mp-action": "update", "url": "http://aaronpk.example/notes/2014/06/01/2/indieweb", "add": { "category": ["webmention","indieweb"] } }
If the property exists, remove it. This completely removes the specified property.
mp-action=update &url=http://example.com/post/1 &delete=category
{ "mp-action": "update", "url": "http://example.com/post/1", "delete": ["category"] }
For properties with multiple values, such as categories, you can remove individual entries by value. If no values remain, the property is removed.
mp-action=update &url=http://example.com/post/1 &delete[category]=indieweb
{ "mp-action": "update", "url": "http://example.com/post/1", "delete": { "category": ["indieweb"] } }
The server MUST respond to successful update requests with HTTP 200, 201 or 204. If the update operation caused the URL of the post to change, the server MUST respond with HTTP 201 and include the new URL in the HTTP Location
header. Otherwise, the server MUST respond with 200 or 204, depending on whether the response body has content. No body is required in the response, but the response MAY contain a JSON object describing the changes that were made.
Micropub servers SHOULD support deleting posts, and MAY support undeleting posts.
To delete an entire entry at a URL, send a POST request containing
mp-action=delete
and the URL of the item in the
url
property.
mp-action=delete &url=http://example.com/post/1
{ "mp-action": "delete", "url": "http://example.com/post/1" }
To undelete a post, use "undelete" as the action.
mp-action=undelete &url=http://example.com/post/1
{ "mp-action": "undelete", "url": "http://example.com/post/1" }
This section does not currently have interoperable implementations on both the server and client side, and therefore may change significantly once more implementation experience is gathered.
Micropub clients may need to query the Micropub endpoint to discover its capabilities, such as finding a list of syndication targets that it displays to the user, or retrieving the source of a post to display in the updating interface.
To query, make a GET
request to the Micropub endpoint and use the
q
parameter to specify what you are querying.
Note: The Micropub endpoint may include a query string such as ?micropub=endpoint
,
so in this case, Micropub clients MUST append the q
parameter
instead of replacing the query string.
A Micropub client can query the endpoint to return specific properties of a post. This allows a client to request only the properties it needs or knows about, supporting such uses as making an interface to add tags to a post.
To query, make a GET
request to the Micropub endpoint and set the q
parameter to source
, and include the URL of the post in the url
parameter. The query can specify the list of properties being requested by setting one or more values for the properties
key. If more than one is specified, use array bracket notation for each name, according to [HTML5] URL encoding.
The endpoint MUST return the response in [Microformats2] [JSON] format, with an object named properties
, where the keys are the names of the properties requested. If no properties are specified, then the response MUST include all properties, as well as a type
property indicating the vocabulary of the post.
GET /micropub?q=source&properties[]=published&properties[]=category&url=http://aaronpk.example/post/1000 Authorization: Bearer xxxxxxxxx { "properties": { "published": ["2016-02-21T12:50:53-08:00"], "category": [ "foo", "bar" ] } }
GET /micropub?q=source&url=http://aaronpk.example/post/1000 Authorization: Bearer xxxxxxxxx { "type": "h-entry", "properties": { "published": ["2016-02-21T12:50:53-08:00"], "content": ["Hello World"], "category": [ "foo", "bar" ] } }
If the source of the post was written as HTML content, then the endpoint MUST return the content
property as an object containing an html
property. Otherwise, the endpoint MUST return a string value for the content
property, and the client will treat the value as plain text. This matches the behavior of the values of properties in [Microformats2].
Below is an example of requesting the content of a post which was authored as HTML.
GET /micropub?q=source&properties=content&url=http://aaronpk.example/post/1000 Authorization: Bearer xxxxxxxxx { "properties": { "content": [ { "html": "<b>Hello</b> <i>World</i>" } ] } }
At a minimum, a syndication destination MUST have uid
and name
properties. The uid
property is opaque to the client, and is the value the client sends in the Micropub request to indicate the targets to syndicate to. The name
property is the value the client can display to the user. The name should be unambiguously descriptive of the destination, so that if for example there are two destinations on the same service, the name can disambiguate them.
The Micropub server MAY also include additional information about the destination service and user account. This is accomplished with the additional properties service
and user
, both of which can have three properties, name
(a human-readable name), url
and photo
(both URLs).
The client may use the service and user properties to enhance the display of the syndication options, for example by including the user or service photos on the syndication buttons.
If there was an error with the request, the endpoint MUST return an appropriate HTTP status code, typically 400, 401, or 403, and MAY include a description of the error. If an error body is returned, the response body MUST be encoded as a [JSON] object and include at least a single property named error
with the value set to one of the below:
forbidden
- The authenticated user does not have permission to perform this requestinsufficient_scope
- The scope of this token does not meet the requirements for this request. The client may wish to re-authorize the user to obtain the necessary scope. The response MAY include the "scope" attribute with the scope necessary to successfully perform this request.invalid_request
- The request is missing a required parameter, or there was a problem with a value of one of the parametersnot_found
- The post with the requested URL was not foundThe response body MAY also contain an error_description
property with a human-readable description of the error message, used to assist the client developer in understanding the error. This is not meant to be shown to the end user.
See the OAuth 2 Bearer Token [RFC6750] spec for more details on the how to return error responses.
GET /micropub?q=source&url=http://aaronpk.example/post/404 Authorization: Bearer xxxxxxxx HTTP/1.1 400 Bad Request Content-type: application/json { "error": "not_found", "error_description": "The post with the requested URL was not found" }
The vocabularies used in Micropub requests SHOULD be the vocabularies defined by [Microformats2] version 2. If the Microformats2 vocabulary is used, clients and servers MUST support at least the [h-entry] vocabulary. Other vocabularies with widespread usage include [h-event] and [h-card]. When creating objects, the vocabulary of the object is indicated in the parameter h
, or type
in the JSON syntax. If no type is provided, the server SHOULD assume a default value of entry
.
This section is non-normative.
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:
h=entry
h=card
h=event
h=cite
The following properties may be included in a request to create a new [h-entry]:
Posting a new note with tags, syndicating to myfavoritesocialnetwork:
POST /micropub HTTP/1.1 Host: aaronpk.example Authorization: Bearer XXXXXXXXXXX Content-type: application/x-www-form-urlencoded h=entry &content=My+favorite+of+the+%23quantifiedself+trackers%2C+finally+released+their+official+API &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 note with tags, syndicating to myfavoritesocialnetwork:
POST /micropub HTTP/1.1 Host: aaronpk.example Authorization: Bearer XXXXXXXXXXX Content-type: application/x-www-form-urlencoded h=entry &content=%40BarnabyWalters+My+favorite+for+that+use+case+is+Redis. &in-reply-to=http://waterpigs.example/notes/4S0LMw/ &mp-syndicate-to=https://myfavoritesocialnetwork.example/aaronpk
Posting a new repost, and adding additional tags.
POST /micropub HTTP/1.1 Host: aaronpk.example Authorization: Bearer XXXXXXXXXXX Content-type: application/x-www-form-urlencoded h=entry &repost-of=http://waterpigs.example/notes/4S0LMw/ &category=realtime
Posting a new article with HTML content. Note that in this case, the content
property is actually sent as an object containing the key html
. This corresponds with the Microformats 2 syntax for indicating the parsed value contains HTML.
POST /micropub HTTP/1.1 Host: aaronparecki.com Content-type: application/x-www-form-urlencoded h=entry &name=Itching%3A+h-event+to+iCal+converter &content[html]=Now+that+I%27ve+been+%3Ca+href%3D%22http%3A%2F%2Faaronparecki.com%22%3Ecreating+a+list+of+events%3C%2Fa%3E +on+my+site+it+would+be+great+if+I+could+get+a+more+calendar-like+view+of+that+list... &category[]=indieweb&category[]=hevent&category[]=events &category[]=calendar&category[]=p3k
When a Micropub request includes a file, the entire request is
sent in multipart form-data
encoding, and the file is named according to the property it corresponds with in the vocabulary, either audio
, video
or photo
. A request MAY include one or more of these files.
For example, a service may post a video in the video
property as well as a single frame preview of the video in the photo
property.
In PHP, these files are accessible using the $_FILES array:
$_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 Micropub endpoint may store the file directly, or make an external request to upload it to a different backend storage, such as Amazon S3.
This section is non-normative.
This section is non-normative.
Note: Many of the services below are also open source Micropub clients.
The editor wishes to thank the IndieWebCamp community and other implementers for their support, encouragement and enthusiasm.
This section is non-normative.
This section lists changes from the 01 March 2016 FPWD to this Working Draft
properties
key in updatessyndicate-to
response to include more details of the destinationThis section lists changes from the 28 January 2016 FPWD to this Working Draft