TL;DR: Nodetonet has a small, stable REST API. Until official SDKs ship you can write a working client in any language in about 20 lines — and this page gives you those 20 lines for Python, Node.js, Go, and Ruby, ready to copy-paste.
This page collects short, working SDK-style examples for the four languages we get asked about most: Python, Node.js, Go, and Ruby. Every example creates a proxy or tunnel against POST /api/v1/proxies, prints the resulting URL, and is short enough to drop into a repo as nodetonet.py, nodetonet.mjs, and so on. If you want more context on what you are calling into, start with REST API: your first call and the overview at understanding your API key.
A note on scope: no first-party SDKs exist yet on PyPI, npm, pkg.go.dev, or RubyGems. The REST API is small — one primary resource, four verbs — so the gap between "no SDK" and "a useful SDK" is roughly 20 lines of code. Once an official SDK lands you will be able to pip install nodetonet and get the same shape with retry logic, pagination, and typed errors baked in.
What the API looks like at a glance
Before diving into language examples, here is the shape of the core resource. Every client below maps to these four operations:
| Verb | Path | What it does | Auth |
|---|---|---|---|
POST | /api/v1/proxies | Create a proxy / tunnel | Bearer token |
GET | /api/v1/proxies | List your proxies | Bearer token |
GET | /api/v1/proxies/:id | Inspect one proxy | Bearer token |
DELETE | /api/v1/proxies/:id | Delete a proxy | Bearer token |
Your Bearer token lives under /tokens in the panel — keep it in an environment variable, never hard-code it. A POST body takes subdomain, target_host, and target_port; the response body gives you back id and url. That is the whole surface area. The full machine-readable spec lives at /openapi.json.
1 · Python
One file, one dependency (requests). Reads the token from an env var so it can be committed safely. Suitable for scripts, Jupyter notebooks, Django apps, or any Python automation pipeline — for example the patterns shown in programmatic tunnel creation in Python.
# nodetonet.py
import os, requests
BASE = "https://nodetonet.com/api/v1"
TOKEN = os.environ["NTN_TOKEN"]
H = {"Authorization": f"Bearer {TOKEN}",
"Content-Type": "application/json"}
def create_proxy(subdomain, target_port, target_host="127.0.0.1"):
r = requests.post(f"{BASE}/proxies", json={
"subdomain": subdomain,
"target_host": target_host,
"target_port": target_port,
}, headers=H, timeout=10)
r.raise_for_status()
return r.json()
def delete_proxy(proxy_id):
r = requests.delete(f"{BASE}/proxies/{proxy_id}", headers=H, timeout=10)
r.raise_for_status()
if __name__ == "__main__":
p = create_proxy("alice-dev", 3000)
print(p["url"])
That is a functional Python client. Use it as-is, wrap it in a class, or paste it into a Jupyter notebook for one-off integrations. The raise_for_status() call surfaces errors immediately rather than silently swallowing a 4xx.
2 · Node.js
Zero npm dependencies — uses Node 18+ built-in fetch. Drop into a project as nodetonet.mjs. Works equally well in a serverless function, a build script, or a Next.js API route during local development.
// nodetonet.mjs
const BASE = 'https://nodetonet.com/api/v1';
const TOKEN = process.env.NTN_TOKEN;
async function api(path, opts = {}) {
const res = await fetch(BASE + path, {
...opts,
headers: {
Authorization: 'Bearer ' + TOKEN,
'Content-Type': 'application/json',
...(opts.headers || {}),
},
});
if (!res.ok) throw new Error(res.status + ' ' + (await res.text()));
return res.json();
}
export const createProxy = (subdomain, port, host = '127.0.0.1') =>
api('/proxies', { method: 'POST', body: JSON.stringify({
subdomain, target_host: host, target_port: port,
})});
export const deleteProxy = (id) =>
api('/proxies/' + id, { method: 'DELETE' });
const p = await createProxy('alice-dev', 3000);
console.log(p.url);
3 · Go
Standard library only — no third-party packages needed. Pair it with a long-running daemon or a one-shot CLI. The struct tags mirror the JSON response shape, so unmarshalling is direct.
// nodetonet.go
package main
import (
"bytes"
"encoding/json"
"fmt"
"net/http"
"os"
)
type Proxy struct {
ID string `json:"id"`
URL string `json:"url"`
}
func CreateProxy(sub string, port int) (*Proxy, error) {
body, _ := json.Marshal(map[string]interface{}{
"subdomain": sub, "target_host": "127.0.0.1", "target_port": port,
})
req, _ := http.NewRequest("POST",
"https://nodetonet.com/api/v1/proxies", bytes.NewReader(body))
req.Header.Set("Authorization", "Bearer "+os.Getenv("NTN_TOKEN"))
req.Header.Set("Content-Type", "application/json")
res, err := http.DefaultClient.Do(req)
if err != nil { return nil, err }
defer res.Body.Close()
if res.StatusCode >= 300 {
return nil, fmt.Errorf("status %d", res.StatusCode)
}
p := &Proxy{}
return p, json.NewDecoder(res.Body).Decode(p)
}
func main() {
p, _ := CreateProxy("alice-dev", 3000)
fmt.Println(p.URL)
}
That is the whole Go client — no go.mod beyond module nodetonet. The idiomatic Go approach pairs well with context.WithTimeout if you need deadline propagation in a larger service.
4 · Ruby
Standard library again — uses net/http and json. Drop into a Rails app or a Sinatra script without adding a gem dependency.
# nodetonet.rb
require 'net/http'
require 'json'
require 'uri'
TOKEN = ENV.fetch('NTN_TOKEN')
def create_proxy(subdomain, target_port, target_host: '127.0.0.1')
uri = URI('https://nodetonet.com/api/v1/proxies')
http = Net::HTTP.new(uri.host, uri.port)
http.use_ssl = true
req = Net::HTTP::Post.new(uri)
req['Authorization'] = "Bearer #{TOKEN}"
req['Content-Type'] = 'application/json'
req.body = {
subdomain: subdomain,
target_host: target_host,
target_port: target_port,
}.to_json
res = http.request(req)
raise "HTTP #{res.code}: #{res.body}" unless res.is_a?(Net::HTTPSuccess)
JSON.parse(res.body)
end
if __FILE__ == $PROGRAM_NAME
puts create_proxy('alice-dev', 3000)['url']
end
5 · Error handling that scales
The DIY clients above surface errors on a non-2xx, but they do not retry. Once you start using them in production, wrap the call in a retry with exponential backoff: 409 means the subdomain is already taken (regenerate), 429 means rate-limited (back off), 5xx is transient (retry up to three times). Treat 401 as a permanent failure — your token is wrong or revoked.
# Python — retry helper
import time
def create_with_retry(sub, port, attempts=3):
for i in range(attempts):
try:
return create_proxy(sub, port)
except requests.HTTPError as e:
code = e.response.status_code
if code == 409:
sub = f"{sub}-{int(time.time()) % 1000}"
elif code in (429, 500, 502, 503, 504):
time.sleep(2 ** i)
else:
raise
raise RuntimeError("gave up after retries")
For a full worked example of production-grade error handling alongside tunnel lifecycle management, see programmatic tunnel creation in Python. For operational tips on keeping proxies healthy in automation, see monitoring your tunnel health.
6 · Generating a typed client from the OpenAPI spec
If you need a language not covered above — Java, C#, Swift, Kotlin, Rust, PHP — use openapi-generator against the spec we publish at /openapi.json. The generator produces a complete typed client with models, request builders, and basic error handling:
npx @openapitools/openapi-generator-cli generate -i https://nodetonet.com/openapi.json -g python -o ./nodetonet-client
Swap python for any of the generator's supported targets. The generated code is verbose but correct, and gives you IDE autocomplete and request-shape validation while you wait for the official SDK.
7 · Official SDKs are on the roadmap
The REST API is, and will remain, the canonical interface. SDKs are conveniences on top: they handle retries, pagination, structured errors, and let your IDE autocomplete the request shape. We are shipping them in this order:
- Python —
pip install nodetonet, Q3 2026. - Node.js / TypeScript —
npm i nodetonet, Q3 2026 (typed, ESM + CJS). - Go —
go get github.com/nodetonet/sdk-go, Q4 2026. - Ruby —
gem install nodetonet, Q4 2026.
Migration from the DIY wrappers above to the official SDKs will be a one-line import swap — the function names and field names are intentionally aligned. See the changelog and the roadmap to track progress.
Related resources
- REST API: your first call — a step-by-step walkthrough with curl before you write any code.
- Understanding your API key — scopes, rotation, and security practice.
- Programmatic tunnel creation in Python — a longer real-world example with lifecycle management.
- Monitoring your tunnel health — polling and webhook patterns for production.
- Webhooks for IP change events — event-driven automation when a proxy IP changes.
- HTTP tunnels and mobile proxies — the two main resources you will create via the API.
- Proxy checker tool — verify a proxy is live before handing it to your application.
- Download the agent apps — the Android and Windows agents that power the devices behind the API.