> ## Documentation Index
> Fetch the complete documentation index at: https://docs.iroh.computer/llms.txt
> Use this file to discover all available pages before exploring further.

# Network Diagnostics

> Integrate on-demand connectivity reports into your iroh application

When you click **Run Diagnostics** in the dashboard, the platform dials back into your
endpoint using the capability token your app granted. Your `ClientHost` receives
the request, runs the diagnostics locally (probing UDP connectivity, NAT
behavior, relay latency, and port mapping), and returns the report to iroh services for
display.

## Integrating Net Diagnostics Into Your App

To add net diagnostics support to your own iroh application, you need to:

1. Connect to iroh services with an `iroh_services::Client`
2. Grant the `NetDiagnosticsCap::GetAny` capability to iroh services so it can request diagnostics from your endpoint
3. Run a `ClientHost` so iroh services can dial back into your endpoint

[See the `net_diagnostics` example in the `iroh-services` repository for a complete working example of this integration.](https://github.com/n0-computer/iroh-services/tree/main/examples/net_diagnostics.rs)

### 1. Update Cargo.toml

Add the dependency

```bash theme={null}
cargo add iroh-services
```

### 2. Get Your API Key

Create one from your project's **Settings → API Keys** tab. See [API Keys](/iroh-services/access) for the full walkthrough. Then export it as an environment variable:

```bash theme={null}
export IROH_SERVICES_API_SECRET=<your-api-key>
```

### 3. Connect to iroh services and Grant Capability

Here's a minimal integration:

```rust theme={null}
use anyhow::Result;
use iroh::{Endpoint, protocol::Router};
use iroh_services::{
    ApiSecret, Client, ClientHost, CLIENT_HOST_ALPN, API_SECRET_ENV_VAR_NAME,
    caps::NetDiagnosticsCap,
};

async fn setup_net_diagnostics(endpoint: &Endpoint) -> Result<Router> {
    // Get your secret somehow, either from an environment variable or config file
    let secret = ApiSecret::from_env_var(API_SECRET_ENV_VAR_NAME)?;

    // The remote_id is the id of the endpoint we'll be sending the network
    // report to, derived from the secret's address
    let remote_id = secret.addr().id;

    // Build the client
    let client = Client::builder(endpoint)
        .api_secret(secret)?
        .build()
        .await?;

    // Grant the GetAny capability so the platform can request diagnostics
    // from this endpoint on demand
    let client2 = client.clone();
    tokio::spawn(async move {
        client2
            .grant_capability(remote_id, vec![NetDiagnosticsCap::GetAny])
            .await
            .unwrap();
    });

    // Set up a ClientHost so the platform can dial back into this endpoint
    let host = ClientHost::new(endpoint);
    let router = Router::builder(endpoint.clone())
        .accept(CLIENT_HOST_ALPN, host)
        .spawn();

    Ok(router)
}
```

## Understanding Reports

### NAT Types

| NAT Type                 | What it means                                           | Connection quality                                   |
| ------------------------ | ------------------------------------------------------- | ---------------------------------------------------- |
| **No NAT**               | Local address matches public address                    | Direct connections work with correct firewall config |
| **Endpoint-Independent** | One outbound UDP packet opens a port for any sender     | NAT traversal works reliably                         |
| **Endpoint-Dependent**   | Only the specific destination can reply (symmetric NAT) | Connections will primarily use relays                |
| **Unknown**              | NAT behavior could not be determined                    | Check UDP connectivity                               |

### Connectivity Summary

The report includes a color-coded connectivity summary:

* **Green**: UDP works and NAT is favorable. Direct connections should work.
* **Orange**: Endpoint-Dependent NAT. Direct connections may be difficult; traffic will often be relayed.
* **Red**: No UDP connectivity. Traffic will be relayed.

## Troubleshooting

The capability grant (`NetDiagnosticsCap::GetAny`) authorizes the platform to
request diagnostics from your endpoint. Without this grant, the **Run
Diagnostics** button will be disabled in the dashboard even if the endpoint is
online.
