# Question Results Over Outgoing Webhooks

> How Question outcomes can flow back to external systems using PingRoom's outgoing webhook pattern.

- Published: 2026-06-23
- Author: Mahdi Salmanzade
- Category: Agents
- Canonical: https://pingroom.io/blog/question-results-over-webhooks
- Cover image: https://pingroom.io/blog/question-results-over-webhooks.webp

Long polling is useful when an agent is actively waiting.

Outgoing webhooks are useful when a system wants to react later, asynchronously, or from a different worker. The Question protocol should support both. A human answer is an event, and many integrations need that event delivered back to the system that asked.

PingRoom already has outgoing webhooks per room with event filtering and HMAC-signed delivery. Question results should fit that pattern instead of inventing a new callback system.

## Event Types

Question lifecycle events should be explicit:

```text
question.answered
question.expired
question.cancelled
```

Those names preserve the distinction between a negative human answer and no answer. A denial is still `question.answered`; the chosen option carries the negative value. Expiry is separate.

![](/blog/question-results-over-webhooks-1.webp)

## Answered Payload

An answered event can look like this:

```json
{
  "event": "question.answered",
  "room": {
    "id": "room_123",
    "invite_code": "ABCD12",
    "name": "Deploys"
  },
  "question": {
    "id": "q_123",
    "prompt": "Deploy production now?",
    "state": "answered",
    "correlation_id": "deploy-abc123",
    "reply_to": "workflow:release",
    "data": {
      "commit": "abc123",
      "environment": "production"
    }
  },
  "answer": {
    "value": "approve",
    "label": "Approve",
    "responder": {
      "id": "user_123",
      "display_name": "Mahdi"
    },
    "answered_at": "2026-06-23T12:44:10Z"
  }
}
```

The receiver should be able to route by `event`, match by `correlation_id`, and continue the workflow using `answer.value`.

## Expired Payload

An expired event should have the same envelope but no answer:

```json
{
  "event": "question.expired",
  "question": {
    "id": "q_123",
    "state": "expired",
    "correlation_id": "deploy-abc123"
  },
  "answer": null,
  "reason": "deadline_passed"
}
```

That lets an external system handle timeout policies cleanly.

## Room Event Filters

PingRoom outgoing webhooks already support event filters.

Question events should participate in that same filter. A room owner may want all events, only Pings, only question resolutions, or only specific automation events. Keeping this in the room's outgoing webhook configuration avoids a new integration surface.

## Signing And Retries

Outgoing Question events should use the same HMAC signing model as other outgoing webhook deliveries.

The receiver should verify the signature, process idempotently, and return a 2xx response after durable handling. The event should include a stable question id so retries do not create duplicate downstream actions.

Question results are especially sensitive because they may approve real work. A webhook consumer should never treat an unsigned request as authoritative.

## Long Polling Plus Webhooks

These two mechanisms are complementary.

Use long polling when the agent process is actively blocked:

```text
ask -> wait -> continue
```

Use outgoing webhooks when the workflow is event-driven:

```text
ask -> store question id -> receive webhook later -> continue
```

For critical workflows, use both. Wait for a fast response, but also accept the signed webhook as a recovery path if the agent process restarts.

## The Product Rule

Question results should leave PingRoom the same way other room events do: through the existing outgoing webhook system, with clear event names, signed delivery, event filtering, and structured payloads.

That keeps the protocol powerful without making the platform sprawl.
