Monitoring
Capture payloads, watch a trigger live, and read what each request did.
Four surfaces, each answering a different question.
| Question | Where |
|---|---|
| What does this provider actually send? | The inspect endpoint |
| What is happening right now? | The trigger monitor |
| What did this request do? | Recent Requests, on the monitor or the handlers page |
| Is this healthy over time? | Observability → API and Webhook Activity |
Capturing a payload without running anything
ANY /api/trigger/inspect/{triggerCode}The inspect endpoint records the request and runs no handlers. Use it to see a real payload before building anything against it, and to check a provider's shape against their documentation.
curl -X POST https://service.ensembleapp.dev/api/trigger/inspect/AbC123XyZ \
-H 'Content-Type: application/json' \
-d '{ "event": "order.created", "order": { "id": "A-1001" } }'It answers with what it stored, and the request then appears under Recent Requests like any other:
{
"success": true,
"message": "Test request logged successfully",
"data": {
"triggerCode": "AbC123XyZ",
"triggerName": "Orders",
"requestId": 918,
"headers": { "content-type": "application/json" },
"body": { "event": "order.created", "order": { "id": "A-1001" } },
"parameters": { "triggerCode": "AbC123XyZ" }
}
}Pointing a real provider at the inspect URL for one event is the fastest way to get a trustworthy payload. Their documentation is often a version behind what they send.
Requests recorded through inspect have no outcome, because no handlers ran. They show as Not recorded rather than as successes.
The trigger monitor
Events → Triggers → Monitor on a trigger opens a live view. It holds a WebSocket open and reports each stage as it happens:
| Stage | Meaning |
|---|---|
request_received | The request arrived and the trigger was found. |
event_classified | The event type path was rendered. The value is shown. |
handler_dispatched | How many handlers matched, and which. |
workflow_invoked | A workflow was started, with its runId. |
error | No handlers matched, or a handler threw. |
The classification stage is the one to watch when a trigger is not doing what you expect: it shows the event type the request was actually classified as, which is what handler matching then compares against.
The live feed exists only while the page is open. Nothing is lost by closing it: the same information is written to the request row, which Recent Requests reads.
Recent Requests
The durable record, on the monitor page and on Events → Handlers for a selected trigger. Each row carries the body, the parameters, the classified event type, and what happened:
| Outcome | Meaning |
|---|---|
| Success | Every matched handler was dispatched without error. |
| Partial | Some handlers were dispatched and at least one failed. |
| Error | Every matched handler failed, or none could be executed. |
| No handlers | The request arrived, was classified, and nothing matched it. |
| Not recorded | An inspect request, or a request from before outcomes were kept. |
Expanding a row names each handler that ran and its result, including the actual error message for the ones that failed.
No handlers is the outcome worth recognising on sight. It means the platform received and understood the request and had nothing to do with it, which is almost always an event type mismatch rather than a delivery problem. Compare the row's classified event type with your handlers' event types; Event types covers the rule.
A handler recorded as Success means the workflow was started. It is not a statement about what the workflow then did.
Following a workflow a trigger started
Because workflows are started rather than awaited, their results are fetched afterwards:
GET /api/trigger-monitoring/{triggerId}/workflow-status/{workflowId}The handler's result in Recent Requests carries the workflowId and runId you need. The
monitor also polls this to report progress for runs it started while the page is open.
API and Webhook Activity
Observability → API and Webhook Activity, on the Webhooks tab, aggregates over a window of 24 hours, 7 days or 30 days:
- Requests received
- Nothing matched, as a count and a share of decided requests
- With a failure, likewise
- Handlers run, which is not the request count: one request can fan out to several
- A chart stacked by outcome
- A per-trigger breakdown, busiest first
- Recent requests that did not land, newest first
Two things about these figures. Nothing matched is treated as a headline failure rather than buried, because a webhook whose events reach no handler is doing nothing at all. And requests with no recorded outcome are counted in the total but excluded from the percentages: dividing by requests nothing is known about would understate both rates.
There is deliberately no latency figure for webhooks. Nothing times the handlers, and the trigger answers before the workflows it started finish, so any number here would be invented. The useful question for a webhook is not how fast but whether anything acted on it.
Retiring a trigger
Triggers are archived, not deleted. Archiving keeps the trigger and its whole request
history, and stops it accepting events: the URL answers 404 Trigger not found, exactly as
an unknown code does.
Archived triggers are hidden from the triggers table until you turn on Show archived. The trigger code stays claimed, so an archived trigger's URL cannot be reused by a new one.