curl --request POST \
--url https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"spans": [
{
"trace_id": "<string>",
"span_id": "<string>"
}
],
"mapping": {
"inputs": {
"question": "gen_ai.request.user_message"
},
"expected_outputs": {
"answer": "gen_ai.completion.content"
},
"metadata": {
"trace_id": "trace.id",
"model": "gen_ai.request.model"
},
"extras": {
"context": "gen_ai.contents.context"
}
},
"source_application_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans"
payload = {
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"spans": [
{
"trace_id": "<string>",
"span_id": "<string>"
}
],
"mapping": {
"inputs": { "question": "gen_ai.request.user_message" },
"expected_outputs": { "answer": "gen_ai.completion.content" },
"metadata": {
"trace_id": "trace.id",
"model": "gen_ai.request.model"
},
"extras": { "context": "gen_ai.contents.context" }
},
"source_application_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
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({
start_time: '2023-11-07T05:31:56Z',
end_time: '2023-11-07T05:31:56Z',
spans: [{trace_id: '<string>', span_id: '<string>'}],
mapping: {
inputs: {question: 'gen_ai.request.user_message'},
expected_outputs: {answer: 'gen_ai.completion.content'},
metadata: {trace_id: 'trace.id', model: 'gen_ai.request.model'},
extras: {context: 'gen_ai.contents.context'}
},
source_application_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans', 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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans",
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([
'start_time' => '2023-11-07T05:31:56Z',
'end_time' => '2023-11-07T05:31:56Z',
'spans' => [
[
'trace_id' => '<string>',
'span_id' => '<string>'
]
],
'mapping' => [
'inputs' => [
'question' => 'gen_ai.request.user_message'
],
'expected_outputs' => [
'answer' => 'gen_ai.completion.content'
],
'metadata' => [
'trace_id' => 'trace.id',
'model' => 'gen_ai.request.model'
],
'extras' => [
'context' => 'gen_ai.contents.context'
]
],
'source_application_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans"
payload := strings.NewReader("{\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans")
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 \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"api_version": "3.0",
"kind": "NORMAL",
"data": {
"items_created": 123,
"item_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"dataset_version": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": 123,
"tag": "<string>"
}
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"error": {
"code": 422,
"message": "One or more spans could not be resolved. No items were written.",
"errors": [
{
"reason": "SpanNotFound",
"message": "Span span-002-b (trace 4f9fa507) not found within the specified time range"
}
]
},
"api_version": "3.0",
"kind": "ERROR"
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}Bulk add spans to dataset
Accept a list of explicit span references and a field mapping, fetch span attributes from ClickHouse, apply the mapping server-side, and write one dataset item per span. All-or-nothing — if any span cannot be resolved, no items are written and a 422 is returned with the list of unresolvable spans.
start_time and end_time are required to bound the ClickHouse lookup to the relevant monthly partitions. Without them, the query would scan every partition for the application. The FE should pass the datagrid’s current time range; MCP agents should pass the time range of the spans being exported.
Mapping values are span attribute keys as returned by POST /v3/spans/fields (e.g. "gen_ai.usage.input_tokens", "user.cost_usd"). Each key maps to the corresponding value from the span’s span_attributes dict.
curl --request POST \
--url https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"spans": [
{
"trace_id": "<string>",
"span_id": "<string>"
}
],
"mapping": {
"inputs": {
"question": "gen_ai.request.user_message"
},
"expected_outputs": {
"answer": "gen_ai.completion.content"
},
"metadata": {
"trace_id": "trace.id",
"model": "gen_ai.request.model"
},
"extras": {
"context": "gen_ai.contents.context"
}
},
"source_application_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
'import requests
url = "https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans"
payload = {
"start_time": "2023-11-07T05:31:56Z",
"end_time": "2023-11-07T05:31:56Z",
"spans": [
{
"trace_id": "<string>",
"span_id": "<string>"
}
],
"mapping": {
"inputs": { "question": "gen_ai.request.user_message" },
"expected_outputs": { "answer": "gen_ai.completion.content" },
"metadata": {
"trace_id": "trace.id",
"model": "gen_ai.request.model"
},
"extras": { "context": "gen_ai.contents.context" }
},
"source_application_id": "3c90c3cc-0d44-4b50-8888-8dd25736052a"
}
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({
start_time: '2023-11-07T05:31:56Z',
end_time: '2023-11-07T05:31:56Z',
spans: [{trace_id: '<string>', span_id: '<string>'}],
mapping: {
inputs: {question: 'gen_ai.request.user_message'},
expected_outputs: {answer: 'gen_ai.completion.content'},
metadata: {trace_id: 'trace.id', model: 'gen_ai.request.model'},
extras: {context: 'gen_ai.contents.context'}
},
source_application_id: '3c90c3cc-0d44-4b50-8888-8dd25736052a'
})
};
fetch('https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans', 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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans",
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([
'start_time' => '2023-11-07T05:31:56Z',
'end_time' => '2023-11-07T05:31:56Z',
'spans' => [
[
'trace_id' => '<string>',
'span_id' => '<string>'
]
],
'mapping' => [
'inputs' => [
'question' => 'gen_ai.request.user_message'
],
'expected_outputs' => [
'answer' => 'gen_ai.completion.content'
],
'metadata' => [
'trace_id' => 'trace.id',
'model' => 'gen_ai.request.model'
],
'extras' => [
'context' => 'gen_ai.contents.context'
]
],
'source_application_id' => '3c90c3cc-0d44-4b50-8888-8dd25736052a'
]),
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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans"
payload := strings.NewReader("{\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\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.example.com/v3/evals/datasets/{dataset_id}/items/from-spans")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.example.com/v3/evals/datasets/{dataset_id}/items/from-spans")
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 \"start_time\": \"2023-11-07T05:31:56Z\",\n \"end_time\": \"2023-11-07T05:31:56Z\",\n \"spans\": [\n {\n \"trace_id\": \"<string>\",\n \"span_id\": \"<string>\"\n }\n ],\n \"mapping\": {\n \"inputs\": {\n \"question\": \"gen_ai.request.user_message\"\n },\n \"expected_outputs\": {\n \"answer\": \"gen_ai.completion.content\"\n },\n \"metadata\": {\n \"trace_id\": \"trace.id\",\n \"model\": \"gen_ai.request.model\"\n },\n \"extras\": {\n \"context\": \"gen_ai.contents.context\"\n }\n },\n \"source_application_id\": \"3c90c3cc-0d44-4b50-8888-8dd25736052a\"\n}"
response = http.request(request)
puts response.read_body{
"api_version": "3.0",
"kind": "NORMAL",
"data": {
"items_created": 123,
"item_ids": [
"3c90c3cc-0d44-4b50-8888-8dd25736052a"
],
"dataset_version": {
"id": "3c90c3cc-0d44-4b50-8888-8dd25736052a",
"version": 123,
"tag": "<string>"
}
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"error": {
"code": 422,
"message": "One or more spans could not be resolved. No items were written.",
"errors": [
{
"reason": "SpanNotFound",
"message": "Span span-002-b (trace 4f9fa507) not found within the specified time range"
}
]
},
"api_version": "3.0",
"kind": "ERROR"
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}{
"api_version": "3.0",
"kind": "ERROR",
"error": {
"code": 400,
"message": "Resource Not Found",
"errors": [
{
"reason": "ResourceNotFoundException",
"message": "Resource Not Found",
"help": "<string>"
}
]
}
}Authorizations
Body
Promote production spans into a dataset. By default spans are read from the dataset's own application. Supply source_application_id to promote spans from another application in the same project as the dataset — the project is the trust boundary, so a source application in a different project (or organization) is rejected with 403.
Was this page helpful?