API Endpoints Design
Introduction
In this tutorial, we'll guide you through the creation of a simple mockup reference API using the built-in tools in the qibb flow editor. This API is designed to allow you to:
Retrieve a list of all customers
Access information about an individual customer through their unique ID
Create a new customer entry
Update existing customer data
Remove an existing customer record from the system
Tutorial Flow Source Code
To follow this tutorial, you can import the attached flow below. Simply download the attached JSON file below and import it into your flow app.
You can do this by either pressing Ctrl + I
simultaneously or by navigating to the main settings and selecting the Import
option.
Tutorial
With qibb, you can effortlessly create polished Open API reference files and share them with your partners or customers. Simply start by adding an HTTP In node, connect it to a few change/function nodes, followed by an HTTP Response node, and then fill out the relevant documentation to add the corresponding description of the endpoints and the possible parameters/body.
This example API contains the following calls:
GET /customers
- to retrieve information for all the customers saved in the CUSTOMERS global variable.GET /customers/:id
- to fetch information about a specific customer based on its unique ID.POST /customers
- to create a new customer’s object.PATCH /customers/:id
- to update an existing customer’s data based on its ID.DELETE /customers/:id
- to delete an existing customer from the global context.
API Documentation
API documentation plays a crucial role in giving your API endpoints a professional and well-documented appearance. You can generate the documentation directly within the corresponding HTTP In node by editing the "Docs" section. Within this section, you'll find several tabs:
Info: Offering general information about the endpoint.
Parameters: Where you can specify the query, body, or path parameters supported by your call.
Responses: For configuring the supported HTTP status codes and the format body of the output from your endpoints.
Info Tab
Here you can specify:
Summary: A concise description, displayed alongside your API call, even when the endpoint is collapsed.
Description: Offers a more detailed explanation of your call, accessible only when you expand the endpoint.
Tags: Defines the tag for this API call, helping organize calls into categories.
Consumes: Comma-separated list of input Mime Types supported by your endpoint.
Produces: Specifies the format of your responses, e.g.
application/json
.Security: Allows you to set the required authentication mechanism for this endpoint.
Deprecated: a checkbox that marks this particular call as deprecated.
Parameters
You can add here the supported parameters, by pressing the +parameter button and define:
Name: Name of the parameter
Parameter’s type: possible types:
query
header
formData
body
Description: Description of the parameter
Type: Choose between string, number, integer, boolean, and array
Format: In OpenAPI, the
format
field typically provides additional information about the data type specified in thetype
field. For example:formats for
"type": "string"
can be:date
date-time
email
uuid
etc.
formats for
"type": "number"
can be:float
double
int32
int64
etc.
Required: a checkbox that defines whether the parameter is required or not. The default value is not required.
Path Parameters
By default, the qibb flow editor automatically includes every path parameter defined in the URL within this tab, and marks them as mandatory.
For instance, in the case of a GET request to /customers/:id
, the id
parameter would be automatically included in this section. However, you still need to define the Description, Type, and Format.
Responses
The third tab, called Responses allows you to specify the potential HTTP status codes and the response format for your API call.
Here, you can describe the HTTP status code and define the properties returned from your call.
A comprehensive list of all HTTP Status codes can be found at https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
API Reference
You can access the API reference documentation that you have created from the API Reference tab as shown in the screenshot below:
From here you can also access the automatically generated URL of your OpenAPI reference in a JSON format, which you can use to load in a swagger editor or provide to a third-party partner.
Customers' Data Storage in the Global Context
Customers Storage
When creating API endpoints, it's common to store the associated data securely for easy access later on. Typically, this involves using a database. However, in this tutorial, we'll keep things simple by using the global context instead.
Initializing the Data
I'm configuring the CUSTOMERS and USER_CREDENTIALS global variables within the change node labeled "Initialize Customers Global Variable". Remember to activate the inject node before proceeding any further.
The API calls write and read the customers' data directly from the global variable called CUSTOMERS
, which is saved in the global context of your flow application. When you initialize the context, it will create that variable with an empty array.
API Authentication
API Authentication
It's important to note that the POST
, PATCH
, and DELETE
calls require basic authentication, ensuring secure interactions, while the GET
calls are accessible without any sort of authentication.
For authentication, we've chosen basic authentication, requiring both the username and password. The "Initialize Customers Global Variable" action sets the USER_CREDENTIALS global variable to a JSON object containing the username in plain text and a salted hash of the actual password.
In the flow, I've decided to employ bcryptjs, leveraging the blowfish cipher to produce a salted hash of the original password, as demonstrated by the following line of code:
const hashedPassword = await bcrypt.hash(decodedPassword, saltRounds);
The bcrypt
hash algorithm is a cryptographic hashing function specifically designed for securely hashing passwords. It is based on the Blowfish cipher and incorporates a unique salt for each password hash. Salting prevents attackers from using precomputed tables (like rainbow tables) to crack passwords, even if multiple users have the same password.
I am using the bcrypt
compare function to compare both the plain text password, provided in the API call, and the salted password, stored in the USER_CREDENTIALS global variable:
const passwordMatch = await bcrypt.compare(decodedPassword, saltedPass);
The constant variable passwordMatch
would return True when both the salted hash saved in the USER_CREDENTIALS matches the plain text password provided with the API call and False otherwise.
You can read more about the hashing and salting implementation of bcrypt
here: https://auth0.com/blog/hashing-in-action-understanding-bcrypt/.
API Endpoints
API Reference Documentation
Please note that all HTTP In nodes are having thoroughly documented Info, Parameters, and Responses that is visible from the API Reference Tab.
Testing the API
In the second logical group, I've developed several flows to accomplish the following tasks:
Retrieve information for all customers.
Retrieve information for a specific customer based on its unique ID.
Execute a flow that involves creating a customer object, modifying it, and then deleting the customer.
Throughout the testing process, I exclusively utilized the qibb OpenAPI node.
To access this node, you must install it from the qibb Node Catalog.
Instructions for installation can be found 👉 https://docs.qibb.com/platform/latest/using-the-qibb-node-catalog-plugin. For further details about the OpenAPI client node, refer to https://docs.qibb.com/platform/latest/openapi-client. To integrate your API reference, follow the steps outlined in https://docs.qibb.com/platform/latest/how-to-expose-your-flow-as-an-openapi.
Once the OpenAPI node is installed, proceed by adding the connection to your OpenAPI reference JSON file, and ensure to configure the Hostname accordingly as shown on the screenshot below:
Once you do this, you will have all available API endpoints available there under Operations.
Basic Authentication
The GET /customers
and GET /customers/:id
endpoints do not require any credentials for access. However, the POST, PATCH, and DELETE calls do require authentication. To execute these operations, you must provide credentials either through the Advanced section of the nodes or by passing them directly before the corresponding OpenAPI node:
msg.parameters.credentials.BasicAuth = {
"username": "admin",
"password": "J8Px(n23E%Sa<.l6)J2Ms6"
}