# Relay & pairing

Source: https://www.pingtower.com/docs/self-hosting/relay/

How a box you run pages a phone it cannot push to. The box calls out; pingtower.com forwards; nothing calls in.

## The shape of it

1. The box mints a join code: `pingtower pair --email you@example.com`.
2. The app redeems the code against the box and gets a box-minted `ptk_` key, plus a receipt.
3. pingtower.com confirms the receipt with the box, once, at `GET /v1/pair/verify`.
4. The app writes the relay credential to the box with `PUT /v1/relay`.
5. From then on, every project on the box has a webhook integration named "pingtower.com relay". An escalation event goes out through it like any other webhook, and pingtower.com turns it into a push to the devices paired with that tenant.

The box never accepts a connection from pingtower.com beyond the one-time verify. Everything is outbound from the box, so it works from behind NAT as long as the app can reach the box's URL when it pairs.

## What the box needs

- A public URL the app can reach, with TLS in front. See [Reverse proxy](/docs/self-hosting/proxy/).
- To answer `/v1/pair/verify` from pingtower.com at pairing time.
- `-secret-key` set, so the relay credential is sealed at rest like any other integration secret.

## Seats

Each paired account is a seat. `POST /v1/pair/codes` on the box, owner or admin, mints another code; `ttl_seconds` defaults to an hour and is capped at seven days. `DELETE /v1/tenants/{tid}/pairings/{aid}` on pingtower.com revokes a seat, which stops that person's pages and nothing else.

## Rotating the relay key

`POST /v1/tenants/{tid}/relay-key` on pingtower.com mints a new credential; write it to the box with `PUT /v1/relay`. Until you do, relayed pages fail and show in the relay integration's delivery log on the box.

## Without pairing

A self-hosted box needs none of this to alert. Webhook, Slack and Telegram deliver from the box directly. Pairing is only for the phone.
