The API object defines an Application Programming Interface of a set of programs like Data Providers and Procedures.
It is meant for modeling an API mediation layer that clearly separates the interface from the implementation and so facilitates incremental development and the management of the evolution of an API.
An API object groups several services that are semantically and functionally related. For each service, it declares a mapping between the internal name (exposed as a service) and the internal implementation in the KB. It features flexibility in terms of service declaration, which allows configuring the access path and configuration details (HTTP method). It also allows indicating the name and type of the parameters, offering great flexibility in parameter transformation.
The API interface is declared in the 'Service Source' part of the object.
For each service of the interface, you can declare:
- Path and Name
- Which GeneXus object contains the implementation and with what parameters it is called
- Annotations for protocol-specific options
The API object allows you to expose an API for the following protocols:
At the object level, you have properties to enable each of them.
(*) The gRPC protocol is not supported in the .NET Generator. It is in a beta state in .NET Core and Java.
The events can be defined in the 'Events' part of the object.
This is the place where you can program:
- Data transformations to the service parameters, before and after calling the object that implements the service, which helps to maintain a stable API
- Manage traffic, analyze it, apply service policies. That is, for example, count service calls, log them, accept or deny access to your API.
For each API object, you can define a 'Before' and 'After' event, which will be executed before and after each service implementation.
In addition, for each service you can define '<service name>.Before|After' events. So, every time a service is invoked, the following will be executed:
- Event 'Before'
- Event '<service>.Before'
- The object corresponding to the implementation of the service, referenced in the 'Service Source'
- Event '<service>.After'
- Event 'After'
Database access is not allowed in Events; that kind of logic should be placed in the called Procedures or Data Providers.
Here you can define the variables to be used in the Source and Events.
There are some standard variables each API object has
- &Pgmname - It contains the name of the object
- &Pgmdesc - It contains the description of the object
- &RestMethod - It contains the HTTP Method with which the object was called. It is empty when the object is called using protocols other than REST
This sample showcases the API called 'Client' with services to list clients, get details of a specific client, and insert a client.
This is the 'Service Source' part of the API object:
- When accessed through the Rest Protocol, List and GetByKey are accessed via HTTP 'GET' Method, and Insert is accessed via 'POST' declared with the '[RestMethod(POST)]' annotation
- Service parameters have to be declared as in or out
- Parameter mapping and parameter value transformations can be done using the 'Events' part as shown below
- Overloading of services (Using the same service name for different Rest Methods as it is usual in REST Services) is possible in APIs that are only exposed as REST.
This is the 'Events' part:
&ClientCategoryCode = 'Any'
if &ClientId <= 0
if &Client.ClientId = 0
&Message.Type = MessageTypes.Error
&Message.Description = format("There was an error loading Client %1",&ClientId)
- 'List.Before' initializes a variable that is not part of the API but that is required by the called object
- The procedure associated with the Insert service (and the Insert.After event) in this sample will only be executed if &ClientId >= 0
You can download the source of this sample from here