curl --request POST \
--url https://api.getbluejay.ai/v1/update-simulation-result \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"simulation_result_id": "<string>",
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"duration": 1,
"events": [
{
"title": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"end_offset_ms": 123,
"tags": [
"<string>"
],
"metadata": {}
}
],
"tool_calls": [
{
"name": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"parameters": {},
"output": null
}
],
"recorded_transcript": [
{
"start_offset_ms": 123,
"end_offset_ms": 123,
"utterance": "<string>",
"filler_utterance": true
}
],
"tags": [
"<string>"
],
"metadata": {},
"trace_ids": [
"<string>"
]
}
'import requests
url = "https://api.getbluejay.ai/v1/update-simulation-result"
payload = {
"simulation_result_id": "<string>",
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"duration": 1,
"events": [
{
"title": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"end_offset_ms": 123,
"tags": ["<string>"],
"metadata": {}
}
],
"tool_calls": [
{
"name": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"parameters": {},
"output": None
}
],
"recorded_transcript": [
{
"start_offset_ms": 123,
"end_offset_ms": 123,
"utterance": "<string>",
"filler_utterance": True
}
],
"tags": ["<string>"],
"metadata": {},
"trace_ids": ["<string>"]
}
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
simulation_result_id: '<string>',
start_time: '2023-11-07T05:31:56Z',
end_time: '2023-11-07T05:31:56Z',
duration: 1,
events: [
{
title: '<string>',
start_offset_ms: 123,
description: '<string>',
end_offset_ms: 123,
tags: ['<string>'],
metadata: {}
}
],
tool_calls: [
{
name: '<string>',
start_offset_ms: 123,
description: '<string>',
parameters: {},
output: null
}
],
recorded_transcript: [
{
start_offset_ms: 123,
end_offset_ms: 123,
utterance: '<string>',
filler_utterance: true
}
],
tags: ['<string>'],
metadata: {},
trace_ids: ['<string>']
})
};
fetch('https://api.getbluejay.ai/v1/update-simulation-result', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.getbluejay.ai/v1/update-simulation-result",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'simulation_result_id' => '<string>',
'start_time' => '2023-11-07T05:31:56Z',
'end_time' => '2023-11-07T05:31:56Z',
'duration' => 1,
'events' => [
[
'title' => '<string>',
'start_offset_ms' => 123,
'description' => '<string>',
'end_offset_ms' => 123,
'tags' => [
'<string>'
],
'metadata' => [
]
]
],
'tool_calls' => [
[
'name' => '<string>',
'start_offset_ms' => 123,
'description' => '<string>',
'parameters' => [
],
'output' => null
]
],
'recorded_transcript' => [
[
'start_offset_ms' => 123,
'end_offset_ms' => 123,
'utterance' => '<string>',
'filler_utterance' => true
]
],
'tags' => [
'<string>'
],
'metadata' => [
],
'trace_ids' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.getbluejay.ai/v1/update-simulation-result"
payload := strings.NewReader("{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.getbluejay.ai/v1/update-simulation-result")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getbluejay.ai/v1/update-simulation-result")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"message": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Update Simulation Result
curl --request POST \
--url https://api.getbluejay.ai/v1/update-simulation-result \
--header 'Content-Type: application/json' \
--header 'X-API-Key: <x-api-key>' \
--data '
{
"simulation_result_id": "<string>",
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"duration": 1,
"events": [
{
"title": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"end_offset_ms": 123,
"tags": [
"<string>"
],
"metadata": {}
}
],
"tool_calls": [
{
"name": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"parameters": {},
"output": null
}
],
"recorded_transcript": [
{
"start_offset_ms": 123,
"end_offset_ms": 123,
"utterance": "<string>",
"filler_utterance": true
}
],
"tags": [
"<string>"
],
"metadata": {},
"trace_ids": [
"<string>"
]
}
'import requests
url = "https://api.getbluejay.ai/v1/update-simulation-result"
payload = {
"simulation_result_id": "<string>",
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"duration": 1,
"events": [
{
"title": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"end_offset_ms": 123,
"tags": ["<string>"],
"metadata": {}
}
],
"tool_calls": [
{
"name": "<string>",
"start_offset_ms": 123,
"description": "<string>",
"parameters": {},
"output": None
}
],
"recorded_transcript": [
{
"start_offset_ms": 123,
"end_offset_ms": 123,
"utterance": "<string>",
"filler_utterance": True
}
],
"tags": ["<string>"],
"metadata": {},
"trace_ids": ["<string>"]
}
headers = {
"X-API-Key": "<x-api-key>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {'X-API-Key': '<x-api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
simulation_result_id: '<string>',
start_time: '2023-11-07T05:31:56Z',
end_time: '2023-11-07T05:31:56Z',
duration: 1,
events: [
{
title: '<string>',
start_offset_ms: 123,
description: '<string>',
end_offset_ms: 123,
tags: ['<string>'],
metadata: {}
}
],
tool_calls: [
{
name: '<string>',
start_offset_ms: 123,
description: '<string>',
parameters: {},
output: null
}
],
recorded_transcript: [
{
start_offset_ms: 123,
end_offset_ms: 123,
utterance: '<string>',
filler_utterance: true
}
],
tags: ['<string>'],
metadata: {},
trace_ids: ['<string>']
})
};
fetch('https://api.getbluejay.ai/v1/update-simulation-result', options)
.then(res => res.json())
.then(res => console.log(res))
.catch(err => console.error(err));<?php
$curl = curl_init();
curl_setopt_array($curl, [
CURLOPT_URL => "https://api.getbluejay.ai/v1/update-simulation-result",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => json_encode([
'simulation_result_id' => '<string>',
'start_time' => '2023-11-07T05:31:56Z',
'end_time' => '2023-11-07T05:31:56Z',
'duration' => 1,
'events' => [
[
'title' => '<string>',
'start_offset_ms' => 123,
'description' => '<string>',
'end_offset_ms' => 123,
'tags' => [
'<string>'
],
'metadata' => [
]
]
],
'tool_calls' => [
[
'name' => '<string>',
'start_offset_ms' => 123,
'description' => '<string>',
'parameters' => [
],
'output' => null
]
],
'recorded_transcript' => [
[
'start_offset_ms' => 123,
'end_offset_ms' => 123,
'utterance' => '<string>',
'filler_utterance' => true
]
],
'tags' => [
'<string>'
],
'metadata' => [
],
'trace_ids' => [
'<string>'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-API-Key: <x-api-key>"
],
]);
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}package main
import (
"fmt"
"strings"
"net/http"
"io"
)
func main() {
url := "https://api.getbluejay.ai/v1/update-simulation-result"
payload := strings.NewReader("{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("X-API-Key", "<x-api-key>")
req.Header.Add("Content-Type", "application/json")
res, _ := http.DefaultClient.Do(req)
defer res.Body.Close()
body, _ := io.ReadAll(res.Body)
fmt.Println(string(body))
}HttpResponse<String> response = Unirest.post("https://api.getbluejay.ai/v1/update-simulation-result")
.header("X-API-Key", "<x-api-key>")
.header("Content-Type", "application/json")
.body("{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.getbluejay.ai/v1/update-simulation-result")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["X-API-Key"] = '<x-api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"simulation_result_id\": \"<string>\",\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"duration\": 1,\n \"events\": [\n {\n \"title\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"end_offset_ms\": 123,\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {}\n }\n ],\n \"tool_calls\": [\n {\n \"name\": \"<string>\",\n \"start_offset_ms\": 123,\n \"description\": \"<string>\",\n \"parameters\": {},\n \"output\": null\n }\n ],\n \"recorded_transcript\": [\n {\n \"start_offset_ms\": 123,\n \"end_offset_ms\": 123,\n \"utterance\": \"<string>\",\n \"filler_utterance\": true\n }\n ],\n \"tags\": [\n \"<string>\"\n ],\n \"metadata\": {},\n \"trace_ids\": [\n \"<string>\"\n ]\n}"
response = http.request(request)
puts response.read_body{
"status": "success",
"message": "<string>"
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}# 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 endpoint, then plan the integration, then implement with minimal changes.
## Update Simulation Result — POST /v1/update-simulation-result
**Endpoint:** POST `https://api.getbluejay.ai/v1/update-simulation-result`
**Auth:** `X-API-Key` header
**Content-Type:** application/json
### Required Parameters
| Name | Type | Description |
|------|------|-------------|
| X-API-Key | string | API key required to authenticate requests. |
| simulation_result_id | string | Simulation result ID from the SIP `X-Simulation-Result-Id` header. Omit this when sending `start_time`, `end_time`, and `duration` instead. |
Send `simulation_result_id`, or all three of `start_time`, `end_time`, and `duration`. One of those two identities is required.
| Name | Type | Description |
|------|------|-------------|
| start_time | string | Call start, ISO-8601 with a timezone. |
| end_time | string | Call end, ISO-8601 with a timezone. |
| duration | integer | Call duration in seconds. |
Review the full parameter list at https://docs.getbluejay.ai/api-reference/endpoint/update-simulation-result and include any optional parameters (e.g., `events`, `tool_calls`, `recorded_transcript`, `tags`, `metadata`) that serve your integration's use case and align with Bluejay's testing and monitoring capabilities.
### Request Body
```json
{
"simulation_result_id": "string"
}
```
Or, without the id:
```json
{
"start_time": "2026-09-29T18:00:00Z",
"end_time": "2026-09-29T18:02:00Z",
"duration": 120,
"recorded_transcript": [
{"speaker": "AGENT", "utterance": "Hello", "start_offset_ms": 0, "end_offset_ms": 400}
]
}
```
Refer to the full schema at https://docs.getbluejay.ai/api-reference/endpoint/update-simulation-result. Include optional fields that serve the goal of setting up for testing and monitoring on Bluejay.
### Example
**POST with body:**
```python
import requests
def update_simulation_result(payload: dict, api_key: str) -> dict:
url = "https://api.getbluejay.ai/v1/update-simulation-result"
headers = {"X-API-Key": api_key}
response = requests.post(url, headers=headers, json=payload)
response.raise_for_status()
return response.json()
```
### Constraints
- Minimal changes — only add/change files needed for this integration.
- Match existing codebase patterns (naming, file structure, error handling).
- Include error handling for 422: Validation Error.
### Integration Checklist
Before writing code, verify:
1. Which module/service owns this API domain in the codebase?
2. What HTTP client and error-handling patterns does the project use?
3. Are there existing types/interfaces to extend?
Then implement the integration, export it, and confirm it compiles/passes lint.
X-Simulation-Result-Id: <simulation_result_id>
This ID associates your tool calls, events, tags, and metadata with the specific simulation result.
Given this ID, this endpoint updates your simulation result to enrich the simulation with the tool calls, events, tags, and metadata you provide.
If you do not have the ID, send start_time, end_time, and duration (seconds) instead. Bluejay looks in the workspaces your key can see for a connected simulation. Calls without a stored duration are always treated as candidates. When duration is stored, the stored start is compared to start_time and the end (stored start plus stored duration) is compared to end_time; both must fall within 90 seconds, and the stored duration must be within the larger of 5 seconds and 10% of duration.
When you omit recorded_transcript, or send one with no readable words, exactly one call must match the window; that call is updated. When you include a transcript, every call in the window is scored: one call is kept only when the transcript shares at least 80% of its normalized words, and several calls are separated only when the closest transcript leads the next one by at least 0.08 on that same score. If more than one call is in the window and the transcript does not separate them, the response is 409 and nothing is written.
404 means nothing in your organization matched the window. 409 means the transcript was missing, not stored yet, too close to separate the calls, or not close enough to the only call in the window. Send simulation_result_id in that case.Body
Simulation result ID provided via SIP for the specific call. Omit to match on start_time, end_time, and duration.
Call start (timezone-aware). With end_time and duration, identifies the result when simulation_result_id is omitted.
Call end (timezone-aware). With start_time and duration, identifies the result when simulation_result_id is omitted.
Call duration in seconds. With start_time and end_time, identifies the result when simulation_result_id is omitted.
x >= 0List of events that occurred during the call
Show child attributes
Show child attributes
List of tool calls made during the call
Show child attributes
Show child attributes
Recorded transcript of the call. Stored for STT accuracy, and used to pick the call when several match the time window.
Show child attributes
Show child attributes
List of tags associated with the call
Additional metadata associated with the call
Trace IDs to associate with this simulation result