Microforms is a media type for hypermedia APIs composed of a notation and a set of built-in affordances with familiar concepts borrowed from HTML. It is designed to make your API entrypoints discoverable, explorable and executable by aggregators.
Notation
The JSON notation is designed to intermingle data nodes
{
"a": "text"
}
with hyperdata nodes in a distinguishable manner (visually and programatically) using a convention of surrounding their names with HTML-like <>
s:
{
"<form action='/create.php'>": "hypertext"
}
For example:
{
"type": "Issues",
"description": "The list of issues we are tracking",
"<form name='create' action='/create'>": {
"<input name='title'>": {},
"<input name='description'>": {}
}
}
Built-in affordances
The built-in affordances (along with the notation) are designed to reuse as much as possible from HTML. There are built-in hyperdata element types to help you express your hypertext transitions:
Discovery
By creating a link from your human-readable page to your microforms
<link rel="alternate" href="/api" type="application/microforms+json">
You enable aggregators to learn about a machine-readable alternative version of your human-readable page.
Documentation
Microforms are designed to be self-documented without requiring clients to access any out-of-band information.
What that means is that each microform carries enough human-readable and machine-readable information to enable programmers and machines to make the decisions on how things should be filled to execute a call.
The primary mechanism to make your APIs self-documented is to associate <label> with your <form> and <input> elements.
{
"type": "Issues",
"description": "The list of issues we are tracking",
"<form name='create' action='/create' method='post'>": {
"<label>": "Create new issues",
"<label for='title'>": "The title of the issue",
"<input name='title' required='true'>": {}
"<label for='description'>": "The description of the issue",
"<input name='description' required='true'>": {}
}
}
With <label>s each and every one of your microforms can carry enough inline information to enable clients to make all of the decisions without accessing further information (e.g. off-band human-readable documentation).
Execution
Microforms enable you to programatically execute them with confidence. With microforms, you can:
- programatically autocomplete input.
- programatically validate user input.
- programatically submit the call.
- programatically manage keys.
- programatically manage quotas.
Autocomplete
The input autocomplete field enables clients of microforms to programatically autofill fields in the API requests with contextual data (e.g. personalized data or natural language processing interfaces).
Validation
Microforms validation helps ensure that users or machines fill out the API calls in the correct format, making sure that submitted data will work successfully on the server.
Microforms borrows as much as possible the validation rules from HTML.
Clients validate:
- the presence of
required
inputs - the matching of
pattern
attributes - the
minlength
andmaxlength
of text inputs - the
step
,min
andmax
values of numeric inputs - the pattern matching of
email
inputs
Submission
Microforms submission works like HTML form submissions:
- The
action
attribute defines the URL containing the server-side script that handles the form data. - The
method
attribute defines the HTTP method to be used (e.g. GET or POST). - The
enctype
attribute defines how the form data should be encoded.
If the data passes the validation rules, the data is encoded according to the enctype
attribute and a HTTP request is constructed based on the action
endpoint and the desired HTTP method
to be used.
Key management
In microforms, as opposed to traditional APIs, the client self-generates an API key without prior / offband negotiation with the server (e.g. signing-up and getting manually a API developer key).
The server is responsible for taking that key and applying its own business decisions (e.g. to manage the callers quota).
Clients identify themselves using Bearer tokens
set in the Authorization
header of every microforms request. For example:
Authorization: Bearer AbCdEf123456
TheBearer token
sent by the client identifies an issuer
(e.g. gmail@system.gserviceaccount.com
) which the server can use to apply its own judgement.
If the token doesn’t verify, the service should respond to the request with an HTTP response code 401 (Unauthorized)
.
Bearer Tokens are part of the OAuth V2 standard.
Quota management
Microforms also defines dedicated HTTP headers to enable the server to tell clients when to expect their quotas to expire.
Header | Description |
---|---|
X-RateLimit-Limit |
The maximum number of requests you’re permitted to make per hour. |
X-RateLimit-Remaining |
The number of requests remaining in the current rate limit window. |
X-RateLimit-Reset |
The time at which the current rate limit window resets in UTC epoch seconds. |
For example:
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4999
X-RateLimit-Reset: 1372700873
Backwards compatibility
Microforms is strictly backwards compatible with JSON: every JSON response is a microform response.
When a microforms client requests a microform, its sets optionally application/json
as an interpretable type:
GET /ordinary-json-document.json HTTP/1.1
Host: example.com
Accept: application/microforms+json,application/json,*/*;q=0.1
That enables the server to pick and choose which mime types to generate (e.g. application/microforms+json
or application/json
) and, if it is easier, generate a microform response with applicaton/json
and a reference to the microform document.
HTTP/1.1 200 OK
...
Content-Type: application/json
Link: </ordinary-json-document.microform>;
rel="import";
type="application/microforms+json"
{
"type": "Issues",
"url": "https://github.com/samuelgoto/microforms/issues",
"description": "The list of issues we are tracking"
}
Microforms clients resolve the link to fetch the microform (caching it across multiple requests, as specified by HTTP headers).
{
"<form name='create' action='/create' method='post'>": {
"<label>": "Create new issues",
"<label for='title'>": "The title of the issue",
"<input name='title' required='true'>": {}
"<label for='description'>": "The description of the issue",
"<input name='description' required='true'>": {}
}
}
Doing so, allows your API to gather the benefits of microforms without requiring developers to drastically change their documents and provides an incremental upgrade path for existing infrastructure without breaking existing clients that rely on your current API.
Extensibility
It is critical that microforms can be extended by users without having to be recompiled / redesigned / reformulated. Specifically, it is critical that new affordances can be created without any permission required.
Being a XML-based formulation, microforms borrows the XML namespace mechanism to provide the same extensibility model. You can use the reserved xmlns
attribute or the xmlns:prefix
attribute to allow declaration of nodes in an external namespace.
{
"@context": "https://schema.org/",
"@type": "Restaurant",
"name": "Sam's restaurant",
"<form action='reservations.php' method='post'>": {
"xmlns": "http://example.com/",
"<contact name='Sam' email='foobar@hello.com'>": {},
"<terms>": "By using this api you agree to our terms of service."
}
}
Related Work
Microforms is a hypermedia API media type, so it is directly related to the following approaches:
- Hydra
- Siren
- HAL
- Swagger
An overview of each is compiled here.
Microforms offers a novel approach in the following dimensions:
- Notation
- Re-use of HTML
- Crawler-oriented
TODO(goto): go over each of these.