diff --git a/config/webpack/browser.config.babel.js b/config/webpack/browser.config.babel.js
index aa3cddda9..ea906a301 100644
--- a/config/webpack/browser.config.babel.js
+++ b/config/webpack/browser.config.babel.js
@@ -74,7 +74,7 @@ const browserMin = {
   devtool: 'source-map',
   performance: {
     hints: 'error',
-    maxEntrypointSize: 270000,
+    maxEntrypointSize: 280000,
     maxAssetSize: 1300000,
   },
   output: {
diff --git a/src/resolver.js b/src/resolver.js
index 619355599..05db33b2d 100644
--- a/src/resolver.js
+++ b/src/resolver.js
@@ -25,6 +25,20 @@ export function clearCache() {
   plugins.refs.clearCache();
 }
 
+export function makeFetchRaw(http, opts = {}) {
+  const { requestInterceptor, responseInterceptor } = opts;
+  // Set credentials with 'http.withCredentials' value
+  const credentials = http.withCredentials ? 'include' : 'same-origin';
+  return (docPath) =>
+    http({
+      url: docPath,
+      loadSpec: true,
+      requestInterceptor,
+      responseInterceptor,
+      credentials,
+    }).then((res) => res.text);
+}
+
 export default function resolve(obj) {
   const {
     fetch,
@@ -66,8 +80,13 @@ export default function resolve(obj) {
 
     // Build a json-fetcher ( ie: give it a URL and get json out )
     plugins.refs.fetchJSON = makeFetchJSON(http, { requestInterceptor, responseInterceptor });
+    // Build a raw-fetcher ( ie: give it a URL and get raw text out )
+    plugins.externalValue.fetchRaw = makeFetchRaw(http, {
+      requestInterceptor,
+      responseInterceptor,
+    });
 
-    const plugs = [plugins.refs];
+    const plugs = [plugins.refs, plugins.externalValue];
 
     if (typeof parameterMacro === 'function') {
       plugs.push(plugins.parameters);
diff --git a/src/specmap/index.js b/src/specmap/index.js
index 1b5407704..bdc649c15 100644
--- a/src/specmap/index.js
+++ b/src/specmap/index.js
@@ -1,5 +1,6 @@
 import lib from './lib';
 import refs from './lib/refs';
+import externalValue from './lib/external-value';
 import allOf from './lib/all-of';
 import parameters from './lib/parameters';
 import properties from './lib/properties';
@@ -393,6 +394,7 @@ export default function mapSpec(opts) {
 
 const plugins = {
   refs,
+  externalValue,
   allOf,
   parameters,
   properties,
diff --git a/src/specmap/lib/external-value.js b/src/specmap/lib/external-value.js
new file mode 100644
index 000000000..63e6439b2
--- /dev/null
+++ b/src/specmap/lib/external-value.js
@@ -0,0 +1,242 @@
+import { fetch } from 'cross-fetch';
+
+import createError from './create-error';
+import lib from '.';
+import url from 'url';
+
+const externalValuesCache = {};
+
+
+/**
+ * Resolves a path(optional absolute) and its base to an abolute URL.
+ * @api public
+ */
+ function absoluteify(path, basePath) {
+  if (!ABSOLUTE_URL_REGEXP.test(path)) {
+    if (!basePath) {
+      throw new ExternalValueError(
+        `Tried to resolve a relative URL, without having a basePath. path: '${path}' basePath: '${basePath}'`
+      );
+    }
+    return url.resolve(basePath, path);
+  }
+  return path;
+}
+
+/**
+ * Clears all external value caches.
+ * @param  {String} url (optional) the original externalValue value of the cache item to be cleared.
+ * @api public
+ */
+function clearCache(url) {
+  if (typeof url !== 'undefined') {
+    delete externalValuesCache[url];
+  } else {
+    Object.keys(externalValuesCache).forEach((key) => {
+      delete externalValuesCache[key];
+    });
+  }
+}
+
+/**
+ * Fetches a document.
+ * @param  {String} docPath the absolute URL of the document.
+ * @return {Promise}        a promise of the document content.
+ * @api public
+ */
+const fetchRaw = (url) => fetch(url).then((res) => res.text);
+
+const shouldResolveTestFn = [
+  // OAS 3.0 Response Media Type Examples externalValue
+  (path) =>
+    // ["paths", *, *, "responses", *, "content", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[3] === 'responses' &&
+    path[5] === 'content' &&
+    path[7] === 'examples' &&
+    path[9] === 'externalValue',
+
+  // OAS 3.0 Request Body Media Type Examples externalValue
+  (path) =>
+    // ["paths", *, *, "requestBody", "content", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[3] === 'requestBody' &&
+    path[4] === 'content' &&
+    path[6] === 'examples' &&
+    path[8] === 'externalValue',
+
+  // OAS 3.0 Parameter Examples externalValue
+  (path) =>
+    // ["paths", *, "parameters", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[2] === 'parameters' &&
+    path[4] === 'examples' &&
+    path[6] === 'externalValue',
+  (path) =>
+    // ["paths", *, *, "parameters", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[3] === 'parameters' &&
+    path[5] === 'examples' &&
+    path[7] === 'externalValue',
+  (path) =>
+    // ["paths", *, "parameters", *, "content", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[2] === 'parameters' &&
+    path[4] === 'content' &&
+    path[6] === 'examples' &&
+    path[8] === 'externalValue',
+  (path) =>
+    // ["paths", *, *, "parameters", *, "content", *, "examples", *, "externalValue"]
+    path[0] === 'paths' &&
+    path[3] === 'parameters' &&
+    path[5] === 'content' &&
+    path[7] === 'examples' &&
+    path[9] === 'externalValue',
+];
+
+const shouldSkipResolution = (path) => !shouldResolveTestFn.some((fn) => fn(path));
+
+const ExternalValueError = createError('ExternalValueError', function cb(message, extra, oriError) {
+  this.originalError = oriError;
+  Object.assign(this, extra || {});
+});
+
+/**
+ * This plugin resolves externalValue keys.
+ * In order to do so it will use a cache in case the url was already requested.
+ * It will use the fetchRaw method in order get the raw content hosted on specified url.
+ * If successful retrieved it will replace the url with the actual value
+ */
+const plugin = {
+  key: 'externalValue',
+  plugin: (externalValue, _, fullPath, specmap, patch) => {
+    const parent = fullPath.slice(0, -1);
+    const parentObj = lib.getIn(patch.value, parent);
+
+    if (parentObj.value !== undefined) {
+      return undefined;
+    }
+
+    if (shouldSkipResolution(fullPath)) {
+      return undefined;
+    }
+    const { baseDoc } = specmap.getContext(fullPath);
+
+    if (typeof externalValue !== 'string') {
+      return new ExternalValueError('externalValue: must be a string', {
+        externalValue,
+        baseDoc,
+        fullPath,
+      });
+    }
+
+    const pathFragmentSplit = externalValue.split('#');
+    const externalValuePath = pathFragmentSplit[0];
+
+    let basePath;
+    try {
+      basePath = baseDoc || externalValuePath ? absoluteify(externalValuePath, baseDoc) : null;
+    } catch (e) {
+      return new ExternalValueError(
+        `Could not absoluteify externalValue: ${externalValue}`,
+        {
+          externalValue,
+          baseDoc,
+          fullPath,
+        }
+      );
+    }
+
+    try {
+      let externalValueOrPromise = getExternalValue(externalValue, fullPath);
+      if (typeof externalValueOrPromise === 'undefined') {
+        externalValueOrPromise = new ExternalValueError(
+          `Could not resolve externalValue: ${externalValue}`,
+          {
+            externalValue,
+            baseDoc,
+            fullPath,
+          }
+        );
+      }
+      // eslint-disable-next-line no-underscore-dangle
+      if (externalValueOrPromise.__value != null) {
+        // eslint-disable-next-line no-underscore-dangle
+        externalValueOrPromise = externalValueOrPromise.__value;
+      } else {
+        externalValueOrPromise = externalValueOrPromise.catch((e) => {
+          throw wrapError(e, {
+            externalValue,
+            fullPath,
+          });
+        });
+      }
+
+      if (externalValueOrPromise instanceof Error) {
+        return [lib.remove(fullPath), externalValueOrPromise];
+      }
+
+      const backupOriginalValuePatch = lib.add([...parent, '$externalValue'], externalValue);
+      const valuePatch = lib.replace([...parent, 'value'], externalValueOrPromise);
+      const cleanUpPatch = lib.remove(fullPath);
+      return [backupOriginalValuePatch, valuePatch, cleanUpPatch];
+    } catch (err) {
+      return [
+        lib.remove(fullPath),
+        wrapError(err, {
+          externalValue,
+          fullPath,
+        }),
+      ];
+    }
+  },
+};
+const mod = Object.assign(plugin, {
+  wrapError,
+  clearCache,
+  ExternalValueError,
+  fetchRaw,
+  getExternalValue,
+  absoluteify
+});
+export default mod;
+
+/**
+ * Wraps an error as ExternalValueError.
+ * @param  {Error} e      the error.
+ * @param  {Object} extra (optional) optional data.
+ * @return {Error}        an instance of ExternalValueError.
+ * @api public
+ */
+function wrapError(e, extra) {
+  let message;
+
+  if (e && e.response && e.response.body) {
+    message = `${e.response.body.code} ${e.response.body.message}`;
+  } else {
+    message = e.message;
+  }
+
+  return new ExternalValueError(`Could not resolve externalValue: ${message}`, extra, e);
+}
+
+/**
+ * Fetches and caches a ExternalValue.
+ * @param  {String} docPath the absolute URL of the document.
+ * @return {Promise}        a promise of the document content.
+ * @api public
+ */
+function getExternalValue(url) {
+  const val = externalValuesCache[url];
+  if (val) {
+    return lib.isPromise(val) ? val : Promise.resolve(val);
+  }
+
+  // NOTE: we need to use `mod.fetchRaw` in order to be able to overwrite it.
+  // Any tips on how to make this cleaner, please ping!
+  externalValuesCache[url] = mod.fetchRaw(url).then((raw) => {
+    externalValuesCache[url] = raw;
+    return raw;
+  });
+  return externalValuesCache[url];
+}
diff --git a/test/specmap/external-value.js b/test/specmap/external-value.js
new file mode 100644
index 000000000..5256f4ac4
--- /dev/null
+++ b/test/specmap/external-value.js
@@ -0,0 +1,100 @@
+import xmock from 'xmock';
+
+import mapSpec, { plugins } from '../../src/specmap';
+
+const { externalValue } = plugins;
+
+describe('externalValue', () => {
+  let xapp;
+
+  beforeAll(() => {
+    xapp = xmock();
+  });
+
+  afterAll(() => {
+    xapp.restore();
+  });
+
+  beforeEach(() => {
+    externalValue.clearCache();
+  });
+
+  describe('ExternalValueError', () => {
+    test('should contain the externalValue error details', () => {
+      try {
+        throw new externalValue.ExternalValueError('Probe', {
+          externalValue: 'http://test.com/probe',
+          fullPath: 'probe',
+        });
+      } catch (e) {
+        expect(e.toString()).toEqual('ExternalValueError: Probe');
+        expect(e.externalValue).toEqual('http://test.com/probe');
+        expect(e.fullPath).toEqual('probe');
+      }
+    });
+    test('.wrapError should wrap an error in ExternalValueError', () => {
+      try {
+        throw externalValue.wrapError(new Error('hi'), {
+          externalValue: 'http://test.com/probe',
+          fullPath: 'probe',
+        });
+      } catch (e) {
+        expect(e.message).toMatch(/externalValue/);
+        expect(e.message).toMatch(/hi/);
+        expect(e.externalValue).toEqual('http://test.com/probe');
+        expect(e.fullPath).toEqual('probe');
+      }
+    });
+  });
+
+  describe('externalValue Plugin value collision', () => {
+    const spec = {
+      paths: {
+        '/probe': {
+          get: {
+            responses: {
+              200: {
+                content: {
+                  '*/*': {
+                    examples: {
+                      probe: {
+                        externalValue: 'http://test.com/probe',
+                        value: 'test',
+                      },
+                    },
+                  },
+                },
+              },
+            },
+          },
+        },
+      },
+    };
+    test('should skip resolution of externalValue if value is defined', () =>
+      mapSpec({
+        spec,
+        plugins: [externalValue],
+      }).then((res) => {
+        expect(res.spec).toEqual(spec);
+      }));
+  });
+
+  describe('absoluteify', () => {
+    test('should find the absolute path for a url', () => {
+      const res = refs.absoluteify('/one', 'http://example.com');
+      expect(res).toEqual('http://example.com/one');
+    });
+
+    describe('relative paths', () => {
+      test('should think of the basePath as pointing to a document, so use the parent folder for resolution', () => {
+        const res = refs.absoluteify('one.json', 'http://example.com/two.json');
+        expect(res).toEqual('http://example.com/one.json');
+      });
+
+      test('should handle ../', () => {
+        const res = refs.absoluteify('../one.json', 'http://example.com/two/three/four.json');
+        expect(res).toEqual('http://example.com/two/one.json');
+      });
+    });
+  });
+});