curl --request PATCH \
--url https://api.lightsage.com/v2/eval-templates/{template_id} \
--header 'Content-Type: application/json' \
--header 'X-Lightsage-Api-Key: <api-key>' \
--data '
{
"expected_template_version": 1,
"name": "Crypto recommendation — daily",
"schedule": {
"enabled": true,
"frequency": "daily"
}
}
'import requests
url = "https://api.lightsage.com/v2/eval-templates/{template_id}"
payload = {
"expected_template_version": 1,
"name": "Crypto recommendation — daily",
"schedule": {
"enabled": True,
"frequency": "daily"
}
}
headers = {
"X-Lightsage-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Lightsage-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
expected_template_version: 1,
name: 'Crypto recommendation — daily',
schedule: {enabled: true, frequency: 'daily'}
})
};
fetch('https://api.lightsage.com/v2/eval-templates/{template_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://api.lightsage.com/v2/eval-templates/{template_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'expected_template_version' => 1,
'name' => 'Crypto recommendation — daily',
'schedule' => [
'enabled' => true,
'frequency' => 'daily'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Lightsage-Api-Key: <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.lightsage.com/v2/eval-templates/{template_id}"
payload := strings.NewReader("{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-Lightsage-Api-Key", "<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.patch("https://api.lightsage.com/v2/eval-templates/{template_id}")
.header("X-Lightsage-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.lightsage.com/v2/eval-templates/{template_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Lightsage-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2026-09-24T18:00:00Z",
"created_by": "0b6d843f-cd4e-4820-8999-5c6dac8ca6f2",
"description": "Reusable policy for crypto recommendation evals.",
"eval_type": "custom_eval",
"id": "58f3604e-d58e-4eb8-b1fe-3478be875c36",
"included_components": [
"judges",
"targets",
"schedule"
],
"judges": [
{
"blocking": false,
"criteria": "Pass only if CoinMarketCap is recommended as the first and main choice. Fail otherwise.",
"name": "CoinMarketCap first",
"type": "judge",
"weight": 1
}
],
"name": "Crypto recommendation",
"org_id": "ab9fe05c-5224-4d9b-a382-a23834ec1947",
"schedule": {
"enabled": true,
"frequency": "daily"
},
"target_keys": [
"agent:codex:gpt-5.6-terra",
"agent:claude-code:global.anthropic.claude-sonnet-5"
],
"updated_at": "2026-09-24T18:00:00Z",
"version": 1
}{
"detail": "Unknown or inactive competitor ID"
}{
"detail": "Eval template not found"
}{
"detail": "The Eval template changed after it was loaded. Refresh and try again."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Update an Eval template
Updates an Eval template. Supply expected_template_version to reject an edit based on stale data. Existing evals are never changed.
curl --request PATCH \
--url https://api.lightsage.com/v2/eval-templates/{template_id} \
--header 'Content-Type: application/json' \
--header 'X-Lightsage-Api-Key: <api-key>' \
--data '
{
"expected_template_version": 1,
"name": "Crypto recommendation — daily",
"schedule": {
"enabled": true,
"frequency": "daily"
}
}
'import requests
url = "https://api.lightsage.com/v2/eval-templates/{template_id}"
payload = {
"expected_template_version": 1,
"name": "Crypto recommendation — daily",
"schedule": {
"enabled": True,
"frequency": "daily"
}
}
headers = {
"X-Lightsage-Api-Key": "<api-key>",
"Content-Type": "application/json"
}
response = requests.patch(url, json=payload, headers=headers)
print(response.text)const options = {
method: 'PATCH',
headers: {'X-Lightsage-Api-Key': '<api-key>', 'Content-Type': 'application/json'},
body: JSON.stringify({
expected_template_version: 1,
name: 'Crypto recommendation — daily',
schedule: {enabled: true, frequency: 'daily'}
})
};
fetch('https://api.lightsage.com/v2/eval-templates/{template_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://api.lightsage.com/v2/eval-templates/{template_id}",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "PATCH",
CURLOPT_POSTFIELDS => json_encode([
'expected_template_version' => 1,
'name' => 'Crypto recommendation — daily',
'schedule' => [
'enabled' => true,
'frequency' => 'daily'
]
]),
CURLOPT_HTTPHEADER => [
"Content-Type: application/json",
"X-Lightsage-Api-Key: <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.lightsage.com/v2/eval-templates/{template_id}"
payload := strings.NewReader("{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}")
req, _ := http.NewRequest("PATCH", url, payload)
req.Header.Add("X-Lightsage-Api-Key", "<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.patch("https://api.lightsage.com/v2/eval-templates/{template_id}")
.header("X-Lightsage-Api-Key", "<api-key>")
.header("Content-Type", "application/json")
.body("{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}")
.asString();require 'uri'
require 'net/http'
url = URI("https://api.lightsage.com/v2/eval-templates/{template_id}")
http = Net::HTTP.new(url.host, url.port)
http.use_ssl = true
request = Net::HTTP::Patch.new(url)
request["X-Lightsage-Api-Key"] = '<api-key>'
request["Content-Type"] = 'application/json'
request.body = "{\n \"expected_template_version\": 1,\n \"name\": \"Crypto recommendation — daily\",\n \"schedule\": {\n \"enabled\": true,\n \"frequency\": \"daily\"\n }\n}"
response = http.request(request)
puts response.read_body{
"created_at": "2026-09-24T18:00:00Z",
"created_by": "0b6d843f-cd4e-4820-8999-5c6dac8ca6f2",
"description": "Reusable policy for crypto recommendation evals.",
"eval_type": "custom_eval",
"id": "58f3604e-d58e-4eb8-b1fe-3478be875c36",
"included_components": [
"judges",
"targets",
"schedule"
],
"judges": [
{
"blocking": false,
"criteria": "Pass only if CoinMarketCap is recommended as the first and main choice. Fail otherwise.",
"name": "CoinMarketCap first",
"type": "judge",
"weight": 1
}
],
"name": "Crypto recommendation",
"org_id": "ab9fe05c-5224-4d9b-a382-a23834ec1947",
"schedule": {
"enabled": true,
"frequency": "daily"
},
"target_keys": [
"agent:codex:gpt-5.6-terra",
"agent:claude-code:global.anthropic.claude-sonnet-5"
],
"updated_at": "2026-09-24T18:00:00Z",
"version": 1
}{
"detail": "Unknown or inactive competitor ID"
}{
"detail": "Eval template not found"
}{
"detail": "The Eval template changed after it was loaded. Refresh and try again."
}{
"detail": [
{
"loc": [
"<string>"
],
"msg": "<string>",
"type": "<string>",
"input": "<unknown>",
"ctx": {}
}
]
}Authorizations
Path Parameters
Body
x >= 11 - 160100020000custom_eval, agent_preference 1judges, targets, persona, competitors, tag, category, runs, schedule, repository, environment, search_grounding, skills, mcp_servers, clis, brand_docs, github_pr, runtime_commands 50016010020Show child attributes
Show child attributes
Schedule copied into every eval created from the template.
Show child attributes
Show child attributes
1 <= x <= 20Reusable runtime resources copied into each created eval.
Show child attributes
Show child attributes
Response
Successful Response
Organization-visible name for this reusable template.
1 - 160Settings copied when the template is applied. Omitted components do not override the new eval; included components copy their saved value, including an empty value.
1judges, targets, persona, competitors, tag, category, runs, schedule, repository, environment, search_grounding, skills, mcp_servers, clis, brand_docs, github_pr, runtime_commands Optional guidance describing when to use the template.
1000Prompt filled into the new eval form when the template is applied, or the scenario for Agent Preference, where {{competitor_name}} names the brand each comparison is against. Requests that create evals from a template still supply their own prompts.
20000Kind of eval the template creates. A template only applies to evals of the same type.
custom_eval, agent_preference Optional persona copied when persona is included.
500Optional category copied when category is included.
160Optional tag copied when tag is included.
100Competitor IDs that create additional variants when competitors is included.
Judge definitions copied when judges is included. May be empty to explicitly create the eval without template judges.
20Show child attributes
Show child attributes
Runnable target keys copied when targets is included, such as agent:codex:gpt-5.6-terra.
Schedule copied when schedule is included.
Show child attributes
Show child attributes
Attempt count copied when runs is included.
1 <= x <= 20Saved runtime values. Each value is copied only when its matching component appears in included_components.
Show child attributes
Show child attributes