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

# Signals & Events API

> List signals, submit curator signals, and subscribe to the SSE stream.

## `GET /signals`

Lists recent signal events.

### Query parameters

| Param    | Type   | Default | Notes                          |
| -------- | ------ | ------: | ------------------------------ |
| `domain` | string |         | Filters by `signal.<domain>.*` |
| `limit`  | int    |     100 | Max 500                        |
| `offset` | int    |       0 | For pagination                 |

### Example

```bash theme={null}
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:5050/api/v1/signals?domain=ta&limit=50&offset=0" | jq
```

### Response (`200`)

```json theme={null}
{
  "items": [
    {
      "id": "1",
      "type": "signal.ta.rsi.v1",
      "ts": "2026-02-20T00:29:58+00:00",
      "source": "producer.ta",
      "payload": {"symbol": "BTC", "rsi_14": 52.1}
    }
  ],
  "limit": 100,
  "offset": 0,
  "total": 1
}
```

Errors: `401 auth.*`

***

## `POST /signals/submit`

Submit a **curator signal** with contributor attribution.

* Resolves the contributor by `node_id`
* Writes the signal event
* Records attribution in `contributor_signals`
* If `source` is omitted/blank, stored event `source` defaults to contributor `node_id` (canonical identity)

### Request body

```json theme={null}
{
  "event_type": "signal.curator.v1",
  "ts": "2026-02-20T00:29:58Z",
  "node_id": "b1e55ed-deadbeef",
  "source": "operator:telegram",
  "payload": {
    "symbol": "BTC",
    "direction": "bullish",
    "conviction": 7.0,
    "rationale": "context"
  }
}
```

### Example

```bash theme={null}
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d @- \
  http://localhost:5050/api/v1/signals/submit <<'JSON'
{
  "event_type": "signal.curator.v1",
  "ts": "2026-02-20T00:29:58Z",
  "node_id": "b1e55ed-deadbeef",
  "source": "operator:telegram",
  "payload": {
    "symbol": "BTC",
    "direction": "bullish",
    "conviction": 7.0,
    "rationale": "ETF flows strong; dips being bought"
  }
}
JSON
```

### Response (`200`)

```json theme={null}
{"event_id": "123", "contributor_id": "contrib_abc123"}
```

Errors:

* `400 signal.invalid_type`
* `404 contributor.not_found`
* `401 auth.*`

***

## `GET /signals/{signal_id}/attribution`

Returns attribution data for a specific signal (contributor, source, and outcome when settled).
When contributor linkage exists, `producer_id` is normalized to contributor `node_id`.

```bash theme={null}
curl -s \
  -H "Authorization: Bearer $TOKEN" \
  http://localhost:5050/api/v1/signals/123/attribution | jq
```

Errors:

* `401 auth.*`
* `404` (signal not found)

***

## `GET /events/stream` (SSE)

Server-Sent Events stream. Reconnect is safe.

### Query parameters

| Param    | Type   | Notes                                                 |
| -------- | ------ | ----------------------------------------------------- |
| `domain` | string | Filter by domain (e.g. `signal`, `alert`, `learning`) |
| `since`  | string | Resume from a specific event id (inclusive)           |

### Event format

```text theme={null}
data: {"id":"123","type":"signal.ta.rsi.v1","ts":"2026-02-20T00:00:00Z","source":"producer.ta","payload":{...}}
```

### Example

```bash theme={null}
curl -N \
  -H "Authorization: Bearer $TOKEN" \
  "http://localhost:5050/api/v1/events/stream?domain=alert"
```
