Registering a sensor in an TTN application via API

OK, bit of boring debugging later and I found the culprit by comparing the Python JSON to the PHP JSON:

$data3 = [
‘end_device’ => [
multicate’ => False,

mulitcate should be multicast

and

‘field_mask’ => [
‘path’ => [

path should be paths

Here’s the whole lot, partial reworked as the use of data1, data2 etc is banned under the Geneva Convention:

<?php

$apiKey = "NNSXS.T0P.53CR3T.AP1.K3Y"

$app_id = "descartes-test01v3";
$app_eui = "0000000000000000";

$device_id = "otaa-test-setup-55";
$dev_eui = "9999999999999955";
$app_key = "19BEC34220EBF366070B59F723F234BE";

$idServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'join_server_address' => 		'eu1.cloud.thethings.network',
		'network_server_address' => 	'eu1.cloud.thethings.network',
		'application_server_address' => 'eu1.cloud.thethings.network',
		'name' => $device_id
	],
	'field_mask' => [
		'paths' => [
			'join_server_address', 'network_server_address', 'application_server_address', 'ids.dev_eui', 'ids.join_eui', 'name'
		]
	]
];

$joinServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'network_server_address' => 	'eu1.cloud.thethings.network',
		'application_server_address' => 'eu1.cloud.thethings.network',
		'network_server_kek_label' => '',
		'application_server_kek_label' => '',
		'application_server_id' => '',
		'net_id' => Null,
		'root_keys' => [
			'app_key' => [
				'key' => $app_key
			],
		],
	],
	'field_mask' => [
		'paths' => [
			 'network_server_address', 'application_server_address', 
			 'ids.device_id', 'ids.dev_eui', 'ids.join_eui', 
			 'network_server_kek_label', 'application_server_kek_label', 
			 'application_server_id', 'net_id', 'root_keys.app_key.key'
		],
	]
];

$networkServer = [
	'end_device' => [
		'multicast' => False,
		'supports_join' => True,
		'lorawan_version' => "MAC_V1_0_2",
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
		'mac_settings' => [
			'supports_32_bit_f_cnt' => True
		],
		'supports_class_c' => False,
		'supports_class_b' => False,
		'lorawan_phy_version' => "PHY_V1_0_2_REV_B",
		'frequency_plan_id' => "EU_863_870_TTN"
	 ],
	'field_mask' => [
		'paths' => [
			'multicast', 'supports_join', 'lorawan_version',
			'ids.device_id', 'ids.dev_eui', 'ids.join_eui',
			'mac_settings.supports_32_bit_f_cnt',
			'supports_class_c', 'supports_class_b',
			'lorawan_phy_version', 'frequency_plan_id' 
		]
	]
];


$applicationServer = [
	'end_device' => [
		'ids' => [
			'device_id' => $device_id,
			'dev_eui' => $dev_eui,
			'join_eui' => $app_eui
		],
	],
	'field_mask' => [
		'paths' => [
			'ids.device_id', 'ids.dev_eui', 'ids.join_eui'
		]
	]
];
		
$data_end_device= json_encode($idServer);
$data_join_server = json_encode($joinServer);
$data_network_server = json_encode($networkServer);
$data_application_server = json_encode($applicationServer);

$url1 = 'https://eu1.cloud.thethings.network/api/v3/applications/'.$app_id.'/devices';
$url2 = 'https://eu1.cloud.thethings.network/api/v3/js/applications/'.$app_id.'/devices';
$url3 = 'https://eu1.cloud.thethings.network/api/v3/ns/applications/'.$app_id.'/devices';
$url4 = 'https://eu1.cloud.thethings.network/api/v3/as/applications/'.$app_id.'/devices';

$authorization = "Authorization: Bearer " . $apiKey;

print($data_end_device."\n");
$ch1 = curl_init($url1);
curl_setopt($ch1, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch1, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch1, CURLOPT_POSTFIELDS, $data_end_device);
curl_setopt($ch1, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch1, CURLOPT_FOLLOWLOCATION, 1);
$result1 = curl_exec($ch1);
curl_close($ch1);
print($result1."\n\n\n");
                
print($data_join_server."\n");  
$ch2 = curl_init($url2);
curl_setopt($ch2, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch2, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch2, CURLOPT_POSTFIELDS, $data_join_server);
curl_setopt($ch2, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch2, CURLOPT_FOLLOWLOCATION, 1);
$result2 = curl_exec($ch2);
curl_close($ch2);
print($result2."\n\n\n");   

print($data_network_server."\n");                
$ch3 = curl_init($url3);
curl_setopt($ch3, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch3, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch3, CURLOPT_POSTFIELDS, $data_network_server);
curl_setopt($ch3, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch3, CURLOPT_FOLLOWLOCATION, 1);
$result3 = curl_exec($ch3);
curl_close($ch3);
print($result3."\n\n\n");

print($data_application_server."\n");  
$ch4 = curl_init($url4);
curl_setopt($ch4, CURLOPT_HTTPHEADER, array($authorization, 'Content-Type: application/json'));
curl_setopt($ch4, CURLOPT_CUSTOMREQUEST, "POST");
curl_setopt($ch4, CURLOPT_POSTFIELDS, $data_application_server);
curl_setopt($ch4, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch4, CURLOPT_FOLLOWLOCATION, 1);
$result4 = curl_exec($ch4);
curl_close($ch4);
print($result4."\n\n\n");

Will do some more tidying up and put this in to a repro