Browse documentation

Tunnels

Create tunnels, change their configuration and choose which device runs them.

List tunnels

GET/tunnelstunnels:read

Returns tunnels newest first. Use limit and cursor for pagination.

Shell
curl "https://api.portwarp.com/v2/tunnels?limit=25" \
  -H "Authorization: Bearer $PORTWARP_API_KEY"

Create a tunnel

POST/tunnelstunnels:write

Creates a tunnel and returns it with status 201. Idempotency required.

FieldUse
local_portRequired. Local service port, 1 to 65535.
protocoltcp, udp, both or http. Default: tcp.
local_hostLocal target visible to the client. Default: 127.0.0.1.
nameOptional display name.
region / countryOptional placement preference.
game_preset_idPreset ID returned by GET /presets.
subdomainOptional requested platform subdomain.
pro_networkUse PRO Network when true. Defaults to true for eligible accounts.
http_ssl_enabledEnable managed HTTPS for HTTP tunnels.
http_basic_auth_*Optional username and password protection for HTTP tunnels.
device_idsOptional device allowlist. An empty array allows any authorized device.
extra_portsOptional array of {label, local_port, protocol}.
JSON body
{
  "name": "Minecraft",
  "protocol": "tcp",
  "local_port": 25565,
  "device_ids": ["DEVICE_ID"],
  "extra_ports": [{"label": "Query", "local_port": 25565, "protocol": "udp"}]
}

Get, update or delete a tunnel

GET/tunnels/{tunnel_id}tunnels:read

Returns one tunnel, including its public address, current device, authorized devices and extra ports.

PATCH/tunnels/{tunnel_id}tunnels:write

Updates only supplied fields. Supported fields: name, local_host, local_port, http_ssl_enabled, HTTP basic-auth fields, idle_timeout, buffer_size and pro_network. Use the domain endpoints below for custom domains.

JSON body
{"name":"Production API","local_port":8080}
DELETE/tunnels/{tunnel_id}tunnels:write

Permanently removes the tunnel. Idempotency required.

Choose allowed devices

PUT/tunnels/{tunnel_id}/devicestunnels:write

Replaces the full device allowlist. Idempotency required.

BodyBehavior
{"device_ids":[]}Any authorized device may run the tunnel.
One IDOnly that device may run it.
Several IDsAny listed device may run it, but never simultaneously.

Start, stop or restart

POST/tunnels/{tunnel_id}/actions/starttunnels:control

Starts the tunnel on device_id and returns a 202 operation. Set handoff to true only to stop the current executor and continue on another device. Idempotency required.

JSON body
{"device_id":"DEVICE_ID","handoff":false}

The device must be online, allowed by the tunnel and locally enabled for remote control. If another device is running the tunnel, start returns 409 tunnel_already_running unless handoff is true.

POST/tunnels/{tunnel_id}/actions/stoptunnels:control

Stops the current executor and returns a 202 operation. Send an empty JSON object. Idempotency required.

POST/tunnels/{tunnel_id}/actions/restarttunnels:control

Restarts the tunnel on its current executor and returns a 202 operation. Send an empty JSON object. Idempotency required.

Extra ports

GET/tunnels/{tunnel_id}/extra-portstunnels:read

Lists additional port mappings for the tunnel.

POST/tunnels/{tunnel_id}/extra-portstunnels:write

Adds one port mapping. Idempotency required.

JSON body
{"label":"Query","local_port":25565,"protocol":"udp"}
DELETE/tunnels/{tunnel_id}/extra-ports/{port_id}tunnels:write

Removes one extra port. Idempotency required.

Custom domain

GET/tunnels/{tunnel_id}/domaintunnels:read

Returns the current custom-domain status and DNS information.

POST/tunnels/{tunnel_id}/domain/actions/verifytunnels:write

Checks whether the domain's CNAME is ready. Send {"domain":"play.example.com"}. Idempotency required.

PUT/tunnels/{tunnel_id}/domaintunnels:write

Assigns a verified domain. Send {"domain":"play.example.com"}. Idempotency required.

DELETE/tunnels/{tunnel_id}/domaintunnels:write

Removes the custom domain. Idempotency required.

Firewall and GeoIP

GET/tunnels/{tunnel_id}/firewalltunnels:read

Lists enabled IP allow/block rules.

PUT/tunnels/{tunnel_id}/firewalltunnels:write

Replaces every firewall rule. Send rules with rule_type (whitelist or blacklist), one of ip_address/ip_cidr, and optional description. Idempotency required.

JSON body
{
  "rules": [
    {
      "rule_type": "whitelist",
      "ip_cidr": "203.0.113.0/24",
      "description": "Office"
    }
  ]
}
GET/tunnels/{tunnel_id}/geoiptunnels:read

Lists enabled country rules.

PUT/tunnels/{tunnel_id}/geoiptunnels:write

Replaces every country rule. Use two-letter ISO country codes and allow or block. Idempotency required.

JSON body
{
  "rules": [
    {"country_code": "BR", "action": "allow"}
  ]
}

Placement, usage and sessions

POST/tunnels/{tunnel_id}/movetunnels:write

Moves the tunnel to a node returned by GET /nodes. Send {"node_id":"NODE_ID"}. Returns 202. Idempotency required.

GET/tunnels/{tunnel_id}/usagetunnels:read

Returns bandwidth totals for today and the current month.

GET/tunnels/{tunnel_id}/sessionstunnels:read

Returns recent runtime sessions with device, timestamps, duration, traffic and end reason. Accepts limit from 1 to 100 and an opaque cursor.