diff --git a/environment.yml b/environment.yml
index 7db446c1709ee9866c8fd685f2c6ef21f553bbc5..db6fd6093cd09a0f0379c6a00aa8b1f90fa6f718 100644
--- a/environment.yml
+++ b/environment.yml
@@ -14,6 +14,7 @@ dependencies:
   - funcsigs=1.0.2
   - jxmlease=1.0
   - lxml=4.5
+  - marshmallow=3.7.1
   - mysqlclient=1.4
   - paramiko
   - pandas=1.0
diff --git a/services/workflow/src/workflow/server.py b/services/workflow/src/workflow/server.py
index 457015ac0190a5b8175fe8737d6b02e681f86169..ef17dffcbd6e5ca4d5a2f2e3e47fb0e5e03caf39 100644
--- a/services/workflow/src/workflow/server.py
+++ b/services/workflow/src/workflow/server.py
@@ -1,32 +1,14 @@
 import zope.sqlalchemy
-from pycapo import CapoConfig
-from pyramid.view import view_config, view_defaults
 from pyramid.config import Configurator
-from pyramid_beaker import session_factory_from_settings
 from pyramid.renderers import JSONP
-from sqlalchemy import create_engine
-from sqlalchemy.orm import sessionmaker
+from pyramid.view import view_config, view_defaults
+from pyramid_beaker import session_factory_from_settings
 from workspaces.services import WorkflowInfo, WorkflowService, get_session_factory, get_engine
 
 """
-Work done:
-
- ☑ Initial sketch of using SQL Alchemy with Pyramid
- ☑ Sketch of first routes we need
- ☑ Bring over interfaces from wksp0 project
- ☑ Need to flesh out the object model—requests have their own files, workflows have templates
- ☑ Separate REST hierarchy for workflow definitions
-
-Work to do:
-
- ☐ Actually do the work, preferably in model classes, not REST API directly
- ☐ Separate this into separate modules, once it makes sense to people how it works
- ☐ Workflow initiation CLI
-
 To consider:
  ☐ Do we want to use Marshmallow to validate inputs/generate API documentation?
  ☐ Do we want to have a separate package with interfaces/model? Or perhaps only JSON schemas?
-
 """
 
 
diff --git a/shared/workspaces/setup.py b/shared/workspaces/setup.py
index 533470dd88fd7de67f7b1bf6810170cc11b0848c..c015bfe242e3fee76789539baa38daa9931f2f95 100644
--- a/shared/workspaces/setup.py
+++ b/shared/workspaces/setup.py
@@ -9,6 +9,7 @@ README = Path('README.md').read_text()
 
 requires = [
     'pycapo',
+    'marshmallow',
     'schema',
     'sqlalchemy',
 ]
diff --git a/shared/workspaces/src/workspaces/json.py b/shared/workspaces/src/workspaces/json.py
new file mode 100644
index 0000000000000000000000000000000000000000..3da6d556dbe648b090fc16571deec562cbb06eaa
--- /dev/null
+++ b/shared/workspaces/src/workspaces/json.py
@@ -0,0 +1,19 @@
+from marshmallow import Schema, fields
+
+
+class WorkflowEventSchema(Schema):
+    """
+    Default schema for serializing WorkflowEvent.
+    """
+    job_name = fields.String()
+    type = fields.Method("get_type", deserialize="load_type")
+    timestamp = fields.DateTime()
+    log = fields.String()
+    retval = fields.Integer()
+
+    # Enums apparently are not a first-class field type in Marshmallow
+    def get_type(self, obj: "EventType") -> str:
+        return obj.type.value
+
+    def load_type(self, value: str) -> "EventType":
+        return EventType[value]