curl --request POST \
--url https://pillarforge.corepillar.ai/api/v1/traces/ingest \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"trace_id": "quickstart-0001",
"root_name": "agent_run",
"environment": "development",
"tags": [
"quickstart"
],
"spans": [
{
"span_id": "root",
"name": "agent_run",
"kind": "function",
"input": {
"user": "What is the capital of France?"
},
"output": {
"content": "Paris."
},
"started_at": "2026-03-17T10:00:00.000Z",
"ended_at": "2026-03-17T10:00:01.200Z"
},
{
"span_id": "llm-1",
"parent_span_id": "root",
"name": "chat.completions.create",
"kind": "llm",
"model": "gpt-4o-mini",
"tokens_in": 120,
"tokens_out": 45,
"cost_usd": 0.00012,
"latency_ms": 890,
"started_at": "2026-03-17T10:00:00.100Z",
"ended_at": "2026-03-17T10:00:00.990Z"
}
]
}
'import requests
url = "https://pillarforge.corepillar.ai/api/v1/traces/ingest"
payload = {
"trace_id": "quickstart-0001",
"root_name": "agent_run",
"environment": "development",
"tags": ["quickstart"],
"spans": [
{
"span_id": "root",
"name": "agent_run",
"kind": "function",
"input": { "user": "What is the capital of France?" },
"output": { "content": "Paris." },
"started_at": "2026-03-17T10:00:00.000Z",
"ended_at": "2026-03-17T10:00:01.200Z"
},
{
"span_id": "llm-1",
"parent_span_id": "root",
"name": "chat.completions.create",
"kind": "llm",
"model": "gpt-4o-mini",
"tokens_in": 120,
"tokens_out": 45,
"cost_usd": 0.00012,
"latency_ms": 890,
"started_at": "2026-03-17T10:00:00.100Z",
"ended_at": "2026-03-17T10:00:00.990Z"
}
]
}
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({
trace_id: 'quickstart-0001',
root_name: 'agent_run',
environment: 'development',
tags: ['quickstart'],
spans: [
{
span_id: 'root',
name: 'agent_run',
kind: 'function',
input: {user: 'What is the capital of France?'},
output: {content: 'Paris.'},
started_at: '2026-03-17T10:00:00.000Z',
ended_at: '2026-03-17T10:00:01.200Z'
},
{
span_id: 'llm-1',
parent_span_id: 'root',
name: 'chat.completions.create',
kind: 'llm',
model: 'gpt-4o-mini',
tokens_in: 120,
tokens_out: 45,
cost_usd: 0.00012,
latency_ms: 890,
started_at: '2026-03-17T10:00:00.100Z',
ended_at: '2026-03-17T10:00:00.990Z'
}
]
})
};
fetch('https://pillarforge.corepillar.ai/api/v1/traces/ingest', 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://pillarforge.corepillar.ai/api/v1/traces/ingest",
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([
'trace_id' => 'quickstart-0001',
'root_name' => 'agent_run',
'environment' => 'development',
'tags' => [
'quickstart'
],
'spans' => [
[
'span_id' => 'root',
'name' => 'agent_run',
'kind' => 'function',
'input' => [
'user' => 'What is the capital of France?'
],
'output' => [
'content' => 'Paris.'
],
'started_at' => '2026-03-17T10:00:00.000Z',
'ended_at' => '2026-03-17T10:00:01.200Z'
],
[
'span_id' => 'llm-1',
'parent_span_id' => 'root',
'name' => 'chat.completions.create',
'kind' => 'llm',
'model' => 'gpt-4o-mini',
'tokens_in' => 120,
'tokens_out' => 45,
'cost_usd' => 0.00012,
'latency_ms' => 890,
'started_at' => '2026-03-17T10:00:00.100Z',
'ended_at' => '2026-03-17T10:00:00.990Z'
]
]
]),
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://pillarforge.corepillar.ai/api/v1/traces/ingest"
payload := strings.NewReader("{\n \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\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://pillarforge.corepillar.ai/api/v1/traces/ingest")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pillarforge.corepillar.ai/api/v1/traces/ingest")
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 \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"trace_id": "quickstart-0001",
"project_id": "6f1c2a9e-3b0d-4c55-9a51-2f7d8e4b1c3a",
"span_count": 2,
"status": "OK"
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid trace payload.",
"details": {
"issues": {
"formErrors": [],
"fieldErrors": {
"spans": [
"Invalid datetime"
]
}
}
}
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "<string>",
"details": {}
}
}Ingest a trace
Store one trace with 1 to 500 spans. Authenticated with a project tracing key; the trace lands in the key’s project.
Ingestion is synchronous: the spans and the recomputed trace totals are stored before the 202 is sent. Resending a span_id replaces that span, so retries never duplicate data. Send an Idempotency-Key to have an exact retry return the original response without reprocessing.
See Trace format and Idempotency and retries.
curl --request POST \
--url https://pillarforge.corepillar.ai/api/v1/traces/ingest \
--header 'Authorization: Bearer <token>' \
--header 'Content-Type: application/json' \
--data '
{
"trace_id": "quickstart-0001",
"root_name": "agent_run",
"environment": "development",
"tags": [
"quickstart"
],
"spans": [
{
"span_id": "root",
"name": "agent_run",
"kind": "function",
"input": {
"user": "What is the capital of France?"
},
"output": {
"content": "Paris."
},
"started_at": "2026-03-17T10:00:00.000Z",
"ended_at": "2026-03-17T10:00:01.200Z"
},
{
"span_id": "llm-1",
"parent_span_id": "root",
"name": "chat.completions.create",
"kind": "llm",
"model": "gpt-4o-mini",
"tokens_in": 120,
"tokens_out": 45,
"cost_usd": 0.00012,
"latency_ms": 890,
"started_at": "2026-03-17T10:00:00.100Z",
"ended_at": "2026-03-17T10:00:00.990Z"
}
]
}
'import requests
url = "https://pillarforge.corepillar.ai/api/v1/traces/ingest"
payload = {
"trace_id": "quickstart-0001",
"root_name": "agent_run",
"environment": "development",
"tags": ["quickstart"],
"spans": [
{
"span_id": "root",
"name": "agent_run",
"kind": "function",
"input": { "user": "What is the capital of France?" },
"output": { "content": "Paris." },
"started_at": "2026-03-17T10:00:00.000Z",
"ended_at": "2026-03-17T10:00:01.200Z"
},
{
"span_id": "llm-1",
"parent_span_id": "root",
"name": "chat.completions.create",
"kind": "llm",
"model": "gpt-4o-mini",
"tokens_in": 120,
"tokens_out": 45,
"cost_usd": 0.00012,
"latency_ms": 890,
"started_at": "2026-03-17T10:00:00.100Z",
"ended_at": "2026-03-17T10:00:00.990Z"
}
]
}
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({
trace_id: 'quickstart-0001',
root_name: 'agent_run',
environment: 'development',
tags: ['quickstart'],
spans: [
{
span_id: 'root',
name: 'agent_run',
kind: 'function',
input: {user: 'What is the capital of France?'},
output: {content: 'Paris.'},
started_at: '2026-03-17T10:00:00.000Z',
ended_at: '2026-03-17T10:00:01.200Z'
},
{
span_id: 'llm-1',
parent_span_id: 'root',
name: 'chat.completions.create',
kind: 'llm',
model: 'gpt-4o-mini',
tokens_in: 120,
tokens_out: 45,
cost_usd: 0.00012,
latency_ms: 890,
started_at: '2026-03-17T10:00:00.100Z',
ended_at: '2026-03-17T10:00:00.990Z'
}
]
})
};
fetch('https://pillarforge.corepillar.ai/api/v1/traces/ingest', 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://pillarforge.corepillar.ai/api/v1/traces/ingest",
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([
'trace_id' => 'quickstart-0001',
'root_name' => 'agent_run',
'environment' => 'development',
'tags' => [
'quickstart'
],
'spans' => [
[
'span_id' => 'root',
'name' => 'agent_run',
'kind' => 'function',
'input' => [
'user' => 'What is the capital of France?'
],
'output' => [
'content' => 'Paris.'
],
'started_at' => '2026-03-17T10:00:00.000Z',
'ended_at' => '2026-03-17T10:00:01.200Z'
],
[
'span_id' => 'llm-1',
'parent_span_id' => 'root',
'name' => 'chat.completions.create',
'kind' => 'llm',
'model' => 'gpt-4o-mini',
'tokens_in' => 120,
'tokens_out' => 45,
'cost_usd' => 0.00012,
'latency_ms' => 890,
'started_at' => '2026-03-17T10:00:00.100Z',
'ended_at' => '2026-03-17T10:00:00.990Z'
]
]
]),
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://pillarforge.corepillar.ai/api/v1/traces/ingest"
payload := strings.NewReader("{\n \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\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://pillarforge.corepillar.ai/api/v1/traces/ingest")
.header("Authorization", "Bearer <token>")
.header("Content-Type", "application/json")
.body("{\n \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://pillarforge.corepillar.ai/api/v1/traces/ingest")
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 \"trace_id\": \"quickstart-0001\",\n \"root_name\": \"agent_run\",\n \"environment\": \"development\",\n \"tags\": [\n \"quickstart\"\n ],\n \"spans\": [\n {\n \"span_id\": \"root\",\n \"name\": \"agent_run\",\n \"kind\": \"function\",\n \"input\": {\n \"user\": \"What is the capital of France?\"\n },\n \"output\": {\n \"content\": \"Paris.\"\n },\n \"started_at\": \"2026-03-17T10:00:00.000Z\",\n \"ended_at\": \"2026-03-17T10:00:01.200Z\"\n },\n {\n \"span_id\": \"llm-1\",\n \"parent_span_id\": \"root\",\n \"name\": \"chat.completions.create\",\n \"kind\": \"llm\",\n \"model\": \"gpt-4o-mini\",\n \"tokens_in\": 120,\n \"tokens_out\": 45,\n \"cost_usd\": 0.00012,\n \"latency_ms\": 890,\n \"started_at\": \"2026-03-17T10:00:00.100Z\",\n \"ended_at\": \"2026-03-17T10:00:00.990Z\"\n }\n ]\n}"
response = http.request(request)
puts response.read_body{
"data": {
"trace_id": "quickstart-0001",
"project_id": "6f1c2a9e-3b0d-4c55-9a51-2f7d8e4b1c3a",
"span_count": 2,
"status": "OK"
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "Invalid trace payload.",
"details": {
"issues": {
"formErrors": [],
"fieldErrors": {
"spans": [
"Invalid datetime"
]
}
}
}
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "<string>",
"details": {}
}
}{
"error": {
"code": "VALIDATION_ERROR",
"message": "<string>",
"details": {}
}
}Authorizations
Project tracing key, from Settings → Tracing keys. Authorization: Bearer tk_live_.... The word Bearer is case-sensitive.
Headers
Optional. Scoped to the project. A repeated key returns the first successful response for that key and stores nothing new. Use a different key for each distinct batch.
Body
Your id for the run. Unique per project; reusing it adds to the same trace.
1 - 1281 - 500 elementsShow child attributes
Show child attributes
Label in the Traces list. Overwritten by every batch; resend it each time.
512Affects only this response's status. The stored status is derived from spans.
OK, ERROR 64live, simulation Optional. Restated as the earliest span start after ingest.
Replaces the trace's tags on every batch.
128Response
Trace stored.
Show child attributes
Show child attributes