Flutter REST API
Building complete REST API integrations
🔗 What is REST API?
REST API is an architectural style for building web services. Flutter apps use REST APIs to perform CRUD operations—Create, Read, Update, Delete—communicating with servers using HTTP methods.
// REST API endpoints
GET /api/users // Get all users
POST /api/users // Create user
PUT /api/users/1 // Update user
DELETE /api/users/1 // Delete user
Output:
✓ REST endpoints defined
REST API Operations
Read (GET)
Fetch data from server
Future<List<User>> getUsers() async {
final response = await http.get(
Uri.parse('$baseUrl/users')
);
return parseUsers(response.body);
}
Create (POST)
Add new data to server
Future<User> createUser(User user) async {
final response = await http.post(
Uri.parse('$baseUrl/users'),
body: json.encode(user.toJson())
);
return User.fromJson(json.decode(response.body));
}
Update (PUT)
Modify existing data
Future<User> updateUser(int id, User user) async {
final response = await http.put(
Uri.parse('$baseUrl/users/$id'),
body: json.encode(user.toJson())
);
return User.fromJson(json.decode(response.body));
}
Delete (DELETE)
Remove data from server
Future<void> deleteUser(int id) async {
await http.delete(
Uri.parse('$baseUrl/users/$id')
);
}
🔹 Complete REST API Service
Create a reusable API service class:
import 'package:http/http.dart' as http;
import 'dart:convert';
class ApiService {
static const String baseUrl = 'https://jsonplaceholder.typicode.com';
// GET - Fetch all users
Future<List<User>> getUsers() async {
final response = await http.get(Uri.parse('$baseUrl/users'));
if (response.statusCode == 200) {
List jsonList = json.decode(response.body);
return jsonList.map((json) => User.fromJson(json)).toList();
} else {
throw Exception('Failed to load users');
}
}
// GET - Fetch single user
Future<User> getUser(int id) async {
final response = await http.get(Uri.parse('$baseUrl/users/$id'));
if (response.statusCode == 200) {
return User.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load user');
}
}
// POST - Create user
Future<User> createUser(User user) async {
final response = await http.post(
Uri.parse('$baseUrl/users'),
headers: {'Content-Type': 'application/json'},
body: json.encode(user.toJson()),
);
if (response.statusCode == 201) {
return User.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to create user');
}
}
// PUT - Update user
Future<User> updateUser(int id, User user) async {
final response = await http.put(
Uri.parse('$baseUrl/users/$id'),
headers: {'Content-Type': 'application/json'},
body: json.encode(user.toJson()),
);
if (response.statusCode == 200) {
return User.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to update user');
}
}
// DELETE - Delete user
Future<void> deleteUser(int id) async {
final response = await http.delete(Uri.parse('$baseUrl/users/$id'));
if (response.statusCode != 200) {
throw Exception('Failed to delete user');
}
}
}
Output:
✓ Complete REST API service created
🔹 Using the API Service
Implement CRUD operations in your Flutter app:
class UserScreen extends StatefulWidget {
@override
_UserScreenState createState() => _UserScreenState();
}
class _UserScreenState extends State<UserScreen> {
final ApiService _apiService = ApiService();
List<User> users = [];
bool isLoading = false;
@override
void initState() {
super.initState();
fetchUsers();
}
Future<void> fetchUsers() async {
setState(() => isLoading = true);
try {
users = await _apiService.getUsers();
} catch (e) {
print('Error: $e');
} finally {
setState(() => isLoading = false);
}
}
Future<void> addUser() async {
User newUser = User(name: 'John Doe', email: '[email protected]');
try {
User createdUser = await _apiService.createUser(newUser);
setState(() => users.add(createdUser));
} catch (e) {
print('Error: $e');
}
}
Future<void> removeUser(int id) async {
try {
await _apiService.deleteUser(id);
setState(() => users.removeWhere((user) => user.id == id));
} catch (e) {
print('Error: $e');
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Users')),
body: isLoading
? Center(child: CircularProgressIndicator())
: ListView.builder(
itemCount: users.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(users[index].name),
subtitle: Text(users[index].email),
trailing: IconButton(
icon: Icon(Icons.delete),
onPressed: () => removeUser(users[index].id),
),
);
},
),
floatingActionButton: FloatingActionButton(
onPressed: addUser,
child: Icon(Icons.add),
),
);
}
}
Output:
🔹 Authentication with REST API
Add authentication tokens to requests:
class AuthApiService {
static const String baseUrl = 'https://api.example.com';
String? _token;
// Login
Future<void> login(String email, String password) async {
final response = await http.post(
Uri.parse('$baseUrl/auth/login'),
headers: {'Content-Type': 'application/json'},
body: json.encode({'email': email, 'password': password}),
);
if (response.statusCode == 200) {
_token = json.decode(response.body)['token'];
} else {
throw Exception('Login failed');
}
}
// Authenticated GET request
Future<List<User>> getUsers() async {
final response = await http.get(
Uri.parse('$baseUrl/users'),
headers: {
'Content-Type': 'application/json',
'Authorization': 'Bearer $_token',
},
);
if (response.statusCode == 200) {
List jsonList = json.decode(response.body);
return jsonList.map((json) => User.fromJson(json)).toList();
} else {
throw Exception('Failed to load users');
}
}
}
Output:
✓ Login successful
Token: eyJhbGciOiJIUzI1NiIsInR5cCI6...
✓ Users fetched with authentication
🔹 Pagination and Filtering
Handle large datasets with pagination:
class PaginatedApiService {
static const String baseUrl = 'https://api.example.com';
Future<PaginatedResponse> getUsers({
int page = 1,
int limit = 10,
String? search,
}) async {
Map<String, String> queryParams = {
'page': page.toString(),
'limit': limit.toString(),
};
if (search != null && search.isNotEmpty) {
queryParams['search'] = search;
}
final uri = Uri.parse('$baseUrl/users').replace(
queryParameters: queryParams,
);
final response = await http.get(uri);
if (response.statusCode == 200) {
return PaginatedResponse.fromJson(json.decode(response.body));
} else {
throw Exception('Failed to load users');
}
}
}
class PaginatedResponse {
final List<User> users;
final int totalPages;
final int currentPage;
PaginatedResponse({
required this.users,
required this.totalPages,
required this.currentPage,
});
factory PaginatedResponse.fromJson(Map<String, dynamic> json) {
return PaginatedResponse(
users: (json['data'] as List)
.map((user) => User.fromJson(user))
.toList(),
totalPages: json['totalPages'],
currentPage: json['currentPage'],
);
}
}
Output:
Page 1 of 5
Showing 10 users
Search: "john" - 3 results