Retrofit 2 — Basics of API Description

In the getting started with Retrofit tutorial you've implemented your first request against one GitHub endpoint. Hopefully, you're excited to try out more of Retrofit's functionality. In this tutorial, you'll learn in more detail how to describe API endpoints in Retrofit.

Retrofit Series Overview

How to Describe API Endpoints

As you've learned in the getting started with Retrofit tutorial, we describe all the Retrofit requests we make in an interface class. Our first example, where we showcase a few functionalities at once, was this one:

public interface GitHubClient {  
    @GET("/users/{user}/repos")
    Call<List<GitHubRepo>> reposForUser(
        @Path("user") String user
    );
}

It's time to look at all of these options in more detail.

HTTP Method

You already know that we use annotations on the Java interface methods to describe individual API endpoints and ultimately, the handling of requests. One of the first things you want to define is the HTTP request method like GET, POST, PUT, DELETE, and so on. Retrofit provides an annotation for each of the main standard request methods. You simply use the appropriate Retrofit annotations for each HTTP method: @GET, @POST, @PUT, @DELETE, @PATCH or @HEAD.

You always need to specify what kind of request method the endpoint expects from your app. If you never heard of HTTP request methods, read up on it on wikipedia’s HTTP page. You should be able to pull the expected HTTP request method from the API documentation.

A few simple examples for @GET, @PUT and @DELETE:

public interface FutureStudioClient {  
    @GET("/user/info")
    Call<UserInfo> getUserInfo();

    @PUT("/user/info")
    Call<UserInfo> updateUserInfo(
        @Body UserInfo userInfo
    );

    @DELETE("/user")
    Call<Void> deleteUser();
}

HTTP Resource Location

Additionally, you need to add the relative endpoint URL as a String parameter to the annotation, e.g. @GET("/user/info"). In most cases, you'll pass only a relative URL, and not a full URL (like http://futurestud.io/api/user/info). This has the advantage, that Retrofit only has to ask for the base URL (http://futurestud.io) once. If you're changing the API base URL, you only have to change it in one place. Furthermore, it makes a couple of more advanced things, like dynamic base URLs, much easier. Nevertheless, you can specify a full URL. If you want to learn more about URL handling and how those base URLs and relative URLs get put together, feel free to read our guide on URL handling, resolution and parsing.

Again, some simple examples:

public interface FutureStudioClient {  
    @GET("/user/info")
    Call<UserInfo> getUserInfo();

    @PUT("/user/info")
    Call<UserInfo> updateUserInfo(
        @Body UserInfo userInfo
    );

    @DELETE("/user")
    Call<Void> deleteUser();

    // example for passing a full URL
    @GET("https://futurestud.io/tutorials/rss/")
    Call<FutureStudioRssFeed> getRssFeed();
}

Function Name & Return Type

You now have an idea what the HTTP request method annotation is used for. However, we haven't talked about the actual Java method declaration: Call<UserInfo> getUserInfo();. This contains three parts:

  1. Method Name
  2. Method Return Type
  3. Method Parameters

Let’s start with the easy one: method name. You can freely define the method name. Retrofit doesn’t care and it won’t have any effect on the functionality. Nevertheless, you should choose a name, which helps you and other developers to understand what API request this is.

On the other hand, the method's return type is critical. You have to define what kind of data you expect from the server. For example, when you're requesting some user information, you might specify it as Call<UserInfo>. The UserInfo class contains the properties that will hold the user data. Retrofit will map it automatically and you won't have to do any manual parsing. If you want the raw response, you can use ResponseBody instead of a specific class like UserInfo. If you don't care at all what the server responds, you can use Void. In all those cases, you'll have to wrap it into a typed Retrofit Call<> class.

Finally, and this highly depends on the API endpoint, you can pass parameters to the method. There is a wide variety of possible options, so we’ll just link you some options:

Again, a demonstration of some use cases:

public interface FutureStudioClient {  
    @GET("/user/info")
    Call<UserInfo> getUserInfo();

    @PUT("/user/info")
    Call<Void> updateUserInfo(
        @Body UserInfo userInfo
    );

    @GET
    Call<ResponseBody> getUserProfilePhoto(
        @Url String profilePhotoUrl
    );
}

Since path and query parameters are so common, we'll talk about them in more detail in the next two sections.

Path Parameters

REST APIs are build on dynamic URLs. You access the resource by replacing parts of the URL, for example getting the third tutorial on our page might be http://futurestud.io/api/tutorials/3. The 3 at the end specifies which tutorial you want to access. Retrofit offers a simple way of replacing these so called path parameters. You've already seen an example in the getting started tutorial:

public interface GitHubClient {  
    @GET("/users/{user}/repos")
    Call<List<GitHubRepo>> reposForUser(
        @Path("user") String user
    );
}

Here, the {user} indicates to Retrofit that the value is dynamic and will be set when the request is being made. If you include a path parameter in the URL, you need to add a @Path() function parameter, where the @Path value matches the placeholder in the URL (in this case it'd be @Path("user")). You can use multiple placeholders, if necessary. Just make sure you always have the exact amount of matching parameters. You can even use optional path parameters.

Query Parameters

Another large part of dynamic URLs are query parameters. If you've used our filters already, you've seen them on our website: https://futurestud.io/tutorials?filter=video. The ?filter=video is a query parameter which further describes the request resource. Unlike the path parameters, you don't need to add them to the annotation URL. You can simply add a method parameter with @Query() and a query parameter name, describe the type and you're good to go. Retrofit will automatically attach it to the request. If you pass a null value as query parameter, Retrofit will ignore it. You can also add multiple query parameters.

public interface FutureStudioClient {  
    @GET("/tutorials")
    Call<List<Tutorial>> getTutorials(
        @Query("page") Integer page
    );

    @GET("/tutorials")
    Call<List<Tutorial>> getTutorials(
            @Query("page") Integer page,
            @Query("order") String order,
            @Query("author") String author,
            @Query("published_at") Date date
    );
}    

In the example above, you could also remove the first getTutorials() method and just use the second one by passing a null value as the value for the last three parameters.

What Comes Next

This was only an introduction to describing API endpoints. You've learned the basics of adding new endpoints to your interfaces. You can adjust the resource locations, the HTTP method, return types, path and query parameters.

Retrofit offers a lot more options to further modify requests. For example, we didn't talk at all about headers yet. There is a lot more to learn, so keep on reading more tutorials!

If you've feedback or a question, let us know in the comments or on twitter @futurestud_io.

Make it rock & enjoy coding!


Explore the Library

Find interesting tutorials and solutions for your problems.