The Micropub syntax describes how to interpret HTTP POST and GET requests into useful server actions.
3.1 Overview
All Micropub requests to create posts are sent as UTF-8
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.
3.1.1 Form-Encoded and Multipart Requests
For x-www-form-urlencoded and multipart/form-data requests, Micropub supports an extension of the standard URL encoding that includes explicit indicators of multi-valued properties. Specifically, this means in order to send multiple values for a given property, you MUST append square brackets [] to the property name.
For example, to specify multiple values for the property "category", the request would include category[]=foo&category[]=bar.
On the server side, it is expected that the server will convert this to an internal representation of an array. For example, the equivalent JSON representation of this would be:
{
"category": [
"foo",
"bar"
]
}
This works equally well in multipart requests, where each value is given in a separate "part" of the request, and the name is given in a line such as Content-Disposition: form-data; name="category[]".
Note that the extent of the extensions to the x-www-form-urlencoded syntax is the addition of the square brackets to indicate an array. Syntax such as foo[0] and foo[bar] is not supported, and so clients are expected to use the JSON syntax when posting more complex objects.
3.3 Create
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 syntax, 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, append square brackets to the property name, indicating it is an array.
e.g., category[]=foo&category[]=bar
Properties that accept multiple values MUST also accept a single value, with or without the square brackets. A complete example of a form-encoded request follows.
Example 1
h=entry&content=hello+world&category[]=foo&category[]=bar
3.3.1 Uploading Files
To upload files, the client MUST check for the presence of a Media Endpoint. If there is no Media Endpoint, the client can assume that the Micropub endpoint accepts files directly, and can send the request to it directly. To upload a file to the Micropub endpoint, 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.
Example 2
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--
For properties that can accept a file upload (such as photo or video), the Micropub endpoint MUST also accept a URL value, treating that the same as if the file had been uploaded directly. The endpoint MAY download [Fetch] a copy of the file at the URL and store it the same way it would store the file if it had been uploaded directly. For example:
Example 3
h=entry&content=hello+world&photo=https%3A%2F%2Fphotos.example.com%2F592829482876343254.jpg
This is to support uploading files via a Media Endpoint, or by reference to other external images. See the Media Endpoint section for more information.
3.3.2 JSON Syntax
In order to support more complex values of properties, you can create a post with JSON syntax by sending the entry in the parsed Microformats 2 JSON format.
Note that in this case, you cannot also upload a file, you can only reference files by URL as described above.
When creating posts in JSON format, all values MUST be specified as arrays, even if there is only one value, identical to the Microformats 2 JSON format. This request is sent with a content type of application/json.
Example 4
POST /micropub HTTP/1.1 Host: aaronpk.example Content-type: application/json { "type": ["h-entry"], "properties": { "content": ["hello world"], "category": ["foo","bar"], "photo": ["https://photos.example.com/592829482876343254.jpg"] } }
Uploading a photo with alt text
To include alt text along with the image being uploaded, you can use the Microformats 2 syntax to specify both the image URL and alt text for the photo property. Instead of the value being simply a URL, the value is instead an object with two properties: value being the URL and alt being the text. Note that because the value of photo needs to be an object, we can't use form-encoded or multipart requests for this. Instead, we have to first upload the photo to the media endpoint, then reference the URL in a JSON request, as illustrated below.
Example 5
POST /micropub HTTP/1.1 Host: aaronpk.example Content-type: application/json { "type": ["h-entry"], "properties": { "content": ["hello world"], "category": ["foo","bar"], "photo": [ { "value": "https://photos.example.com/globe.gif", "alt": "Spinning globe animation" } ] } }
Warning
The specific method described here of specifying alt text was added with the assumption that the Microformats 2 proposal for how to represent image alt text (issue 2) will be incorporated. If the referenced issue is resolved a different way, the Micropub spec should be adjusted accordingly.
3.3.3 Nested Microformats 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.
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.
Nested objects require that the request be sent in JSON format, since the form-encoding syntax does not consistently support nested objects.
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.
Example 6
{
"type": ["h-entry"],
"properties": {
"summary": [
"Weighed 70.64 kg"
],
"weight": [
{
"type": ["h-measure"],
"properties": {
"num": ["70.64"],
"unit": ["kg"]
}
}
],
"bodyfat": [
{
"type": ["h-measure"],
"properties": {
"num": ["19.83"],
"unit": ["%"]
}
}
]
}
}
3.3.4 Bidirectional Text
Natural language values in Micropub requests MAY contain bidirectional text. The default base direction of Micropub text values is left-to-right. The base direction of individual natural language values MAY be modified as described below.
When specifying bidirectional text for a natural language value, and the base direction of the text cannot be correctly identified by the first strong directional character of that text ([BIDI]), publishing clients SHOULD explicitly identify the default direction either by prefixing the value with an appropriate Unicode bidirectional control character, or by using HTML directional markup for HTML values.
Micropub servers that accept natural language values that contain bidirectional text SHOULD identify the base direction of any given natural language value by either: for plaintext values, scanning the text for the first strong directional character; or for HTML values, by utilizing directional markup, if available, or otherwise scanning for the first strong directional character not contained in a markup tag. When displaying these natural language values, the server MUST determine the appropriate rendering of the content according to the [BIDI] algorithm, which may necessitate wrapping additional control characters or markup around the string prior to display, in order to apply the base direction.
3.3.5 Unrecognized Properties
If the request includes properties that the server does not recognize, it MUST ignore unrecognized properties and create the post with the values that are recognized.
This allows clients to post rich types of content to servers that support it, while also posting fallback content to servers that don't.
For example, a client may create a post that contains a weight measurement, with an h-measure value for the weight property, and a plaintext summary of the post in the summary property. Servers that don't recognize the weight property will simply ignore it, and will create the post as a plaintext post with the summary instead.
3.3.6 Response
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]
Example 7
HTTP/1.1 201 Created Location: https://aaronpk.example/post/1000
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. The server MUST do any error checking and validation of the request synchronously in order to ensure the object will be created successfully, prior to returning HTTP 202. Clients will expect the object at the indicated URL to exist at some point in the (near) future if they receive an HTTP 202 response.
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://myfavoritesocialnetwork.example/aaronpk/xxxxxx>; rel="syndication"
Error Response
See the "Error Response" section below for details on how to indicate an error occurred.
3.4 Update
Micropub servers SHOULD support updating posts, including adding and removing individual properties as described in this section.
Updating entries is done with a JSON post describing the changes to make.
To update an entry, send "action": "update" and specify the URL of the entry that is being updated using the "url" property. The request MUST also include a replace,
add or delete property (or any combination of these) containing the updates to make.
The values of each property inside the replace, add or delete keys MUST be an array, even if there is only a single value.
3.4.1 Replace
Replace all values of the property. If the property does not exist already, it is created.
Example 8
{
"action": "update",
"url": "https://aaronpk.example/post/100",
"replace": {
"content": ["hello moon"]
}
}
This will replace the entire entry content with the new text.
3.4.2 Add
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.
Adding a syndication URL
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.
Example 9
{
"action": "update",
"url": "https://aaronpk.example/2014/06/01/9/indieweb",
"add": {
"syndication": ["http://web.archive.org/web/20040104110725/https://aaronpk.example/2014/06/01/9/indieweb"]
}
}
Use case: adding tags to a post after it's been created.
To add multiple values to a property (such as category), provide the new values in an array.
Example 10
{
"action": "update",
"url": "https://aaronpk.example/2014/06/01/9/indieweb",
"add": {
"category": ["micropub","indieweb"]
}
}
3.4.3 Remove
If the property exists, remove it. This completely removes the specified property.
Example 11
{
"action": "update",
"url": "https://aaronpk.example/2014/06/01/9/indieweb",
"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.
Example 12
{
"action": "update",
"url": "https://aaronpk.example/2014/06/01/9/indieweb",
"delete": {
"category": ["indieweb"]
}
}
3.4.4 Response
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.
3.7 Querying
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 URL 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.
3.7.1 Configuration
When a user initially logs in to a Micropub client, the client will want to query some initial information about the user's endpoint. The client SHOULD make a query request q=config to obtain initial configuration information.
The server SHOULD include the following information in the configuration response.
- The list of syndication endpoints supported, in a property called
syndicate-to(see Syndication Targets for details on the structure of the response) - The Media Endpoint if supported, in a property called
media-endpoint
Example 20
GET /micropub?q=config Authorization: Bearer xxxxxxxxx Accept: application/json HTTP/1.1 200 OK Content-type: application/json { "media-endpoint": "https://media.example.com/micropub", "syndicate-to": [ { "uid": "https://myfavoritesocialnetwork.example/aaronpk", "name": "aaronpk on myfavoritesocialnetwork", "service": { "name": "My Favorite Social Network", "url": "https://myfavoritesocialnetwork.example/", "photo": "https://myfavoritesocialnetwork.example/img/icon.png" }, "user": { "name": "aaronpk", "url": "https://myfavoritesocialnetwork.example/aaronpk", "photo": "https://myfavoritesocialnetwork.example/aaronpk/photo.jpg" } } ] }
Servers SHOULD support the configuration query, and returning all properties relevant to the server. If none of the properties apply to the server, the response SHOULD be an empty JSON object, {}.
Clients SHOULD treat unexpected responses the same as an empty response, in order to handle unexpected responses from servers that don't support this query. For example, a server that does not implement the configuration query at all may return an HTTP 400 response rather than the expected 200 response with an empty JSON object.
3.7.2 Source Content
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.
Servers that support updating posts MUST support the source content query.
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-parsing] [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.
Example 21
GET /micropub?q=source&properties[]=published&properties[]=category&url=https: Authorization: Bearer xxxxxxxxx Accept: application/json HTTP/1.1 200 OK Content-type: application/json { "properties": { "published": ["2016-02-21T12:50:53-08:00"], "category": [ "foo", "bar" ] } }
Example 22
GET /micropub?q=source&url=https: Authorization: Bearer xxxxxxxxx Accept: application/json HTTP/1.1 200 OK Content-type: application/json { "type": ["h-entry"], "properties": { "published": ["2016-02-21T12:50:53-08:00"], "content": ["Hello World"], "category": [ "foo", "bar" ] } }
HTML Content
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-parsing].
Below is an example of requesting the content of a post which was authored as HTML.
Example 23
GET /micropub?q=source&properties=content&url=https: Authorization: Bearer xxxxxxxxx Accept: application/json HTTP/1.1 200 OK Content-type: application/json { "properties": { "content": [ { "html": "<b>Hello</b> <i>World</i>" } ] } }
3.7.3 Syndication Targets
To return a list of supported syndication targets, set the q parameter to syndicate-to.
GET /micropub?q=syndicate-to
The endpoint MUST return the response in [JSON] format, with a key of syndicate-to and the values being objects descriptive of the supported syndication targets. If no endpoints are defined, the value of the syndicate-to object SHOULD be an empty JSON array [].
At a minimum, a syndication target MUST have a uid and human-readable name property. The uid can be any identifier unique to the Micropub endpoint and is not intended to be visible to the end user. The name is intended to be visible to the user in the posting interface, and should be descriptive of the syndication destination.
A syndication target MAY optionally include additional details about the service or user account at the syndication destination, indicated with a property called service and user respectively. Both service and user objects MUST contain a name property, intended to be displayed to the user, and MAY contain a url and photo property. The client can use the name and photo to improve the display of the syndication options to the user.
Example 24
GET /micropub?q=syndicate-to Authorization: Bearer xxxxxxxxx Accept: application/json HTTP/1.1 200 OK Content-type: application/json { "syndicate-to": [ { "uid": "https://archive.org/", "name": "archive.org" }, { "uid": "https://wikimedia.org/", "name": "WikiMedia" }, { "uid": "https://myfavoritesocialnetwork.example/aaronpk", "name": "aaronpk on myfavoritesocialnetwork", "service": { "name": "My Favorite Social Network", "url": "https://myfavoritesocialnetwork.example/", "photo": "https://myfavoritesocialnetwork.example/img/icon.png" }, "user": { "name": "aaronpk", "url": "https://myfavoritesocialnetwork.example/aaronpk", "photo": "https://myfavoritesocialnetwork.example/aaronpk/photo.jpg" } } ] }
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.
Servers that support syndicating posts SHOULD support the syndicate-to query.
3.7.4 Query Extensions
Clients and servers wishing to extend the functionality of the query action are encouraged to brainstorm and document implementations at indieweb.org/Micropub-extensions.