How to do a "staged" migration with using API v2 and v3 using Java SDK?

We are migrating our application to the new Nylas API v3, but it appears the Java SDK v2.2.1 is not backwards compatible with API v2. And due to dependency conflicts, I can’t import both SDK v1.22.0 & v2.2.1 to use them separately. I’m curious how others have migrated using the Java SDK. Right now, I am at a loss on how to proceed.

@burtonrhodes thanks for reaching out.

So Nylas API v3 is a breaking change from Nylas API v2, and this will be the reason why the latest version of the Java SDK is not backwards compatible, so you can’t use both SDKs. I was chatting with a colleague, and one option if you want to consider importing both libraries is by consuming the Nylas API v2 Java SDK locally and consuming Nylas API v3 Java SDK from a public repo (Maven).

Just considering alternatives, have you had a chance to take a look at the Nylas Developer documentation, we provide code samples for all relevant Nylas API v3 endpoints in both Kotlin and Java for reference when migrating.

As for how others have migrated using the Java SDK, will see if others have thoughts on this from the community.

Thanks for the response. I have downloaded both branches and luckily the packages are different between each v1.x and v2.x except for one class: NylasClient. I have renamed this class in a modified version of v1.x locally. In theory this should work, as the dependencies are essentially the same. However, I’m getting an error when trying init the NylasClient in either package.

For example, the code below produces the following error:

// Init v2 client
NylasClient nylas = new NylasClient.Builder(nylas3ApiKey).build();
Exception in thread "main" java.lang.NoSuchFieldError: INSTANCE
	at com.nylas.interceptors.AddVersionHeadersInterceptor.<clinit>(AddVersionHeadersInterceptor.kt:20)
	at com.nylas.NylasClient.<init>(NylasClient.kt:70)
	at com.nylas.NylasClient$
	at com.afs.nylas.NylasTest.createNylas3AuthUrl(
	at com.afs.nylas.NylasTest.main(

Hello @burtonrhodes

Internally V2 and V3 SDK are completely different, starting from the fact that V2 was developed in Java and V3 is being developed in Kotlin.

Calling a V3 class from V2 will not work or at least it will not work that easily.

I have no huge project in V2, but the ones I have were migrated to V3 without any issues.

Correct. But I was never calling a V3 class from a V2 class (or vice versa). The only issue was the conflicting packages/names when I tried to import both versions into my application. Now that I’ve changed the one class from V2, there are no conflicts. So it should work. Oh well.

In regard to migration, I assume a hard switch to v3 would require every user to reconnect their Google/Outlook connections on day one. I’m trying to avoid this at all costs - especially if we have to rollback to v2 due to some unforeseen issue in production.

It doesn’t help with the rollback scenario, but I know our Support team is able to migrate user accounts to v3 for you. Just contact them when you’re ready. We definitely want to help you avoid reauthing everyone!

1 Like

That is good to know. What happens when the scopes are different? Currently we don’t have the email.read_write scope on any account. However, we are planning on implementing this in our new version. I know the users will need to reauthorize, but I’m curious if Nylas will be able to migrate authorizations with scopes that don’t match our new feature.

If you have an ongoing thread with Support exploring account migration, worth clarifying with them.

Also, if the user needs to reauthorize, that is also an opportunity to test out the migration to v3 as a limited roll out and/or feature flag.

Absolutely agree. That’s why I need to figure out how to use v1 and v2 sdk’s at once

Just FYI, with the help of Nylas support, we able to figure this out with some minor code modifications. 2 changes were necessary to make this happen.

  1. Modify SDK 1.x by renaming the class main NylasClient to Nylas1Client
  2. Modify SDK 2.x by changing AddVersionHeadersInterceptor.kt class (see below)
// AddVersionHeadersInterceptor.kt
class AddVersionHeadersInterceptor : Interceptor {
  override fun intercept(chain: Interceptor.Chain): Response {
  val requestBuilder = chain.request().newBuilder()
  .header("User-Agent", ("Nylas Java SDK" + BuildInfo.VERSION))
  return chain.proceed(

// Move user agent string into the above
// companion object {
// private val USER_AGENT = "Nylas Java SDK " + (BuildInfo.VERSION ?: "unknown")
// }

@burtonrhodes thanks for sharing this, super helpful!

1 Like