Skip to main content
POST
/
v1
/
tunnels
/
:tunnelId
/
telemetry
Ingest Telemetry
curl --request POST \
  --url https://api.example.com/v1/tunnels/:tunnelId/telemetry \
  --header 'Content-Type: application/json' \
  --data '
{
  "region": {},
  "metrics": {
    "ttl": 123,
    "opn": 123,
    "rt1Ms": {},
    "rt5Ms": {},
    "p50Ms": {},
    "p90Ms": {},
    "requests": 123,
    "errors": 123,
    "bytes": 123
  },
  "requests": [
    {
      "startedAtEpochMs": 123,
      "method": "<string>",
      "path": "<string>",
      "statusCode": 123,
      "durationMs": 123,
      "responseBytes": {},
      "error": true,
      "protocol": "<string>"
    }
  ]
}
'
{
  "ok": true,
  "code": "<string>",
  "message": "<string>",
  "details": {}
}

Authentication

Requires a valid access token in the Authorization header.

Path Parameters

tunnelId
string
required
The UUID or slug of the tunnel to submit telemetry for. Must belong to the authenticated user.

Request Body

region
string | null
The region identifier where the telemetry was captured (e.g., “US-EAST”, “EU-WEST”). Maximum 16 characters. Will be normalized to uppercase.
metrics
object
required
Aggregated metrics snapshot for the tunnel.
requests
array
required
Array of individual HTTP/WebSocket request events. Maximum 200 events per request.

Response

ok
boolean
Always returns true on successful ingestion.

Rate Limiting

This endpoint is rate limited to 1200 requests per minute per user.
Telemetry data is downsampled to create historical metrics points approximately every 10 seconds. Request logs are retained for 24 hours, and metrics history is retained for 7 days.
The requests array is limited to 200 events per call. If you have more events to submit, make multiple requests or implement batching on the client side.

Example Request

curl -X POST https://api.rs-tunnel.example.com/v1/tunnels/550e8400-e29b-41d4-a716-446655440000/telemetry \
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "region": "us-east",
    "metrics": {
      "ttl": 1523,
      "opn": 12,
      "rt1Ms": 5.2,
      "rt5Ms": 8.7,
      "p50Ms": 45.3,
      "p90Ms": 123.8,
      "requests": 1500,
      "errors": 23,
      "bytes": 5242880
    },
    "requests": [
      {
        "startedAtEpochMs": 1678901234567,
        "method": "GET",
        "path": "/api/users",
        "statusCode": 200,
        "durationMs": 42.5,
        "responseBytes": 1024,
        "error": false,
        "protocol": "http"
      },
      {
        "startedAtEpochMs": 1678901235123,
        "method": "POST",
        "path": "/api/orders",
        "statusCode": 500,
        "durationMs": 150.2,
        "responseBytes": null,
        "error": true,
        "protocol": "http"
      }
    ]
  }'

Example Response

{
  "ok": true
}

Error Responses

code
string
Error code identifier.
message
string
Human-readable error message.
details
unknown
Additional error details, if available.

Common Errors

  • 400 INVALID_TUNNEL_ID: Tunnel identifier is missing or malformed
  • 400 INVALID_INPUT: Request body failed validation (check details for specifics)
  • 404 TUNNEL_NOT_FOUND: The tunnel does not exist or does not belong to the authenticated user
  • 429 RATE_LIMIT_EXCEEDED: Too many requests (limit: 1200/minute)

Build docs developers (and LLMs) love