Skip to content
tsrelay

Receiving calls

What your app receives

Bodies arrive exactly as sent, byte for byte, so signatures from Stripe, GitHub, Svix, or Standard Webhooks verify normally. The relay adds these headers, after removing any copies the sender sent:

HeaderValue
Tsrelay-Sender-Node
The calling machine's name
Tsrelay-Sender-Tags
Its tags, comma-separated
Tsrelay-Sender-Login
Its user, if it isn't a tagged machine
Tsrelay-Sender-Public
true for a call from the internet to a public hook; such a call has no Tsrelay-Sender-Node, -Tags or -Login
Tsrelay-Hook
user/path of the hook
Tsrelay-Call-Id
Also returned to the caller, for matching logs
X-Forwarded-For, -Host, -Proto, -Prefix
The original request, for URL-signing schemes

What senders get

Your app's response goes back to the sender as it is. Errors produced by the relay itself are application/problem+json responses and carry a Tsrelay-Error header. Responses from your app are never marked, including its own 5xx. Tunnel and transport failures have statuses of their own, 561 to 565, so they can't be mistaken for your app's 502, 503 or 504; clients that don't know them treat them as 500. Senders see these:

Tsrelay-ErrorStatusMeaning
sender_forbidden403The caller has no sender grant
hook_not_found404No such hook, not in the caller's channels, or it was deleted/expired while a call was held for it
body_stalled408The sender's request body stalled past idleTimeout
body_too_large413Over the hook's maxBodyBytes, or for a call from the internet, over the relay's --funnel-max-body-bytes
rate_limited429Over the hook's rateLimit; Retry-After is the limiter's wait, rounded up to whole seconds
tunnel_unavailable561No tunnel attached within holdTimeout; Retry-After is holdTimeout, but never less than 5 s
hold_queue_full562No tunnel attached and too many calls are already waiting for one; same Retry-After
tunnel_overloaded562Too many concurrent calls on the tunnel; Retry-After: 1
tunnel_lost563The tunnel dropped mid-call
upstream_unreachable564The tunnel is up but your app isn't listening
upstream_timeout565Your app didn't answer within the hook's responseTimeout

Every response a sender gets carries Tsrelay-Call-Id, which names the call in the inspector.