Developer reference

One ordered
event history.

Groundhog's event log stores immutable JSON events. Each log has its own endpoint. Callers append events, retrieve an event by ID, or read a sequence in append order.

The log assigns each event an ID and recording timestamp. The caller supplies its source and payload.

Implementation status

This reference describes the current Rust HTTP service. It implements durable append, read by ID, and ordered reads.

The product architecture also includes application synchronization, maintained projections, queries over those projections, authorization, and managed action execution. Those capabilities are described on the public Architecture page. They are not exposed by this HTTP service.

Start locally

You need a Groundhog source checkout and a Rust toolchain with Cargo. Run the commands below from the directory containing Cargo.toml. Preview details describe the current access stage.

Start a log with a persistent local data directory. The endpoint below listens on your local machine.

cargo run --release --bin groundhog -- \
  --data-dir ./data \
  --listen 127.0.0.1:3000

Keep the service running in one terminal. In a second terminal, append the example event below. The --prefix option selects a log prefix in the object store. Its default is log.

Append events

POST /events accepts one event object or a nonempty array of event objects. Every input has two required fields:

  • source: a string identifying the connection or producer.
  • payload: any valid JSON value, including an object, array, string, number, boolean, or null.
curl http://127.0.0.1:3000/events \
  -H 'Content-Type: application/json' \
  -d '{
    "source": "application_api",
    "payload": {
      "event": "record.observed",
      "record_id": "4821",
      "revision": 13
    }
  }'

The response is a JSON array, even when the input contains one event. The service returns 201 Created after the entire request is appended atomically and storage confirms durability.

Example response

[
  {
    "id": "1",
    "source": "application_api",
    "recorded_at": "2026-09-24T15:30:07.000Z",
    "payload": {
      "event": "record.observed",
      "record_id": "4821",
      "revision": 13
    }
  }
]

id is a positive 64-bit integer encoded as a decimal string. IDs increase in append order. recorded_at is the UTC timestamp assigned during append.

The payload is preserved without an application schema. Payload fields do not set or override envelope fields. Source timestamps, revisions, and application IDs belong inside the payload.

Client batches

A submitted array is atomic and retains its input order. The writer can group multiple requests for storage without splitting an individual client batch. Empty or oversized batches are rejected.

Read an event

GET /events/{id} returns the complete original event. Use the ID returned by append.

curl http://127.0.0.1:3000/events/1

The response contains id, source, recorded_at, and payload. An absent event returns 404 Not Found.

Read in order

GET /events returns durable events in increasing ID order.

curl 'http://127.0.0.1:3000/events?after=1&limit=100'
  • after is exclusive. Reading starts after that ID. Omit it to begin at the start of the log.
  • limit is the maximum number of returned events. The default is 100.

Continue by supplying the last returned event ID as after. Append order describes when the log recorded an event. A later append can contain an older application revision.

Failure behavior

A successful append waits for storage durability. Reads expose durable events.

A failed or cancelled call may still have stored its events. Retrying can append another event. The current API does not supply a deduplication guarantee.

After an uncertain storage failure, the writer stops accepting appends. Reopen the log before appending again. Normal shutdown drains accepted work and waits for durability.

  • 400: invalid input, event ID, or query parameters.
  • 413: a configured request or batch limit is exceeded.
  • 503: storage is closed or unavailable.
  • 507: event ID allocation is exhausted.
  • 500: another storage failure.

The service bounds pending requests and accounted bytes. Those limits provide backpressure while writes await durability. They are not a complete process memory bound.

Product architecture

Groundhog's vision connects application data access and action execution through a shared recorded history.

  • Agent reads and background synchronization acquire application data.
  • Projections maintain queryable state under defined computation rules.
  • Executors perform authorized requests and record attempts and outcomes.
  • Later work can retrieve the observations, decisions, and results that preceded it.

The illustrative website demonstrates an account projection. It uses source revisions to preserve the latest observed state when an older observation arrives later. Reconstructing that projection consumes retained data and results under the same rules.

Explore the product architecture

About this site.

Groundhog is infrastructure for companies building agents. This site explains the product architecture and the current event log implementation.

The interactive examples use illustrative data. They do not connect to applications or execute external actions. Early access remains a placeholder in this preview.

Read the API reference