diff --git b/crm_core/contact/src/Tests/EventProcessingTest.php a/crm_core/contact/src/Tests/EventProcessingTest.php
new file mode 100644
index 0000000..8c859b6
--- /dev/null
+++ a/crm_core/contact/src/Tests/EventProcessingTest.php
@@ -0,0 +1,298 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\collect_crm_core_contact\Tests\EventProcessingTest.
+ */
+
+namespace Drupal\collect_crm_core_contact\Tests;
+
+use Drupal\collect\CollectContainerInterface;
+use Drupal\collect\Entity\Container;
+use Drupal\collect\Event\CollectEvent;
+use Drupal\crm_core_activity\Entity\Activity;
+use Drupal\crm_core_contact\Entity\Contact;
+use Drupal\crm_core_default_matching_engine\Entity\MatchingRule;
+use Drupal\simpletest\KernelTestBase;
+
+/**
+ * Tests the processing of contact form submission on integration level.
+ *
+ * @group collect
+ */
+class EventProcessingTest extends KernelTestBase {
+
+  /**
+   * Disabled config schema checking temporarily until all errors are resolved.
+   */
+  protected $strictConfigSchema = FALSE;
+
+  /**
+   * {@inheritdoc}
+   */
+  public static $modules = array(
+    'user',
+    'serialization',
+    'rest',
+    'hal',
+    'collect',
+    'field',
+    'text',
+    'datetime',
+    'entity',
+    'filter',
+    'entity_reference',
+    'crm_core_contact',
+    'crm_core_activity',
+    'crm_core_match',
+    'crm_core_default_matching_engine',
+    'collect_crm_core_contact',
+  );
+
+  /**
+   * Test json data.
+   *
+   * @var string
+   */
+  protected $json;
+
+  /**
+   * The submission to process.
+   *
+   * @var \Drupal\collect\CollectContainerInterface
+   */
+  protected $submission;
+
+  /**
+   * An existing contact.
+   *
+   * @var \Drupal\crm_core_contact\Entity\Contact
+   */
+  protected $contact;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->installEntitySchema('collect_container');
+    $this->installEntitySchema('crm_core_contact');
+    $this->installEntitySchema('crm_core_activity');
+    $this->installEntitySchema('user');
+
+    $this->installConfig(array(
+      'crm_core_contact',
+      'crm_core_activity',
+      'collect_crm_core_contact',
+    ));
+
+    \Drupal::configFactory()->getEditable('crm_core_match.engines')->set('default', array('status' => TRUE))->save();
+    /* @var \Drupal\crm_core_default_matching_engine\Entity\MatchingRule $rule */
+    $rule = MatchingRule::load('individual');
+    $rule->setStatus(TRUE);
+    $rule->threshold = 8;
+    $rule->rules = array(
+      'contact_remote_id' => array(
+        'value' => array(
+          'status' => '1',
+          'operator' => '=',
+          'options' => '',
+          'score' => '10',
+          'weight' => '0',
+        ),
+      ),
+      'contact_mail' => array(
+        'value' => array(
+          'status' => '1',
+          'operator' => '=',
+          'options' => '',
+          'score' => '9',
+          'weight' => '0',
+        ),
+      ),
+    );
+    $rule->save();
+
+    $this->json = file_get_contents(__DIR__ . '/../../tests/src/Unit/fixture.json');
+    $this->submission = Container::create(array(
+      'origin_uri' => 'http://localhost/entity/message/feedback/2494b3ba-158b-4066-9833-510bd72c82eb',
+      'date' => REQUEST_TIME,
+      'data' => array(
+        'data' => $this->json,
+        'type' => 'application/json',
+        'schema' => 'https://drupal.org/project/collect_client/contact',
+      ),
+    ));
+    $this->submission->save();
+
+    $this->contact = Contact::create(array(
+      'type' => 'individual',
+      'name' => 'Aenean Risus',
+      'contact_mail' => 'anean@example.com',
+    ));
+    $this->contact->save();
+  }
+
+  /**
+   * Tests submission containing a user that does not match an existing contact.
+   */
+  public function testWithUserWithoutMatch() {
+    $this->triggerProcessing($this->submission);
+
+    $contact = Contact::load(2);
+    $this->assertNewUserContact($contact);
+
+    $activity = Activity::load(1);
+    $this->assertActivity($activity, $contact);
+  }
+
+  /**
+   * Tests submission containing a user that does match an existing contact.
+   */
+  public function testWithUserWithMatch() {
+    $this->contact->set('contact_remote_id', 'http://example.com/user/1');
+    $this->contact->save();
+
+    $this->triggerProcessing($this->submission);
+
+    $contact = Contact::load(2);
+    $this->assertNull($contact, 'No new contact was created.');
+
+    $contact = Contact::load(1);
+    $this->assertMatchContact($contact);
+    $activity = Activity::load(1);
+    $this->assertActivity($activity, $contact);
+  }
+
+  /**
+   * Tests submission not containing a user not matching an existing contact.
+   */
+  public function testWithoutUserWithoutMatch() {
+    $this->unsetUser();
+
+    $this->triggerProcessing($this->submission);
+
+    $contact = Contact::load(2);
+    $this->assertNewMessageContact($contact);
+    $activity = Activity::load(1);
+    $this->assertActivity($activity, $contact);
+  }
+
+  /**
+   * Tests submission not containing a user that does match an existing contact.
+   */
+  public function testWithoutUserWithMatch() {
+    $this->unsetUser();
+    $data = json_decode($this->json, TRUE);
+    $data['values']['mail'][0]['value'] = 'anean@example.com';
+    $this->json = json_encode($data);
+    $this->submission->setData($this->json);
+
+    $this->triggerProcessing($this->submission);
+
+    $contact = Contact::load(2);
+    $this->assertNull($contact, 'No new contact was created.');
+
+    $contact = Contact::load(1);
+    $this->assertMatchContact($contact);
+    $activity = Activity::load(1);
+    $this->assertActivity($activity, $contact);
+  }
+
+  /**
+   * Asserts an activity.
+   *
+   * An activity was created with values from the submission and linked to the
+   * container and contact
+   *
+   * @param Activity $activity
+   *   The activity to assert.
+   * @param Contact $contact
+   *   The contact expected to be linked with the activity.
+   */
+  protected function assertActivity(Activity $activity = NULL, Contact $contact = NULL) {
+    $this->assertNotNull($activity, 'New activity was created.');
+    if ($activity) {
+      $this->assertEqual('Aenean lacinia bibendum nulla sed consectetur', $activity->get('title')->value, 'Found expected activity title');
+      $data = json_decode($this->json, TRUE);
+      $this->assertEqual($data['values']['message'][0]['value'], $activity->get('activity_notes')->value, 'Found expected activity title');
+      if ($contact) {
+        $this->assertEqual($contact->id(), $activity->get('activity_participants')->target_id, 'Activity was assigned to the expected contact');
+      }
+      $this->assertEqual($this->submission->id(), $activity->get('activity_submission')->target_id, 'Activity was linked to the container record');
+      $this->assertNotNull($activity->get('activity_date')->value, 'Activity has date set');
+    }
+  }
+
+  /**
+   * Asserts a new user contact.
+   *
+   * A new contact was created with values from the user section of the
+   * submission.
+   *
+   * @param Contact $contact
+   *   The contact to assert.
+   */
+  protected function assertNewUserContact(Contact $contact = NULL) {
+    $this->assertNotNull($contact, 'New contact was created.');
+    if ($contact) {
+      $this->assertEqual('dapibus', $contact->get('name')->value, 'Contact is named \'dapibus\'');
+      $this->assertEqual('dapibus@example.com', $contact->get('contact_mail')->value, 'Contact mail is \'dapibus@example.com\'');
+      $this->assertEqual('http://example.com/user/1', $contact->get('contact_remote_id')->value, 'Remote identifier is \'http://example.com/user/1\'');
+    }
+  }
+
+  /**
+   * Asserts a new message contact.
+   *
+   * A new contact was created with values from the message part of the
+   * submission.
+   *
+   * @param Contact $contact
+   *   The contact to assert.
+   */
+  protected function assertNewMessageContact(Contact $contact = NULL) {
+    $this->assertNotNull($contact, 'New contact was created.');
+    if ($contact) {
+      $this->assertEqual('Ullamcorper Fermentum', $contact->get('name')->value, 'Contact is named \'Ullamcorper Fermentum\'');
+      $this->assertEqual('ullamcorper@example.com', $contact->get('contact_mail')->value, 'Contact mail is \'ullamcorper@example.com\'');
+      $this->assertNull($contact->get('contact_remote_id')->value, 'Remote identifier is undefined');
+    }
+  }
+
+  /**
+   * Asserts the value of a contact identified as a match.
+   *
+   * The existing contact was not overwritten.
+   *
+   * @param Contact $contact
+   *   The contact to assert.
+   */
+  protected function assertMatchContact(Contact $contact) {
+    $this->assertEqual('Aenean Risus', $contact->get('name')->value, 'Contact is named \'Aenean Risus\'');
+    $this->assertEqual('anean@example.com', $contact->get('contact_mail')->value, 'Contact mail is \'anean@example.com\'');
+  }
+
+  /**
+   * Triggers processing.
+   *
+   * @param \Drupal\collect\CollectContainerInterface $submission
+   *   The submission to be processed.
+   */
+  protected function triggerProcessing(CollectContainerInterface $submission) {
+    $event = new CollectEvent($submission);
+    /* @var \Symfony\Component\EventDispatcher\EventDispatcherInterface $dispatcher */
+    $dispatcher = $this->container->get('event_dispatcher');
+    $dispatcher->dispatch(CollectEvent::NAME, $event);
+  }
+
+  /**
+   * Sets the user to null in the submission data.
+   */
+  protected function unsetUser() {
+    $data = json_decode($this->json, TRUE);
+    $data['user'] = NULL;
+    $this->json = json_encode($data);
+    $this->submission->setData($this->json);
+  }
+}
diff --git b/crm_core/contact/tests/src/Unit/EventSubscriberTest.php a/crm_core/contact/tests/src/Unit/EventSubscriberTest.php
new file mode 100644
index 0000000..f31141a
--- /dev/null
+++ a/crm_core/contact/tests/src/Unit/EventSubscriberTest.php
@@ -0,0 +1,399 @@
+<?php
+/**
+ * @file
+ * Contains \Drupal\Tests\collect_crm_core_contact\Unit\EventSubscriberTest.
+ */
+
+namespace Drupal\Tests\collect_crm_core_contact\Unit;
+
+use Drupal\collect\Event\CollectEvent;
+use Drupal\collect_crm_core_contact\EventSubscriber;
+use Drupal\Tests\UnitTestCase;
+
+/**
+ * Tests the processing of contact form submissions.
+ *
+ * @group collect
+ */
+class EventSubscriberTest extends UnitTestCase {
+
+  /**
+   * The tested event subscriber.
+   *
+   * @var \Drupal\collect_crm_core_contact\EventSubscriber
+   */
+  protected $subscriber;
+
+  /**
+   * The entity manager service.
+   *
+   * @var \Drupal\Core\Entity\EntityManagerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $entityManager;
+
+  /**
+   * The mocked contact storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $contactStorage;
+
+  /**
+   * The mocked activity storage.
+   *
+   * @var \Drupal\Core\Entity\EntityStorageInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $activityStorage;
+
+  /**
+   * The mocked logger channel.
+   *
+   * @var \Drupal\Core\Logger\LoggerChannelInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $logger;
+
+  /**
+   * The mocked contact matcher.
+   *
+   * @var \Drupal\crm_core_match\MatcherInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $matcher;
+
+  /**
+   * The mocked data container.
+   *
+   * @var \Drupal\collect\CollectContainerInterface|\PHPUnit_Framework_MockObject_MockObject
+   */
+  protected $submission;
+
+  /**
+   * Test json data.
+   *
+   * @var string
+   */
+  protected $json;
+
+  /**
+   * The decoded json test data.
+   *
+   * @var array
+   */
+  protected $data;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp() {
+    parent::setUp();
+
+    $this->json = file_get_contents(__DIR__ . '/fixture.json');
+    $this->data = json_decode($this->json, TRUE);
+
+    $this->entityManager = $this->getMock('Drupal\Core\Entity\EntityManagerInterface');
+    $this->contactStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
+    $this->activityStorage = $this->getMock('Drupal\Core\Entity\EntityStorageInterface');
+    $this->logger = $this->getMock('Drupal\Core\Logger\LoggerChannelInterface');
+    $this->matcher = $this->getMock('Drupal\crm_core_match\MatcherInterface');
+    $this->submission = $this->getMock('Drupal\collect\CollectContainerInterface');
+
+    $this->subscriber = new EventSubscriber($this->entityManager, $this->logger, $this->matcher);
+
+    $this->entityManager->expects($this->any())
+      ->method('getStorage')
+      ->will($this->returnValueMap(array(
+        array('crm_core_contact', $this->contactStorage),
+        array('crm_core_activity', $this->activityStorage),
+      )));
+
+    $this->submission->expects($this->any())
+      ->method('getSchemaUri')
+      ->will($this->returnValue('https://drupal.org/project/collect_client/contact'));
+
+
+  }
+
+  /**
+   * Tests the announced event subscription..
+   */
+  public function testGetSubscribedEvents() {
+    $expected_subscription = array(
+      'collect.process' => 'process',
+    );
+    $subscription = EventSubscriber::getSubscribedEvents();
+
+    $this->assertArrayEquals($expected_subscription, $subscription, 'Got subscription to event collect.process to method process.');
+  }
+
+  /**
+   * Tests the processing of an unknown mime type.
+   */
+  public function testProcessUnknownType() {
+    $event = new CollectEvent($this->submission);
+
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/pdf'));
+
+    $this->logger->expects($this->once())
+      ->method('notice')
+      ->with('Unsupported MIME type {type} when processing submission with scheme {schema}', array(
+        'type' => 'application/pdf',
+        'schema' => 'https://drupal.org/project/collect_client/contact',
+      ));
+    $this->subscriber->process($event);
+  }
+
+  /**
+   * Tests the processing with a user present in the received data.
+   */
+  public function testProcessWithUser() {
+    $event = new CollectEvent($this->submission);
+    $contact = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $activity = $this->getMockBuilder('Drupal\crm_core_activity\Entity\Activity')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/json'));
+    $this->submission->expects($this->any())
+      ->method('getData')
+      ->will($this->returnValue($this->json));
+
+    $this->contactStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'individual',
+        'contact_remote_id' => 'http://example.com/user/1',
+        'name' => 'dapibus',
+        'contact_mail' => array(
+          'dapibus@example.com',
+          'dapibus@example.com',
+        ),
+      ))
+      ->will($this->returnValue($contact));
+
+    $contact->expects($this->once())
+      ->method('save');
+
+    $this->activityStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'contact',
+        'title' => $this->data['values']['subject'][0]['value'],
+        'activity_notes' => $this->data['values']['message'][0]['value'],
+        'activity_participants' => $contact,
+        'activity_submission' => $this->submission,
+      ))
+      ->will($this->returnValue($activity));
+
+    $activity->expects($this->once())
+      ->method('save');
+
+    $this->subscriber->process($event);
+  }
+
+  /**
+   * Tests the processing with no user present in the received data.
+   */
+  public function testProcessWithoutUser() {
+    $data = $this->data;
+    $data['user'] = NULL;
+
+    $event = new CollectEvent($this->submission);
+    $contact = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $activity = $this->getMockBuilder('Drupal\crm_core_activity\Entity\Activity')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/json'));
+    $this->submission->expects($this->any())
+      ->method('getData')
+      ->will($this->returnValue(json_encode($data)));
+
+    $this->contactStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'individual',
+        'name' => 'Ullamcorper Fermentum',
+        'contact_mail' => array(
+          'ullamcorper@example.com',
+        ),
+      ))
+      ->will($this->returnValue($contact));
+
+    $contact->expects($this->once())
+      ->method('save');
+
+    $this->activityStorage->expects($this->once())
+      ->method('create')
+      ->will($this->returnValue($activity));
+
+    $activity->expects($this->once())
+      ->method('save');
+
+    $this->subscriber->process($event);
+  }
+
+  /**
+   * Tests the processing with a user present in the received data and a match.
+   */
+  public function testProcessWithUserAndUserMatch() {
+    $event = new CollectEvent($this->submission);
+    $contact = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $contact_match = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $activity = $this->getMockBuilder('Drupal\crm_core_activity\Entity\Activity')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/json'));
+    $this->submission->expects($this->any())
+      ->method('getData')
+      ->will($this->returnValue($this->json));
+
+    $this->contactStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'individual',
+        'contact_remote_id' => 'http://example.com/user/1',
+        'name' => 'dapibus',
+        'contact_mail' => array(
+          'dapibus@example.com',
+          'dapibus@example.com',
+        ),
+      ))
+      ->will($this->returnValue($contact));
+
+    $this->matcher->expects($this->once())
+      ->method('match')
+      ->with($contact)
+      ->will($this->returnValue(array(42)));
+
+    $this->contactStorage->expects($this->once())
+      ->method('load')
+      ->with(42)
+      ->will($this->returnValue($contact_match));
+
+    $contact->expects($this->any())
+      ->method('get')
+      ->will($this->returnValueMap(array(
+        array('contact_remote_id', (object) array('value' => 'http://example.com/user/42')),
+        array('name', (object) array('value' => 'Amet Dolor')),
+        array('contact_mail', (object) array('value' => 'amet@example.com')),
+      )));
+    $contact_match->expects($this->never())
+      ->method('set');
+
+    $contact_match->expects($this->never())
+      ->method('save');
+
+    $this->activityStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'contact',
+        'title' => $this->data['values']['subject'][0]['value'],
+        'activity_notes' => $this->data['values']['message'][0]['value'],
+        'activity_participants' => $contact_match,
+        'activity_submission' => $this->submission,
+      ))
+      ->will($this->returnValue($activity));
+
+    $activity->expects($this->once())
+      ->method('save');
+
+    $this->subscriber->process($event);
+  }
+
+  /**
+   * Tests the processing with no user present in the received data and a match.
+   */
+  public function testProcessWithoutUserAndUserMatch() {
+    $data = $this->data;
+    $data['user'] = NULL;
+
+    $event = new CollectEvent($this->submission);
+    $contact = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $contact_match = $this->getMockBuilder('Drupal\crm_core_contact\Entity\Contact')
+      ->disableOriginalConstructor()
+      ->getMock();
+    $activity = $this->getMockBuilder('Drupal\crm_core_activity\Entity\Activity')
+      ->disableOriginalConstructor()
+      ->getMock();
+
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/json'));
+    $this->submission->expects($this->any())
+      ->method('getType')
+      ->will($this->returnValue('application/json'));
+
+    $this->submission->expects($this->any())
+      ->method('getData')
+      ->will($this->returnValue(json_encode($data)));
+
+    $this->contactStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'individual',
+        'name' => 'Ullamcorper Fermentum',
+        'contact_mail' => array(
+          'ullamcorper@example.com',
+        ),
+      ))
+      ->will($this->returnValue($contact));
+
+    $this->matcher->expects($this->once())
+      ->method('match')
+      ->with($contact)
+      ->will($this->returnValue(array(42)));
+
+    $this->contactStorage->expects($this->once())
+      ->method('load')
+      ->with(42)
+      ->will($this->returnValue($contact_match));
+
+    $contact->expects($this->any())
+      ->method('get')
+      ->will($this->returnValueMap(array(
+        array('contact_remote_id', (object) array('value' => NULL)),
+        array('name', (object) array('value' => 'Amet Dolor')),
+        array('contact_mail', (object) array('value' => 'amet@example.com')),
+      )));
+
+    $contact_match->expects($this->never())
+      ->method('set');
+
+    $contact_match->expects($this->never())
+      ->method('save');
+
+    $this->activityStorage->expects($this->once())
+      ->method('create')
+      ->with(array(
+        'type' => 'contact',
+        'title' => $this->data['values']['subject'][0]['value'],
+        'activity_notes' => $this->data['values']['message'][0]['value'],
+        'activity_participants' => $contact_match,
+        'activity_submission' => $this->submission,
+      ))
+      ->will($this->returnValue($activity));
+
+    $activity->expects($this->once())
+      ->method('save');
+
+    $this->subscriber->process($event);
+  }
+}
diff --git b/crm_core/contact/tests/src/Unit/fixture.json a/crm_core/contact/tests/src/Unit/fixture.json
new file mode 100644
index 0000000..52d389d
--- /dev/null
+++ a/crm_core/contact/tests/src/Unit/fixture.json
@@ -0,0 +1,223 @@
+{
+  "user": {
+    "_links": {
+      "self": {
+        "href": "http://example.com/user/1"
+      },
+      "type": {
+        "href": "http://example.com/rest/type/user/user"
+      }
+    },
+    "uuid": [
+      {
+        "value": "6d8e652c-77ce-4c1a-9500-e1d59b4c80fc"
+      }
+    ],
+    "langcode": [
+      {
+        "value": "en"
+      }
+    ],
+    "preferred_langcode": [
+      {
+        "value": "und"
+      }
+    ],
+    "preferred_admin_langcode": [
+      {
+        "value": "und"
+      }
+    ],
+    "name": [
+      {
+        "value": "dapibus"
+      }
+    ],
+    "mail": [
+      {
+        "value": "dapibus@example.com"
+      }
+    ],
+    "timezone": [
+      {
+        "value": "Europe/Berlin"
+      }
+    ],
+    "status": [
+      {
+        "value": 1
+      }
+    ],
+    "created": [
+      {
+        "value": 1403211798
+      }
+    ],
+    "access": [
+      {
+        "value": 1403693295
+      }
+    ],
+    "login": [
+      {
+        "value": 1403212044
+      }
+    ],
+    "init": [
+      {
+        "value": "dapibus@example.com"
+      }
+    ],
+    "roles": [
+      {
+        "value": "authenticated"
+      },
+      {
+        "value": "administrator"
+      }
+    ]
+  },
+  "fields": {
+    "category": {
+      "type": "entity_reference",
+      "label": "Category ID",
+      "description": "The ID of the associated category.",
+      "required": true,
+      "properties": {
+        "target_id": {
+          "type": "string",
+          "label": "Entity ID",
+          "description": null
+        },
+        "entity": {
+          "type": "entity_reference",
+          "label": "Entity",
+          "description": "The referenced entity"
+        }
+      }
+    },
+    "name": {
+      "type": "string",
+      "label": "The sender's name",
+      "description": "The name of the person that is sending the contact message.",
+      "required": false,
+      "properties": {
+        "value": {
+          "type": "string",
+          "label": "Text value",
+          "description": null
+        }
+      }
+    },
+    "mail": {
+      "type": "email",
+      "label": "The sender's email",
+      "description": "The email of the person that is sending the contact message.",
+      "required": false,
+      "properties": {
+        "value": {
+          "type": "email",
+          "label": "Email value",
+          "description": null
+        }
+      }
+    },
+    "subject": {
+      "type": "string",
+      "label": "The message subject",
+      "description": "The subject of the contact message.",
+      "required": false,
+      "properties": {
+        "value": {
+          "type": "string",
+          "label": "Text value",
+          "description": null
+        }
+      }
+    },
+    "message": {
+      "type": "string",
+      "label": "The message text",
+      "description": "The text of the contact message.",
+      "required": false,
+      "properties": {
+        "value": {
+          "type": "string",
+          "label": "Text value",
+          "description": null
+        }
+      }
+    },
+    "copy": {
+      "type": "boolean",
+      "label": "Copy",
+      "description": "Whether to send a copy of the message to the sender.",
+      "required": false,
+      "properties": {
+        "value": {
+          "type": "boolean",
+          "label": "Boolean value",
+          "description": null
+        }
+      }
+    },
+    "recipient": {
+      "type": "entity_reference",
+      "label": "Recipient ID",
+      "description": "The ID of the recipient user for personal contact messages.",
+      "required": false,
+      "properties": {
+        "target_id": {
+          "type": "integer",
+          "label": "Entity ID",
+          "description": null
+        },
+        "entity": {
+          "type": "entity_reference",
+          "label": "Entity",
+          "description": "The referenced entity"
+        }
+      }
+    }
+  },
+  "values": {
+    "_links": {
+      "self": {
+        "href": ""
+      },
+      "type": {
+        "href": "http://client/rest/type/contact_message/feedback"
+      }
+    },
+    "category": [
+      {
+        "target_id": "feedback"
+      }
+    ],
+    "name": [
+      {
+        "value": "Ullamcorper Fermentum"
+      }
+    ],
+    "mail": [
+      {
+        "value": "ullamcorper@example.com"
+      }
+    ],
+    "subject": [
+      {
+        "value": "Aenean lacinia bibendum nulla sed consectetur"
+      }
+    ],
+    "message": [
+      {
+        "value": "Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Maecenas faucibus mollis interdum. Donec id elit non mi porta gravida at eget metus. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Integer posuere erat a ante venenatis dapibus posuere velit aliquet.\r\n\r\nVivamus sagittis lacus vel augue laoreet rutrum faucibus dolor auctor. Nulla vitae elit libero, a pharetra augue. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Donec sed odio dui. Lorem ipsum dolor sit amet, consectetur adipiscing elit."
+      }
+    ],
+    "copy": [
+      {
+        "value": 0
+      }
+    ]
+  }
+}
