# Voidly Probes: agent quickstart

Start with public data. Reading these links does not create an account, register a node, or run a measurement. An agent should not install or start a probe without the network operator's explicit decision.

## One read-only call

```bash
curl --fail-with-body --max-time 10 -sS https://api.voidly.ai/v1/probe/network
```

This compact public JSON gives a network snapshot with `updated_at`, per-core-node status, core-country metadata and raw probe totals. It needs no Voidly credential and does not run a probe. **Do not add `active_nodes` and `community.active` as if they share one window:** core active uses a 15-minute last-result window, while public-path active is distinct nodes with raw results in 24 hours. Public-path nodes can be Voidly-operated; `coverage.countries` describes core locations, not national or independent-operator coverage. A non-2xx response, missing timestamp or malformed fields means unavailable, not zero. Keep a named User-Agent in custom clients; a default client signature may be refused by the live edge. Cache or back off rather than polling rapidly.

## Deeper 24-hour result read

```bash
curl --fail-with-body --max-time 30 -sS https://api.voidly.ai/v1/probe/stats
```

This larger response summarizes raw result rows over a consistent 24-hour window, including distinct measured nodes and countries, result rows, and blocked flags. It is not a test from your network or proof of accepted downstream observations. The checked-in API proxy sets a 25-second upstream deadline; the example allows 30 seconds. The hosted MCP `get_probe_stats` tool can truncate large responses at its proxy size cap; validate complete JSON or use REST.

**Check the body before using a number.** A non-2xx response is unavailable. HTTP 503 can return `{"error":"Probe stats unavailable","available":false}`. HTTP 200 can still carry `"degraded":true` and an `"errors"` array naming failed sections. If any section failed, a top-level `error` or `available:false` is present, or the error markers are malformed, treat the whole stats body as unavailable. A missing count or one that is not a non-negative integer is unavailable. Do not replace unavailable values with zero or infer success from HTTP 200 alone. A 429, if returned, is a limit response: honor `Retry-After` when present and back off. This read path does not promise an unlimited quota.

## Discover before installing

| Purpose | Public link | What it establishes |
| --- | --- | --- |
| Current served targets | [GET `/v1/probe/domains`](https://api.voidly.ai/v1/probe/domains) | The target-list response for this request. Add `?country=XX` for a country supplement. Inspect `global` and `country_domains`; a missing or empty `global` list is not proof that the client has no targets. |
| Registered contact | [GET `/v1/probe/network/heartbeats`](https://api.voidly.ai/v1/probe/network/heartbeats) | Public `activity_status`, `activity_counts`, and `activity_policy`. Contact is not an accepted measurement. |
| Community registry | [GET `/v1/community/nodes?limit=500`](https://api.voidly.ai/v1/community/nodes?limit=500) | Registered node records. Compare `stats.totalNodes` with returned row count before claiming completeness; check operator and activity labels before describing ownership or recent contact. |
| Human setup and risks | [Probes](https://voidly.ai/probes) · [Join guide](https://voidly.ai/probes/join) | Participation, privacy, traffic, and stopping details. |
| API and client source | [API docs](https://voidly.ai/api-docs) · [OpenAPI](https://voidly.ai/openapi.json) · [Python client source](https://github.com/voidly-ai/community-probe) | Integrator reference and inspectable client code. |
| Custom client protocol | [Probe protocol](https://voidly.ai/probe-protocol.md) | Separate ingest-key registration path; do not use it as the Python client's token instructions. |

The served target list can change without a client update. The continuous Python client fetches it at startup and about daily; if the fetch fails, it uses its bundled targets. Its `--once` mode also uses bundled targets. Reading the target list sends a request to Voidly, but does not contact the listed sites.

## Install and activation are separate

The published Python package is [`voidly-probe` on PyPI](https://pypi.org/project/voidly-probe/). `python3 -m pip install voidly-probe` installs it; installation alone does not register a node or measure. On an unregistered installation, `voidly-probe` without `--consent` prints the consent disclosure and exits. `voidly-probe --status` reads the local node identity and, if present, requests its public status.

**Activation is an explicit operator action:** `voidly-probe --consent` registers through `POST /v1/community/register`, stores a private token in `~/.voidly/node.json`, and starts outbound DNS, TLS, and HTTP checks. Do not use that command as a dry run. Starting the [Docker image](https://hub.docker.com/r/emperormew2/voidly-probe) also activates measurement immediately. Before either start, review the served and bundled targets, local network rules, and [participation risks](https://voidly.ai/probes#risks). The network operator and tested services can observe the traffic; node location and measurement history can become public. The default registration location lookup contacts ipinfo.io unless `VOIDLY_COUNTRY` and optional `VOIDLY_CITY` are set before first registration.

After activation, stop the running process to stop new checks. `voidly-probe --unregister` removes only the local identity file; it does not revoke the remote token, remove a pending-results cache, or erase submitted data and downstream copies. Keep the token private.

## What counts as a measurement

The Python client signs result submissions with its community token and sends them to `POST /v1/probe/results`. The custom-client [ingest-key protocol](https://voidly.ai/probe-protocol.md) uses a different registration and credential. Registration, a last-seen timestamp, a leaderboard counter, or a successful client status check shows neither a new result row nor downstream acceptance. The Worker can update community counters before forwarding a submission, and the client may cache failed submissions locally. A successful API response is a submission response, not proof that every downstream dataset accepted the observation. Check measured data and its freshness separately.

For the community-client path, the checked-in Worker specifies at most 10 registration requests per hour per IP and 1,000 authenticated submissions per hour per node; its submission 429 includes `Retry-After: 3600`. It filters off-list domains and caps a submitted batch at 100 results. These implementation limits can change; use the served response and back off on refusal. The custom-client path has its own trial/full limits in the [protocol](https://voidly.ai/probe-protocol.md).
