Monitor a TCP port
What it does
Section titled “What it does”A TCP monitor connects to a host and port on each check interval and confirms the connection succeeds — no HTTP request, no response body, just “can we open a socket.” Use it for databases, SSH, SMTP, or any other service that doesn’t speak HTTP.
Set it up in the app
Section titled “Set it up in the app”- In the dashboard, click Add to create a monitor.
- Set Type to TCP.
- Enter a Name (for example
prod-postgres). - Enter the target in the Host:port field, for example
db.example.com:5432. - Click Add.

The dashboard’s port field is free text with a hint listing a curated set of common ports — see Plan limits below for why the real, complete allowed list is longer than the hint.
Do the same through the API or MCP
Section titled “Do the same through the API or MCP”curl -X POST https://api.uptimemonitoring.com/api/v1/monitors \ -H "Authorization: Bearer $UPTIMEMONITORING_API_KEY" \ -H "Content-Type: application/json" \ -d '{ "name": "prod-postgres", "url": "tcp://db.example.com:5432", "type": "tcp" }'The url field takes host:port or tcp://host:port — no path, query, or scheme other than tcp://. expected_status and body_match are ignored for type: "tcp". TCP and ping monitors return state.status: "unknown" in the create response; the next scheduled check fills in up or down. See Monitors for the full create/update/delete reference.
Through MCP, ask your agent to create a monitor and give it the host:port target and type: tcp; the create_monitor tool accepts the same url/type shape. See Use UptimeMonitoring through MCP.
Plan limits
Section titled “Plan limits”The account’s real, complete allowed-port list comes from um-api’s checker.AllowedTCPPortsList() (internal/checker/ssrf.go), backed by the allowedTCPPorts map in internal/checker/checker.go. Don’t treat the list below as fixed — it’s a snapshot of what AllowedTCPPortsList() returns as of this writing, not a forward compatibility promise:
21, 22, 25, 80, 110, 143, 443, 465, 587, 993, 995, 2222,3000, 3306, 5000, 5432, 6379, 8000, 8080, 8443, 8888, 27017The dashboard’s port hint shows a narrower, curated subset of eight common ports (80, 443, 8080, 8443, 3000, 5000, 8000, 8888) as a convenience — it’s not the complete list, and it doesn’t validate the port itself. The API accepts any port from the complete list above, whether or not the dashboard’s hint mentions it.
If you create a monitor with a port outside the complete list, the API rejects it with a 400 whose message echoes the same list:
{"error": "port 11211 is not allowed for TCP monitors; allowed ports: 21, 22, 25, 80, 110, 143, 443, 465, 587, 993, 995, 2222, 3000, 3306, 5000, 5432, 6379, 8000, 8080, 8443, 8888, 27017"}See Monitors for the shared monitor limits (name length, monitor count caps).
Troubleshooting
Section titled “Troubleshooting”“port is not allowed for TCP monitors.” The port you targeted isn’t on the allowed list above. Check the exact port number in your url — a typo’d port (like a container’s internal port instead of its published one) is a common cause.
The monitor shows unknown right after creation. That’s expected for TCP monitors — the immediate test check that HTTP monitors get doesn’t apply here. Wait for the next scheduled check (up to interval_sec seconds later).
Connection refused or timeout, but the port is allowed. The allowed-port check only confirms the port is on UptimeMonitoring’s list — it doesn’t guarantee the target host accepts connections on it. Confirm the service is actually listening and reachable from the public internet; UptimeMonitoring’s probes can’t reach hosts behind a private network or firewall allowlist that excludes them.