What is Micro API?

Micro API

Micro API is a subset of JSON-LD intended for hypermedia APIs. It includes a vocabulary, and semantics for CRUD operations. As the name implies, it is intended to be concise and generic. Its registered media type is:

Content-Type: application/vnd.micro+json

The current published version is 2016-09-06, and the media type is registered with the IANA.

Introduction #

Micro API simplifies JSON-LD by limiting it to a subset which can be traversed reliably without using processing algorithms. It also provides a minimal vocabulary for basic fields. Example payloads and HTTP requests should be considered non-normative.

The key words MUST, MUST NOT, REQUIRED, SHALL, SHALL NOT, SHOULD, SHOULD NOT, RECOMMENDED, NOT RECOMMENDED, MAY, and OPTIONAL in this specification have the meaning defined in RFC 2119.

Vocabulary #

This section should be considered normative.

There are three sub-categories of the vocabulary: generic fields, ontological fields, and concrete data types.

Generic Fields

PropertyTypeDescription
idString, NumberA unique value used for identifying resources.
metaObjectAny meta-information may be contained here.
queryObjectA container for showing information about the current query.
operateObjectReserved for arbitrary operations to update resources.
errorObjectIf a request fails for any reason, it SHOULD return an error.

Ontological Fields

PropertyTypeDescription
vocabObjectAn enumeration of classes and properties.
descriptionStringDescriptions for classes and properties.
belongsToStringPresence of this field indicates a property. It is valued as an enumeration of types which a property belongs to, including the built-in field definitions meta, query, operate, error.
inverseStringAn inversely related property for a relationship.
isArrayBooleanFor properties, indicates if their values are arrays. Defaults to false.

Data Types

PropertyTypeDescription
TypeTypeA type defines any data structure which contains the same set of properties.
StringTypeAn UTF-8 string.
NumberTypeAn IEEE 754 floating point number.
BooleanTypeA boolean value.
DateTypeAn ISO 8601 date.
BufferTypeA base64-encoded buffer.
ObjectTypeAn object, or arbitrary data structure.

Payload Restrictions #

This section should be considered normative.

In general, the payload should look like the flattened form of JSON-LD, with some additional restrictions:

The entirety of Micro API can be expressed using only a few reserved keywords from JSON-LD: @context, @vocab, @base, @graph, @type, @id, and @reverse.

Entry Point #

The expectation of a Micro API entry point is to enumerate types and properties and provide links to collections. It MUST contain the µ:vocab property, valued as an array of objects.

GET /
{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "µ:vocab": [
    { "@id": "/#name", "@type": "µ:String",
      "µ:belongsTo": [ "Person", "Movie" ] },
    { "@id": "/#actor", "@type": "Person",
      "µ:belongsTo": [ "Movie" ], "µ:isArray": true },
    { "@id": "/#Person", "@type": "µ:Type",
      "µ:description": "A human being." },
    { "@id": "/#Movie", "@type": "µ:Type",
      "µ:description": "A moving picture." }
  ],
  "Person": { "@id": "/people" },
  "Movie": { "@id": "/movies" }
}

The @vocab field of a Micro API MUST be the path to the API suffixed with the # character, so that dereferencing always refers to the entry point.

Finding Resources #

A GET request MAY be allowed on the collection IRI for a particular type.

GET /movies
{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "@graph": [ {
    "@type": "Movie",
    "@id": "/movies/1",
    "µ:id": 1,
    "name": "The Matrix",
    "actor": {
      "@id": "/movies/1/actors",
      "µ:id": [ 1, 2, 3 ]
    }
  } ]
}

Dereferencing an @id MUST return types corresponding to that property.

GET /movies/the-matrix/actors?limit=1
{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "@graph": [ {
    "@type": "Person",
    "@id": "/people/1",
    "µ:id": 1,
    "name": "Keanu Reeves",
    "@reverse": {
      "actor": {
        "@id": "/people/1/acted-in",
        "µ:id": [ 1 ]
      }
    }
  } ]
}

Creating Resources #

Requesting to create an resource MAY be allowed at the collection IRI for that type. The payload MUST be a valid Micro API document, and referenced IDs must be specified using the id property.

POST /people
{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "@graph": [ {
    "@type": "Person",
    "name": "John Doe",
    "@reverse": {
      "actor": {
        "µ:id": [ "memento" ]
      }
    }
  } ]
}

It may be helpful for the response to have a Location header, but it is not required since the response body may include a link to the created resource.

Updating Resources #

IDs MUST be specified in the payload per resource to update, and PATCH requests can be made wherever the resource exists (corollary: IDs can not be changed, only specified).

PATCH /people
{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "@graph": [ {
    "@type": "Person",
    "µ:id": "john-doe",
    "name": "Johnny Doe",
    "@reverse": {
      "actor": {
        "µ:id": [ "point-break" ]
      }
    },
    "µ:operate": {}
  } ]
}

If the a specified resource does not exist at the requested location, it SHOULD return an error. The assumption is that the PATCH method replaces the fields specified. There is a special µ:operate property which allows for arbitrary updates, which this specification is agnostic about. In common update cases, it may be desirable to reject upserts (the PUT method defines that a resource may be created), so PATCH is typically what you want to do.

PATCH requests can update existing resources, however Micro API does not define the semantics to create or delete resources with this method. In this example, by setting a link's µ:id property to null (for a to-one relationship) or [] (empty array for a to-many relationship), it removes the link.

Deleting Resources #

DELETE /people/john-doe

A delete request can return no payload (HTTP 204 No Content) if it succeeds. It can apply to any IRI, including collections.

DELETE /people/john-doe/children

In this example, the request means delete all of the resources at this IRI, not just the link. There is no concept of relationship entities.

Error Response #

If a request fails for any reason, it MUST return a µ:error object. The contents of the error object are opaque to this specification.

{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "µ:error": {
    "name": "NotFoundError",
    "description": "The requested resource was not found."
  }
}

Querying #

Micro API does not specify anything about pagination, filtering, sparse fields, sorting, etc. For example, the µ:query object MAY contain hints on what queries can be appended to GET requests, with further information about the query provided by a vocabulary (optional):

{
  "@context": {
    "@vocab": "http://example.com/#",
    "µ": "http://micro-api.org/"
  },
  "µ:query": {
    "include": [],
    "sort": {},
    "field": {},
    "match": {},
    "limit": 1000,
    "offset": 0,
    "count": 0
  }
}

Unregistered Media Type #

One may use MessagePack instead of JSON as the serialization format for greater bandwidth savings. Since MessagePack is an unregistered media type, the corresponding Micro API media type may be unregistered as well:

Content-Type: application/x-micro-api

It is completely optional to support this unregistered media type, but it should be interpreted as Micro API with MessagePack enabled.

Prior Art #

Micro API builds upon JSON-LD, which is a W3C recommendation. A JSON-based serialization format has the advantage of widespread tooling and developer understanding.

In contrast to Linked Data Platform, it does not use the Turtle format, which is useful only for working within RDF. It also lacks a concept of "containers", which assumes that relationships are hierarchical. What is similar is that both stipulate which actions may be taken on resources.

Micro API is an alternative for Hydra, another specification for Web APIs. It is much less prescriptive than Hydra, and is implicit in cases which Hydra is more explicit. For example, some differences are:

A key difference between Micro API and Hydra is that Micro API does not assume that documentation is machine-processable. Why this matters is that natural language may be the only way to express application logic.

About #

The source for this document is on GitHub. It is licensed under the CC0 1.0 License.