Upsert an Auto Monitor Setup by External ID
curl --request PUT \
--url https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"selector": [
{}
],
"evaluators": [
"<string>"
],
"evaluator_configs": [
{}
]
}
'import requests
url = "https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}"
payload = {
"selector": [{}],
"evaluators": ["<string>"],
"evaluator_configs": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({selector: [{}], evaluators: ['<string>'], evaluator_configs: [{}]})
};
fetch('https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}', 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://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'selector' => [
[
]
],
'evaluators' => [
'<string>'
],
'evaluator_configs' => [
[
]
]
]),
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://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}"
payload := strings.NewReader("{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyAuto-monitor-setups
Upsert an Auto Monitor Setup by External ID
Idempotently create or fully replace an auto monitor setup identified by external ID
PUT
/
v2
/
auto-monitor-setups
/
by-external-id
/
{external_id}
Upsert an Auto Monitor Setup by External ID
curl --request PUT \
--url https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id} \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"selector": [
{}
],
"evaluators": [
"<string>"
],
"evaluator_configs": [
{}
]
}
'import requests
url = "https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}"
payload = {
"selector": [{}],
"evaluators": ["<string>"],
"evaluator_configs": [{}]
}
headers = {
"Authorization": "Bearer <token>",
"Content-Type": "application/json"
}
response = requests.put(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PUT',
headers: {Authorization: 'Bearer <token>', 'Content-Type': 'application/json'},
body: JSON.stringify({selector: [{}], evaluators: ['<string>'], evaluator_configs: [{}]})
};
fetch('https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}', 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://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PUT",
CURLOPT_POSTFIELDS => json_encode([
'selector' => [
[
]
],
'evaluators' => [
'<string>'
],
'evaluator_configs' => [
[
]
]
]),
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://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}"
payload := strings.NewReader("{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}")
req, _ := http.NewRequest("PUT", 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.put("https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://app.traceloop.com/api/v2/auto-monitor-setups/by-external-id/{external_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Put.new(url)
request["Authorization"] = 'Bearer <token>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"selector\": [\n {}\n ],\n \"evaluators\": [\n \"<string>\"\n ],\n \"evaluator_configs\": [\n {}\n ]\n}"
response = http.request(request)
puts response.read_bodyIdempotent full-replace of an auto monitor setup keyed by
external_id. If no setup with the given external_id exists for the org/project, one is created and the response is 201 Created. If a setup already exists, all fields in the body fully replace the existing record and the response is 200 OK.
The env_project_id is preserved across updates — it is only set on the create branch.
All API requests require authentication. Pass your API key as a Bearer token in the
Authorization header.
See Authentication for details.Path Parameters
string
required
The external ID of the auto monitor setup to create or replace.Example:
"my-agent-monitor-1"Request Body
object[]
required
An array of filter rules used to match spans. Each rule specifies an attribute key, a value to match, and a source indicating where the attribute lives. Only spans matching all provided rules will be evaluated. Must contain at least one filter.Each rule has the following fields:
| Field | Type | Required | Description |
|---|---|---|---|
key | string | Yes | The attribute key to filter on (e.g., gen_ai.system, service.name) |
value | string | Conditional | The value to match against. Required for equals, not_equals, contains, not_contains operators |
values | string[] | Conditional | List of values to match against. Required for in, not_in operators |
source | string | Yes | Where the attribute lives: span_attributes or resource_attributes |
operator | string | No | Comparison operator. Defaults to equals. One of: equals, not_equals, contains, not_contains, exists, not_exists, in, not_in |
string[]
List of evaluator slugs to run on matched spans. One of
evaluators or evaluator_configs is required.Example: ["answer-relevancy", "toxicity-detector"]See the full list of available slugs in the Evaluator Slugs reference.object[]
Per-evaluator configuration, used in place of
evaluators when you need to pass evaluator-specific options. One of evaluators or evaluator_configs is required.Example Request
curl -X PUT https://api.traceloop.com/v2/auto-monitor-setups/by-external-id/my-agent-monitor-1 \
-H "Authorization: Bearer YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"evaluators": ["answer-relevancy", "toxicity-detector"],
"selector": [
{"key": "gen_ai.system", "value": "openai", "source": "span_attributes"},
{"key": "gen_ai.request.model", "value": "gpt-4o", "source": "span_attributes"}
]
}'
Response
200 OK
Returned when an existing setup was replaced. The response body is the updated auto monitor setup.201 Created
Returned when a new setup was created. The response body is the newly created auto monitor setup. See the Create endpoint for the full response shape.{
"id": "cmm...",
"external_id": "my-agent-monitor-1",
"org_id": "c108269c-...",
"project_id": "cm9v2g95l...",
"env_project_id": "cm9v2ga9i...",
"init_rules": [
{
"key": "gen_ai.system",
"value": "openai",
"source": "span_attributes",
"operator": "equals"
},
{
"key": "gen_ai.request.model",
"value": "gpt-4o",
"source": "span_attributes",
"operator": "equals"
}
],
"evaluators": [
{
"evaluator_type": "answer-relevancy",
"status": "pending"
},
{
"evaluator_type": "toxicity-detector",
"status": "pending"
}
],
"status": "pending",
"created_at": "2026-01-15T10:30:00Z",
"updated_at": "2026-01-15T10:30:00Z"
}
400 Bad Request
Returned when the request body is invalid (e.g. emptyselector, missing both evaluators and evaluator_configs, or an unknown evaluator slug).
{
"error": "selector must have at least 1 filter"
}
500 Internal Server Error
{
"error": "internal server error"
}
Was this page helpful?

