Skip to content

Link a tunnel or check to a server

POST
/hosts/{id}/link
curl --request POST \
--url https://dev.tunnelhq.com/api/v1/hosts/hst_7/link \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <X-API-Key>' \
--header 'X-Project-Id: prj_12' \
--data '{ "monitor_id": "srv_81" }'

Links a tunnel or check to the server by hand, for when TunnelHQ can’t tell from the address, such as behind a load balancer or a CDN. Unlink undoes it.

It needs a role that can edit monitors (Owner, Admin and Manager have it by default).

Need an API key? See Getting an API key.

id
required
string

The server, as hst_7 or 7.

Example
hst_7
X-Project-Id
required
string

The project, as prj_12 or 12. A workspace key can only reach its own workspace’s projects.

Example
prj_12
Media typeapplication/json
object
monitor_id
required

The tunnel or check, as srv_81 or 81.

string
Example
{
"monitor_id": "srv_81"
}

The server, with its linked tunnels and checks after the change.

Media typeapplication/json
object
id
string
name

The name a person gave it, else its hostname.

string
hostname
string | null
group
string | null
status

Online: a report in the last 60 seconds. Stale: 60 to 90 seconds. Offline: more than 90 seconds, or never.

string
Allowed values: online stale offline
os
string | null
agent_version
string | null
agent_latest

The agent version TunnelHQ hands out now.

string | null
agent_update

A newer release than this server’s agent is out.

boolean
agent_can_update

The agent has the updater, so TunnelHQ can update it. False for one installed before updates came, or with --no-updates.

boolean
agent_auto_update

TunnelHQ updates this agent by itself, a day after each release.

boolean
agent_updating

The version on its way

string | null
agent_update_result

How the last update went, as the agent reported it.

object
version
string
from
string
ok
boolean
message
string
at
string
public_ip
string | null
public_ip6
string | null
country

The country of the server’s own address, as the agent reports it (agent 1.4.0 and later).

string | null
last_report_at
string | null format: date-time
seconds_since_report
integer | null
cpu_percent
number | null
memory_percent
number | null
disk_percent
number | null
load_1
number | null
health_score

0 to 100, where 0 is best: 0 means no sign of trouble for users, 100 that users are suffering now.

number | null
balance_score

0 to 100: how little room is left for more users (100: none).

number | null
load_score

0 to 100: how busy the server is overall.

number | null
packet_drop_rate
number | null
users
integer | null
protocols

Users per VPN protocol.

object | null
services

The VPN services it watches.

object | null
hosting_services

Web servers, databases and the like, with their state (agent 1.6.0 and later).

object | null
monitors

Its linked tunnels and checks that you can see.

Array<object>
object
id
string
name
string
family
string
via

How it was linked: by hand, by address, or by hostname.

string
Allowed values: manual address hostname
open_incidents
integer
tags
Array<string>
memory_used_mb
number | null
memory_total_mb
number | null
swap_percent
number | null
load_5
number | null
load_15
number | null
steal_percent
number | null
iowait_percent
number | null
disk_read_bytes_per_sec
number | null
disk_write_bytes_per_sec
number | null
disks

Every disk the agent reports.

Array<object> | null
object
programs

The biggest programs by memory, up to 8.

Array<object>
object
name
string
memory_mb
number
change_24h_mb
number | null
running_seconds
integer | null
countries

Users per country, biggest first, on a VPN server. Countries under 11 users are counted under “Other”.

Array<object> | null
object
country
string
users
integer
system
object
os
string | null
kernel
string | null
arch
string | null
cpu_model
string | null
cpu_count
integer | null
memory_total_mb
number | null
uptime_seconds
integer | null
last_boot_at
string | null
network_interface
string | null
bandwidth_capacity_mbps
number | null
ips
Array<string>
country
string | null
alerts
object
offline
object
enabled
boolean
after_seconds
integer
service
object
enabled
boolean
after_seconds
integer
country
object
enabled
boolean
cert
object
enabled
boolean
days
integer
Allowed values: 7 14 21 30
resources
Array<object>
object
metric
string
Allowed values: cpu memory disk
above
number
>= 1 <= 100
for_seconds
integer
>= 60 <= 3600
enabled
boolean
incidents

Its open incidents.

Array<object>
object
id
string
kind
string
Allowed values: offline service resource country cert
subject

The service, metric (cpu, memory, disk) or country code, when the kind has one.

string | null
state
string
Allowed values: open resolved
opened_at
string | null format: date-time
sent_at

When its message went. Servers failing together share one message.

string | null format: date-time
resolved_at
string | null format: date-time
servers
Array<object>
object
id
string
name
string
back
boolean
detail

What the message was built from, such as a certificate’s expiry and names.

object
uninstall_command

The command that removes the agent from the machine.

string
certificate

The certificate the server’s OpenConnect service serves, read by the agent every hour (agent 1.8.0). Null when it serves none. There is no revocation check.

object
not_after
string format: date-time
not_before
string | null format: date-time
days_left
integer | null
names
Array<string>
subject

Its common name.

string | null
issuer
string | null
serial
string | null
key
string | null
signature
string | null
tls_version
string | null
chain

Server certificate first, then the ones above it.

Array<object>
object
name
string
not_after
string
renewed_on_disk

True when the file on disk was renewed and OpenConnect still serves the old one.

boolean | null
trusted
boolean | null
trust_problem
string | null
first_seen

When TunnelHQ first saw this certificate.

string | null
checks

Each check passes (true), fails (false) or is not known (null).

Array<object>
object
key
string
Allowed values: validity hostname trusted chain tls strength disk
ok
boolean | null
Example
{
"id": "hst_7",
"status": "online",
"monitors": [
{
"id": "srv_81",
"family": "tunnel",
"via": "manual"
}
],
"alerts": {
"offline": {
"enabled": true,
"after_seconds": 90
},
"service": {
"enabled": true,
"after_seconds": 60
},
"country": {
"enabled": false
},
"cert": {
"enabled": true,
"days": 14
},
"resources": [
{
"metric": "disk",
"above": 85,
"for_seconds": 300,
"enabled": true
}
]
},
"incidents": [
{
"id": "hin_3",
"kind": "offline",
"state": "open"
}
],
"certificate": {
"key": "RSA 2048",
"tls_version": "TLS 1.3",
"trust_problem": "self-signed",
"checks": [
{
"key": "validity"
}
]
}
}
X-RateLimit-Limit
integer

Requests the workspace’s plan allows per minute.

X-RateLimit-Remaining
integer

Requests left in the current minute.

X-RateLimit-Reset
integer

Unix time, in seconds, when the current minute ends.

The body names no tunnel or check.

Media typeapplication/json
object
error
required
boolean
code
required

The HTTP status, repeated.

integer
message
required

What went wrong.

string
details

More detail, on some errors.

retry_after

Seconds to wait, on the 429 for wrong keys.

integer
Example
{
"error": true,
"code": 400,
"message": "Send monitor_id: the tunnel or check, such as srv_81."
}

The API key is missing, wrong, expired, switched off, or no longer valid.

Media typeapplication/json
object
error
required
boolean
code
required

The HTTP status, repeated.

integer
message
required

What went wrong.

string
details

More detail, on some errors.

retry_after

Seconds to wait, on the 429 for wrong keys.

integer
Examples
{
"error": true,
"code": 401,
"message": "API key is required. Provide X-API-Key header or Authorization: Bearer <key>"
}

Your role can’t edit monitors.

Media typeapplication/json
object
error
required
boolean
code
required

The HTTP status, repeated.

integer
message
required

What went wrong.

string
details

More detail, on some errors.

retry_after

Seconds to wait, on the 429 for wrong keys.

integer
Example
{
"error": true,
"code": 403,
"message": "Changing a server needs a role that can edit monitors."
}

No such server, or no such tunnel or check that you can see in this project.

Media typeapplication/json
object
error
required
boolean
code
required

The HTTP status, repeated.

integer
message
required

What went wrong.

string
details

More detail, on some errors.

retry_after

Seconds to wait, on the 429 for wrong keys.

integer
Examples
{
"error": true,
"code": 404,
"message": "No such server in this project."
}

A usage limit was reached, or this IP address made too many requests with a wrong key.

Usage limits are per workspace and plan: per minute (Retry-After: 60), per day (Retry-After: 3600), and per month (no Retry-After). They use their own body shape. An IP address may send 10 wrong keys a minute; one more is allowed every 6 seconds. While that allowance is used up, every request from the address is refused, even one with a valid key.

Media typeapplication/json
One of:
object
error
required
string
Allowed values: Rate limit exceeded Daily limit exceeded Monthly limit exceeded
message
required
string
retry_after

Seconds to wait. Absent for the monthly limit.

integer
Examples
{
"error": "Rate limit exceeded",
"message": "Per-minute limit of 60 requests exceeded",
"retry_after": 60
}
Retry-After
integer

Seconds to wait. 60 for the per-minute limit, 3600 for the daily limit, 6 after wrong keys. Absent for the monthly limit.

Something failed on TunnelHQ’s side.

Media typeapplication/json
object
error
required
boolean
code
required

The HTTP status, repeated.

integer
message
required

What went wrong.

string
details

More detail, on some errors.

retry_after

Seconds to wait, on the 429 for wrong keys.

integer
Example
{
"error": true,
"code": 500,
"message": "Internal server error"
}