[{"data":1,"prerenderedAt":1471},["ShallowReactive",2],{"docs-\u002Fapi\u002Fai-transform":3},{"id":4,"title":5,"body":6,"description":1463,"extension":1464,"meta":1465,"navigation":1466,"path":1467,"seo":1468,"stem":1469,"__hash__":1470},"docs\u002Fdocs\u002Fapi\u002Fai-transform.md","AI Transform API",{"type":7,"value":8,"toc":1423},"minimark",[9,13,32,35,38,43,83,90,92,96,99,180,185,284,299,301,305,356,361,363,367,370,373,410,413,419,429,435,462,464,468,528,534,536,540,593,595,599,606,623,625,629,654,656,660,675,690,699,714,716,720,723,729,732,757,763,766,800,806,809,836,842,845,866,872,875,894,899,902,933,939,949,956,1017,1023,1026,1070,1076,1079,1098,1104,1107,1126,1132,1135,1170,1172,1176,1179,1185,1188,1207,1213,1223,1251,1257,1260,1281,1287,1293,1324,1330,1337,1358,1364,1367,1395,1401,1404],[10,11,5],"h1",{"id":12},"ai-transform-api",[14,15,16],"blockquote",{},[17,18,19,23,24,31],"p",{},[20,21,22],"strong",{},"Preview feature."," AI Transform is in active preview — the API surface, rule semantics, rate limits, and per-token pricing may change before general availability. Suitable for evaluation and non-critical workloads. Production deployments should pin a specific SDK version, monitor token spend in the dashboard, and avoid putting AI-rewritten responses on user-blocking critical paths until GA. See the ",[25,26,30],"a",{"href":27,"rel":28},"https:\u002F\u002Fstatus.cachely.io",[29],"nofollow","Cachely status page"," for any active limitations.",[17,33,34],{},"AI Transforms let you rewrite, translate, shorten, or otherwise adapt CMS JSON responses at the Cachely proxy layer. The transformed result is what your frontend receives — the source CMS entry is never modified.",[36,37],"hr",{},[39,40,42],"h2",{"id":41},"how-it-works","How it works",[44,45,46,54,70,77,80],"ol",{},[47,48,49,50,53],"li",{},"You define one or more ",[20,51,52],{},"rules"," for a project. Each rule targets specific JSON fields and describes a transformation (translate, shorten, rewrite tone, or a custom instruction).",[47,55,56,57,60,61,65,66,69],{},"Rules are grouped by an optional ",[20,58,59],{},"profile"," label (e.g. ",[62,63,64],"code",{},"\"de\"",", ",[62,67,68],{},"\"editorial\"",").",[47,71,72,73,76],{},"At request time, adding ",[62,74,75],{},"?transform=\u003Cprofile>"," to an API proxy request activates all active rules with that profile.",[47,78,79],{},"The proxy executes the transformation server-side and returns the adapted JSON to the client.",[47,81,82],{},"Transformed responses are cached at the edge — repeat requests with the same profile serve from cache without re-running the LLM.",[17,84,85,86,89],{},"AI Transforms only operate on ",[62,87,88],{},"application\u002Fjson"," upstream responses. Asset responses, HTML, and non-JSON payloads are never transformed.",[36,91],{},[39,93,95],{"id":94},"rule-configuration","Rule configuration",[17,97,98],{},"Each rule requires:",[100,101,102,118],"table",{},[103,104,105],"thead",{},[106,107,108,112,115],"tr",{},[109,110,111],"th",{},"Field",[109,113,114],{},"Required",[109,116,117],{},"Description",[119,120,121,142,154,167],"tbody",{},[106,122,123,129,132],{},[124,125,126],"td",{},[62,127,128],{},"fieldSelector",[124,130,131],{},"Yes",[124,133,134,135,65,138,141],{},"Dot-notation path to one or more fields (e.g. ",[62,136,137],{},"fields.title",[62,139,140],{},"data.items[*].description",")",[106,143,144,149,151],{},[124,145,146],{},[62,147,148],{},"presetId",[124,150,131],{},[124,152,153],{},"The transformation type — see presets below",[106,155,156,161,164],{},[124,157,158],{},[62,159,160],{},"routePattern",[124,162,163],{},"No",[124,165,166],{},"Path prefix filter; only requests matching this prefix trigger the rule",[106,168,169,173,175],{},[124,170,171],{},[62,172,59],{},[124,174,163],{},[124,176,177,178],{},"A string label used to group rules and activate them at runtime via ",[62,179,75],{},[181,182,184],"h3",{"id":183},"preset-modes","Preset modes",[100,186,187,200],{},[103,188,189],{},[106,190,191,194,197],{},[109,192,193],{},"Preset",[109,195,196],{},"What it does",[109,198,199],{},"Additional options",[119,201,202,227,240,260],{},[106,203,204,209,212],{},[124,205,206],{},[62,207,208],{},"rewrite_tone",[124,210,211],{},"Rewrites content in a different tone",[124,213,214,217,218,65,221,65,224,141],{},[62,215,216],{},"tone"," (e.g. ",[62,219,220],{},"formal",[62,222,223],{},"casual",[62,225,226],{},"playful",[106,228,229,234,237],{},[124,230,231],{},[62,232,233],{},"shorten",[124,235,236],{},"Condenses the field to fewer words",[124,238,239],{},"—",[106,241,242,247,250],{},[124,243,244],{},[62,245,246],{},"translate",[124,248,249],{},"Translates the field to another language",[124,251,252,217,255,65,257,141],{},[62,253,254],{},"targetLanguage",[62,256,64],{},[62,258,259],{},"\"fr\"",[106,261,262,267,270],{},[124,263,264],{},[62,265,266],{},"custom",[124,268,269],{},"Applies a free-form GPT instruction",[124,271,272,275,276,279,280,283],{},[62,273,274],{},"customInstruction"," (text); optionally ",[62,277,278],{},"constraints"," and an ",[62,281,282],{},"example"," input\u002Foutput pair",[17,285,286,287,290,291,294,295,298],{},"Array fields use ",[62,288,289],{},"[*]"," notation — for example, ",[62,292,293],{},"items[*].title"," targets the ",[62,296,297],{},"title"," field of every item in an array.",[36,300],{},[39,302,304],{"id":303},"rule-statuses","Rule statuses",[100,306,307,320],{},[103,308,309],{},[106,310,311,314,317],{},[109,312,313],{},"Status",[109,315,316],{},"Preview",[109,318,319],{},"Runtime",[119,321,322,333,345],{},[106,323,324,329,331],{},[124,325,326],{},[62,327,328],{},"active",[124,330,131],{},[124,332,131],{},[106,334,335,340,342],{},[124,336,337],{},[62,338,339],{},"draft",[124,341,131],{},[124,343,344],{},"No — never runs on live traffic",[106,346,347,352,354],{},[124,348,349],{},[62,350,351],{},"paused",[124,353,163],{},[124,355,163],{},[17,357,358,360],{},[62,359,339],{}," is the default status for newly created rules. Activate a rule explicitly before it affects production traffic.",[36,362],{},[39,364,366],{"id":365},"preview-vs-runtime","Preview vs. runtime",[181,368,316],{"id":369},"preview",[17,371,372],{},"Preview lets you test a transformation against sample content before activating a rule.",[374,375,376,385,388,398,404],"ul",{},[47,377,378,381,382],{},[20,379,380],{},"Endpoint:"," ",[62,383,384],{},"POST \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Fpreview",[47,386,387],{},"Runs immediately; no production traffic is affected",[47,389,390,393,394,397],{},[20,391,392],{},"Fail-closed:"," if token limits are exceeded, the request returns HTTP ",[62,395,396],{},"429",". The error is shown in the admin panel.",[47,399,400,401],{},"Processes up to ",[20,402,403],{},"5 fields per request",[47,405,406,407],{},"Recorded in the run log with ",[62,408,409],{},"mode: \"preview\"",[181,411,319],{"id":412},"runtime",[17,414,415,416,418],{},"Runtime transforms run on live API proxy traffic when a request includes ",[62,417,75],{},".",[420,421,426],"pre",{"className":422,"code":424,"language":425},[423],"language-text","GET \u002F~api\u002Fentries?transform=editorial\nGET \u002F~api\u002Fentries?transform=de\n","text",[62,427,424],{"__ignoreMap":428},"",[17,430,431,432,434],{},"The profile value must match the ",[62,433,59],{}," field on at least one active rule. If no active rule matches, the request passes through untransformed.",[374,436,437,447,457],{},[47,438,439,442,443,446],{},[20,440,441],{},"Fail-open:"," if token limits are exceeded or the LLM call fails, the original (untransformed) JSON is returned with ",[62,444,445],{},"status: \"passthrough\"",". No error is returned to the end client.",[47,448,400,449,452,453,456],{},[20,450,451],{},"20 fields per rule"," (subject to the tenant-level ",[62,454,455],{},"maxFieldsPerResponse"," limit)",[47,458,406,459],{},[62,460,461],{},"mode: \"runtime\"",[36,463],{},[39,465,467],{"id":466},"usage-and-limits","Usage and limits",[100,469,470,483],{},[103,471,472],{},[106,473,474,477,480],{},[109,475,476],{},"Limit",[109,478,479],{},"Default",[109,481,482],{},"Notes",[119,484,485,496,506,517],{},[106,486,487,490,493],{},[124,488,489],{},"Monthly token cap",[124,491,492],{},"none",[124,494,495],{},"Total input + output tokens per calendar month (UTC)",[106,497,498,501,503],{},[124,499,500],{},"Daily token cap",[124,502,492],{},[124,504,505],{},"Total input + output tokens per UTC day",[106,507,508,511,514],{},[124,509,510],{},"Max fields per response",[124,512,513],{},"20 (runtime), 5 (preview)",[124,515,516],{},"Global across all rules in one request",[106,518,519,522,525],{},[124,520,521],{},"Max characters per field",[124,523,524],{},"8,000",[124,526,527],{},"Configurable down, not up",[17,529,530,531,533],{},"When a runtime transform is skipped because a limit is exceeded, the run log records ",[62,532,445],{}," with a reason string. Check the run detail to diagnose limit-related skips.",[36,535],{},[39,537,539],{"id":538},"run-status-values","Run status values",[100,541,542,551],{},[103,543,544],{},[106,545,546,548],{},[109,547,313],{},[109,549,550],{},"Meaning",[119,552,553,563,573,583],{},[106,554,555,560],{},[124,556,557],{},[62,558,559],{},"applied",[124,561,562],{},"All targeted fields were transformed successfully",[106,564,565,570],{},[124,566,567],{},[62,568,569],{},"partial",[124,571,572],{},"Some fields transformed; others failed (e.g. per-field LLM error)",[106,574,575,580],{},[124,576,577],{},[62,578,579],{},"passthrough",[124,581,582],{},"Original content returned unchanged — no matching active rules, non-JSON upstream response, or limits exceeded",[106,584,585,590],{},[124,586,587],{},[62,588,589],{},"error",[124,591,592],{},"Execution failed entirely (LLM error, timeout, etc.)",[36,594],{},[39,596,598],{"id":597},"observability","Observability",[17,600,601,602,605],{},"The ",[20,603,604],{},"Recent Runs"," panel in the admin dashboard shows:",[374,607,608,617,620],{},[47,609,610,611,613,614,616],{},"Timestamp, mode (",[62,612,369],{}," \u002F ",[62,615,412],{},"), profile, status, fields attempted, rules evaluated, latency, token usage",[47,618,619],{},"Filters by mode, status, and profile",[47,621,622],{},"Expanding a row shows rule summary, per-field error details, and limit reason where applicable",[36,624],{},[39,626,628],{"id":627},"what-ai-transforms-do-not-do","What AI Transforms do not do",[374,630,631,634,637,643,646,649],{},[47,632,633],{},"They do not modify images, video, or any non-text content",[47,635,636],{},"They do not transform asset proxy responses",[47,638,639,640,642],{},"They do not process HTML — only ",[62,641,88],{}," upstream responses",[47,644,645],{},"They do not run on non-GET requests",[47,647,648],{},"They do not guarantee deterministic output — LLM responses vary between runs",[47,650,651,653],{},[62,652,339],{}," rules never run in production, regardless of profile name",[36,655],{},[39,657,659],{"id":658},"common-issues","Common issues",[17,661,662,665,666,668,669,671,672,674],{},[20,663,664],{},"Transforms not running in production:"," check that the rule status is ",[62,667,328],{}," (not ",[62,670,339],{},") and that the ",[62,673,75],{}," value matches the rule's profile field exactly — case-sensitive.",[17,676,677,680,681,683,684,686,687,69],{},[20,678,679],{},"Wrong fields being transformed:"," array fields require ",[62,682,289],{}," notation (e.g. ",[62,685,293],{},", not ",[62,688,689],{},"items.title",[17,691,692,698],{},[20,693,694,695,697],{},"Runtime returning ",[62,696,579],{}," unexpectedly:"," check the run detail for the reason — exceeded token limits are the most common cause.",[17,700,701,704,705,707,708,710,711,713],{},[20,702,703],{},"Preview works but runtime does not:"," preview evaluates ",[62,706,339],{}," + ",[62,709,328],{}," rules; runtime evaluates only ",[62,712,328],{}," rules.",[36,715],{},[39,717,719],{"id":718},"api-reference","API reference",[17,721,722],{},"All endpoints require a Clerk session. Role requirements are noted per endpoint.",[181,724,726],{"id":725},"get-apitenantsslugai-transformrules",[62,727,728],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Frules",[17,730,731],{},"List all AI transform rules for a tenant.",[374,733,734,740,748],{},[47,735,736,739],{},[20,737,738],{},"Auth:"," Clerk session + tenant access (viewer+)",[47,741,742,381,745],{},[20,743,744],{},"Response:",[62,746,747],{},"{ rules[] }",[47,749,750,381,753,756],{},[20,751,752],{},"Errors:",[62,754,755],{},"404"," tenant not found",[181,758,760],{"id":759},"post-apitenantsslugai-transformrules",[62,761,762],{},"POST \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Frules",[17,764,765],{},"Create a new AI transform rule.",[374,767,768,773,781,786],{},[47,769,770,772],{},[20,771,738],{}," Clerk session + tenant access (editor+)",[47,774,775,381,778],{},[20,776,777],{},"Body:",[62,779,780],{},"{ presetId, fieldSelector, routePattern?, profile?, targetLanguage?, tone?, customInstruction? }",[47,782,783,785],{},[20,784,744],{}," Created rule object",[47,787,788,381,790,793,794,797,798,756],{},[20,789,752],{},[62,791,792],{},"400"," validation, ",[62,795,796],{},"403"," insufficient role, ",[62,799,755],{},[181,801,803],{"id":802},"put-apitenantsslugai-transformrulesid",[62,804,805],{},"PUT \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Frules\u002F{id}",[17,807,808],{},"Update an existing rule.",[374,810,811,815,820,825],{},[47,812,813,772],{},[20,814,738],{},[47,816,817,819],{},[20,818,777],{}," Changed fields (partial update)",[47,821,822,824],{},[20,823,744],{}," Updated rule object",[47,826,827,381,829,793,831,65,833,835],{},[20,828,752],{},[62,830,792],{},[62,832,796],{},[62,834,755],{}," rule not found",[181,837,839],{"id":838},"delete-apitenantsslugai-transformrulesid",[62,840,841],{},"DELETE \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Frules\u002F{id}",[17,843,844],{},"Delete a rule.",[374,846,847,851,858],{},[47,848,849,772],{},[20,850,738],{},[47,852,853,381,855],{},[20,854,744],{},[62,856,857],{},"{ ok }",[47,859,860,381,862,65,864,835],{},[20,861,752],{},[62,863,796],{},[62,865,755],{},[181,867,869],{"id":868},"post-apitenantsslugai-transformrulesidactivate",[62,870,871],{},"POST \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Frules\u002F{id}\u002Factivate",[17,873,874],{},"Toggle the active\u002Fdraft status of a rule.",[374,876,877,881,886],{},[47,878,879,772],{},[20,880,738],{},[47,882,883,885],{},[20,884,744],{}," Updated rule with new status",[47,887,888,381,890,65,892,835],{},[20,889,752],{},[62,891,796],{},[62,893,755],{},[181,895,897],{"id":896},"post-apitenantsslugai-transformpreview",[62,898,384],{},[17,900,901],{},"Preview a transformation without saving or affecting production traffic.",[374,903,904,908,913,920],{},[47,905,906,772],{},[20,907,738],{},[47,909,910,912],{},[20,911,777],{}," Rule config + sample content",[47,914,915,381,917],{},[20,916,744],{},[62,918,919],{},"{ original, transformed }",[47,921,922,381,924,793,926,65,928,65,930,932],{},[20,923,752],{},[62,925,792],{},[62,927,796],{},[62,929,755],{},[62,931,396],{}," token limit exceeded",[181,934,936],{"id":935},"post-apitenantsslugai-transformregenerate",[62,937,938],{},"POST \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Fregenerate",[17,940,941,942,945,946,948],{},"Force-refresh the edge cache for a single ",[62,943,944],{},"(profile, apiPath)"," pair. The handler fetches the upstream CMS response, applies the same URL rewrites the Worker would, runs the active rules through the runtime AI pipeline, and bumps a per-(tenant, profile) cache version so the next public ",[62,947,75],{}," request misses and stores the regenerated body.",[17,950,951,952,955],{},"Use this when an active rule has been edited and you want the next visitor to see the new AI output immediately, or when the LLM produced a one-off bad answer that you want to overwrite without changing any rule. Cache invalidation is scoped to the ",[62,953,954],{},"(tenant, profile)"," pair — no global cache wipe.",[374,957,958,962,982,1001],{},[47,959,960,772],{},[20,961,738],{},[47,963,964,381,966,969,970,973,974,977,978,981],{},[20,965,777],{},[62,967,968],{},"{ profile: string, apiPath: string }"," — ",[62,971,972],{},"apiPath"," must start with ",[62,975,976],{},"\u002F","; an optional leading ",[62,979,980],{},"\u002F~api"," prefix is stripped",[47,983,984,381,986,969,989,992,993,996,997,1000],{},[20,985,744],{},[62,987,988],{},"{ profile, apiPath, regenVersion, status, skipReason, errorCode, stats, body }",[62,990,991],{},"body"," is the regenerated JSON, ",[62,994,995],{},"regenVersion"," is the new per-profile counter, ",[62,998,999],{},"status"," mirrors the run status values above",[47,1002,1003,381,1005,1007,1008,797,1010,1012,1013,1016],{},[20,1004,752],{},[62,1006,792],{}," validation or non-JSON upstream, ",[62,1009,796],{},[62,1011,755],{}," tenant not found \u002F no active rules \u002F no rules match the path, ",[62,1014,1015],{},"502"," upstream CMS error",[181,1018,1020],{"id":1019},"get-apitenantsslugai-transformruns",[62,1021,1022],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Fruns",[17,1024,1025],{},"List recent transform runs with optional filters.",[374,1027,1028,1032,1057,1064],{},[47,1029,1030,739],{},[20,1031,738],{},[47,1033,1034,381,1037,65,1040,65,1043,1046,1047,1049,1050,1052,1053,65,1055],{},[20,1035,1036],{},"Query params:",[62,1038,1039],{},"limit",[62,1041,1042],{},"offset",[62,1044,1045],{},"mode"," (",[62,1048,369],{}," | ",[62,1051,412],{},"), ",[62,1054,999],{},[62,1056,59],{},[47,1058,1059,381,1061],{},[20,1060,744],{},[62,1062,1063],{},"{ runs[], total }",[47,1065,1066,381,1068,756],{},[20,1067,752],{},[62,1069,755],{},[181,1071,1073],{"id":1072},"get-apitenantsslugai-transformusage",[62,1074,1075],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Fusage",[17,1077,1078],{},"Return current token usage and configured limits for the tenant.",[374,1080,1081,1085,1092],{},[47,1082,1083,739],{},[20,1084,738],{},[47,1086,1087,381,1089],{},[20,1088,744],{},[62,1090,1091],{},"{ monthly: TokenUsage, daily: TokenUsage, limits }",[47,1093,1094,381,1096,756],{},[20,1095,752],{},[62,1097,755],{},[181,1099,1101],{"id":1100},"get-apitenantsslugai-transformprofiles",[62,1102,1103],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-transform\u002Fprofiles",[17,1105,1106],{},"Return the list of distinct profile slugs that have at least one active rule for the tenant. Used by the AI Experiments variant editor to populate the profile dropdown — activation validation in the experiments API enforces the same constraint server-side.",[374,1108,1109,1113,1120],{},[47,1110,1111,739],{},[20,1112,738],{},[47,1114,1115,381,1117],{},[20,1116,744],{},[62,1118,1119],{},"{ profiles: string[] }",[47,1121,1122,381,1124,756],{},[20,1123,752],{},[62,1125,755],{},[181,1127,1129],{"id":1128},"post-apiai-transformexecute",[62,1130,1131],{},"POST \u002Fapi\u002Fai-transform\u002Fexecute",[17,1133,1134],{},"Internal execution endpoint called by the edge Worker for live transform profiles. Not intended for direct use.",[374,1136,1137,1145,1150,1155],{},[47,1138,1139,381,1141,1144],{},[20,1140,738],{},[62,1142,1143],{},"X-AI-Transform-Key"," header — shared secret between the proxy Worker and Nitro",[47,1146,1147,1149],{},[20,1148,777],{}," Transform profile, request URL, and JSON payload",[47,1151,1152,1154],{},[20,1153,744],{}," Transformed JSON payload",[47,1156,1157,381,1159,1162,1163,1165,1166,1169],{},[20,1158,752],{},[62,1160,1161],{},"401"," invalid key, ",[62,1164,792],{}," missing fields, ",[62,1167,1168],{},"500"," transform failure",[36,1171],{},[39,1173,1175],{"id":1174},"ai-experiments-api","AI Experiments API",[17,1177,1178],{},"AI Experiments let you A\u002FB test content variants at the proxy layer. An experiment defines a route pattern and a set of named variants; the Worker selects a variant per request and returns the matching content.",[181,1180,1182],{"id":1181},"get-apitenantsslugai-experiments",[62,1183,1184],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments",[17,1186,1187],{},"List all non-archived AI experiments and their variants for the tenant.",[374,1189,1190,1194,1201],{},[47,1191,1192,739],{},[20,1193,738],{},[47,1195,1196,381,1198],{},[20,1197,744],{},[62,1199,1200],{},"{ experiments[] }",[47,1202,1203,381,1205,756],{},[20,1204,752],{},[62,1206,755],{},[181,1208,1210],{"id":1209},"post-apitenantsslugai-experiments",[62,1211,1212],{},"POST \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments",[17,1214,1215,1216,1218,1219,1222],{},"Create a new AI experiment in ",[62,1217,339],{}," status. Pass an optional ",[62,1220,1221],{},"variants"," array to set the initial variant set in the same call.",[374,1224,1225,1229,1236,1241],{},[47,1226,1227,772],{},[20,1228,738],{},[47,1230,1231,381,1233],{},[20,1232,777],{},[62,1234,1235],{},"{ name, routePattern?, routeMatch?, variants?: [{ key, weight?, config? }] }",[47,1237,1238,1240],{},[20,1239,744],{}," Created experiment object with variants",[47,1242,1243,381,1245,793,1247,797,1249,756],{},[20,1244,752],{},[62,1246,792],{},[62,1248,796],{},[62,1250,755],{},[181,1252,1254],{"id":1253},"get-apitenantsslugai-experimentsid",[62,1255,1256],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments\u002F{id}",[17,1258,1259],{},"Return a single experiment and its current variants.",[374,1261,1262,1266,1271],{},[47,1263,1264,739],{},[20,1265,738],{},[47,1267,1268,1270],{},[20,1269,744],{}," Experiment object with variants",[47,1272,1273,381,1275,1277,1278,1280],{},[20,1274,752],{},[62,1276,792],{}," invalid id, ",[62,1279,755],{}," experiment or tenant not found",[181,1282,1284],{"id":1283},"patch-apitenantsslugai-experimentsid",[62,1285,1286],{},"PATCH \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments\u002F{id}",[17,1288,1289,1290,1292],{},"Update an experiment's name, route pattern, route match, or status. Transitioning status to ",[62,1291,328],{}," runs activation validation (variant count, profile existence, route overlap). On success the proxy KV config is re-synced so the Worker picks up the change within its cache TTL.",[374,1294,1295,1299,1307,1312],{},[47,1296,1297,772],{},[20,1298,738],{},[47,1300,1301,1303,1304],{},[20,1302,777],{}," Partial update — any combination of ",[62,1305,1306],{},"{ name?, routePattern?, routeMatch?, status? }",[47,1308,1309,1311],{},[20,1310,744],{}," Updated experiment object",[47,1313,1314,381,1316,1318,1319,65,1321,1323],{},[20,1315,752],{},[62,1317,792],{}," validation or activation validation failure, ",[62,1320,796],{},[62,1322,755],{}," experiment not found",[181,1325,1327],{"id":1326},"delete-apitenantsslugai-experimentsid",[62,1328,1329],{},"DELETE \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments\u002F{id}",[17,1331,1332,1333,1336],{},"Soft-archive an experiment (sets status to ",[62,1334,1335],{},"archived","). The row and variants are preserved so historical request log entries remain joinable.",[374,1338,1339,1343,1348],{},[47,1340,1341,772],{},[20,1342,738],{},[47,1344,1345,1347],{},[20,1346,744],{}," Archived experiment object",[47,1349,1350,381,1352,1277,1354,65,1356,1323],{},[20,1351,752],{},[62,1353,792],{},[62,1355,796],{},[62,1357,755],{},[181,1359,1361],{"id":1360},"put-apitenantsslugai-experimentsidvariants",[62,1362,1363],{},"PUT \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments\u002F{id}\u002Fvariants",[17,1365,1366],{},"Transactionally replace the full variant set for an experiment. All existing variants are deleted and replaced with the supplied list in a single operation. On success the proxy KV config is re-synced.",[374,1368,1369,1373,1380,1385],{},[47,1370,1371,772],{},[20,1372,738],{},[47,1374,1375,381,1377],{},[20,1376,777],{},[62,1378,1379],{},"{ variants: [{ key, weight?, config? }] }",[47,1381,1382,1384],{},[20,1383,744],{}," Updated experiment object with new variants",[47,1386,1387,381,1389,793,1391,65,1393,1323],{},[20,1388,752],{},[62,1390,792],{},[62,1392,796],{},[62,1394,755],{},[181,1396,1398],{"id":1397},"get-apitenantsslugai-experimentsidexposures",[62,1399,1400],{},"GET \u002Fapi\u002Ftenants\u002F{slug}\u002Fai-experiments\u002F{id}\u002Fexposures",[17,1402,1403],{},"Return aggregate exposure metrics for one experiment, sourced from request logs. Reports how many requests were routed to each variant. Phase 2A: all-time totals, no time-window filtering.",[374,1405,1406,1410,1415],{},[47,1407,1408,739],{},[20,1409,738],{},[47,1411,1412,1414],{},[20,1413,744],{}," Exposure summary with per-variant counts",[47,1416,1417,381,1419,1277,1421,1280],{},[20,1418,752],{},[62,1420,792],{},[62,1422,755],{},{"title":428,"searchDepth":1424,"depth":1424,"links":1425},2,[1426,1427,1431,1432,1436,1437,1438,1439,1440,1441,1454],{"id":41,"depth":1424,"text":42},{"id":94,"depth":1424,"text":95,"children":1428},[1429],{"id":183,"depth":1430,"text":184},3,{"id":303,"depth":1424,"text":304},{"id":365,"depth":1424,"text":366,"children":1433},[1434,1435],{"id":369,"depth":1430,"text":316},{"id":412,"depth":1430,"text":319},{"id":466,"depth":1424,"text":467},{"id":538,"depth":1424,"text":539},{"id":597,"depth":1424,"text":598},{"id":627,"depth":1424,"text":628},{"id":658,"depth":1424,"text":659},{"id":718,"depth":1424,"text":719,"children":1442},[1443,1444,1445,1446,1447,1448,1449,1450,1451,1452,1453],{"id":725,"depth":1430,"text":728},{"id":759,"depth":1430,"text":762},{"id":802,"depth":1430,"text":805},{"id":838,"depth":1430,"text":841},{"id":868,"depth":1430,"text":871},{"id":896,"depth":1430,"text":384},{"id":935,"depth":1430,"text":938},{"id":1019,"depth":1430,"text":1022},{"id":1072,"depth":1430,"text":1075},{"id":1100,"depth":1430,"text":1103},{"id":1128,"depth":1430,"text":1131},{"id":1174,"depth":1424,"text":1175,"children":1455},[1456,1457,1458,1459,1460,1461,1462],{"id":1181,"depth":1430,"text":1184},{"id":1209,"depth":1430,"text":1212},{"id":1253,"depth":1430,"text":1256},{"id":1283,"depth":1430,"text":1286},{"id":1326,"depth":1430,"text":1329},{"id":1360,"depth":1430,"text":1363},{"id":1397,"depth":1430,"text":1400},"Apply LLM-powered content transformations to CMS API responses at the proxy layer. Configure rules, preview results, and serve transformed JSON cached at the edge.","md",{},true,"\u002Fdocs\u002Fapi\u002Fai-transform",{"title":5,"description":1463},"docs\u002Fapi\u002Fai-transform","ZTWW6VoGMXpwTOHZewFmrUJ2iN3zngnWcU4RS6I5fx0",1781192375082]