diff --git a/django/website/data_layer/tests/item_tests.py b/django/website/data_layer/tests/item_tests.py
new file mode 100644
index 0000000000000000000000000000000000000000..d69158a868a73a76af6c9870ca0af1f9f6bfb6ea
--- /dev/null
+++ b/django/website/data_layer/tests/item_tests.py
@@ -0,0 +1,35 @@
+import pytest
+
+from .factories import ItemFactory
+from taxonomies.tests.factories import TermFactory, TaxonomyFactory
+
+
+@pytest.mark.django_db
+def test_apply_term_replaces_term_for_categories():
+    item = ItemFactory()
+    taxonomy = TaxonomyFactory()  # Ensure multiplicity = optional
+    term1 = TermFactory(taxonomy=taxonomy)
+    term2 = TermFactory(taxonomy=taxonomy)
+    assert taxonomy.is_optional
+
+    item.apply_term(term1)
+    assert list(item.terms.all()) == [term1]
+
+    item.apply_term(term2)
+    assert list(item.terms.all()) == [term2]
+
+@pytest.mark.xfail
+# I'm putting this here to explain some of my thinking.
+@pytest.mark.django_db
+def test_apply_term_adds_term_for_tags():
+    item = ItemFactory()
+    taxonomy = TaxonomyFactory()  # Ensure multiplicity == multiple
+    term1 = TermFactory(taxonomy=taxonomy)
+    term2 = TermFactory(taxonomy=taxonomy)
+    assert taxonomy.is_multiple
+
+    item.apply_term(term1)
+    assert list(item.terms.all()) == [term1]
+
+    item.apply_term(term2)
+    assert set(item.terms.all()) == set([term1, term2])
diff --git a/django/website/hid/tests/categorize_items_tests.py b/django/website/hid/tests/categorize_items_tests.py
index 1a787e49c6322eb62fcca8905694836b9f0bc4f0..d85a6023facf973b7f486ba6b29438b450162a7a 100644
--- a/django/website/hid/tests/categorize_items_tests.py
+++ b/django/website/hid/tests/categorize_items_tests.py
@@ -13,6 +13,13 @@ from ..views import add_items_categories
 ReqFactory = RequestFactory()
 
 
+@pytest.fixture
+def term():
+    # TODO rewrite using transport.terms, etc.
+    taxonomy = TaxonomyFactory(name="Test Ebola Questions")
+    return TermFactory(taxonomy=taxonomy, name="Vaccine")
+
+
 @pytest.fixture
 def terms():
     # TODO rewrite using transport.terms, etc.
@@ -31,6 +38,26 @@ def items():
     ]
 
 
+@pytest.fixture
+def item():
+    return transport.items.create({'body': 'test message one'})
+
+
+@pytest.mark.django_db
+def test_add_categories_adds_term_to_item(term, item):
+    category_list = [(item['id'], term.taxonomy.slug, term.name), ]
+
+    url = reverse('data-view-process')
+    request = ReqFactory.post(url, {'a': 'b'})
+    request = fix_messages(request)
+    add_items_categories(request, category_list)
+
+    [item_data] = transport.items.list()
+    [term_data] = item_data['terms']
+    assert term_data['name'] == term.name
+    assert term_data['taxonomy'] == term.taxonomy.slug
+
+
 @pytest.mark.django_db
 def test_add_items_categories_adds_term_to_items(terms, items):
     url = reverse('data-view-process')
diff --git a/django/website/rest_api/tests/categorize_items_tests.py b/django/website/rest_api/tests/categorize_items_tests.py
index 91d467b43464fc204cfaedf249eb23263b33b119..d06392f0d3dc23123d0f90ba2290b2e6c3900bcb 100644
--- a/django/website/rest_api/tests/categorize_items_tests.py
+++ b/django/website/rest_api/tests/categorize_items_tests.py
@@ -70,6 +70,15 @@ def test_item_can_haz_category(term, item):
 
 # TODO test for terms with the same name in different taxonomies
 
+@pytest.mark.django_db
+def test_categorize_item_returns_the_categorized_item(term, item):
+    result = categorize_item(item, term).data
+
+    assert result['id'] == item['id']
+    terms = result['terms']
+    assert term in terms
+
+
 @pytest.mark.django_db
 def test_categorize_item_fails_gracefully_if_term_not_found(item):
     response = categorize_item(
@@ -81,6 +90,15 @@ def test_categorize_item_fails_gracefully_if_term_not_found(item):
     assert response.data['detail'] == "Term matching query does not exist."
 
 
+@pytest.mark.django_db
+def test_categorize_item_fails_gracefully_if_item_not_found(term, item):
+    unknown_item_id = 6  # I am not a prisoner
+    response = categorize_item({'id': unknown_item_id}, term)
+
+    assert response.status_code == status.HTTP_404_NOT_FOUND
+    assert response.data['detail'] == "Message matching query does not exist."
+
+
 @pytest.mark.django_db
 def test_only_one_category_per_item_per_taxonomy(item, term, second_term):
     """
diff --git a/django/website/rest_api/views.py b/django/website/rest_api/views.py
index 2ea8627f98554e13976f1145a0e8cd31d087a12f..f58b2910d48f15bf149d92168e8fe471ee50fa9c 100644
--- a/django/website/rest_api/views.py
+++ b/django/website/rest_api/views.py
@@ -37,7 +37,12 @@ class ItemViewSet(viewsets.ModelViewSet, BulkDestroyModelMixin):
 
     @detail_route(methods=['post'])
     def add_term(self, request, item_pk):
-        item = Item.objects.get(pk=item_pk)
+        try:
+            item = Item.objects.get(pk=item_pk)
+        except Item.DoesNotExist as e:
+            data = {'detail': e.message}
+            return Response(data, status=status.HTTP_404_NOT_FOUND)
+
         term_data = request.data
         try:
             term = Term.objects.by_taxonomy(
@@ -49,8 +54,9 @@ class ItemViewSet(viewsets.ModelViewSet, BulkDestroyModelMixin):
             return Response(data, status=status.HTTP_400_BAD_REQUEST)
 
         item.apply_term(term)
-        data = {}  # TODO should be the item containing the new term
-        return Response(data, status=status.HTTP_200_OK)
+
+        serializer = ItemSerializer(item)
+        return Response(serializer.data, status=status.HTTP_200_OK)
 
 
 class TaxonomyViewSet(viewsets.ModelViewSet):
diff --git a/django/website/taxonomies/models.py b/django/website/taxonomies/models.py
index 5d50b06936790e18db0bff24cc2e71a2f7e33ff6..da8295e2aca041c95359430ab217f4bf2a191a81 100644
--- a/django/website/taxonomies/models.py
+++ b/django/website/taxonomies/models.py
@@ -82,7 +82,10 @@ class TermManager(models.Manager):
             raise ValueError(
                 "taxonomy must be a Taxonomy instance "
                 "or a valid taxonomy slug")
-        return self.get(taxonomy__slug=taxonomy_slug, name=name)
+        return self.select_related('taxonomy').get(
+            taxonomy__slug=taxonomy_slug,
+            name=name
+        )
 
 
 class Term(models.Model):
diff --git a/django/website/transport/items.py b/django/website/transport/items.py
index 1bf54b00bc2adc0e53be8e573eade7dc6625f6a7..e7691947c442835c2efe4f4689fd77c13d38f8c5 100644
--- a/django/website/transport/items.py
+++ b/django/website/transport/items.py
@@ -113,4 +113,6 @@ def add_term(item_id, taxonomy_slug, name):
         return response.data
     else:
         response.data['status_code'] = response.status_code
+        response.data['term'] = term
+        response.data['item_id'] = item_id
         raise TransportException(response.data)
diff --git a/django/website/transport/tests/item_add_term_tests.py b/django/website/transport/tests/item_add_term_tests.py
index 1c189de16477b5ec06be65442bd5040c4f8904b6..0e877ecdd72457e0ad4c9c43a65b34ad51c67035 100644
--- a/django/website/transport/tests/item_add_term_tests.py
+++ b/django/website/transport/tests/item_add_term_tests.py
@@ -3,9 +3,7 @@ import pytest
 
 from data_layer.models import Item
 
-from taxonomies.tests.factories import (
-    TaxonomyFactory,
-    TermFactory)
+from taxonomies.tests.factories import TermFactory
 from transport import items
 from ..exceptions import TransportException
 
@@ -42,3 +40,19 @@ def test_add_term_fails_if_term_does_not_exist(item_data):
 
     assert error['status_code'] == 400
     assert error['detail'] == "Term matching query does not exist."
+    assert error['term']['name'] == "unknown term name"
+
+
+@pytest.mark.django_db
+def test_add_term_fails_if_item_does_not_exist():
+    with pytest.raises(TransportException) as excinfo:
+        term = TermFactory()
+        unknown_item_id = 6  # I am a Free Man
+        items.add_term(unknown_item_id, term.taxonomy.slug, term.name)
+
+    error = excinfo.value.message
+
+    assert error['status_code'] == 404
+    assert error['detail'] == "Message matching query does not exist."
+    # TODO: assert error['detail'] == "Item matching query does not exist."
+    assert error['item_id'] == unknown_item_id