I have a business central API page. When I POST to it, I get a 400 error. Here is the AL code for the page:
page 50115 PunchoutReceiverAPI
{
PageType = API;
APIPublisher = 'Contoso';
APIGroup = 'Punchout';
APIVersion = 'v2.0';
ApplicationArea = All;
Caption = 'Punchout Receiver API';
EntityName = 'PunchoutReceiver';
EntitySetName = 'PunchoutReceivers';
EntityCaption = 'Punchout Receiver';
EntitySetCaption = 'Punchout Receivers';
SourceTable = PunchoutReceiver;
DelayedInsert = true;
InsertAllowed = true;
layout
{
area(content)
{
repeater(Group)
{
field(Payload; Rec.Payload)
{
Caption = 'Payload';
}
}
}
}
actions
{
}
}
and here is the cXML message I am trying to send
"Payload": "<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE cXML SYSTEM "http://xml.cxml.org/schemas/cXML/1.2.014/cXML.dtd">
<cXML xml:lang="en-US" payloadID="933695160894" timestamp="2025-06-30T19:55:33.520Z">
<Header>
<From>
<Credential domain="DUNS">
<Identity>83528721</Identity>
</Credential>
</From>
<To>
<Credential domain="DUNS">
<Identity>65652314</Identity>
</Credential>
</To>
<Sender>
<Credential domain="workchairs.com">
<Identity>website 1</Identity>
</Credential>
<UserAgent>Zilch cXML application</UserAgent>
</Sender>
</Header>
<Message>
<PunchOutOrderMessage>
<BuyerCookie>E281C149319B44BE96115813B382676B</BuyerCookie>
<PunchOutOrderMessageHeader operationAllowed="edit">
<Total>
<Money currency="USD">140.00</Money>
</Total>
</PunchOutOrderMessageHeader>
<ItemIn quantity="2">
<ItemID>
<SupplierPartID>1</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">10.00</Money>
</UnitPrice>
<Description xml:lang="en">Product 1</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
</ItemDetail>
</ItemIn>
<ItemIn quantity="2">
<ItemID>
<SupplierPartID>3</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">30.00</Money>
</UnitPrice>
<Description xml:lang="en">Product 3</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
</ItemDetail>
</ItemIn>
<ItemIn quantity="3">
<ItemID>
<SupplierPartID>2</SupplierPartID>
</ItemID>
<ItemDetail>
<UnitPrice>
<Money currency="USD">20.00</Money>
</UnitPrice>
<Description xml:lang="en">Product 2</Description>
<UnitOfMeasure>EA</UnitOfMeasure>
</ItemDetail>
</ItemIn>
</PunchOutOrderMessage>
</Message>
</cXML>"
I dealt with CORS issues, then a 400 error, then a 401 error, then a 404 error, and now, again, a 400 error. This means that the CORS policy is correct, the basic structure of the payload is correct, the authentication is correct and the endpoint is correct. I am trying to POST to this endpoint: https://api.businesscentral.dynamics.com/v2.0/<user-domain-name>/api/Contoso/Punchout/v2.0/companies(<company-id>)/PunchoutReceiver
. When I POST using postman I also get a 400 error. I have ensured that the table fields and JSON fields match. Here is the BC table and the POSt request in my flask backend, respectively:
table 50102 PunchoutReceiver
{
DataClassification = ToBeClassified;
fields
{
field(1; payloadid; Integer)
{
DataClassification = ToBeClassified;
AutoIncrement = true;
InitValue = 1;
}
field(2; Payload; Text[2048])
{
DataClassification = ToBeClassified;
}
}
keys
{
key(PK; payloadid)
{
Clustered = true;
}
}
}
external_payload = {
"Payload": "this is the data"
}
external_url = "https://api.businesscentral.dynamics.com/v2.0/******************/api/Contoso/Punchout/v2.0/companies(*****************)/PunchoutReceiver"
access_token = get_BC_token()
response = requests.post(
external_url,
json=external_payload,
headers={
"Authorization": f"Bearer {access_token}",
'Content-Type': 'application/json'
},
timeout=30
)
I have also tried including the payloadid
in the post request, but to no avail. If anyone could point me in the right direction I would very much appreciate that. Thank you in advance.
The issue here was in fact the endpoint. Instead of
https://api.businesscentral.dynamics.com/v2.0/<user-domain-name>/api/Contoso/Punchout/v2.0/companies(<company-id>)/<EntityName>
it is
https://api.businesscentral.dynamics.com/v2.0/<tenant id>/<environment name>/api/<Api publisher>/<Api group>/v2.0/companies(<company ID>)/<EntitySetName>
If after this you receive a 403 forbidden error, simply generate a permission set within vs code that gives your add-on application full control over its tables/pages/data etc and go into the BC UI and search entra -> microsoft entra application -> select the application you are working on -> under permission sets, add the one you just created in vs code.