POST operations allow you to create a new record in an external system and with RESTwithUS you want to create it from Business Central data.
Let's have a simple example of a POST API Endpoint on URL https://test.api.com/v3/Customer, which expects data of a new Customer:
And if the Customer was created without an error, it returns his data including the Customer id
in an external system:
For the sake of simplicity let's say that you are storing Business Central Customer No. in the no
node. And there are more fields like customer name
, address
, city
etc.
To call this API endpoint you need to create a new Operation.
If you are creating your own AL extension that should implement connection with some API provider, the recommended way to start is to add your operation to Operation ID RWU
enum:
enumextension 50002 "Test Operation ID RWU" extends "Operation ID RWU"
{
value(50000; "TestProvider_CreateCustomer")
{
Caption = 'Create Customer (Test Provider)';
}
}
Tip: You can skip this step for testing purposes and call your operations with provider description instead of the enum ID. However, this is not recommended for production applications.
Now select your API provider from the list and open Operations:
Create a new POST operation pointing to your API endpoint:
POST
./Customer
in the Endpoint field – i.e. the part of the URL without Provider URL (see Setting up API Provider).Open
, meaning you can update the operation.With POST operations you are usually sending a JSON request and then receiving a JSON response.
To create a request body and fill the JSON nodes from Business Central tables and fields select your operation from the list and open Request Body:
Initially the request body is empty, so use function Payload / Import Payload, paste an example of JSON request and press OK:
RESTwithUS will generate request structure for you and you just need to map it to Business Central tables and fields:
The root
node contains Customer record, so let's connect it with Customer table in Business Central. Set Type to Table
and Object ID to the ID of Customer Table: 18
.
Set up fields, that are both in the Business Central record and a record in an external system.
Let's say that the node phones
is optional – if a Customer does not have any phone number, there is no value. With default settings, this will throw an error, but you can mark the node as optional by setting MinOccurs to Zero
.
Tip: You can set request node values with code using
ADD_VALUE
orADD_VARIABLE
functions, too (see API Script Functions Reference or Using RESTwithUS Variables).
To create a response body and map the JSON data to Business Central tables and fields select your operation from the list and open Response Body:
Initially the response body is empty, so use function Payload / Import Payload, paste an example of JSON response and press OK:
RESTwithUS will generate response structure for you and you just need to map it to Business Central tables and fields:
The recommended way on how to proceed is to use Entities and define the JSON schema in one place (see guideline Working with Entities). But let's now just define a simple POST response and map it to Business Central fields.
The root
node contains Customer record, so let's connect it with Customer table in Business Central. Set Type to Table
and Object ID to the ID of Customer Table: 18
.
If you want to store connections between records in Business Central and an external system, it must be done at Entity level. Firstly, go to provider Entities and create a new entity called Customer
(if you haven't done that already for another operation):
Now map the JSON response to the entity:
a. Select the Customer
entity in the Entity ID field on the root
node.
b. Set id
node to Mapping Type External ID
and select the Entity ID, too. (External ID
marks node which contains the record ID in an external system.)
c. Set name
node to Mapping Type Description
and select the Entity ID, too. (This is just for easier visual searching in connections.)
Set up fields, which are both in Business Central record and a record in an external system.
Mark the node phones
as optional like in the request body.
Tip: You do not need to match all fields to Business Central counterparts. In this example, you basically need only the
no
node to get the right connection. Since you do not saveaddress
orcountryCode
values back to Business Central you may as well leave them unmatched.
The last thing that needs to be done is to save the unique id
of the newly created record to Business Central for further use. This can be done with Connections.
All connection mappings are done on the nodes with Type Table
. Select the root
node and open Home / Details:
First you need to select the Connection Operation. You are creating a new record, so let's set Create
option here.
Now you need to fill in Table View field which defines, how to search for the matching record in Business Central. You can write it manually, or you can use helper function Generate Table View:
In this scenario you are matching the records by Customer No.
so select the No.
key and press OK. RESTwithUS will generate a Table View based on the selected table key:
As you can see, this is a simple table view expression meaning:
{{Field1}}
(field number 1 from the current table) – and previously you defined that Field 1
of a Customer table is in the JSON node no
.Let's run the operation for the first time and try to create a new customer from Business Central data. You will need only a few lines of code for that using the API Script RWU codeunit. Just don't forget to Release both the Entity and the Operation before running the code.
var
Customer: Record "Customer";
APIScriptRWU: Codeunit "API Script RWU";
ProviderID: Enum "Provider ID RWU";
OperationID: Enum "Operation ID RWU";
Customer.GET('01121212'); //Get customer record
APIScriptRWU.INIT(OperationID::TestProvider_CreateCustomer); //Set the identifier for saving Batch Entries
APIScriptRWU.ENDPOINT(ProviderID::TestProvider,OperationID::TestProvider_CreateCustomer); //Select the provider and his operation
APIScriptRWU.ADD_VALUE('/',Customer); //Add the selected Customer record to the root node
APIScriptRWU.ADD_VALUE('/phones','123456789'); //Add first phone number to phones node
APIScriptRWU.ADD_VALUE('/phones','999999999'); //Add second phone number to phones node
APIScriptRWU.EXECUTE(); //Start the operation
In this example you are adding phone numbers manually with ADD_VALUE
function. But with a different setup you can fill the array from a table, too – see the details of Simple Array JSON Data Type.
Tip: For more API Script functions see guideline API Script Functions Reference.
For testing purposes you can call the provider and operation by their description. However, this is not recommended for production applications:
APIScriptRWU.INIT('TEST_PROVIDER_CREATE_CUSTOMER');
APIScriptRWU.ENDPOINT('Test Provider','Create Customer');
Now you can check the result. First go to Operations, select the operation from the list and open Related / Batch Entries from the menu:
Here you can see all the details about the operation run like:
root
node values.root
and phones
nodes in request.Tip: You set the Batch Code value with the
INIT
function and you can use whatever string you want. Just remember that each new call of an operation deletes all previous Batch Entries with the same Batch Code. For more details see guideline Batch Entries.
Connections are maintained on Entity level. To check them select your API Provider and choose Entities from the menu:
You can click the number in marked columns to see the connection details:
As you can see, the customer 01121212
has a healthy connection which means that it was successfully created in an external system and matched with a record in Business Central. Plus its id
in an external system was saved to External Id column for further use in any other operation.
Tip: For more details about connections see guideline Connections.
In a real project we recommend merging POST and PUT/PATCH operations into one function, that will:
Example of such a function:
procedure RefreshCustomer(Customer: Record Customer)
var
APIScriptRWU: Codeunit "API Script RWU";
EntityID: Enum "Entity ID RWU";
ProviderID: Enum "Provider ID RWU";
OperationID: Enum "Operation ID RWU";
MappingId: Text;
begin
//Try to get external record id from connections
MappingId := APIScriptRWU.MAPPING(ProviderID::TestProvider,EntityID::TestProvider_Customer, Customer);
//For BC 18 and newer use record SystemId instead
//MappingId := APIScriptRWU.MAPPING(ProviderID::TestProvider,EntityID::TestProvider_Customer, Customer.SystemId);
//Connection not found, create the record
if MappingId = '' then begin
APIScriptRWU.INIT(OperationID::TestProvider_CreateCustomer);
APIScriptRWU.ENDPOINT(ProviderID::TestProvider,OperationID::TestProvider_CreateCustomer);
APIScriptRWU.ADD_VALUE('/',Customer);
APIScriptRWU.EXECUTE();
end
//Connection found, update the record data
else begin
APIScriptRWU.INIT(OperationID::TestProvider_UpdateCustomer);
APIScriptRWU.ENDPOINT(ProviderID::TestProvider,OperationID::TestProvider_UpdateCustomer);
APIScriptRWU.ADD_VARIABLE('','CustomerId',MappingId);
APIScriptRWU.ADD_VALUE('/',Customer);
APIScriptRWU.EXECUTE();
end;
end