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
- Getting Started and Creating an Android Client
- Basics of API Description
- Creating a Sustainable Android Client
- URL Handling, Resolution and Parsing
- How to Change API Base Url at Runtime
- Multiple Server Environments (Develop, Staging, Production)
- Share OkHttp Client and Converters between Retrofit Instances
- Upgrade Guide from 1.9
- Beyond Android: Retrofit for Java Projects
- How to use OkHttp 3 with Retrofit 1
- Synchronous and Asynchronous Requests
- Send Objects in Request Body
- Add Custom Request Header
- Manage Request Headers in OkHttp Interceptor
- Dynamic Request Headers with @HeaderMap
- Multiple Query Parameters of Same Name
- Optional Query Parameters
- Send Data Form-Urlencoded
- Send Data Form-Urlencoded Using FieldMap
- How to Add Query Parameters to Every Request
- Add Multiple Query Parameter With QueryMap
- How to Use Dynamic Urls for Requests
- Constant, Default and Logic Values for POST and PUT Requests
- Cancel Requests
- Reuse and Analyze Requests
- Optional Path Parameters
- How to Send Plain Text Request Body
- Customize Network Timeouts
- How to Trust Unsafe SSL certificates (Self-signed, Expired)
- Dynamic Endpoint-Dependent Interceptor Actions
- How to Update Objects on the Server (PUT vs. PATCH)
- How to Delete Objects on the Server
- Introduction to (Multiple) Converters
- Adding & Customizing the Gson Converter
- Implementing Custom Converters
- How to Integrate XML Converter
- Access Mapped Objects and Raw Response Payload
- Supporting JSON and XML Responses Concurrently
- Handling of Empty Server Responses with Custom Converter
- Send JSON Requests and Receive XML Responses (or vice versa)
- Unwrapping Envelope Responses with Custom Converter
- Wrapping Requests in Envelope with Custom Converter
- Define a Custom Response Converter
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:
- Method Name
- Method Return Type
- 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:
@Body
: send Java objects as request body.@Url
: use dynamic URLs.@Field
: send data as form-urlencoded.
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!