Retrofit integration issue with RapidAPI service

I’m having trouble converting my working OkHttp implementation to Retrofit for a translation service from RapidAPI. The OkHttp version works perfectly, but I can’t get the Retrofit equivalent to function properly.

Here’s my working OkHttp implementation:

val httpClient = OkHttpClient()

val contentType = MediaType.parse("application/x-www-form-urlencoded")
val requestBody = RequestBody.create(contentType, "text=Good%20morning&lang=fr")
val httpRequest = Request.Builder()
    .url("https://translator-api.p.rapidapi.com/translate/v1")
    .post(requestBody)
    .addHeader("content-type", "application/x-www-form-urlencoded")
    .addHeader("Accept-Encoding", "application/gzip")
    .addHeader("X-RapidAPI-Host", "translator-api.p.rapidapi.com")
    .addHeader("X-RapidAPI-Key", MY_API_KEY)
    .build()

val result = httpClient.newCall(httpRequest).execute()

I want to achieve the same functionality using Retrofit. Here’s my current API interface setup:

interface TranslationService {

    @Headers(
        "content-type: application/x-www-form-urlencoded",
        "Accept-Encoding: application/gzip",
        "X-RapidAPI-Host: translator-api.p.rapidapi.com",
        "X-RapidAPI-Key: MY_API_KEY"
    )
    @POST("translate/v1")
    suspend fun performTranslation(
        @Body text: String,
        @Query("lang") language: String,
        @Query("from") sourceLanguage: String
    ): Response<TranslationResponse>
}

What am I doing wrong in my Retrofit setup? Any help would be appreciated.

You’re mixing up query parameters and form data. Your OkHttp version sends form-encoded data in the request body (text=Good%20morning&lang=fr), but your Retrofit interface tries to send text as raw body and language as query parameters.

For form-encoded data in Retrofit, use @FormUrlEncoded on your method and @Field for the parameters:

@Headers(
    "Accept-Encoding: application/gzip",
    "X-RapidAPI-Host: translator-api.p.rapidapi.com",
    "X-RapidAPI-Key: MY_API_KEY"
)
@FormUrlEncoded
@POST("translate/v1")
suspend fun performTranslation(
    @Field("text") text: String,
    @Field("lang") language: String
): Response<TranslationResponse>

@FormUrlEncoded automatically sets the content-type to application/x-www-form-urlencoded, so you don’t need to add it manually. This’ll match your working OkHttp setup exactly.

the issue is ur using @Body with a string when the api wants form data. @Body sends raw data, not form fields. switch to @FormUrlEncoded with @Field annotations like others said. also, your retrofit call has a sourceLanguage parameter that u defined but your okhttp doesn’t use it - either check if the api actually needs it or just remove it.

You’re mixing up @Body with form data - that’s the issue. Your OkHttp code uses RequestBody.create() to build form-encoded data, but @Body expects raw request bodies, not form fields. Drop @Body completely and use the form-encoded setup instead. Also noticed your OkHttp request doesn’t have a “from” parameter, but your Retrofit interface does. Double-check that your parameters match what the API wants. One more thing - don’t hardcode that API key in @Headers for production. Use an interceptor to add it dynamically, especially if you’re shipping this app. Fine for testing though.