Most of our APIs will deal with database content of course so lets take a look at how we can build these types of APIs.

As a sample database we chose to use DAWs order entry database just because we all have and know it already.

To start with an easy one we will create an API for the inventory table

We will add another HTTP Handler based on the cszWebAPIController class named oInventoryAPI

Object oInventoryAPI is a cszWebAPIController
  Set psResourceName to "Inventory Item"
  Set Key_Field to Field inventory.Item_ID
  Set psPath to "api/v1/inventory"
  Set psVerbs to "*"
   ... 
End_Object

we also need to add our DataDictionaries

Object oVendor_DD is a cVendorDataDictionary 
End_Object

Object oInventory_DD is a cInventoryDataDictionary
    Set DDO_Server to oVendor_DD
End_Object

Set Main_DD to oInventory_DD

then we define the data model as follows

Procedure OnDefineModels
  Send BeginModel "inventory"
  Send AddTableColumn File_Field Inventory.Item_ID
  Send AddTableColumn File_Field Inventory.Description
  Send AddTableColumn File_Field Inventory.Vendor_ID 
  Send AddTableColumn File_Field Inventory.Vendor_Part_ID
  Send AddTableColumn File_Field Inventory.Unit_Price
  Send AddTableColumn File_Field Inventory.On_Hand
  Send EndModel
End_Procedure

next we want to define a route to get a list of inventory items

Send RegisterPath "GET" "" (RefProc(webAPI_Get))

this is all that is needed to create a REST API to return a list of inventory items. And again as before the OpenAPI documentation is created automatically as well

now lets see what it takes to add another route to return a single inventory item by id

we need to define a new route as follows

Send RegisterPath "GET" "/{itemid}" (RefProc(webAPI_GetScalar))

this new route has a variable parameter called itemid. this item id is passed as a variable to the webAPI_GetScalar method which handles finding the record and returning the json object based on the schema provided

Now what about deleting an inventory item

lets add the following route

Send RegisterPath "DELETE" "/{itemid}" (RefProc(webAPI_Delete))

this route again uses a variable parameter for the item id and passes it to the webAPI_Delete method which handles deleting the inventory item.

Now what about creating new inventory records. For this to work we need a POST route as follows

Send RegisterPath "POST" "" (RefProc(webAPI_Post))

this route will use the schema provided as an input from the post method and create an inventory record by calling the webAPI_Post method.

Then of course we would like to update an inventory record as well. We can do this by declaring a PATCH route as follows

Send RegisterPath "PATCH" "/{itemid}" (RefProc(webAPI_Patch))

And this is all that is needed to update inventory records.

And again the documentation for the API is automatically created usign the OpenAPI specifications

the schema we used so far in this example is a pretty simple flat schema. What if we wanted a more complex schema adding a child object for the vendor definition and maybe even a child object for the vendors address even though it only exists in a flat structure in the table.

Also we want some of the fields to only appear in the scalar functions and not in the return of the list methods

lets look at the following schema declaration

Procedure OnDefineModelColumnsVendorAddress 
  Send AddTableColumn File_Field Vendor.Address 
  Send AddTableColumn File_Field Vendor.City 
End_Procedure 

Procedure OnDefineModelColumnsVendor 
  Send AddTableColumn File_Field Vendor.ID 
  Send AddTableColumn File_Field Vendor.Name 
  Send AddModelParent "Address" (RefProc(OnDefineModelColumnsVendorAddress)) 
End_Procedure

Procedure OnDefineModels 
  Send BeginModel "inventory" 
  Send AddTableColumn File_Field Inventory.Item_ID 
  Send AddTableColumn File_Field Inventory.Description  
  Send AddModelParent "Vendor" (RefProc(OnDefineModelColumnsVendor)) True 
  Send AddTableColumn File_Field Inventory.Vendor_ID 
  Send AddTableColumn File_Field Vendor.Name 
  Send AddTableColumn File_Field Inventory.Vendor_Part_ID 
  Send AddTableColumn File_Field Inventory.Unit_Price 
  Send AddTableColumn File_Field Inventory.On_Hand 
  Send EndModel 
End_Procedure

we start by defining a schema called inventory with the fields item_id and description

then we add a parent schema called vendor with the vendor fields but we define this parent as scalar only so it will not appear in the return data when getting a list of inventory items.

and here is a quick screen grab of the documentation for the API

This is just an example there are a number of features to describe the schemas and you can also define multiple schemas to be used for different routes.

In the next part to this series we will look at the order API which will show additional features of the library

Michael Salzlechner is the CEO of StarZen Technologies, Inc.

He was part of the Windows Team at Data Access Worldwide that created the DataFlex for Windows Product before joining StarZen Technologies. StarZen Technologies provides consulting services as well as custom Application development and third party products