Chronicle
1.x
Docs/Chronicle/HTTP Admin API
Open

Reading5 min
Updated31 Jul 2026
Sourcev1/api-reference/http-api.mdx

The admin API is served by handler.New(deps, router). All routes are mounted under /v1. Requests and responses use JSON. All requests require an AppID in the context; missing AppID returns 401 Unauthorized.

Setup01

import "github.com/xraph/chronicle/handler"

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)

When using the Forge extension, routes are registered automatically unless WithDisableRoutes(true) is set.

Error format02

{"error": "chronicle: event not found"}
CodeCondition
400Invalid request body or query parameters
401Missing AppID
404Entity not found
500Internal error

Events03

List events

GET /v1/events

Query parameters:

ParameterTypeDescription
categorystringFilter by event category
actionstringFilter by action verb
severitystringinfo, warning, or critical
outcomestringsuccess, failure, or denied
fromRFC3339Start time
toRFC3339End time
limitintPage size (default 20)
offsetintPage offset
orderstringasc or desc (by timestamp)

Response 200 OK: audit.QueryResult

{
  "events": [
    {
      "id": "audit_01j9vk...",
      "timestamp": "2025-01-15T10:00:00Z",
      "sequence": 42,
      "hash": "abc123...",
      "prev_hash": "def456...",
      "stream_id": "stream_01j9vk...",
      "app_id": "myapp",
      "tenant_id": "tenant-1",
      "user_id": "user-42",
      "action": "login",
      "resource": "session",
      "category": "auth",
      "resource_id": "sess-001",
      "outcome": "success",
      "severity": "info"
    }
  ],
  "total": 1
}

Get event

GET /v1/events/:id

Response 200 OK: Single audit.Event.

Response 404 Not Found

Events by user

GET /v1/events/user/:userId

Query parameters: from, to (RFC3339), limit, offset.

Response 200 OK: audit.QueryResult

Aggregate events

POST /v1/events/aggregate

Request body: audit.AggregateQuery

{
  "group_by": "category",
  "from": "2025-01-01T00:00:00Z",
  "to": "2025-01-31T23:59:59Z"
}

Response 200 OK: audit.AggregateResult

{
  "buckets": [
    {"name": "auth", "count": 142},
    {"name": "billing", "count": 38}
  ]
}

Verification04

Verify hash chain

POST /v1/verify

Request body:

{
  "stream_id": "stream_01j9vk...",
  "from_seq": 0,
  "to_seq": 0
}

from_seq and to_seq default to 0 (full chain). stream_id is optional if app_id and tenant_id are in context.

Response 200 OK: verify.Report

{
  "valid": true,
  "verified": 42,
  "gaps": [],
  "tampered": [],
  "first_event": 1,
  "last_event": 42
}

Erasure05

Request erasure

POST /v1/erasures

Request body:

{
  "subject_id": "user-42",
  "reason": "GDPR Article 17",
  "requested_by": "[email protected]"
}

Response 201 Created: erasure.Result

{
  "id": "erasure_01j9vk...",
  "subject_id": "user-42",
  "events_affected": 5,
  "key_destroyed": true
}

List erasures

GET /v1/erasures

Query parameters: limit, offset.

Response 200 OK: []*erasure.Erasure

Get erasure

GET /v1/erasures/:id

Response 200 OK: erasure.Erasure

Response 404 Not Found


Retention06

List policies

GET /v1/retention

Response 200 OK: []*retention.Policy

Save policy

POST /v1/retention

Request body:

{
  "category": "auth",
  "duration": "2160h",
  "archive": true
}

Response 201 Created: retention.Policy

Delete policy

DELETE /v1/retention/:id

Response 204 No Content

Enforce retention

Immediately runs all retention policies once.

POST /v1/retention/enforce

Response 200 OK: retention.EnforceResult

{
  "archived": 150,
  "purged": 150,
  "retained": 8420
}

List archives

GET /v1/retention/archives

Response 200 OK: []*retention.Archive


Reports07

List reports

GET /v1/reports

Query parameters: limit, offset.

Response 200 OK: []*compliance.Report

Generate SOC2 report

POST /v1/reports/soc2

Request body: compliance.SOC2Input

{
  "period": {"from": "2025-01-01T00:00:00Z", "to": "2025-03-31T23:59:59Z"},
  "app_id": "myapp",
  "tenant_id": "tenant-1",
  "generated_by": "[email protected]"
}

Response 201 Created: compliance.Report

Generate HIPAA report

POST /v1/reports/hipaa

Request body: compliance.HIPAAInput (same shape as SOC2Input).

Response 201 Created: compliance.Report

Generate EU AI Act report

POST /v1/reports/euaiact

Request body: compliance.EUAIActInput.

Response 201 Created: compliance.Report

Generate custom report

POST /v1/reports/custom

Request body: compliance.CustomInput

{
  "period": {"from": "2025-01-01T00:00:00Z", "to": "2025-01-31T23:59:59Z"},
  "app_id": "myapp",
  "title": "Q1 Security Review",
  "categories": ["auth", "billing"],
  "generated_by": "[email protected]"
}

Response 201 Created: compliance.Report

Get report

GET /v1/reports/:id

Response 200 OK: compliance.Report

Response 404 Not Found

Export report

GET /v1/reports/:id/export/:format

:format is one of: json, csv, markdown, html.

Response 200 OK: Report content in the requested format (Content-Type varies).


Stats08

Chronicle stats

GET /v1/stats

Response 200 OK:

{
  "total_events": 8420,
  "events_by_severity": {
    "info": 7800,
    "warning": 580,
    "critical": 40
  },
  "events_by_outcome": {
    "success": 8100,
    "failure": 250,
    "denied": 70
  }
}