diff --git a/__tests__/src/actions/annotation.test.js b/__tests__/src/actions/annotation.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..97632ae57aae911eb3198c311d417847302389af
--- /dev/null
+++ b/__tests__/src/actions/annotation.test.js
@@ -0,0 +1,110 @@
+import configureMockStore from 'redux-mock-store';
+import thunk from 'redux-thunk';
+
+import * as actions from '../../../src/state/actions';
+import ActionTypes from '../../../src/state/actions/action-types';
+
+const middlewares = [thunk];
+const mockStore = configureMockStore(middlewares);
+
+describe('annotation actions', () => {
+  describe('requestAnnotation', () => {
+    it('requests an annotation from given a url', () => {
+      const canvasId = 'foo';
+      const annotationId = 'abc123';
+      const expectedAction = {
+        type: ActionTypes.REQUEST_ANNOTATION,
+        canvasId,
+        annotationId,
+      };
+      expect(actions.requestAnnotation(canvasId, annotationId)).toEqual(expectedAction);
+    });
+  });
+  describe('receiveAnnotation', () => {
+    it('recieves an annotation', () => {
+      const canvasId = 'foo';
+      const annotationId = 'abc123';
+      const json = {
+        annotationId,
+        content: 'annotation request',
+      };
+      const expectedAction = {
+        type: ActionTypes.RECEIVE_ANNOTATION,
+        canvasId,
+        annotationId,
+        annotationJson: json,
+      };
+      expect(actions.receiveAnnotation(canvasId, annotationId, json)).toEqual(expectedAction);
+    });
+  });
+  describe('fetchAnnotation', () => {
+    let store = null;
+    beforeEach(() => {
+      store = mockStore({});
+    });
+    describe('success response', () => {
+      beforeEach(() => {
+        fetch.mockResponseOnce(JSON.stringify({ data: '12345' })); // eslint-disable-line no-undef
+      });
+      it('dispatches the REQUEST_ANNOTATION action', () => {
+        store.dispatch(actions.fetchAnnotation(
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+        ));
+        expect(store.getActions()).toEqual([
+          {
+            canvasId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+            annotationId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+            type: 'REQUEST_ANNOTATION',
+          },
+        ]);
+      });
+      it('dispatches the REQUEST_ANNOTATION and then RECEIVE_ANNOTATION', () => {
+        store.dispatch(actions.fetchAnnotation(
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+        ))
+          .then(() => {
+            const expectedActions = store.getActions();
+            expect(expectedActions).toEqual([
+              {
+                canvasId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+                annotationId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+                type: 'REQUEST_ANNOTATION',
+              },
+              {
+                canvasId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+                annotationId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+                annotationJson: { data: '12345' },
+                type: 'RECEIVE_ANNOTATION',
+              },
+            ]);
+          });
+      });
+    });
+    describe('error response', () => {
+      it('dispatches the REQUEST_ANNOTATION and then RECEIVE_ANNOTATION', () => {
+        store.dispatch(actions.fetchAnnotation(
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+          'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+        ))
+          .then(() => {
+            const expectedActions = store.getActions();
+            expect(expectedActions).toEqual([
+              {
+                canvasId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+                annotationId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+                type: 'REQUEST_ANNOTATION',
+              },
+              {
+                canvasId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/canvas/canvas-47174896',
+                annotationId: 'https://iiif.harvardartmuseums.org/manifests/object/299843/list/47174896',
+                error: new Error('invalid json response body at undefined reason: Unexpected end of JSON input'),
+                type: 'RECEIVE_ANNOTATION_FAILURE',
+              },
+            ]);
+          });
+      });
+    });
+  });
+});
diff --git a/__tests__/src/reducers/annotations.test.js b/__tests__/src/reducers/annotations.test.js
new file mode 100644
index 0000000000000000000000000000000000000000..5b54799254802fe883a86e105e48380d60774e3a
--- /dev/null
+++ b/__tests__/src/reducers/annotations.test.js
@@ -0,0 +1,75 @@
+import { annotationsReducer } from '../../../src/state/reducers/annotations';
+import ActionTypes from '../../../src/state/actions/action-types';
+
+describe('annotation reducer', () => {
+  it('should handle REQUEST_ANNOTATION', () => {
+    expect(annotationsReducer({}, {
+      type: ActionTypes.REQUEST_ANNOTATION,
+      canvasId: 'foo',
+      annotationId: 'abc123',
+    })).toEqual({
+      foo: {
+        abc123: {
+          id: 'abc123',
+          isFetching: true,
+        },
+      },
+    });
+  });
+  it('should handle RECEIVE_ANNOTATION', () => {
+    expect(annotationsReducer(
+      {
+        foo: {
+          abc123: {
+            id: 'abc123',
+            isFetching: true,
+          },
+        },
+      },
+      {
+        type: ActionTypes.RECEIVE_ANNOTATION,
+        canvasId: 'foo',
+        annotationId: 'abc123',
+        annotationJson: {
+          id: 'abc123',
+          '@type': 'sc:AnnotationList',
+          content: 'anno stuff',
+        },
+      },
+    )).toMatchObject({
+      foo: {
+        abc123: {
+          id: 'abc123',
+          isFetching: false,
+          json: {},
+        },
+      },
+    });
+  });
+  it('should handle RECEIVE_ANNOTATION_FAILURE', () => {
+    expect(annotationsReducer(
+      {
+        foo: {
+          abc123: {
+            id: 'abc123',
+            isFetching: true,
+          },
+        },
+      },
+      {
+        type: ActionTypes.RECEIVE_ANNOTATION_FAILURE,
+        canvasId: 'foo',
+        annotationId: 'abc123',
+        error: "This institution didn't enable CORS.",
+      },
+    )).toEqual({
+      foo: {
+        abc123: {
+          id: 'abc123',
+          isFetching: false,
+          error: "This institution didn't enable CORS.",
+        },
+      },
+    });
+  });
+});
diff --git a/src/state/actions/action-types.js b/src/state/actions/action-types.js
index e6ebd50c6d6f7f35894f7e334631411df9afac2c..36857f308053af1571dd2bbfc96a08e2e13544df 100644
--- a/src/state/actions/action-types.js
+++ b/src/state/actions/action-types.js
@@ -4,6 +4,10 @@ const ActionTypes = {
   REMOVE_COMPANION_WINDOW: 'REMOVE_COMPANION_WINDOW',
   UPDATE_WINDOW: 'UPDATE_WINDOW',
 
+  REQUEST_ANNOTATION: 'REQUEST_ANNOTATION',
+  RECEIVE_ANNOTATION: 'RECEIVE_ANNOTATION',
+  RECEIVE_ANNOTATION_FAILURE: 'RECEIVE_ANNOTATION_FAILURE',
+
   FOCUS_WINDOW: 'FOCUS_WINDOW',
   SET_WORKSPACE_FULLSCREEN: 'SET_WORKSPACE_FULLSCREEN',
   SET_WORKSPACE_VIEWPORT_POSITION: 'SET_WORKSPACE_VIEWPORT_POSITION',
diff --git a/src/state/actions/annotation.js b/src/state/actions/annotation.js
new file mode 100644
index 0000000000000000000000000000000000000000..4924945b0adb58bb1dcaf84828a48cb7315da5a5
--- /dev/null
+++ b/src/state/actions/annotation.js
@@ -0,0 +1,67 @@
+import fetch from 'node-fetch';
+import ActionTypes from './action-types';
+
+/**
+ * requestAnnotation - action creator
+ *
+ * @param  {String} canvasId
+ * @param  {String} annotationId
+ * @memberof ActionCreators
+ */
+export function requestAnnotation(canvasId, annotationId) {
+  return {
+    type: ActionTypes.REQUEST_ANNOTATION,
+    canvasId,
+    annotationId,
+  };
+}
+
+/**
+ * receiveAnnotation - action creator
+ *
+ * @param  {String} canvasId
+ * @param  {String} annotationId
+ * @param  {Object} annotationJson
+ * @memberof ActionCreators
+ */
+export function receiveAnnotation(canvasId, annotationId, annotationJson) {
+  return {
+    type: ActionTypes.RECEIVE_ANNOTATION,
+    canvasId,
+    annotationId,
+    annotationJson,
+  };
+}
+
+/**
+ * receiveAnnotationFailure - action creator
+ *
+ * @param  {String} canvasId
+ * @param  {String} annotationId
+ * @param  {String} error
+ * @memberof ActionCreators
+ */
+export function receiveAnnotationFailure(canvasId, annotationId, error) {
+  return {
+    type: ActionTypes.RECEIVE_ANNOTATION_FAILURE,
+    canvasId,
+    annotationId,
+    error,
+  };
+}
+
+/**
+ * fetchAnnotation - action creator
+ *
+ * @param  {String} annotationId
+ * @memberof ActionCreators
+ */
+export function fetchAnnotation(canvasId, annotationId) {
+  return ((dispatch) => {
+    dispatch(requestAnnotation(canvasId, annotationId));
+    return fetch(annotationId)
+      .then(response => response.json())
+      .then(json => dispatch(receiveAnnotation(canvasId, annotationId, json)))
+      .catch(error => dispatch(receiveAnnotationFailure(canvasId, annotationId, error)));
+  });
+}
diff --git a/src/state/actions/index.js b/src/state/actions/index.js
index 465e1fd28e821c29b4f49679fa3b1520fb3bbd02..9465bc715a3c952c12b4ac7a98b8f0daa232e9db 100644
--- a/src/state/actions/index.js
+++ b/src/state/actions/index.js
@@ -9,3 +9,4 @@ export * from './manifest';
 export * from './infoResponse';
 export * from './canvas';
 export * from './workspace';
+export * from './annotation';
diff --git a/src/state/reducers/annotations.js b/src/state/reducers/annotations.js
new file mode 100644
index 0000000000000000000000000000000000000000..140b68bb72f8555a7f8834f1731c5dc7632c18a2
--- /dev/null
+++ b/src/state/reducers/annotations.js
@@ -0,0 +1,42 @@
+import ActionTypes from '../actions/action-types';
+
+/**
+ * annotationReducer
+ */
+export const annotationsReducer = (state = {}, action) => {
+  switch (action.type) {
+    case ActionTypes.REQUEST_ANNOTATION:
+      return {
+        ...state,
+        [action.canvasId]: {
+          [action.annotationId]: {
+            id: action.annotationId,
+            isFetching: true,
+          },
+        },
+      };
+    case ActionTypes.RECEIVE_ANNOTATION:
+      return {
+        ...state,
+        [action.canvasId]: {
+          [action.annotationId]: {
+            id: action.annotationId,
+            json: action.annotationJson,
+            isFetching: false,
+          },
+        },
+      };
+    case ActionTypes.RECEIVE_ANNOTATION_FAILURE:
+      return {
+        ...state,
+        [action.canvasId]: {
+          [action.annotationId]: {
+            id: action.annotationId,
+            error: action.error,
+            isFetching: false,
+          },
+        },
+      };
+    default: return state;
+  }
+};
diff --git a/src/state/reducers/index.js b/src/state/reducers/index.js
index 478ac4467e511e258bce3edd51967b9d7496cc10..481f808243359fe4fe7b9d1038e7e2c26e5eb3de 100644
--- a/src/state/reducers/index.js
+++ b/src/state/reducers/index.js
@@ -5,3 +5,4 @@ export * from './manifests';
 export * from './infoResponses';
 export * from './config';
 export * from './viewers';
+export * from './annotations';
diff --git a/src/state/reducers/rootReducer.js b/src/state/reducers/rootReducer.js
index 927420a4fad8f8429abb6c7dbbb41da45f9e4675..087b0024c73299247d717b6865c9dafbd991d8d9 100644
--- a/src/state/reducers/rootReducer.js
+++ b/src/state/reducers/rootReducer.js
@@ -7,6 +7,7 @@ import {
   viewersReducer,
   windowsReducer,
   workspaceReducer,
+  annotationsReducer,
 } from '.';
 
 /**
@@ -23,6 +24,7 @@ export default function createRootReducer(pluginReducers) {
     infoResponses: infoResponsesReducer,
     config: configReducer,
     viewers: viewersReducer,
+    annotations: annotationsReducer,
     ...pluginReducers,
   });
 }