Skip to main content
WEBHOOK
events_webhook
{
  "id": 123,
  "digital_human_id": 123,
  "simulation_run_id": 123,
  "simulation_id": 123,
  "agent_id": 123,
  "type": "simulation_result_evaluated",
  "status": "COMPLETED",
  "folder_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
  "result": {},
  "custom_metrics": [
    {
      "name": "<string>",
      "description": "<string>",
      "response_type": "<string>",
      "response_value": "<string>",
      "reasoning": "<string>",
      "min_value": 123,
      "max_value": 123,
      "category": "<string>",
      "tags": [
        "<string>"
      ],
      "scoring_guidance": "<string>",
      "enum_options": [
        "<string>"
      ]
    }
  ],
  "evaluations": [
    {
      "agent_speak_percentage": 123,
      "avg_agent_latency": 123,
      "id": "<string>",
      "created_at": "2023-11-07T05:31:56Z",
      "hallucination": true,
      "hallucination_reasoning": "<string>",
      "redundancy": true,
      "redundancy_reasoning": "<string>",
      "latency": {
        "avg_agent_latency": 0,
        "max_agent_latency": 0,
        "p50_agent_latency": 0,
        "p90_agent_latency": 0,
        "p95_agent_latency": 0,
        "p99_agent_latency": 0
      },
      "filler_ignored_latency": {
        "avg_filler_ignored_latency": 0,
        "p50_filler_ignored_latency": 0,
        "p90_filler_ignored_latency": 0,
        "p95_filler_ignored_latency": 0,
        "p99_filler_ignored_latency": 0
      },
      "num_turns": 123,
      "call_summary": "<string>",
      "custom_evals": [
        "<unknown>"
      ],
      "custom_evals_success_rate": 123,
      "goal_success": true,
      "goal_reasoning": "<string>",
      "pronunciation_score": 123,
      "pronunciation_reasoning": "<string>",
      "sentiment_label": "<string>",
      "sentiment_score": 123,
      "sentiment_scores": {},
      "custom_metrics": [
        {
          "name": "<string>",
          "description": "<string>",
          "response_type": "<string>",
          "response_value": "<string>",
          "reasoning": "<string>",
          "min_value": 123,
          "max_value": 123,
          "category": "<string>",
          "tags": [
            "<string>"
          ],
          "scoring_guidance": "<string>",
          "enum_options": [
            "<string>"
          ]
        }
      ]
    }
  ],
  "created_at": "2023-11-07T05:31:56Z",
  "start_time": "2023-11-07T05:31:56Z",
  "end_time": "2023-11-07T05:31:56Z",
  "duration": 123,
  "latency": [
    123
  ],
  "events": [
    {
      "title": "<string>",
      "start_offset_ms": 123,
      "description": "<string>",
      "end_offset_ms": 123,
      "tags": [
        "<string>"
      ],
      "metadata": {}
    }
  ],
  "tool_calls": [
    {
      "name": "<string>",
      "start_offset_ms": 1,
      "description": "<string>",
      "parameters": {},
      "output": "<unknown>"
    }
  ],
  "tags": [
    "<string>"
  ],
  "metadata": {}
}
Integration Prompt for AI Agents
# Bluejay — Testing & Monitoring Platform for Conversational AI Agents

You are a senior backend engineer integrating the Bluejay API. Think step-by-step: first understand the webhook payload, then plan the handler, then implement with minimal changes.

## Handle Events Webhook — WEBHOOK

> **What this webhook does:** Upon an event on the platform, we'll send you the results to the URL you registered within the dashboard

**Type:** Incoming Webhook (JSON POST)

### Required Payload Fields
| Name | Type | Required | Description |
|------|------|----------|-------------|
| **Variant: `simulation_result_evaluated`** | | | |
| id | integer | yes | The ID of the simulation result |
| digital_human_id | integer | yes | The ID of the digital human |
| simulation_run_id | integer | yes | The ID of the simulation run that this simulation result belongs to |
| simulation_id | integer | yes | The ID of the simulation that this simulation result belongs to |
| agent_id | integer | yes | The ID of the agent that this simulation result belongs to |
| **Variant: `observability_call_evaluated`** | | | |
| id | string | yes | Unique identifier for the call |
| agent_id | string | yes | ID of the agent associated with the call |
| recording_url | string (nullable) | yes | URL to the recording file (supported formats: .mp4, .wav, .m4a) |
| start_time_utc | string | yes | When the call started, in UTC |
| participants | array[object] | yes | List of call participants |
| status | string (enum: INITIALIZING, QUEUED, EVALUATING, COMPLETED, INCOMPLETED) | yes | Enum representing the possible states of a call. |
| **Variant: `simulation_ended`** | | | |
| id | integer | yes | The ID of the simulation result |
| digital_human_id | integer | yes | The ID of the digital human |
| simulation_run_id | integer | yes | The ID of the simulation run that this simulation result belongs to |
| **Variant: `outbound_simulation_started`** | | | |
| agent_id | integer | yes | The ID of the agent that this simulation belongs to |
| simulation_id | integer | yes | The ID of the simulation |
| simulation_run_id | integer | yes | The ID of the simulation run |
| digital_humans | array[object] | yes | The digital humans that were run for this simulation run |

### Payload Schema
Discriminated by `type`:

**When `type` = `simulation_result_evaluated`:**
```json
{
  "type": "simulation_result_evaluated",
  "id": 123,
  "digital_human_id": 123,
  "status": "INITIALIZING",
  "simulation_run_id": 123,
  "simulation_id": 123,
  "agent_id": 123,
  "folder_id": "string",
  "result": {
    "key": "value"
  },
  "custom_metrics": [
    {
      "name": "example_name",
      "description": "string",
      "response_type": "string",
      "response_value": "string",
      "reasoning": "string",
      "min_value": 1.0,
      "max_value": 1.0,
      "category": "string",
      "tags": [
        "string"
      ],
      "scoring_guidance": "string",
      "enum_options": [
        "string"
      ]
    }
  ],
  "evaluations": [
    {
      "id": "string",
      "created_at": "string",
      "hallucination": true,
      "hallucination_reasoning": "string",
      "redundancy": true,
      "redundancy_reasoning": "string",
      "agent_speak_percentage": 1.0,
      "avg_agent_latency": 1.0,
      "latency": {
        "avg_agent_latency": 1.0,
        "max_agent_latency": 1.0,
        "p50_agent_latency": 1.0,
        "p90_agent_latency": 1.0,
        "p95_agent_latency": 1.0,
        "p99_agent_latency": 1.0
      },
      "filler_ignored_latency": {
        "avg_filler_ignored_latency": 1.0,
        "p50_filler_ignored_latency": 1.0,
        "p90_filler_ignored_latency": 1.0,
        "p95_filler_ignored_latency": 1.0,
        "p99_filler_ignored_latency": 1.0
      },
      "num_turns": 123,
      "call_summary": "string",
      "custom_evals": [],
      "custom_evals_success_rate": 1.0,
      "goal_success": true,
      "goal_reasoning": "string",
      "pronunciation_score": 1.0,
      "pronunciation_reasoning": "string",
      "custom_metrics": [
        {
          "name": "example_name",
          "description": "string",
          "response_type": "string",
          "response_value": "string",
          "reasoning": "string",
          "min_value": 1.0,
          "max_value": 1.0,
          "category": "string",
          "tags": [],
          "scoring_guidance": "string",
          "enum_options": []
        }
      ]
    }
  ],
  "created_at": "string",
  "start_time": "string",
  "end_time": "string",
  "duration": 123,
  "latency": [
    1.0
  ],
  "events": [
    {
      "title": "string",
      "start_offset_ms": 123,
      "description": "string",
      "end_offset_ms": 123,
      "tags": [
        "string"
      ],
      "metadata": {
        "key": "value"
      }
    }
  ],
  "tool_calls": [
    {
      "name": "example_name",
      "start_offset_ms": 123,
      "description": "string",
      "parameters": {
        "key": "value"
      }
    }
  ],
  "tags": [
    "string"
  ],
  "metadata": {
    "key": "value"
  }
}
```

**When `type` = `observability_call_evaluated`:**
```json
{
  "id": "string",
  "agent_id": "string",
  "external_agent_id": "string",
  "recording_url": "string",
  "start_time_utc": "string",
  "participants": [
    {
      "role": "AGENT",
      "spoke_first": true,
      "name": "string",
      "phone_number": "string"
    }
  ],
  "call_direction": "INBOUND",
  "interface": "PHONE",
  "status": "INITIALIZING",
  "created_at": "string",
  "transcript_url": "string",
  "tool_calls": [
    {
      "name": "example_name",
      "start_offset_ms": 123,
      "description": "string",
      "parameters": {
        "key": "value"
      }
    }
  ],
  "events": [
    {
      "title": "string",
      "start_offset_ms": 123,
      "description": "string",
      "end_offset_ms": 123,
      "tags": [
        "string"
      ],
      "metadata": {
        "key": "value"
      }
    }
  ],
  "tags": [
    "string"
  ],
  "duration_ms": 123,
  "evaluations": [
    {
      "id": "string",
      "created_at": "string",
      "hallucination": true,
      "hallucination_reasoning": "string",
      "redundancy": true,
      "redundancy_reasoning": "string",
      "agent_speak_percentage": 1.0,
      "avg_agent_latency": 1.0,
      "latency": {
        "avg_agent_latency": 1.0,
        "max_agent_latency": 1.0,
        "p50_agent_latency": 1.0,
        "p90_agent_latency": 1.0,
        "p95_agent_latency": 1.0,
        "p99_agent_latency": 1.0
      },
      "filler_ignored_latency": {
        "avg_filler_ignored_latency": 1.0,
        "p50_filler_ignored_latency": 1.0,
        "p90_filler_ignored_latency": 1.0,
        "p95_filler_ignored_latency": 1.0,
        "p99_filler_ignored_latency": 1.0
      },
      "num_turns": 123,
      "call_summary": "string",
      "custom_evals": [],
      "custom_evals_success_rate": 1.0,
      "goal_success": true,
      "goal_reasoning": "string",
      "pronunciation_score": 1.0,
      "pronunciation_reasoning": "string",
      "custom_metrics": [
        {
          "name": "example_name",
          "description": "string",
          "response_type": "string",
          "response_value": "string",
          "reasoning": "string",
          "min_value": 1.0,
          "max_value": 1.0,
          "category": "string",
          "tags": [],
          "scoring_guidance": "string",
          "enum_options": []
        }
      ]
    }
  ],
  "annotations": [],
  "metadata": {
    "key": "value"
  },
  "custom_metrics": [],
  "conversation_ended_by": "AGENT",
  "type": "observability_call_evaluated"
}
```

**When `type` = `simulation_ended`:**
```json
{
  "type": "simulation_ended",
  "id": 123,
  "digital_human_id": 123,
  "status": "INITIALIZING",
  "simulation_run_id": 123,
  "created_at": "string",
  "start_time": "string",
  "end_time": "string",
  "duration": 123
}
```

**When `type` = `outbound_simulation_started`:**
```json
{
  "type": "outbound_simulation_started",
  "agent_id": 123,
  "simulation_id": 123,
  "simulation_run_id": 123,
  "digital_humans": [
    {
      "id": 123,
      "name": "example_name",
      "phone_number": "+15551234567",
      "associated_simulation_result_ids": [
        123
      ]
    }
  ]
}
```


Refer to the Bluejay API documentation for additional optional payload fields.

### Example
```python
from fastapi import FastAPI, Request

app = FastAPI()

@app.post("/webhooks/events_webhook")
async def handle_events_webhook(request: Request):
    payload = await request.json()
    event_type = payload.get("type")
    # process based on event type
    return {"status": "received"}
```

### Constraints
- Minimal changes — only add/change files needed for this integration.
- Match existing codebase patterns (naming, file structure, error handling).
- Return a 200 OK response to acknowledge receipt.

### Integration Checklist
Before writing code, verify:
1. Which module/service owns webhook handling in the codebase?
2. What routing and validation patterns does the project use?
3. Are there existing types/interfaces to extend?

Then implement the handler, export it, and confirm it compiles/passes lint.
Upon an event on the platform, all webhooks that are subscribed to the specific event will receive the results to the URL you registered within the dashboard.

Authorizations

X-API-Key
string
header
required

API key required to authenticate requests.

Body

application/json

Represents a simulation result evaluated event.

id
integer
required

The ID of the simulation result

digital_human_id
integer
required

The ID of the digital human

simulation_run_id
integer
required

The ID of the simulation run that this simulation result belongs to

simulation_id
integer
required

The ID of the simulation that this simulation result belongs to

agent_id
integer
required

The ID of the agent that this simulation result belongs to

type
string
default:simulation_result_evaluated

Type of webhook payload

status
enum<string>
default:COMPLETED

The status of the simulation result

Available options:
INITIALIZING,
QUEUED,
READY,
DISPATCHED,
RUNNING,
CONVERSATION_ENDED,
EVALUATING,
COMPLETED,
INCOMPLETED,
REJECTED,
INSUFFICIENT_FUNDS
folder_id
string<uuid> | null

The ID of the folder that the agent belongs to

result
Result · object
deprecated

Please use the evaluations instead

custom_metrics
Custom Metric · object[] | null
deprecated

Please use the custom metrics in the evaluations instead

evaluations
Evaluation · object[] | null

The evaluations of the simulation result

created_at
string<date-time> | null

The creation time of the simulation result

start_time
string<date-time> | null

The start time of the simulation result

end_time
string<date-time> | null

The end time of the simulation result

duration
integer | null

The duration of the simulation result

latency
number[] | null

The latency of the simulation result

events
Event · object[] | null

The events of the simulation result

tool_calls
ToolCall · object[] | null

The tool calls of the simulation result

tags
string[] | null

The tags of the simulation result

metadata
Metadata · object

The metadata of the simulation result

Response

200

Webhook received successfully