Tunnel Tags

Durable, account-owned labels attached to a tunnel. These are the editable counterpart to the ephemeral agent-reported tags returned inside the agents[] array on GET /v1/tunnels/{uuid} — agent-reported tags are rewritten on every reconnect, whereas these survive disconnect/reconnect because they're keyed by the stable tunnel record.

Tags are normalized server-side: trimmed, lowercased (so Prod and prod collapse to one), and truncated to 64 characters. A single tunnel may carry at most 20 tags.

Account scope: tags belong to your active account — a tunnel must belong to that account before its tags can be read or written. Use switch account to act in a different account.

List Account Tags

GET /v1/tunnels/tags

Returns the active account's full distinct set of durable tags — used to seed a fleet-filter dropdown without paging through every tunnel.

Response (200 OK)

tags string[]
Distinct tags across all of the account's tunnels, sorted alphabetically. Always present (empty array when none).

Add a Tag

POST /v1/tunnels/{uuid}/tags

Adds a durable tag to a tunnel the account owns. Idempotent — re-adding an existing tag is a no-op and does not count against the per-tunnel cap. Returns the tunnel's full tag set after the add.

Path parameters

uuid string (uuid) Req
The tunnel's uuid from /tunnels.

Deprecated: the legacy integer id is still accepted in the path until the sunset, answered with Deprecation and Sunset headers. Use the uuid.

Request body

tag string Req
The tag to add. Normalized (trimmed, lowercased, capped at 64 chars). Must not be empty after normalization.

Response (200 OK)

tunnel_uuid string (uuid)
The tunnel the tags belong to.
tags string[]
The tunnel's full, sorted tag set after the add.

Deprecated: until the sunset this response also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Remove a Tag

DELETE /v1/tunnels/{uuid}/tags/{tag}

Deletes a durable tag from a tunnel the account owns. Idempotent — deleting a tag that isn't present is still a 200 with the resulting set. Returns the tunnel's full tag set after the delete.

Path parameters

uuid string (uuid) Req
The tunnel's uuid.
tag string Req
The tag to remove. Normalized the same way as on add (trimmed, lowercased) before matching.

Deprecated: the legacy integer id is still accepted in the path until the sunset, answered with Deprecation and Sunset headers. Use the uuid.

Response (200 OK)

tunnel_uuid string (uuid)
The tunnel the tags belong to.
tags string[]
The tunnel's full, sorted tag set after the delete.

Deprecated: until the sunset this response also carries the legacy integer id and *_id fields. Don't use them; read uuid and the *_uuid fields.

Errors

400 Bad Request
Invalid request body, empty tag, (on add) the 20-tag-per-tunnel limit reached, or an integer id after the sunset (integer_id_unsupported).
401 Unauthorized
Missing auth.
404 Not Found
The tunnel doesn't exist or doesn't belong to your active account (another account's uuid reads exactly like an unknown one).
Request — list account tags
curl -X GET "https://api.ngris.com/v1/tunnels/tags" \ -H "X-API-KEY: <your_api_key>"
Response — list (200 OK)
{ "tags": ["api", "prod", "staging"] }
Request — add a tag
curl -X POST "https://api.ngris.com/v1/tunnels/019ab73a-b951-7031-aea5-1435da834122/tags" \ -H "X-API-KEY: <your_api_key>" \ -H "Content-Type: application/json" \ -d '{"tag": "prod"}'
Response — add (200 OK)
{ "tunnel_uuid": "019ab73a-b951-7031-aea5-1435da834122", "tags": ["api", "prod"] }
Request — remove a tag
curl -X DELETE "https://api.ngris.com/v1/tunnels/019ab73a-b951-7031-aea5-1435da834122/tags/prod" \ -H "X-API-KEY: <your_api_key>"
Response — remove (200 OK)
{ "tunnel_uuid": "019ab73a-b951-7031-aea5-1435da834122", "tags": ["api"] }
Was this helpful?
On this page
Tunnel Tags
Was this helpful?