Flutter API Calls with Dio: Setup and Patterns

Dio is the most widely used HTTP client in Flutter. Here's how I set it up — interceptors for auth, error mapping, and cancellation — without overengineering.

Richard GamoraRichard GamoraFullstack developer·4 min read
FlutterDioAPI

Dio is the de facto HTTP client for Flutter. Out of the box it works fine. The wins come from setting up interceptors and consistent error handling once, then leaving them alone.

Base configuration

dartfinal dio = Dio(BaseOptions(
  baseUrl: 'https://api.example.com',
  connectTimeout: const Duration(seconds: 10),
  receiveTimeout: const Duration(seconds: 10),
  responseType: ResponseType.json,
  headers: {'Accept': 'application/json'},
));

Auth interceptor

Add an interceptor that attaches the auth token on every request and refreshes it when the server returns 401. Centralizing this means individual repository methods do not need to know about auth at all — they call dio.get() and the interceptor handles the rest.

Error mapping

Wrap Dio calls in a function that converts DioException into your own typed errors (ApiError.network, ApiError.unauthorized, ApiError.server). Repositories return Either or AsyncValue with these typed errors instead of raw exceptions. The UI now has a small, named set of failures to handle.

Cancellation

Pass a CancelToken to long-running requests, and cancel it when the widget is disposed or the user changes inputs. This avoids the classic bug where a slow search request returns after the user has typed something different and replaces the new results.

The whole setup — base URL, interceptors, error mapping, cancellation — is roughly 80 lines of code. Done once, every call site stays clean.

About the author

Richard Gamora

Richard Gamora

Fullstack developer based in the Philippines, working mostly with Laravel and Vue.js, with eight years of production experience across web and mobile.

me@richardgamora.comUpwork ↗

More on Flutter