REST API integration in Flutter is a common approach for building mobile applications that need to interact with remote data sources. A REST (Representational State Transfer) API is a type of API that uses HTTP requests to perform CRUD (Create, Read, Update, Delete) operations on resources.
An API is a set of protocols, routines, and tools for building software applications. In simple terms, an API is a way for two or more computer programs to communicate with each other. It acts as an intermediary, allowing different software applications to exchange data and functionality. REST API integration in Flutter allows developers to seamlessly connect their Flutter-based mobile apps with remote servers and services, enabling them to fetch, manipulate, and display data from various sources.
In this article we will go through step by step process to integrate REST API in you flutter app from creating an API to actually performing CRUD operation.
Creating a REST API to Perform CRUD
The site named Retool provides an API generator that generates rest API in matter of seconds on the basis of the data we needed and it is completely free (no signups no credit card). First of all go to https://retool.com/api-generator and start defining your schema like in the screenshot given below. The video tutorial is provided at the bottom of article in case if you are confused to interact with the interface.

Now click on the generate API button as soon as you complete defining your data set. Once you click on that button, scroll down and you will see interface like this.

Now our rest APIs endpoints are ready and we are good to start working on our app. Now create a basic flutter app by using command “flutter create your_app_name”. In order to use REST API and make http methods call we need to use package like http or dio. For current tutorial we are going to use http package from pub.dev and install it on our project. You can directly write this command (in the screenshot below) to add http in your project.

Now lets create the following folders to manage our application.

Inside models folder we will define our data model and methods associated with it. Inside the model folder create file named company_model.dart and use the following code.
class Company {
int? id;
String? companyName;
String? companyAddress;
String? companyNumber;
String? companyLogo;
Company(
{this.companyAddress,
this.companyLogo,
this.companyName,
this.id,
this.companyNumber});
Company.fromJson(Map<String, dynamic> json) {
id = json['id'];
companyName = json['name'];
companyAddress = json['address'];
companyNumber = json['phone'];
companyLogo = json['logo'];
}
Map<String, dynamic> toJson() {
Map<String, dynamic> data = {};
data['name'] = companyName;
data['address'] = companyAddress;
data['phone'] = companyNumber;
data['logo'] = companyLogo;
return data;
}
}
Inside the services folder create a new file named employee_services.dart. This files contains code about implementing five http methods GET, POST, PUT, PATCH, DELETE.
GET retrieves data from a specified resource or endpoint on the server.
POST creates a new resource on the server, sending the data for the new resource in the request body.
PUT updates an entire resource on the server, replacing the existing resource with the new data provided in the request body.
PATCH partially updates an existing resource on the server, modifying only the specific fields or attributes included in the request body.
DELETE removes a resource from the server, permanently deleting the specified resource.
The compnay_services.dart file is given below.
import 'dart:convert';
import 'dart:developer';
import 'package:crud_api/model/company.dart';
import 'package:http/http.dart' as http;
class CompanyService {
String baseUrl = "https://retoolapi.dev/rd7Mbe/";
getAllCompanies() async {
try {
List<Company> allCompanies = [];
var response = await http.get(Uri.parse(baseUrl + 'company'));
if (response.statusCode == 200) {
var data = response.body;
var jsonData = jsonDecode(data);
print(jsonData);
for (var company in jsonData) {
Company newCompnay = Company.fromJson(company);
allCompanies.add(newCompnay);
}
return allCompanies;
} else {
throw Exception(
"Error occured with status code ${response.statusCode} and the message is ${response.body}");
}
} catch (e) {
print("Error occured: ${e.toString()}");
}
}
createCompany(Company company) async {
log("create company is caleld");
try {
var response = await http.post(Uri.parse(baseUrl + 'company'),
body: company.toJson());
log("The response is ${response.body}");
if (response.statusCode == 201 || response.statusCode == 200) {
print(
"The company is suceesfully created with the following details: ${response.body}");
} else {
throw Exception(
"Error occured with status code ${response.statusCode} and the message is ${response.body}");
}
} catch (e) {
print("Error occured: ${e.toString()}");
}
}
updateCompanyPartially(Map<String, dynamic> updatedData, int id)async{
try {
var response = await http.patch(Uri.parse(baseUrl + 'company' + '/$id'), body: updatedData);
log("the responses status code os ${response.statusCode}");
if (response.statusCode == 201 || response.statusCode == 200) {
print(
"The company is suceesfully deleted with the following details: ${response.body}");
} else {
throw Exception(
"Error occured with status code ${response.statusCode} and the message is ${response.body}");
}
} catch (e) {
print("Error occured: ${e.toString()}");
}
}
updateCompany(Company company, int id) async {
try {
var response = await http.put(Uri.parse(baseUrl + 'company' + '/$id'), body: company.toJson());
log("the responses status code os ${response.statusCode}");
if (response.statusCode == 201 || response.statusCode == 200) {
print(
"The company is suceesfully deleted with the following details: ${response.body}");
} else {
throw Exception(
"Error occured with status code ${response.statusCode} and the message is ${response.body}");
}
} catch (e) {
print("Error occured: ${e.toString()}");
}
}
deleteCompany(int id) async {
try {
var response = await http.delete(Uri.parse(baseUrl + 'company' + '/$id'));
if (response.statusCode == 204 || response.statusCode == 200) {
print(
"The company is suceesfully deleted with the following details: ${response.body}");
} else {
throw Exception(
"Error occured with status code ${response.statusCode} and the message is ${response.body}");
}
} catch (e) {
print("Error occured: ${e.toString()}");
}
}
}
Now inside screens folder lets create two files to display the employees and create new employee. We are using future builder to display the data fetched from the server via API.
Code for company_screen.dart is given below.
import 'package:crud_api/model/company.dart';
import 'package:crud_api/screen/create_company.dart';
import 'package:crud_api/services/company_service.dart';
import 'package:flutter/material.dart';
class CompanyScreen extends StatefulWidget {
const CompanyScreen({super.key});
@override
State<CompanyScreen> createState() => _CompanyScreenState();
}
// Company neCompnay = Company();
class _CompanyScreenState extends State<CompanyScreen> {
@override
Widget build(BuildContext context) {
return Scaffold(
floatingActionButton: FloatingActionButton(
onPressed: () {
Navigator.push(
context, MaterialPageRoute(builder: (_) => CreateCompany()));
},
child: Icon(Icons.add),
),
appBar: AppBar(
title: Text("Company"),
centerTitle: true,
),
body: FutureBuilder(
future: CompanyService().getAllCompanies(),
builder: (context, snapshot) {
if (snapshot.hasError) {
return Center(
child: Text("Error receiving data from server"),
);
}
if (snapshot.hasData) {
List<Company> data = snapshot.data as List<Company>;
return ListView.builder(
itemCount: data.length,
itemBuilder: (context, index) {
return Material(
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
decoration: BoxDecoration(),
// color: Colors.red,
// height: MediaQuery.of(context).size.height * 0.15,
width: double.maxFinite,
child: Padding(
padding: const EdgeInsets.symmetric(
horizontal: 0, vertical: 15),
child: Row(
children: [
Expanded(
flex: 1,
child: CircleAvatar(
backgroundImage: NetworkImage(data[index]
.companyLogo ??
"https://logo.clearbit.com/google.ru"),
)),
Expanded(
flex: 4,
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.start,
children: [
Text(data[index].companyName ??
"Company Name Unavailable"),
Text(data[index].companyNumber ??
"No Number"),
Text(data[index].companyAddress ??
"No address"),
],
)),
Expanded(
flex: 3,
child: Row(
children: [
IconButton(
onPressed: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
CreateCompany(
company:
data[index],
)));
},
icon: Icon(
Icons.edit,
color: Colors.blue,
)),
IconButton(
onPressed: () {
showDialog(
context: context,
builder: (context) {
return AlertDialog(
title: Text(
"Are you sure want to deelet Company?"),
actions: [
ElevatedButton(
onPressed:
() async {
await CompanyService()
.deleteCompany(
data[index]
.id!);
Navigator.pop(
context);
setState(() {});
},
child: Text("Yes")),
ElevatedButton(
onPressed: () {},
child: Text("NO")),
],
);
});
},
icon: Icon(
Icons.delete,
color: Colors.red,
)),
IconButton(
onPressed: () async {
await CompanyService()
.updateCompanyPartially(
{'name': "Flutter Hero"},
data[index].id!);
setState(() {});
},
icon: Icon(Icons.favorite_outline))
],
))
],
),
),
),
),
);
});
} else {
return Center(child: CircularProgressIndicator());
}
}),
);
}
}
The code for add new company is given below.
import 'package:crud_api/services/company_service.dart';
import 'package:flutter/material.dart';
import '../model/company.dart';
class CreateCompany extends StatefulWidget {
final Company? company;
const CreateCompany({super.key, this.company});
@override
State<CreateCompany> createState() => _CreateCompanyState();
}
class _CreateCompanyState extends State<CreateCompany> {
TextEditingController _nameController = TextEditingController();
TextEditingController _addressController = TextEditingController();
TextEditingController _phoneController = TextEditingController();
GlobalKey<FormState> _key = GlobalKey();
@override
void initState() {
if (widget.company != null) {
_nameController.text = widget.company!.companyName!;
_addressController.text = widget.company!.companyAddress!;
_phoneController.text = widget.company!.companyNumber!;
}
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Add Company"),
),
body: Form(
key: _key,
child: SingleChildScrollView(
child: Column(
children: [
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
validator: (value) {
if (value!.length == 0) {
return "Please enter company name";
}
},
controller: _nameController,
decoration: InputDecoration(
helperText: "Your name here",
labelText: "Name",
hintText: "Enter the company name",
border: OutlineInputBorder()),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _addressController,
decoration: InputDecoration(
helperText: "Your address here",
labelText: "Address",
hintText: "Enter the company address",
border: OutlineInputBorder()),
),
),
Padding(
padding: const EdgeInsets.all(8.0),
child: TextFormField(
controller: _phoneController,
decoration: InputDecoration(
helperText: "Your company phone number here",
labelText: "Phone Number",
hintText: "Enter the company phone number",
border: OutlineInputBorder()),
),
),
ElevatedButton(
onPressed: () async {
if (_key.currentState!.validate()) {
Company newCompany = Company(
companyName: _nameController.text,
companyAddress: _addressController.text,
companyNumber: _phoneController.text,
companyLogo:
"https://logo.clearbit.com/godaddy.com");
if (widget.company != null) {
await CompanyService().updateCompany(newCompany, widget.company!.id!);
} else {
await CompanyService().createCompany(newCompany);
}
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
content: Text("Company added successfully")));
Navigator.pop(context);
}
},
child: Text(widget.company==null?"Create Company": "Update Company"))
],
),
)),
);
}
}
In this way we can integrate the REST API in our flutter app. The full source code of this code is available in github be sure to check organization named Flutter Hero in github.
Source Code: https://github.com/Flutter-Hero/crud-api