diff --git a/doc/source/conf.py b/doc/source/conf.py
index 7e5ca83c..a2ca3008 100755
--- a/doc/source/conf.py
+++ b/doc/source/conf.py
@@ -79,3 +79,17 @@ latex_documents = [
 
 # Example configuration for intersphinx: refer to the Python standard library.
 intersphinx_mapping = {'http://docs.python.org/': None}
+
+
+def skip_methods(app, what, name, obj, skip, options):
+    # We have a blacklist because wsme's autodoc extension doesn't like
+    # inherited attributes.
+    blacklist = ('id', 'created_at', 'updated_at')
+    if hasattr(obj, 'nodoc') or not hasattr(obj, 'datatype')\
+            or name in blacklist:
+        return True
+    return False
+
+
+def setup(app):
+    app.connect('autodoc-skip-member', skip_methods)
diff --git a/doc/source/webapi/v1.rst b/doc/source/webapi/v1.rst
index a783ae5e..d94812b6 100644
--- a/doc/source/webapi/v1.rst
+++ b/doc/source/webapi/v1.rst
@@ -132,42 +132,85 @@ Permissions
 Object model
 ############
 
-Project
-=======
-.. autotype:: storyboard.api.v1.projects.Project
-   :members:
-
-
 Story
 =====
-.. autotype:: storyboard.api.v1.stories.Story
-   :members:
-
-
-Comment
-=======
-.. autotype:: storyboard.api.v1.timeline.Comment
-   :members:
-
-
-Timeline event
-==============
-.. autotype:: storyboard.api.v1.timeline.TimeLineEvent
+.. autotype:: storyboard.api.v1.wmodels.Story
    :members:
 
 
 Task
 ====
-.. autotype:: storyboard.api.v1.tasks.Task
+.. autotype:: storyboard.api.v1.wmodels.Task
    :members:
 
 
+Project
+=======
+.. autotype:: storyboard.api.v1.wmodels.Project
+   :members:
+
+
+ProjectGroup
+============
+.. autotype:: storyboard.api.v1.wmodels.ProjectGroup
+   :members:
+
+
+Comment
+=======
+.. autotype:: storyboard.api.v1.wmodels.Comment
+   :members:
+
+
+Timeline event
+==============
+.. autotype:: storyboard.api.v1.wmodels.TimeLineEvent
+   :members:
+
+
+Due Date
+========
+.. autotype:: storyboard.api.v1.wmodels.DueDate
+   :members:
+
+
+Board
+=====
+.. autotype:: storyboard.api.v1.wmodels.Board
+    :members:
+
+
+Worklist
+========
+.. autotype:: storyboard.api.v1.wmodels.Worklist
+    :members:
+
+
+WorklistItem
+============
+.. autotype:: storyboard.api.v1.wmodels.WorklistItem
+    :members:
+
+
+WorklistFilter
+==============
+.. autotype:: storyboard.api.v1.wmodels.WorklistFilter
+    :members:
+
+
+FilterCriterion
+===============
+.. autotype:: storyboard.api.v1.wmodels.FilterCriterion
+    :members:
+
+
 User
 ====
-.. autotype:: storyboard.api.v1.users.User
+.. autotype:: storyboard.api.v1.wmodels.User
    :members:
 
+
 SystemInfo
 ==========
-.. autotype:: storyboard.api.v1.system_info.SystemInfo
+.. autotype:: storyboard.api.v1.wmodels.SystemInfo
    :members:
diff --git a/storyboard/api/v1/wmodels.py b/storyboard/api/v1/wmodels.py
index a010fc09..6229fdb9 100644
--- a/storyboard/api/v1/wmodels.py
+++ b/storyboard/api/v1/wmodels.py
@@ -32,10 +32,14 @@ from storyboard.db.api import worklists as worklists_api
 from storyboard.db import models
 
 
+def nodoc(obj):
+    """Add a flag which autodoc can use to decide whether to skip a member."""
+    obj.nodoc = True
+    return obj
+
+
 class Comment(base.APIBase):
-    """Any user may leave comments for stories. Also comments api is used by
-    gerrit to leave service comments.
-    """
+    """Any user may leave comments on stories."""
 
     content = wtypes.text
     """The content of the comment."""
@@ -46,6 +50,15 @@ class Comment(base.APIBase):
     in_reply_to = int
     """The ID of the parent comment, if any."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=5,
+            created_at=datetime.fromtimestamp(1321009871),
+            content="A sample comment body.",
+            is_active=True,
+            in_reply_to=2)
+
 
 class SystemInfo(base.APIBase):
     """Represents the system information for Storyboard
@@ -93,6 +106,8 @@ class Project(base.APIBase):
     @classmethod
     def sample(cls):
         return cls(
+            id=3,
+            created_at=datetime.fromtimestamp(1321009871),
             name="StoryBoard",
             description="This is an awesome project.",
             is_active=True,
@@ -116,6 +131,8 @@ class ProjectGroup(base.APIBase):
     @classmethod
     def sample(cls):
         return cls(
+            id=1,
+            created_at=datetime.fromtimestamp(1321009871),
             name="Infra",
             title="Awesome projects")
 
@@ -125,6 +142,10 @@ class TaskStatusCount(base.APIBase):
     key = wtypes.text
     count = int
 
+    @classmethod
+    def sample(cls):
+        return cls(key='todo', count=2)
+
 
 class User(base.APIBase):
     """Represents a user."""
@@ -133,13 +154,14 @@ class User(base.APIBase):
     """Full (Display) name."""
 
     openid = wtypes.text
-    """The unique identifier, returned by an OpneId provider"""
+    """The unique identifier, returned by an OpenId provider"""
 
     email = wtypes.text
     """Email Address."""
 
     # Todo(nkonovalov): use teams to define superusers
     is_superuser = bool
+    """Whether or not the user has superuser permissions."""
 
     last_login = datetime
     """Date of the last login."""
@@ -150,6 +172,7 @@ class User(base.APIBase):
     @classmethod
     def sample(cls):
         return cls(
+            id=3,
             full_name="Bart Simpson",
             openid="https://login.launchpad.net/+id/Abacaba",
             email="skinnerstinks@springfield.net",
@@ -191,23 +214,29 @@ class Story(base.APIBase):
     """Tag list assigned to this story."""
 
     due_dates = wtypes.ArrayType(int)
+    """List of IDs of Due Dates which are related to this story."""
 
     private = bool
+    """Whether or not this story is private."""
 
     users = wtypes.ArrayType(User)
+    """The set of users with permission to see this story if it is private."""
 
     @classmethod
     def sample(cls):
         return cls(
+            id=425,
+            created_at=datetime.fromtimestamp(1321009871),
             title="Use Storyboard to manage Storyboard",
             description="We should use Storyboard to manage Storyboard.",
             is_bug=False,
             creator_id=1,
-            task_statuses=[TaskStatusCount],
+            task_statuses=[TaskStatusCount(key='todo', count=2)],
             story_type_id=1,
             status="active",
             tags=["t1", "t2"])
 
+    @nodoc
     def summarize_task_statuses(self, story_summary):
         """Populate the task_statuses array."""
         self.task_statuses = []
@@ -216,6 +245,7 @@ class Story(base.APIBase):
                 key=task_status, count=getattr(story_summary, task_status))
             self.task_statuses.append(task_count)
 
+    @nodoc
     def resolve_users(self, story):
         """Resolve the people who can see the story."""
         self.users = [User.from_db_model(user)
@@ -274,6 +304,22 @@ class Task(base.APIBase):
     """The ID of corresponding Milestone"""
 
     due_dates = wtypes.ArrayType(int)
+    """The IDs of due dates related to this task."""
+
+    @classmethod
+    def sample(cls):
+        return cls(
+            title="My really important task.",
+            status="todo",
+            creator_id=1,
+            story_id=3456,
+            link="Some notes about the task, this name is bad.",
+            project_id=1,
+            assignee_id=1,
+            priority="medium",
+            branch_id=1,
+            milestone_id=1,
+            due_dates=[1, 2, 3])
 
 
 class Branch(base.APIBase):
@@ -343,18 +389,15 @@ class Milestone(base.APIBase):
 
 
 class Team(base.APIBase):
-    """The Team is a group od Users with a fixed set of permissions.
-    """
+    """The Team is a group of Users with a fixed set of permissions."""
 
     name = NameType()
     """The Team unique name. This name will be displayed in the URL.
     At least 3 alphanumeric symbols. Minus and dot symbols are allowed as
-    separators.
-    """
+    separators."""
 
     description = wtypes.text
-    """Details about the team.
-    """
+    """Details about the team."""
 
     @classmethod
     def sample(cls):
@@ -387,6 +430,14 @@ class TimeLineEvent(base.APIBase):
     comment = Comment
     """The resolved comment."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=45543,
+            event_type="story_created",
+            event_info='{"story_id": 100, "story_title": "A story"}',
+            story_id=100)
+
     @staticmethod
     def resolve_event_values(event):
         if event.comment_id:
@@ -503,6 +554,15 @@ class FilterCriterion(base.APIBase):
     field = wtypes.text
     """The field to filter by."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            title='TaskStatus',
+            filter_id=1,
+            negative=True,
+            value='merged',
+            field='status')
+
 
 class WorklistFilter(base.APIBase):
     """Represents a set of criteria to filter items using AND."""
@@ -516,10 +576,25 @@ class WorklistFilter(base.APIBase):
     filter_criteria = wtypes.ArrayType(FilterCriterion)
     """The list of criteria to apply."""
 
+    @nodoc
     def resolve_criteria(self, filter):
         self.filter_criteria = [FilterCriterion.from_db_model(criterion)
                                 for criterion in filter.criteria]
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            type='Task',
+            list_id=1,
+            filter_criteria=[FilterCriterion(
+                type='Task',
+                title='TaskStatus',
+                filter_id=1,
+                negative=True,
+                value='merged',
+                field='status')
+            ])
+
 
 class DueDate(base.APIBase):
     """Represents a due date for tasks/stories."""
@@ -567,6 +642,23 @@ class DueDate(base.APIBase):
     assignable = bool
     """Whether or not the due date is assignable by the request sender."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=1,
+            name='A really great deadline',
+            date=datetime(2016, 5, 30, 10, 10),
+            private=False,
+            creator_id=3,
+            owners=[3],
+            users=[],
+            tasks=[],
+            stories=[],
+            count=0,
+            editable=True,
+            assignable=True)
+
+    @nodoc
     def resolve_count_in_board(self, due_date, board):
         self.count = 0
         for lane in board.lanes:
@@ -575,6 +667,7 @@ class DueDate(base.APIBase):
                 if card.display_due_date == due_date.id:
                     self.count += 1
 
+    @nodoc
     def resolve_items(self, due_date):
         """Resolve the various lists for the due date."""
         stories, tasks = due_dates_api.get_visible_items(
@@ -584,6 +677,7 @@ class DueDate(base.APIBase):
                         for story in stories]
         self.count = len(self.tasks) + len(self.stories)
 
+    @nodoc
     def resolve_permissions(self, due_date, user=None):
         """Resolve the permissions groups of the due date."""
         self.owners = due_dates_api.get_owners(due_date)
@@ -617,11 +711,26 @@ class WorklistItem(base.APIBase):
     """The ID of the due date displayed on this item."""
 
     resolved_due_date = DueDate
-    """The due date displayed on this item."""
+    """The Due Date displayed on this item."""
 
     task = Task
-    story = Story
+    """The Task referred to by this list item."""
 
+    story = Story
+    """The Story referred to by this list item."""
+
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=1,
+            list_id=1,
+            item_id=1,
+            item_type="story",
+            list_position=0,
+            archived=False,
+            display_due_date=None)
+
+    @nodoc
     def resolve_due_date(self, worklist_item):
         due_date = due_dates_api.get(worklist_item.display_due_date)
         resolved = None
@@ -629,6 +738,7 @@ class WorklistItem(base.APIBase):
             resolved = DueDate.from_db_model(due_date)
         self.resolved_due_date = resolved
 
+    @nodoc
     def resolve_item(self, item):
         user_id = request.current_user_id
         if item.item_type == 'story':
@@ -689,6 +799,21 @@ class Worklist(base.APIBase):
     items = wtypes.ArrayType(WorklistItem)
     """The items in the worklist."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=1,
+            title="My great worklist",
+            creator_id=1,
+            private=False,
+            archived=False,
+            automatic=False,
+            filters=[],
+            owners=[1],
+            users=[2],
+            items=[])
+
+    @nodoc
     def resolve_items(self, worklist):
         """Resolve the contents of this worklist."""
         self.items = []
@@ -698,6 +823,7 @@ class Worklist(base.APIBase):
         else:
             self._resolve_set_items(worklist, user_id)
 
+    @nodoc
     def _resolve_automatic_items(self, worklist, user_id):
         for item in worklists_api.filter_items(worklist):
             item_model = WorklistItem(**item)
@@ -708,6 +834,7 @@ class Worklist(base.APIBase):
             self.items.append(item_model)
         self.items.sort(key=lambda x: x.list_position)
 
+    @nodoc
     def _resolve_set_items(self, worklist, user_id):
         for item in worklist.items:
             if item.archived:
@@ -720,10 +847,12 @@ class Worklist(base.APIBase):
             self.items.append(item_model)
         self.items.sort(key=lambda x: x.list_position)
 
+    @nodoc
     def resolve_permissions(self, worklist):
         self.owners = worklists_api.get_owners(worklist)
         self.users = worklists_api.get_users(worklist)
 
+    @nodoc
     def resolve_filters(self, worklist):
         self.filters = []
         for filter in worklist.filters:
@@ -747,6 +876,26 @@ class Lane(base.APIBase):
     position = int
     """The position of the lane in the board."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=1,
+            board_id=23,
+            list_id=10,
+            position=1,
+            worklist=Worklist(
+                id=1,
+                title="My great worklist",
+                creator_id=1,
+                private=False,
+                archived=False,
+                automatic=False,
+                filters=[],
+                owners=[1],
+                users=[2],
+                items=[]))
+
+    @nodoc
     def resolve_list(self, lane, resolve_items=True):
         """Resolve the worklist which represents the lane."""
         self.worklist = Worklist.from_db_model(lane.worklist)
@@ -797,6 +946,36 @@ class Board(base.APIBase):
     users = wtypes.ArrayType(int)
     """A list of the IDs of the users who can move cards in the board."""
 
+    @classmethod
+    def sample(cls):
+        return cls(
+            id=1,
+            title="StoryBoard development",
+            description="Board for tracking StoryBoard development.",
+            creator_id=1,
+            private=False,
+            archived=False,
+            lanes=[Lane(
+                id=1,
+                board_id=23,
+                list_id=10,
+                position=1,
+                worklist=Worklist(
+                    id=1,
+                    title="My great worklist",
+                    creator_id=1,
+                    private=False,
+                    archived=False,
+                    automatic=False,
+                    filters=[],
+                    owners=[1],
+                    users=[2],
+                    items=[]))],
+            due_dates=[],
+            owners=[1],
+            users=[])
+
+    @nodoc
     def resolve_lanes(self, board, resolve_items=True):
         """Resolve the lanes of the board."""
         self.lanes = []
@@ -806,6 +985,7 @@ class Board(base.APIBase):
             self.lanes.append(lane_model)
         self.lanes.sort(key=lambda x: x.position)
 
+    @nodoc
     def resolve_due_dates(self, board):
         self.due_dates = []
         for due_date in board.due_dates:
@@ -817,6 +997,7 @@ class Board(base.APIBase):
                 due_date_model.resolve_count_in_board(due_date, board)
                 self.due_dates.append(due_date_model)
 
+    @nodoc
     def resolve_permissions(self, board):
         """Resolve the permissions groups of the board."""
         self.owners = boards_api.get_owners(board)