API to create a new Customer

Seem to be struggling here to create a new customer via the API docs. I’m supplying the following via a post to the URL: https://xx.com/xx/api/v1/Erp.BO.CustomerSvc/Customers

{
  "Company": "1",
  "Name": "Customer Name",
  "Address1": "1234 Anywhere St",
  "Address2": "Ste 123",
  "City": "Atlanta",
  "State": "GA",
  "Zip": "12345",
  "Country": "USA",
  "PhoneNum": "855-123-4567",
  "EMailAddress": "myemail@mydomain.com"
}

For what its worth it is a PHP script, and I’m sending the post via curl in a normal fashion of ‘key’ => ‘value’

I continuously get a 400 error:

{
  "odata.metadata": "https://xx.com/xx/api/v1/Erp.BO.CustomerSvc/$metadata#Edm.String",
  "value": "Unable to deserialize entity"
}

I dont know what is formatting wrong? Any ideas what I might be missing? This is a brand new customer that doesnt exist yet.

Hey Marcus,
I’m wondering if the @ symbol is being tripped up on the php to .net serialization. Can you try removing that from your payload and see if it goes through ok?

/* Get Cust / Pass "CustNum" */
	function createCust($data){
		$service = "Erp.BO.CustomerSvc/Customers";
		
		return $this->call_epicor($service, $data);
	}
function submitCustPerConForm() {
		$action = ee()->input->get('action', true);
		$actions = array('create_cust', 'create_percon', 'create_link');
		
		$return_data['success'] = 0;
		$return_data['message'] = "";
		
		if($action && in_array($action, $actions)) { 
			switch ($action) {
				case "create_cust":
					$Name = ee()->input->post('Name', true);
					$Address1 = ee()->input->post('Address1', true);
					$Address2 = ee()->input->post('Address2', true);
					$Address3 = ee()->input->post('Address3', true);
					$City = ee()->input->post('City', true);
					$State = ee()->input->post('State', true);
					$Zip = ee()->input->post('Zip', true);
					$EMailAddress = ee()->input->post('EMailAddress', true);
					$PhoneNum = ee()->input->post('PhoneNum', true);
					$FaxNum = ee()->input->post('FaxNum', true);
					$custID = ee()->input->post('custID', true);
					
					$BTName = ee()->input->post('BTName', true);
					$BTPhoneNum = ee()->input->post('BTPhoneNum', true);
					$BTFaxNum = ee()->input->post('BTFaxNum', true);
					$BTAddress1 = ee()->input->post('BTAddress1', true);
					$BTAddress2 = ee()->input->post('BTAddress2', true);
					$BTAddress3 = ee()->input->post('BTAddress3', true);
					$BTCity = ee()->input->post('BTCity', true);
					$BTState = ee()->input->post('BTState', true);
					$BTZip = ee()->input->post('BTZip', true);				

					if($Name){
						$data = array(
							"Company" 		=> 	"JRF",
							"Name" 			=> 	"$Name",
							"Address1" 		=> 	"$Address1",
							"Address2" 		=> 	"$Address2",
							"Address3" 		=> 	"$Address3",
							"City"			=> 	"$City",
							"State" 		=> 	"$State",
							"Zip" 			=> 	"$Zip",
							"EMailAddress"	=> 	"$EMailAddress",
							"PhoneNum" 		=> 	"$PhoneNum",
							"FaxNum" 		=> 	"$FaxNum",
							"BTName" 		=> 	"$BTName",
							"BTPhoneNum" 	=> 	"$BTPhoneNum",
							"BTFaxNum" 		=> 	"$BTFaxNum",
							"BTAddress1" 	=> 	"$BTAddress1",
							"BTAddress2" 	=> 	"$BTAddress2",
							"BTAddress3" 	=> 	"$BTAddress3",
							"BTCity" 		=> 	"$BTCity",
							"BTState" 		=> 	"$BTState",
							"BTZip" 		=> 	"$BTZip",
							"GroupCode"  	=> 	"DR",
							"CustomerType"  => 	"CUS",
						);
						if($custID != ""){
							$data["CustID"] = "$custID";
							$data["GroupCode"] = "FAC";
						}
						
						$result = $this->api->createCust($data);						
						if(!$result['success']){
							$return_data['message'] .= isset($result['error_msg']) && $result['error_msg'] != "" ? $result['error_msg'] : "Epicor Connection Error";
						}
function call_epicor($service, $post_data = null, $method = null) {

		if(!$service){
			return false;
		}
		
		if($this->hlp_fn->_is_asc()){
			$conn_timeout = 30;
		}else{
			$conn_timeout = 9;
		}
		
		$url = $this->creds['url'] . $this->encode_url_epi($service);
		$user = $this->creds['user'];
		$pass = $this->creds['pass'];
		
		$headers = array(                                                                          
			'Content-Type: application/json',
		);
		if($post_data){
			$data_string = json_encode($post_data);
			$headers[] = 'Content-Length: ' . strlen($data_string);
		}
		if($this->session_id != "" && $this->session_id !== false && $this->skip_session == false){
			$sess_arr = array('SessionID' => $this->session_id);
			$headers[] = 'SessionInfo: ' . json_encode($sess_arr);
		}
		
		/* Curl Init */
		$ch = curl_init($url);
		curl_setopt($ch, CURLOPT_USERPWD, "$user:$pass");
		curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
		curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, $conn_timeout); 
		curl_setopt($ch, CURLOPT_TIMEOUT, 80);
		if($post_data){
			if($method){
				curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
			}else{
				curl_setopt($ch, CURLOPT_POST, 1);
			}
			curl_setopt($ch, CURLOPT_POSTFIELDS, $data_string);
		}elseif($method == "POST0"){
			$headers[] = 'Content-Length: 0';
			curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "POST");
		}
		curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
				
		$result = curl_exec($ch);
		$http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
		curl_close($ch);
		
		$return_data = array(
			'data' => $result,
			'code' => $http_code,
		);
		$check = $this->checkResponse($return_data, $service);
		$return_data['success'] = $check['success'];
		$return_data['error_msg'] = isset($check['ErrorMessage']) ? $check['ErrorMessage'] : false;
						
		return $return_data;
	}

Unfortunately no luck on that either, good thought though for sure!

I should also note, this payload doesnt work via the REST Swagger utility via the /api/v1/help section either. I’ve not been able to figure out the combination of stuff to make that accept and work properly either, so I dont think it is PHP related. Nothing is marked as required, but it doesn’t seem that anything works that I try

Oh really? So it doesn’t work in Swagger too? Are you using “” and not ’ ’ ?

Do you have all required fields in the payload? I don’t see a CustID for example.

1 Like

I’m guessing that is it, I was able to create one in Swagger with just below (and yes, I left the default “string” values :slight_smile: )

{
  "Company": "EPIC06",
  "CustID": "testapi",
  "CustNum": 0,
  "Name": "test api",
  "Address1": "string",
  "Address2": "string",
  "Address3": "string"
}
1 Like

Is there a list of required fields? Nothing in the docs explain what is required. I didnt realize CustID wouldn’t be generated automatically I guess.

Specifying a random value to CustID is now giving me a different error, so there is some progress.

Something you will hear a lot on this list: Trace is your friend. Do the command at the terminal and capture the trace. (There are other threads you can search for how to do this.) Enter the minimal amount of fields to determine the required fields. Use the most of the template as your guide.

If you have DMT, it will show required fields when you create a template - for the most part. :thinking:

3 Likes

Appreciate it, i’m new to using epicor as a 3rd party integrator so all new to me haha!

My next thing is to figure out how to autoincrement the custID upon new customer creation!

No problem Marcus!

You will find searching this forum will provide a lot of help for you. There are many posts about integrations and using REST. If you take some time to learn Epicor Functions, it will simplify your projects even more by not exposing Epicor details within your integration.

As for auto-increment, it’s been done several times. The odd thing is, Epicor allows one to change the Customer ID and Supplier ID whenever you want and uses a separate numeric key internally. The quickest way to do it is to just take the auto-generated CustNum and make it the Customer ID. :person_shrugging:

1 Like