Flutter integration
Flutter applications connect to Apso through the generated REST API. Use an end-user access token in the mobile client and keep service API keys in a trusted server environment.
Add dependencies
flutter pub add http flutter_secure_storageCreate the client
lib/api_client.dart
import 'dart:convert';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:http/http.dart' as http;
class ApiException implements Exception {
final int statusCode;
final String message;
ApiException(this.statusCode, this.message);
}
class ApiClient {
ApiClient({required this.baseUrl});
final String baseUrl;
final FlutterSecureStorage _storage = const FlutterSecureStorage();
Future<Map<String, String>> _headers() async {
final token = await _storage.read(key: 'access_token');
return {
'Content-Type': 'application/json',
if (token != null) 'Authorization': 'Bearer $token',
};
}
Future<dynamic> get(String path) async {
final response = await http.get(
Uri.parse('$baseUrl$path'),
headers: await _headers(),
);
return _decode(response);
}
Future<dynamic> post(String path, Map<String, dynamic> body) async {
final response = await http.post(
Uri.parse('$baseUrl$path'),
headers: await _headers(),
body: jsonEncode(body),
);
return _decode(response);
}
dynamic _decode(http.Response response) {
if (response.statusCode >= 200 && response.statusCode < 300) {
return response.body.isEmpty ? null : jsonDecode(response.body);
}
throw ApiException(response.statusCode, 'API request failed');
}
}Do not embed an Apso service API key in the Flutter application. Mobile users can extract values shipped in the bundle.
Model a paginated response
lib/project.dart
class Project {
Project({required this.id, required this.name});
final int id;
final String name;
factory Project.fromJson(Map<String, dynamic> json) {
return Project(id: json['id'] as int, name: json['name'] as String);
}
}
class ProjectPage {
ProjectPage({required this.data, required this.total});
final List<Project> data;
final int total;
factory ProjectPage.fromJson(Map<String, dynamic> json) {
return ProjectPage(
data: (json['data'] as List)
.map((item) => Project.fromJson(item as Map<String, dynamic>))
.toList(),
total: json['total'] as int,
);
}
}Query and create projects
lib/project_service.dart
import 'api_client.dart';
import 'project.dart';
class ProjectService {
ProjectService(this.client);
final ApiClient client;
Future<ProjectPage> list() async {
final json = await client.get('/Projects?limit=20&page=1');
return ProjectPage.fromJson(json as Map<String, dynamic>);
}
Future<Project> create(String name) async {
final json = await client.post('/Projects', {
'name': name,
'status': 'Active',
});
return Project.fromJson(json as Map<String, dynamic>);
}
}Store and clear the user token
const storage = FlutterSecureStorage();
await storage.write(key: 'access_token', value: accessToken);
await storage.delete(key: 'access_token');The access token must come from an authentication flow configured for the generated backend. See Bring Your Own Auth.
Mobile checklist
- Use HTTPS outside local development.
- Store user tokens in platform-backed secure storage.
- Clear expired credentials after
401responses. - Handle offline, timeout, empty, and retry states.
- Keep service API keys in a server or BFF.
- Validate tenant scope on every protected request.
Related
Last updated on