Skip to content

HTTP API Reference ​

All CritterWatch HTTP endpoints are implemented using Wolverine.HTTP and mounted under /api/critterwatch/*. They are automatically mapped by UseCritterWatch().

Bus-only queries don't appear here

The on-demand lookups for endpoint configuration, handler properties, handler source code, and HTTP-chain OpenAPI are bus queries, not HTTP endpoints — they go from the CritterWatch console to the monitored service over the message bus and the response comes back the same way. They live on the Inbound Commands page (RequestEndpointProperties, RequestMessageHandlerProperties, RequestHandlerSourceCode, RequestHttpChainOpenApi). If you're looking for an HTTP equivalent, there isn't one — invoke the matching command record over your transport.

Services ​

GET /api/critterwatch/services ​

Returns all monitored services as ServiceSummary documents.

Response: ServiceSummary[]

json
[
  {
    "id": "trip-service",
    "label": "Trip Service",
    "wolverineVersion": "5.28.0",
    "communicationUri": "amqp://trip-service",
    "tenancy": "None",
    "nodes": { ... },
    "agents": { ... },
    "messages": [ ... ],
    "messagingEndpoints": [ ... ]
  }
]

GET /api/critterwatch/services/{serviceName} ​

Returns a single service by name.

Response: ServiceSummary

Dead Letter Queue ​

POST /api/critterwatch/dead-letters/query ​

Query dead-lettered envelopes across services.

Request body:

json
{
  "serviceName": "trip-service",
  "tenantId": null,
  "messageType": "TripService.Messages.BookTrip",
  "exceptionType": null,
  "from": "2024-01-01T00:00:00Z",
  "to": null,
  "limit": 100
}

Response: DeadLetterEnvelope[]

POST /api/critterwatch/dead-letters/replay ​

Replay matching dead-lettered messages.

Request body:

json
{
  "serviceName": "trip-service",
  "tenantId": null,
  "messageType": "TripService.Messages.BookTrip",
  "limit": null
}

Response: { "replayedCount": 12 }

POST /api/critterwatch/dead-letters/discard ​

Permanently discard matching dead-lettered messages.

Request body: Same as replay.

Response: { "discardedCount": 12 }

POST /api/critterwatch/dead-letters/{envelopeId}/replay ​

Replay a single message by envelope ID.

Request body:

json
{
  "serviceName": "trip-service",
  "tenantId": null
}

POST /api/critterwatch/dead-letters/{envelopeId}/edit-replay ​

Edit a message body and replay.

Request body:

json
{
  "serviceName": "trip-service",
  "tenantId": null,
  "updatedBody": "{ \"tripId\": \"abc\", \"fare\": 450.00 }"
}

DELETE /api/critterwatch/dead-letters/{envelopeId} ​

Discard a single message.

Scheduled Messages ​

GET /api/critterwatch/scheduled-messages ​

Query scheduled messages.

Query parameters: serviceName, tenantId, messageType, from, to, status (upcoming/overdue/all)

PUT /api/critterwatch/scheduled-messages/{envelopeId} ​

Edit a scheduled message.

Request body:

json
{
  "serviceName": "trip-service",
  "tenantId": null,
  "updatedBody": "{ ... }",
  "newExecutionTime": "2024-06-01T12:00:00Z"
}

DELETE /api/critterwatch/scheduled-messages/{envelopeId} ​

Cancel a scheduled message.

Commands ​

POST /api/critterwatch/commands/pause-listener ​

Pause a listener on a service.

Request body: { "serviceName": "trip-service", "endpointName": "rabbitmq://trip-bookings" }

POST /api/critterwatch/commands/restart-listener ​

POST /api/critterwatch/commands/pause-all-listeners ​

POST /api/critterwatch/commands/restart-all-listeners ​

POST /api/critterwatch/commands/pause-projection ​

POST /api/critterwatch/commands/restart-projection ​

POST /api/critterwatch/commands/rebuild-projection ​

POST /api/critterwatch/commands/rewind-subscription ​

POST /api/critterwatch/commands/eject-node ​

POST /api/critterwatch/commands/trigger-election ​

POST /api/critterwatch/commands/add-tenant ​

POST /api/critterwatch/commands/remove-tenant ​

All command endpoints accept JSON bodies matching their corresponding command record types. See Inbound Commands for the full schema of each command.

Alerts ​

GET /api/critterwatch/alerts ​

Query alerts with optional filters: serviceName, status, severity, type.

POST /api/critterwatch/alerts/{alertId}/acknowledge ​

POST /api/critterwatch/alerts/{alertId}/snooze ​

POST /api/critterwatch/alerts/{alertId}/clear ​

Timeline ​

GET /api/critterwatch/timeline ​

Query timeline entries.

Query parameters: serviceName, category, severity, from, to, limit

System Health ​

GET /api/critterwatch/system-health ​

The console's own component health (GH-685) — not the health of monitored services. Console subsystems that detect they are broken (e.g. the metrics sample storage when its table schema cannot be reconciled) mark themselves degraded here with an actionable reason, instead of failing silently behind anonymous 500s.

Response:

json
{
  "status": "degraded",
  "components": [
    {
      "component": "metrics-store",
      "status": "Degraded",
      "reason": "CritterWatch cannot reconcile critterwatch.mt_doc_metricssample: ...",
      "changedAtUtc": "2026-07-12T12:00:00Z"
    }
  ]
}

status is "healthy" when no component is degraded. The same state also feeds the critterwatch-system ASP.NET Core health check, so hosts that call MapHealthChecks(...) report Degraded through their standard health endpoint. See the upgrade notes for the schema migration that motivated this surface.

Authentication ​

The HTTP API does not ship with built-in authentication. Add ASP.NET Core authorization middleware and use RequireAuthorization() on routes to protect the API.

Response Format ​

All responses use application/json. JSON serialization uses camelCase property names (via JsonNamingPolicy.CamelCase). Enums are serialized as string names.

Free for read-only monitoring. A commercial license is required for administrative actions and the MCP server.