Admin API
HTTP admin API — 21 endpoints for events, verification, erasure, retention, reports, and stats.
The handler package exposes 21 REST endpoints using the Forge router with full OpenAPI metadata. Routes are mounted under /v1/ and require an AppID in the request context.
Setup
import (
"net/http"
"log/slog"
"github.com/xraph/chronicle/handler"
)
mux := http.NewServeMux()
api := handler.New(handler.Dependencies{
AuditStore: myStore,
VerifyStore: myStore,
ErasureStore: myStore,
RetentionStore: myStore,
ReportStore: myStore,
Compliance: complianceEngine,
Retention: retentionEnforcer,
Logger: slog.Default(),
}, mux)
api.RegisterRoutes(mux)
http.ListenAndServe(":8080", mux)Authentication
Every request must have an AppID in the context (populated by your auth middleware). Requests without an AppID return 401 Unauthorized. TenantID is also enforced on all queries to prevent cross-tenant access.
Error format
{"error": "chronicle: event not found"}Events
| Method | Path | Description |
|---|---|---|
GET | /v1/events | List events with filters (category, action, severity, outcome, time range) |
GET | /v1/events/:id | Get a single event by ID |
GET | /v1/events/user/:userId | Get events for a specific user |
POST | /v1/events/aggregate | Grouped counts for analytics |
List events query parameters
| Parameter | Description |
|---|---|
category | Filter by event category |
action | Filter by action verb |
severity | info, warning, or critical |
outcome | success, failure, or denied |
from | Start time (RFC3339) |
to | End time (RFC3339) |
limit | Page size (default 20) |
offset | Page offset |
order | asc or desc |
Verification
| Method | Path | Description |
|---|---|---|
POST | /v1/verify | Verify hash chain integrity |
Request body:
{
"stream_id": "stream_01j9vk...",
"from_seq": 0,
"to_seq": 0
}Response: verify.Report — valid, verified, gaps, tampered.
Erasure
| Method | Path | Description |
|---|---|---|
POST | /v1/erasures | Request GDPR erasure for a subject |
GET | /v1/erasures | List erasure records |
GET | /v1/erasures/:id | Get a specific erasure record |
Retention
| Method | Path | Description |
|---|---|---|
GET | /v1/retention | List retention policies |
POST | /v1/retention | Create or update a retention policy |
DELETE | /v1/retention/:id | Delete a policy |
POST | /v1/retention/enforce | Trigger immediate retention enforcement |
GET | /v1/retention/archives | List archive records |
Reports
| Method | Path | Description |
|---|---|---|
GET | /v1/reports | List compliance reports |
POST | /v1/reports/soc2 | Generate SOC2 Type II report |
POST | /v1/reports/hipaa | Generate HIPAA report |
POST | /v1/reports/euaiact | Generate EU AI Act report |
POST | /v1/reports/custom | Generate custom report |
GET | /v1/reports/:id | Get a specific report |
GET | /v1/reports/:id/export/:format | Export report (json, csv, markdown, html) |
Stats
| Method | Path | Description |
|---|---|---|
GET | /v1/stats | Aggregate statistics for audit events |
Forge extension
When using the Forge extension, routes are registered automatically during Register unless WithDisableRoutes(true) is set:
ext := extension.New(
extension.WithStore(s),
// WithDisableRoutes defaults to false — routes are auto-registered
)
app.Register(ext)Access the underlying handler.API for manual control:
ext.API().RegisterRoutes(customRouter)Or get an http.Handler for standalone use:
h := ext.Handler()
http.ListenAndServe(":8080", h)