diff --git a/modules/registrars/cozaepp/cozaepp.php b/modules/registrars/cozaepp/cozaepp.php
index 26a563aa6b501ca879c6c1469d4876d7cb1638d7..f6a58d1461732818323fb9b8d2cba72ce82904a6 100644
--- a/modules/registrars/cozaepp/cozaepp.php
+++ b/modules/registrars/cozaepp/cozaepp.php
@@ -35,7 +35,7 @@
 # integration, customizations and consulting all available from
 # http://allworldit.com
 
-// Make sure we not being accssed directly
+# Make sure we not being accssed directly
 if (!defined("WHMCS"))
 	die("This file cannot be accessed directly");
 
@@ -286,8 +286,8 @@ function cozaepp_SaveRegistrarLock($params) {
 
 
 # Function to retrieve an available contact id
-function _cozaepp_CheckContact($domain) {
-	$prehash = $domain . time() . rand(0, 1000000);
+function _cozaepp_CheckContact($domain,$type) {
+	$prehash = $domain . time() . rand(0, 1000000) . $type;
 	$contactid = substr(md5($prehash), 0,15);
 
 	# Get client instance and check for available contact id
@@ -550,7 +550,7 @@ function cozaepp_RegisterDomain($params) {
 			} else if($coderes == '2302') {
 				$values['contact'] = 'Contact Already exists';
 			} else {
-				$values["error"] = "RegisterDomain/admincontact-create($additional_contactid): Code ($coderes) $msg";
+				$values["error"] = "RegisterDomain/additional-create($additional_contactid): Code ($coderes) $msg";
 				return $values;
 			}
 
@@ -766,60 +766,88 @@ function cozaepp_RenewDomain($params) {
 	return $values;
 }
 
-function _getContactDetails($domain, $client = null) {
+
+
+function __getContact($contactID,$client = null) {
 	# Get client instance
 	try {
 		if (!isset($client)) {
 			$client = _cozaepp_Client($domain);
 		}
 
-		# Grab domain info
+		# Grab contact info
 		$request = $client->request($xml = '
-<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
-		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
+<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
 	<epp:command>
 		<epp:info>
-			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
-				<domain:name hosts="all">'.$domain.'</domain:name>
-			</domain:info>
+			<contact:info>
+				<contact:id>'.$contactID.'</contact:id>
+			</contact:info>
 		</epp:info>
 	</epp:command>
 </epp:epp>
 ');
-
 		# Parse XML result
 		$doc= new DOMDocument();
 		$doc->loadXML($request);
-		logModuleCall('Cozaepp', '_GetContactDetails', $xml, $request);
+		logModuleCall('Cozaepp', '__getContact', $xml, $request);
 
 		$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
 		$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
-
 		# Check result
 		if($coderes != '1000') {
-			$values["error"] = "_GetContactDetails/domain-info($domain): Code (".$coderes.") ".$msg;
+			$values["error"] = "__getContact/contact-info($contactID): Code (".$coderes.") ".$msg;
 			return $values;
 		}
 
-		# Grab contact info
-		$registrant = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;
-		if (empty($registrant)) {
-			$values["error"] = "_GetContactDetails/domain-info($domain): Registrant info not available";
-			return $values;
+		$nodes = $doc->getElementsByTagName('postalInfo');
+		for ($i = 0; ($i < $nodes->length); $i++) {
+			if ($nodes->item($i)->getAttributeNode('type')->nodeValue == 'loc') {
+				$childNodes = $nodes->item($i);
+				$results["Contact Name"] = $childNodes->getElementsByTagName('name')->item(0)->nodeValue;
+				$results["Organisation"] = $childNodes->getElementsByTagName('org')->item(0)->nodeValue;
+				$results["Address line 1"] = $childNodes->getElementsByTagName('street')->item(0)->nodeValue;
+				$results["Address line 2"] = $childNodes->getElementsByTagName('street')->item(1)->nodeValue;
+				$results["TownCity"] = $childNodes->getElementsByTagName('city')->item(0)->nodeValue;
+				$results["State"] = $childNodes->getElementsByTagName('sp')->item(0)->nodeValue;
+				$results["Zip code"] = $childNodes->getElementsByTagName('pc')->item(0)->nodeValue;
+				$results["Country Code"] = $childNodes->getElementsByTagName('cc')->item(0)->nodeValue;
+			}
 		}
 
-		# Grab contact info
+		$results["Phone"] = $doc->getElementsByTagName('voice')->item(0)->nodeValue;
+		$results["Email"] = $doc->getElementsByTagName('email')->item(0)->nodeValue;
+
+		return $results;
+	} catch (Exception $e) {
+		$values["error"] = '__getContact/EPP: '.$e->getMessage();
+		return $values;
+	}
+}
+
+
+
+function _getContactDetails($domain, $client = null) {
+	# Get client instance
+	try {
+		if (!isset($client)) {
+			$client = _cozaepp_Client($domain);
+		}
+
+		# Grab domain info
 		$request = $client->request($xml = '
-<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
+<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
+		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
 	<epp:command>
 		<epp:info>
-			<contact:info>
-				<contact:id>'.$registrant.'</contact:id>
-			</contact:info>
+			<domain:info xsi:schemaLocation="urn:ietf:params:xml:ns:domain-1.0 domain-1.0.xsd">
+				<domain:name hosts="all">'.$domain.'</domain:name>
+			</domain:info>
 		</epp:info>
 	</epp:command>
 </epp:epp>
 ');
+
 		# Parse XML result
 		$doc= new DOMDocument();
 		$doc->loadXML($request);
@@ -827,35 +855,79 @@ function _getContactDetails($domain, $client = null) {
 
 		$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
 		$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
+
 		# Check result
 		if($coderes != '1000') {
-			$values["error"] = "_GetContactDetails/contact-info($registrant): Code (".$coderes.") ".$msg;
+			$values["error"] = "_GetContactDetails/domain-info($domain): Code (".$coderes.") ".$msg;
 			return $values;
 		}
 
-		$nodes = $doc->getElementsByTagName('postalInfo');
-		for ($i = 0; ($i < $nodes->length); $i++) {
-			if ($nodes->item($i)->getAttributeNode('type')->nodeValue == 'loc') {
-				$childNodes = $nodes->item($i);
-				$results["Registrant"]["Contact Name"] = $childNodes->getElementsByTagName('name')->item(0)->nodeValue;
-				$results["Registrant"]["Organisation"] = $childNodes->getElementsByTagName('org')->item(0)->nodeValue;
-				$results["Registrant"]["Address line 1"] = $childNodes->getElementsByTagName('street')->item(0)->nodeValue;
-				$results["Registrant"]["Address line 2"] = $childNodes->getElementsByTagName('street')->item(1)->nodeValue;
-				$results["Registrant"]["TownCity"] = $childNodes->getElementsByTagName('city')->item(0)->nodeValue;
-				$results["Registrant"]["State"] = $childNodes->getElementsByTagName('sp')->item(0)->nodeValue;
-				$results["Registrant"]["Zip code"] = $childNodes->getElementsByTagName('pc')->item(0)->nodeValue;
-				$results["Registrant"]["Country Code"] = $childNodes->getElementsByTagName('cc')->item(0)->nodeValue;
+		# Grab contact ID's
+		$registrantContactID = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;
+		if (empty($registrantContactID)) {
+			$values["error"] = "_GetContactDetails/domain-info($domain): Registrant contact info not available => $request";
+			return $values;
+		}
+
+		$contactNodes = $doc->getElementsByTagName('contact');
+		foreach ($contactNodes as $contactNode) {
+			# Check if we have found the relevant contact nodes
+			$type = $contactNode->getAttribute('type');
+			if ($type == "admin") {
+				$adminContactID = $contactNode->nodeValue;
+			} elseif ($type == "tech") {
+				$techContactID = $contactNode->nodeValue;
+			} elseif ($type == "billing") {
+				$billingContactID = $contactNode->nodeValue;
 			}
 		}
 
-		$results["Registrant"]["Phone"] = $doc->getElementsByTagName('voice')->item(0)->nodeValue;
-		$results["Registrant"]["Email"] = $doc->getElementsByTagName('email')->item(0)->nodeValue;
+		if (empty($adminContactID)) {
+			$values["error"] = "_GetContactDetails/domain-info($domain): Admin contact info not available";
+			return $values;
+		}
+		if (empty($techContactID)) {
+			$values["error"] = "_GetContactDetails/domain-info($domain): Technical contact info not available";
+			return $values;
+		}
+		if (empty($billingContactID)) {
+			$values["error"] = "_GetContactDetails/domain-info($domain): Billing contact info not available";
+			return $values;
+		}
 
-		return $results;
 	} catch (Exception $e) {
-		$values["error"] = 'GetContactDetails/EPP: '.$e->getMessage();
+		$values["error"] = '_GetContactDetails/EPP: '.$e->getMessage();
 		return $values;
 	}
+
+	# Grab contacts
+	$registrantContactInfo = __getContact($registrantContactID,$client);
+	# If there was an error return it
+	if (isset($registrantContactInfo["error"])) {
+		return $registrantContactInfo;
+	}
+	$adminContactInfo = __getContact($adminContactID,$client);
+	# If there was an error return it
+	if (isset($adminContactInfo["error"])) {
+		return $adminContactInfo;
+	}
+	$techContactInfo = __getContact($techContactID,$client);
+	# If there was an error return it
+	if (isset($techContactInfo["error"])) {
+		return $techContactInfo;
+	}
+	$billingContactInfo = __getContact($billingContactID,$client);
+	# If there was an error return it
+	if (isset($billingContactInfo["error"])) {
+		return $billingContactInfo;
+	}
+
+	$results['Registrant'] = $registrantContactInfo;
+	$results['Admin'] = $adminContactInfo;
+	$results['Technical'] = $techContactInfo;
+	$results['Billing'] = $billingContactInfo;
+
+	return $results;
 }
 
 
@@ -868,27 +940,29 @@ function cozaepp_GetContactDetails($params) {
 	$domain = strtolower("$sld.$tld");
 
 	# Fetching contact details
-	$results = _getContactDetails($domain);
-
+	$contacts = _getContactDetails($domain);
 	# If there was an error return it
-	if (isset($results["error"])) {
-		return $results;
+	if (isset($contacts["error"])) {
+		return $contacts;
 	}
 
 	# What we going to do here is make sure all the attirbutes we return back are set
 	# If we don't do this WHMCS won't display the options for editing
-	foreach (
-			array("Contact Name","Organisation","Address line 1","Address line 2","TownCity","State","Zip code","Country Code","Phone","Email")
+	foreach (array("Registrant","Admin","Technical","Billing") as $type) {
+		foreach (
+			array("Contact Name","Organisation","Address line 1","Address line 2","TownCity","State","Zip code","Country Code",
+					"Phone","Email")
 			as $item
-	) {
-		# Check if the item is set
-		if ($results["Registrant"][$item] == "") {
-			# Just set it to -
-			$values["Registrant"][$item] = "-";
-		} else {
-			# We setting this here so we maintain the right order, else we get the set
-			# things first and all the unsets second, which looks crap
-			$values["Registrant"][$item] = $results["Registrant"][$item];
+		) {
+			# Check if the item is set
+			if (empty($contacts[$type][$item])) {
+				# Just set it to -
+				$values[$type][$item] = "-";
+			} else {
+				# We setting this here so we maintain the right order, else we get the set
+				# things first and all the unsets second, which looks crap
+				$values[$type][$item] = $contacts[$type][$item];
+			}
 		}
 	}
 
@@ -904,76 +978,138 @@ function cozaepp_GetContactDetails($params) {
  * https://gitlab.devlabs.linuxassist.net/awit-whmcs/whmcs-coza-epp/issues/11#note_630
  * http://lists.linuxassist.net/pipermail/whmcs-coza-epp_lists.linuxassist.net/2013-April/000319.html
  */
-function _getContactDetailsFromParams($params) {
+function _getContactDetailsFromParams($params,$type) {
 	$results = array();
 
-	$results["Contact Name"] = $params["contactdetails"]["Registrant"]["Contact Name"];
+	$results["Contact Name"] = $params["contactdetails"][$type]["Contact Name"];
 
-	// Catching different variations of Organisation
-	if (isset($params["contactdetails"]["Registrant"]["Organisation"])) {
-		$results["Organisation"] = $params["contactdetails"]["Registrant"]["Organisation"];
-	} else if (isset($params["contactdetails"]["Registrant"]["Company Name"])) {
-		$results["Organisation"] = $params["contactdetails"]["Registrant"]["Company Name"];
+	# Catching different variations of Organisation
+	if (isset($params["contactdetails"][$type]["Organisation"])) {
+		$results["Organisation"] = $params["contactdetails"][$type]["Organisation"];
+	} else if (isset($params["contactdetails"][$type]["Company Name"])) {
+		$results["Organisation"] = $params["contactdetails"][$type]["Company Name"];
 	} else {
 		$results["Organisation"] = "";
 	}
 
-	// Catching different variations of Address line 1
-	if (isset($params["contactdetails"]["Registrant"]["Address line 1"])) {
-		$results["Address line 1"] = $params["contactdetails"]["Registrant"]["Address line 1"];
-	} else if (isset($params["contactdetails"]["Registrant"]["Address 1"])) {
-		$results["Address line 1"] = $params["contactdetails"]["Registrant"]["Address 1"];
+	# Catching different variations of Address line 1
+	if (isset($params["contactdetails"][$type]["Address line 1"])) {
+		$results["Address line 1"] = $params["contactdetails"][$type]["Address line 1"];
+	} else if (isset($params["contactdetails"][$type]["Address 1"])) {
+		$results["Address line 1"] = $params["contactdetails"][$type]["Address 1"];
 	} else {
 		$results["Address line 1"] = "";
 	}
 
-	// Catching different variations of Address line 2
-	if (isset($params["contactdetails"]["Registrant"]["Address line 2"])) {
-		$results["Address line 2"] = $params["contactdetails"]["Registrant"]["Address line 2"];
-	} else if (isset($params["contactdetails"]["Registrant"]["Address 2"])) {
-		$results["Address line 2"] = $params["contactdetails"]["Registrant"]["Address 2"];
+	# Catching different variations of Address line 2
+	if (isset($params["contactdetails"][$type]["Address line 2"])) {
+		$results["Address line 2"] = $params["contactdetails"][$type]["Address line 2"];
+	} else if (isset($params["contactdetails"][$type]["Address 2"])) {
+		$results["Address line 2"] = $params["contactdetails"][$type]["Address 2"];
 	} else {
 		$results["Address line 2"] = "";
 	}
 
-	// Catching different variations of TownCity
-	if (isset($params["contactdetails"]["Registrant"]["TownCity"])) {
-		$results["TownCity"] = $params["contactdetails"]["Registrant"]["TownCity"];
-	} else if (isset($params["contactdetails"]["Registrant"]["City"])) {
-		$results["TownCity"] = $params["contactdetails"]["Registrant"]["City"];
+	# Catching different variations of TownCity
+	if (isset($params["contactdetails"][$type]["TownCity"])) {
+		$results["TownCity"] = $params["contactdetails"][$type]["TownCity"];
+	} else if (isset($params["contactdetails"][$type]["City"])) {
+		$results["TownCity"] = $params["contactdetails"][$type]["City"];
 	} else {
 		$results["TownCity"] = "";
 	}
 
-	$results["State"] = $params["contactdetails"]["Registrant"]["State"];
+	$results["State"] = $params["contactdetails"][$type]["State"];
 
-	// Catching different variations of Postal Code
-	if (isset($params["contactdetails"]["Registrant"]["Zip code"])) {
-		$results["Zip code"] = $params["contactdetails"]["Registrant"]["Zip code"];
-	} else if (isset($params["contactdetails"]["Registrant"]["ZIP Code"])) {
-		$results["Zip code"] = $params["contactdetails"]["Registrant"]["ZIP Code"];
-	} else if (isset($params["contactdetails"]["Registrant"]["Postcode"])) {
-		$results["Zip code"] = $params["contactdetails"]["Registrant"]["Postcode"];
+	# Catching different variations of Postal Code
+	if (isset($params["contactdetails"][$type]["Zip code"])) {
+		$results["Zip code"] = $params["contactdetails"][$type]["Zip code"];
+	} else if (isset($params["contactdetails"][$type]["ZIP Code"])) {
+		$results["Zip code"] = $params["contactdetails"][$type]["ZIP Code"];
+	} else if (isset($params["contactdetails"][$type]["Postcode"])) {
+		$results["Zip code"] = $params["contactdetails"][$type]["Postcode"];
 	} else {
 		$results["Zip code"] = "";
 	}
 
-	// Catching different variations of Country Code
-	if (isset($params["contactdetails"]["Registrant"]["Country Code"])) {
-		$results["Country Code"] = $params["contactdetails"]["Registrant"]["Country Code"];
-	} else if (isset($params["contactdetails"]["Registrant"]["Country"])) {
-		$results["Country Code"] = $params["contactdetails"]["Registrant"]["Country"];
+	# Catching different variations of Country Code
+	if (isset($params["contactdetails"][$type]["Country Code"])) {
+		$results["Country Code"] = $params["contactdetails"][$type]["Country Code"];
+	} else if (isset($params["contactdetails"][$type]["Country"])) {
+		$results["Country Code"] = $params["contactdetails"][$type]["Country"];
 	} else {
 		$results["Country Code"] = "";
 	}
 
-	$results["Phone"] = $params["contactdetails"]["Registrant"]["Phone"];
-	$results["Email"] = $params["contactdetails"]["Registrant"]["Email"];
+	$results["Phone"] = $params["contactdetails"][$type]["Phone"];
+	$results["Email"] = $params["contactdetails"][$type]["Email"];
 
 	return $results;
 }
 
 
+# Function to actually do the saving of contact details
+function __saveContact($contactID,$contacts,$type,$client = null) {
+	# Get client instance
+	try {
+		if (!isset($client)) {
+			$client = _cozaepp_Client($domain);
+		}
+
+		# Grab contact
+		$contact = $contacts[$type];
+
+		# Save contact details
+		$request = $client->request($xml = '
+<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
+	<epp:command>
+		<epp:update>
+			<contact:update>
+				<contact:id>'.$contactID.'</contact:id>
+				<contact:chg>
+					<contact:postalInfo type="loc">
+						<contact:name>'.$contact['Contact Name'].'</contact:name>
+						<contact:org>'.$contact['Organization'].'</contact:org>
+						<contact:addr>
+							<contact:street>'.$contact['Address line 1'].'</contact:street>
+							<contact:street>'.$contact['Address line 2'].'</contact:street>
+							<contact:city>'.$contact['TownCity'].'</contact:city>
+							<contact:sp>'.$contact['State'].'</contact:sp>
+							<contact:pc>'.$contact['Zip code'].'</contact:pc>
+							<contact:cc>'.$contact['Country Code'].'</contact:cc>
+						</contact:addr>
+						</contact:postalInfo>
+						<contact:voice>'.$contact['Phone'].'</contact:voice>
+						<contact:fax></contact:fax>
+						<contact:email>'.$contact['Email'].'</contact:email>
+				</contact:chg>
+			</contact:update>
+		</epp:update>
+	</epp:command>
+</epp:epp>
+');
+
+		# Parse XML result
+		$doc= new DOMDocument();
+		$doc->loadXML($request);
+		logModuleCall('Cozaepp', 'SaveContactDetails', $xml, $request);
+
+		$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
+		$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
+		if($coderes != '1001') {
+			$values["error"] = "SaveContactDetails/contact-update($registrant): Code ($coderes) $msg";
+			return $values;
+		}
+
+		$values["status"] = $msg;
+
+		return $values;
+	} catch (Exception $e) {
+		$values["error"] = 'SaveContactDetails/EPP: '.$e->getMessage();
+		return $values;
+	}
+}
+
 
 # Function to save contact details
 function cozaepp_SaveContactDetails($params) {
@@ -983,19 +1119,10 @@ function cozaepp_SaveContactDetails($params) {
 	$domain = strtolower("$sld.$tld");
 	# Registrant details
 
-	$contactDetails = _getContactDetailsFromParams($params);
-
-	$registrant_name = $contactDetails["Contact Name"];
-	$registrant_org = $contactDetails["Organisation"];
-	$registrant_address1 = $contactDetails["Address line 1"];
-	$registrant_address2 = $contactDetails["Address line 2"];
-	$registrant_town = $contactDetails["TownCity"];
-	$registrant_state = $contactDetails["State"];
-	$registrant_zipcode = $contactDetails["Zip code"];
-	$registrant_countrycode = $contactDetails["Country Code"];
-	$registrant_phone = $contactDetails["Phone"];
-	#$registrant_fax = '',
-	$registrant_email = $contactDetails["Email"];
+	$registrantContactDetails = _getContactDetailsFromParams($params,"Registrant");
+	$adminContactDetails = _getContactDetailsFromParams($params,"Admin");
+	$technicalContactDetails = _getContactDetailsFromParams($params,"Technical");
+	$billingContactDetails = _getContactDetailsFromParams($params,"Billing");
 
 	# Get client instance
 	try {
@@ -1026,54 +1153,167 @@ function cozaepp_SaveContactDetails($params) {
 			return $values;
 		}
 
-		$values["status"] = $msg;
+		# Grab contact ID's
+		$registrantContactID = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;
+		if (empty($registrantContactID)) {
+			$values["error"] = "_SaveContactDetails/domain-info($domain): Registrant contact info not available";
+			return $values;
+		}
 
-		# Time to do the update
-		$registrant = $doc->getElementsByTagName('registrant')->item(0)->nodeValue;
+		$contactNodes = $doc->getElementsByTagName('contact');
+		foreach ($contactNodes as $contactNode) {
+			# Check if we have found the relevant contact nodes
+			$type = $contactNode->getAttribute('type');
+			if ($type == "admin") {
+				$adminContactID = $contactNode->nodeValue;
+			} elseif ($type == "tech") {
+				$techContactID = $contactNode->nodeValue;
+			} elseif ($type == "billing") {
+				$billingContactID = $contactNode->nodeValue;
+			}
+		}
 
-		# Save contact details
-		$request = $client->request($xml = '
-<epp:epp xmlns:epp="urn:ietf:params:xml:ns:epp-1.0" xmlns:contact="urn:ietf:params:xml:ns:contact-1.0">
+		if (empty($adminContactID)) {
+			$values["error"] = "_SaveContactDetails/domain-info($domain): Admin contact info not available";
+			return $values;
+		}
+		if (empty($techContactID)) {
+			$values["error"] = "_SaveContactDetails/domain-info($domain): Technical contact info not available";
+			return $values;
+		}
+		if (empty($billingContactID)) {
+			$values["error"] = "_SaveContactDetails/domain-info($domain): Billing contact info not available";
+			return $values;
+		}
+
+		# Create contacts for use in our recreate below
+		$contacts['Registrant'] = $registrantContactDetails;
+		$contacts['Admin'] = $adminContactDetails;
+		$contacts['Technical'] = $technicalContactDetails;
+		$contacts['Billing'] = $billingContactDetails;
+
+		# We'll store the XML in here if we need to recreate contacts, this happens if admin/tech/billing are the same as
+		# registrant
+		$contactXML_chg = '';
+		$contactXML_rem = '';
+		$contactXML_add = '';
+		# Store errors we got
+		$errors = '';
+
+		# Check the contact ID's differ, if not, recreate the extra ones
+		if ($adminContactID == $registrantContactID || $adminContactID == $techContactID || $adminContactID == $billingContactID) {
+			$adminContact = __recreateContact($domain,$contacts,"Admin",$client);
+			# If there was an error return it
+			if (!isset($adminContact["error"])) {
+				$contactXML_rem .= '<domain:contact type="admin">'.$adminContactID.'</domain:contact>';
+				$adminContactID = $adminContact['contactid'];
+				$contactXML_add .= '<domain:contact type="admin">'.$adminContactID.'</domain:contact>';
+			} else {
+				$errors .= $adminContact["error"];
+			}
+		} else {
+			$values = __saveContact($adminContactID,$contacts,"Admin",$client);
+			# If there was an error return it
+			if (isset($values["error"])) {
+				$errors .= $values["error"];
+			}
+		}
+
+		if ($techContactID == $registrantContactID || $techContactID == $adminContactID || $techContactID == $billingContactID) {
+			$techContact = __recreateContact($domain,$contacts,"Technical",$client);
+			# If there was an error return it
+			if (!isset($techContact["error"])) {
+				$contactXML_rem .= '<domain:contact type="tech">'.$techContactID.'</domain:contact>';
+				$techContactID = $techContact['contactid'];
+				$contactXML_add .= '<domain:contact type="tech">'.$techContactID.'</domain:contact>';
+			} else {
+				$errors .= $adminContact["error"];
+			}
+		} else {
+			$values = __saveContact($techContactID,$contacts,"Technical",$client);
+			# If there was an error return it
+			if (isset($values["error"])) {
+				$errors .= $values["error"];
+			}
+		}
+
+		if ($billingContactID == $registrantContactID || $billingContactID == $adminContactID || $billingContactID == $techContactID) {
+			$billingContact = __recreateContact($domain,$contacts,"Billing",$client);
+			# If there was an error return it
+			if (!isset($billingContact["error"])) {
+				$contactXML_rem .= '<domain:contact type="billing">'.$billingContactID.'</domain:contact>';
+				$billingContactID = $billingContact['contactid'];
+				$contactXML_add .= '<domain:contact type="billing">'.$billingContactID.'</domain:contact>';
+			} else {
+				$errors .= $billingContact["error"];
+			}
+		} else {
+			$values = __saveContact($billingContactID,$contacts,"Billing",$client);
+			# If there was an error return it
+			if (isset($values["error"])) {
+				$errors .= $values["error"];
+			}
+		}
+
+		# Save registrant
+		$values = __saveContact($registrantContactID,$contacts,"Registrant",$client);
+		# If there was an error return it
+		if (isset($values["error"])) {
+			$errors .= $values["error"];
+		}
+
+		$contactXML_chg .= '<domain:registrant>'.$registrantContactID.'</domain:registrant>';
+
+		# Build the XML for the updates we need to do
+		$contactXML = "";
+		if (!empty($contactXML_add)) {
+			$contactXML .= '<domain:add>'.$contactXML_add.'</domain:add>';
+		}
+		if (!empty($contactXML_rem)) {
+			$contactXML .= '<domain:rem>'.$contactXML_rem.'</domain:rem>';
+		}
+		if (!empty($contactXML_chg)) {
+			$contactXML .= '<domain:chg>'.$contactXML_chg.'</domain:chg>';
+		}
+
+		# Check if we need to do a contact ID update
+		if (!empty($contactXML)) {
+			# Update domain contacts if any changed
+			$request = $client->request($xml = '
+<epp:epp xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:epp="urn:ietf:params:xml:ns:epp-1.0"
+		xmlns:domain="urn:ietf:params:xml:ns:domain-1.0" xmlns:cozadomain="http://co.za/epp/extensions/cozadomain-1-0"
+		xsi:schemaLocation="urn:ietf:params:xml:ns:epp-1.0 epp-1.0.xsd">
 	<epp:command>
 		<epp:update>
-			<contact:update>
-				<contact:id>'.$registrant.'</contact:id>
-				<contact:chg>
-					<contact:postalInfo type="loc">
-						<contact:name>'.$registrant_name.'</contact:name>
-						<contact:org>'.$registrant_org.'</contact:org>
-						<contact:addr>
-							<contact:street>'.$registrant_address1.'</contact:street>
-							<contact:street>'.$registrant_address2.'</contact:street>
-							<contact:city>'.$registrant_town.'</contact:city>
-							<contact:sp>'.$registrant_state.'</contact:sp>
-							<contact:pc>'.$registrant_zipcode.'</contact:pc>
-							<contact:cc>'.$registrant_countrycode.'</contact:cc>
-						</contact:addr>
-						</contact:postalInfo>
-						<contact:voice>'.$registrant_phone.'</contact:voice>
-						<contact:fax></contact:fax>
-						<contact:email>'.$registrant_email.'</contact:email>
-				</contact:chg>
-			</contact:update>
+			<domain:update>
+				<domain:name>'.$domain.'</domain:name>
+				'.$contactXML.'
+			</domain:update>
 		</epp:update>
 	</epp:command>
 </epp:epp>
 ');
+			# Parse XML result
+			$doc= new DOMDocument();
+			$doc->loadXML($request);
+			logModuleCall('Cozaepp', 'SaveContactDetails', $xml, $request);
 
-		# Parse XML result
-		$doc= new DOMDocument();
-		$doc->loadXML($request);
-		logModuleCall('Cozaepp', 'SaveContactDetails', $xml, $request);
+			$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
+			$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
+			if($coderes != '1001') {
+				$errors .= "_SaveContactDetails/domain-info($domain): Code (".$coderes.") ".$msg;
+			}
+		}
 
-		$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
-		$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
-		if($coderes != '1001') {
-			$values["error"] = "SaveContactDetails/contact-update($registrant): Code ($coderes) $msg";
-			return $values;
+		# Check what we're going to return
+		unset($values);
+		if ($errors) {
+			$values["error"] = $errors;
+		} else {
+			$values['msg'] = "Contact details saved.";
 		}
 
-		$values["status"] = $msg;
+		return $values;
 
 	} catch (Exception $e) {
 		$values["error"] = 'SaveContactDetails/EPP: '.$e->getMessage();
@@ -1520,26 +1760,15 @@ function cozaepp_TransferSync($params) {
 
 
 
-function cozaepp_RecreateContact($params) {
-	# Grab variables
-	$tld = $params["tld"];
-	$sld = $params["sld"];
-	$domain = strtolower("$sld.$tld");
-
+function __recreateContact($domain,$contacts,$type,$client = null) {
 	# Get client instance
 	try {
-		$client = _cozaepp_Client($domain);
-
-		# Fetching contact details
-		$contact = _getContactDetails($domain, $client);
-
-		# If there was an error return it
-		if (isset($contact["error"])) {
-			return $contact;
+		if (!isset($client)) {
+			$client = _cozaepp_Client($domain);
 		}
 
 		# Check for available contact id
-		$registrant = _cozaepp_CheckContact($domain);
+		$contactID = _cozaepp_CheckContact($domain,$type);
 
 		# Generate a random password for the contact
 		$pw = substr(md5($domain . time() . rand(0, 1000000)), 0,15);
@@ -1551,22 +1780,22 @@ function cozaepp_RecreateContact($params) {
 	<epp:command>
 		<epp:create>
 			<contact:create xsi:schemaLocation="urn:ietf:params:xml:ns:contact-1.0 contact-1.0.xsd">
-				<contact:id>'.$registrant.'</contact:id>
+				<contact:id>'.$contactID.'</contact:id>
 				<contact:postalInfo type="loc">
-				<contact:name>'.$contact["Registrant"]["Contact Name"].'</contact:name>
-				<contact:org>'.$contact["Registrant"]["Organisation"].'</contact:org>
+				<contact:name>'.$contacts[$type]["Contact Name"].'</contact:name>
+				<contact:org>'.$contacts[$type]["Organisation"].'</contact:org>
 				<contact:addr>
-					<contact:street>'.$contact["Registrant"]["Address line 1"].'</contact:street>
-					<contact:street>'.$contact["Registrant"]["Address line 2"].'</contact:street>
-					<contact:city>'.$contact["Registrant"]["TownCity"].'</contact:city>
-					<contact:sp>'.$contact["Registrant"]["State"].'</contact:sp>
-					<contact:pc>'.$contact["Registrant"]["Zip code"].'</contact:pc>
-					<contact:cc>'.$contact["Registrant"]["Country Code"].'</contact:cc>
+					<contact:street>'.$contacts[$type]["Address line 1"].'</contact:street>
+					<contact:street>'.$contacts[$type]["Address line 2"].'</contact:street>
+					<contact:city>'.$contacts[$type]["TownCity"].'</contact:city>
+					<contact:sp>'.$contacts[$type]["State"].'</contact:sp>
+					<contact:pc>'.$contacts[$type]["Zip code"].'</contact:pc>
+					<contact:cc>'.$contacts[$type]["Country Code"].'</contact:cc>
 				</contact:addr>
 				</contact:postalInfo>
-				<contact:voice>'.$contact["Registrant"]["Phone"].'</contact:voice>
+				<contact:voice>'.$contacts[$type]["Phone"].'</contact:voice>
 				<contact:fax></contact:fax>
-				<contact:email>'.$contact["Registrant"]["Email"].'</contact:email>
+				<contact:email>'.$contacts[$type]["Email"].'</contact:email>
 				<contact:authInfo>
 					<contact:pw>'.$pw.'</contact:pw>
 				</contact:authInfo>
@@ -1579,16 +1808,70 @@ function cozaepp_RecreateContact($params) {
 		# Parse XML result
 		$doc= new DOMDocument();
 		$doc->loadXML($request);
-		logModuleCall('Cozaepp', 'RecreateContact', $xml, $request);
+		logModuleCall('Cozaepp', '__recreateContact', $xml, $request);
 
 		$coderes = $doc->getElementsByTagName('result')->item(0)->getAttribute('code');
 		$msg = $doc->getElementsByTagName('msg')->item(0)->nodeValue;
 		if($coderes != '1000') {
-			$values["error"] = "RecreateContact/contact-create($registrant): Code ($coderes) $msg";
+			$values["error"] = "__recreateContact/contact-create($contactID:$type): Code ($coderes) $msg";
 			return $values;
 		}
 
-		$values["status"] = $msg;
+		$values["contactid"] = $contactID;
+
+		return $values;
+	} catch (Exception $e) {
+		$values["error"] = '__recreateContact/EPP: '.$e->getMessage();
+		return $values;
+	}
+}
+
+
+function cozaepp_RecreateContact($params) {
+	# Grab variables
+	$tld = $params["tld"];
+	$sld = $params["sld"];
+	$domain = strtolower("$sld.$tld");
+
+	# Get client instance
+	try {
+		$client = _cozaepp_Client($domain);
+
+		# Fetching contact details
+		$contacts = _getContactDetails($domain, $client);
+		# If there was an error return it
+		if (isset($contacts["error"])) {
+			return $contacts;
+		}
+
+		# Create contacts
+		$registrantContact = __recreateContact($domain,$contacts,"Registrant",$client);
+		# If there was an error return it
+		if (isset($registrantContact["error"])) {
+			return $registrantContact;
+		}
+		$registrantContactID = $registrantContact['contactid'];
+
+		$adminContact = __recreateContact($domain,$contacts,"Admin",$client);
+		# If there was an error return it
+		if (isset($adminContact["error"])) {
+			return $adminContact;
+		}
+		$adminContactID = $adminContact['contactid'];
+
+		$techContact = __recreateContact($domain,$contacts,"Technical",$client);
+		# If there was an error return it
+		if (isset($techContact["error"])) {
+			return $techContact;
+		}
+		$techContactID = $techContact['contactid'];
+
+		$billingContact = __recreateContact($domain,$contacts,"Billing",$client);
+		# If there was an error return it
+		if (isset($billingContact["error"])) {
+			return $billingContact;
+		}
+		$billingContactID = $billingContact['contactid'];
 
 		# Update domain registrant
 		$request = $client->request($xml = '
@@ -1598,7 +1881,10 @@ function cozaepp_RecreateContact($params) {
 			<domain:update>
 				<domain:name>'.$domain.'</domain:name>
 				<domain:chg>
-					<domain:registrant>'.$registrant.'</domain:registrant>
+					<domain:registrant>'.$registrantContactID.'</domain:registrant>
+					<domain:admin>'.$adminContactID.'</domain:admin>
+					<domain:tech>'.$techContactID.'</domain:tech>
+					<domain:billing>'.$billingContactID.'</domain:billing>
 				</domain:chg>
 			</domain:update>
 		</epp:update>