curl --request PUT \
--url https://melso.ai/api/workspaces/{id}/private-network \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"provider": "<string>",
"client_id": "<string>",
"client_secret": "<string>",
"tags": [
"<string>"
],
"login_server": "<string>",
"auth_key": "<string>",
"accept_routes": true,
"accept_dns": true,
"enabled": true
}
'import requests
url = "https://melso.ai/api/workspaces/{id}/private-network"
payload = {
"provider": "<string>",
"client_id": "<string>",
"client_secret": "<string>",
"tags": ["<string>"],
"login_server": "<string>",
"auth_key": "<string>",
"accept_routes": True,
"accept_dns": True,
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
provider: '<string>',
client_id: '<string>',
client_secret: '<string>',
tags: ['<string>'],
login_server: '<string>',
auth_key: '<string>',
accept_routes: true,
accept_dns: true,
enabled: true
})
};
fetch('https://melso.ai/api/workspaces/{id}/private-network', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://melso.ai/api/workspaces/{id}/private-network",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'provider' => '<string>',
'client_id' => '<string>',
'client_secret' => '<string>',
'tags' => [
'<string>'
],
'login_server' => '<string>',
'auth_key' => '<string>',
'accept_routes' => true,
'accept_dns' => true,
'enabled' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://melso.ai/api/workspaces/{id}/private-network"
payload := strings.NewReader("{\n \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\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(string(body))
}HttpResponse<String> response = Unirest.put("https://melso.ai/api/workspaces/{id}/private-network")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://melso.ai/api/workspaces/{id}/private-network")
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 \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"private_network": {
"provider": "<string>",
"enabled": true,
"client_id": "<string>",
"tags": [
"<string>"
],
"login_server": "<string>",
"accept_routes": true,
"accept_dns": true,
"generation": 123,
"configured_by": "<string>",
"configured_at": "2023-11-07T05:31:56Z",
"verified_at": "2023-11-07T05:31:56Z",
"last_error": "<string>"
}
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Put workspace private network
Workspace owner/admin (a person), or an admin API key. configured_by is then the key’s identity.
Request: For Tailscale: provider:"tailscale", client_id:string, client_secret?:string (starts with tskey-client-), tags:string[] (1–20 tags, each matching tag:[a-zA-Z][a-zA-Z0-9-]*), accept_routes?:boolean, accept_dns?:boolean, enabled?:boolean. For Headscale: provider:"headscale", login_server:string (an https:// origin with no path, credentials, query or fragment), auth_key?:string (20–512 characters, no whitespace), accept_routes?:boolean, accept_dns?:boolean, enabled?:boolean. Leaving out client_secret or auth_key keeps the stored one while the provider stays the same; switching provider needs a new one. A left-out switch keeps its saved value, and is on for a new network. Every save increments generation.
Response: The GET shape.
Status: 200; 400 private_network_invalid (a field failed validation; error names it); 403 insufficient permissions for a member who is not an owner or admin, this endpoint is only available to human actors for a credential that is neither a person’s nor an admin API key, or workspace_key_scope for a tasks API key; 422 private_network_rejected (Tailscale refused the OAuth client, or could not be reached to check it; nothing changed); 503 when the server has no Secrets keyring to seal the secret. A Tailscale save that changes the provider, client ID, secret or tags is checked first: Melso mints a one-minute, single-use key for the tags with the OAuth client and deletes it at once. Saving the same credential again, for example to turn the network on or off, does not check it again. Authentication and resource-access errors follow Overview.
curl --request PUT \
--url https://melso.ai/api/workspaces/{id}/private-network \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"provider": "<string>",
"client_id": "<string>",
"client_secret": "<string>",
"tags": [
"<string>"
],
"login_server": "<string>",
"auth_key": "<string>",
"accept_routes": true,
"accept_dns": true,
"enabled": true
}
'import requests
url = "https://melso.ai/api/workspaces/{id}/private-network"
payload = {
"provider": "<string>",
"client_id": "<string>",
"client_secret": "<string>",
"tags": ["<string>"],
"login_server": "<string>",
"auth_key": "<string>",
"accept_routes": True,
"accept_dns": True,
"enabled": True
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
provider: '<string>',
client_id: '<string>',
client_secret: '<string>',
tags: ['<string>'],
login_server: '<string>',
auth_key: '<string>',
accept_routes: true,
accept_dns: true,
enabled: true
})
};
fetch('https://melso.ai/api/workspaces/{id}/private-network', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://melso.ai/api/workspaces/{id}/private-network",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'provider' => '<string>',
'client_id' => '<string>',
'client_secret' => '<string>',
'tags' => [
'<string>'
],
'login_server' => '<string>',
'auth_key' => '<string>',
'accept_routes' => true,
'accept_dns' => true,
'enabled' => true
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://melso.ai/api/workspaces/{id}/private-network"
payload := strings.NewReader("{\n \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\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(string(body))
}HttpResponse<String> response = Unirest.put("https://melso.ai/api/workspaces/{id}/private-network")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://melso.ai/api/workspaces/{id}/private-network")
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 \"provider\": \"<string>\",\n \"client_id\": \"<string>\",\n \"client_secret\": \"<string>\",\n \"tags\": [\n \"<string>\"\n ],\n \"login_server\": \"<string>\",\n \"auth_key\": \"<string>\",\n \"accept_routes\": true,\n \"accept_dns\": true,\n \"enabled\": true\n}"
response = http.request(request)
puts response.read_body{
"private_network": {
"provider": "<string>",
"enabled": true,
"client_id": "<string>",
"tags": [
"<string>"
],
"login_server": "<string>",
"accept_routes": true,
"accept_dns": true,
"generation": 123,
"configured_by": "<string>",
"configured_at": "2023-11-07T05:31:56Z",
"verified_at": "2023-11-07T05:31:56Z",
"last_error": "<string>"
}
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}{
"error": "<string>",
"code": "<string>"
}Authorizations
Company API key (mwk_) or personal access token (mel_). A PAT requires X-Workspace-ID on company-scoped routes. An API key implies its own company.
Headers
Company UUID for a personal token on company-scoped operations. A company API key already binds its company.
Path Parameters
id from the corresponding authorized response.
Body
Response
The GET shape.
Show child attributes
Show child attributes