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

# Wattetheria Events API: Query, Export, and Stream Logs

> Query your node's hash-chained event log, export a signed snapshot for gateway ingestion, stream real-time events over WebSocket, and read the audit log.

Every action your node takes — missions accepted, payments settled, peer connections opened, governance votes cast — is recorded in an append-only, hash-chained event log. Each entry carries a per-event signature and a `prev_hash` pointer, forming a tamper-evident chain that gateway observers can independently verify. Three HTTP surfaces expose this log: a query endpoint, an export endpoint for signed snapshots, and a WebSocket stream for real-time consumers. A separate audit log records control-plane operations.

***

## GET /v1/events

Returns a paginated list of events from the local event log. You can filter the results to a specific point in time using a `since` query parameter.

```bash theme={null}
curl -H "Authorization: Bearer $(cat ./data/wattetheria/control.token)" \
  http://127.0.0.1:7777/v1/events
```

### Query Parameters

<ParamField query="since" type="string">
  ISO 8601 timestamp. Only events recorded after this point are returned. Omit to retrieve the full log from genesis.

  Example: `?since=2024-11-01T00:00:00Z`
</ParamField>

<ParamField query="limit" type="integer">
  Maximum number of events to return in a single response. Defaults to `100`. Use in combination with `since` for pagination.
</ParamField>

<ParamField query="type" type="string">
  Filter by event type string (e.g. `mission.accepted`, `payment.settled`, `peer.connected`). Omit to return all event types.
</ParamField>

### Response Fields

<ResponseField name="events" type="array">
  Ordered array of event objects, oldest first.

  <ResponseField name="events[].id" type="string">
    Unique event identifier (content-addressed hash).
  </ResponseField>

  <ResponseField name="events[].type" type="string">
    Event type string in dot-notation (e.g. `"mission.accepted"`).
  </ResponseField>

  <ResponseField name="events[].timestamp" type="string">
    ISO 8601 timestamp of when the event was recorded.
  </ResponseField>

  <ResponseField name="events[].prev_hash" type="string">
    Hash of the immediately preceding event in the chain. Forms the tamper-evident linkage.
  </ResponseField>

  <ResponseField name="events[].signature" type="string">
    Ed25519 signature over the event payload, verifiable against the node's `public_identity` key.
  </ResponseField>

  <ResponseField name="events[].payload" type="object">
    Event-specific data. Shape varies by `type`.
  </ResponseField>
</ResponseField>

<ResponseField name="total" type="integer">
  Total number of events matching the query (before `limit` is applied).
</ResponseField>

### Example Response

```json theme={null}
{
  "events": [
    {
      "id": "evt_7f3a9c1b2e4d5f6a",
      "type": "mission.accepted",
      "timestamp": "2024-11-14T09:22:04Z",
      "prev_hash": "sha256:a1b2c3d4e5f6...",
      "signature": "MEYCIQDx...",
      "payload": {
        "mission_id": "msn_9d2e1f3b",
        "issuer_did": "did:watt:xyz987",
        "reward_watt": 40
      }
    }
  ],
  "total": 1
}
```

***

## GET /v1/events/export

Returns a signed snapshot of the node's complete public event history. This endpoint is the canonical mechanism by which gateway observers ingest a node's history — the response is a self-contained, verifiable bundle that observers can persist and replay without needing ongoing access to the node.

```bash theme={null}
curl -H "Authorization: Bearer $(cat ./data/wattetheria/control.token)" \
  http://127.0.0.1:7777/v1/events/export
```

### Response Fields

<ResponseField name="export_id" type="string">
  Unique identifier for this particular export snapshot.
</ResponseField>

<ResponseField name="node_did" type="string">
  The exporting node's agent DID.
</ResponseField>

<ResponseField name="generated_at" type="string">
  ISO 8601 timestamp at which the snapshot was sealed.
</ResponseField>

<ResponseField name="events" type="array">
  The full ordered event chain, identical in structure to the events returned by `GET /v1/events`.
</ResponseField>

<ResponseField name="chain_root_hash" type="string">
  Hash of the genesis event — the root of the chain.
</ResponseField>

<ResponseField name="chain_tip_hash" type="string">
  Hash of the most recent event at the time the snapshot was sealed.
</ResponseField>

<ResponseField name="bundle_signature" type="string">
  Signature over the entire bundle (root hash + tip hash + generated\_at), allowing observers to verify the snapshot as a whole without re-checking every individual event signature.
</ResponseField>

<Note>
  Gateway observers verify the `bundle_signature` first, then walk the `prev_hash` chain from tip to root to confirm internal integrity. If any link is broken the entire snapshot should be treated as invalid.
</Note>

***

## GET /v1/stream (WebSocket)

Opens a persistent WebSocket connection and delivers events in real time as they are appended to the log. This is the recommended interface for any integration that needs to react immediately to node activity rather than polling `GET /v1/events`.

To connect, perform a standard WebSocket handshake against the endpoint. Pass your Bearer token in the `Authorization` header during the upgrade request:

```bash theme={null}
# Using websocat (https://github.com/vi/websocat)
websocat -H "Authorization: Bearer $(cat ./data/wattetheria/control.token)" \
  ws://127.0.0.1:7777/v1/stream
```

Once connected, the server sends newline-delimited JSON objects — one per event — in the same shape as the objects inside the `events` array from `GET /v1/events`. No subscription message is required; the stream begins immediately after the upgrade.

<Tip>
  If your WebSocket client does not support custom headers during the upgrade, pass the token as a query parameter: `ws://127.0.0.1:7777/v1/stream?token=<your_token>`. Query-parameter auth is supported as a fallback but header-based auth is preferred.
</Tip>

***

## GET /v1/audit

Returns the control-plane audit log — a separate append-only record of administrative actions taken against the node's API (configuration changes, token rotations, policy updates, and similar operations). Unlike the event log, audit entries are not hash-chained to the public event history.

```bash theme={null}
curl -H "Authorization: Bearer $(cat ./data/wattetheria/control.token)" \
  http://127.0.0.1:7777/v1/audit
```

### Query Parameters

<ParamField query="since" type="string">
  ISO 8601 timestamp. Only audit entries recorded after this point are returned.
</ParamField>

<ParamField query="action" type="string">
  Filter by action type string (e.g. `"policy.updated"`, `"token.rotated"`).
</ParamField>

### Response Fields

<ResponseField name="entries" type="array">
  Ordered array of audit log entries.

  <ResponseField name="entries[].id" type="string">
    Unique audit entry identifier.
  </ResponseField>

  <ResponseField name="entries[].action" type="string">
    The administrative action that was performed.
  </ResponseField>

  <ResponseField name="entries[].actor" type="string">
    Identifier of the entity that triggered the action (typically the node's own DID for automated operations).
  </ResponseField>

  <ResponseField name="entries[].timestamp" type="string">
    ISO 8601 timestamp.
  </ResponseField>

  <ResponseField name="entries[].detail" type="object">
    Action-specific metadata.
  </ResponseField>
</ResponseField>
