Skip to content

Latest commit

 

History

History
269 lines (169 loc) · 10.7 KB

README.md

File metadata and controls

269 lines (169 loc) · 10.7 KB

#Siren: a hypermedia specification for representing entities

Current version: 0.6.1

Your input is appreciated. Feel free to file a GitHub Issue, a Pull Request, or contact us. Thank you!

##Example

Below is a JSON Siren example of an order, including sub-entities. The first sub-entity, a collection of items associated with the order, is an embedded link. Clients may choose to automatically resolve linked sub-entities. The second sub-entity is an embedded representation of customer information associated with the order. The example also includes an action to add items to the order and a set of links to navigate through a list of orders.

The media type for JSON Siren is application/vnd.siren+json.

{
  "class": [ "order" ],
  "properties": { 
      "orderNumber": 42, 
      "itemCount": 3,
      "status": "pending"
  },
  "entities": [
    { 
      "class": [ "items", "collection" ], 
      "rel": [ "http://x.io/rels/order-items" ], 
      "href": "http://api.x.io/orders/42/items"
    },
    {
      "class": [ "info", "customer" ],
      "rel": [ "http://x.io/rels/customer" ], 
      "properties": { 
        "customerId": "pj123",
        "name": "Peter Joseph"
      },
      "links": [
        { "rel": [ "self" ], "href": "http://api.x.io/customers/pj123" }
      ]
    }
  ],
  "actions": [
    {
      "name": "add-item",
      "title": "Add Item",
      "method": "POST",
      "href": "http://api.x.io/orders/42/items",
      "type": "application/x-www-form-urlencoded",
      "fields": [
        { "name": "orderNumber", "type": "hidden", "value": "42" },
        { "name": "productCode", "type": "text" },
        { "name": "quantity", "type": "number" }
      ]
    }
  ],
  "links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]
}

##Introduction

Siren is a hypermedia specification for representing entities. As HTML is used for visually representing documents on a Web site, Siren is a specification for presenting entities via a Web API. Siren offers structures to communicate information about entities, actions for executing state transitions, and links for client navigation.

Siren is intended to be a general specification of a generic media type that can be applied to other types that are not inherently hypermedia-powered. The initial implementation is JSON Siren. Other implementations, such as XML Siren, may also be implemented using the Siren specification.

All examples in this document are in the JSON Siren format.

##Entities

An Entity is a URI-addressable resource that has properties and actions associated with it. It may contain sub-entities and navigational links.

Root entities and sub-entities that are embedded representations SHOULD contain a links collection with at least one item contain a rel value of self and an href attribute with a value of the entity's URI.

Sub-entities that are embedded links MUST contain an href attribute with a value of its URI.

###Entity

####class

Describes the nature of an entity's content based on the current representation. Possible values are implementation-dependent and should be documented. MUST be an array of strings. Optional.

####properties

A set of key-value pairs that describe the state of an entity. In JSON Siren, this is an object such as { "name": "Kevin", "age": 30 }. Optional.

####entities

A collection of related sub-entities. If a sub-entity contains an href value, it should be treated as an embedded link. Clients may choose to optimistically load embedded links. If no href value exists, the sub-entity is an embedded entity representation that contains all the characteristics of a typical entity. One difference is that a sub-entity MUST contain a rel attribute to describe its relationship to the parent entity.

In JSON Siren, this is represented as an array. Optional.

####links

A collection of items that describe navigational links, distinct from entity relationships. Link items should contain a rel attribute to describe the relationship and an href attribute to point to the target URI. Entities should include a link rel to self. In JSON Siren, this is represented as "links": [{ "rel": ["self"], "href": "http://api.x.io/orders/1234" }] Optional.

####actions

A collection of action objects, represented in JSON Siren as an array such as { "actions": [{ ... }] }. See Actions. Optional

####title Descriptive text about the entity. Optional.

###Sub-Entities

Sub-entities can be expressed as either an embedded link or an embedded representation. In JSON Siren, sub-entities are represented by an entities array, such as { "entities": [{ ... }] }.

####Embedded Link

A sub-entity that's an embedded link may contain the following:

#####class

Describes the nature of an entity's content based on the current representation. Possible values are implementation-dependent and should be documented. MUST be an array of strings. Optional.

#####rel

Defines the relationship of the sub-entity to its parent, per Web Linking (RFC5899). MUST be an array of strings. Required.

#####href

The URI of the linked sub-entity. Required.

#####type

Defines media type of the linked sub-entity, per Web Linking (RFC5899). Optional.

#####title Descriptive text about the entity. Optional.

####Embedded Representation

Embedded sub-entity representations retain all the characteristics of a standard entity, but MUST also contain a rel attribute describing the relationship of the sub-entity to its parent.

###Classes vs. Relationships

It's important to note the distinction between link relations and classes. Link relations define a relationship between two resources. Classes define a classification of the nature of the element, be it an entity or an action, in its current representation.

###Sub-Entities vs Links

Another distinction is the difference between sub-entities and links. Sub-entities exist to communicate a relationship between entities, in context. Links are primarily navigational and communicate ways clients can navigate outside the entity graph.

##Links

Links represent navigational transitions. In JSON Siren, links are represented as an array inside the entity, such as { "links": [{ "rel": [ "self" ], "href": "http://api.x.io/orders/42"}] }

Links may contain the following attributes:

###rel

Defines the relationship of the link to its entity, per Web Linking (RFC5988). MUST be an array of strings. Required.

###class

Describes aspects of the link based on the current representation. Possible values are implementation-dependent and should be documented. MUST be an array of strings. Optional.

###href

The URI of the linked resource. Required.

###title

Text describing the nature of a link. Optional.

###type

Defines media type of the linked resource, per Web Linking (RFC5988). Optional.

##Actions

Actions show available behaviors an entity exposes.

###name

A string that identifies the action to be performed. Action names MUST be unique within the set of actions for an entity. The behaviour of clients when parsing a Siren document that violates this constraint is undefined. Required.

###class

Describes the nature of an action based on the current representation. Possible values are implementation-dependent and should be documented. MUST be an array of strings. Optional.

###method

An enumerated attribute mapping to a protocol method. For HTTP, these values may be GET, PUT, POST, DELETE, or PATCH. As new methods are introduced, this list can be extended. If this attribute is omitted, GET should be assumed. Optional.

###href

The URI of the action. Required.

###title

Descriptive text about the action. Optional.

type

The encoding type for the request. When omitted and the fields attribute exists, the default value is application/x-www-form-urlencoded. Optional.

fields

A collection of fields, expressed as an array of objects in JSON Siren such as { "fields" : [{ ... }] }. See Fields. Optional.

###Fields

Fields represent controls inside of actions. They may contain these attributes:

####name

A name describing the control. Field names MUST be unique within the set of fields for an action. The behaviour of clients when parsing a Siren document that violates this constraint is undefined.

When a request body contains a nested object, this object must be described using dot-seperated field names. To clarify this, take the following action to add an order-line as an example:

"actions": [{
	"name": "add-order-line",
	"title": "Add Order Line",
	"method": "POST",
	"type": "application/json",
	"fields": [
		{ "name": "price.amount", "type": "number"},
		{ "name": "price.currency", "type": "text"},
		{ "name": "quantity", "type": "number"}
	]
}]

The dot-seperated field names correspond with the following request body:

{
	"price": {
		"amount" : 123.4,
		"currency": "EUR"
	},
	"quantity": 2
}

Required.

###class

Describes aspects of the field based on the current representation. Possible values are implementation-dependent and should be documented. MUST be an array of strings. Optional.

####type

The input type of the field. This may include any of the following input types specified in HTML5:

hidden, text, search, tel, url, email, password, datetime, date, month, week, time, datetime-local, number, range, color, checkbox, radio, file

When missing, the default value is text. Serialization of these fields will depend on the value of the action's type attribute. See type under Actions, above. Optional.

####value

A value assigned to the field. Optional.

####title

Textual annotation of a field. Clients may use this as a label. Optional.

##Usage Considerations

Siren supports a resource design style that doesn't have to be primarily CRUD-based. A root entity may take ownership of facilitating changes to sub-entities via actions. Using Siren allows you to easily provide a task-based interface through your Web API.

Feedback

Siren is still a work in progress looking for some real world usage and feedback. Please contribute! Feel free to use GitHub Issues to make suggestions or fire up a Pull Request with changes to be reviewed. Thank you!