1665019396
In this tutorial, we’ll learn how to build a REST API using MySQL as our database and Node.js as our language. We’ll also use the Express.js framework to make our task easier. Our example REST API will track the most popular programming languages.
To follow along with this article, you should have the following:
GET
, POST
, PUT
, and DELETE
The code in this tutorial is performed on a Mac with Node 14 LTS installed. You can also access the full code at the GitHub repository. Let’s get started!
GET
popular programming languagesPOST
a new programming languagePUT
to update an existing programming languageDELETE
a programming languageMySQL is one of the most popular databases in the world, if not the most popular. Per the 2020 Stack Overflow survey, MySQL was the most-loved database, with more than 55 percent of respondents using it. The community edition is freely available, supported by a large and active community.
MySQL is a feature-packed relational database first released in 1995. MySQL runs on all major operating systems like, Linux, Windows, and macOS. Because of its features and its cost-effectiveness, MySQL is used by big enterprises and new startups alike.
For our example REST API, we’ll use a free MySQL service instead of setting up a local MySQL server. To host our testing MySQL database, we’ll use db4free.net.
To get your free MySQL 8.0 database up and running, you can register on db4free.net. First, go to the db4free signup page, then fill out the required details by choosing your database name and username:
Click on Signup and you should receive a confirmation email. Confirm your account by clicking on the link in the email. Next, on the sidebar, click on phpMyAdmin. In the phpMyAdmin login, enter the username and password you chose and click Go:
Now, we have an empty database. Let’s add the programming_languages
table. First, click on the database name on the left; for me, it was restapitest123. Then, click SQL on the top menu, which is the second link after Structure, and put the following code for CREATE TABLE
in the text area:
CREATE TABLE `programming_languages`
(
`id` INT(11) NOT NULL auto_increment ,
`name` VARCHAR(255) NOT NULL ,
`released_year` INT NOT NULL ,
`githut_rank` INT NULL ,
`pypl_rank` INT NULL ,
`tiobe_rank` INT NULL ,
`created_at` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ,
`updated_at` DATETIME on UPDATE CURRENT_TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ,
PRIMARY KEY (`id`),
UNIQUE `idx_name_unique` (`name`(255))
)
engine = innodb charset=utf8mb4 COLLATE utf8mb4_general_ci;
Click the Go button, as below:
The code will come back with a green check box and a message along the lines of MySQL returned an empty result set (i.e. zero rows)
.
With that, we’ve created a table called programming_languages
with eight columns and a primary key called id
, which is an internet and auto-increment. The name
column is unique, and we also added the released_year
for the programming language. We have three columns to input the rank of the programming language, sourced from the following resources:
The created_at
and updated_at
columns store dates to keep a track of when the rows were created and updated.
Next, we’ll add 16 popular programming languages to our programming_languages
table. Click the same SQL link on the top of the page and copy and paste the code below:
INSERT INTO programming_languages(id,name,released_year,githut_rank,pypl_rank,tiobe_rank)
VALUES
(1,'JavaScript',1995,1,3,7),
(2,'Python',1991,2,1,3),
(3,'Java',1995,3,2,2),
(4,'TypeScript',2012,7,10,42),
(5,'C#',2000,9,4,5),
(6,'PHP',1995,8,6,8),
(7,'C++',1985,5,5,4),
(8,'C',1972,10,5,1),
(9,'Ruby',1995,6,15,15),
(10,'R',1993,33,7,9),
(11,'Objective-C',1984,18,8,18),
(12,'Swift',2015,16,9,13),
(13,'Kotlin',2011,15,12,40),
(14,'Go',2009,4,13,14),
(15,'Rust',2010,14,16,26),
(16,'Scala',2004,11,17,34);
You should receive a message that reads something like “16 rows inserted”.
The data collected from our three sources is collected and added to the table in bulk by the INSERT
statement, creating 16 rows, one for each programming language. We’ll return to this later when we fetch data for the GET
API endpoint.
If we click on the programming_languages table, visible on the left, we’ll see the rows that we just added:
Next, we’ll set up Express.js for our REST API with Node.js and MySQL.
To set up a Node.js app with an Express.js server, we’ll first create a directory for our project to reside in:
mkdir programming-languages-api && cd programming-languages-api
Then, we can create a package.json
file with npm init -y
as follows:
{
"name": "programming-languages-api",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC"
}
To install Express, we’ll run npm i
express
, adding Express as a dependency in the package.json
file.Next, we’ll create a slim server in the index.js
file. It will print an ok
message on the main path /
:
const express = require("express");
const app = express();
const port = 3000;
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.get("/", (req, res) => {
res.json({ message: "ok" });
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
There are a few important things to note in the code above. For one, we’ll using the built-in Express JSON parser middleware to parse JSON in the next steps. We’ll also utilize the express.urlencoded()
middleware to parse the URL encoded body.
If the PORT
is not provided as an environment variable, our app will run on port 3000
. We can run the server with node index.js
and hit http://localhost:3000
to see {message: "ok"}
as the output.
We’ll structure our project in the following manner to arrange our files logically in folders:
config.js
will contain configuration for information like the database credentials and the rows we want to show per page when we paginate results. helper.js
is the home for any helper functions, like calculating offset for pagination.
The routes/programmingLanguages.js
file will act as the glue between the URI and the corresponding function in the services/programmingLanguages.js
service. The services
folder will house all our services. One of them is db.js
, which we use to talk with the MySQL database.
Another service is programmingLanguages.js
, which will have methods like getMultiple
, create
, etc. to get and create the programming language resource. Basic mapping of the URI and the related service function will look like the code below:
GET /programming-languages → getMultiple()
POST /programming-languages → create()
PUT /programming-languages/:id → update()
DELETE /programming-languages/:id → remove()
Now, let’s code our GET
programming languages API with pagination.
GET
popular programming languagesTo create our GET
programming languages API, we’ll need to link our Node.js server with MySQL. To do so, we’ll use the mysql2
package from npm, which we can install with the npm i mysql2
command on the project root.
Next, we’ll create the config
file on the root of the project with the following contents:
const config = {
db: {
/* don't expose password or any sensitive info, done only for demo */
host: "db4free.net",
user: "restapitest123",
password: "restapitest123",
database: "restapitest123",
},
listPerPage: 10,
};
module.exports = config;
Consequently, we’ll create the helper.js
file with the code below:
function getOffset(currentPage = 1, listPerPage) {
return (currentPage - 1) * [listPerPage];
}
function emptyOrRows(rows) {
if (!rows) {
return [];
}
return rows;
}
module.exports = {
getOffset,
emptyOrRows
}
For the fun part, we’ll add the route and link it to the services. First, we’ll connect to the database and enable running queries on the database in the services/db.js
file:
const mysql = require('mysql2/promise');
const config = require('../config');
async function query(sql, params) {
const connection = await mysql.createConnection(config.db);
const [results, ] = await connection.execute(sql, params);
return results;
}
module.exports = {
query
}
Now, we’ll write up the services/programmingLanguage.js
file that acts as the bridge between the route and the database:
const db = require('./db');
const helper = require('../helper');
const config = require('../config');
async function getMultiple(page = 1){
const offset = helper.getOffset(page, config.listPerPage);
const rows = await db.query(
`SELECT id, name, released_year, githut_rank, pypl_rank, tiobe_rank
FROM programming_languages LIMIT ${offset},${config.listPerPage}`
);
const data = helper.emptyOrRows(rows);
const meta = {page};
return {
data,
meta
}
}
module.exports = {
getMultiple
}
After that, we’ll create the routes
file in routes/programmingLanguages.js
, which looks like the following:
const express = require('express');
const router = express.Router();
const programmingLanguages = require('../services/programmingLanguages');
/* GET programming languages. */
router.get('/', async function(req, res, next) {
try {
res.json(await programmingLanguages.getMultiple(req.query.page));
} catch (err) {
console.error(`Error while getting programming languages `, err.message);
next(err);
}
});
module.exports = router;
For the final piece of our GET
endpoint, we need to wire up the route in the index.js
file as follows:
const express = require("express");
const app = express();
const port = 3000;
const programmingLanguagesRouter = require("./routes/programmingLanguages");
app.use(express.json());
app.use(
express.urlencoded({
extended: true,
})
);
app.get("/", (req, res) => {
res.json({ message: "ok" });
});
app.use("/programming-languages", programmingLanguagesRouter);
/* Error handler middleware */
app.use((err, req, res, next) => {
const statusCode = err.statusCode || 500;
console.error(err.message, err.stack);
res.status(statusCode).json({ message: err.message });
return;
});
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`);
});
We made two important changes in our entrypoint index.js
file. For one, we added the code below:
const programmingLanguagesRouter = require('./routes/programmingLanguages');
Secondly, we link up the /programming-languages
route to the router we just created as follows:
app.use('/programming-languages', programmingLanguagesRouter);
We’ve also added an error handler middleware to handle any errors and provide a proper status code and message.
After adding the GET
endpoint, when we run our app again with node index.js
and hit the browser with http://localhost:3000/programming-languages
, we’ll see an output like the following:
Depending on the extensions you have installed on your browser, your output might look a little different.
Note that we’ve already implemented pagination for our GET
API, which is possible because of the getOffset
function in helper.js
and the way we run the SELECT
query in services/programmingLanguage.js
. Try http://localhost:3000/programming-languages?page=2
to see languages 11–16.
POST
a new programming languageOur POST
API will allow us to create a new programming language in our table.
To create a POST
programming language API in the /programming-languages
endpoint, we’ll add code to the service
and the routes
files. In the service method, we’ll get the name, the release year, and other ranks from the request body, then insert them into the programming_languages
table.
Append the following code to the services/programmingLanguages.js
file:
async function create(programmingLanguage){
const result = await db.query(
`INSERT INTO programming_languages
(name, released_year, githut_rank, pypl_rank, tiobe_rank)
VALUES
(${programmingLanguage.name}, ${programmingLanguage.released_year}, ${programmingLanguage.githut_rank}, ${programmingLanguage.pypl_rank}, ${programmingLanguage.tiobe_rank})`
);
let message = 'Error in creating programming language';
if (result.affectedRows) {
message = 'Programming language created successfully';
}
return {message};
}
Make sure you export the following function as well:
module.exports = {
getMultiple,
create
}
For the function above to be accessible, we need to add a route to link it up in the routes/programmingLanguages.js
file as follows:
/* POST programming language */
router.post('/', async function(req, res, next) {
try {
res.json(await programmingLanguages.create(req.body));
} catch (err) {
console.error(`Error while creating programming language`, err.message);
next(err);
}
});
PUT
to update an existing programming languageTo update an existing programming language, we’ll use the /programming-languages/:id
endpoint, where we’ll get the data to update the language. To update a programming language, we’ll run the UPDATE
query based on the data we got in the request.
PUT
is an idempotent action, meaning if the same call is made over and over again, it will produce the exact same results. To enable updating existing records, we’ll add the following code to the programming language service:
async function update(id, programmingLanguage){
const result = await db.query(
`UPDATE programming_languages
SET name="${programmingLanguage.name}", released_year=${programmingLanguage.released_year}, githut_rank=${programmingLanguage.githut_rank},
pypl_rank=${programmingLanguage.pypl_rank}, tiobe_rank=${programmingLanguage.tiobe_rank}
WHERE id=${id}`
);
let message = 'Error in updating programming language';
if (result.affectedRows) {
message = 'Programming language updated successfully';
}
return {message};
}
Make sure you export this function as well as we did before:
module.exports = {
getMultiple,
create,
update,
};
To wire up the code with the PUT
endpoint, we’ll add the code below to the programming languages route file, just above module.exports = router;
:
/* PUT programming language */
router.put('/:id', async function(req, res, next) {
try {
res.json(await programmingLanguages.update(req.params.id, req.body));
} catch (err) {
console.error(`Error while updating programming language`, err.message);
next(err);
}
});
Now, we have the ability to update any existing programming language. For instance, we can update a language’s name if we see a typo.
DELETE
a programming languageWe’ll use the /programming-languages/:id
path with the HTTP DELETE
method to add the functionality to delete a programming language. Go ahead and run the code below:
async function remove(id){
const result = await db.query(
`DELETE FROM programming_languages WHERE id=${id}`
);
let message = 'Error in deleting programming language';
if (result.affectedRows) {
message = 'Programming language deleted successfully';
}
return {message};
}
Don’t forget to export this function as well. Once again, to link up the service with the route, we’ll add the following code to the routes/programmingLanguages.js
file:
/* DELETE programming language */
router.delete('/:id', async function(req, res, next) {
try {
res.json(await programmingLanguages.remove(req.params.id));
} catch (err) {
console.error(`Error while deleting programming language`, err.message);
next(err);
}
});
After you have the Node.js Express server running with node index.js
, you can test all the API endpoints. To create a new programming language, let’s go with Dart, run the following cURLcommand. Alternately, you can use Postman or any other HTTP client:
curl -i -X POST -H 'Accept: application/json' \
-H 'Content-type: application/json' http://localhost:3000/programming-languages \
--data '{"name":"dart", "released_year": 2011, "githut_rank": 13, "pypl_rank": 20, "tiobe_rank": 25}'
The code above will result in the following output:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 55
ETag: W/"37-3mETlnRrtfrms6wlAjdgAXKq9GE"
Date: Mon, 01 Feb 2021 11:20:07 GMT
Connection: keep-alive
{"message":"Programming language created successfully"}
You can remove the X-Powered-By
header and add other security response headers using Express.js Helmet, which will be a great addition to improve the API’s security. For now, let’s update the GitHut rank of Dart
from 13 to 12:
curl -i -X PUT -H 'Accept: application/json' \
-H 'Content-type: application/json' http://localhost:3000/programming-languages/17 \
--data '{"name":"dart", "released_year": 2011, "githut_rank": 12, "pypl_rank": 20, "tiobe_rank": 25}'
The code above will generate an output like below:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 55
ETag: W/"37-0QPAQsRHsm23S9CNV3rPa+AFuXo"
Date: Mon, 01 Feb 2021 11:40:03 GMT
Connection: keep-alive
{"message":"Programming language updated successfully"}
To test out the DELETE
API, you can use the following cURL to delete Dart with ID 17
:
curl -i -X DELETE -H 'Accept: application/json' \
-H 'Content-type: application/json' http://localhost:3000/programming-languages/17
The code above will result in the following output:
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 55
ETag: W/"37-aMzd+8NpWQ09igvHbNLorsXxGFo"
Date: Mon, 01 Feb 2021 11:50:17 GMT
Connection: keep-alive
{"message":"Programming language deleted successfully"}
If you’re more used to a visual interface for testing, for instance, Postman, you can import the cURL commands into Postman.
For the sake of simplicity in this tutorial, we kept our example fairly simple. However, if this was a real-life API, and not a demo, I’d highly recommend the following:
We now have a functioning API server that uses Node.js and MySQL. In this tutorial, we learned how to set up MySQL on a free service. We then created an Express.js server that can handle various HTTP methods in connection to how it translates to SQL queries.
The example REST API in this tutorial serves as a good starting point and foundation for building real-world, production-ready REST APIs, wherein you can practice the additional considerations describes above. I hope you enjoyed this article, happy coding!
Original article source at https://blog.logrocket.com
#node #mysql #api #expressjs #database #restapi
1594289280
The REST acronym is defined as a “REpresentational State Transfer” and is designed to take advantage of existing HTTP protocols when used for Web APIs. It is very flexible in that it is not tied to resources or methods and has the ability to handle different calls and data formats. Because REST API is not constrained to an XML format like SOAP, it can return multiple other formats depending on what is needed. If a service adheres to this style, it is considered a “RESTful” application. REST allows components to access and manage functions within another application.
REST was initially defined in a dissertation by Roy Fielding’s twenty years ago. He proposed these standards as an alternative to SOAP (The Simple Object Access Protocol is a simple standard for accessing objects and exchanging structured messages within a distributed computing environment). REST (or RESTful) defines the general rules used to regulate the interactions between web apps utilizing the HTTP protocol for CRUD (create, retrieve, update, delete) operations.
An API (or Application Programming Interface) provides a method of interaction between two systems.
A RESTful API (or application program interface) uses HTTP requests to GET, PUT, POST, and DELETE data following the REST standards. This allows two pieces of software to communicate with each other. In essence, REST API is a set of remote calls using standard methods to return data in a specific format.
The systems that interact in this manner can be very different. Each app may use a unique programming language, operating system, database, etc. So, how do we create a system that can easily communicate and understand other apps?? This is where the Rest API is used as an interaction system.
When using a RESTful API, we should determine in advance what resources we want to expose to the outside world. Typically, the RESTful API service is implemented, keeping the following ideas in mind:
The features of the REST API design style state:
For REST to fit this model, we must adhere to the following rules:
#tutorials #api #application #application programming interface #crud #http #json #programming #protocols #representational state transfer #rest #rest api #rest api graphql #rest api json #rest api xml #restful #soap #xml #yaml
1595905879
HTML to Markdown
MySQL is the all-time number one open source database in the world, and a staple in RDBMS space. DigitalOcean is quickly building its reputation as the developers cloud by providing an affordable, flexible and easy to use cloud platform for developers to work with. MySQL on DigitalOcean is a natural fit, but what’s the best way to deploy your cloud database? In this post, we are going to compare the top two providers, DigitalOcean Managed Databases for MySQL vs. ScaleGrid MySQL hosting on DigitalOcean.
At a glance – TLDR
ScaleGrid Blog - At a glance overview - 1st pointCompare Throughput
ScaleGrid averages almost 40% higher throughput over DigitalOcean for MySQL, with up to 46% higher throughput in write-intensive workloads. Read now
ScaleGrid Blog - At a glance overview - 2nd pointCompare Latency
On average, ScaleGrid achieves almost 30% lower latency over DigitalOcean for the same deployment configurations. Read now
ScaleGrid Blog - At a glance overview - 3rd pointCompare Pricing
ScaleGrid provides 30% more storage on average vs. DigitalOcean for MySQL at the same affordable price. Read now
MySQL DigitalOcean Performance Benchmark
In this benchmark, we compare equivalent plan sizes between ScaleGrid MySQL on DigitalOcean and DigitalOcean Managed Databases for MySQL. We are going to use a common, popular plan size using the below configurations for this performance benchmark:
Comparison Overview
ScaleGridDigitalOceanInstance TypeMedium: 4 vCPUsMedium: 4 vCPUsMySQL Version8.0.208.0.20RAM8GB8GBSSD140GB115GBDeployment TypeStandaloneStandaloneRegionSF03SF03SupportIncludedBusiness-level support included with account sizes over $500/monthMonthly Price$120$120
As you can see above, ScaleGrid and DigitalOcean offer the same plan configurations across this plan size, apart from SSD where ScaleGrid provides over 20% more storage for the same price.
To ensure the most accurate results in our performance tests, we run the benchmark four times for each comparison to find the average performance across throughput and latency over read-intensive workloads, balanced workloads, and write-intensive workloads.
Throughput
In this benchmark, we measure MySQL throughput in terms of queries per second (QPS) to measure our query efficiency. To quickly summarize the results, we display read-intensive, write-intensive and balanced workload averages below for 150 threads for ScaleGrid vs. DigitalOcean MySQL:
ScaleGrid MySQL vs DigitalOcean Managed Databases - Throughput Performance Graph
For the common 150 thread comparison, ScaleGrid averages almost 40% higher throughput over DigitalOcean for MySQL, with up to 46% higher throughput in write-intensive workloads.
#cloud #database #developer #digital ocean #mysql #performance #scalegrid #95th percentile latency #balanced workloads #developers cloud #digitalocean droplet #digitalocean managed databases #digitalocean performance #digitalocean pricing #higher throughput #latency benchmark #lower latency #mysql benchmark setup #mysql client threads #mysql configuration #mysql digitalocean #mysql latency #mysql on digitalocean #mysql throughput #performance benchmark #queries per second #read-intensive #scalegrid mysql #scalegrid vs. digitalocean #throughput benchmark #write-intensive
1604399880
I’ve been working with Restful APIs for some time now and one thing that I love to do is to talk about APIs.
So, today I will show you how to build an API using the API-First approach and Design First with OpenAPI Specification.
First thing first, if you don’t know what’s an API-First approach means, it would be nice you stop reading this and check the blog post that I wrote to the Farfetchs blog where I explain everything that you need to know to start an API using API-First.
Before you get your hands dirty, let’s prepare the ground and understand the use case that will be developed.
If you desire to reproduce the examples that will be shown here, you will need some of those items below.
To keep easy to understand, let’s use the Todo List App, it is a very common concept beyond the software development community.
#api #rest-api #openai #api-first-development #api-design #apis #restful-apis #restful-api
1652251629
Unilevel MLM Wordpress Rest API FrontEnd | UMW Rest API Woocommerce Price USA, Philippines : Our API’s handle the Unilevel MLM woo-commerce end user all functionalities like customer login/register. You can request any type of information which is listed below, our API will provide you managed results for your all frontend needs, which will be useful for your applications like Mobile App etc.
Business to Customer REST API for Unilevel MLM Woo-Commerce will empower your Woo-commerce site with the most powerful Unilevel MLM Woo-Commerce REST API, you will be able to get and send data to your marketplace from other mobile apps or websites using HTTP Rest API request.
Our plugin is used JWT authentication for the authorization process.
REST API Unilevel MLM Woo-commerce plugin contains following APIs.
User Login Rest API
User Register Rest API
User Join Rest API
Get User info Rest API
Get Affiliate URL Rest API
Get Downlines list Rest API
Get Bank Details Rest API
Save Bank Details Rest API
Get Genealogy JSON Rest API
Get Total Earning Rest API
Get Current Balance Rest API
Get Payout Details Rest API
Get Payout List Rest API
Get Commissions List Rest API
Withdrawal Request Rest API
Get Withdrawal List Rest API
If you want to know more information and any queries regarding Unilevel MLM Rest API Woocommerce WordPress Plugin, you can contact our experts through
Skype: jks0586,
Mail: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com,
Call/WhatsApp/WeChat: +91-9717478599.
more information : https://www.mlmtrees.com/product/unilevel-mlm-woocommerce-rest-api-addon
Visit Documentation : https://letscms.com/documents/umw_apis/umw-apis-addon-documentation.html
#Unilevel_MLM_WooCommerce_Rest_API's_Addon #umw_mlm_rest_api #rest_api_woocommerce_unilevel #rest_api_in_woocommerce #rest_api_woocommerce #rest_api_woocommerce_documentation #rest_api_woocommerce_php #api_rest_de_woocommerce #woocommerce_rest_api_in_android #woocommerce_rest_api_in_wordpress #Rest_API_Woocommerce_unilevel_mlm #wp_rest_api_woocommerce
1652251528
Opencart REST API extensions - V3.x | Rest API Integration : OpenCart APIs is fully integrated with the OpenCart REST API. This is interact with your OpenCart site by sending and receiving data as JSON (JavaScript Object Notation) objects. Using the OpenCart REST API you can register the customers and purchasing the products and it provides data access to the content of OpenCart users like which is publicly accessible via the REST API. This APIs also provide the E-commerce Mobile Apps.
Opencart REST API
OCRESTAPI Module allows the customer purchasing product from the website it just like E-commerce APIs its also available mobile version APIs.
Opencart Rest APIs List
Customer Registration GET APIs.
Customer Registration POST APIs.
Customer Login GET APIs.
Customer Login POST APIs.
Checkout Confirm GET APIs.
Checkout Confirm POST APIs.
If you want to know Opencart REST API Any information, you can contact us at -
Skype: jks0586,
Email: letscmsdev@gmail.com,
Website: www.letscms.com, www.mlmtrees.com
Call/WhatsApp/WeChat: +91–9717478599.
Download : https://www.opencart.com/index.php?route=marketplace/extension/info&extension_id=43174&filter_search=ocrest%20api
View Documentation : https://www.letscms.com/documents/api/opencart-rest-api.html
More Information : https://www.letscms.com/blog/Rest-API-Opencart
VEDIO : https://vimeo.com/682154292
#opencart_api_for_android #Opencart_rest_admin_api #opencart_rest_api #Rest_API_Integration #oc_rest_api #rest_api_ecommerce #rest_api_mobile #rest_api_opencart #rest_api_github #rest_api_documentation #opencart_rest_admin_api #rest_api_for_opencart_mobile_app #opencart_shopping_cart_rest_api #opencart_json_api