---
audience: developer
summary: Admin setup to peer your ScaiWave server with another.
title: Enable federation with a peer
path: tutorials/developer/enable-federation-with-a-peer
status: published
---

# Enable federation with a peer

You're an admin on `your-host.example.com` and you want to peer with
`peer.acme.com`. Both must agree.

## 1. Verify your `/.well-known`

Hit your own descriptor first to make sure it's correct:

```bash
curl https://your-host.example.com/.well-known/scaiwave/server | jq .
```

Should look like:

```json
{
  "server_name": "your-host.example.com",
  "public_key": "ed25519:base64...",
  "protocol_versions": ["v1"],
  "endpoints": {
    "send": "/_scaiwave/federation/v1/send",
    "profile": "/_scaiwave/federation/v1/profile/{local_id}",
    "members": "/_scaiwave/federation/v1/rooms/{room_id}/members",
    "backfill": "/_scaiwave/federation/v1/rooms/{room_id}/backfill"
  }
}
```

If this doesn't load: check that:

- `SCAIWAVE_SERVER_NAME` matches the host name.
- TLS is valid (peers verify cert chains by default).
- A federation key is provisioned. If `public_key` is empty, run
  `scaiwave admin federation key generate`.

## 2. Check the peer's descriptor

```bash
curl https://peer.acme.com/.well-known/scaiwave/server | jq .
```

If the peer doesn't publish one, federation isn't possible.

## 3. Update your federation policy

```bash
curl -X PUT "https://your-host.example.com/v1/admin/federation/policy" \
  -H "Authorization: Bearer $ADMIN" \
  -H "Content-Type: application/json" \
  -d '{
    "default_mode": "invite_only",
    "allowed_peers": ["peer.acme.com"],
    "max_foreign_participants_per_room": 50
  }'
```

`default_mode` options:

- `open` — accept federation invites from any peer.
- `invite_only` — only accept invites where the peer is in
  `allowed_peers`.
- `closed` — refuse all federation.

## 4. Have the peer reciprocate

The peer's admin runs the same setup pointed at your server. Both
sides need each other's descriptor; both sides need each other in
their respective `allowed_peers` lists (if either is in
`invite_only` mode).

## 5. Test with a federated DM

```bash
curl -X POST "https://your-host.example.com/v1/me/federated-dms" \
  -H "Authorization: Bearer $YOUR_USER_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"fqid": "@alice:peer.acme.com"}'
```

If this succeeds, the foreign user gets the invite in their
notification panel. When they accept, the DM is operational.

## 6. Backfill

If you want history to flow from the peer (e.g. you joined an
already-existing room), the federation backfill endpoint pulls it:

```bash
curl -X POST "https://your-host.example.com/v1/admin/rooms/$ROOM_ID/federation/backfill" \
  -H "Authorization: Bearer $ADMIN"
```

Pulls up to 1000 historical events from the peer's
`/_scaiwave/federation/v1/rooms/{room_id}/backfill` endpoint. Each
event is signature-verified before storage.

## 7. Monitor

`GET /v1/admin/federation/peers` returns the active peer set with
`last_seen` and `last_error` columns:

```json
{
  "data": [
    {
      "server_name": "peer.acme.com",
      "last_seen": "2026-05-17T13:00:00Z",
      "last_error": null,
      "events_sent_24h": 142,
      "events_received_24h": 87
    }
  ]
}
```

If `last_error` is set, traffic is failing. Common causes:

- Their `/.well-known` returns a different public key than what you
  cached → key rotation. Refresh with
  `POST /v1/admin/federation/foreign/{participant_id}/refresh`.
- Their server is down → wait.
- Signature mismatch → check that both sides are on the same
  protocol version.

## 8. Rotate your federation key

Federation keys rotate yearly. To rotate manually:

```bash
scaiwave admin federation key rotate
```

Generates a new keypair, publishes the new public key on
`/.well-known`, and starts signing new events with it. Peers
auto-discover the new key on next event verification (with a 30-day
overlap window where both keys are accepted).

## What can't be federated

- Incognito rooms.
- Bridge rooms.
- Rooms with `room_type=sidekick`.
- Rooms whose owner tenant has federation disabled tenant-wide.

The federation endpoint refuses these with clear error codes.

## Where to go next

- [Concepts: Federation](/docs/scaiwave/concepts/federation).
- API: [Federation](/docs/scaiwave/reference/api/federation).
- [Join a federated room](/docs/scaiwave/tutorials/power-user/join-a-federated-room) — user-side.
