Create a movie

Story

As an API client I want to create a new movie resource

Several possibilities exist, to define operations with Hydra. In this example we will describe a custom type mov:Movies in the API documenation and add a supported operation there.

API behaviour

GET https://hydra-movies.herokuapp.com/

Response body (excerpt):

{
  "@id": "/",
  "collection": {
    "@id": "movies",
    "@type": [
      "Collection",
      "mov:Movies"
    ]
  }
}

Api documentation (excerpt):

{
  "@id": "/doc",
  "supportedClass": [
    {
      "@id": "mov:Movies",
      "@type": "Class",
      "supportedOperation": {
        "@id": "mov:create-movie",
        "@type": [
          "Operation",
          "schema:CreateAction"
        ],
        "title": "Create movie",
        "description": "Creates a new movie",
        "method": "POST",
        "expects": "schema:Movie",
        "returns": "schema:Movie"
      }
    },
    {
      "@id": "schema:Movie",
      "@type": "Class",
      "title": "Movie",
      "description": "A single movie",
      "supportedProperty": [
        {
          "property": "schema:name",
          "title": "name",
          "description": "The movie's name"
        },
        {
          "property": "schema:description",
          "title": "description",
          "description": "Textual description of the movie."
        },
        {
          "property": "schema:duration",
          "title": "duration",
          "description": "The movie's duration in ISO 8601 date format."
        }
      ]
    }
  ]
}
POST https://hydra-movies.herokuapp.com/movies
Content-Type: application/ld+json

{
  "@context": "https://schema.org/",
  "@type": "Movie",
  "name": "Pulp Fiction",
  "description": "Pulp Fiction is a 1994 American crime film. It tells several stories of criminal Los Angeles.",
  "duration": "PT2H34M"
}

Response (excerpt):

HTTP/1.1 201 Created
Location: /movies/d517cae6-6cdc-11e9-a923-1681be663d3e
Content-Type: application/ld+json

{
  "@context": "https://hydra-movies.herokuapp.com/context.jsonld",
  "@type": "schema:Movie",
  "@id": "/movies/d517cae6-6cdc-11e9-a923-1681be663d3e",
  "schema:name": "Pulp Fiction"
}

Explanation

"collection": {
    "@id": "movies",
    "@type": [
      "Collection",
      "mov:Movies"
    ]
  }

By loading the API entry point a client came across a resource of type mov:Movies. This API includes does not include any inline hypermedia controls within the resource representation, so the client has to consult the API documentation to understand what the resource is capable of.

"supportedClass": [
  {
    "@id": "mov:Movies",
    "@type": "Class",

The type can be found within supportedClass.

"supportedOperation": {
  "@id": "mov:create-movie",
  "@type": [
    "Operation",
    "schema:CreateAction"
  ],
  "title": "Create movie",
  "description": "Creates a new movie",

The supportedOperation of mov:Movies describe what can be done on resources of that type. Operation is the hydra type for any API operation. By adding schema:CreateAction we can be more precise and define it as an operation that creates new resources. title and description allow a friendly human-readable output in generated developer documentation and generic clients.

"method": "POST",
"expects": "schema:Movie",
"returns": "schema:Movie"

The method is exactly telling the client, that it should use the HTTP POST verb to use this operation. expects and returns specify which types the operation expects as input and returns in response.

{
    "@id": "schema:Movie",
    "@type": "Class",
    "title": "Movie",
    "description": "A single movie",

This type is also present in the API documentation as a supportedClass. Again title and description give some info for humans.

"supportedProperty": [
  {
    "property": "schema:name",
    "title": "name",
    "description": "The movie's name"
  },

To construct an HTTP request the client needs to know which properties are supported by the expected type schema:Movie. The API documentation contains this information in supportedProperty. The client now is aware that it can send schema:name, schema:description and schema:duration.

It is also possible to describe which properties are required, readable and writable. Further a property could define a range to clarify data type and cardinality. Those features will be addressed in another recipe.

POST https://hydra-movies.herokuapp.com/movies
Content-Type: application/ld+json

{
  "@context": "https://schema.org/",
  "@type": "Movie",
  "name": "Pulp Fiction",
  "description": "Pulp Fiction is a 1994 American crime film. It tells several stories of criminal Los Angeles.",
  "duration": "PT2H34M"
}

With the information about the method and the @id from the mov:Movies resource, the client is able to perform the correct request against the API. In the body it sends the expected type schema:Movie with the properties defined by supportedProperties.

HTTP/1.1 201 Created
Location: /movies/d517cae6-6cdc-11e9-a923-1681be663d3e
Content-Type: application/ld+json

{
  "@context": "https://hydra-movies.herokuapp.com/context.jsonld",
  "@type": "schema:Movie",
  "@id": "/movies/d517cae6-6cdc-11e9-a923-1681be663d3e",
  "schema:name": "Pulp Fiction"
}

The server responds with a 201 status code and a Location header pointing to the new movie resource. It also contains a representation of the new movie in the response body.

As you might have seen, client and server can use different JSON-LD contexts. This is OK, as long as both stick to the semantics described by the API documentation.

results matching ""

    No results matching ""