> This page is for Developers.

> For clean Markdown of any page, append .md to the page URL.
> For a complete documentation index, see https://docs.emnify.com/llms.txt.
> For AI client integration (Claude Code, Cursor, etc.), connect to the MCP server at https://docs.emnify.com/_mcp/server.

# Update device-to-device mode of a service profile

PUT https://cdn.emnify.net/api/v1/service_profile/{service_profile_id}/d2d
Content-Type: application/json

Required permissions Beta [Learn more](/developers/api-guidelines/permissions#how-permissions-work)`ServiceProfile.D2d` + `Update`Roles: AdministratorSets the device-to-device (D2D) mode of a service profile.
The response returns the updated configuration, so there's no need for a follow-up `GET` request.For devices to communicate, enable device-to-device on the service profile of every device involved.
If only one side is enabled, return traffic is blocked.
Devices must belong to the same organization and region.
Communication across organizations or regions isn't supported.Setting `enabled` or `forward_to_backend` requires your organization to have a virtual network.
Setting `disabled` doesn't require a virtual network.
Changes take effect without devices reconnecting.`forward_to_backend` only prepares the configuration.
It requires a default route over [Cloud Connect](/services/cloud-connect), and OpenVPN isn't supported.
The API accepts the mode without checking your Cloud Connect configuration and returns a warning instead.
Traffic between devices is dropped until the setup is complete.Device-to-device is opt-in and enabled per organization.
Until it's enabled for your organization, requests return `403`.
To request access, contact emnify support.

Reference: https://docs.emnify.com/developers/api/service-profiles/service-profile-device-to-device-put

## Authentication

- `Authorization` header (bearer token, required) — An `auth_token` should be provided to authenticate a session. To obtain an `auth_token`, see the [`/api/v1/authenticate` **POST** request](/developers/api/authentication/authenticate).

## Request

### Path parameters

- `service_profile_id` (integer, required) — The numeric ID of a service profile.

### Query parameters

- `org_id` (long, optional) — Numeric ID of a child organization to act on. Omit to use your own organization. Returns `403` if the organization isn't a child of yours. The service profile must belong to that organization, and device-to-device must be enabled for it.

### Body (application/json)

This endpoint expects an object.

- `mode` (enum, required) — Device-to-device mode to set. The value is case-insensitive.
  - Allowed values: `disabled`, `enabled`, `forward_to_backend`

## Response

### 200

Device-to-device mode updated.

- `service_profile_id` (integer, required) — ID of the service profile.
- `mode` (enum, required) — Device-to-device mode of the service profile: - `disabled` (default): Traffic between devices is dropped. - `enabled`: Traffic is delivered directly between devices, as long as the service profiles of both devices have device-to-device enabled. - `forward_to_backend`: Traffic between devices is routed through your Cloud Connect backend, for example so your own firewall can inspect it.
  - Allowed values: `disabled`, `enabled`, `forward_to_backend`
- `modified_at` (string, required, nullable) — When the mode was last changed. `null` if device-to-device has never been configured on the service profile.
- `warnings` (list of string, optional) — Advisory messages about the configuration. Only present in `PUT` responses, and only when there's something to report, for example after setting `forward_to_backend`.

## Errors

### 400 Bad Request Error

Invalid payload.

- `error_code` (integer, optional)
- `error_token` (string, optional)
- `message` (string, optional)

### 401 Unauthorized Error

Missing or invalid Authorization header.

- `any`

### 403 Forbidden Error

Your user doesn't have the required permission, device-to-device isn't enabled for the organization, or `org_id` isn't a child organization.

- `error_code` (integer, optional)
- `error_token` (string, optional)
- `message` (string, optional)

### 404 Not Found Error

Service profile not found, or it belongs to another organization.

- `any`

### 409 Conflict Error

The organization doesn't have a virtual network, so `enabled` and `forward_to_backend` can't be set. Contact emnify support to set one up.

- `error_code` (integer, optional)
- `error_token` (string, optional)
- `message` (string, optional)

### 422 Unprocessable Entity Error

`service_profile_id` or `org_id` isn't a number.

- `any`

### 503 Service Unavailable Error

The configuration couldn't be applied. Retry the request.

- `any`

## Examples

### Enable Device-To-Device

**Request**

```json
{
  "mode": "enabled"
}
```

**Response**

```json
{
  "service_profile_id": 1234,
  "mode": "enabled",
  "modified_at": "2026-08-19T10:00:00Z"
}
```

**SDK Code**

```python Enable Device-To-Device
import requests

url = "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

payload = { "mode": "enabled" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.put(url, json=payload, headers=headers)

print(response.json())
```

```javascript Enable Device-To-Device
const url = 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d';
const options = {
  method: 'PUT',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"mode":"enabled"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Enable Device-To-Device
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

	payload := strings.NewReader("{\n  \"mode\": \"enabled\"\n}")

	req, _ := http.NewRequest("PUT", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Enable Device-To-Device
require 'uri'
require 'net/http'

url = URI("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"mode\": \"enabled\"\n}"

response = http.request(request)
puts response.read_body
```

```java Enable Device-To-Device
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.put("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"mode\": \"enabled\"\n}")
  .asString();
```

```php Enable Device-To-Device
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PUT', 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d', [
  'body' => '{
  "mode": "enabled"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Enable Device-To-Device
using RestSharp;

var client = new RestClient("https://cdn.emnify.net/api/v1/service_profile/1234/d2d");
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"mode\": \"enabled\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Enable Device-To-Device
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["mode": "enabled"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://cdn.emnify.net/api/v1/service_profile/1234/d2d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Forward To Backend

**Request**

```json
{
  "mode": "forward_to_backend"
}
```

**Response**

```json
{
  "service_profile_id": 1234,
  "mode": "forward_to_backend",
  "modified_at": "2026-08-19T10:00:00Z",
  "warnings": [
    "this mode requires cloud connect with default route set, please reach out for customer support"
  ]
}
```

**SDK Code**

```python Forward To Backend
import requests

url = "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

payload = { "mode": "forward_to_backend" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.put(url, json=payload, headers=headers)

print(response.json())
```

```javascript Forward To Backend
const url = 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d';
const options = {
  method: 'PUT',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"mode":"forward_to_backend"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Forward To Backend
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

	payload := strings.NewReader("{\n  \"mode\": \"forward_to_backend\"\n}")

	req, _ := http.NewRequest("PUT", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Forward To Backend
require 'uri'
require 'net/http'

url = URI("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"mode\": \"forward_to_backend\"\n}"

response = http.request(request)
puts response.read_body
```

```java Forward To Backend
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.put("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"mode\": \"forward_to_backend\"\n}")
  .asString();
```

```php Forward To Backend
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PUT', 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d', [
  'body' => '{
  "mode": "forward_to_backend"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Forward To Backend
using RestSharp;

var client = new RestClient("https://cdn.emnify.net/api/v1/service_profile/1234/d2d");
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"mode\": \"forward_to_backend\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Forward To Backend
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["mode": "forward_to_backend"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://cdn.emnify.net/api/v1/service_profile/1234/d2d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```

### Disable Device-To-Device

**Request**

```json
{
  "mode": "disabled"
}
```

**Response**

```json
{
  "service_profile_id": 1234,
  "mode": "disabled",
  "modified_at": "2026-08-19T10:00:00Z"
}
```

**SDK Code**

```python Disable Device-To-Device
import requests

url = "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

payload = { "mode": "disabled" }
headers = {
    "Authorization": "Bearer <token>",
    "Content-Type": "application/json"
}

response = requests.put(url, json=payload, headers=headers)

print(response.json())
```

```javascript Disable Device-To-Device
const url = 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d';
const options = {
  method: 'PUT',
  headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
  body: '{"mode":"disabled"}'
};

try {
  const response = await fetch(url, options);
  const data = await response.json();
  console.log(data);
} catch (error) {
  console.error(error);
}
```

```go Disable Device-To-Device
package main

import (
	"fmt"
	"strings"
	"net/http"
	"io"
)

func main() {

	url := "https://cdn.emnify.net/api/v1/service_profile/1234/d2d"

	payload := strings.NewReader("{\n  \"mode\": \"disabled\"\n}")

	req, _ := http.NewRequest("PUT", url, payload)

	req.Header.Add("Authorization", "Bearer <token>")
	req.Header.Add("Content-Type", "application/json")

	res, _ := http.DefaultClient.Do(req)

	defer res.Body.Close()
	body, _ := io.ReadAll(res.Body)

	fmt.Println(res)
	fmt.Println(string(body))

}
```

```ruby Disable Device-To-Device
require 'uri'
require 'net/http'

url = URI("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")

http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true

request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n  \"mode\": \"disabled\"\n}"

response = http.request(request)
puts response.read_body
```

```java Disable Device-To-Device
import com.mashape.unirest.http.HttpResponse;
import com.mashape.unirest.http.Unirest;

HttpResponse<String> response = Unirest.put("https://cdn.emnify.net/api/v1/service_profile/1234/d2d")
  .header("Authorization", "Bearer <token>")
  .header("Content-Type", "application/json")
  .body("{\n  \"mode\": \"disabled\"\n}")
  .asString();
```

```php Disable Device-To-Device
<?php
require_once('vendor/autoload.php');

$client = new \GuzzleHttp\Client();

$response = $client->request('PUT', 'https://cdn.emnify.net/api/v1/service_profile/1234/d2d', [
  'body' => '{
  "mode": "disabled"
}',
  'headers' => [
    'Authorization' => 'Bearer <token>',
    'Content-Type' => 'application/json',
  ],
]);

echo $response->getBody();
```

```csharp Disable Device-To-Device
using RestSharp;

var client = new RestClient("https://cdn.emnify.net/api/v1/service_profile/1234/d2d");
var request = new RestRequest(Method.PUT);
request.AddHeader("Authorization", "Bearer <token>");
request.AddHeader("Content-Type", "application/json");
request.AddParameter("application/json", "{\n  \"mode\": \"disabled\"\n}", ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
```

```swift Disable Device-To-Device
import Foundation

let headers = [
  "Authorization": "Bearer <token>",
  "Content-Type": "application/json"
]
let parameters = ["mode": "disabled"] as [String : Any]

let postData = JSONSerialization.data(withJSONObject: parameters, options: [])

let request = NSMutableURLRequest(url: NSURL(string: "https://cdn.emnify.net/api/v1/service_profile/1234/d2d")! as URL,
                                        cachePolicy: .useProtocolCachePolicy,
                                    timeoutInterval: 10.0)
request.httpMethod = "PUT"
request.allHTTPHeaderFields = headers
request.httpBody = postData as Data

let session = URLSession.shared
let dataTask = session.dataTask(with: request as URLRequest, completionHandler: { (data, response, error) -> Void in
  if (error != nil) {
    print(error as Any)
  } else {
    let httpResponse = response as? HTTPURLResponse
    print(httpResponse)
  }
})

dataTask.resume()
```