# Hindsight REST API Endpoints

Base URL: `http://127.0.0.1:9177`
Swagger UI: `http://127.0.0.1:9177/docs`
OpenAPI spec: `http://127.0.0.1:9177/openapi.json`

## Key Endpoints

### Health
- `GET /health` → `{"status": "healthy", "database": "connected"}`
- `GET /version` → version info
- `GET /metrics` → prometheus metrics

### Banks
- `GET /v1/default/banks` → list all banks
- `GET /v1/default/banks/{bank_id}` → bank info
- `GET /v1/default/banks/{bank_id}/stats` → memory counts, timeseries
- `GET /v1/default/banks/{bank_id}/stats/memories-timeseries` → growth over time
- `GET /v1/default/banks/{bank_id}/config` → bank configuration

### Memories (Semantic Search)
- `POST /v1/default/banks/{bank_id}/memories/recall` → semantic search
  - Body: `{"query": "...", "budget": "low|mid|high", "types": ["world","experience","observation"]}`
  - Returns: JSON **array** of matching memories (NOT `{"text": "..."}`)
  - Each result has a `scores` **dict** (not scalar `score`):
    `{"scores": {"final": 0.92, "semantic": 0.58, "keyword": 0.10, "reranker": 0.82}}`
  - Access overall relevance via `result["scores"]["final"]`
- `GET /v1/default/banks/{bank_id}/memories/list` → list all memories
- `GET /v1/default/banks/{bank_id}/memories/{memory_id}` → single memory
- `GET /v1/default/banks/{bank_id}/memories/{memory_id}/history` → revision history

### Reflect (Synthesis)
- `POST /v1/default/banks/{bank_id}/reflect` → synthesize answer across all memories
  - Body: `{"query": "...", "budget": "low|mid|high", "context": "deprecated, put in query"}`
  - Returns: `{"text": "...", "usage": {"input_tokens": N, "output_tokens": N, "total_tokens": N}}`

### Entities
- `GET /v1/default/banks/{bank_id}/entities` → list entities
- `GET /v1/default/banks/{bank_id}/entities/{entity_id}` → single entity
- `GET /v1/default/banks/{bank_id}/entities/graph` → entity co-occurrence graph
- `POST /v1/default/banks/{bank_id}/entities/{entity_id}/regenerate` → regenerate entity

### Mental Models
- `GET /v1/default/banks/{bank_id}/mental-models` → list mental models
- `POST /v1/default/banks/{bank_id}/mental-models/{id}/refresh` → refresh model

### Consolidation & Maintenance
- `POST /v1/default/banks/{bank_id}/consolidate` → trigger consolidation
- `POST /v1/default/banks/{bank_id}/consolidation/recover` → recover failed consolidation
- `GET /v1/default/banks/{bank_id}/operations` → async operations status
- `POST /v1/default/banks/{bank_id}/operations/{id}/retry` → retry failed operation

### Import/Export
- `POST /v1/default/banks/{bank_id}/import` → import memories
- `GET /v1/default/banks/{bank_id}/export` → export memories

### Audit & Observations
- `GET /v1/default/banks/{bank_id}/audit-logs` → audit trail
- `GET /v1/default/banks/{bank_id}/audit-logs/stats` → audit statistics
- `GET /v1/default/banks/{bank_id}/observations` → observations

### Webhooks
- `GET /v1/default/banks/{bank_id}/webhooks` → list webhooks
- `POST /v1/default/banks/{bank_id}/webhooks` → create webhook
- `GET /v1/default/banks/{bank_id}/webhooks/{id}/deliveries` → delivery history

## Budget Levels

| Budget | Behavior |
|---|---|
| `low` | Fewer memories retrieved, faster, cheaper |
| `mid` | Balanced (default for recall) |
| `high` | More memories, deeper results (use for pattern detection) |

## Direct PostgreSQL Access

When the REST API isn't enough, query PostgreSQL directly:

```bash
PSQL=~/.pg0/installation/18.1.0/bin/psql
$PSQL -h 127.0.0.1 -p 5432 -U hindsight -d hindsight -c "<SQL>"
```

### Key Tables

| Table | Purpose |
|---|---|
| `memory_units` | Stored facts with embeddings, tags, access_count |
| `entities` | Named entities extracted from memories |
| `documents` | Source documents (conversation turns) |
| `chunks` | Document chunks with embeddings |
| `unit_entities` | Links between memories and entities |
| `memory_links` | Links between memories |
| `audit_log` | All mutations |
| `banks` | Bank configurations |

### Useful Queries

```sql
-- Count memories
SELECT COUNT(*) FROM memory_units WHERE bank_id='hermes';

-- Find exact duplicates
SELECT text, COUNT(*) FROM memory_units WHERE bank_id='hermes'
GROUP BY text HAVING COUNT(*) > 1;

-- Find stale memories (old, never accessed)
SELECT id, text FROM memory_units WHERE bank_id='hermes'
AND access_count = 0 AND created_at < NOW() - INTERVAL '6 months';

-- Recent memories
SELECT id, text, created_at FROM memory_units WHERE bank_id='hermes'
ORDER BY created_at DESC LIMIT 10;
```
