How to Migrate OTAA Devices from V2 to V3

I’m writing this post as a quick draft that will be extended and eventually turned into a documentation page.

Before you Begin

  • We assume your gateway is still connected to V2.
  • Your device will have to perform a new join.
    • If your device doesn’t perform a join procedure regularly (once a week/month), automatically (after it loses connection) and you can’t trigger a join procedure remotely (by sending a downlink), you may have to physically visit your device to
  • If you have easy access to your device, it’s probably better to just re-program it with new root keys. Would be a good opportunity to update the firmware to add some best practices.

1. Migrating a Few Devices

If you’re migrating a few devices, you can just do that in the Console:

V3 Registration

  • If you don’t have an application in V3, add a new one.
    • The Application ID does not have to match your V2 application ID.
  • Add a new End Device in V3.
    • If your device brand/model/etc. is available, you can use that, otherwise follow the manual steps:
    • Select Over the air activation (OTAA)
    • The End device ID does not have to match your V2 device ID.
    • The LoRaWAN version is probably v1.0.2.
    • The AppEUI and DevEUI must be exactly the same as for your v2 device registration.
    • Select a Frequency Plan
    • The Regional Parameters version is probably v1.0.2 rev B
    • Your device does not support class B or class C
    • The Advanced settings probably don’t have to be set.
    • The AppKey must be exactly the same as for your v2 device registration.

Preventing V2 Joins

With the registration in v3 set up, you should prevent your devices from getting accepted on v2. You can do that by deleting the device from V2, but that would make your device stop working immediately. Instead, you can change the AppKey in the V2 Console, so that new joins will no longer get accepted by V2, but the existing session is not deleted yet.

Performing a New Join

Now, the end device will have to perform a new join. It depends on the end device firmware how this is done exactly. Some devices do a new join every week/month, then it’s just a matter of waiting. Some devices let you send a downlink message to trigger a new join, then you need to send that command from the v2 console (or your application). Some devices will do a new join when they lose connection, then you should delete your device from the V2 Console. Some devices do a new join when they are power cycled, then you should do that.

What Happens After the New Join

  • The Join request is received by both V2 (because your gateway is still connected to V2) and V3 (through Packet Broker)
  • Since you changed the AppKey in V2, or deleted the device there, V2 will not accept the Join.
  • Instead, V3 will accept the join. Your device now gets a V3 DevAddr, receives channel settings and other MAC parameters.
  • Based on this DevAddr, Packet Broker will route

2. Migrating a Lot of Devices

If you need to migrate a lot of devices, you can use the migration tool.

[to be added later]


After migrating a OOTA-Device to V3, and change AppKey in V2 and then do a Join

i got a raw-payload 00C57903D07ED5B37076985883F767FC000109ABAF5DCD

MAC Version 1.0.2

But i send only 4 Byte! What its wrong?



After some joins, the payload data arrived fine!

If you are thinking of the V2 console, it’s at the bottom left of the device settings page.

Only delete if you are happy you are on V3.

1 Like

Thank you, it thougt the V3 console, but i found it, thank you!

I tryed to yuse CLI:

Configure V2 CLI

For using ttnctl with The Things Network, follow these instructions.

When using a private V2 network server, provided by The Things Industries, go through the following steps:

  1. Download ttnctl for your operating system.
  2. Update ttnctl to the latest version by running:
$ ttnctl selfupdate
  1. Create a file called .ttnctl.yml in your home directory and fill it with the following information:
auth-server: https://account.<domain_id>
allow-insecure: false
data: /home/<user_name>/.ttnctl
router-id: <domain_id>-router
mqtt-address: <domain_id>
handler-id: <domain_id>-handler
discovery-address: <domain_id>

4.For windows users* make sure to use the --config flag with the full path to the configuration file:

ttnctl.exe --config fullpath/config.yml
  1. Get the access code needed for logging in: https://<domain_id>

Is <domain_id> = “eu” fpr europe?

Is <user_name> the name shown in the TTN-Console?

ttnctl.exe --config fullpath/config.yml

maybee ttnctl.exe --config c:\ttn\cli/config.yml worked not for me!

Will the file config.yml be generated?

The Point 5 https://<domain_id>` with <domain_id> =“eu” worked not for me!

Can somone help, i want to export my devices?


@BK-Vest edited his message so this no longer makes sense:

The original question was:

How do I copy the access key of the application for the application!

What about the network session key, it is not queried in V3?

I relied to the second version of the question which was:

How can i delete a OTTA-Device?

The one visible above is a third question, edited to add a status update.

I can provide some direction on the new question once I have assurance that the question will not be substantially changed from the original.

1 Like

I am located in the nam1 area (North America, California). I believe I need to wait for the V3 nam1 cluster to be installed before I can begin migrating my V2 devices to V3. Is this correct?

Yes that’s correct. Where would you want to migrate to if the target is not yet available?

In the mean time you could already have a look at the V3 documentation and the topics in the V2 to V3 Upgrade category.

Thank you. Another question: I have V2 devices that are buried and programmed to only transmit if an erosion event occurs and the device is exposed - possibly years from now. Will these V2 devices still be able to communicate through our updated V3 stack as long as they are able to detect network loss and rejoin via OTAA?

Yes, as long as it’s migrated to the V3 stack.

Test several units for reassurance!

I’d personally start burying ABP devices going forward, less reliant on hearing any downlink so the message is more likely to get through as gateway antennas are pretty good at hearing but partially buried devices not so much.

1 Like

OK, thank you both for the prompt replies!

Is there any http-Integration on V3? (webhook)

Like V2: HTTP | The Things Network

Backround: I had a application with http-integration

Access Key

The access key used for downlink
default key

The URL of the endpoint

The HTTP method to use

How will be made the Integration in TTS V3?


See V3 documentation.

Next time do some searching on the forum first.

I read the V3 documentation, but i can’t find a solution!
Creating Webhooks | The Things Stack for LoRaWAN (

In V3 I have to make decisions for which I have no information because I did not have to set this before in V2!

I am only user of the interface!

I only see, that the infercae workes not for me!


1 Like

If you want other users to be able to help you you should be more specific.
(I have not used the webhooks myself.)

Please give any details like.

  • What did you expect?
  • What is different?
  • What are you missing?
  • For what exactly do you need help.

TTN V3 is still new and TTI has not worked out all migration guides yet unfortunately.

It’s almost identical to V2. I didn’t even break step setting up a WebHook using my V2 PHP scripts - no changes in PHP, just a change of UI but still very similar in V3.

There are some additional options, but if you don’t need them, don’t worry about them. About the only extra you do have to choose is JSON vs Protocol Buffers - V2 was only JSON, so stick with that.

What are the settings in the webhook to get the behavior of the old settings?

Is it possible that the changed format for the payload on the server side leads to problems?


Like this:

The id is like v2, something you can use to id the HTTP integration / Webhook

Webhook format should be JSON (it’s what we had in V2, I don’t have time to learn Protocol Buffers and I have a PHP script that can semi-auto read JSON)

The Base URL is the v2 URL.

The rest can be left alone unless your script requires some authorisation id.

You will have to make substantive changes to picking out the data you want from the new expanded format, but it’s still just JSON. But it’s just a different structure. Not something I’d describe as leading to problems, just different.

1 Like

Ok, thanks!