Skip to content

List your API keys

GET
/keys
curl --request GET \
--url https://app.tunnelhq.com/api/v1/keys \
--header 'X-API-Key: <X-API-Key>'

Your own keys, newest first. A workspace key lists your keys in its workspace; an account-wide key lists all of yours. Secrets are never returned.

Need an API key? See Getting an API key.

Your keys.

Media typeapplication/json
object
keys
required
Array<object>

One of your API keys, without its secret. Note the camelCase field names.

object
id
required
integer
name
required
string
userID
required

The key’s owner.

integer
organizationId
required

The workspace the key belongs to; null for an account-wide key.

integer | null
createdDate
required

In UTC, as YYYY-MM-DD HH:MM:SS.

string
active
required

Whether the key is switched on: true/false when just created, 1/0 when listed.

boolean | integer
expires
required

When the key stops working, in UTC, as YYYY-MM-DD HH:MM:SS. null if never.

string | null
lastUsedAt
required
string | null
status
required

inactive means switched off.

string
Allowed values: active inactive expired
total
required
integer
Example
{
"keys": [
{
"id": 41,
"name": "Production CI",
"userID": 7,
"organizationId": 3,
"createdDate": "2026-09-02 10:15:00",
"active": 1,
"expires": null,
"lastUsedAt": "2026-09-25 14:29:58",
"status": "active"
}
],
"total": 1
}
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 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>"
}

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"
}