curl --request POST \
--url https://api.galtea.ai/monitors \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"productId": "prod_123",
"name": "Production quality watch",
"versionId": "version_123",
"metricGroupIds": [
"metricGroup_123"
],
"specificationIds": [
"specification_123"
],
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE"
}
'import requests
url = "https://api.galtea.ai/monitors"
payload = {
"productId": "prod_123",
"name": "Production quality watch",
"versionId": "version_123",
"metricGroupIds": ["metricGroup_123"],
"specificationIds": ["specification_123"],
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
productId: 'prod_123',
name: 'Production quality watch',
versionId: 'version_123',
metricGroupIds: ['metricGroup_123'],
specificationIds: ['specification_123'],
samplingPercentage: 10,
monthlyCreditCap: 500,
filterQuery: 'refund, cancel, chargeback',
filterTarget: 'EITHER',
excludeQuery: 'test, internal',
excludeTarget: 'EITHER',
messageConditions: [{count: 'messages', operator: 'gt', value: 1}],
status: 'ACTIVE'
})
};
fetch('https://api.galtea.ai/monitors', 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.galtea.ai/monitors",
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([
'productId' => 'prod_123',
'name' => 'Production quality watch',
'versionId' => 'version_123',
'metricGroupIds' => [
'metricGroup_123'
],
'specificationIds' => [
'specification_123'
],
'samplingPercentage' => 10,
'monthlyCreditCap' => 500,
'filterQuery' => 'refund, cancel, chargeback',
'filterTarget' => 'EITHER',
'excludeQuery' => 'test, internal',
'excludeTarget' => 'EITHER',
'messageConditions' => [
[
'count' => 'messages',
'operator' => 'gt',
'value' => 1
]
],
'status' => 'ACTIVE'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.galtea.ai/monitors"
payload := strings.NewReader("{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.galtea.ai/monitors")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.galtea.ai/monitors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}"
response = http.request(request)
puts response.read_body{
"id": "monitor_123",
"productId": "prod_123",
"versionId": "version_123",
"userId": "user_123",
"name": "Production quality watch",
"metricGroupIds": [
"metricGroup_123"
],
"specificationIds": [
"specification_123"
],
"scoredMetricGroupIds": [
"metricGroup_123"
],
"specificationIdsByMetricGroupId": {
"metricGroup_123": [
"specification_123"
]
},
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE",
"families": [
{
"metricGroupId": "metricGroup_123",
"name": "Answer relevancy",
"state": "ACTIVE",
"metricId": "metric_123"
}
],
"createdAt": "2023-11-07T05:31:56Z",
"deletedAt": "2023-11-07T05:31:56Z"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}Create monitor
Create a new monitor. It scores the metric families in metricGroupIds and the metrics of the Specifications in specificationIds; at least one of the two is required. See Monitors.
curl --request POST \
--url https://api.galtea.ai/monitors \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"productId": "prod_123",
"name": "Production quality watch",
"versionId": "version_123",
"metricGroupIds": [
"metricGroup_123"
],
"specificationIds": [
"specification_123"
],
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE"
}
'import requests
url = "https://api.galtea.ai/monitors"
payload = {
"productId": "prod_123",
"name": "Production quality watch",
"versionId": "version_123",
"metricGroupIds": ["metricGroup_123"],
"specificationIds": ["specification_123"],
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE"
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.post(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'POST',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({
productId: 'prod_123',
name: 'Production quality watch',
versionId: 'version_123',
metricGroupIds: ['metricGroup_123'],
specificationIds: ['specification_123'],
samplingPercentage: 10,
monthlyCreditCap: 500,
filterQuery: 'refund, cancel, chargeback',
filterTarget: 'EITHER',
excludeQuery: 'test, internal',
excludeTarget: 'EITHER',
messageConditions: [{count: 'messages', operator: 'gt', value: 1}],
status: 'ACTIVE'
})
};
fetch('https://api.galtea.ai/monitors', 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.galtea.ai/monitors",
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([
'productId' => 'prod_123',
'name' => 'Production quality watch',
'versionId' => 'version_123',
'metricGroupIds' => [
'metricGroup_123'
],
'specificationIds' => [
'specification_123'
],
'samplingPercentage' => 10,
'monthlyCreditCap' => 500,
'filterQuery' => 'refund, cancel, chargeback',
'filterTarget' => 'EITHER',
'excludeQuery' => 'test, internal',
'excludeTarget' => 'EITHER',
'messageConditions' => [
[
'count' => 'messages',
'operator' => 'gt',
'value' => 1
]
],
'status' => 'ACTIVE'
]),
CURLOPT_HTTPHEADER => [
"Authorization: Bearer <token>",
"Content-Type: application/json"
],
]);
$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.galtea.ai/monitors"
payload := strings.NewReader("{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}")
req, _ := http.NewRequest("POST", url, payload)
req.Header.Add("Authorization", "Bearer <token>")
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.galtea.ai/monitors")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.galtea.ai/monitors")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Post.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"productId\": \"prod_123\",\n \"name\": \"Production quality watch\",\n \"versionId\": \"version_123\",\n \"metricGroupIds\": [\n \"metricGroup_123\"\n ],\n \"specificationIds\": [\n \"specification_123\"\n ],\n \"samplingPercentage\": 10,\n \"monthlyCreditCap\": 500,\n \"filterQuery\": \"refund, cancel, chargeback\",\n \"filterTarget\": \"EITHER\",\n \"excludeQuery\": \"test, internal\",\n \"excludeTarget\": \"EITHER\",\n \"messageConditions\": [\n {\n \"count\": \"messages\",\n \"operator\": \"gt\",\n \"value\": 1\n }\n ],\n \"status\": \"ACTIVE\"\n}"
response = http.request(request)
puts response.read_body{
"id": "monitor_123",
"productId": "prod_123",
"versionId": "version_123",
"userId": "user_123",
"name": "Production quality watch",
"metricGroupIds": [
"metricGroup_123"
],
"specificationIds": [
"specification_123"
],
"scoredMetricGroupIds": [
"metricGroup_123"
],
"specificationIdsByMetricGroupId": {
"metricGroup_123": [
"specification_123"
]
},
"samplingPercentage": 10,
"monthlyCreditCap": 500,
"filterQuery": "refund, cancel, chargeback",
"filterTarget": "EITHER",
"excludeQuery": "test, internal",
"excludeTarget": "EITHER",
"messageConditions": [
{
"count": "messages",
"operator": "gt",
"value": 1
}
],
"status": "ACTIVE",
"families": [
{
"metricGroupId": "metricGroup_123",
"name": "Answer relevancy",
"state": "ACTIVE",
"metricId": "metric_123"
}
],
"createdAt": "2023-11-07T05:31:56Z",
"deletedAt": "2023-11-07T05:31:56Z"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}{
"error": "Error type",
"message": "Error message description"
}Authorizations
API key authorization. Pass your API key in the Authorization header as a Bearer token. Both new (gsk_*) and legacy (gsk-) API keys are accepted, e.g. Authorization: Bearer gsk_... or Authorization: Bearer gsk-....
Body
1"prod_123"
"Production quality watch"
Optional version to narrow the monitor to. When null the monitor watches the whole product.
"version_123"
The metric families (Metric.metricGroupId) picked directly on the monitor. The list may be empty when specificationIds is set. The families the monitor scores are in scoredMetricGroupIds. The monitor binds the family, not a specific revision, so revising a metric is picked up automatically without editing the monitor.
["metricGroup_123"]
The Specifications (Specification.id) bound to the monitor. The monitor also scores the metrics each one links, so a metric added to or removed from a Specification takes effect on the next scan. Only Policy and Capability Specifications can be bound. At least one of metricGroupIds and specificationIds is required.
["specification_123"]
Percentage of production sessions to evaluate (greater than 0, at most 100).
0 < x <= 10010
Optional monthly credit ceiling for this monitor. When set it must be a positive integer; it may exceed the organization monthly allocation (spend is clamped to the available balance). Null means uncapped.
x >= 1500
Optional content gate. Comma-separated terms; a session matches when at least one turn whose chosen target (filterTarget) contains ANY term (case-insensitive). Only matching sessions are sampled and evaluated; other sessions are skipped, spending no credits. Max 500 chars. Must be set together with filterTarget. Null means no content gate: every session that meets messageConditions is sampled.
500"refund, cancel, chargeback"
Which side of a turn filterQuery is matched against: INPUT (the user turn), OUTPUT (the agent turn), or EITHER. Must be set together with filterQuery.
INPUT, OUTPUT, EITHER, null "EITHER"
Optional exclude gate. Comma-separated terms; a session is dropped when at least one turn whose chosen target (excludeTarget) contains ANY term (case-insensitive). Applied on top of filterQuery: a session passes the content gate only when it passes filterQuery (if set) AND is not hit by excludeQuery. Max 500 chars. Must be set together with excludeTarget. Null means exclude nothing.
500"test, internal"
Which side of a turn excludeQuery is matched against: INPUT (the user turn), OUTPUT (the agent turn), or EITHER. Must be set together with excludeQuery.
INPUT, OUTPUT, EITHER, null "EITHER"
Conditions on the number of messages in a session, joined by AND: the monitor scores a session only when every condition holds. Sessions that fail are skipped and spend no credits. An empty list turns the filter off. A list no session can meet is refused, such as messages above 5 with messages at most 3, or more user messages than the messages allow: messages counts the user messages too. Defaults to messages above 1, which skips a session where only the agent spoke once.
10Show child attributes
Show child attributes
[
{
"count": "messages",
"operator": "gt",
"value": 1
}
]
Users may set ACTIVE or PAUSED; CAPPED and NO_CREDITS are system-set by the scanner, FAILING is reserved and never set yet, and all three are rejected on user writes.
ACTIVE, PAUSED, CAPPED, NO_CREDITS, FAILING "ACTIVE"
Response
Monitor created successfully. The Location header holds its path. The body holds only the monitor id when the read after the write fails; read the monitor by that id.
- Option 1
- Option 2
"monitor_123"
"prod_123"
Optional version to narrow the monitor to. When null the monitor watches the whole product.
"version_123"
"user_123"
"Production quality watch"
The metric families (Metric.metricGroupId) picked directly on the monitor. The list may be empty when specificationIds is set. The families the monitor scores are in scoredMetricGroupIds. The monitor binds the family, not a specific revision, so revising a metric is picked up automatically without editing the monitor.
["metricGroup_123"]
The Specifications (Specification.id) bound to the monitor. The monitor also scores the metrics each one links, so a metric added to or removed from a Specification takes effect on the next scan. Only Policy and Capability Specifications can be bound.
["specification_123"]
Read-only. The metric families the monitor scores: metricGroupIds plus the families of its bound Specifications that can score production sessions.
["metricGroup_123"]
Read-only. For each family a bound Specification brings, the ids of the bound Specifications that bring it.
Show child attributes
Show child attributes
{ "metricGroup_123": ["specification_123"] }
Percentage of production sessions to evaluate (greater than 0, at most 100).
0 < x <= 10010
Optional monthly credit ceiling for this monitor. When set it must be a positive integer; it may exceed the organization monthly allocation (spend is clamped to the available balance). Null means uncapped.
x >= 1500
Optional content gate. Comma-separated terms; a session matches when at least one turn whose chosen target (filterTarget) contains ANY term (case-insensitive). Only matching sessions are sampled and evaluated; other sessions are skipped, spending no credits. Max 500 chars. Must be set together with filterTarget. Null means no content gate: every session that meets messageConditions is sampled.
500"refund, cancel, chargeback"
Which side of a turn filterQuery is matched against: INPUT (the user turn), OUTPUT (the agent turn), or EITHER. Must be set together with filterQuery.
INPUT, OUTPUT, EITHER, null "EITHER"
Optional exclude gate. Comma-separated terms; a session is dropped when at least one turn whose chosen target (excludeTarget) contains ANY term (case-insensitive). Applied on top of filterQuery: a session passes the content gate only when it passes filterQuery (if set) AND is not hit by excludeQuery. Max 500 chars. Must be set together with excludeTarget. Null means exclude nothing.
500"test, internal"
Which side of a turn excludeQuery is matched against: INPUT (the user turn), OUTPUT (the agent turn), or EITHER. Must be set together with excludeQuery.
INPUT, OUTPUT, EITHER, null "EITHER"
Conditions on the number of messages in a session, joined by AND: the monitor scores a session only when every condition holds. Sessions that fail are skipped and spend no credits. An empty list turns the filter off.
10Show child attributes
Show child attributes
[
{
"count": "messages",
"operator": "gt",
"value": 1
}
]
Users may set ACTIVE or PAUSED; CAPPED and NO_CREDITS are system-set by the scanner, FAILING is reserved and never set yet, and all three are rejected on user writes.
ACTIVE, PAUSED, CAPPED, NO_CREDITS, FAILING "ACTIVE"
Read-only. Every family in scoredMetricGroupIds with its state, so a family that no longer scores stays visible and can be removed.
Show child attributes
Show child attributes