diff --git a/src/box/key_def.c b/src/box/key_def.c
index ca8a00dc5af757431bb011f02aa510577124acae..509b21458ad411574fc30c7fd7c14a77ffbaeab1 100644
--- a/src/box/key_def.c
+++ b/src/box/key_def.c
@@ -644,6 +644,23 @@ box_key_def_validate_key(const box_key_def_t *key_def, const char *key,
 	return rc;
 }
 
+int
+box_key_def_validate_full_key(const box_key_def_t *key_def, const char *key,
+			      uint32_t *key_size_ptr)
+{
+	const char *pos = key;
+	uint32_t part_count = mp_decode_array(&pos);
+	if (part_count != key_def->part_count) {
+		diag_set(ClientError, ER_EXACT_MATCH, key_def->part_count,
+			 part_count);
+		return -1;
+	}
+	int rc = key_validate_parts(key_def, pos, part_count, true, &pos);
+	if (rc == 0 && key_size_ptr != NULL)
+		*key_size_ptr = pos - key;
+	return rc;
+}
+
 /* }}} Module API functions */
 
 int
diff --git a/src/box/key_def.h b/src/box/key_def.h
index 3c004d9e46c8783dc35f9188ecf6ad28e12517ef..13c85c67c8268175641ec58e5ecacc7235f3a5b3 100644
--- a/src/box/key_def.h
+++ b/src/box/key_def.h
@@ -586,6 +586,31 @@ API_EXPORT int
 box_key_def_validate_key(const box_key_def_t *key_def, const char *key,
 			 uint32_t *key_size_ptr);
 
+/**
+ * Check a full key against given key definition.
+ *
+ * Verifies key parts against given key_def's field types with
+ * respect to nullability.
+ *
+ * Imposes the same parts count in @a key as in @a key_def.
+ * Absense of trailing key parts fails the check.
+ *
+ * Note: nil is accepted for nullable fields, but only for them.
+ *
+ * @param key_def       Key definition.
+ * @param key           MessagePack'ed data for matching.
+ * @param key_size_ptr  Here will be size of the validated key.
+ *
+ * @retval 0   The key is valid.
+ * @retval -1  The key is invalid.
+ *
+ * In case of an invalid key set a diag and return -1.
+ * @sa <box_error_last>().
+ */
+API_EXPORT int
+box_key_def_validate_full_key(const box_key_def_t *key_def, const char *key,
+			      uint32_t *key_size_ptr);
+
 /** \endcond public */
 
 /*
diff --git a/src/exports.h b/src/exports.h
index e77a118788fca91e2490436d9e530d685b18013e..628d839c9151ca0132056761850f8b4f9893f4f2 100644
--- a/src/exports.h
+++ b/src/exports.h
@@ -35,6 +35,7 @@ EXPORT(box_key_def_extract_key)
 EXPORT(box_key_def_merge)
 EXPORT(box_key_def_new)
 EXPORT(box_key_def_new_v2)
+EXPORT(box_key_def_validate_full_key)
 EXPORT(box_key_def_validate_key)
 EXPORT(box_key_def_validate_tuple)
 EXPORT(box_key_part_def_create)
diff --git a/test/app-tap/module_api.c b/test/app-tap/module_api.c
index 55f237027b16be4f500440aabad71e516be2e13b..95ff0bc409e4606492329e2437c391e7cdbc2748 100644
--- a/test/app-tap/module_api.c
+++ b/test/app-tap/module_api.c
@@ -1732,7 +1732,8 @@ test_key_def_extract_key(struct lua_State *L)
 }
 
 /**
- * Basic <box_key_def_validate_key>() test.
+ * Basic <box_key_def_validate_key>() and
+ * <box_key_def_validate_full_key>() test.
  */
 static int
 test_key_def_validate_key(struct lua_State *L)
@@ -1762,15 +1763,16 @@ test_key_def_validate_key(struct lua_State *L)
 	/*
 	 * Create keys to validate them against given key_def.
 	 *
-	 *  | # | key            | Is valid? |
-	 *  | - | -------------- | --------- |
-	 *  | 0 | [1, 1]         | valid     |
-	 *  | 1 | [1, null]      | valid     |
-	 *  | 2 | [1]            | valid     |
-	 *  | 3 | []             | valid     |
-	 *  | 4 | [null]         | invalid   |
-	 *  | 5 | [1, 2, 3]      | invalid   |
-	 *  | 6 | [1, -1]        | invalid   |
+	 *  | # | key            | Is valid? | Is valid? |
+	 *  |   |                | (partial) |   (full)  |
+	 *  | - | -------------- | --------- | --------- |
+	 *  | 0 | [1, 1]         | valid     | valid     |
+	 *  | 1 | [1, null]      | valid     | valid     |
+	 *  | 2 | [1]            | valid     | invalid   |
+	 *  | 3 | []             | valid     | invalid   |
+	 *  | 4 | [null]         | invalid   | invalid   |
+	 *  | 5 | [1, 2, 3]      | invalid   | invalid   |
+	 *  | 6 | [1, -1]        | invalid   | invalid   |
 	 */
 	struct {
 		const char *data;
@@ -1784,49 +1786,61 @@ test_key_def_validate_key(struct lua_State *L)
 		/* [5] = */ {"\x93\x01\x02\x03", 4},
 		/* [6] = */ {"\x92\x01\xff",     3},
 	};
-	int expected_results[] = {
-		/* [0] = */ 0,
-		/* [1] = */ 0,
-		/* [2] = */ 0,
-		/* [3] = */ 0,
-		/* [4] = */ -1,
-		/* [5] = */ -1,
-		/* [6] = */ -1,
-	};
-	uint32_t expected_error_codes[] = {
-		/* [0] = */ box_error_code_MAX,
-		/* [1] = */ box_error_code_MAX,
-		/* [2] = */ box_error_code_MAX,
-		/* [3] = */ box_error_code_MAX,
-		/* [4] = */ ER_KEY_PART_TYPE,
-		/* [5] = */ ER_KEY_PART_COUNT,
-		/* [6] = */ ER_KEY_PART_TYPE,
+	int expected_results[][2] = {
+		/* [0] = */ {0,  0 },
+		/* [1] = */ {0,  0 },
+		/* [2] = */ {0,  -1},
+		/* [3] = */ {0,  -1},
+		/* [4] = */ {-1, -1},
+		/* [5] = */ {-1, -1},
+		/* [6] = */ {-1, -1},
+	};
+	uint32_t expected_error_codes[][2] = {
+		/* [0] = */ {box_error_code_MAX, box_error_code_MAX},
+		/* [1] = */ {box_error_code_MAX, box_error_code_MAX},
+		/* [2] = */ {box_error_code_MAX, ER_EXACT_MATCH    },
+		/* [3] = */ {box_error_code_MAX, ER_EXACT_MATCH    },
+		/* [4] = */ {ER_KEY_PART_TYPE,   ER_EXACT_MATCH    },
+		/* [5] = */ {ER_KEY_PART_COUNT,  ER_EXACT_MATCH    },
+		/* [6] = */ {ER_KEY_PART_TYPE,   ER_KEY_PART_TYPE  },
+	};
+
+	typedef int (*key_def_validate_key_f)(const box_key_def_t *key_def,
+					      const char *key,
+					      uint32_t *key_size_ptr);
+	key_def_validate_key_f funcs[] = {
+		box_key_def_validate_key,
+		box_key_def_validate_full_key,
 	};
 
 	for (size_t i = 0; i < lengthof(keys); ++i) {
-		uint32_t key_size = 0;
-		const char *key = keys[i].data;
-		int rc = box_key_def_validate_key(key_def, key, &key_size);
-		assert(rc == expected_results[i]);
-		(void)rc;
-		(void)expected_results;
-
-		if (expected_error_codes[i] == box_error_code_MAX) {
-			/* Verify key_size. */
-			assert(key_size != 0);
-			assert(key_size == keys[i].size);
-
-			/*
-			 * Verify that no NULL pointer dereference
-			 * occurs when NULL is passed as
-			 * key_size_ptr.
-			 */
-			box_key_def_validate_key(key_def, key, NULL);
-		} else {
-			assert(rc != 0);
-			box_error_t *e = box_error_last();
-			(void)e;
-			assert(box_error_code(e) == expected_error_codes[i]);
+		for (size_t f = 0; f < lengthof(funcs); ++f) {
+			int exp_res = expected_results[i][f];
+			uint32_t exp_err_code = expected_error_codes[i][f];
+			const char *key = keys[i].data;
+			uint32_t key_size = 0;
+			int rc = funcs[f](key_def, key, &key_size);
+			assert(rc == exp_res);
+			(void)rc;
+			(void)exp_res;
+
+			if (exp_err_code == box_error_code_MAX) {
+				/* Verify key_size. */
+				assert(key_size != 0);
+				assert(key_size == keys[i].size);
+
+				/*
+				 * Verify that no NULL pointer
+				 * dereference occurs when NULL
+				 * is passed as key_size_ptr.
+				 */
+				box_key_def_validate_key(key_def, key, NULL);
+			} else {
+				assert(rc != 0);
+				box_error_t *e = box_error_last();
+				(void)e;
+				assert(box_error_code(e) == exp_err_code);
+			}
 		}
 	}