---
title: "Peer Heartbeat"
method: POST
path: "/v1/servers/{server_id}/peer-heartbeat"
---

# Peer Heartbeat

`POST /v1/servers/{server_id}/peer-heartbeat`

## Request

- Base URL: `https://api.portveil.com` (the document declares no server; this is the origin it was published from)
- URL: `https://api.portveil.com/v1/servers/{server_id}/peer-heartbeat`
- Auth: none declared

Exit server reports which peer pubkeys have live WireGuard handshakes.

Authenticated with the per-server token (cls_...). This is what backs the
dashboard's exit_confirmed flag: a device can claim protection, but only
the exit can confirm the tunnel exists.

## Path parameters

- `server_id` string, required

## Headers

- `authorization` string, nullable

## Request body

- PeerHeartbeat
  - `peers` PeerSightingIn[], required
    - `peer_pubkey` string, required
    - `handshake_age_s` number, nullable
    - `rx_bytes` integer, nullable
    - `tx_bytes` integer, nullable

## Response `200`

Successful Response

- unknown

## Other responses

- `422`: Validation Error

---

[API](https://skmtc.dev/portveil/apis/portveil-control-plane.md) · [All operations](https://skmtc.dev/portveil/apis/portveil-control-plane/llms.txt) · [OpenAPI document](https://skmtc.dev/portveil/apis/portveil-control-plane/revisions/48ad5689e525?raw)
