Kotlin CI/CD: Refreshing OAuth Client Credentials token without hardcoding secrets

We’re setting up a GitHub Actions pipeline to deploy our Android app configs using the Genesys Cloud CX as Code provider. The issue is managing the authentication lifecycle inside the workflow. We can’t hardcode the client_id and client_secret directly in the code, so we’re pulling them from GitHub Secrets.

I’ve got a small Kotlin helper script running in the CI environment that hits the /api/v2/oauth/token endpoint. It works fine for the initial login, but the token expires in 24 hours. If the pipeline runs again the next day without a fresh token, it fails with a 401 Unauthorized.

Here’s the current setup using kotlinx.serialization:

val body = mapOf(
 "grant_type" to "client_credentials",
 "client_id" to System.getenv("GC_CLIENT_ID"),
 "client_secret" to System.getenv("GC_CLIENT_SECRET")
)

val response = client.post("https://api.mypurecloud.com/api/v2/oauth/token") {
 contentType(ContentType.Application.FormUrlEncoded)
 setBody(body)
}

val token = response.body<TokenResponse>().access_token

The problem is that TokenResponse doesn’t seem to expose an explicit refresh_token field for client_credentials grants in the way I’m expecting. The docs mention short-lived tokens for this flow. Should I be hitting the endpoint every single time the pipeline starts? That feels inefficient and risks hitting rate limits if we have parallel jobs.

Is there a way to generate a longer-lived token specifically for CI/CD use, or is the standard pattern just to cache the token in the runner’s filesystem and check the expiration timestamp before making the HTTP call? We’re trying to avoid adding too much logic into the workflow YAML file itself.