I recently ran into the problem of customising timeouts for different API calls when using retrofit.

Ideally, you would be able to specify a timeout using a custom annotation.

interface Api {
    fun listRepos(@Path("user") user: String): Call<List<Repo>>

However, without creating a wrapper around retrofit this isn’t possible.

Instead I created a custom interceptor that uses the @Headers annotation to parse timeouts. (This will override the default timeouts you have set on your OkHttpClient)

class TimeoutInterceptor : Interceptor {

    override fun intercept(chain: Interceptor.Chain): Response {
        val request = chain.request()

        val timeout = request.header("X-Timeout")?.toInt() ?: 0

        return if (timeout > 0) {
            chain.withWriteTimeout(timeout, TimeUnit.MILLISECONDS)
                    .withReadTimeout(timeout, TimeUnit.MILLISECONDS)
                    .withConnectTimeout(timeout, TimeUnit.MILLISECONDS)
        } else {

To use this you add a header with your timeout to the API declaration. The interceptor will consume this and apply the custom timeout to the chain.

@Headers("X-Timeout: 60000")
fun listRepos(@Path("user") user: String): Call<List<Repo>>

Don’t forget to add your interceptor to your OkHttpClient

val client = OkHttpClient.Builder()

val retrofit = Retrofit.Builder()

val service = retrofit.create(GitHubService::class.java)

This functionality was added in OkHttp 3.9.0 so ensure you are targeting the latest version.