Skip to main content

Command Palette

Search for a command to run...

How to properly organize your API EndPoints in Flutter

Updated
2 min read
How to properly organize your API EndPoints in Flutter
A

I love programming and I work as a Software Engineer developing web based applications and mobile apps. I'm a full stack developer, from the backend where I primarly use Node.js and MySQL on Linux Servers to the frontend where I use modern web technologies and CSS frameworks. I love to develop mobile app, especially in Android mainly in Java, and in the last year I'm using Flutter, first to experiment and in the last period to develop cross platform enterprise apps. In my spare time I like to experiment on side projects apps, ui designs, web app to improve my skills and test new ideas.

Hi everyone, in this post, I'll show you how I organize my API call in one class to manage my API endpoint better and pass parameters to them.

If you've got an app that syncs or gets information from a third-party service you must call some API from your code and it is often tempting to write endpoints directly within our HTTP calls, more or less like this:

//Worst case
Future<MyClass> callEndPoint(int id) async {
    var response = await http.get(Uri.parse("https://myendpointurl/myclass/$id"));
    ...
}

//not that much worse
Future<MyClass> callEndPoint(int id) async {
    var response = await     http.get(Uri.parse("${Env.BASE_URL}/myclass/$id"));
    ...
}

but it is not good practice to hardcode endpoints in all calls, and it is a tad better to manage an environment variable or constant that defines our BASE_URL for calls.

My solution

The solution I have adopted for some time in all my projects is to create an ApiEndPoint class where I define all my endpoints and the parameters I need to manage. So for example to implement calls to the Star Wars API I can do it this way:

class ApiEndPoint {

  late String FILM_ALL;
  late String FILM_SINGLE;

  ApiEndPoint({int? id}) {

    //Value added for simplicity but it is always better 
    //  to add it in a configuration file
    String baseUrlPath = 'https://swapi.dev/api';

    FILM_ALL = '$baseUrlPath/films/';
    FILM_SINGLE = '$baseUrlPath/films/$id';
  }
}

That way when I need to call the endpoint to get the list of movies I just type in:

Future<List<Film>> getAllFilms() async {
  var response = await http.get(
    Uri.parse(ApiEndPoint().FILM_ALL),
  );
  //...
}

And if this endpoint requires input parameters, such as the endpoint to get the information about a single movie, simply write:

Future<Film> getSingleFilm(int idFilm) async {
  var response = await http.get(
    Uri.parse(ApiEndPoint(id: idFilm).FILM_SINGLE),
  );
  //...
}

Easy isn't it?

I find this setup useful and with the following advantages:

  • I have a single class with the responsibility of managing my EndPoints and organizing the paths as required by the API;

  • I can easily pass input parameters without worrying about URL formatting;

  • In my repositories and in my HTTP calls I can tell right away what API it is without going to the URL to figure it out because I have made it explicit in the attributes of my ApiEndPoint class;

  • In the most extreme case, I can switch to another API without having to change my HTTP calls but only by changing the URLs within the ApiEndPoint class;

Code strong, Alberto

Cover Photo by Maria Orlova: Corner Of Aged House Near Direction Post In Town

More from this blog

Flutter and Other Experiments

49 posts

I love programming and I work as a Software Engineer on Web and Mobile Apps. I'm expanding my knowledge on Flutter and Dart I post content about these two technologies.

How to properly organize your API EndPoints in Flutter