Retrofit Dependency in Android Kotlin: Complete Setup Guide (2026)

All about retrofit

Last Updated: August 2026

If you are looking for the Retrofit dependency in Android, this guide will show you exactly how to add Retrofit to an Android Kotlin project and use it to call a REST API.

Retrofit is one of the most popular networking libraries used in Android development. It allows developers to define API endpoints using simple Kotlin interfaces and annotations such as @GET, @POST, @Path, and @Query.

In this tutorial, you’ll learn how to:

  • Add the Retrofit dependency
  • Add the Gson converter
  • Configure Internet permission
  • Create a Kotlin data class
  • Create an API interface
  • Build a Retrofit client
  • Make a GET API request
  • Use Retrofit with Kotlin Coroutines
  • Handle HTTP responses
  • Structure Retrofit with MVVM
  • Avoid common Retrofit mistakes

Let’s start with the dependency itself.


Retrofit Dependency for Android

As of 2026, Retrofit 3.0.0 is the current stable release.

If your Android project uses Kotlin DSL, open:

app/build.gradle.kts

Add:

dependencies {

    implementation("com.squareup.retrofit2:retrofit:3.0.0")

    implementation("com.squareup.retrofit2:converter-gson:3.0.0")
}

The first dependency adds Retrofit itself.

The second dependency adds Gson support so Retrofit can convert JSON responses into Kotlin objects.

After adding the dependencies, sync your Gradle project.

What does the Retrofit dependency do?

This dependency:

implementation("com.squareup.retrofit2:retrofit:3.0.0")

provides the core Retrofit functionality.

It allows us to create API interfaces such as:

interface ApiService {

    @GET("posts")
    suspend fun getPosts(): List<Post>
}

Retrofit generates the implementation of this interface for us.


Retrofit Dependency Using Version Catalog

Many modern Android Studio projects use a Version Catalog.

If your project contains:

gradle/libs.versions.toml

you can manage the Retrofit version there instead.

Add:

[versions]
retrofit = "3.0.0"

[libraries]

retrofit = { module = “com.squareup.retrofit2:retrofit”, version.ref = “retrofit” } retrofit-converter-gson = { module = “com.squareup.retrofit2:converter-gson”, version.ref = “retrofit” }

Then inside app/build.gradle.kts:

dependencies {

    implementation(libs.retrofit)

    implementation(libs.retrofit.converter.gson)
}

Why use a Version Catalog?

Suppose your application has multiple modules.

Without a Version Catalog, you may repeat:

implementation("com.squareup.retrofit2:retrofit:3.0.0")

in several Gradle files.

A Version Catalog centralizes dependency versions, making larger projects easier to maintain.


What is Retrofit in Android?

Retrofit is a type-safe HTTP client used for Android and JVM applications.

It converts your API definition into callable Kotlin or Java objects.

For example, suppose an API provides:

https://jsonplaceholder.typicode.com/posts

Instead of manually creating and managing the entire HTTP request, we can define:

@GET("posts")
suspend fun getPosts(): List<Post>

Retrofit handles the networking integration for us.

The basic flow looks like this:

Android UI
    ↓
ViewModel
    ↓
Repository
    ↓
ApiService
    ↓
Retrofit
    ↓
HTTP Request
    ↓
REST API
    ↓
JSON Response
    ↓
Gson Converter
    ↓
Kotlin Object

This makes networking code significantly easier to organize.


Step 1: Add Internet Permission

An Android application needs Internet permission to communicate with an API.

Open:

AndroidManifest.xml

Add:

<uses-permission android:name="android.permission.INTERNET" />

For example:

<manifest xmlns:android="http://schemas.android.com/apk/res/android">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:theme="@style/Theme.MyApplication">

    </application>

</manifest>

You don’t need to request this permission from the user at runtime.


Step 2: Create a Kotlin Data Class

For this tutorial, we’ll use JSONPlaceholder.

Suppose the server returns:

{
  "userId": 1,
  "id": 1,
  "title": "Example Post",
  "body": "Example body"
}

Create:

Post.kt

data class Post(

    val userId: Int,

    val id: Int,

    val title: String,

    val body: String
)

The Gson converter can deserialize the JSON response into this Kotlin class.

Conceptually:

JSON Response
      ↓
Gson Converter
      ↓
Post Object

Instead of manually extracting individual JSON fields, we work directly with Kotlin objects.


Step 3: Create the Retrofit API Interface

Create:

ApiService.kt

Add:

import retrofit2.http.GET

interface ApiService {

    @GET("posts")
    suspend fun getPosts(): List<Post>
}

There are two important parts here.

What does @GET mean?

@GET("posts")

tells Retrofit that this endpoint uses the HTTP GET method.

If our base URL is:

https://jsonplaceholder.typicode.com/

Retrofit combines it with:

posts

to call:

https://jsonplaceholder.typicode.com/posts

Why is the function suspend?

We declared:

suspend fun getPosts()

because we’re using Kotlin Coroutines.

Network operations shouldn’t block Android’s main thread.

A suspend API function integrates naturally with coroutine-based application architecture.


Step 4: Create the Retrofit Instance

Create:

RetrofitClient.kt

Add:

import retrofit2.Retrofit
import retrofit2.converter.gson.GsonConverterFactory

object RetrofitClient {

    private const val BASE_URL =
        "https://jsonplaceholder.typicode.com/"

    val apiService: ApiService by lazy {

        Retrofit.Builder()
            .baseUrl(BASE_URL)
            .addConverterFactory(
                GsonConverterFactory.create()
            )
            .build()
            .create(ApiService::class.java)
    }
}

Let’s understand each part.

Retrofit.Builder()

Retrofit.Builder()

starts building a Retrofit configuration.

baseUrl()

.baseUrl(BASE_URL)

defines the base URL used by our API.

A very common mistake is forgetting the trailing slash.

Correct:

https://example.com/api/
https://example.com/api

addConverterFactory()

.addConverterFactory(
    GsonConverterFactory.create()
)

tells Retrofit to use Gson for conversion.

For example:

API JSON
   ↓
GsonConverterFactory
   ↓
Kotlin Object

build()

.build()

creates the configured Retrofit instance.

create()

.create(ApiService::class.java)

creates an implementation of our ApiService.

This is an important Retrofit concept:

You define the API interface; Retrofit creates its implementation.


Step 5: Make a GET Request Using Kotlin Coroutines

For a simple Activity example:

lifecycleScope.launch {

    try {

        val posts =
            RetrofitClient.apiService.getPosts()

        posts.forEach { post ->

            println(post.title)
        }

    } catch (e: Exception) {

        e.printStackTrace()
    }
}

The flow is:

lifecycleScope.launch
        ↓
getPosts()
        ↓
Retrofit
        ↓
GET /posts
        ↓
Server
        ↓
JSON
        ↓
Gson
        ↓
List<Post>

Retrofit therefore removes much of the repetitive networking code we’d otherwise need.


Using Response With Retrofit

Sometimes we need more than the response body.

For example, we may need the HTTP status code.

Change:

suspend fun getPosts(): List<Post>

to:

import retrofit2.Response
import retrofit2.http.GET

interface ApiService {

    @GET("posts")
    suspend fun getPosts(): Response<List<Post>>
}

Now we can write:

val response =
    RetrofitClient.apiService.getPosts()

if (response.isSuccessful) {

    val posts = response.body()

    posts?.forEach { post ->
        println(post.title)
    }

} else {

    println(
        "HTTP Error: ${response.code()}"
    )
}

This gives us access to HTTP information such as:

200 → Success
400 → Bad Request
401 → Unauthorized
403 → Forbidden
404 → Not Found
500 → Internal Server Error

In a real application, you should design explicit loading, success and error states instead of simply printing errors.


Retrofit Annotations Explained

Retrofit uses annotations to describe API operations.

Some of the most important annotations are:

  • @GET
  • @POST
  • @PUT
  • @DELETE
  • @Path
  • @Query
  • @Body
  • @Header

Let’s understand them.


@GET

Used to retrieve data.

@GET("users")
suspend fun getUsers(): List<User>

This could call:

GET /users

@POST

Usually used to create or submit data.

@POST("users")
suspend fun createUser(
    @Body user: User
): Response<User>

@PUT

Commonly used to update a resource.

@PUT("users/{id}")
suspend fun updateUser(

    @Path("id") id: Int,

    @Body user: User

): Response<User>

@DELETE

Used to delete a resource.

@DELETE("users/{id}")
suspend fun deleteUser(

    @Path("id") id: Int

): Response<Unit>

@Path

@Path replaces a dynamic part of an endpoint.

For example:

@GET("users/{id}")
suspend fun getUser(

    @Path("id") id: Int

): User

Calling:

getUser(10)

results in an endpoint similar to:

/users/10

@Query

@Query adds a query parameter to the request URL.

@GET("users")
suspend fun getUsers(

    @Query("page") page: Int

): List<User>

Calling:

getUsers(2)

creates a request similar to:

/users?page=2

@Body

@Body sends an object as the request body.

@POST("users")
suspend fun createUser(

    @Body user: User

): Response<User>

The converter serializes the compatible Kotlin object into the request representation.


@Header

Headers are commonly required for authentication or other request metadata.

For example:

@GET("profile")
suspend fun getProfile(

    @Header("Authorization")
    token: String

): Response<User>

A production application may instead add common headers centrally using an OkHttp interceptor.


Retrofit With MVVM Architecture

The previous Activity example is useful for understanding Retrofit, but production networking logic generally shouldn’t live directly inside an Activity or Fragment.

A better structure is:

Activity / Fragment / Compose
             ↓
         ViewModel
             ↓
        Repository
             ↓
        ApiService
             ↓
         Retrofit
             ↓
           Server

For example:

class PostRepository(
    private val apiService: ApiService
) {

    suspend fun getPosts(): List<Post> {

        return apiService.getPosts()
    }
}

The ViewModel can depend on the repository:

class PostViewModel(
    private val repository: PostRepository
) : ViewModel() {

    fun loadPosts() {

        viewModelScope.launch {

            try {

                val posts =
                    repository.getPosts()

                // Update UI state here

            } catch (e: Exception) {

                // Update error state here
            }
        }
    }
}

Now the ViewModel doesn’t need to know the details of how Retrofit is configured.

This separation becomes increasingly important as the application grows.


Retrofit + Repository + ViewModel Flow

Think of each layer as having a specific responsibility.

UI
│
│ User requests data
↓
ViewModel
│
│ Requests business/application data
↓
Repository
│
│ Selects data source
↓
ApiService
│
│ Defines endpoint
↓
Retrofit
│
│ Executes network integration
↓
REST API

The response then travels back through the layers:

REST API
    ↓
Retrofit
    ↓
Repository
    ↓
ViewModel
    ↓
UI State
    ↓
Screen

This structure is much easier to maintain than putting networking, business logic and UI logic in one Activity.


Common Retrofit Errors and Solutions

1. Internet Permission Missing

Make sure your manifest contains:

<uses-permission android:name="android.permission.INTERNET" />

Without Internet permission, your application cannot normally perform the required network communication.


2. Base URL Doesn’t End With /

Incorrect:

private const val BASE_URL =
    "https://example.com/api"

Use:

private const val BASE_URL =
    "https://example.com/api/"

Retrofit requires a properly structured base URL.


3. Wrong API Endpoint

Suppose:

BASE_URL =
    "https://example.com/api/"

and:

@GET("users")

Retrofit will request:

https://example.com/api/users

Check the server’s API documentation carefully if you receive a 404.


4. Kotlin Model Doesn’t Match JSON

Suppose the server returns:

{
  "id": 10,
  "username": "androiddev"
}

Your model needs to correctly represent the response contract.

For example:

data class User(

    val id: Int,

    val username: String
)

When API field names and Kotlin property names differ, configure the serialization mapping appropriately.


5. HTTP Instead of HTTPS

Modern Android applications generally should communicate over HTTPS.

Prefer:

https://example.com

rather than:

http://example.com

Cleartext HTTP traffic may also be restricted by Android’s network security configuration.


6. Doing Too Much Inside Activity

Avoid building your entire networking architecture inside:

MainActivity.kt

A better project might contain:

data/
    remote/
        ApiService.kt
        RetrofitClient.kt

    repository/
        PostRepository.kt

model/
    Post.kt

ui/
    PostViewModel.kt
    MainActivity.kt

As the application grows, you can evolve this into a fuller Clean Architecture structure.


Retrofit Best Practices for Production Android Apps

A tutorial project can call Retrofit directly.

Production applications usually need more structure.

Consider the following practices.

Use Repository Pattern

Keep networking implementation outside the UI layer.

UI → ViewModel → Repository → API

Use Dependency Injection

Instead of manually constructing Retrofit everywhere, use a dependency-injection solution such as Hilt or Dagger when appropriate for your architecture.

Handle Errors Properly

Don’t rely only on:

e.printStackTrace()

Your UI should be able to represent states such as:

Loading
Success
Network Error
Server Error
Authentication Error
Empty Result

Keep the Base URL Centralized

Don’t repeat API URLs throughout your project.

Use Interceptors for Common Request Logic

Authentication headers, logging and other shared request concerns can often be implemented with OkHttp interceptors.

Don’t Expose Network Models Everywhere

In larger applications, consider separating API DTOs from domain models.

For example:

API Response
    ↓
PostDto
    ↓
Mapper
    ↓
Post
    ↓
Domain / UI

This prevents API changes from unnecessarily affecting the rest of your application.


Retrofit 3.0.0 vs Retrofit 2.x

Retrofit 3.0.0 is the current stable release.

One notable change in Retrofit 3 is the move from the older OkHttp 3.14 dependency to OkHttp 4.12.

Retrofit 3.x maintains forward binary compatibility with Retrofit 2.x, which helps reduce migration friction for existing libraries and applications.

For a new Android project in 2026, use the current stable version unless your project’s dependency requirements give you a specific reason to remain on an older release.


Frequently Asked Questions About Retrofit

What is the latest Retrofit dependency for Android?

As of August 2026, the current stable Retrofit release is 3.0.0.

The core dependency is:

implementation(
    "com.squareup.retrofit2:retrofit:3.0.0"
)

For Gson:

implementation(
    "com.squareup.retrofit2:converter-gson:3.0.0"
)

Always verify dependency versions before using them in a long-lived production project.


What is Retrofit used for in Android?

Retrofit is used to integrate HTTP APIs with Android/JVM applications.

Developers commonly use it for operations such as:

  • Getting data from a REST API
  • Sending form/application data
  • User login APIs
  • Registration APIs
  • Loading product data
  • Loading user profiles
  • Updating server resources
  • Deleting resources
  • Working with authenticated APIs

Is Retrofit only for Kotlin?

No.

Retrofit can be used with both Kotlin and Java.

Kotlin Android projects commonly combine Retrofit with Coroutines.


Does Retrofit require Internet permission?

Yes.

Add:

<uses-permission android:name="android.permission.INTERNET" />

inside your Android manifest.


Does Retrofit support Kotlin Coroutines?

Yes.

You can define Retrofit endpoints using suspend functions:

@GET("posts")
suspend fun getPosts(): List<Post>

This works naturally with coroutine scopes such as viewModelScope.


What is GsonConverterFactory in Retrofit?

GsonConverterFactory provides Gson-based serialization/deserialization for Retrofit.

For a response:

{
  "id": 1,
  "name": "Android"
}

it can deserialize the JSON into an appropriate Kotlin object.


Retrofit vs OkHttp: What is the difference?

OkHttp is the underlying HTTP client commonly used by Retrofit.

A simplified way to understand the relationship is:

Your Kotlin Code
       ↓
Retrofit
       ↓
OkHttp
       ↓
HTTP
       ↓
Server

Retrofit provides the higher-level API-interface and conversion abstraction, while OkHttp handles the underlying HTTP communication.


Should I use Retrofit with MVVM?

Retrofit works very well with MVVM.

A typical architecture is:

Compose / Activity / Fragment
            ↓
        ViewModel
            ↓
        Repository
            ↓
        ApiService
            ↓
         Retrofit

This keeps network implementation separate from UI logic.


Conclusion

Adding the Retrofit dependency in Android is easy, but understanding where Retrofit belongs in an Android architecture is more important than simply copying a Gradle dependency.

For a basic Kotlin project, you need:

Retrofit
   +
JSON Converter
   +
Internet Permission
   +
Data Class
   +
ApiService
   +
Retrofit Client
   +
Coroutines

For a production Android application, the architecture typically grows toward:

UI
 ↓
ViewModel
 ↓
Repository
 ↓
ApiService
 ↓
Retrofit / OkHttp
 ↓
REST API

Once you’re comfortable with this setup, the next topics to learn are Retrofit annotations, POST requests, error handling, OkHttp interceptors, authentication, MVVM integration, Kotlin Coroutines, StateFlow and dependency injection.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top