Skip to content

REST API Release

This function exposes the equivalent of action processing, which is not coupled with the UI, to the outside world as a REST API. It is possible to make REST calls to the REST API application from the outside. Upon receiving a REST call, the REST API application can perform processing and reply, access the execution environment DB, or call an external REST API and reply with the results.

Tips

Creation

The procedure for creating a REST API definition is as follows

  1. Select “New” from the "Create" button in the same panel.
  2. Enter information in the "Rest API ID" and "Rest API Label" fields in the dialog and click the "Create" button.
  3. Enter the REST API configuration items and click the "Save" button. The REST API configuration items are as follows
ItemInputDescription
MethodRequiredSpecify the HTTP method. Select one of the following five types:
  • GET: Data acquisition
  • POST: Data creation
  • PUT: Data update
  • DELETE: Data deletion
  • PATCH: Partial data replacement
  • OPTIONS: Get allowed communication options.
ResourceRequiredEnter the path segment. Path parameters should be enclosed in parentheses like {xx}.
Debug Endpoint URLURL to invoke the debug-deployed REST API. https ://{domain}/dev/{Rest API ID}/{resource} URL can also be opened or copied to the clipboard
Release Endpoint URLURL to call the release deployed REST API. https ://{domain}/prod/{Rest API ID}/{resource} URL can also be opened or copied to the clipboard.
Content typeSets the type initially registered in the response header. Content types can be set, but can be overridden by actions.
Requires authenticationRequiredSets whether or not authentication is required.
  • Required
  • Not Required(Default)
  1. Click the "Action Editor" button to open the Action Editor.
  2. Write the action on the Action Board, create a user function, etc., and click the "Save" button.

Tips

Deploy

Deploying a REST API definition makes the REST API public.
Click the [Deploy] button in the upper right corner of the REST API definition to deploy.

Tips

For example, deploy the following definition

  • Application definition ID "restapi_sample"
  • REST API defined method "GET"
  • REST API defined resource "employee/{id}"

The number of resources used by this REST API will be three. (Methods are not counted). The total number of resources in the deployed execution environment is 4, including the root.

/restapi_sample
/employee
/{id}
GET

After this, deploy the following definitions.

  • Application definition ID "restapi_sample"
  • REST API defined method "POST"
  • REST API defined resource "calculator"

The REST API resources are as follows. The total number of resources in the deployed execution environment will be 5, including the root.

/restapi_sample
/calculator
POST
/employee
/{id}
GET

Tips

Action editor

There are some differences in writing REST API action scripts from desktop and mobile actions. This section describes what can be done and what to be aware of.

Object

Describes objects that can be used within REST API action scripts.

ObjectDescription
$constRefer to $const
$fnBuilt-in functions can be called. See the table below for available functions.
$reqRefer to $req
$resRefer to $res

Built-in Functions

Describes the built-in functions that can be used within REST API action scripts.

Built-in FunctionsDescription
$fn.getFile(path)Refer to $fn.getFile(path)
$fn.getFileNames(path)Refer to $fn.getFileNames(path)
$fn.putFile(path, parameters)Refer to $fn.putFile(path, parameters)
$fn.deleteFile(path)Refer to $fn.deleteFile(path)
$fn.getUsers(groupName?,option)Refer to $fn.getUsers(groupName?,option)
$fn.createUser(param)Refer to $fn.createUser(param)
$fn.updateUser(param)Refer to $fn.updateUser(param)
$fn.deleteUser(email)Refer to $fn.deleteUser(email)
$fn.resetPassword(param)Refer to $fn.resetPassword(param)
$fn.getGroups(option)Refer to $fn.getGroups(option)
$fn.createGroup(param)Refer to $fn.createGroup(param)
$fn.addUsers(param)Refer to $fn.addUsers(param)
$fn.removeUsers(param)Refer to $fn.removeUsers(param)
$fn.svf.oauth2.token()Refer to $fn.svf.oauth2.token()
$fn.svf.oauth2.revoke()Refer to $fn.svf.oauth2.revoke()
$fn.svf.artifacts.print()Refer to $fn.svf.artifacts.print()
$fn.svf.artifacts.info()Refer to $fn.svf.artifacts.info()
$fn.svf.artifacts.download()Refer to $fn.svf.artifacts.download()
$fn.svf.actions.status()Refer to $fn.svf.actions.status()
$fn.sendMail(param)Refer to $fn.sendMail(param)
$fn.csvToObject(csv)Refer to $fn.csvToObject(csv)
$fn.getPresignedUrl(path,options)Refer to $fn.getPresignedUrl(path,options)
$fn.listUsersByEmail(email,option)Refer to $fn.listUsersByEmail(email,option)
$fn.listUsersByName(name,option)Refer to $fn.listUsersByName(name,option)

Edit

The ID and label of the REST API definition can be changed. From the REST API list, select [Menu] - [Edit] for the REST API to be edited. The REST API item can also be edited. After editing, click the "Save" button.

Delete

To delete a REST API definition, select "Menu" - "Delete" for the REST API.

Copy

REST API definitions can be copied and inserted into the specified application. Select [Menu] - [Copy] of the UI to be copied from the REST API list.

The REST API can be filtered by Rest API label from the search field at the top of the panel.

Export

REST API definitions can be downloaded locally as a file. This can be done by selecting [Menu] - [Export] in the REST API.

Import

REST API definitions exported locally can be uploaded to the service. Select "Import" from the [Create] button in the upper right corner of the REST API list. Select a REST API definition file from the [Import] dialog and perform the upload. Only REST API definitions of application type "REST API" can be imported.

Commit

The user can commit an app definition to repository with the application definition against commit.

Sample REST API already deployed in a free environment

Sample REST API Information

ResourceDebug Endpoint URLRelease Endpoint URLMethodAuthenticationContent-Type[Request]Content-Type[Response]
/employee/{id}https: //api.feda9x.webperformer.jp/dev/restapi_sample/employee/{id}https: //api.feda9x.webperformer.jp/prod/restapi_sample/employee/{id}GETRequired-application/json
/calculatorhttps: //api.feda9x.webperformer.jp/dev/restapi_sample/calculatorhttps: //api.feda9x.webperformer.jp/prod/restapi_sample/calculatorPOSTRequiredapplication/jsontext/plain

API key

Deploy environmentAPI key
DebuguarsnOdmlF3Wcth1C8KeaPg4njkheaq7VtAYh0De
Release0mUykFa2j82t08kA8Xdhe5W4a7THnv8Maq3MtN4v

Tips

Resource: /employee/{id} specification

By specifying the employee id as a path parameter, the information of 5 dummy employees in JSON format is returned in JSON.

[
{
"id": "E001",
"name": "Tom Williams",
"age": 28
},
{
"id": "E002",
"name": "David Campbell",
"age": 39
},
{
"id": "E003",
"name": "Nick Raj",
"age": 21
},
{
"id": "E004",
"name": "Kevin Dean",
"age": 45
},
{
"id": "E005",
"name": "John Smith",
"age": 26
}
]

If the REST API call succeeds, HTTP status 200 is returned. The Content-Type of the response is application/json. The response body returns only the employee information corresponding to the id (E001-E005).

(Example of GET /employee/E001)

{
"id": "E001",
"name": "Tom Williams",
"age": 28
}

If a non-existent ID is specified, HTTP status 404 is returned. The Content-Type of the response is application/json. The response body is as follows {“message”: “Employee ID {id} not found.”}

Action Definition

/* Modules */
const util = require("node:util");
/* Consts */
const EMPLOYEES = [
{
id: "E001",
name: "Tom Williams",
age: 28,
},
{
id: "E002",
name: "David Campbell",
age: 39,
},
{
id: "E003",
name: "Nick Raj",
age: 21,
},
{
id: "E004",
name: "Kevin Dean",
age: 45,
},
{
id: "E005",
name: "John Smith",
age: 26,
},
];
/* Class */
class EmployeeService {
constructor() {}
find({ employeeId }) {
return EMPLOYEES.find((e) => e.id === employeeId);
}
}
class Response {
static ok(employee) {
return {
statusCode: 200,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(employee),
};
}
static notFound({ employeeId }) {
return {
statusCode: 404,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message: util.format($const.MESSAGE_EMPLOYEE_NOT_FOUND, employeeId),
}),
};
}
static internalServerError() {
return {
statusCode: 500,
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
message: $const.MESSAGE_EMPLOYEE_INTERNAL_SERVER_ERROR,
}),
};
}
}
class Api {
constructor() {
this.employeeService = new EmployeeService();
}
execute({ pathParameters }) {
try {
const employeeId = pathParameters?.id;
const employee = this.employeeService.find({ employeeId });
if (!employee) {
return Response.notFound({ employeeId });
}
return Response.ok(employee);
} catch (e) {
console.error(e);
return Response.internalServerError();
}
}
}
/* Instances */
const api = new Api();
/* Main */
const response = api.execute({
pathParameters: $req.pathParameters,
});
$res.statusCode = response.statusCode;
$res.headers = response.headers;
$res.body = response.body;

Constant Definition

NameData TypeValue
MESSAGE_EMPLOYEE_INTERNAL_SERVER_ERRORStringSystem error.
MESSAGE_EMPLOYEE_NOT_FOUNDStringEmployee ID %s not found.

Resource: /calculator specification

Upon receiving the arguments arg1 and arg2, and an operation (addition or subtraction), it returns the value of the result of the calculation.

  • arg1: A number between -999999999 and 99999999
  • arg2: A number between -99999999999 and 9999999999
  • operation: plus|minu

The Content-Type of the request is application/json. The request body is as follows

Eg.)
{
"arg1": 1234.56,
"arg2": -123.45,
"operation": "plus"
}

On success, HTTP status 200 is returned. The Content-Type of the response is text/plain. The response body returns only the calculation result as follows. Eg.)1111.11

The number of significant digits of a number (type number) is 16 (double precision of IEEE 754 in JS specification. including decimals) Convert to BigNumber for calculation.

If arg1, arg2, or operation is invalid, the HTTP status of the response is 400. The Content-Type of the response is text/plain. The response body is uniformly returned as follows. Input values are incorrect.

Action Definition

/* Consts */
const ARG_MIN = -99999999;
const ARG_MAX = 99999999;
/* Class */
class Calculator {
constructor(type) {
this.type = type;
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
throw new Error("Not implemented.");
}
}
class PlusCalculator extends Calculator {
constructor() {
super("plus");
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
return BigNumber(arg1).plus(BigNumber(arg2));
}
}
class MinusCalculator extends Calculator {
constructor() {
super("minus");
}
/**
* @param {number} arg1
* @param {number} arg2
* @returns {BigNumber}
*/
calculate(arg1, arg2) {
return BigNumber(arg1).minus(BigNumber(arg2));
}
}
class CalculatorManager {
/**
* @param {Calculator[]} calculators
*/
constructor(calculators) {
this.calculators = calculators;
}
/**
* @param {string} type
* @returns {Calculator}
*/
getCalculator(type) {
return this.calculators.find((c) => c.type === type);
}
/**
* @returns {string}
*/
getTypes() {
return this.calculators.map((c) => c.type);
}
}
class Response {
/**
* @param {BigNumber} result
*/
static ok(result) {
return {
statusCode: 200,
headers: {
"Content-Type": "text/plain",
},
body: result?.toFixed(),
};
}
static badRequest() {
return {
statusCode: 400,
headers: {
"Content-Type": "text/plain",
},
body: $const.MESSAGE_CALC_BAD_REQUEST,
};
}
static internalServerError() {
return {
statusCode: 500,
headers: {
"Content-Type": "text/plain",
},
body: $const.MESSAGE_CALC_INTERNAL_SERVER_ERROR,
};
}
}
class Api {
constructor() {
this.calcManager = new CalculatorManager([
new PlusCalculator(),
new MinusCalculator(),
]);
}
toParams(body) {
try {
return JSON.parse(body);
} catch (e) {
console.error("Invalid request body: ", e);
return null;
}
}
isValid({ type, arg1, arg2 }) {
const allowedTypes = this.calcManager.getTypes();
// type.
if (!allowedTypes.includes(type)) {
return false;
}
// arg1.
if (typeof arg1 !== "number") {
return false;
}
if (arg1 < ARG_MIN || ARG_MAX < arg1) {
return false;
}
// arg2.
if (typeof arg2 !== "number") {
return false;
}
if (arg2 < ARG_MIN || ARG_MAX < arg2) {
return false;
}
return true;
}
/**
* @param {{
* body: string;
* }}
*/
execute({ body }) {
try {
const params = this.toParams(body);
if (!params) {
return Response.badRequest();
}
const type = params.operation;
const arg1 = params.arg1;
const arg2 = params.arg2;
if (!this.isValid({ type, arg1, arg2 })) {
return Response.badRequest();
}
const calculator = this.calcManager.getCalculator(type);
const result = calculator.calculate(arg1, arg2);
return Response.ok(result);
} catch (e) {
console.error(e);
return Response.internalServerError();
}
}
}
/* Instances */
const api = new Api();
/* Main */
const response = api.execute({
body: $req.body,
});
$res.statusCode = response.statusCode;
$res.headers = response.headers;
$res.body = response.body;

Constant Definition

NameData TypeValue
MESSAGE_CALC_BAD_REQUESTStringInput values are incorrect.
MESSAGE_CALC_INTERNAL_SERVER_ERRORStringSystem error.

When invoking REST from a browser

When deploying a RESTAPI, a simple request, a preflight request will be generated if it is not simple request link.

For this reason, an additional OPTIONS method must also be provided.

The OPTIONS method requests the specified URL or allowed communication options for the server.

Action Definition

const response = {
statusCode: 200,
headers: {
'Access-Control-Allow-Origin' : '*',
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
'Access-Control-Allow-Headers': 'origin,x-api-key' ,
}
};
$res= response;
return $res;

Tips

Header NameDescription
Access-Control-Allow-OriginIndicates whether the response can be shared by code making requests from the specified origin
Access-Control-Allow-MethodsSpecifies one or more methods that can be used when accessing the resource
Access-Control-Allow-HeadersUsed to indicate HTTP headers that can be used during the actual request