diff --git a/CMakeLists.txt b/CMakeLists.txt
index 347952f21f1157d8df6123684fadc98d51cd3057..ae7120fb9535b89c78cb098f3842c723c1a9cf65 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -28,6 +28,7 @@ add_executable(makeSerialList "makeseriallist.cxx")
 add_executable(makeGridList "makeGridList.cxx")
 add_executable(getIrradiationDose "getirradiationstatus.cxx")
 add_executable(apdUnitCreator "apdUnitCreator.cpp")
+add_executable(validateSerials "validateSerials.cpp")
 
 add_executable(testXmlStructure "testxmlstructure.cxx")
 
@@ -51,4 +52,4 @@ target_link_libraries(setArrivalForIrradiation proddbaccess proddbclient boost_p
 target_link_libraries(setSentForAnalysisAfterIrradiation proddbaccess proddbclient boost_program_options Qt5::Gui Qt5::Widgets)
 target_link_libraries(setIrradiationInfo proddbaccess proddbclient boost_program_options Qt5::Gui Qt5::Widgets)
 target_link_libraries(setAnnealingInfo proddbaccess proddbclient boost_program_options Qt5::Gui Qt5::Widgets)
-
+target_link_libraries(validateSerials proddbaccess)
diff --git a/validateSerials.cpp b/validateSerials.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dde47ad70e1ef87c34c12d5e004d1635781d2a11
--- /dev/null
+++ b/validateSerials.cpp
@@ -0,0 +1,81 @@
+#include <iostream>
+#include <iomanip>
+#include <vector>
+#include <string>
+#include <fstream>
+#include <QCoreApplication>
+
+#include "ProdDbAccess.h"
+#include "BulkDbAccess.h"
+#include "toolbox.cpp"
+
+using namespace std;
+
+bool checkDuplicates(vector<string> serials);
+bool validateWithDB(vector<string> serials);
+
+int main(int argc, char* argv[]) {
+  if ( argc > 2 ) {
+    cerr << "ERROR: Too many parameters! Please only provide the name of a text file containing the serials needed." << endl;
+    exit(1);
+  }
+  std::string fileName = "";
+
+  if ( argc == 2)
+    fileName = string(argv[1]);
+  else
+    fileName = "serials.dat";
+
+  vector<string> apdSerials = loadSerialsFromFileName(fileName);
+  
+  if (apdSerials.size() != 30) {
+    if (apdSerials.size() < 30)
+      cerr << "There are less than 30 APDs in this file. This might indicate an error. Do you want to continue?" << std::endl;
+    else
+      cerr << "There are more than 30 APDs in this file. There can only be up to 30 APDs in one batch. Do you want to continue?" << std::endl;
+    std::string answer;
+    cin >> answer;
+    if (answer != "yes" && answer != "y")
+      return 1;
+  }
+
+  if (!checkDuplicates(apdSerials)) {
+    cerr << "At least one APD was found at least twice. Since an APD can't be in two slots at once, this serial file is invalid and will not be checked against the database." << std::endl;
+    return 1;
+  }
+
+  if (!validateWithDB(apdSerials)) {
+    cerr << "At least one APD was naughty!" << endl;
+    return 1;
+  }
+  cerr << "Santa will visit all of these APDs." << endl;
+  return 0;
+}
+
+bool checkDuplicates(vector<string> serials) {
+  bool result = true;
+  for (auto outerIterator = serials.begin(); outerIterator != serials.end(); outerIterator++) {
+    for (auto innerIterator = outerIterator; innerIterator != serials.end(); innerIterator++) {
+      if (innerIterator != outerIterator && *innerIterator == *outerIterator) {
+        result = false;
+        cerr << "Serial " << *innerIterator << " appears at least twice!" << std::endl;
+      }
+    }
+  }
+  return result;
+}
+
+bool validateWithDB(vector<string> serials) {
+  AbsDbAccess* _dba = suitedDbAccess(serials.size());
+  bool result = true;
+  for (auto iterator = serials.begin(); iterator != serials.end(); iterator++) {
+    if (_dba->apdAvailable(stoul(*iterator))) {
+      cout << "Serial " << *iterator << " is good!" << endl;
+    }
+    else {
+      cerr << "Serial " << *iterator << " was not found or is not available! ERROR!" << endl;
+      result = false;
+    }
+  }
+  return result;
+}