Request Ledger

The request ledger is a core feature, not a debug afterthought. Every provider request an emulator handles is recorded so humans, tests, and agents can validate exactly how an application called a service. Control-plane traffic under /_emulate is not recorded.

# Recent records, newest first, sensitive fields redacted
curl -s http://localhost:4001/_emulate/ledger

# Webhook deliveries plus the most recent requests in one payload
curl -s http://localhost:4001/_emulate/logs

# Clear the ledger
curl -s -X DELETE http://localhost:4001/_emulate/ledger

Recorded fields

Each ledger entry records:

FieldDescription
idStable entry id, e.g. req_42
correlationIdHonored from the incoming X-Correlation-Id or X-Request-Id header, otherwise generated, and echoed back on the X-Correlation-Id response header
timestampISO 8601 time the request completed
method, host, path, queryThe request line as received
routeMatched route pattern, e.g. /repos/:owner/:repo/issues
operationIdProvider operation id when the handler advertises one
faulted, faultIdSet when a response was injected by /_emulate/faults, so tests can prove the fault fired
requestSanitized request headers and body, with bodyTruncated set when the body was clipped
identityAuthenticated identity resolved for the request: the user (login, id, scopes) or app (app id, slug, name)
responseResponse status, sanitized headers, and body
summaryOne-line human and agent readable summary, e.g. POST /repos/:owner/:repo -> 201
sideEffectsState changes the request caused: create, update, delete, or custom, with the affected collection and id
webhookDeliveriesWebhook deliveries this request fired, correlated by delivery id, event, action, status code, and success
durationMsHow long the request took to handle

Redaction

Sensitive headers such as authorization, cookie, set-cookie, x-api-key, x-github-token, and stripe-signature are replaced with [redacted]. Request and response bodies are redacted by key, so any field whose name matches token, secret, password, authorization, api_key, client_secret, or private_key is masked. Form-encoded bodies are redacted by the same rules. Bodies larger than the limit are clipped and flagged with bodyTruncated.

Correlation ids

Set X-Correlation-Id (or X-Request-Id) on a request and the emulator stores it on the ledger entry and echoes it back on the X-Correlation-Id response header, so you can stitch an entry to a specific call in your test. When no id is supplied the emulator generates one.

Faulted requests

POST /_emulate/faults arms a one-shot or counted response for matching provider requests. Match criteria are combined: operationId when the emulator can resolve one from the service manifest, method, and pathPattern. pathPattern is a glob where * matches any characters in the request path. A matched request short-circuits with the configured response, decrements the fault's remaining count, and is recorded here with faulted: true and faultId.

Persistence

On the hosted Cloudflare surface the ledger is persistent. Each instance is backed by a Durable Object that snapshots state and the ledger to storage, so records survive eviction. Locally and in process the ledger is in memory and is cleared on reset. See Deployment for the instance model.

Example entry

{
  "id": "req_42",
  "correlationId": "cor_8f1c0a2b4d6e",
  "timestamp": "2026-06-08T17:04:22.118Z",
  "method": "POST",
  "host": "github.my-run.emulators.dev",
  "path": "/repos/acme/web/issues",
  "query": "",
  "route": "/repos/:owner/:repo/issues",
  "operationId": "issues/create",
  "request": {
    "headers": {
      "authorization": "[redacted]",
      "content-type": "application/json"
    },
    "body": { "title": "Bug report", "body": "It broke" }
  },
  "identity": {
    "user": { "login": "octocat", "id": 1, "scopes": ["repo"] }
  },
  "response": {
    "status": 201,
    "headers": { "content-type": "application/json" },
    "body": { "number": 7, "state": "open" }
  },
  "summary": "POST /repos/:owner/:repo/issues -> 201",
  "sideEffects": [{ "type": "create", "collection": "issues", "id": 7 }],
  "webhookDeliveries": [
    { "id": 3, "hook_id": 1, "event": "issues", "action": "opened", "status_code": 200, "success": true }
  ],
  "durationMs": 4
}

The Service Manifest advertises ledger capabilities under its ledger block, including the recorded fields, whether redaction and correlation ids are supported, and whether the ledger is persistent on this host.