REST PATCH - "Create not allowed" / 400 response?

I am trying to run a PATCH through the REST GUI for PriceLstPartsSrv::PLPartBrks(’{Company}’,’{ListCode}’,’{PartNum}’,{Quantity},’{UOMCode}’) and keep getting a 400 response (posted below).

The connection is super basic, as I’m only trying to update a price for a particular list/part/qty. When running PATCH for other services (e.g. Ship Via to update a single description) I have no issues. Below are the responses from the REST GUI. Are you able to run a PATCH to update an individual price for an individual list/part/qty? Any ideas?

curl -X PATCH “https://our_server/pilot700/api/v2/odata/GLCT/Erp.BO.PriceLstPartsSvc/PLPartBrks(‘GLCT’,‘MFGCINST’,‘811-63786-1000’,2,‘EA’)” -H “accept: application/json” -H “X-API-Key: ourapikey” -H “Content-Type: application/json” -H “Authorization: Bearer ourauthorizationbearer” -d “{ “UnitPrice”: 68.99}”

Request URL

“HttpStatus”: 400,
“ReasonPhrase”: “REST API Exception”,
“ErrorMessage”: “Create not allowed.”,
“ErrorType”: “Ice.Common.BusinessObjectException”,
“ErrorDetails”: [
“Message”: “Create not allowed.”,
“Type”: “Error”,
“Table”: “PLPartBrk”,
“Program”: “Epicor.RESTApi.dll”,
“Method”: “ThrowUpdateExtException”,
“ColumnNumber”: 17,
“LineNumber”: 48
“CorrelationId”: “56db7d7d-01b1-400f-aadc-b22bd7c3087c”

Response Headers
access-control-allow-credentials: true
access-control-allow-origin: https://ourserver
access-control-expose-headers: ContextHeader
cache-control: private
content-length: 381
content-type: application/json; charset=utf-8
date: Thu16 Jun 2022 14:46:26 GMT
server: Microsoft-IIS/10.0
x-aspnet-version: 4.0.30319

I just tested it on my system and got the same result. In order for the PATCH to be accepted, I had to include the “SysRowID” of the PLPartBrk record in the body of the request. When I did that, I got a 200 OK response the first time, but am subsequently getting 400 Update not allowed as a response even though the smart client shows the update actually goes through. A little weird.

We’ve had issues with updates using the v2 interface, and have to use the v1 interface for updates. Using v1 always works for us, though we’d prefer to use v2 for both Get and Patch instead of just Get.

Thank you both, but I’m still stuck.

I was hopeful to use v1 for this one call to Price List Part Breaks, but it also throws an error in Swagger. v2 connects when I provide the SysRowID, but I haven’t been able to actually update any value.

We’re able to make PATCH calls through v1 and v2 for other services through both Swagger and our app, such as customers, e.g

← those both work to update any customer fields

but not for Price List Part Breaks… perhaps this service is broken in both v1 and v2?


Any thoughts on using the @Aaron_Moreng method of integration and use an Epicor Function instead of calling the BOs directly? It’s more efficient over the wire, and it does not let Epicor logic sneak into your client making upgrades easier.

What is this magic method of integration that you are referring to?

Function error logged - ERP 10 - Epicor User Help Forum (


Okay, I’ve reviewed the link and I think I understand what he is doing, but why wouldn’t one stick with the REST API to handle this same sort of integration? I thought the standards in their API would allow anyone to tap into the system without any customization within Epicor and just stick with an API version.

… I guess I’m confused why I’d want to consider leaving their API structure for custom integrations.

I’m just getting going with it. Is it really under developed? Other API endpoints have worked flawlessly and have been easy to pull and push data. Are there speed issues with the REST stack?


First of all, you’re still using REST but calling your EFx instead. Secondly, YOU get to decide what the API looks like. Your client doesn’t have to know about RowMod or other Epicor specific requirements. You can send multiple requests in a single call and receive results in a single call leading to fewer transactions over the wire. When upgrading Epicor, you generally won’t have to touch every client calling your system to update them to a newer version since all the code is encapsulated in your functions. OData is another wrapper around the RPC functions and there have been some errors in implementation (fewer with time). You always run v2 REST. There is better control over error handling and notification within functions.

The downside is everything is a POST with functions. Finally, you don’t have control over the HTTP status. It’s generally 200, 403 or 500.

1 Like

PriceLstParts does not allow to create/modify parts or part breaks, this should be done with the PriceLst BO. But even if you use that you will probably run into error

"Duplicate quantity found."

It seems the reason this is not working is because the Quantity is not matching the existing record because of the decimals.

In my tests the quantity on the database has 8 decimals, so sending 10 in swagger did not work, but sending 10.00000000 actually worked to get past the error, I will check this and probably create an internal ticket. Not a lot of entities have a decimal column as part of the key, as a workaround as mentioned is to use the SysRowID.

The original REST API was exposed as the first generation of exposing all of the native Epicor APIs via REST in that it was a REST wrapper over the WCF services. These included the OData ones and the custom RPC calls. By design, they mimic the client and have complex and chatty datasets (often).
The second iteration (v2) included more security (API key required). Epicor Functions are called over the v2 API but you can basically forget about most of the other APIs if you use Functions. I still use the BAQ service, but basically everything else outside of getting a session can be rolled into a function.
I view the Epicor Functions as the preferred approach of REST integration technology. You get to use the RESTful architecture without needing to deal with the complexities of the Epicor API (in that you don’t need to mimic the client calls over their REST API) and can instead expose a user defined endpoint with your own request and response signatures and can leverage the Functions GUI to handle ALL of the server side logic. This vastly improves both performance over the wire (all the work is being done on the server, not passing calls and data back and forth to your client) and packages up all the business logic in a perfect little package in Epicor.

The only speed issues I’ve had (with Functions) is that they are blazing fast and have outpaced the PHP app calling it. It’s really the best approach you can take.