diff --git a/examples.module b/examples.module
index 1f7cd9a..8eb873b 100644
--- a/examples.module
+++ b/examples.module
@@ -56,6 +56,7 @@ function examples_toolbar() {
     'pager_example' => 'pager_example.page',
     'phpunit_example' => 'phpunit_example_description',
     'plugin_type_example' => 'plugin_type_example.description',
+    'rest_example' => 'rest_example.getting_started',
     'simpletest_example' => 'simpletest_example_description',
     'tabledrag_example' => 'tabledrag_example.description',
     'stream_wrapper_example' => 'stream_wrapper_example.description',
diff --git a/rest_example/config/install/node.type.rest_example_test.yml b/rest_example/config/install/node.type.rest_example_test.yml
new file mode 100644
index 0000000..5d8fb9a
--- /dev/null
+++ b/rest_example/config/install/node.type.rest_example_test.yml
@@ -0,0 +1,22 @@
+# Imports a new node type that we use for testing REST. The content that we
+# create, read, update and delete will be of this type.
+langcode: en
+status: true
+dependencies:
+  enforced:
+    module:
+      - node_type_example
+  module:
+    - menu_ui
+third_party_settings:
+  menu_ui:
+    available_menus:
+      - main
+    parent: 'main:'
+name: 'REST Example Test'
+type: rest_example_test
+description: 'This content is created through the REST API'
+help: ''
+new_revision: false
+preview_mode: 0
+display_submitted: true
diff --git a/rest_example/config/install/views.view.rest_service.yml b/rest_example/config/install/views.view.rest_service.yml
new file mode 100644
index 0000000..8eb5893
--- /dev/null
+++ b/rest_example/config/install/views.view.rest_service.yml
@@ -0,0 +1,211 @@
+# This View is used to collect the all the relevant nodes from the system, of
+# the type 'rest_example_test', and print them as json, so that we can use it
+langcode: en
+status: true
+dependencies:
+  config:
+    - node.type.rest_example_test
+  module:
+    - node
+    - rest
+    - serialization
+    - user
+id: rest_service
+label: 'REST Service'
+module: views
+description: ''
+tag: ''
+base_table: node_field_data
+base_field: nid
+core: 8.x
+display:
+  default:
+    display_plugin: default
+    id: default
+    display_title: Master
+    position: 0
+    display_options:
+      access:
+        type: perm
+        options:
+          perm: 'access content'
+      cache:
+        type: tag
+        options: {  }
+      query:
+        type: views_query
+        options:
+          disable_sql_rewrite: false
+          distinct: false
+          replica: false
+          query_comment: ''
+          query_tags: {  }
+      exposed_form:
+        type: basic
+        options:
+          submit_button: Apply
+          reset_button: false
+          reset_button_label: Reset
+          exposed_sorts_label: 'Sort by'
+          expose_sort_order: true
+          sort_asc_label: Asc
+          sort_desc_label: Desc
+      pager:
+        type: mini
+        options:
+          items_per_page: 10
+          offset: 0
+          id: 0
+          total_pages: null
+          expose:
+            items_per_page: false
+            items_per_page_label: 'Items per page'
+            items_per_page_options: '5, 10, 25, 50'
+            items_per_page_options_all: false
+            items_per_page_options_all_label: '- All -'
+            offset: false
+            offset_label: Offset
+          tags:
+            previous: ‹‹
+            next: ››
+      style:
+        type: serializer
+      row:
+        type: fields
+        options:
+          inline: {  }
+          separator: ''
+          hide_empty: false
+          default_field_elements: true
+      fields:
+        title:
+          id: title
+          table: node_field_data
+          field: title
+          entity_type: node
+          entity_field: title
+          label: ''
+          alter:
+            alter_text: false
+            make_link: false
+            absolute: false
+            trim: false
+            word_boundary: false
+            ellipsis: false
+            strip_tags: false
+            html: false
+          hide_empty: false
+          empty_zero: false
+          settings:
+            link_to_entity: true
+          plugin_id: field
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exclude: false
+          element_type: ''
+          element_class: ''
+          element_label_type: ''
+          element_label_class: ''
+          element_label_colon: true
+          element_wrapper_type: ''
+          element_wrapper_class: ''
+          element_default_classes: true
+          empty: ''
+          hide_alter_empty: true
+          click_sort_column: value
+          type: string
+          group_column: value
+          group_columns: {  }
+          group_rows: true
+          delta_limit: 0
+          delta_offset: 0
+          delta_reversed: false
+          delta_first_last: false
+          multi_type: separator
+          separator: ', '
+          field_api_classes: false
+      filters:
+        status:
+          value: '1'
+          table: node_field_data
+          field: status
+          plugin_id: boolean
+          entity_type: node
+          entity_field: status
+          id: status
+          expose:
+            operator: ''
+          group: 1
+        type:
+          id: type
+          table: node_field_data
+          field: type
+          value:
+            rest_example_test: rest_example_test
+          entity_type: node
+          entity_field: type
+          plugin_id: bundle
+      sorts:
+        created:
+          id: created
+          table: node_field_data
+          field: created
+          order: DESC
+          entity_type: node
+          entity_field: created
+          plugin_id: date
+          relationship: none
+          group_type: group
+          admin_label: ''
+          exposed: false
+          expose:
+            label: ''
+          granularity: second
+      header: {  }
+      footer: {  }
+      empty: {  }
+      relationships: {  }
+      arguments: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - request_format
+        - url.query_args
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
+  rest_export_1:
+    display_plugin: rest_export
+    id: rest_export_1
+    display_title: 'REST export'
+    position: 1
+    display_options:
+      display_extenders: {  }
+      path: rest/node
+      pager:
+        type: some
+        options:
+          items_per_page: 10
+          offset: 0
+      style:
+        type: serializer
+        options:
+          grouping: {  }
+          uses_fields: false
+          formats: {  }
+      row:
+        type: data_entity
+        options: {  }
+    cache_metadata:
+      max-age: -1
+      contexts:
+        - 'languages:language_content'
+        - 'languages:language_interface'
+        - request_format
+        - 'user.node_grants:view'
+        - user.permissions
+      tags: {  }
+# in or REST module.
diff --git a/rest_example/rest_example.info.yml b/rest_example/rest_example.info.yml
new file mode 100644
index 0000000..bee4a69
--- /dev/null
+++ b/rest_example/rest_example.info.yml
@@ -0,0 +1,11 @@
+name: REST Example
+type: module
+description: An example outlining how a module can use the RESTful Web Services to communicate with another Drupal instance.
+package: Example modules
+core: 8.x
+dependencies:
+  - drupal:rest
+  - drupal:basic_auth
+  - drupal:hal
+  - views:views
+  - examples:examples
diff --git a/rest_example/rest_example.links.action.yml b/rest_example/rest_example.links.action.yml
new file mode 100644
index 0000000..3680ebb
--- /dev/null
+++ b/rest_example/rest_example.links.action.yml
@@ -0,0 +1,5 @@
+rest_example.create_node:
+  route_name: rest_example.client_actions_create
+  title: 'Create node'
+  appears_on:
+    - rest_example.client_actions_index
diff --git a/rest_example/rest_example.links.menu.yml b/rest_example/rest_example.links.menu.yml
new file mode 100644
index 0000000..f2d13b0
--- /dev/null
+++ b/rest_example/rest_example.links.menu.yml
@@ -0,0 +1,23 @@
+# This file contains entries that will appear in the "Tool" menu.
+
+# Help page
+rest_example:
+  title: 'REST Example'
+  description: 'How to use the REST example module'
+  route_name: rest_example.getting_started
+  expanded: TRUE
+
+# Creates a link that points to the page where we can setup the REST client, so
+# that it will know where the server resides, and how to authenticate.
+rest_example.settings:
+  title: 'Client Settings'
+  description: 'Callback for REST client settings form.'
+  route_name: rest_example.client_settings
+
+# This link points to the page where all the magic happens: The display of the
+# nodes on the remote server, and from where we can create, edit and delete them
+# too.
+rest_example.actions:
+  title: 'Client Actions'
+  description: 'Callback for REST client action form.'
+  route_name: rest_example.client_actions_index
diff --git a/rest_example/rest_example.module b/rest_example/rest_example.module
new file mode 100644
index 0000000..a82db6e
--- /dev/null
+++ b/rest_example/rest_example.module
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * This is a demonstration of how to the REST service in Drupal works.
+ */
+
+/**
+ * @defgroup rest_example Example: REST
+ * @ingroup examples
+ * @{
+ * This module will give you a brief demonstration of how the REST service
+ * works.
+ *
+ * This example uses nodes, because they works out of the box. But any entity
+ * could be used.
+ *
+ * To complete a demo, we'll need a server site, containing the nodes, and a
+ * client, that sends requests to the server. The same site can very well act
+ * as both client and server.
+ *
+ * First thing you want to do, is visit 'examples/rest-client-settings' and
+ * setup what website you want to interact with. To avoid complications, and
+ * minimize the chance of failure, I'll sugest that you start using the same
+ * site as both server and client, using the user 1 credentials. And when you
+ * have gotten the feel of how things works, try to use two seperate sites, and
+ * maybe another user. Please note that you need to install this module on both
+ * client and server site.
+ *
+ * Next thing you want is to go to 'examples/rest-client-actions'. This page
+ * contains a table where all the remote nodes, of the type rest_example_test,
+ * will be displayed. At first there might not be any.
+ *
+ * From the same page you can create, edit and delete nodes on the remote site.
+ *
+ * The server site actually only uses the View (rest_serice) and the node type
+ * (rest_example_test), imported upon installatin of this module. The rest of
+ * the functionallity comes from Drupal Core modules, like 'rest', 'basic_auth'
+ * and 'hal'.
+ *
+ * The client part of the site uses the following classes:
+ *
+ *  - @see \Drupal\rest_example\Controller\RestExampleClientController::indexAction()
+ *    Builds the list of nodes on the remote server.
+ *
+ *  - @see \Drupal\rest_example\Form\RestExampleClientSettings
+ *    A form that can creates/edits nodes.
+ *
+ *  - @see \Drupal\rest_example\Form\RestExampleClientSettings
+ *    A form used to confirm the deletion of the node.
+ *
+ *  - @see \Drupal\rest_example\Form\RestExampleClientSettings
+ *    A form wher you setup what site you want to interact with.
+ *
+ *  - @see \Drupal\rest_example\RestExampleClientCalls
+ *    This class handles all the calls to the remote site, and returns the
+ *    response back, to be processed by the requesting method.
+ */
+
+/**
+ * @} End of "defgroup rest_example".
+ */
diff --git a/rest_example/rest_example.routing.yml b/rest_example/rest_example.routing.yml
new file mode 100644
index 0000000..d0ae76c
--- /dev/null
+++ b/rest_example/rest_example.routing.yml
@@ -0,0 +1,55 @@
+# These routes are tells Drupal where to find the content/actions for each URL.
+
+# Description and help text.
+rest_example.getting_started:
+  path: 'examples/rest-getting-started'
+  defaults:
+    _title: 'REST Example: Getting started'
+    _controller: 'Drupal\rest_example\Controller\RestExampleHelpController::description'
+  requirements:
+    _permission: 'access content'
+
+# The client setup page.
+rest_example.client_settings:
+  path: 'examples/rest-client-settings'
+  defaults:
+    _title: 'Connect to a remote Drupal site'
+    _form: '\Drupal\rest_example\Form\RestExampleClientSettings'
+  requirements:
+    _permission: 'access content'
+
+# Listing of all the remote nodes, of the type rest_example_test.
+rest_example.client_actions_index:
+  path: 'examples/rest-client-actions'
+  defaults:
+    _title: 'Nodes on the remote Drupal server'
+    _controller: '\Drupal\rest_example\Controller\RestExampleClientController::indexAction'
+  requirements:
+    _permission: 'access content'
+
+# Create a new node on the remote server.
+rest_example.client_actions_create:
+  path: 'examples/rest-client-actions/create'
+  defaults:
+    _title: 'Create node on remote Drupal server'
+    _form: '\Drupal\rest_example\Form\RestExampleClientEdit'
+  requirements:
+    _permission: 'access content'
+
+# Edit a node on the remote server.
+rest_example.client_actions_edit:
+  path: 'examples/rest-client-actions/edit/{id}'
+  defaults:
+    _title: 'Edit node on remote Drupal server'
+    _form: '\Drupal\rest_example\Form\RestExampleClientEdit'
+  requirements:
+    _permission: 'access content'
+
+# Delete a node on the remote server.
+rest_example.client_actions_delete:
+  path: 'examples/rest-client-actions/delete/{id}'
+  defaults:
+    _title: 'Delete node on remote Drupal server'
+    _form: '\Drupal\rest_example\Form\RestExampleClientDelete'
+  requirements:
+    _permission: 'access content'
diff --git a/rest_example/rest_example.services.yml b/rest_example/rest_example.services.yml
new file mode 100644
index 0000000..814c707
--- /dev/null
+++ b/rest_example/rest_example.services.yml
@@ -0,0 +1,4 @@
+services:
+  rest_example_client_calls:
+    class: Drupal\rest_example\RestExampleClientCalls
+    arguments: ['@http_client', '@config.factory']
diff --git a/rest_example/src/Controller/RestExampleClientController.php b/rest_example/src/Controller/RestExampleClientController.php
new file mode 100644
index 0000000..8eee25b
--- /dev/null
+++ b/rest_example/src/Controller/RestExampleClientController.php
@@ -0,0 +1,92 @@
+<?php
+
+namespace Drupal\rest_example\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Link;
+use Drupal\Core\Messenger\MessengerInterface;
+use Drupal\rest_example\RestExampleClientCalls;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+
+/**
+ * Controller routines for rest example routes.
+ *
+ * @ingroup rest_example
+ */
+class RestExampleClientController extends ControllerBase {
+
+  /**
+   * RestExampleClientCalls object.
+   *
+   * @var \Drupal\rest_example\RestExampleClientCalls
+   */
+  private $restExampleClientCalls;
+
+  /**
+   * RestExampleClientController constructor.
+   *
+   * @param \Drupal\rest_example\RestExampleClientCalls $rest_example_client_calls
+   *   RestExampleClientCalls service.
+   */
+  public function __construct(RestExampleClientCalls $rest_example_client_calls) {
+    $this->restExampleClientCalls = $rest_example_client_calls;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public static function create(ContainerInterface $container) {
+    return new static(
+      $container->get('rest_example_client_calls')
+    );
+  }
+
+
+  /**
+   * Retrieve a list of all nodes available on the remote site.
+   *
+   * Building the list as a table by calling the RestExampleClientCalls::index()
+   * and builds the list from the response of that.
+   *
+   * @throws \RuntimeException
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function indexAction() {
+
+    if (NULL === $this->configFactory->get('rest_example.settings')->get('server_url')) {
+      drupal_set_message($this->t('The remote endpoint service address have not been set. Please go and provide the credentials and the endpoint address on the <a href="@url">config page</a>.', ['@url' => base_path() . 'examples/rest-client-settings']), 'warning');
+    }
+    $build = [];
+
+    $nodes = $this->restExampleClientCalls->index();
+
+    $build['intro'] = [
+      '#markup' => $this->t('This is a list of nodes, of type <em>Rest Example Test</em>, on the remote server. From here you can create new node, edit and delete existing ones.'),
+    ];
+
+    $build['node_table'] = [
+      '#type' => 'table',
+      '#header' => [
+        $this->t('Title'),
+        $this->t('Type'),
+        $this->t('Created'),
+        $this->t('Edit'),
+        $this->t('Delete'),
+      ],
+      '#empty' => t('There are no items on the remote system yet'),
+    ];
+
+    if (!empty($nodes)) {
+      foreach ($nodes as $delta => $node) {
+        $build['node_table'][$delta]['title']['#plain_text'] = $node['title'];
+        $build['node_table'][$delta]['type']['#plain_text'] = $node['type'];
+        $build['node_table'][$delta]['created']['#plain_text'] = $node['created'];
+        $build['node_table'][$delta]['edit']['#plain_text'] = Link::createFromRoute($this->t('Edit'), 'rest_example.client_actions_edit', ['id' => $node['nid']])->toString();
+        $build['node_table'][$delta]['delete']['#plain_tex'] = Link::createFromRoute($this->t('Delete'), 'rest_example.client_actions_delete', ['id' => $node['nid']])->toString();
+      }
+    }
+
+    return $build;
+  }
+
+}
diff --git a/rest_example/src/Controller/RestExampleHelpController.php b/rest_example/src/Controller/RestExampleHelpController.php
new file mode 100644
index 0000000..c6e4c3f
--- /dev/null
+++ b/rest_example/src/Controller/RestExampleHelpController.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Drupal\rest_example\Controller;
+
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\examples\Utility\DescriptionTemplateTrait;
+
+/**
+ * Provides a help page for the REST Examples module.
+ *
+ * @ingroup rest_example
+ */
+class RestExampleHelpController extends ControllerBase {
+
+  use DescriptionTemplateTrait;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function getModuleName() {
+    return 'rest_example';
+  }
+
+}
diff --git a/rest_example/src/Form/RestExampleClientDelete.php b/rest_example/src/Form/RestExampleClientDelete.php
new file mode 100644
index 0000000..bc3556c
--- /dev/null
+++ b/rest_example/src/Form/RestExampleClientDelete.php
@@ -0,0 +1,81 @@
+<?php
+
+namespace Drupal\rest_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\ConfirmFormBase;
+use Drupal\Core\Url;
+use Drupal\rest_example\RestExampleClientCalls;
+
+/**
+ * Delete a new node on a remote Drupal site.
+ *
+ * @ingroup rest_example
+ */
+class RestExampleClientDelete extends ConfirmFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'rest_example_client_delete';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getQuestion() {
+    return $this->t('Are you sure that you want to delete this content.');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getCancelUrl() {
+    return new Url('rest_example.client_actions_index');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getConfirmText() {
+    return t('Delete');
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    if (is_null($form_state->get('node_id')) || !is_numeric($form_state->get('node_id'))) {
+      $form_state->setErrorByName('delete', $this->t('The ID passed in the URL is not an integer'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $id = NULL) {
+    $form = parent::buildForm($form, $form_state);
+
+    $form_state->set('node_id', $id);
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $node_id = $form_state->get('node_id');
+
+    $node = [
+      'nid' => $node_id,
+    ];
+
+    $client = new RestExampleClientCalls(\Drupal::httpClient(), \Drupal::configFactory());
+    $client->delete($node);
+    drupal_set_message($this->t('Node was successfully deleted'));
+    $form_state->setRedirect('rest_example.client_actions_index');
+  }
+
+}
diff --git a/rest_example/src/Form/RestExampleClientEdit.php b/rest_example/src/Form/RestExampleClientEdit.php
new file mode 100644
index 0000000..708af74
--- /dev/null
+++ b/rest_example/src/Form/RestExampleClientEdit.php
@@ -0,0 +1,109 @@
+<?php
+
+namespace Drupal\rest_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\FormBase;
+use Drupal\rest_example\RestExampleClientCalls;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Edit or create a new node on a remote Drupal site.
+ *
+ * @ingroup rest_example
+ */
+class RestExampleClientEdit extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'rest_example_client_edit';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function validateForm(array &$form, FormStateInterface $form_state) {
+    if (!is_null($form_state->get('node_id')) && !is_numeric($form_state->get('node_id'))) {
+      $form_state->setErrorByName('submit', $this->t('The ID passed in the URL is not an integer'));
+    }
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state, $id = NULL) {
+
+    $config_factory = \Drupal::configFactory();
+    if (empty($config_factory->get('rest_example.settings')->get('server_url'))) {
+      drupal_set_message($this->t('The remote endpoint service address have not been set. Please go and provide the credentials and the endpoint address on the <a href="@url">config page</a>.', ['@url' => base_path() . 'examples/rest-client-settings']), 'error');
+      return [
+        'error' => [
+          '#markup' => 'Unable to establish to the remote site.',
+        ],
+      ];
+    }
+
+    if (!is_null($id) && !is_numeric($id)) {
+      return new Response('The ID passed in the URL is not an integer', 500);
+    }
+
+    $title = '';
+    $form_state->set('node_id', NULL);
+    $form_state->set('node_type', 'rest_example_test');
+
+    // If this an existing node, we pull the data from the remote and set the
+    // variables that we use as default values later on.
+    if (is_numeric($id)) {
+      $client = new RestExampleClientCalls(\Drupal::httpClient(), $config_factory);
+      $node = $client->index($id);
+      if (isset($node[0])) {
+        $title = $node[0]['title'];
+        $form_state->set('node_id', $id);
+      }
+    }
+
+    $form['title'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Node title'),
+      '#default_value' => $title,
+    ];
+
+    $form['submit'] = [
+      '#type' => 'submit',
+      '#value' => $this->t('Save'),
+    ];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $node_id = $form_state->get('node_id');
+    $node_type = $form_state->get('node_type');
+    $form_values = $form_state->getValues();
+
+    $node = [
+      'nid' => $node_id,
+      'title' => $form_values['title'],
+      'type' => $node_type,
+    ];
+
+    $client = new RestExampleClientCalls(\Drupal::httpClient(), \Drupal::configFactory());
+
+    if (is_null($node_id)) {
+      $client->create($node);
+    }
+    else {
+      $client->update($node);
+    }
+
+    drupal_set_message($this->t('Node was successfully created'));
+
+    $form_state->setRedirect('rest_example.client_actions_index');
+  }
+
+}
diff --git a/rest_example/src/Form/RestExampleClientSettings.php b/rest_example/src/Form/RestExampleClientSettings.php
new file mode 100644
index 0000000..bf13c64
--- /dev/null
+++ b/rest_example/src/Form/RestExampleClientSettings.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Drupal\rest_example\Form;
+
+use Drupal\Core\Form\FormStateInterface;
+use Drupal\Core\Form\ConfigFormBase;
+
+/**
+ * Setup form for a Drupal REST client.
+ *
+ * Here you configure what the other Drupal installation.
+ *
+ * @ingroup rest_example
+ */
+class RestExampleClientSettings extends ConfigFormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'rest_example_client_settings';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['intro'] = [
+      '#markup' => t('Set here the remote server options.'),
+    ];
+    $form['server_url'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Remote server URL'),
+      '#description' => $this->t('Format like this: http://www.example.com or http://www.example.com/test-site (no trailing slash)'),
+      '#default_value' => $this->config('rest_example.settings')->get('server_url'),
+      '#required' => TRUE,
+    ];
+    $form['server_username'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Remote server username'),
+      '#default_value' => $this->config('rest_example.settings')->get('server_username'),
+      '#description' => $this->t('A user on the remote system that has the proper rights to use the REST service'),
+      '#required' => TRUE,
+    ];
+    $form['server_password'] = [
+      '#type' => 'textfield',
+      '#title' => $this->t('Remote server password'),
+      '#default_value' => $this->config('rest_example.settings')->get('server_password'),
+      '#description' => $this->t('Remote users password'),
+      '#required' => TRUE,
+    ];
+    return parent::buildForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $form_values = $form_state->getValues();
+
+    $this->config('rest_example.settings')
+      ->set('server_url', $form_values['server_url'])
+      ->set('server_username', $form_values['server_username'])
+      ->set('server_password', $form_values['server_password'])
+      ->save();
+
+    parent::submitForm($form, $form_state);
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getEditableConfigNames() {
+    return [
+      'rest_example.settings',
+    ];
+  }
+
+}
diff --git a/rest_example/src/RestExampleClientCalls.php b/rest_example/src/RestExampleClientCalls.php
new file mode 100644
index 0000000..3df1a24
--- /dev/null
+++ b/rest_example/src/RestExampleClientCalls.php
@@ -0,0 +1,236 @@
+<?php
+
+namespace Drupal\rest_example;
+
+use Drupal\Component\Serialization\Json;
+use Drupal\Core\Config\ConfigFactoryInterface;
+use GuzzleHttp\ClientInterface;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Here we interact with the remote service.
+ *
+ * We use Guzzle (what else ;-) ).
+ */
+class RestExampleClientCalls {
+
+  /**
+   * The client used to send HTTP requests.
+   *
+   * @var \GuzzleHttp\ClientInterface
+   */
+  protected $client;
+
+  /**
+   * The header uses when sending HTTP request.
+   *
+   * The headers are very important when communicating with the REST server.
+   * It's used by the server the verify that it supports the sent data
+   * (Content-Type) and that it supports the type of response that the client
+   * wants.
+   *
+   * @var array
+   */
+
+  protected $clientHeaders = [
+    'Accept' => 'application/haljson',
+    'Content-Type' => 'application/haljson',
+  ];
+
+  /**
+   * The authentication parameters used when calling the remote REST server.
+   *
+   * @var array
+   */
+
+  protected $clientAuth;
+
+  /**
+   * The URL of the remote REST server.
+   *
+   * @var string
+   */
+
+  protected $remoteUrl;
+
+  /**
+   * The constructor.
+   *
+   * @param \GuzzleHttp\ClientInterface $client
+   *   The HTTP client.
+   * @param \Drupal\Core\Config\ConfigFactoryInterface $config_factory
+   *   The Config Factory.
+   */
+  public function __construct(ClientInterface $client, ConfigFactoryInterface $config_factory) {
+    $this->client = $client;
+
+    // Retrieve the config from the configuration page set at
+    // examples/rest_client_settings.
+    $rest_config = $config_factory->get('rest_example.settings');
+
+    $this->clientAuth = [
+      $rest_config->get('server_password'),
+      $rest_config->get('server_username'),
+    ];
+
+    $this->remoteUrl = $rest_config->get('server_url');
+  }
+
+  /**
+   * Retrieve a list of nodes from the remote server.
+   *
+   * When we retrieve entities we use GET.
+   *
+   * @param int $node_id
+   *   The ID of the remote node, if needed. If the ID is NULL, all nodes will
+   *   be fetched.
+   *
+   * @return mixed
+   *   JSON formatted string with the nodes from the remote server.
+   *
+   * @throws \RuntimeException
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function index($node_id = NULL) {
+
+    // If the configurated URL is an empty string, return nothing.
+    if (empty($this->remoteUrl)) {
+      return '';
+    }
+
+    $id = '';
+    if (!empty($node_id) && is_numeric($node_id)) {
+      $id = '/' . $node_id;
+    }
+
+    $response = $this->client->request('GET',
+    $this->remoteUrl . '/rest/node' . $id, [
+      'headers' => $this->clientHeaders,
+    ]
+    );
+
+    return Json::decode($response->getBody()->getContents());
+  }
+
+  /**
+   * Create a node on the remote server, using POST.
+   *
+   * @param array $node
+   *   Contains the data of the node we want to create.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   *   A HTTP response.
+   *
+   * @throws \InvalidArgumentException
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function create(array $node) {
+
+    if (empty($this->remoteUrl)) {
+      return new Response('The remote endpoint URL has not been setup.', 500);
+    }
+
+    // Build an array of options telling the remote server what type of content
+    // we want to create, and give it a title. After that, we encode it all
+    // to JSON.
+    $request_body = json_encode([
+      '_links' => [
+        'type' => [
+          'href' => $this->remoteUrl . '/rest/type/node/' . $node['type'],
+        ],
+      ],
+      'title' => [0 => ['value' => $node['title']]],
+    ]);
+
+    $response = $this->client->request('POST',
+        $this->remoteUrl . '/entity/node',
+    [
+      'headers' => $this->clientHeaders,
+      'auth' => $this->clientAuth,
+      'body' => $request_body,
+    ]
+    );
+
+    // Validate the response from the remote server.
+    if ($response->getStatusCode() != 201) {
+      return new Response('An error occured while creating the node.', 500);
+    }
+  }
+
+  /**
+   * Update (PATCH) a node on the remote server.
+   *
+   * You are encuraged to read the code and the comments in
+   * RestExampleClientCalls::create() first.
+   *
+   * @param array $node
+   *   Contains the data of the node we want to create.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   *   A HTTP response.
+   *
+   * @throws \InvalidArgumentException
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function update(array $node) {
+    if (empty($this->remoteUrl)) {
+      return new Response('The remote URL has not been setup.', 500);
+    }
+
+    $request_body = json_encode([
+      '_links' => [
+        'type' => [
+          'href' => $this->remoteUrl . '/rest/type/node/' . $node['type'],
+        ],
+      ],
+      'title' => [0 => ['value' => $node['title']]],
+    ]);
+    $response = $this->client->request('POST',
+        $this->remoteUrl . '/node/' . $node['nid'],
+    [
+      'headers' => $this->clientHeaders,
+      'auth' => $this->clientAuth,
+      'body' => $request_body,
+    ]
+    );
+
+    if ($response->getStatusCode() != 204) {
+      return new Response('An error occured while patching the node.', 500);
+    }
+  }
+
+  /**
+   * Delete a node on the remote server, using DELETE.
+   *
+   * You are encouraged to read the code and the comments in
+   * RestExampleClientCalls::create() first.
+   *
+   * @param array $node
+   *   Contains the data of the node we want to create.
+   *
+   * @return \Symfony\Component\HttpFoundation\Response
+   *   An HTTP response.
+   *
+   * @throws \InvalidArgumentException
+   * @throws \GuzzleHttp\Exception\GuzzleException
+   */
+  public function delete(array $node) {
+
+    if (empty($this->remoteUrl)) {
+      return new Response('The remote URL has not been setup.', 500);
+    }
+
+    $response = $this->client->request('DELETE',
+        $this->remoteUrl . '/node/' . $node['nid'],
+    [
+      'headers' => $this->clientHeaders,
+      'auth' => $this->clientAuth,
+    ]
+    );
+
+    if ($response->getStatusCode() != 204) {
+      return new Response('An error occured while patching the node.', 500);
+    }
+  }
+
+}
diff --git a/rest_example/templates/description.html.twig b/rest_example/templates/description.html.twig
new file mode 100644
index 0000000..c5b2120
--- /dev/null
+++ b/rest_example/templates/description.html.twig
@@ -0,0 +1,37 @@
+{#
+
+Description text for the Rest Example.
+
+#}
+
+{% set rest_client_settings = path('rest_example.client_settings') %}
+{% set rest_client_actions = path('rest_example.client_actions_index') %}
+
+{% trans %}
+<p>This module will give you a brief demonstration of how the REST service works</p>
+<p>This example uses nodes, because they works out of the box. But any entity could be used.</p>
+<p>To complete a demo, we will need a server site, containing the nodes, and a client, that sends requests to the server. The same site can very well act as both client and server.</p>
+<p>First thing you want to do, is visit <a href="{{ rest_client_settings }}">examples/rest-client-settings</a> and setup what website you want to interact with. To avoid complications, and minimize the chance of failure, I will sugest that you start using the same site as both server and client, using the user 1 credentials. And when you have gotten the feel of how things works, try to use two seperate sites, and maybe another user. Please note that you need to install this module on both client and server site.</p>
+<p>Next thing you want is to go to <a href="{{ rest_client_actions }}">examples/rest-client-actions</a>. This page contains a table where all the remote nodes, of the type rest_example_test, will be displayed. At first there might not be any.</p>
+<p>From the same page you can create, edit and delete nodes on the remote site.</p>
+<p>The server site actually only uses the View (rest_service) and the node type (rest_example_test), imported upon installation of this module. The rest of the functionallity comes from Drupal Core modules, like "rest", "basic_auth" and "hal".</p>
+
+<h3>The client part of the site uses the following classes:</h3>
+<ul>
+    <li>
+        <p><code>\Drupal\rest_example\Controller\RestExampleClientController::indexAction()</code>: Builds the list of nodes on the remote server.</p>
+    </li>
+    <li>
+        <p><code>\Drupal\rest_example\Form\RestExampleClientSettings</code>: A form that can creates/edits nodes.</p>
+    </li>
+    <li>
+        <p><code>\Drupal\rest_example\Form\RestExampleClientSettings</code>: A form used to confirm the deletion of the node.</p>
+    </li>
+    <li>
+        <p><code>\Drupal\rest_example\Form\RestExampleClientSettings</code>: A form wher you setup what site you want to interact with.</p>
+    </li>
+    <li>
+        <p><code>\Drupal\rest_example\RestExampleClientCalls</code>: This class handles all the calls to the remote site, and returns the response back, to be processed by the requesting method.</p>
+    </li>
+</ul>
+{% endtrans %}
diff --git a/rest_example/tests/src/Functional/RestExampleActionTest.php b/rest_example/tests/src/Functional/RestExampleActionTest.php
new file mode 100644
index 0000000..e01eef4
--- /dev/null
+++ b/rest_example/tests/src/Functional/RestExampleActionTest.php
@@ -0,0 +1,72 @@
+<?php
+
+namespace Drupal\Tests\rest_example\Funtional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Verify that the Views are accessible.
+ *
+ * @ingroup rest_example
+ * @group rest_example
+ * @group examples
+ */
+class RestExampleActionTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['rest_example'];
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * {@inheritdoc}
+   */
+  public function setUp() {
+    parent::setup();
+
+    global $base_url;
+
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+
+    $config_factory = \Drupal::configFactory();
+
+    $rest_config = $config_factory->getEditable('rest_example.settings');
+    $rest_config
+      ->set('server_url', $base_url)
+      ->set('server_username', $account->get('name')->value)
+      ->set('server_password', $account->passRaw)
+      ->save();
+  }
+
+  /**
+   * Test that we access the client side View.
+   *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   */
+  public function testClientNode() {
+
+    $this->drupalGet('examples/rest-client-actions');
+    $this->assertSession()->responseContains('Nodes on the remote Drupal server');
+  }
+
+  /**
+   * Test that we can access the server side View.
+   *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   */
+  public function testServerView() {
+    $this->drupalGet('rest/node');
+    $this->assertSession()->responseContains('[]');
+  }
+
+}
diff --git a/rest_example/tests/src/Functional/RestExampleMenuTest.php b/rest_example/tests/src/Functional/RestExampleMenuTest.php
new file mode 100644
index 0000000..d03635a
--- /dev/null
+++ b/rest_example/tests/src/Functional/RestExampleMenuTest.php
@@ -0,0 +1,56 @@
+<?php
+
+namespace Drupal\Tests\rest_example\Funtional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Test the user-facing menus in Rest Example.
+ *
+ * @ingroup rest_example
+ * @group rest_example
+ * @group examples
+ */
+class RestExampleMenuTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['rest_example'];
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * This test class requires the "Tools" block.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test for a link to the rest example in the Tools menu.
+   *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   */
+  public function testRestExampleLink() {
+    $this->drupalGet('');
+    $this->assertSession()->linkByHrefExists('examples/rest-client-actions');
+    $this->assertSession()->linkByHrefExists('examples/rest-client-settings');
+  }
+
+  /**
+   * Tests rest_example menus.
+   *
+   * @throws \Behat\Mink\Exception\ExpectationException
+   */
+  public function testRestExampleMenu() {
+    $this->drupalGet('examples/rest-client-actions');
+    $this->assertSession()->statusCodeEquals(200);
+
+    $this->drupalGet('examples/rest-client-settings');
+    $this->assertSession()->statusCodeEquals(200);
+  }
+
+}
diff --git a/rest_example/tests/src/Functional/RestExampleSettingsTest.php b/rest_example/tests/src/Functional/RestExampleSettingsTest.php
new file mode 100644
index 0000000..1978151
--- /dev/null
+++ b/rest_example/tests/src/Functional/RestExampleSettingsTest.php
@@ -0,0 +1,60 @@
+<?php
+
+namespace Drupal\Tests\rest_example\Funtional;
+
+use Drupal\Tests\BrowserTestBase;
+
+/**
+ * Test the settings in Rest Example.
+ *
+ * @ingroup rest_example
+ * @group rest_example
+ * @group examples
+ */
+class RestExampleSettingsTest extends BrowserTestBase {
+
+  /**
+   * Modules to enable.
+   *
+   * @var array
+   */
+  public static $modules = ['rest_example'];
+
+  /**
+   * The installation profile to use with this test.
+   *
+   * @var string
+   */
+  protected $profile = 'minimal';
+
+  /**
+   * Test that the form can be submitted.
+   */
+  public function testRestExampleSettings() {
+    global $base_url;
+
+    $account = $this->drupalCreateUser();
+    $this->drupalLogin($account);
+
+    $this->drupalGet('examples/rest-client-settings');
+
+    $edit = [
+      'server_url' => $base_url,
+      'server_username' => $account->get('name')->value,
+      'server_password' => $account->passRaw,
+    ];
+
+    $this->drupalPostForm(base_path() . 'examples/rest-client-settings', $edit, t('Save configuration'));
+    $this->assertText('The configuration options have been saved.');
+
+    $config_factory = \Drupal::configFactory();
+
+    $rest_config = $config_factory->get('rest_example.settings');
+
+    self::assertEquals($base_url, $rest_config->get('server_url'));
+    self::assertEquals($account->get('name')->value, $rest_config->get('server_username'));
+    self::assertEquals($account->passRaw, $rest_config->get('server_password'));
+
+  }
+
+}
