diff --git a/dist/adapter.esm.js b/dist/adapter.esm.js
index dfd3c838ef6639fc9506ebca8b26bf47c2429b6f..d79a030d469bd3fde4ab8fe19dad0a056f8ed65e 100644
--- a/dist/adapter.esm.js
+++ b/dist/adapter.esm.js
@@ -27,7 +27,10 @@ class Adapter {
   validate(message) {
     return this.validator.validate(
       message,
-      this.protocol.schema.definitions.Message
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
     );
   }
 
diff --git a/dist/adapter.js b/dist/adapter.js
index 5d4ae04b5da3f7fc16bed8586da3b545ef6bed5f..565f78dbfd4301d50e51ddcf7981f1c69943232d 100644
--- a/dist/adapter.js
+++ b/dist/adapter.js
@@ -29,7 +29,10 @@ class Adapter {
   validate(message) {
     return this.validator.validate(
       message,
-      this.protocol.schema.definitions.Message
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
     );
   }
 
diff --git a/dist/protocol.esm.js b/dist/protocol.esm.js
index bd50069d95117a2d8ff08f85b37dc4f8c878eef3..0b9a29f0b53148df63a5751b5fafdd8cb1d6a27a 100644
--- a/dist/protocol.esm.js
+++ b/dist/protocol.esm.js
@@ -35,7 +35,13 @@ class GenericProtocol {
    * @returns {object}
    */
   validate(message) {
-    return this.validator.validate(message, this.schema.definitions.Message);
+    return this.validator.validate(
+      message,
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
+    );
   }
 
   /**
diff --git a/dist/protocol.js b/dist/protocol.js
index 4ced40e9adc71012668693a495fee38e2cf30047..c5004e1f84c4cfe22664804963513cc6fd43a744 100644
--- a/dist/protocol.js
+++ b/dist/protocol.js
@@ -37,7 +37,13 @@ class GenericProtocol {
    * @returns {object}
    */
   validate(message) {
-    return this.validator.validate(message, this.schema.definitions.Message);
+    return this.validator.validate(
+      message,
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
+    );
   }
 
   /**
diff --git a/features/adapter/authenticates.js b/features/adapter/auth.js
similarity index 88%
rename from features/adapter/authenticates.js
rename to features/adapter/auth.js
index 373b9f00bd693e55157a259adf427c5e512f685d..4a64298638c8e7ba476739f09325a5c2c98b7f72 100644
--- a/features/adapter/authenticates.js
+++ b/features/adapter/auth.js
@@ -9,13 +9,21 @@ const mockAxios = new MockAdapter(axios);
 
 const { fixtures } = require('../../test/fixtures/server');
 
-const mockValidConfig = fixtures.get('valid-config');
-const mockInvalidConfig = fixtures.get('invalid-config');
+const mockValidConfig = fixtures.get('config-valid');
+const mockInvalidConfig = fixtures.get('config-invalid');
 
 const mockSchema = require('../../test/mock/swagger.json');
 const { Adapter } = require('../../dist/adapter');
 const { GenericProtocol } = require('../../dist/protocol');
 
+
+let decodeTracker;
+class TrackedGenericProtocol extends GenericProtocol {
+  decode() {
+    return super.decode()
+  }
+}
+
 Before(function() {
   this.mockAxios = mockAxios;
   this.mockAxios.reset();
diff --git a/features/adapter/receives.js b/features/adapter/poll.js
similarity index 89%
rename from features/adapter/receives.js
rename to features/adapter/poll.js
index 6cbf5bb0db52d2a54a53fb0c26787efad0df1bf1..76c537abe675d25078e0d3d5732f5109300b59b7 100644
--- a/features/adapter/receives.js
+++ b/features/adapter/poll.js
@@ -3,8 +3,7 @@ const { Before, Given, When, Then } = require('@cucumber/cucumber');
 
 const { fixtures } = require('../../test/fixtures/server');
 
-const mockValidConfig = fixtures.get('valid-config');
-const mockInvalidConfig = fixtures.get('invalid-config');
+const mockValidConfig = fixtures.get('config-valid');
 
 const xMessageResponse = function(xMessages) {
   const message = fixtures.get('message-vehicle-status');
diff --git a/features/adapter/validate.js b/features/adapter/validate.js
new file mode 100644
index 0000000000000000000000000000000000000000..db57e8e3cf9c7484445bbd05a71f9470269a2330
--- /dev/null
+++ b/features/adapter/validate.js
@@ -0,0 +1,26 @@
+const assert = require('assert');
+const { Before, Given, When, Then } = require('@cucumber/cucumber');
+
+const { fixtures } = require('../../test/fixtures/server');
+
+Given('a valid message', function() {
+  this.message = fixtures.get('message-vehicle-status');
+});
+
+Given('an invalid message', function() {
+  this.message = fixtures.get('message-vehicle-status-invalid');
+});
+
+When('the validate method is called', function() {
+  this.validation = this.adapter.validate(this.message);
+});
+
+Then('the message is validated successfully', function() {
+  assert.equal(this.validation.valid, true);
+  assert.equal(this.validation.errorCount, 0);
+});
+
+Then('the message fails to validate', function() {
+  assert.equal(this.validation.valid, false);
+  assert.notEqual(this.validation.errorCount, 0);
+});
\ No newline at end of file
diff --git a/features/adapter_validates.feature b/features/adapter_validates.feature
new file mode 100644
index 0000000000000000000000000000000000000000..c2af9f1ed21550495bc96952abc6793f436f236a
--- /dev/null
+++ b/features/adapter_validates.feature
@@ -0,0 +1,16 @@
+Feature: Can the adapter validate messages?
+  The adapter validate method works as expected
+
+  Scenario: A valid message is successfully validated against the protocol schema
+    Given valid config
+    Given a valid message
+    When the adapter instance is created
+    When the validate method is called
+    Then the message is validated successfully  
+  
+  Scenario: An invalid message fails to validate against the protocol schema
+    Given valid config
+    Given an invalid message
+    When the adapter instance is created
+    When the validate method is called
+    Then the message fails to validate  
\ No newline at end of file
diff --git a/features/schema/validate.js b/features/schema/validate.js
new file mode 100644
index 0000000000000000000000000000000000000000..58a4964594d054e8e9d43437d6dffa931e28931e
--- /dev/null
+++ b/features/schema/validate.js
@@ -0,0 +1,23 @@
+const assert = require('assert');
+const { Given, When, Then } = require('@cucumber/cucumber');
+const OpenAPISchemaValidator = require('openapi-schema-validator').default;
+
+const fs = require('fs');
+
+const schemaLocation = './test/mock/swagger.json';
+
+Given('the test schema', function() {
+  this.schema = JSON.parse(fs.readFileSync(schemaLocation));
+});
+
+When('it is validated', function() {
+  const validator = new OpenAPISchemaValidator({ version: 3 });
+  this.validation = validator.validate(this.schema);
+});
+
+Then('it matches the OpenAPI specification', function() {
+  // According to the docs this should return a valid:boolean 
+  // but if you look at the code it just returns a list of errors 
+  // which is empty for a valid result
+  assert.equal(this.validation.errors.length, 0);
+});
\ No newline at end of file
diff --git a/features/schema_validates.feature b/features/schema_validates.feature
new file mode 100644
index 0000000000000000000000000000000000000000..34f457a2543f1bf91948a4e367945e6565a985a9
--- /dev/null
+++ b/features/schema_validates.feature
@@ -0,0 +1,10 @@
+# If the mock schema fixture fails to validate 
+# it can cause invalid messages to show as valid
+
+Feature: Is the mock schema valid?
+  The mock schema must validate in order for the adapter test to work
+
+  Scenario: The schema matches the OpenAPI specification
+    Given the test schema
+    When it is validated
+    Then it matches the OpenAPI specification  
\ No newline at end of file
diff --git a/package.json b/package.json
index c7bededab3ea6a589efe6cd36ccc050a127ecf6f..90ecb8937ae25cb72e8db21c759563ad50f10001 100644
--- a/package.json
+++ b/package.json
@@ -51,6 +51,7 @@
     "husky": "^7.0.4",
     "jest": "^27.4.4",
     "lint-staged": "^12.1.2",
+    "openapi-schema-validator": "^12.1.0",
     "prettier": "^2.5.1",
     "rollup": "^3.9.1"
   }
diff --git a/src/adapter/index.js b/src/adapter/index.js
index 2604c5c344d35e01fa0751682f06850e37ac8dd1..ad41f54b7132c5101bc435ce72e0fa4fde02592a 100644
--- a/src/adapter/index.js
+++ b/src/adapter/index.js
@@ -27,7 +27,10 @@ export class Adapter {
   validate(message) {
     return this.validator.validate(
       message,
-      this.protocol.schema.definitions.Message
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
     );
   }
 
diff --git a/src/protocol/index.js b/src/protocol/index.js
index 151cc98d0bbf70e1b23cdb89eafdaba599840230..74676ddb91706e411b78024dc8ad3e3081995dd5 100644
--- a/src/protocol/index.js
+++ b/src/protocol/index.js
@@ -35,7 +35,13 @@ export class GenericProtocol {
    * @returns {object}
    */
   validate(message) {
-    return this.validator.validate(message, this.schema.definitions.Message);
+    return this.validator.validate(
+      message,
+      this.protocol.schema.components.schemas.Message,
+      this.protocol.schema.components.schemas,
+      false,
+      true
+    );
   }
 
   /**
diff --git a/test/fixtures/invalid-config.json b/test/fixtures/config-invalid.json
similarity index 100%
rename from test/fixtures/invalid-config.json
rename to test/fixtures/config-invalid.json
diff --git a/test/fixtures/valid-config.json b/test/fixtures/config-valid.json
similarity index 100%
rename from test/fixtures/valid-config.json
rename to test/fixtures/config-valid.json
diff --git a/test/fixtures/message-vehicle-status-invalid.json b/test/fixtures/message-vehicle-status-invalid.json
new file mode 100644
index 0000000000000000000000000000000000000000..cbcf1629280e09db0e587d87973fe2d7785e40ab
--- /dev/null
+++ b/test/fixtures/message-vehicle-status-invalid.json
@@ -0,0 +1,20 @@
+{
+  "metadata": {
+    "source": "ae",
+    "destination": "soar.po.ecosub.eco1",
+    "delivery_type": "publish",
+    "message_id": "test"
+  },
+  "payload": {
+    "message_type": "VehicleStatus",
+    "xoperator_id": 1,
+    "xvehicle_id": 12,
+    "coordinates": {
+      "latitude": "monkeys",
+      "longitude": "janvier",
+      "depth": "twenty five metres please",
+      "projection": 4326
+    },
+    "battery_percentage": "plenty"
+  }
+}
\ No newline at end of file
diff --git a/test/fixtures/message-vehicle-status.json b/test/fixtures/message-vehicle-status.json
index 1e47be57f27c4e72f809a0c2041d75637ca6ecee..55cdd818781ab404ebf70d3087a7f6c83396cc3a 100644
--- a/test/fixtures/message-vehicle-status.json
+++ b/test/fixtures/message-vehicle-status.json
@@ -1,18 +1,20 @@
 {
-  "message_type": "VehicleStatus",
-  "headers": {
+  "metadata": {
     "source": "ae",
     "destination": "soar.po.ecosub.eco1",
     "delivery_type": "publish",
     "message_id": "test"
   },
-  "operator_id": "po",
-  "vehicle_id": "eco1",
-  "coordinates": {
-    "latitude": 57.234,
-    "longitude": -8.432,
-    "depth": 50,
-    "projection": "EPSG:4326"
-  },
-  "battery_percentage": 64
+  "payload": {
+    "message_type": "VehicleStatus",
+    "operator_id": "po",
+    "vehicle_id": "eco1",
+    "coordinates": {
+      "latitude": 57.234,
+      "longitude": -8.432,
+      "depth": 50,
+      "projection": 4326
+    },
+    "battery_percentage": 64
+  }
 }
\ No newline at end of file
diff --git a/test/fixtures/server.js b/test/fixtures/server.js
index 1b1f9ed6673b0e38e60eaedc568837ecefdaa00d..f541f7b55981c9d0f96d06511bb93aae46452fa9 100644
--- a/test/fixtures/server.js
+++ b/test/fixtures/server.js
@@ -8,7 +8,7 @@ exports.fixtures = {
       let fixture = JSON.parse(fixtureContent);
       return fixture;
     } catch(e) {
-      console.error('Fixture not found', fixrureName);
+      console.error('Fixture not found', fixtureName);
       return null;
     }
   } 
diff --git a/test/mock/messages/Message_VehicleMission.json b/test/mock/messages/Message_VehicleMission.json
index b23a461743f248e6ba2dc7e05e77f0cc23df16e5..1036455bf142f2a44938fc053974fbdac3b204bb 100644
--- a/test/mock/messages/Message_VehicleMission.json
+++ b/test/mock/messages/Message_VehicleMission.json
@@ -1,6 +1,6 @@
 {
   "message_type": "VehicleMission",
-  "headers": {
+  "metadata": {
     "source": "ae",
     "destination": "soar.po.ecosub.eco1",
     "delivery_type": "publish",
@@ -12,6 +12,6 @@
     "latitude": 59.234,
     "longitude": -10.432,
     "depth": 50,
-    "projection": "EPSG:4326"
+    "projection": 4326
   }
 }
diff --git a/test/mock/messages/Message_VehicleMissionActions.json b/test/mock/messages/Message_VehicleMissionActions.json
index 68978fbec6f31f3c7cb3fae3346cd576b27f3ae0..921bf26414980e06febccd4acf79fcb1a24f2703 100644
--- a/test/mock/messages/Message_VehicleMissionActions.json
+++ b/test/mock/messages/Message_VehicleMissionActions.json
@@ -1,6 +1,6 @@
 {
   "message_type": "VehicleMission",
-  "headers": {
+  "metadata": {
     "source": "ae",
     "destination": "soar.po.ecosub.eco1",
     "delivery_type": "publish",
@@ -12,7 +12,7 @@
     "latitude": 59.234,
     "longitude": -10.432,
     "depth": 50,
-    "projection": "EPSG:4326"
+    "projection": 4326
   },
   "actions": [
     {
@@ -21,7 +21,7 @@
         "latitude": 59.234,
         "longitude": -10.432,
         "depth": 50,
-        "projection": "EPSG:4326"
+        "projection": 4326
       }
     },
     {
@@ -30,7 +30,7 @@
         "latitude": 59.234,
         "longitude": -10.432,
         "altitude": 50,
-        "projection": "EPSG:4326"
+        "projection": 4326
       }
     }
   ]
diff --git a/test/mock/messages/Message_VehicleStatus.json b/test/mock/messages/Message_VehicleStatus.json
index 490dbe139f1deaa32dab800d0010782a7a823309..5891bbab19f73c31f1815f3b4cb298acff043e23 100644
--- a/test/mock/messages/Message_VehicleStatus.json
+++ b/test/mock/messages/Message_VehicleStatus.json
@@ -1,6 +1,6 @@
 {
   "message_type": "VehicleStatus",
-  "headers": {
+  "metadata": {
     "source": "ae",
     "destination": "soar.po.ecosub.eco1",
     "delivery_type": "publish",
@@ -12,7 +12,7 @@
     "latitude": 57.234,
     "longitude": -8.432,
     "depth": 50,
-    "projection": "EPSG:4326"
+    "projection": 4326
   },
   "battery_percentage": 64
 }
diff --git a/test/mock/swagger.json b/test/mock/swagger.json
index cc4b6d6660535464799a2b0c6803580cc87ef5b6..35999bc48b202f254f93dcb3c6547e667037705d 100644
--- a/test/mock/swagger.json
+++ b/test/mock/swagger.json
@@ -1,237 +1,251 @@
 {
-  "swagger": "2.0",
-  "basePath": "/soar",
+  "openapi": "3.0.3",
   "info": {
     "title": "soar",
-    "version": "1.3.1",
+    "version": "1.0",
     "description": "SoAR message schemas"
   },
-  "produces": ["application/json"],
-  "consumes": ["application/json"],
-  "definitions": {
-    "Message": {
-      "discriminator": {
-        "propertyName": "message_type",
-        "mapping": {
-          "VehicleStatus": "#/definitions/VehicleStatus",
-          "VehicleMission": "#/definitions/VehicleMission",
-          "AreaOfInterest": "#/definitions/AreaOfInterest"
-        }
-      },
-      "oneOf": [
-        {
-          "$ref": "#/definitions/VehicleStatus"
-        },
-        {
-          "$ref": "#/definitions/VehicleMission"
-        },
-        {
-          "$ref": "#/definitions/AreaOfInterest"
-        }
-      ]
-    },
-    "Metadata": {
-      "properties": {
-        "source": {
-          "type": "string",
-          "description": "The sender.",
-          "example": "autonomy-engine"
-        },
-        "destination": {
-          "type": "string",
-          "description": "Publisher topic.",
-          "example": "soar.noc.autosub.ah1.status"
-        },
-        "delivery_type": {
-          "type": "string",
-          "description": "Published or broadcast",
-          "enum": ["broadcast", "publish"],
-          "example": "2.0.0"
+  "paths": {},
+  "components": {
+    "schemas": {
+      "Message": {
+        "properties": {
+          "metadata": {
+            "$ref": "#/components/schemas/Metadata"
+          },
+          "payload": {
+            "$ref": "#/components/schemas/Payload"
+          }
         },
-        "message_id": {
-          "type": "string",
-          "description": "An identifier for the type of message received.",
-          "example": "VehicleStatus"
-        }
+        "required": ["metadata", "payload"]
       },
-      "type": "object"
-    },
-    "Coordinates": {
-      "properties": {
-        "latitude": {
-          "type": "number",
-          "description": "Latitude in decimal degrees.",
-          "example": 54.234
-        },
-        "longitude": {
-          "type": "number",
-          "description": "Longitude in decimal degrees.",
-          "example": -1.432
-        },
-        "depth": {
-          "type": "number",
-          "description": "Target depth",
-          "default": 0,
-          "example": 50
-        },
-        "altitude": {
-          "type": "number",
-          "description": "Target altitude above bottom",
-          "default": 0,
-          "example": 50
-        },
-        "projection": {
-          "type": "integer",
-          "description": "EPSG Projection Code",
-          "example": 4326,
-          "default": 4326
-        }
-      }
-    },
-    "VehicleStatus": {
-      "properties": {
-        "message_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "VehicleStatus",
-          "enum": ["VehicleStatus"]
-        },
-        "metadata": {
-          "$ref": "#/definitions/Metadata"
-        },
-        "operator_id": {
-          "type": "string",
-          "description": "An identifier for the operator.",
-          "example": "noc"
-        },
-        "vehicle_id": {
-          "type": "string",
-          "description": "An identifier for the vehicle.",
-          "example": "noc_ah1"
-        },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
-        },
-        "battery_percentage": {
-          "type": "number",
-          "description": "The remaining battery capacity.",
-          "example": 64
-        }
-      }
-    },
-    "VehicleMission": {
-      "properties": {
-        "message_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "VehicleMission",
-          "enum": ["VehicleMission"]
-        },
-        "metadata": {
-          "$ref": "#/definitions/Metadata"
+      "Payload": {
+        "discriminator": {
+          "propertyName": "message_type",
+          "mapping": {
+            "VehicleStatus": "#/components/schemas/VehicleStatus",
+            "VehicleMission": "#/components/schemas/VehicleMission",
+            "AreaOfInterest": "#/components/schemas/AreaOfInterest"
+          }
         },
-        "operator_id": {
-          "type": "string",
-          "description": "An identifier for the operator.",
-          "example": "noc"
+        "oneOf": [
+          {
+            "$ref": "#/components/schemas/VehicleStatus"
+          },
+          {
+            "$ref": "#/components/schemas/VehicleMission"
+          },
+          {
+            "$ref": "#/components/schemas/AreaOfInterest"
+          }
+        ]
+      },
+      "Metadata": {
+        "properties": {
+          "source": {
+            "type": "string",
+            "description": "The sender.",
+            "example": "autonomy-engine"
+          },
+          "destination": {
+            "type": "string",
+            "description": "Publisher topic.",
+            "example": "soar.noc.autosub.ah1.status"
+          },
+          "delivery_type": {
+            "type": "string",
+            "description": "Published or broadcast",
+            "enum": ["broadcast", "publish"],
+            "example": "2.0.0"
+          },
+          "message_id": {
+            "type": "string",
+            "description": "An identifier for the type of message received.",
+            "example": "VehicleStatus"
+          }
         },
-        "vehicle_id": {
-          "type": "string",
-          "description": "An identifier for the vehicle.",
-          "example": "noc_ah1"
+        "required": ["source","destination","message_id"],
+        "type": "object"
+      },
+      "Coordinates": {
+        "properties": {
+          "latitude": {
+            "type": "number",
+            "description": "Latitude in decimal degrees.",
+            "example": 54.234
+          },
+          "longitude": {
+            "type": "number",
+            "description": "Longitude in decimal degrees.",
+            "example": -1.432
+          },
+          "depth": {
+            "type": "number",
+            "description": "Target depth",
+            "default": 0,
+            "example": 50
+          },
+          "altitude": {
+            "type": "number",
+            "description": "Target altitude above bottom",
+            "default": 0,
+            "example": 50
+          },
+          "projection": {
+            "type": "integer",
+            "description": "EPSG Projection Code",
+            "example": 4326,
+            "default": 4326
+          }
         },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
+        "required": ["latitude", "longitude"],
+        "type": "object"
+      },
+      "VehicleStatus": {
+        "properties": {
+          "message_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "VehicleStatus",
+            "enum": ["VehicleStatus"]
+          },
+          "operator_id": {
+            "type": "string",
+            "description": "An identifier for the operator.",
+            "example": "noc"
+          },
+          "vehicle_id": {
+            "type": "string",
+            "description": "An identifier for the vehicle.",
+            "example": "noc_ah1"
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          },
+          "battery_percentage": {
+            "type": "number",
+            "description": "The remaining battery capacity.",
+            "example": 64
+          }
         },
-        "actions": {
-          "type": "array",
-          "items": {
-            "discriminator": {
-              "propertyName": "action_type",
-              "mapping": {
-                "GoToWaypoint": "#/definitions/GoToWaypoint",
-                "DescendToAltitude": "#/definitions/DescendToAltitude",
-                "AscendToSurface": "#/definitions/AscendToSurface"
-              }
-            },
-            "oneOf": [
-              {
-                "$ref": "#/definitions/VehicleStatus"
-              },
-              {
-                "$ref": "#/definitions/VehicleMission"
+        "required": ["message_type", "operator_id", "vehicle_id", "coordinates", "battery_percentage"],
+        "type": "object"
+      },
+      "VehicleMission": {
+        "properties": {
+          "message_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "VehicleMission",
+            "enum": ["VehicleMission"]
+          },
+          "operator_id": {
+            "type": "string",
+            "description": "An identifier for the operator.",
+            "example": "noc"
+          },
+          "vehicle_id": {
+            "type": "string",
+            "description": "An identifier for the vehicle.",
+            "example": "noc_ah1"
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          },
+          "actions": {
+            "type": "array",
+            "items": {
+              "discriminator": {
+                "propertyName": "action_type",
+                "mapping": {
+                  "GoToWaypoint": "#/components/schemas/GoToWaypoint",
+                  "DescendToAltitude": "#/components/schemas/DescendToAltitude",
+                  "AscendToSurface": "#/components/schemas/AscendToSurface"
+                }
               },
-              {
-                "$ref": "#/definitions/AreaOfInterest"
-              }
-            ]
+              "oneOf": [
+                {
+                  "$ref": "#/components/schemas/VehicleStatus"
+                },
+                {
+                  "$ref": "#/components/schemas/VehicleMission"
+                },
+                {
+                  "$ref": "#/components/schemas/AreaOfInterest"
+                }
+              ]
+            }
           }
-        }
-      }
-    },
-    "AreaOfInterest": {
-      "properties": {
-        "message_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "AreaOfInterest",
-          "enum": ["AreaOfInterest"]
-        },
-        "metadata": {
-          "$ref": "#/definitions/Metadata"
         },
-        "operator_id": {
-          "type": "string",
-          "description": "An identifier for the operator.",
-          "example": "noc"
-        },
-        "vehicle_id": {
-          "type": "string",
-          "description": "An identifier for the vehicle.",
-          "example": "noc_ah1"
+        "required": ["message_type", "operator_id", "vehicle_id", "coordinates", "actions"],
+        "type": "object"
+      },
+      "AreaOfInterest": {
+        "properties": {
+          "message_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "AreaOfInterest",
+            "enum": ["AreaOfInterest"]
+          },
+          "operator_id": {
+            "type": "string",
+            "description": "An identifier for the operator.",
+            "example": "noc"
+          },
+          "vehicle_id": {
+            "type": "string",
+            "description": "An identifier for the vehicle.",
+            "example": "noc_ah1"
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          }
         },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
-        }
-      }
-    },
-    "GoToWaypoint": {
-      "properties": {
-        "action_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "GoToWaypoint",
-          "enum": ["GoToWaypoint"]
+        "required": ["message_type", "operator_id", "vehicle_id", "coordinates"],
+        "type": "object"
+      },
+      "GoToWaypoint": {
+        "properties": {
+          "action_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "GoToWaypoint",
+            "enum": ["GoToWaypoint"]
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          }
         },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
-        }
-      }
-    },
-    "DescendToAltitude": {
-      "properties": {
-        "action_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "DescendToAltitude",
-          "enum": ["DescendToAltitude"]
+        "type": "object"
+      },
+      "DescendToAltitude": {
+        "properties": {
+          "action_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "DescendToAltitude",
+            "enum": ["DescendToAltitude"]
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          }
         },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
-        }
-      }
-    },
-    "AscendToSurface": {
-      "properties": {
-        "action_type": {
-          "type": "string",
-          "description": "An identifier for the payload type.",
-          "example": "AscendToSurface",
-          "enum": ["AscendToSurface"]
+        "type": "object"
+      },
+      "AscendToSurface": {
+        "properties": {
+          "action_type": {
+            "type": "string",
+            "description": "An identifier for the payload type.",
+            "example": "AscendToSurface",
+            "enum": ["AscendToSurface"]
+          },
+          "coordinates": {
+            "$ref": "#/components/schemas/Coordinates"
+          }
         },
-        "coordinates": {
-          "$ref": "#/definitions/Coordinates"
-        }
+        "type": "object"
       }
     }
   }
diff --git a/yarn.lock b/yarn.lock
index b9878a6ccf11c5b5fe1bb269d9c6c57c2eb8ad38..1d0dd6384b1294cfe28b66b41702497516495c20 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1081,6 +1081,13 @@ aggregate-error@^3.0.0:
     clean-stack "^2.0.0"
     indent-string "^4.0.0"
 
+ajv-formats@^2.0.2:
+  version "2.1.1"
+  resolved "https://registry.yarnpkg.com/ajv-formats/-/ajv-formats-2.1.1.tgz#6e669400659eb74973bbf2e33327180a0996b520"
+  integrity sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==
+  dependencies:
+    ajv "^8.0.0"
+
 ajv@^6.10.0, ajv@^6.12.4:
   version "6.12.6"
   resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4"
@@ -1091,6 +1098,16 @@ ajv@^6.10.0, ajv@^6.12.4:
     json-schema-traverse "^0.4.1"
     uri-js "^4.2.2"
 
+ajv@^8.0.0, ajv@^8.1.0:
+  version "8.12.0"
+  resolved "https://registry.yarnpkg.com/ajv/-/ajv-8.12.0.tgz#d1a0527323e22f53562c567c00991577dfbe19d1"
+  integrity sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==
+  dependencies:
+    fast-deep-equal "^3.1.1"
+    json-schema-traverse "^1.0.0"
+    require-from-string "^2.0.2"
+    uri-js "^4.2.2"
+
 ansi-escapes@^4.2.1, ansi-escapes@^4.3.0:
   version "4.3.2"
   resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e"
@@ -2951,6 +2968,11 @@ json-schema-traverse@^0.4.1:
   resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
   integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==
 
+json-schema-traverse@^1.0.0:
+  version "1.0.0"
+  resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz#ae7bcb3656ab77a73ba5c49bf654f38e6b6860e2"
+  integrity sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==
+
 json-stable-stringify-without-jsonify@^1.0.1:
   version "1.0.1"
   resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651"
@@ -3086,7 +3108,7 @@ lodash.isequal@^4.5.0:
   resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
   integrity sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==
 
-lodash.merge@^4.6.2:
+lodash.merge@^4.6.1, lodash.merge@^4.6.2:
   version "4.6.2"
   resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
   integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==
@@ -3337,6 +3359,21 @@ onetime@^5.1.0, onetime@^5.1.2:
   dependencies:
     mimic-fn "^2.1.0"
 
+openapi-schema-validator@^12.1.0:
+  version "12.1.0"
+  resolved "https://registry.yarnpkg.com/openapi-schema-validator/-/openapi-schema-validator-12.1.0.tgz#8ab5c7fd57189551126589426e5d71d8190eb80f"
+  integrity sha512-gr9mZCHu5QmADePYNhizaSAsB0HdY/DespPue10NQID1jB+56Jf+dfnJcnMOVKsG4ZAedVY5oyLFGI1Gk0wm7w==
+  dependencies:
+    ajv "^8.1.0"
+    ajv-formats "^2.0.2"
+    lodash.merge "^4.6.1"
+    openapi-types "^12.1.0"
+
+openapi-types@^12.1.0:
+  version "12.1.0"
+  resolved "https://registry.yarnpkg.com/openapi-types/-/openapi-types-12.1.0.tgz#bd01acc937b73c9f6db2ac2031bf0231e21ebff0"
+  integrity sha512-XpeCy01X6L5EpP+6Hc3jWN7rMZJ+/k1lwki/kTmWzbVhdPie3jd5O2ZtedEx8Yp58icJ0osVldLMrTB/zslQXA==
+
 optionator@^0.8.1:
   version "0.8.3"
   resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.8.3.tgz#84fa1d036fe9d3c7e21d99884b601167ec8fb495"
@@ -3644,6 +3681,11 @@ require-directory@^2.1.1:
   resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42"
   integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==
 
+require-from-string@^2.0.2:
+  version "2.0.2"
+  resolved "https://registry.yarnpkg.com/require-from-string/-/require-from-string-2.0.2.tgz#89a7fdd938261267318eafe14f9c32e598c36909"
+  integrity sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==
+
 requires-port@^1.0.0:
   version "1.0.0"
   resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff"